Browse Source

PlayerComponent: add new finished/canceled signals

Web-client needs better information on whether playback finished
normally (until the end of the file), or whether it was intentionally
stopped.

The old "stopped" signal will remain for short-term compatibility until
all versions of web-client use the new signals.
Vincent Lang 7 years ago
parent
commit
304f4da215
2 changed files with 45 additions and 18 deletions
  1. 36 15
      src/player/PlayerComponent.cpp
  2. 9 3
      src/player/PlayerComponent.h

+ 36 - 15
src/player/PlayerComponent.cpp

@@ -36,8 +36,8 @@ static void wakeup_cb(void *context)
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 PlayerComponent::PlayerComponent(QObject* parent)
-  : ComponentBase(parent), m_state(State::stopped), m_paused(false), m_playbackActive(false),
-  m_windowVisible(false), m_videoPlaybackActive(false), m_inPlayback(false),
+  : ComponentBase(parent), m_state(State::finished), m_paused(false), m_playbackActive(false),
+  m_windowVisible(false), m_videoPlaybackActive(false), m_inPlayback(false), m_playbackCanceled(false),
   m_bufferingPercentage(100), m_lastBufferingPercentage(-1),
   m_lastPositionUpdate(0.0), m_playbackAudioDelay(0),
   m_window(nullptr), m_mediaFrameRate(0),
@@ -376,8 +376,12 @@ void PlayerComponent::updatePlaybackState()
   }
   else
   {
-    if (newState != State::error)
-      newState = State::stopped;
+    if (!m_playbackError.isEmpty())
+      newState = State::error;
+    else if (m_playbackCanceled)
+      newState = State::canceled;
+    else
+      newState = State::finished;
   }
 
   if (newState != m_state)
@@ -391,16 +395,23 @@ void PlayerComponent::updatePlaybackState()
       QLOG_INFO() << "Entering state: playing";
       emit playing();
       break;
-    case State::stopped:
-      QLOG_INFO() << "Entering state: stopped";
-      emit stopped();
-      break;
     case State::buffering:
       QLOG_INFO() << "Entering state: buffering";
       m_lastBufferingPercentage = -1; /* force update below */
       break;
+    case State::finished:
+      QLOG_INFO() << "Entering state: finished";
+      emit finished();
+      emit stopped();
+      break;
+    case State::canceled:
+      QLOG_INFO() << "Entering state: canceled";
+      emit canceled();
+      emit stopped();
+      break;
     case State::error:
-      /* handled separately */
+      QLOG_INFO() << ("Entering state: error (" + m_playbackError + ")");
+      emit error(m_playbackError);
       break;
     }
     m_state = newState;
@@ -431,14 +442,24 @@ void PlayerComponent::handleMpvEvent(mpv_event *event)
     case MPV_EVENT_END_FILE:
     {
       mpv_event_end_file *endFile = (mpv_event_end_file *)event->data;
-      if (endFile->reason == MPV_END_FILE_REASON_ERROR)
-      {
-        QLOG_INFO() << "Entering state: error";
-        m_state = State::error;
-        emit error(mpv_error_string(endFile->error));
-      }
 
       m_inPlayback = false;
+      m_playbackCanceled = false;
+      m_playbackError = "";
+
+      switch (endFile->reason)
+      {
+        case MPV_END_FILE_REASON_ERROR:
+        {
+          m_playbackError = mpv_error_string(endFile->error);
+          break;
+        }
+        case MPV_END_FILE_REASON_STOP:
+        {
+          m_playbackCanceled = true;
+          break;
+        }
+      }
 
       if (!m_streamSwitchImminent)
         m_restoreDisplayTimer.start(0);

+ 9 - 3
src/player/PlayerComponent.h

@@ -54,7 +54,7 @@ public:
   Q_INVOKABLE virtual void stop();
 
   // A full reload of the stream is imminent (stop() + load())
-  // Used ofr not resetting display mode with the next stop() call.
+  // Used for not resetting display mode with the next stop() call.
   Q_INVOKABLE virtual void streamSwitch();
 
   Q_INVOKABLE virtual void pause();
@@ -128,7 +128,8 @@ public:
   static QStringList AudioCodecsSPDIF() { return { "ac3", "dts" }; };
 
   enum class State {
-    stopped,
+    finished,
+    canceled,
     error,
     paused,
     playing,
@@ -157,9 +158,12 @@ Q_SIGNALS:
   // The following signals correspond to the State enum above.
   void playing();                 // playback is progressing (audio playing, pictures are moving)
   void buffering(float percent);  // temporary state during "playing", or during media loading
-  void stopped();                 // playback finished successfully, or was stopped with stop()
   void paused();                  // paused (covers all sub-states)
+  void finished();                // playback finished successfully
+  void canceled();                // playback was stopped (by user/via API)
   void error(const QString& msg); // playback stopped due to external error
+  // To be phased out. Raised on finished() and canceled().
+  void stopped();                 // playback finished successfully, or was stopped with stop()
 
   // true if the video (or music) is actually playing
   // false if nothing is loaded, playback is paused, during seeking, or media is being loaded
@@ -213,6 +217,8 @@ private:
   bool m_windowVisible;
   bool m_videoPlaybackActive;
   bool m_inPlayback;
+  bool m_playbackCanceled;
+  QString m_playbackError;
   int m_bufferingPercentage;
   int m_lastBufferingPercentage;
   double m_lastPositionUpdate;