From 0d4572595698502e04f491bfea3e16bb1851b645 Mon Sep 17 00:00:00 2001
From: Justin McPherson <justin.mcpherson@nokia.com>
Date: Fri, 19 Mar 2010 12:56:15 +1000
Subject: Fix; QML Video item is sensitive to property assignment order

Task-number: QTBUG-8605
Reviewed-by: Andrew den Exter
---
 src/imports/multimedia/qdeclarativeaudio.cpp       |  36 ++--
 src/imports/multimedia/qdeclarativeaudio_p.h       |   2 +
 src/imports/multimedia/qdeclarativemediabase.cpp   | 219 ++++++++++++++-------
 src/imports/multimedia/qdeclarativemediabase_p.h   |  11 +-
 src/imports/multimedia/qdeclarativevideo.cpp       |  56 +++---
 src/imports/multimedia/qdeclarativevideo_p.h       |   2 +
 .../qdeclarativeaudio/tst_qdeclarativeaudio.cpp    |  66 +++++--
 .../qdeclarativevideo/tst_qdeclarativevideo.cpp    |  38 ++--
 8 files changed, 281 insertions(+), 149 deletions(-)

diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp
index 40133ee..39223dc 100644
--- a/src/imports/multimedia/qdeclarativeaudio.cpp
+++ b/src/imports/multimedia/qdeclarativeaudio.cpp
@@ -77,7 +77,6 @@ void QDeclarativeAudio::_q_error(int errorCode, const QString &errorString)
 QDeclarativeAudio::QDeclarativeAudio(QObject *parent)
     : QObject(parent)
 {
-    setObject(this);
 }
 
 QDeclarativeAudio::~QDeclarativeAudio()
@@ -94,13 +93,12 @@ QDeclarativeAudio::~QDeclarativeAudio()
 */
 
 void QDeclarativeAudio::play()
-{    
-    m_playerControl->play();
+{
+    if (m_playerControl == 0)
+        return;
 
-    if (m_paused) {
-        m_paused = false;
-        emit pausedChanged();
-    }
+    setPaused(false);
+    setPlaying(true);
 }
 
 /*!
@@ -113,12 +111,11 @@ void QDeclarativeAudio::play()
 
 void QDeclarativeAudio::pause()
 {
-    m_playerControl->pause();
+    if (m_playerControl == 0)
+        return;
 
-    if (!m_paused && m_state == QMediaPlayer::PausedState) {
-        m_paused = true;
-        emit pausedChanged();
-    }
+    setPaused(true);
+    setPlaying(true);
 }
 
 /*!
@@ -131,12 +128,11 @@ void QDeclarativeAudio::pause()
 
 void QDeclarativeAudio::stop()
 {
-    m_playerControl->stop();
+    if (m_playerControl == 0)
+        return;
 
-    if (m_paused) {
-        m_paused = false;
-        emit pausedChanged();
-    }
+    setPlaying(false);
+    setPaused(false);
 }
 
 /*!
@@ -307,6 +303,12 @@ QDeclarativeAudio::Error QDeclarativeAudio::error() const
     return Error(m_error);
 }
 
+void QDeclarativeAudio::componentComplete()
+{
+    setObject(this);
+}
+
+
 /*!
     \qmlproperty string Audio::errorString
 
diff --git a/src/imports/multimedia/qdeclarativeaudio_p.h b/src/imports/multimedia/qdeclarativeaudio_p.h
index 9881dbc..2e8ae30 100644
--- a/src/imports/multimedia/qdeclarativeaudio_p.h
+++ b/src/imports/multimedia/qdeclarativeaudio_p.h
@@ -114,6 +114,8 @@ public:
     Status status() const;
     Error error() const;
 
+    void componentComplete();
+
 public Q_SLOTS:
     void play();
     void pause();
diff --git a/src/imports/multimedia/qdeclarativemediabase.cpp b/src/imports/multimedia/qdeclarativemediabase.cpp
index 8e87e44..542c931 100644
--- a/src/imports/multimedia/qdeclarativemediabase.cpp
+++ b/src/imports/multimedia/qdeclarativemediabase.cpp
@@ -131,43 +131,56 @@ private:
 
 void QDeclarativeMediaBase::_q_stateChanged(QMediaPlayer::State state)
 {
-    if (state != m_state) {
-        QMediaPlayer::State oldState = m_state;
+    if (m_state == state)
+        return;
 
-        m_state = state;
-
-        if (state == QMediaPlayer::StoppedState) {
+    switch (state) {
+    case QMediaPlayer::StoppedState: {
             emit stopped();
-            emit playingChanged();
-        } else if (oldState == QMediaPlayer::StoppedState) {
-            emit started();
-            emit playingChanged();
-        } else if (oldState  == QMediaPlayer::PausedState) {
-            m_paused = false;
-
-            emit resumed();
-            emit pausedChanged();
-        }
-
-        if (state == m_state && state == QMediaPlayer::PausedState) {
-            bool wasPaused = m_paused;
-
-            m_paused = true;
 
+            if (m_playing) {
+                m_playing = false;
+                emit playingChanged();
+            }
+        }
+        break;
+    case QMediaPlayer::PausedState: {
             emit paused();
 
-            if (!wasPaused)
+            if (!m_paused) {
+                m_paused = true;
                 emit pausedChanged();
-        }
+            }
 
-        if (m_state == QMediaPlayer::PlayingState
-                || m_status == QMediaPlayer::BufferingMedia
-                || m_status == QMediaPlayer::StalledMedia) {
-            m_animation->start();
-        } else {
-            m_animation->stop();
+            if (m_state == QMediaPlayer::StoppedState)
+                emit started();
         }
+        break;
+    case QMediaPlayer::PlayingState: {
+            if (m_state == QMediaPlayer::PausedState)
+                emit resumed();
+            else
+                emit started();
+
+           if (m_paused) {
+               m_paused = false;
+               emit pausedChanged();
+           }
+        }
+        break;
+    }
+
+    // Check
+    if (state == QMediaPlayer::PlayingState
+            || m_status == QMediaPlayer::BufferingMedia
+            || m_status == QMediaPlayer::StalledMedia) {
+        m_animation->start();
     }
+    else {
+        m_animation->stop();
+    }
+
+    m_state = state;
 }
 
 void QDeclarativeMediaBase::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status)
@@ -213,7 +226,13 @@ void QDeclarativeMediaBase::_q_metaDataChanged()
 }
 
 QDeclarativeMediaBase::QDeclarativeMediaBase()
-    : m_mediaService(0)
+    : m_paused(false)
+    , m_playing(false)
+    , m_muted(false)
+    , m_position(0)
+    , m_volume(1.0)
+    , m_playbackRate(1.0)
+    , m_mediaService(0)
     , m_playerControl(0)
     , m_mediaObject(0)
     , m_mediaProvider(0)
@@ -222,8 +241,7 @@ QDeclarativeMediaBase::QDeclarativeMediaBase()
     , m_animation(0)
     , m_state(QMediaPlayer::StoppedState)
     , m_status(QMediaPlayer::NoMedia)
-    , m_error(QMediaPlayer::NoError)
-    , m_paused(false)
+    , m_error(QMediaPlayer::ServiceMissingError)
 {
 }
 
@@ -280,9 +298,8 @@ void QDeclarativeMediaBase::setObject(QObject *object)
                 object, SLOT(_q_error(int,QString)));
 
         m_animation = new QDeclarativeMediaBaseAnimation(this);
+        m_error = QMediaPlayer::NoError;
     } else {
-        m_error = QMediaPlayer::ServiceMissingError;
-
         m_playerControl = new QDeclarativeMediaBasePlayerControl(object);
     }
 
@@ -292,40 +309,74 @@ void QDeclarativeMediaBase::setObject(QObject *object)
         QObject::connect(m_metaDataControl, SIGNAL(metaDataChanged()),
                 object, SLOT(_q_metaDataChanged()));
     }
+
+    // Init
+    m_playerControl->setVolume(m_volume * 100);
+    m_playerControl->setMuted(m_muted);
+    m_playerControl->setPlaybackRate(m_playbackRate);
+
+    if (!m_source.isEmpty())
+        m_playerControl->setMedia(m_source, 0);
+
+    if (m_playing)
+        m_playerControl->play();
+
+    if (m_position > 0)
+        m_playerControl->setPosition(m_position);
 }
 
+
+// Properties
+
 QUrl QDeclarativeMediaBase::source() const
 {
-    return m_playerControl->media().canonicalUrl();
+    return m_source;
 }
 
 void QDeclarativeMediaBase::setSource(const QUrl &url)
 {
-    if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) {
-        m_error = QMediaPlayer::NoError;
-        m_errorString = QString();
+    if (url == m_source)
+        return;
 
-        emit errorChanged();
-    }
+    m_source = url;
+
+    if (m_playerControl != 0) {
+        if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) {
+            m_error = QMediaPlayer::NoError;
+            m_errorString = QString();
+
+            emit errorChanged();
+        }
 
-    m_playerControl->setMedia(QMediaContent(url), 0);
+        m_playerControl->setMedia(m_source, 0);
+    }
+    else
+        emit sourceChanged();
 }
 
 bool QDeclarativeMediaBase::isPlaying() const
 {
-    return m_state != QMediaPlayer::StoppedState;
+    return m_playing;
 }
 
 void QDeclarativeMediaBase::setPlaying(bool playing)
 {
-    if (playing && m_state == QMediaPlayer::StoppedState) {
-        if (m_paused)
-            m_playerControl->pause();
-        else
-            m_playerControl->play();
-    } else if (!playing) {
-        m_playerControl->stop();
+    if (playing == m_playing)
+        return;
+
+    m_playing = playing;
+    if (m_playerControl != 0) {
+        if (m_playing) {
+            if (!m_paused)
+                m_playerControl->play();
+            else
+                m_playerControl->pause();
+        }
+        else if (m_state != QMediaPlayer::StoppedState)
+            m_playerControl->stop();
     }
+
+    emit playingChanged();
 }
 
 bool QDeclarativeMediaBase::isPaused() const
@@ -335,73 +386,107 @@ bool QDeclarativeMediaBase::isPaused() const
 
 void QDeclarativeMediaBase::setPaused(bool paused)
 {
-    if (m_paused != paused) {
-        if (paused && m_state == QMediaPlayer::PlayingState) {
+    if (m_paused == paused)
+        return;
+
+    m_paused = paused;
+    if (m_playerControl != 0) {
+        // Check if completed, change state
+        if (m_paused && m_state == QMediaPlayer::PlayingState) {
             m_playerControl->pause();
-        } else if (!paused && m_state == QMediaPlayer::PausedState) {
+        }
+        else if (!m_paused && m_playing) {
             m_playerControl->play();
-        } else {
-            m_paused = paused;
-
-            emit pausedChanged();
         }
     }
+
+    emit pausedChanged();
 }
 
 int QDeclarativeMediaBase::duration() const
 {
-    return m_playerControl->duration();
+    return m_playerControl == 0 ? 0 : m_playerControl->duration();
 }
 
 int QDeclarativeMediaBase::position() const
 {
-    return m_playerControl->position();
-
+    return m_playerControl == 0 ? m_position : m_playerControl->position();
 }
 
 void QDeclarativeMediaBase::setPosition(int position)
 {
-    m_playerControl->setPosition(position);
+    if (m_position == position)
+        return;
+
+    m_position = position;
+    if (m_playerControl != 0)
+        m_playerControl->setPosition(m_position);
+    else
+        emit positionChanged();
 }
 
 qreal QDeclarativeMediaBase::volume() const
 {
-    return qreal(m_playerControl->volume()) / 100;
+    return m_playerControl == 0 ? m_volume : qreal(m_playerControl->volume()) / 100;
 }
 
 void QDeclarativeMediaBase::setVolume(qreal volume)
 {
-    m_playerControl->setVolume(qRound(volume * 100));
+    if (m_volume == volume)
+        return;
+
+    m_volume = volume;
+
+    if (m_playerControl != 0)
+        m_playerControl->setVolume(qRound(volume * 100));
+    else
+        emit volumeChanged();
 }
 
 bool QDeclarativeMediaBase::isMuted() const
 {
-    return m_playerControl->isMuted();
+    return m_playerControl == 0 ? m_muted : m_playerControl->isMuted();
 }
 
 void QDeclarativeMediaBase::setMuted(bool muted)
 {
-    m_playerControl->setMuted(muted);
+    if (m_muted == muted)
+        return;
+
+    m_muted = muted;
+
+    if (m_playerControl != 0)
+        m_playerControl->setMuted(muted);
+    else
+        emit mutedChanged();
 }
 
 qreal QDeclarativeMediaBase::bufferProgress() const
 {
-    return qreal(m_playerControl->bufferStatus()) / 100;
+    return m_playerControl == 0 ? 0 : qreal(m_playerControl->bufferStatus()) / 100;
 }
 
 bool QDeclarativeMediaBase::isSeekable() const
 {
-    return m_playerControl->isSeekable();
+    return m_playerControl == 0 ? false : m_playerControl->isSeekable();
 }
 
 qreal QDeclarativeMediaBase::playbackRate() const
 {
-    return m_playerControl->playbackRate();
+    return m_playbackRate;
 }
 
 void QDeclarativeMediaBase::setPlaybackRate(qreal rate)
 {
-    m_playerControl->setPlaybackRate(rate);
+    if (m_playbackRate == rate)
+        return;
+
+    m_playbackRate = rate;
+
+    if (m_playerControl != 0)
+        m_playerControl->setPlaybackRate(m_playbackRate);
+    else
+        emit playbackRateChanged();
 }
 
 QString QDeclarativeMediaBase::errorString() const
diff --git a/src/imports/multimedia/qdeclarativemediabase_p.h b/src/imports/multimedia/qdeclarativemediabase_p.h
index b40e84e..d279f4a 100644
--- a/src/imports/multimedia/qdeclarativemediabase_p.h
+++ b/src/imports/multimedia/qdeclarativemediabase_p.h
@@ -107,13 +107,14 @@ public:
 
     void _q_metaDataChanged();
 
+    void componentComplete();
+
 protected:
     void shutdown();
 
     void setObject(QObject *object);
 
     virtual void sourceChanged() = 0;
-
     virtual void playingChanged() = 0;
     virtual void pausedChanged() = 0;
 
@@ -143,6 +144,12 @@ protected:
 
     virtual void errorChanged() = 0;
 
+    bool m_paused;
+    bool m_playing;
+    bool m_muted;
+    int m_position;
+    qreal m_volume;
+    qreal m_playbackRate;
     QMediaService *m_mediaService;
     QMediaPlayerControl *m_playerControl;
 
@@ -155,8 +162,8 @@ protected:
     QMediaPlayer::State m_state;
     QMediaPlayer::MediaStatus m_status;
     QMediaPlayer::Error m_error;
-    bool m_paused;
     QString m_errorString;
+    QUrl m_source;
 
     friend class QDeclarativeMediaBaseAnimation;
 };
diff --git a/src/imports/multimedia/qdeclarativevideo.cpp b/src/imports/multimedia/qdeclarativevideo.cpp
index 80c0ba4..67d9aef 100644
--- a/src/imports/multimedia/qdeclarativevideo.cpp
+++ b/src/imports/multimedia/qdeclarativevideo.cpp
@@ -100,17 +100,6 @@ QDeclarativeVideo::QDeclarativeVideo(QDeclarativeItem *parent)
     m_graphicsItem = new QGraphicsVideoItem(this);
     connect(m_graphicsItem, SIGNAL(nativeSizeChanged(QSizeF)),
             this, SLOT(_q_nativeSizeChanged(QSizeF)));
-
-    setObject(this);
-
-    if (m_mediaService) {
-        connect(m_playerControl, SIGNAL(audioAvailableChanged(bool)),
-                this, SIGNAL(hasAudioChanged()));
-        connect(m_playerControl, SIGNAL(videoAvailableChanged(bool)),
-                this, SIGNAL(hasVideoChanged()));
-
-        m_graphicsItem->setMediaObject(m_mediaObject);
-    }
 }
 
 QDeclarativeVideo::~QDeclarativeVideo()
@@ -253,7 +242,7 @@ QDeclarativeVideo::Status QDeclarativeVideo::status() const
 
 bool QDeclarativeVideo::hasAudio() const
 {
-    return m_playerControl->isAudioAvailable();
+    return m_playerControl == 0 ? false : m_playerControl->isAudioAvailable();
 }
 
 /*!
@@ -264,7 +253,7 @@ bool QDeclarativeVideo::hasAudio() const
 
 bool QDeclarativeVideo::hasVideo() const
 {
-    return m_playerControl->isVideoAvailable();
+    return m_playerControl == 0 ? false : m_playerControl->isVideoAvailable();
 }
 
 /*!
@@ -356,12 +345,11 @@ void QDeclarativeVideo::setFillMode(FillMode mode)
 
 void QDeclarativeVideo::play()
 {
-    m_playerControl->play();
+    if (m_playerControl == 0)
+        return;
 
-    if (m_paused) {
-        m_paused = false;
-        emit pausedChanged();
-    }
+    setPaused(false);
+    setPlaying(true);
 }
 
 /*!
@@ -374,12 +362,11 @@ void QDeclarativeVideo::play()
 
 void QDeclarativeVideo::pause()
 {
-    m_playerControl->pause();
+    if (m_playerControl == 0)
+        return;
 
-    if (!m_paused && m_state == QMediaPlayer::PausedState) {
-        m_paused = true;
-        emit pausedChanged();
-    }
+    setPaused(true);
+    setPlaying(true);
 }
 
 /*!
@@ -392,12 +379,11 @@ void QDeclarativeVideo::pause()
 
 void QDeclarativeVideo::stop()
 {
-    m_playerControl->stop();
+    if (m_playerControl == 0)
+        return;
 
-    if (m_paused) {
-        m_paused = false;
-        emit pausedChanged();
-    }
+    setPlaying(false);
+    setPaused(false);
 }
 
 void QDeclarativeVideo::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
@@ -411,6 +397,20 @@ void QDeclarativeVideo::geometryChanged(const QRectF &newGeometry, const QRectF
     QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
 }
 
+void QDeclarativeVideo::componentComplete()
+{
+    setObject(this);
+
+    if (m_mediaService) {
+        connect(m_playerControl, SIGNAL(audioAvailableChanged(bool)),
+                this, SIGNAL(hasAudioChanged()));
+        connect(m_playerControl, SIGNAL(videoAvailableChanged(bool)),
+                this, SIGNAL(hasVideoChanged()));
+
+        m_graphicsItem->setMediaObject(m_mediaObject);
+    }
+}
+
 QT_END_NAMESPACE
 
 // ***************************************
diff --git a/src/imports/multimedia/qdeclarativevideo_p.h b/src/imports/multimedia/qdeclarativevideo_p.h
index fb13519..2dead2e 100644
--- a/src/imports/multimedia/qdeclarativevideo_p.h
+++ b/src/imports/multimedia/qdeclarativevideo_p.h
@@ -136,6 +136,8 @@ public:
 
     void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *);
 
+    void componentComplete();
+
 public Q_SLOTS:
     void play();
     void pause();
diff --git a/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
index d750c69..a604854 100644
--- a/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
+++ b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
@@ -298,11 +298,12 @@ void tst_QmlAudio::nullPlayerControl()
 
     QCOMPARE(audio.source(), QUrl());
     audio.setSource(QUrl("http://example.com"));
-    QCOMPARE(audio.source(), QUrl());
+    QCOMPARE(audio.source(), QUrl("http://example.com"));
 
     QCOMPARE(audio.isPlaying(), false);
     audio.setPlaying(true);
-    QCOMPARE(audio.isPlaying(), false);
+    QCOMPARE(audio.isPlaying(), true);
+    audio.setPlaying(false);
     audio.play();
     QCOMPARE(audio.isPlaying(), false);
 
@@ -316,15 +317,15 @@ void tst_QmlAudio::nullPlayerControl()
 
     QCOMPARE(audio.position(), 0);
     audio.setPosition(10000);
-    QCOMPARE(audio.position(), 0);
+    QCOMPARE(audio.position(), 10000);
 
-    QCOMPARE(audio.volume(), qreal(0));
-    audio.setVolume(50);
-    QCOMPARE(audio.volume(), qreal(0));
+    QCOMPARE(audio.volume(), qreal(1.0));
+    audio.setVolume(0.5);
+    QCOMPARE(audio.volume(), qreal(0.5));
 
     QCOMPARE(audio.isMuted(), false);
     audio.setMuted(true);
-    QCOMPARE(audio.isMuted(), false);
+    QCOMPARE(audio.isMuted(), true);
 
     QCOMPARE(audio.bufferProgress(), qreal(0));
 
@@ -357,11 +358,12 @@ void tst_QmlAudio::nullService()
 
     QCOMPARE(audio.source(), QUrl());
     audio.setSource(QUrl("http://example.com"));
-    QCOMPARE(audio.source(), QUrl());
+    QCOMPARE(audio.source(), QUrl("http://example.com"));
 
     QCOMPARE(audio.isPlaying(), false);
     audio.setPlaying(true);
-    QCOMPARE(audio.isPlaying(), false);
+    QCOMPARE(audio.isPlaying(), true);
+    audio.setPlaying(false);
     audio.play();
     QCOMPARE(audio.isPlaying(), false);
 
@@ -375,15 +377,15 @@ void tst_QmlAudio::nullService()
 
     QCOMPARE(audio.position(), 0);
     audio.setPosition(10000);
-    QCOMPARE(audio.position(), 0);
+    QCOMPARE(audio.position(), 10000);
 
-    QCOMPARE(audio.volume(), qreal(0));
-    audio.setVolume(50);
-    QCOMPARE(audio.volume(), qreal(0));
+    QCOMPARE(audio.volume(), qreal(1.0));
+    audio.setVolume(0.5);
+    QCOMPARE(audio.volume(), qreal(0.5));
 
     QCOMPARE(audio.isMuted(), false);
     audio.setMuted(true);
-    QCOMPARE(audio.isMuted(), false);
+    QCOMPARE(audio.isMuted(), true);
 
     QCOMPARE(audio.bufferProgress(), qreal(0));
 
@@ -408,6 +410,7 @@ void tst_QmlAudio::source()
 
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
+    audio.componentComplete();
 
     QSignalSpy spy(&audio, SIGNAL(sourceChanged()));
 
@@ -440,6 +443,8 @@ void tst_QmlAudio::playing()
     int started = 0;
     int stopped = 0;
 
+    audio.componentComplete();
+
     QCOMPARE(audio.isPlaying(), false);
 
     // setPlaying(true) when stopped.
@@ -533,6 +538,8 @@ void tst_QmlAudio::paused()
     int resumed = 0;
     int stopped = 0;
 
+    audio.componentComplete();
+
     QCOMPARE(audio.isPlaying(), false);
     QCOMPARE(audio.isPaused(), false);
 
@@ -806,6 +813,8 @@ void tst_QmlAudio::duration()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy spy(&audio, SIGNAL(durationChanged()));
 
     QCOMPARE(audio.duration(), 0);
@@ -832,6 +841,7 @@ void tst_QmlAudio::position()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
+    audio.componentComplete();
 
     QSignalSpy spy(&audio, SIGNAL(positionChanged()));
 
@@ -853,32 +863,33 @@ void tst_QmlAudio::position()
     audio.setPosition(-5403);
     QCOMPARE(audio.position(), -5403);
     QCOMPARE(provider.playerControl()->position(), qint64(-5403));
-    QCOMPARE(spy.count(), 3);
+    QCOMPARE(spy.count(), 2);
 
     // Check the signal change signal is emitted if the change originates from the media service.
     provider.playerControl()->setPosition(0);
     QCOMPARE(audio.position(), 0);
-    QCOMPARE(spy.count(), 4);
+    QCOMPARE(spy.count(), 3);
 
     connect(&audio, SIGNAL(positionChanged()), &QTestEventLoop::instance(), SLOT(exitLoop()));
 
     provider.playerControl()->updateState(QMediaPlayer::PlayingState);
     QTestEventLoop::instance().enterLoop(1);
-    QVERIFY(spy.count() > 4 && spy.count() < 7); // 5 or 6
+    QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5
 
     provider.playerControl()->updateState(QMediaPlayer::PausedState);
     QTestEventLoop::instance().enterLoop(1);
-    QVERIFY(spy.count() < 7);
+    QVERIFY(spy.count() < 6);
 }
 
 void tst_QmlAudio::volume()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
+    audio.componentComplete();
 
     QSignalSpy spy(&audio, SIGNAL(volumeChanged()));
 
-    QCOMPARE(audio.volume(), qreal(0.5));
+    QCOMPARE(audio.volume(), qreal(1.0));
 
     audio.setVolume(0.7);
     QCOMPARE(audio.volume(), qreal(0.7));
@@ -888,17 +899,18 @@ void tst_QmlAudio::volume()
     audio.setVolume(0.7);
     QCOMPARE(audio.volume(), qreal(0.7));
     QCOMPARE(provider.playerControl()->volume(), 70);
-    QCOMPARE(spy.count(), 2);
+    QCOMPARE(spy.count(), 1);
 
     provider.playerControl()->setVolume(30);
     QCOMPARE(audio.volume(), qreal(0.3));
-    QCOMPARE(spy.count(), 3);
+    QCOMPARE(spy.count(), 2);
 }
 
 void tst_QmlAudio::muted()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
+    audio.componentComplete();
 
     QSignalSpy spy(&audio, SIGNAL(mutedChanged()));
 
@@ -924,6 +936,8 @@ void tst_QmlAudio::bufferProgress()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy spy(&audio, SIGNAL(bufferProgressChanged()));
 
     QCOMPARE(audio.bufferProgress(), qreal(0.0));
@@ -957,6 +971,8 @@ void tst_QmlAudio::seekable()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy spy(&audio, SIGNAL(seekableChanged()));
 
     QCOMPARE(audio.isSeekable(), false);
@@ -979,6 +995,8 @@ void tst_QmlAudio::playbackRate()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy spy(&audio, SIGNAL(playbackRateChanged()));
 
     QCOMPARE(audio.playbackRate(), qreal(1.0));
@@ -1003,6 +1021,8 @@ void tst_QmlAudio::status()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy statusChangedSpy(&audio, SIGNAL(statusChanged()));
     QSignalSpy loadedSpy(&audio, SIGNAL(loaded()));
     QSignalSpy bufferingSpy(&audio, SIGNAL(buffering()));
@@ -1141,6 +1161,8 @@ void tst_QmlAudio::metaData()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy spy(&audio, SIGNAL(__metaDataChanged()));
 
     const int index = audio.metaObject()->indexOfProperty(propertyName.constData());
@@ -1166,6 +1188,8 @@ void tst_QmlAudio::error()
     QtTestMediaServiceProvider provider;
     QDeclarativeAudio audio;
 
+    audio.componentComplete();
+
     QSignalSpy errorSpy(&audio, SIGNAL(error(QDeclarativeAudio::Error,QString)));
     QSignalSpy errorChangedSpy(&audio, SIGNAL(errorChanged()));
 
diff --git a/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp b/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp
index 5fd3675..56dce28 100644
--- a/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp
+++ b/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp
@@ -304,11 +304,12 @@ void tst_QmlGraphicsVideo::nullPlayerControl()
 
     QCOMPARE(video.source(), QUrl());
     video.setSource(QUrl("http://example.com"));
-    QCOMPARE(video.source(), QUrl());
+    QCOMPARE(video.source(), QUrl("http://example.com"));
 
     QCOMPARE(video.isPlaying(), false);
     video.setPlaying(true);
-    QCOMPARE(video.isPlaying(), false);
+    QCOMPARE(video.isPlaying(), true);
+    video.setPlaying(false);
     video.play();
     QCOMPARE(video.isPlaying(), false);
 
@@ -322,15 +323,15 @@ void tst_QmlGraphicsVideo::nullPlayerControl()
 
     QCOMPARE(video.position(), 0);
     video.setPosition(10000);
-    QCOMPARE(video.position(), 0);
+    QCOMPARE(video.position(), 10000);
 
-    QCOMPARE(video.volume(), qreal(0));
-    video.setVolume(50);
-    QCOMPARE(video.volume(), qreal(0));
+    QCOMPARE(video.volume(), qreal(1.0));
+    video.setVolume(0.5);
+    QCOMPARE(video.volume(), qreal(0.5));
 
     QCOMPARE(video.isMuted(), false);
     video.setMuted(true);
-    QCOMPARE(video.isMuted(), false);
+    QCOMPARE(video.isMuted(), true);
 
     QCOMPARE(video.bufferProgress(), qreal(0));
 
@@ -354,11 +355,12 @@ void tst_QmlGraphicsVideo::nullService()
 
     QCOMPARE(video.source(), QUrl());
     video.setSource(QUrl("http://example.com"));
-    QCOMPARE(video.source(), QUrl());
+    QCOMPARE(video.source(), QUrl("http://example.com"));
 
     QCOMPARE(video.isPlaying(), false);
     video.setPlaying(true);
-    QCOMPARE(video.isPlaying(), false);
+    QCOMPARE(video.isPlaying(), true);
+    video.setPlaying(false);
     video.play();
     QCOMPARE(video.isPlaying(), false);
 
@@ -372,15 +374,15 @@ void tst_QmlGraphicsVideo::nullService()
 
     QCOMPARE(video.position(), 0);
     video.setPosition(10000);
-    QCOMPARE(video.position(), 0);
+    QCOMPARE(video.position(), 10000);
 
-    QCOMPARE(video.volume(), qreal(0));
-    video.setVolume(50);
-    QCOMPARE(video.volume(), qreal(0));
+    QCOMPARE(video.volume(), qreal(1.0));
+    video.setVolume(0.5);
+    QCOMPARE(video.volume(), qreal(0.5));
 
     QCOMPARE(video.isMuted(), false);
     video.setMuted(true);
-    QCOMPARE(video.isMuted(), false);
+    QCOMPARE(video.isMuted(), true);
 
     QCOMPARE(video.bufferProgress(), qreal(0));
 
@@ -404,6 +406,7 @@ void tst_QmlGraphicsVideo::playing()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
+    video.componentComplete();
 
     QSignalSpy playingChangedSpy(&video, SIGNAL(playingChanged()));
     QSignalSpy startedSpy(&video, SIGNAL(started()));
@@ -491,6 +494,7 @@ void tst_QmlGraphicsVideo::paused()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
+    video.componentComplete();
 
     QSignalSpy playingChangedSpy(&video, SIGNAL(playingChanged()));
     QSignalSpy pausedChangedSpy(&video, SIGNAL(pausedChanged()));
@@ -780,6 +784,7 @@ void tst_QmlGraphicsVideo::error()
 
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
+    video.componentComplete();
 
     QSignalSpy errorSpy(&video, SIGNAL(error(QDeclarativeVideo::Error,QString)));
     QSignalSpy errorChangedSpy(&video, SIGNAL(errorChanged()));
@@ -814,6 +819,7 @@ void tst_QmlGraphicsVideo::hasAudio()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
+    video.componentComplete();
 
     QSignalSpy spy(&video, SIGNAL(hasAudioChanged()));
 
@@ -837,6 +843,8 @@ void tst_QmlGraphicsVideo::hasVideo()
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
 
+    video.componentComplete();
+
     QSignalSpy spy(&video, SIGNAL(hasVideoChanged()));
 
     QCOMPARE(video.hasVideo(), false);
@@ -858,6 +866,7 @@ void tst_QmlGraphicsVideo::fillMode()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
+    video.componentComplete();
 
     QList<QGraphicsItem *> children = video.childItems();
     QCOMPARE(children.count(), 1);
@@ -883,6 +892,7 @@ void tst_QmlGraphicsVideo::geometry()
 {
     QtTestMediaServiceProvider provider;
     QDeclarativeVideo video;
+    video.componentComplete();
 
     QAbstractVideoSurface *surface = provider.rendererControl()->surface();
     QVERIFY(surface != 0);
-- 
cgit v0.12


From ace866a969cd438b9f1dc11b7d40a99f53a13009 Mon Sep 17 00:00:00 2001
From: Justin McPherson <justin.mcpherson@nokia.com>
Date: Fri, 19 Mar 2010 14:25:45 +1000
Subject: Add autoLoad property to multimedia declarative elements.

Task-number: QTBUG-8947
Reviewed-by: Andrew den Exter
---
 src/imports/multimedia/qdeclarativeaudio.cpp       |  8 +++++
 src/imports/multimedia/qdeclarativeaudio_p.h       |  3 +-
 src/imports/multimedia/qdeclarativemediabase.cpp   | 42 ++++++++++++++++++----
 src/imports/multimedia/qdeclarativemediabase_p.h   |  6 ++++
 src/imports/multimedia/qdeclarativevideo.cpp       |  8 +++++
 src/imports/multimedia/qdeclarativevideo_p.h       |  3 +-
 .../qdeclarativeaudio/tst_qdeclarativeaudio.cpp    | 28 +++++++++++++++
 7 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/src/imports/multimedia/qdeclarativeaudio.cpp b/src/imports/multimedia/qdeclarativeaudio.cpp
index 39223dc..dfe125f 100644
--- a/src/imports/multimedia/qdeclarativeaudio.cpp
+++ b/src/imports/multimedia/qdeclarativeaudio.cpp
@@ -142,6 +142,14 @@ void QDeclarativeAudio::stop()
 */
 
 /*!
+    \qmlproperty url Audio:autoLoad
+
+    This property indicates if loading of media should begin immediately.
+
+    Defaults to true, if false media will not be loaded until playback is started.
+*/
+
+/*!
     \qmlproperty bool Audio::playing
 
     This property holds whether the media is playing.
diff --git a/src/imports/multimedia/qdeclarativeaudio_p.h b/src/imports/multimedia/qdeclarativeaudio_p.h
index 2e8ae30..24276ea 100644
--- a/src/imports/multimedia/qdeclarativeaudio_p.h
+++ b/src/imports/multimedia/qdeclarativeaudio_p.h
@@ -69,6 +69,7 @@ class QDeclarativeAudio : public QObject, public QDeclarativeMediaBase, public Q
 {
     Q_OBJECT
     Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+    Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
     Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
     Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
     Q_PROPERTY(Status status READ status NOTIFY statusChanged)
@@ -123,7 +124,7 @@ public Q_SLOTS:
 
 Q_SIGNALS:
     void sourceChanged();
-
+    void autoLoadChanged();
     void playingChanged();
     void pausedChanged();
 
diff --git a/src/imports/multimedia/qdeclarativemediabase.cpp b/src/imports/multimedia/qdeclarativemediabase.cpp
index 542c931..5bad969 100644
--- a/src/imports/multimedia/qdeclarativemediabase.cpp
+++ b/src/imports/multimedia/qdeclarativemediabase.cpp
@@ -228,6 +228,8 @@ void QDeclarativeMediaBase::_q_metaDataChanged()
 QDeclarativeMediaBase::QDeclarativeMediaBase()
     : m_paused(false)
     , m_playing(false)
+    , m_autoLoad(true)
+    , m_loaded(false)
     , m_muted(false)
     , m_position(0)
     , m_volume(1.0)
@@ -315,13 +317,15 @@ void QDeclarativeMediaBase::setObject(QObject *object)
     m_playerControl->setMuted(m_muted);
     m_playerControl->setPlaybackRate(m_playbackRate);
 
-    if (!m_source.isEmpty())
+    if (!m_source.isEmpty() && (m_autoLoad || m_playing)) // Override autoLoad if playing set
         m_playerControl->setMedia(m_source, 0);
 
-    if (m_playing)
+    if (m_paused)
+        m_playerControl->pause();
+    else if (m_playing)
         m_playerControl->play();
 
-    if (m_position > 0)
+    if ((m_playing || m_paused) && m_position > 0)
         m_playerControl->setPosition(m_position);
 }
 
@@ -339,8 +343,8 @@ void QDeclarativeMediaBase::setSource(const QUrl &url)
         return;
 
     m_source = url;
-
-    if (m_playerControl != 0) {
+    m_loaded = false;
+    if (m_playerControl != 0 && m_autoLoad) {
         if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) {
             m_error = QMediaPlayer::NoError;
             m_errorString = QString();
@@ -349,11 +353,26 @@ void QDeclarativeMediaBase::setSource(const QUrl &url)
         }
 
         m_playerControl->setMedia(m_source, 0);
+        m_loaded = true;
     }
     else
         emit sourceChanged();
 }
 
+bool QDeclarativeMediaBase::isAutoLoad() const
+{
+    return m_autoLoad;
+}
+
+void QDeclarativeMediaBase::setAutoLoad(bool autoLoad)
+{
+    if (m_autoLoad == autoLoad)
+        return;
+
+    m_autoLoad = autoLoad;
+    emit autoLoadChanged();
+}
+
 bool QDeclarativeMediaBase::isPlaying() const
 {
     return m_playing;
@@ -367,6 +386,12 @@ void QDeclarativeMediaBase::setPlaying(bool playing)
     m_playing = playing;
     if (m_playerControl != 0) {
         if (m_playing) {
+            if (!m_autoLoad && !m_loaded) {
+                m_playerControl->setMedia(m_source, 0);
+                m_playerControl->setPosition(m_position);
+                m_loaded = true;
+            }
+
             if (!m_paused)
                 m_playerControl->play();
             else
@@ -391,7 +416,12 @@ void QDeclarativeMediaBase::setPaused(bool paused)
 
     m_paused = paused;
     if (m_playerControl != 0) {
-        // Check if completed, change state
+        if (!m_autoLoad && !m_loaded) {
+            m_playerControl->setMedia(m_source, 0);
+            m_playerControl->setPosition(m_position);
+            m_loaded = true;
+        }
+
         if (m_paused && m_state == QMediaPlayer::PlayingState) {
             m_playerControl->pause();
         }
diff --git a/src/imports/multimedia/qdeclarativemediabase_p.h b/src/imports/multimedia/qdeclarativemediabase_p.h
index d279f4a..43df54d 100644
--- a/src/imports/multimedia/qdeclarativemediabase_p.h
+++ b/src/imports/multimedia/qdeclarativemediabase_p.h
@@ -76,6 +76,9 @@ public:
     QUrl source() const;
     void setSource(const QUrl &url);
 
+    bool isAutoLoad() const;
+    void setAutoLoad(bool autoLoad);
+
     bool isPlaying() const;
     void setPlaying(bool playing);
 
@@ -115,6 +118,7 @@ protected:
     void setObject(QObject *object);
 
     virtual void sourceChanged() = 0;
+    virtual void autoLoadChanged() = 0;
     virtual void playingChanged() = 0;
     virtual void pausedChanged() = 0;
 
@@ -146,6 +150,8 @@ protected:
 
     bool m_paused;
     bool m_playing;
+    bool m_autoLoad;
+    bool m_loaded;
     bool m_muted;
     int m_position;
     qreal m_volume;
diff --git a/src/imports/multimedia/qdeclarativevideo.cpp b/src/imports/multimedia/qdeclarativevideo.cpp
index 67d9aef..6aff9bd 100644
--- a/src/imports/multimedia/qdeclarativevideo.cpp
+++ b/src/imports/multimedia/qdeclarativevideo.cpp
@@ -116,6 +116,14 @@ QDeclarativeVideo::~QDeclarativeVideo()
 */
 
 /*!
+    \qmlproperty url Audio:autoLoad
+
+    This property indicates if loading of media should begin immediately.
+
+    Defaults to true, if false media will not be loaded until playback is started.
+*/
+
+/*!
     \qmlproperty bool Video::playing
 
     This property holds whether the media is playing.
diff --git a/src/imports/multimedia/qdeclarativevideo_p.h b/src/imports/multimedia/qdeclarativevideo_p.h
index 2dead2e..29e1090 100644
--- a/src/imports/multimedia/qdeclarativevideo_p.h
+++ b/src/imports/multimedia/qdeclarativevideo_p.h
@@ -73,6 +73,7 @@ class QDeclarativeVideo : public QDeclarativeItem, public QDeclarativeMediaBase
 {
     Q_OBJECT
     Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+    Q_PROPERTY(bool autoLoad READ isAutoLoad WRITE setAutoLoad NOTIFY autoLoadChanged)
     Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged)
     Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged)
     Q_PROPERTY(Status status READ status NOTIFY statusChanged)
@@ -145,7 +146,7 @@ public Q_SLOTS:
 
 Q_SIGNALS:
     void sourceChanged();
-
+    void autoLoadChanged();
     void playingChanged();
     void pausedChanged();
 
diff --git a/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
index a604854..a215bd5 100644
--- a/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
+++ b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp
@@ -61,6 +61,7 @@ private slots:
     void nullService();
 
     void source();
+    void autoLoad();
     void playing();
     void paused();
     void duration();
@@ -430,6 +431,33 @@ void tst_QmlAudio::source()
     QCOMPARE(spy.count(), 3);
 }
 
+void tst_QmlAudio::autoLoad()
+{
+    QtTestMediaServiceProvider provider;
+    QDeclarativeAudio audio;
+    audio.componentComplete();
+
+    QSignalSpy spy(&audio, SIGNAL(autoLoadChanged()));
+
+    QCOMPARE(audio.isAutoLoad(), true);
+
+    audio.setAutoLoad(false);
+    QCOMPARE(audio.isAutoLoad(), false);
+    QCOMPARE(spy.count(), 1);
+
+    audio.setSource(QUrl("http://example.com"));
+    QCOMPARE(audio.source(), QUrl("http://example.com"));
+    audio.play();
+    QCOMPARE(audio.isPlaying(), true);
+    audio.stop();
+
+    audio.setAutoLoad(true);
+    audio.setSource(QUrl("http://example.com"));
+    audio.setPaused(true);
+    QCOMPARE(spy.count(), 2);
+    QCOMPARE(audio.isPaused(), true);
+}
+
 void tst_QmlAudio::playing()
 {
     QtTestMediaServiceProvider provider;
-- 
cgit v0.12