Replace QSoundEffect backend using qmedia with qaudiooutput implementation
authorKurt Korbatits <kurt.korbatits@nokia.com>
Wed, 18 Jul 2012 05:39:20 +0000 (15:39 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 26 Jul 2012 21:10:46 +0000 (23:10 +0200)
- Use backend built on QAudioOutput
- Fixed unit test so backend will pass

Change-Id: I2f2a7d8bf382127c5a5c333d6e36c79169754b4e
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
Reviewed-by: Kurt Korbatits <kurt.korbatits@nokia.com>
src/multimedia/audio/audio.pri
src/multimedia/audio/qsoundeffect.cpp
src/multimedia/audio/qsoundeffect_qaudio_p.cpp [new file with mode: 0644]
src/multimedia/audio/qsoundeffect_qaudio_p.h [moved from src/multimedia/audio/qsoundeffect_qmedia_p.h with 78% similarity]
src/multimedia/audio/qsoundeffect_qmedia_p.cpp [deleted file]
tests/auto/integration/qsoundeffect/tst_qsoundeffect.cpp

index 6fc99f9..73a9d65 100644 (file)
@@ -72,9 +72,9 @@ unix:!mac {
         SOURCES += audio/qsoundeffect_pulse_p.cpp
         !maemo*:DEFINES += QTM_PULSEAUDIO_DEFAULTBUFFER
     } else {
-        DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER
-        PRIVATE_HEADERS += audio/qsoundeffect_qmedia_p.h
-        SOURCES += audio/qsoundeffect_qmedia_p.cpp
+        DEFINES += QT_MULTIMEDIA_QAUDIO
+        PRIVATE_HEADERS += audio/qsoundeffect_qaudio_p.h
+        SOURCES += audio/qsoundeffect_qaudio_p.cpp
 
         config_alsa {
             DEFINES += HAS_ALSA
@@ -86,7 +86,7 @@ unix:!mac {
         }
     }
 } else {
-    DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER
-    PRIVATE_HEADERS += audio/qsoundeffect_qmedia_p.h
-    SOURCES += audio/qsoundeffect_qmedia_p.cpp
+    DEFINES += QT_MULTIMEDIA_QAUDIO
+    PRIVATE_HEADERS += audio/qsoundeffect_qaudio_p.h
+    SOURCES += audio/qsoundeffect_qaudio_p.cpp
 }
index 956f868..373e6fb 100644 (file)
@@ -43,8 +43,8 @@
 
 #if defined(QT_MULTIMEDIA_PULSEAUDIO)
 #include "qsoundeffect_pulse_p.h"
-#elif(QT_MULTIMEDIA_QMEDIAPLAYER)
-#include "qsoundeffect_qmedia_p.h"
+#elif(QT_MULTIMEDIA_QAUDIO)
+#include "qsoundeffect_qaudio_p.h"
 #endif
 
 QT_BEGIN_NAMESPACE
diff --git a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp
new file mode 100644 (file)
index 0000000..7727063
--- /dev/null
@@ -0,0 +1,445 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// INTERNAL USE ONLY: Do NOT use for any other purpose.
+//
+
+#include "qsoundeffect_qaudio_p.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qiodevice.h>
+
+//#include <QDebug>
+//#define QT_QAUDIO_DEBUG 1
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QSampleCache, sampleCache)
+
+QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
+    QObject(parent),
+    d(new PrivateSoundSource(this))
+{
+}
+
+QSoundEffectPrivate::~QSoundEffectPrivate()
+{
+}
+
+void QSoundEffectPrivate::release()
+{
+    stop();
+    if (d->m_audioOutput) {
+        d->m_audioOutput->stop();
+        d->m_audioOutput->deleteLater();
+        d->m_sample->release();
+    }
+    delete d;
+    this->deleteLater();
+}
+
+QStringList QSoundEffectPrivate::supportedMimeTypes()
+{
+    return QStringList() << QLatin1String("audio/x-wav")
+                         << QLatin1String("audio/wav")
+                         << QLatin1String("audio/wave")
+                         << QLatin1String("audio/x-pn-wav");
+}
+
+QUrl QSoundEffectPrivate::source() const
+{
+    return d->m_url;
+}
+
+void QSoundEffectPrivate::setSource(const QUrl &url)
+{
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "setSource current=" << d->m_url << ", to=" << url;
+#endif
+    Q_ASSERT(d->m_url != url);
+
+    stop();
+
+    d->m_url = url;
+
+    d->m_sampleReady = false;
+
+    if (url.isEmpty()) {
+        setStatus(QSoundEffect::Null);
+        return;
+    }
+
+    if (!url.isValid()) {
+        setStatus(QSoundEffect::Error);
+        return;
+    }
+
+    if (d->m_sample) {
+        if (!d->m_sampleReady) {
+            disconnect(d->m_sample, SIGNAL(error()), d, SLOT(decoderError()));
+            disconnect(d->m_sample, SIGNAL(ready()), d, SLOT(sampleReady()));
+        }
+        d->m_sample->release();
+        d->m_sample = 0;
+    }
+
+    setStatus(QSoundEffect::Loading);
+    d->m_sample = sampleCache()->requestSample(url);
+    connect(d->m_sample, SIGNAL(error()), d, SLOT(decoderError()));
+    connect(d->m_sample, SIGNAL(ready()), d, SLOT(sampleReady()));
+
+    switch (d->m_sample->state()) {
+    case QSample::Ready:
+        d->sampleReady();
+        break;
+    case QSample::Error:
+        d->decoderError();
+        break;
+    default:
+        break;
+    }
+}
+
+int QSoundEffectPrivate::loopCount() const
+{
+    return d->m_loopCount;
+}
+
+int QSoundEffectPrivate::loopsRemaining() const
+{
+    return d->m_runningCount;
+}
+
+void QSoundEffectPrivate::setLoopCount(int loopCount)
+{
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << "setLoopCount " << loopCount;
+#endif
+    if (loopCount == 0)
+        loopCount = 1;
+    d->m_loopCount = loopCount;
+    d->m_runningCount = loopCount;
+}
+
+int QSoundEffectPrivate::volume() const
+{
+    if (d->m_audioOutput && !d->m_muted)
+        return d->m_audioOutput->volume()*100.0f;
+
+    return d->m_volume;
+}
+
+void QSoundEffectPrivate::setVolume(int volume)
+{
+    d->m_volume = volume;
+
+    if (d->m_audioOutput && !d->m_muted)
+        d->m_audioOutput->setVolume(volume/100.0f);
+
+    emit volumeChanged();
+}
+
+bool QSoundEffectPrivate::isMuted() const
+{
+    return d->m_muted;
+}
+
+void QSoundEffectPrivate::setMuted(bool muted)
+{
+    if (muted && d->m_audioOutput)
+        d->m_audioOutput->setVolume(0);
+    else if (!muted && d->m_audioOutput && d->m_muted)
+        d->m_audioOutput->setVolume(d->m_volume/100.0f);
+
+    d->m_muted = muted;
+    emit mutedChanged();
+}
+
+bool QSoundEffectPrivate::isLoaded() const
+{
+    return d->m_status == QSoundEffect::Ready;
+}
+
+
+bool QSoundEffectPrivate::isPlaying() const
+{
+    return d->m_playing;
+}
+
+QSoundEffect::Status QSoundEffectPrivate::status() const
+{
+    return d->m_status;
+}
+
+void QSoundEffectPrivate::play()
+{
+    d->m_offset = 0;
+    d->m_runningCount = d->m_loopCount;
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "play";
+#endif
+    if (d->m_status == QSoundEffect::Null || d->m_status == QSoundEffect::Error) {
+        setStatus(QSoundEffect::Null);
+        return;
+    }
+    if (d->m_audioOutput && d->m_audioOutput->state() == QAudio::StoppedState && d->m_sampleReady)
+        d->m_audioOutput->start(d);
+
+    setPlaying(true);
+}
+
+void QSoundEffectPrivate::stop()
+{
+    if (!d->m_playing)
+        return;
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << "stop()";
+#endif
+    d->m_offset = 0;
+
+    setPlaying(false);
+
+    if (d->m_audioOutput)
+        d->m_audioOutput->stop();
+}
+
+void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
+{
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "setStatus" << status;
+#endif
+    if (d->m_status == status)
+        return;
+    bool oldLoaded = isLoaded();
+    d->m_status = status;
+    emit statusChanged();
+    if (oldLoaded != isLoaded())
+        emit loadedChanged();
+}
+
+void QSoundEffectPrivate::setPlaying(bool playing)
+{
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "setPlaying(" << playing << ")";
+#endif
+    if (d->m_playing == playing)
+        return;
+    d->m_playing = playing;
+    emit playingChanged();
+}
+
+void QSoundEffectPrivate::setLoopsRemaining(int loopsRemaining)
+{
+    if (!d->m_runningCount && loopsRemaining)
+        return;
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "setLoopsRemaining " << loopsRemaining;
+#endif
+    d->m_runningCount = loopsRemaining;
+    emit loopsRemainingChanged();
+}
+
+/* Categories are ignored */
+QString QSoundEffectPrivate::category() const
+{
+    return d->m_category;
+}
+
+void QSoundEffectPrivate::setCategory(const QString &category)
+{
+    if (d->m_category != category && !d->m_playing) {
+        d->m_category = category;
+        emit categoryChanged();
+    }
+}
+
+PrivateSoundSource::PrivateSoundSource(QSoundEffectPrivate* s):
+    m_loopCount(1),
+    m_runningCount(0),
+    m_playing(false),
+    m_status(QSoundEffect::Null),
+    m_audioOutput(0),
+    m_sample(0),
+    m_muted(false),
+    m_volume(100),
+    m_sampleReady(false),
+    m_offset(0)
+{
+    soundeffect = s;
+    m_category = QLatin1String("game");
+    open(QIODevice::ReadOnly);
+}
+
+void PrivateSoundSource::sampleReady()
+{
+    if (m_status == QSoundEffect::Error)
+        return;
+
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "sampleReady "<<m_playing;
+#endif
+    disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
+    disconnect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
+    if (!m_audioOutput) {
+        m_audioOutput = new QAudioOutput(m_sample->format());
+        connect(m_audioOutput,SIGNAL(stateChanged(QAudio::State)), this, SLOT(stateChanged(QAudio::State)));
+        if (!m_muted)
+            m_audioOutput->setVolume(m_volume/100.0f);
+        else
+            m_audioOutput->setVolume(0);
+    }
+    m_sampleReady = true;
+    soundeffect->setStatus(QSoundEffect::Ready);
+
+    if (m_playing)
+        m_audioOutput->start(this);
+}
+
+void PrivateSoundSource::decoderError()
+{
+    qWarning("QSoundEffect(qaudio): Error decoding source");
+    disconnect(m_sample, SIGNAL(ready()), this, SLOT(sampleReady()));
+    disconnect(m_sample, SIGNAL(error()), this, SLOT(decoderError()));
+    m_playing = false;
+    soundeffect->setStatus(QSoundEffect::Error);
+}
+
+void PrivateSoundSource::stateChanged(QAudio::State state)
+{
+#ifdef QT_QAUDIO_DEBUG
+    qDebug() << this << "stateChanged " << state;
+#endif
+    if (state == QAudio::IdleState && m_runningCount == 0)
+        emit soundeffect->stop();
+}
+
+qint64 PrivateSoundSource::readData( char* data, qint64 len)
+{
+    if (m_runningCount > 0 && m_playing) {
+
+        if (m_sample->state() != QSample::Ready)
+            return 0;
+
+        qint64 bytesWritten = 0;
+
+        const int   periodSize = m_audioOutput->periodSize();
+        const int   sampleSize = m_sample->data().size();
+        const char* sampleData = m_sample->data().constData();
+
+        // Some systems can have large buffers we only need a max of three
+        int    periodsFree = qMin(3, (int)(m_audioOutput->bytesFree()/periodSize));
+        int    dataOffset = 0;
+
+#ifdef QT_QAUDIO_DEBUG
+        qDebug() << "bytesFree=" << m_audioOutput->bytesFree() << ", can fit " << periodsFree << " periodSize() chunks";
+#endif
+
+        while ((periodsFree > 0) && (bytesWritten + periodSize <= len)) {
+
+            if (sampleSize - m_offset >= periodSize) {
+                // We can fit a whole period of data
+                memcpy(data + dataOffset, sampleData + m_offset, periodSize);
+                m_offset += periodSize;
+                dataOffset += periodSize;
+                bytesWritten += periodSize;
+#ifdef QT_QAUDIO_DEBUG
+                qDebug() << "WHOLE PERIOD: bytesWritten=" << bytesWritten << ", offset=" << m_offset
+                         << ", filesize=" << sampleSize;
+#endif
+            } else {
+                // We are at end of sound, first write what is left of current sound
+                memcpy(data + dataOffset, sampleData + m_offset, sampleSize - m_offset);
+                bytesWritten += sampleSize - m_offset;
+                int wrapLen = periodSize - (sampleSize - m_offset);
+#ifdef QT_QAUDIO_DEBUG
+                qDebug() << "END OF SOUND: bytesWritten=" << bytesWritten << ", offset=" << m_offset
+                         << ", part1=" << (sampleSize-m_offset);
+#endif
+                dataOffset += (sampleSize - m_offset);
+                m_offset = 0;
+
+                if (m_runningCount > 0 || m_runningCount == QSoundEffect::Infinite) {
+                    // There are still more loops of this sound to play, append the start of sound to make up full period
+                    memcpy(data + dataOffset, sampleData + m_offset, wrapLen);
+                    m_offset += wrapLen;
+                    dataOffset += wrapLen;
+                    bytesWritten += wrapLen;
+#ifdef QT_QAUDIO_DEBUG
+                    qDebug() << "APPEND START FOR FULL PERIOD: bytesWritten=" << bytesWritten << ", offset=" << m_offset
+                             << ", part2=" << wrapLen;
+                    qDebug() << "part1 + part2 should be a period " << periodSize;
+#endif
+                    if (m_runningCount != QSoundEffect::Infinite)
+                        soundeffect->setLoopsRemaining(m_runningCount-1);
+                }
+            }
+            if (m_runningCount == 0)
+                break;
+
+            periodsFree--;
+        }
+        return bytesWritten;
+    }
+
+    return 0;
+}
+
+qint64 PrivateSoundSource::writeData(const char* data, qint64 len)
+{
+    Q_UNUSED(data)
+    Q_UNUSED(len)
+    return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qsoundeffect_qaudio_p.cpp"
similarity index 78%
rename from src/multimedia/audio/qsoundeffect_qmedia_p.h
rename to src/multimedia/audio/qsoundeffect_qaudio_p.h
index cc4786c..def1e72 100644 (file)
@@ -39,8 +39,8 @@
 **
 ****************************************************************************/
 
-#ifndef QSOUNDEFFECT_QMEDIA_H
-#define QSOUNDEFFECT_QMEDIA_H
+#ifndef QSOUNDEFFECT_QAUDIO_H
+#define QSOUNDEFFECT_QAUDIO_H
 
 //
 //  W A R N I N G
@@ -55,7 +55,8 @@
 
 #include <QtCore/qobject.h>
 #include <QtCore/qurl.h>
-#include "qmediaplayer.h"
+#include "qaudiooutput.h"
+#include "qsamplecache_p.h"
 #include "qsoundeffect.h"
 
 QT_BEGIN_HEADER
@@ -64,10 +65,45 @@ QT_BEGIN_NAMESPACE
 
 QT_MODULE(Multimedia)
 
+class QSoundEffectPrivate;
+
+class PrivateSoundSource : public QIODevice
+{
+    friend class QSoundEffectPrivate;
+    Q_OBJECT
+public:
+    PrivateSoundSource(QSoundEffectPrivate* s);
+    ~PrivateSoundSource() {}
+
+    qint64 readData( char* data, qint64 len);
+    qint64 writeData(const char* data, qint64 len);
+
+private Q_SLOTS:
+    void sampleReady();
+    void decoderError();
+    void stateChanged(QAudio::State);
+
+private:
+    QUrl           m_url;
+    int            m_loopCount;
+    int            m_runningCount;
+    bool           m_playing;
+    QSoundEffect::Status  m_status;
+    QAudioOutput   *m_audioOutput;
+    QSample        *m_sample;
+    bool           m_muted;
+    int            m_volume;
+    bool           m_sampleReady;
+    qint64         m_offset;
+    QString        m_category;
+
+    QSoundEffectPrivate *soundeffect;
+};
 
 
 class QSoundEffectPrivate : public QObject
 {
+    friend class PrivateSoundSource;
     Q_OBJECT
 public:
 
@@ -91,7 +127,6 @@ public:
 
     void release();
 
-    // Categories are not really supported with QMediaPlayer
     QString category() const;
     void setCategory(const QString &);
 
@@ -108,26 +143,16 @@ Q_SIGNALS:
     void statusChanged();
     void categoryChanged();
 
-private Q_SLOTS:
-    void stateChanged(QMediaPlayer::State);
-    void mediaStatusChanged(QMediaPlayer::MediaStatus);
-    void error(QMediaPlayer::Error);
-
 private:
     void setStatus(QSoundEffect::Status status);
     void setPlaying(bool playing);
     void setLoopsRemaining(int loopsRemaining);
 
-    int            m_loopCount;
-    int            m_runningCount;
-    bool           m_playing;
-    QSoundEffect::Status  m_status;
-    QMediaPlayer  *m_player;
-    QString         m_category;
+    PrivateSoundSource* d;
 };
 
 QT_END_NAMESPACE
 
 QT_END_HEADER
 
-#endif // QSOUNDEFFECT_QMEDIA_H
+#endif // QSOUNDEFFECT_QAUDIO_H
diff --git a/src/multimedia/audio/qsoundeffect_qmedia_p.cpp b/src/multimedia/audio/qsoundeffect_qmedia_p.cpp
deleted file mode 100644 (file)
index 66d05e6..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-//  W A R N I N G
-//  -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// INTERNAL USE ONLY: Do NOT use for any other purpose.
-//
-
-#include "qsoundeffect_qmedia_p.h"
-
-#include <QtCore/qcoreapplication.h>
-
-#include "qmediacontent.h"
-#include "qmediaplayer.h"
-
-
-QT_BEGIN_NAMESPACE
-
-QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent):
-    QObject(parent),
-    m_loopCount(1),
-    m_runningCount(0),
-    m_playing(false),
-    m_status(QSoundEffect::Null),
-    m_player(0)
-{
-    m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency);
-    connect(m_player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(stateChanged(QMediaPlayer::State)));
-    connect(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
-    connect(m_player, SIGNAL(error(QMediaPlayer::Error)), SLOT(error(QMediaPlayer::Error)));
-    connect(m_player, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged()));
-    connect(m_player, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged()));
-}
-
-void QSoundEffectPrivate::release()
-{
-    this->deleteLater();
-}
-
-QSoundEffectPrivate::~QSoundEffectPrivate()
-{
-}
-
-QStringList QSoundEffectPrivate::supportedMimeTypes()
-{
-    return QMediaPlayer::supportedMimeTypes();
-}
-
-QUrl QSoundEffectPrivate::source() const
-{
-    return m_player->media().canonicalUrl();
-}
-
-void QSoundEffectPrivate::setSource(const QUrl &url)
-{
-    m_player->setMedia(url);
-}
-
-int QSoundEffectPrivate::loopCount() const
-{
-    return m_loopCount;
-}
-
-int QSoundEffectPrivate::loopsRemaining() const
-{
-    return m_runningCount;
-}
-
-void QSoundEffectPrivate::setLoopCount(int loopCount)
-{
-    m_loopCount = loopCount;
-}
-
-int QSoundEffectPrivate::volume() const
-{
-    return m_player->volume();
-}
-
-void QSoundEffectPrivate::setVolume(int volume)
-{
-    m_player->setVolume(volume);
-}
-
-bool QSoundEffectPrivate::isMuted() const
-{
-    return m_player->isMuted();
-}
-
-void QSoundEffectPrivate::setMuted(bool muted)
-{
-    m_player->setMuted(muted);
-}
-
-bool QSoundEffectPrivate::isLoaded() const
-{
-    return m_status == QSoundEffect::Ready;
-}
-
-bool QSoundEffectPrivate::isPlaying() const
-{
-    return m_playing;
-}
-
-QSoundEffect::Status QSoundEffectPrivate::status() const
-{
-    return m_status;
-}
-
-void QSoundEffectPrivate::play()
-{
-    if (m_status == QSoundEffect::Null || m_status == QSoundEffect::Error)
-        return;
-    if (m_loopCount < 0) {
-        setLoopsRemaining(-1);
-    }
-    else {
-        if (m_runningCount < 0)
-            setLoopsRemaining(0);
-        setLoopsRemaining(m_runningCount + m_loopCount);
-    }
-    m_player->play();
-}
-
-void QSoundEffectPrivate::stop()
-{
-    setLoopsRemaining(0);
-    m_player->stop();
-}
-
-void QSoundEffectPrivate::stateChanged(QMediaPlayer::State state)
-{
-    if (state == QMediaPlayer::StoppedState) {
-        if (m_runningCount < 0) {
-            m_player->play();
-        } else if (m_runningCount == 0) {
-            setPlaying(false);
-            return;
-        } else {
-            setLoopsRemaining(m_runningCount - 1);
-            if (m_runningCount > 0) {
-                m_player->play();
-            } else {
-             setPlaying(false);
-            }
-        }
-    } else {
-        setPlaying(true);
-    }
-}
-
-void QSoundEffectPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus status)
-{
-    switch(status) {
-    case QMediaPlayer::LoadingMedia:
-        setStatus(QSoundEffect::Loading);
-        break;
-    case QMediaPlayer::NoMedia:
-        setStatus(QSoundEffect::Null);
-        break;
-    case QMediaPlayer::InvalidMedia:
-        setStatus(QSoundEffect::Error);
-        break;
-    default:
-        setStatus(QSoundEffect::Ready);
-        break;
-    }
-}
-
-void QSoundEffectPrivate::error(QMediaPlayer::Error err)
-{
-    Q_UNUSED(err);
-    bool playingDirty = false;
-    if (m_playing) {
-        m_playing = false;
-        playingDirty = true;
-    }
-    setStatus(QSoundEffect::Error);
-    if (playingDirty)
-        emit playingChanged();
-}
-
-void QSoundEffectPrivate::setStatus(QSoundEffect::Status status)
-{
-    if (m_status == status)
-        return;
-    bool oldLoaded = isLoaded();
-    m_status = status;
-    emit statusChanged();
-    if (oldLoaded != isLoaded())
-        emit loadedChanged();
-}
-
-void QSoundEffectPrivate::setPlaying(bool playing)
-{
-    if (m_playing == playing)
-        return;
-    m_playing = playing;
-    emit playingChanged();
-}
-
-void QSoundEffectPrivate::setLoopsRemaining(int loopsRemaining)
-{
-    if (m_runningCount == loopsRemaining)
-        return;
-    m_runningCount = loopsRemaining;
-    emit loopsRemainingChanged();
-}
-
-/* Categories are ignored */
-QString QSoundEffectPrivate::category() const
-{
-    return m_category;
-}
-
-void QSoundEffectPrivate::setCategory(const QString &category)
-{
-    if (m_category != category && !m_playing) {
-        m_category = category;
-        emit categoryChanged();
-    }
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qsoundeffect_qmedia_p.cpp"
index 131aed0..adcb9cd 100644 (file)
@@ -155,10 +155,7 @@ void tst_QSoundEffect::testLooping()
     // test.wav is about 200ms, wait until it has finished playing 5 times
     QTestEventLoop::instance().enterLoop(3);
 
-    QCOMPARE(sound->loopsRemaining(), 0);
-#ifdef Q_OS_MAC
-    QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
+    QTRY_COMPARE(sound->loopsRemaining(), 0);
     QCOMPARE(readSignal_Remaining.count(),5);
 }
 
@@ -193,7 +190,7 @@ void tst_QSoundEffect::testPlaying()
     QTestEventLoop::instance().enterLoop(1);
     sound->play();
     QTestEventLoop::instance().enterLoop(1);
-    QCOMPARE(sound->isPlaying(), true);
+    QTRY_COMPARE(sound->isPlaying(), true);
     sound->stop();
 
     //empty source
@@ -201,17 +198,14 @@ void tst_QSoundEffect::testPlaying()
     QTestEventLoop::instance().enterLoop(1);
     sound->play();
     QTestEventLoop::instance().enterLoop(1);
-#ifdef Q_OS_MAC
-    QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
-    QCOMPARE(sound->isPlaying(), false);
+    QTRY_COMPARE(sound->isPlaying(), false);
 
     //invalid source
     sound->setSource(QUrl((QLatin1String("invalid source"))));
     QTestEventLoop::instance().enterLoop(1);
     sound->play();
     QTestEventLoop::instance().enterLoop(1);
-    QTRY_VERIFY(!sound->isPlaying());
+    QTRY_COMPARE(sound->isPlaying(), false);
 
     sound->setLoopCount(1); // TODO: What if one of the tests fail?
 }
@@ -219,9 +213,6 @@ void tst_QSoundEffect::testPlaying()
 void tst_QSoundEffect::testStatus()
 {
     sound->setSource(QUrl());
-#ifdef Q_OS_MAC
-    QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
     QCOMPARE(sound->status(), QSoundEffect::Null);
 
     //valid source
@@ -281,9 +272,6 @@ void tst_QSoundEffect::testSetSourceWhileLoading()
         QVERIFY(sound->isPlaying());
 
         sound->setSource(QUrl());
-#ifdef Q_OS_MAC
-        QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
         QCOMPARE(sound->status(), QSoundEffect::Null);
 
         sound->setSource(url2);
@@ -314,9 +302,6 @@ void tst_QSoundEffect::testSetSourceWhilePlaying()
         QVERIFY(sound->isPlaying());
 
         sound->setSource(QUrl());
-#ifdef Q_OS_MAC
-        QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
         QCOMPARE(sound->status(), QSoundEffect::Null);
 
         sound->setSource(url2);
@@ -338,9 +323,6 @@ void tst_QSoundEffect::testSetSourceWhilePlaying()
 void tst_QSoundEffect::testSupportedMimeTypes()
 {
     QStringList mimeTypes = sound->supportedMimeTypes();
-#ifdef Q_OS_MAC
-    QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
     QVERIFY(!mimeTypes.empty());
     QVERIFY(mimeTypes.indexOf(QLatin1String("audio/wav")) != -1 ||
             mimeTypes.indexOf(QLatin1String("audio/x-wav")) != -1 ||
@@ -356,9 +338,6 @@ void tst_QSoundEffect::testCorruptFile()
         QVERIFY(!sound->isPlaying());
         QVERIFY(sound->status() == QSoundEffect::Loading || sound->status() == QSoundEffect::Error);
         QTRY_COMPARE(sound->status(), QSoundEffect::Error);
-#ifdef Q_OS_MAC
-        QEXPECT_FAIL("", "QTBUG-26488 Fails on Mac", Abort);
-#endif
         QCOMPARE(statusSpy.count(), 2);
         sound->play();
         QVERIFY(!sound->isPlaying());