Android: fix QMediaPlayer's state and mediaStatus signals.
authorYoann Lopes <yoann.lopes@digia.com>
Tue, 16 Sep 2014 15:30:27 +0000 (17:30 +0200)
committerYoann Lopes <yoann.lopes@digia.com>
Wed, 24 Sep 2014 12:46:38 +0000 (14:46 +0200)
Emit signals only after both properties are written to avoid having
incoherent values in signal handlers.

Task-number: QTBUG-40314
Change-Id: I6c8445e61cccf1a9803647329c4fa1f0e452f56d
Reviewed-by: Christian Stromme <christian.stromme@digia.com>
src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.cpp
src/plugins/android/src/mediaplayer/qandroidmediaplayercontrol.h

index bd936f8..fb1c8b7 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
+class StateChangeNotifier
+{
+public:
+    StateChangeNotifier(QAndroidMediaPlayerControl *mp)
+        : mControl(mp)
+        , mPreviousState(mp->state())
+        , mPreviousMediaStatus(mp->mediaStatus())
+    {
+        ++mControl->mActiveStateChangeNotifiers;
+    }
+
+    ~StateChangeNotifier()
+    {
+        if (--mControl->mActiveStateChangeNotifiers)
+            return;
+
+        if (mPreviousState != mControl->state())
+            Q_EMIT mControl->stateChanged(mControl->state());
+
+        if (mPreviousMediaStatus != mControl->mediaStatus())
+            Q_EMIT mControl->mediaStatusChanged(mControl->mediaStatus());
+    }
+
+private:
+    QAndroidMediaPlayerControl *mControl;
+    QMediaPlayer::State mPreviousState;
+    QMediaPlayer::MediaStatus mPreviousMediaStatus;
+};
+
+
 QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
     : QMediaPlayerControl(parent),
       mMediaPlayer(new AndroidMediaPlayer),
@@ -55,7 +85,8 @@ QAndroidMediaPlayerControl::QAndroidMediaPlayerControl(QObject *parent)
       mPendingPosition(-1),
       mPendingSetMedia(false),
       mPendingVolume(-1),
-      mPendingMute(-1)
+      mPendingMute(-1),
+      mActiveStateChangeNotifiers(0)
 {
     connect(mMediaPlayer,SIGNAL(bufferingChanged(qint32)),
             this,SLOT(onBufferingChanged(qint32)));
@@ -138,6 +169,8 @@ void QAndroidMediaPlayerControl::setPosition(qint64 position)
         return;
     }
 
+    StateChangeNotifier notifier(this);
+
     if (mCurrentMediaStatus == QMediaPlayer::EndOfMedia)
         setMediaStatus(QMediaPlayer::LoadedMedia);
 
@@ -275,6 +308,8 @@ const QIODevice *QAndroidMediaPlayerControl::mediaStream() const
 void QAndroidMediaPlayerControl::setMedia(const QMediaContent &mediaContent,
                                           QIODevice *stream)
 {
+    StateChangeNotifier notifier(this);
+
     const bool reloading = (mMediaContent == mediaContent);
 
     if (!reloading) {
@@ -346,6 +381,8 @@ void QAndroidMediaPlayerControl::setVideoOutput(QObject *videoOutput)
 
 void QAndroidMediaPlayerControl::play()
 {
+    StateChangeNotifier notifier(this);
+
     // We need to prepare the mediaplayer again.
     if ((mState & AndroidMediaPlayer::Stopped) && !mMediaContent.isNull()) {
         setMedia(mMediaContent, mMediaStream);
@@ -366,6 +403,8 @@ void QAndroidMediaPlayerControl::play()
 
 void QAndroidMediaPlayerControl::pause()
 {
+    StateChangeNotifier notifier(this);
+
     setState(QMediaPlayer::PausedState);
 
     if ((mState & (AndroidMediaPlayer::Started
@@ -380,6 +419,8 @@ void QAndroidMediaPlayerControl::pause()
 
 void QAndroidMediaPlayerControl::stop()
 {
+    StateChangeNotifier notifier(this);
+
     setState(QMediaPlayer::StoppedState);
 
     if ((mState & (AndroidMediaPlayer::Prepared
@@ -397,6 +438,8 @@ void QAndroidMediaPlayerControl::stop()
 
 void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
 {
+    StateChangeNotifier notifier(this);
+
     Q_UNUSED(extra);
     switch (what) {
     case AndroidMediaPlayer::MEDIA_INFO_UNKNOWN:
@@ -428,6 +471,8 @@ void QAndroidMediaPlayerControl::onInfo(qint32 what, qint32 extra)
 
 void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
 {
+    StateChangeNotifier notifier(this);
+
     QString errorString;
     QMediaPlayer::Error error = QMediaPlayer::ResourceError;
 
@@ -480,6 +525,8 @@ void QAndroidMediaPlayerControl::onError(qint32 what, qint32 extra)
 
 void QAndroidMediaPlayerControl::onBufferingChanged(qint32 percent)
 {
+    StateChangeNotifier notifier(this);
+
     mBuffering = percent != 100;
     mBufferPercent = percent;
 
@@ -511,6 +558,8 @@ void QAndroidMediaPlayerControl::onStateChanged(qint32 state)
         return;
     }
 
+    StateChangeNotifier notifier(this);
+
     mState = state;
     switch (mState) {
     case AndroidMediaPlayer::Idle:
@@ -599,7 +648,6 @@ void QAndroidMediaPlayerControl::setState(QMediaPlayer::State state)
         return;
 
     mCurrentState = state;
-    Q_EMIT stateChanged(mCurrentState);
 }
 
 void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status)
@@ -614,7 +662,6 @@ void QAndroidMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status
         Q_EMIT durationChanged(duration());
 
     mCurrentMediaStatus = status;
-    Q_EMIT mediaStatusChanged(mCurrentMediaStatus);
 
     updateBufferStatus();
 }
index ec4dd32..7de0c2d 100644 (file)
@@ -112,6 +112,7 @@ private:
     int mPendingVolume;
     int mPendingMute;
     QScopedPointer<QTemporaryFile> mTempFile;
+    int mActiveStateChangeNotifiers;
 
     void setState(QMediaPlayer::State state);
     void setMediaStatus(QMediaPlayer::MediaStatus status);
@@ -122,6 +123,8 @@ private:
     void resetBufferingProgress();
     void flushPendingStates();
     void updateBufferStatus();
+
+    friend class StateChangeNotifier;
 };
 
 QT_END_NAMESPACE