]> git.sur5r.net Git - minitube/blobdiff - src/mediaview.cpp
Upload 3.9.3-2 to unstable
[minitube] / src / mediaview.cpp
index e6343ab9b2c498507ff3973611047a040f157c1b..5d74d0ba379ec3f2fa290fb7b52521c623a47890 100644 (file)
@@ -34,6 +34,7 @@ $END_LICENSE */
 #include "videoarea.h"
 #ifdef APP_ACTIVATION
 #include "activation.h"
+#include "activationview.h"
 #endif
 #ifdef APP_EXTRA
 #include "extra.h"
@@ -44,7 +45,6 @@ $END_LICENSE */
 #include "videosource.h"
 #include "ytchannel.h"
 #include "ytsearch.h"
-#include "ytsinglevideosource.h"
 #ifdef APP_SNAPSHOT
 #include "snapshotsettings.h"
 #endif
@@ -52,6 +52,10 @@ $END_LICENSE */
 #include "idle.h"
 #include "videodefinition.h"
 
+#include "searchvideosource.h"
+#include "singlevideosource.h"
+#include "videoapi.h"
+
 MediaView *MediaView::instance() {
     static MediaView *i = new MediaView();
     return i;
@@ -132,7 +136,16 @@ void MediaView::initialize() {
 #ifdef APP_ACTIVATION
     demoTimer = new QTimer(this);
     demoTimer->setSingleShot(true);
-    connect(demoTimer, &QTimer::timeout, mainWindow, &MainWindow::showActivationView,
+    connect(
+            demoTimer, &QTimer::timeout, this,
+            [this] {
+                if (media->state() != Media::PlayingState) return;
+                media->pause();
+                connect(
+                        ActivationView::instance(), &ActivationView::done, media,
+                        [this] { media->play(); }, Qt::UniqueConnection);
+                MainWindow::instance()->showActivationView();
+            },
             Qt::QueuedConnection);
 #endif
 
@@ -153,6 +166,34 @@ void MediaView::initialize() {
     for (auto *name : videoActionNames) {
         currentVideoActions.append(mainWindow->getAction(name));
     }
+
+    for (int i = 0; i < 10; ++i) {
+        QAction *action = new QAction(QString());
+        action->setShortcut(Qt::Key_0 + i);
+        action->setAutoRepeat(false);
+        connect(action, &QAction::triggered, this, [this, i] {
+            qint64 duration = media->duration();
+            // dur : pos = 100 : i*10
+            qint64 position = (duration * (i * 10)) / 100;
+            media->seek(position);
+        });
+        addAction(action);
+        playingVideoActions << action;
+    }
+
+    QAction *leftAction = new QAction(tr("Rewind %1 seconds").arg(10));
+    leftAction->setShortcut(Qt::Key_Left);
+    leftAction->setAutoRepeat(false);
+    connect(leftAction, &QAction::triggered, this, [this] { media->relativeSeek(-10000); });
+    addAction(leftAction);
+    playingVideoActions << leftAction;
+
+    QAction *rightAction = new QAction(tr("Fast forward %1 seconds").arg(10));
+    rightAction->setShortcut(Qt::Key_Right);
+    rightAction->setAutoRepeat(false);
+    connect(rightAction, &QAction::triggered, this, [this] { media->relativeSeek(10000); });
+    addAction(rightAction);
+    playingVideoActions << rightAction;
 }
 
 void MediaView::setMedia(Media *media) {
@@ -169,9 +210,11 @@ void MediaView::setMedia(Media *media) {
 
 SearchParams *MediaView::getSearchParams() {
     VideoSource *videoSource = playlistModel->getVideoSource();
-    if (videoSource && videoSource->metaObject()->className() == QLatin1String("YTSearch")) {
-        YTSearch *search = qobject_cast<YTSearch *>(videoSource);
-        return search->getSearchParams();
+    if (!videoSource) return nullptr;
+    auto clazz = videoSource->metaObject()->className();
+    if (clazz == QLatin1String("SearchVideoSource")) {
+        auto search = qobject_cast<SearchVideoSource *>(videoSource);
+        if (search) return search->getSearchParams();
     }
     return nullptr;
 }
@@ -182,19 +225,19 @@ void MediaView::search(SearchParams *searchParams) {
             searchParams->keywords().startsWith("https://")) {
             QString videoId = YTSearch::videoIdFromUrl(searchParams->keywords());
             if (!videoId.isEmpty()) {
-                YTSingleVideoSource *singleVideoSource = new YTSingleVideoSource(this);
-                singleVideoSource->setVideoId(videoId);
-                setVideoSource(singleVideoSource);
+                auto source = new SingleVideoSource(this);
+                source->setVideoId(videoId);
+                setVideoSource(source);
+
                 QTime tstamp = YTSearch::videoTimestampFromUrl(searchParams->keywords());
                 pauseTime = QTime(0, 0).msecsTo(tstamp);
                 return;
             }
         }
     }
-    YTSearch *ytSearch = new YTSearch(searchParams);
-    ytSearch->setAsyncDetails(true);
-    connect(ytSearch, SIGNAL(gotDetails()), playlistModel, SLOT(emitDataChanged()));
-    setVideoSource(ytSearch);
+
+    VideoSource *search = new SearchVideoSource(searchParams);
+    setVideoSource(search);
 }
 
 void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory, bool back) {
@@ -204,13 +247,6 @@ void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory, bool
 
     // qDebug() << "Adding VideoSource" << videoSource->getName() << videoSource;
 
-    YTSearch * ytSearch = qobject_cast<YTSearch *>(videoSource);
-    if (nullptr != ytSearch) {
-        if (!ytSearch->getSearchParams()->channelId().isEmpty()) {
-            updateSubscriptionActionForChannel(ytSearch->getSearchParams()->channelId());
-        }
-    }
-
     if (addToHistory) {
         int currentIndex = getHistoryIndex();
         if (currentIndex >= 0 && currentIndex < history.size() - 1) {
@@ -218,6 +254,7 @@ void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory, bool
                 VideoSource *vs = history.takeLast();
                 if (!vs->parent()) {
                     qDebug() << "Deleting VideoSource" << vs->getName() << vs;
+                    vs->abort();
                     vs->deleteLater();
                 }
             }
@@ -239,13 +276,17 @@ void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory, bool
         }
     }
 
+    SearchParams *searchParams = getSearchParams();
+
     sidebar->showPlaylist();
-    sidebar->getRefineSearchWidget()->setSearchParams(getSearchParams());
+    sidebar->getRefineSearchWidget()->setSearchParams(searchParams);
     sidebar->hideSuggestions();
     sidebar->getHeader()->updateInfo();
 
-    SearchParams *searchParams = getSearchParams();
     bool isChannel = searchParams && !searchParams->channelId().isEmpty();
+    if (isChannel) {
+        updateSubscriptionActionForChannel(searchParams->channelId());
+    }
     playlistView->setClickableAuthors(!isChannel);
 }
 
@@ -311,6 +352,7 @@ void MediaView::mediaStateChanged(Media::State state) {
     if (pauseTime > 0 && (state == Media::PlayingState || state == Media::BufferingState)) {
         qDebug() << "Seeking to" << pauseTime;
         media->seek(pauseTime);
+        media->play();
         pauseTime = 0;
     }
     if (state == Media::PlayingState) {
@@ -319,6 +361,10 @@ void MediaView::mediaStateChanged(Media::State state) {
         handleError(media->errorString());
     }
 
+    bool enablePlayingVideoActions = state != Media::StoppedState;
+    for (QAction *action : qAsConst(playingVideoActions))
+        action->setEnabled(enablePlayingVideoActions);
+
     if (state == Media::PlayingState) {
         bool res = Idle::preventDisplaySleep(QString("%1 is playing").arg(Constants::NAME));
         if (!res) qWarning() << "Error disabling idle display sleep" << Idle::displayErrorMessage();
@@ -331,17 +377,25 @@ void MediaView::mediaStateChanged(Media::State state) {
 void MediaView::pause() {
     switch (media->state()) {
     case Media::PlayingState:
+        qDebug() << "Pausing";
         media->pause();
         pauseTimer.start();
         break;
     default:
-        if (pauseTimer.hasExpired(60000)) {
+        if (pauseTimer.isValid() && pauseTimer.hasExpired(60000)) {
+            qDebug() << "Pause timer expired";
             pauseTimer.invalidate();
-            connect(playlistModel->activeVideo(), &Video::gotStreamUrl, this,
-                    &MediaView::resumeWithNewStreamUrl);
-            playlistModel->activeVideo()->loadStreamUrl();
-        } else
+            auto activeVideo = playlistModel->activeVideo();
+            if (activeVideo) {
+                connect(activeVideo, &Video::gotStreamUrl, this,
+                        &MediaView::resumeWithNewStreamUrl);
+                activeVideo->loadStreamUrl();
+            } else
+                qDebug() << "No active video";
+        } else {
+            qDebug() << "Playing" << media->file();
             media->play();
+        }
         break;
     }
 }
@@ -357,6 +411,7 @@ void MediaView::stop() {
         VideoSource *videoSource = history.takeFirst();
         // Don't delete videoSource in the Browse view
         if (!videoSource->parent()) {
+            videoSource->abort();
             videoSource->deleteLater();
         }
     }
@@ -373,7 +428,7 @@ void MediaView::stop() {
     demoTimer->stop();
 #endif
 
-    for (QAction *action : currentVideoActions)
+    for (QAction *action : qAsConst(currentVideoActions))
         action->setEnabled(false);
 
     QAction *a = MainWindow::instance()->getAction("download");
@@ -497,8 +552,8 @@ void MediaView::gotStreamUrl(const QString &streamUrl, const QString &audioUrl)
     }
 
 #ifdef APP_ACTIVATION
-    if (!Activation::instance().isActivated() && !demoTimer->isActive()) {
-        int ms = (60000 * 5) + (qrand() % (60000 * 5));
+    if (!demoTimer->isActive() && !Activation::instance().isActivated()) {
+        int ms = (60000 * 2) + (QRandomGenerator::global()->generate() % (60000 * 2));
         demoTimer->start(ms);
     }
 #endif
@@ -556,14 +611,7 @@ void MediaView::skipBackward() {
 }
 
 void MediaView::onAboutToFinish() {
-    qint64 currentTime = media->position();
-    qint64 totalTime = media->duration();
-    // qDebug() << __PRETTY_FUNCTION__ << currentTime << totalTime;
-    if (totalTime < 1 || currentTime + 10000 < totalTime) {
-        // QTimer::singleShot(500, this, SLOT(playbackResume()));
-        media->seek(currentTime);
-        media->play();
-    }
+
 }
 
 void MediaView::onPlaybackFinished() {
@@ -653,7 +701,7 @@ void MediaView::moveUpSelected() {
     if (!playlistView->selectionModel()->hasSelection()) return;
 
     QModelIndexList indexes = playlistView->selectionModel()->selectedIndexes();
-    qStableSort(indexes.begin(), indexes.end());
+    std::stable_sort(indexes.begin(), indexes.end());
     playlistModel->move(indexes, true);
 
     // set current index after row moves to something more intuitive
@@ -666,7 +714,8 @@ void MediaView::moveDownSelected() {
     if (!playlistView->selectionModel()->hasSelection()) return;
 
     QModelIndexList indexes = playlistView->selectionModel()->selectedIndexes();
-    qStableSort(indexes.begin(), indexes.end(), qGreater<QModelIndex>());
+    std::stable_sort(indexes.begin(), indexes.end(),
+                     [](const QModelIndex &a, const QModelIndex &b) { return b < a; });
     playlistModel->move(indexes, false);
 
     // set current index after row moves to something more intuitive
@@ -848,10 +897,11 @@ void MediaView::findVideoParts() {
 void MediaView::relatedVideos() {
     Video *video = playlistModel->activeVideo();
     if (!video) return;
-    YTSingleVideoSource *singleVideoSource = new YTSingleVideoSource();
-    singleVideoSource->setVideo(video->clone());
-    singleVideoSource->setAsyncDetails(true);
-    setVideoSource(singleVideoSource);
+
+    auto source = new SingleVideoSource(this);
+    source->setVideo(video->clone());
+    setVideoSource(source);
+
     MainWindow::instance()->getAction("relatedVideos")->setEnabled(false);
 }