qtmobility/tests/auto/qaudiooutput/tst_qaudiooutput.cpp
changeset 14 6fbed849b4f4
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QtTest/QtTest>
       
    43 #include <QtCore/qlocale.h>
       
    44 
       
    45 #include <qaudiooutput.h>
       
    46 #include <qaudiodeviceinfo.h>
       
    47 #include <qaudioformat.h>
       
    48 #include <qaudio.h>
       
    49 
       
    50 #include "wavheader.h"
       
    51 
       
    52 #define AUDIO_BUFFER 192000
       
    53 
       
    54 #if defined(Q_OS_SYMBIAN)
       
    55 #define SRCDIR ""
       
    56 #endif
       
    57 
       
    58 class tst_QAudioOutput : public QObject
       
    59 {
       
    60     Q_OBJECT
       
    61 public:
       
    62     tst_QAudioOutput(QObject* parent=0) : QObject(parent) {}
       
    63 
       
    64 private slots:
       
    65     void initTestCase();
       
    66 
       
    67     void format();
       
    68     void invalidFormat();
       
    69 
       
    70     void bufferSize();
       
    71 
       
    72     void notifyInterval();
       
    73     void disableNotifyInterval();
       
    74 
       
    75     void stopWhileStopped();
       
    76     void suspendWhileStopped();
       
    77     void resumeWhileStopped();
       
    78 
       
    79     void pull();
       
    80     void pullSuspendResume();
       
    81 
       
    82     void push();
       
    83     void pushSuspendResume();
       
    84     void pushUnderrun();
       
    85 
       
    86     void cleanupTestCase();
       
    87 
       
    88 private:
       
    89     QString formatToFileName(const QAudioFormat &format);
       
    90     QString workingDir();
       
    91     void createSineWaveData(const QAudioFormat &format, qint64 length, int frequency = 440);
       
    92 
       
    93     QAudioDeviceInfo audioDevice;
       
    94     QList<QAudioFormat> testFormats;
       
    95     QList<QFile*> audioFiles;
       
    96 
       
    97     QScopedPointer<QByteArray> m_byteArray;
       
    98     QScopedPointer<QBuffer> m_buffer;
       
    99 };
       
   100 
       
   101 QString tst_QAudioOutput::formatToFileName(const QAudioFormat &format)
       
   102 {
       
   103     const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian)
       
   104         ?   QString("LE") : QString("BE");
       
   105 
       
   106     const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt)
       
   107         ?   QString("signed") : QString("unsigned");
       
   108 
       
   109     return QString("%1_%2_%3_%4_%5")
       
   110         .arg(format.frequency())
       
   111         .arg(format.sampleSize())
       
   112         .arg(formatSigned)
       
   113         .arg(formatEndian)
       
   114         .arg(format.channels());
       
   115 }
       
   116 
       
   117 
       
   118 QString tst_QAudioOutput::workingDir()
       
   119 {
       
   120     QDir working(QString(SRCDIR));
       
   121 
       
   122     if (working.exists())
       
   123         return QString(SRCDIR);
       
   124 
       
   125     return QDir::currentPath();
       
   126 }
       
   127 
       
   128 void tst_QAudioOutput::createSineWaveData(const QAudioFormat &format, qint64 length, int frequency)
       
   129 {
       
   130     const int channelBytes = format.sampleSize() / 8;
       
   131     const int sampleBytes = format.channels() * channelBytes;
       
   132 
       
   133     Q_ASSERT(length % sampleBytes == 0);
       
   134     Q_UNUSED(sampleBytes) // suppress warning in release builds
       
   135 
       
   136     m_byteArray.reset(new QByteArray(length, 0));
       
   137     unsigned char *ptr = reinterpret_cast<unsigned char *>(m_byteArray->data());
       
   138     int sampleIndex = 0;
       
   139 
       
   140     while (length) {
       
   141         const qreal x = qSin(2 * M_PI * frequency * qreal(sampleIndex % format.frequency()) / format.frequency());
       
   142         for (int i=0; i<format.channels(); ++i) {
       
   143             if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::UnSignedInt) {
       
   144                 const quint8 value = static_cast<quint8>((1.0 + x) / 2 * 255);
       
   145                 *reinterpret_cast<quint8*>(ptr) = value;
       
   146             } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) {
       
   147                 const qint8 value = static_cast<qint8>(x * 127);
       
   148                 *reinterpret_cast<quint8*>(ptr) = value;
       
   149             } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) {
       
   150                 quint16 value = static_cast<quint16>((1.0 + x) / 2 * 65535);
       
   151                 if (format.byteOrder() == QAudioFormat::LittleEndian)
       
   152                     qToLittleEndian<quint16>(value, ptr);
       
   153                 else
       
   154                     qToBigEndian<quint16>(value, ptr);
       
   155             } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) {
       
   156                 qint16 value = static_cast<qint16>(x * 32767);
       
   157                 if (format.byteOrder() == QAudioFormat::LittleEndian)
       
   158                     qToLittleEndian<qint16>(value, ptr);
       
   159                 else
       
   160                     qToBigEndian<qint16>(value, ptr);
       
   161             }
       
   162 
       
   163             ptr += channelBytes;
       
   164             length -= channelBytes;
       
   165         }
       
   166         ++sampleIndex;
       
   167     }
       
   168 
       
   169     m_buffer.reset(new QBuffer(m_byteArray.data(), this));
       
   170     Q_ASSERT(m_buffer->open(QIODevice::ReadOnly));
       
   171 }
       
   172 
       
   173 void tst_QAudioOutput::initTestCase()
       
   174 {
       
   175     // Only perform tests if audio output device exists
       
   176     const QList<QAudioDeviceInfo> devices =
       
   177         QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
       
   178     QVERIFY(devices.size() > 0);
       
   179 
       
   180     audioDevice = QAudioDeviceInfo::defaultOutputDevice();
       
   181 
       
   182 
       
   183     QAudioFormat format;
       
   184 
       
   185     format.setCodec("audio/pcm");
       
   186 
       
   187     if (audioDevice.isFormatSupported(audioDevice.preferredFormat()))
       
   188         testFormats.append(audioDevice.preferredFormat());
       
   189 
       
   190     // PCM 8000  mono S8
       
   191     format.setFrequency(8000);
       
   192     format.setSampleSize(8);
       
   193     format.setSampleType(QAudioFormat::SignedInt);
       
   194     format.setByteOrder(QAudioFormat::LittleEndian);
       
   195     format.setChannels(1);
       
   196     if (audioDevice.isFormatSupported(format))
       
   197         testFormats.append(format);
       
   198 
       
   199     // PCM 11025 mono S16LE
       
   200     format.setFrequency(11025);
       
   201     format.setSampleSize(16);
       
   202     if (audioDevice.isFormatSupported(format))
       
   203         testFormats.append(format);
       
   204 
       
   205     // PCM 22050 mono S16LE
       
   206     format.setFrequency(22050);
       
   207     if (audioDevice.isFormatSupported(format))
       
   208         testFormats.append(format);
       
   209 
       
   210     // PCM 22050 stereo S16LE
       
   211     format.setChannels(2);
       
   212     if (audioDevice.isFormatSupported(format))
       
   213         testFormats.append(format);
       
   214 
       
   215     // PCM 44100 stereo S16LE
       
   216     format.setFrequency(44100);
       
   217     if (audioDevice.isFormatSupported(format))
       
   218         testFormats.append(format);
       
   219 
       
   220     // PCM 48000 stereo S16LE
       
   221     format.setFrequency(48000);
       
   222     if (audioDevice.isFormatSupported(format))
       
   223         testFormats.append(format);
       
   224 
       
   225     QVERIFY(testFormats.size());
       
   226 
       
   227     foreach (format, testFormats) {
       
   228         qint64 len = (format.frequency()*format.channels()*(format.sampleSize()/8)*2); // 2 seconds
       
   229         createSineWaveData(format, len);
       
   230         // Write generate sine wave data to file
       
   231         QFile* file = new QFile(workingDir() + QString("generated") + formatToFileName(format) + QString(".wav"));
       
   232         if (file->open(QIODevice::WriteOnly)) {
       
   233             WavHeader wavHeader(format, len);
       
   234             wavHeader.write(*file);
       
   235             file->write(m_byteArray->data(), len);
       
   236             file->close();
       
   237             audioFiles.append(file);
       
   238         }
       
   239     }
       
   240 }
       
   241 
       
   242 void tst_QAudioOutput::format()
       
   243 {
       
   244     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   245 
       
   246     QAudioFormat requested = audioDevice.preferredFormat();
       
   247     QAudioFormat actual    = audioOutput.format();
       
   248 
       
   249     QVERIFY2((requested.channels() == actual.channels()),
       
   250             QString("channels: requested=%1, actual=%2").arg(requested.channels()).arg(actual.channels()).toLocal8Bit().constData());
       
   251     QVERIFY2((requested.frequency() == actual.frequency()),
       
   252             QString("frequency: requested=%1, actual=%2").arg(requested.frequency()).arg(actual.frequency()).toLocal8Bit().constData());
       
   253     QVERIFY2((requested.sampleSize() == actual.sampleSize()),
       
   254             QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData());
       
   255     QVERIFY2((requested.codec() == actual.codec()),
       
   256             QString("codec: requested=%1, actual=%2").arg(requested.codec()).arg(actual.codec()).toLocal8Bit().constData());
       
   257     QVERIFY2((requested.byteOrder() == actual.byteOrder()),
       
   258             QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData());
       
   259     QVERIFY2((requested.sampleType() == actual.sampleType()),
       
   260             QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData());
       
   261 }
       
   262 
       
   263 void tst_QAudioOutput::invalidFormat()
       
   264 {
       
   265     QAudioFormat invalidFormat;
       
   266     invalidFormat.setFrequency(0);
       
   267 
       
   268     QVERIFY2(!audioDevice.isFormatSupported(invalidFormat),
       
   269             "isFormatSupported() is returning true on an invalid format");
       
   270 
       
   271     QAudioOutput audioOutput(invalidFormat, this);
       
   272 
       
   273     // Check that we are in the default state before calling start
       
   274     QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   275     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   276 
       
   277     audioOutput.start();
       
   278 
       
   279     // Check that error is raised
       
   280     QVERIFY2((audioOutput.error() == QAudio::OpenError),"error() was not set to QAudio::OpenError after start()");
       
   281 }
       
   282 
       
   283 void tst_QAudioOutput::bufferSize()
       
   284 {
       
   285     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   286 
       
   287     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
       
   288 
       
   289     audioOutput.setBufferSize(512);
       
   290     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(512)");
       
   291     QVERIFY2((audioOutput.bufferSize() == 512),
       
   292             QString("bufferSize: requested=512, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData());
       
   293 
       
   294     audioOutput.setBufferSize(4096);
       
   295     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(4096)");
       
   296     QVERIFY2((audioOutput.bufferSize() == 4096),
       
   297             QString("bufferSize: requested=4096, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData());
       
   298 
       
   299     audioOutput.setBufferSize(8192);
       
   300     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(8192)");
       
   301     QVERIFY2((audioOutput.bufferSize() == 8192),
       
   302             QString("bufferSize: requested=8192, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData());
       
   303 }
       
   304 
       
   305 void tst_QAudioOutput::notifyInterval()
       
   306 {
       
   307     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   308 
       
   309     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
       
   310 
       
   311     audioOutput.setNotifyInterval(50);
       
   312     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(50)");
       
   313     QVERIFY2((audioOutput.notifyInterval() == 50),
       
   314             QString("notifyInterval: requested=50, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
       
   315 
       
   316     audioOutput.setNotifyInterval(100);
       
   317     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(100)");
       
   318     QVERIFY2((audioOutput.notifyInterval() == 100),
       
   319             QString("notifyInterval: requested=100, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
       
   320 
       
   321     audioOutput.setNotifyInterval(250);
       
   322     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(250)");
       
   323     QVERIFY2((audioOutput.notifyInterval() == 250),
       
   324             QString("notifyInterval: requested=250, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
       
   325 
       
   326     audioOutput.setNotifyInterval(1000);
       
   327     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(1000)");
       
   328     QVERIFY2((audioOutput.notifyInterval() == 1000),
       
   329             QString("notifyInterval: requested=1000, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData());
       
   330 }
       
   331 
       
   332 void tst_QAudioOutput::disableNotifyInterval()
       
   333 {
       
   334     // Sets an invalid notification interval (QAudioOutput::setNotifyInterval(0))
       
   335     // Checks that
       
   336     //  - No error is raised (QAudioOutput::error() returns QAudio::NoError)
       
   337     //  - if <= 0, set to zero and disable notify signal
       
   338 
       
   339     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   340 
       
   341     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation");
       
   342 
       
   343     audioOutput.setNotifyInterval(0);
       
   344     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(0)");
       
   345     QVERIFY2((audioOutput.notifyInterval() == 0),
       
   346             "notifyInterval() is not zero after setNotifyInterval(0)");
       
   347 
       
   348     audioOutput.setNotifyInterval(-1);
       
   349     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(-1)");
       
   350     QVERIFY2((audioOutput.notifyInterval() == 0),
       
   351             "notifyInterval() is not zero after setNotifyInterval(-1)");
       
   352 
       
   353     //start and run to check if notify() is emitted
       
   354     if (audioFiles.size() > 0) {
       
   355         QAudioOutput audioOutputCheck(testFormats.at(0), this);
       
   356         audioOutputCheck.setNotifyInterval(0);
       
   357         QSignalSpy notifySignal(&audioOutputCheck, SIGNAL(notify()));
       
   358         audioFiles.at(0)->open(QIODevice::ReadOnly);
       
   359         audioOutputCheck.start(audioFiles.at(0));
       
   360         QTest::qWait(3000); // 3 seconds should be plenty
       
   361         audioOutputCheck.stop();
       
   362         QVERIFY2((notifySignal.count() == 0),
       
   363                 QString("didn't disable notify interval: shouldn't have got any but got %1").arg(notifySignal.count()).toLocal8Bit().constData());
       
   364         audioFiles.at(0)->close();
       
   365     }
       
   366 }
       
   367 
       
   368 void tst_QAudioOutput::stopWhileStopped()
       
   369 {
       
   370     // Calls QAudioOutput::stop() when object is already in StoppedState
       
   371     // Checks that
       
   372     //  - No state change occurs
       
   373     //  - No error is raised (QAudioOutput::error() returns QAudio::NoError)
       
   374 
       
   375     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   376 
       
   377     QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   378     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   379 
       
   380     QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   381     audioOutput.stop();
       
   382 
       
   383     // Check that no state transition occurred
       
   384     QVERIFY2((stateSignal.count() == 0), "stop() while stopped is emitting a signal and it shouldn't");
       
   385     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()");
       
   386 }
       
   387 
       
   388 void tst_QAudioOutput::suspendWhileStopped()
       
   389 {
       
   390     // Calls QAudioOutput::suspend() when object is already in StoppedState
       
   391     // Checks that
       
   392     //  - No state change occurs
       
   393     //  - No error is raised (QAudioOutput::error() returns QAudio::NoError)
       
   394 
       
   395     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   396 
       
   397     QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   398     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   399 
       
   400     QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   401     audioOutput.suspend();
       
   402 
       
   403     // Check that no state transition occurred
       
   404     QVERIFY2((stateSignal.count() == 0), "stop() while suspended is emitting a signal and it shouldn't");
       
   405     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()");
       
   406 }
       
   407 
       
   408 void tst_QAudioOutput::resumeWhileStopped()
       
   409 {
       
   410     // Calls QAudioOutput::resume() when object is already in StoppedState
       
   411     // Checks that
       
   412     //  - No state change occurs
       
   413     //  - No error is raised (QAudioOutput::error() returns QAudio::NoError)
       
   414 
       
   415     QAudioOutput audioOutput(audioDevice.preferredFormat(), this);
       
   416 
       
   417     QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   418     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   419 
       
   420     QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   421     audioOutput.resume();
       
   422 
       
   423     // Check that no state transition occurred
       
   424     QVERIFY2((stateSignal.count() == 0), "resume() while stopped is emitting a signal and it shouldn't");
       
   425     QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after resume()");
       
   426 }
       
   427 
       
   428 void tst_QAudioOutput::pull()
       
   429 {
       
   430     for(int i=0; i<audioFiles.count(); i++) {
       
   431         QAudioOutput audioOutput(testFormats.at(i), this);
       
   432 
       
   433         audioOutput.setNotifyInterval(100);
       
   434 
       
   435         QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
       
   436         QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   437 
       
   438         // Check that we are in the default state before calling start
       
   439         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   440         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   441         QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
       
   442 
       
   443         audioFiles.at(i)->close();
       
   444         audioFiles.at(i)->open(QIODevice::ReadOnly);
       
   445         audioFiles.at(i)->seek(WavHeader::headerLength());
       
   446 
       
   447         audioOutput.start(audioFiles.at(i));
       
   448 
       
   449         // Check that QAudioOutput immediately transitions to ActiveState
       
   450         QVERIFY2((stateSignal.count() == 1),
       
   451                 QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   452         QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after start()");
       
   453         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
       
   454         QVERIFY(audioOutput.periodSize() > 0);
       
   455         stateSignal.clear();
       
   456 
       
   457         // Check that 'elapsed' increases
       
   458         QTest::qWait(40);
       
   459         QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
       
   460 
       
   461         // Wait until playback finishes
       
   462         QTest::qWait(3000); // 3 seconds should be plenty
       
   463 
       
   464         QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
       
   465         QVERIFY2((stateSignal.count() == 1),
       
   466             QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   467         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
       
   468         stateSignal.clear();
       
   469 
       
   470         qint64 processedUs = audioOutput.processedUSecs();
       
   471 
       
   472         audioOutput.stop();
       
   473         QTest::qWait(40);
       
   474         QVERIFY2((stateSignal.count() == 1),
       
   475             QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   476         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
       
   477 
       
   478         QVERIFY2((processedUs == 2000000),
       
   479                 QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
       
   480         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
       
   481         QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
       
   482         QVERIFY2((notifySignal.count() > 15 && notifySignal.count() < 25),
       
   483                 QString("too many notify() signals emitted (%1)").arg(notifySignal.count()).toLocal8Bit().constData());
       
   484 
       
   485         audioFiles.at(i)->close();
       
   486     }
       
   487 }
       
   488 
       
   489 void tst_QAudioOutput::pullSuspendResume()
       
   490 {
       
   491     for(int i=0; i<audioFiles.count(); i++) {
       
   492         QAudioOutput audioOutput(testFormats.at(i), this);
       
   493 
       
   494         audioOutput.setNotifyInterval(100);
       
   495 
       
   496         QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
       
   497         QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   498 
       
   499         // Check that we are in the default state before calling start
       
   500         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   501         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   502         QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
       
   503 
       
   504         audioFiles.at(i)->close();
       
   505         audioFiles.at(i)->open(QIODevice::ReadOnly);
       
   506         audioFiles.at(i)->seek(WavHeader::headerLength());
       
   507 
       
   508         audioOutput.start(audioFiles.at(i));
       
   509 
       
   510         // Check that QAudioOutput immediately transitions to ActiveState
       
   511         QVERIFY2((stateSignal.count() == 1),
       
   512                 QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   513         QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after start()");
       
   514         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
       
   515         QVERIFY(audioOutput.periodSize() > 0);
       
   516         stateSignal.clear();
       
   517 
       
   518         // Wait for half of clip to play
       
   519         QTest::qWait(1000);
       
   520 
       
   521         audioOutput.suspend();
       
   522 
       
   523         // Give backends running in separate threads a chance to suspend.
       
   524         QTest::qWait(100);
       
   525 
       
   526         QVERIFY2((stateSignal.count() == 1),
       
   527                 QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead")
       
   528                 .arg(stateSignal.count()).toLocal8Bit().constData());
       
   529         QVERIFY2((audioOutput.state() == QAudio::SuspendedState), "didn't transition to SuspendedState after suspend()");
       
   530         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after suspend()");
       
   531         stateSignal.clear();
       
   532 
       
   533         // Check that only 'elapsed', and not 'processed' increases while suspended
       
   534         qint64 elapsedUs = audioOutput.elapsedUSecs();
       
   535         qint64 processedUs = audioOutput.processedUSecs();
       
   536         QTest::qWait(1000);
       
   537         QVERIFY(audioOutput.elapsedUSecs() > elapsedUs);
       
   538         QVERIFY(audioOutput.processedUSecs() == processedUs);
       
   539 
       
   540         audioOutput.resume();
       
   541 
       
   542         // Give backends running in separate threads a chance to suspend.
       
   543         QTest::qWait(100);
       
   544 
       
   545         // Check that QAudioOutput immediately transitions to ActiveState
       
   546         QVERIFY2((stateSignal.count() == 1),
       
   547                 QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   548         QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()");
       
   549         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
       
   550         stateSignal.clear();
       
   551 
       
   552         // Wait until playback finishes
       
   553         QTest::qWait(3000); // 3 seconds should be plenty
       
   554 
       
   555         QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
       
   556         QVERIFY2((stateSignal.count() == 1),
       
   557             QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   558         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
       
   559         stateSignal.clear();
       
   560 
       
   561         processedUs = audioOutput.processedUSecs();
       
   562 
       
   563         audioOutput.stop();
       
   564         QTest::qWait(40);
       
   565         QVERIFY2((stateSignal.count() == 1),
       
   566             QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   567         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
       
   568 
       
   569         QVERIFY2((processedUs == 2000000),
       
   570                 QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
       
   571         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
       
   572         QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
       
   573 
       
   574         audioFiles.at(i)->close();
       
   575     }
       
   576 }
       
   577 
       
   578 void tst_QAudioOutput::push()
       
   579 {
       
   580     for(int i=0; i<audioFiles.count(); i++) {
       
   581         QAudioOutput audioOutput(testFormats.at(i), this);
       
   582 
       
   583         audioOutput.setNotifyInterval(100);
       
   584 
       
   585         QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
       
   586         QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   587 
       
   588         // Check that we are in the default state before calling start
       
   589         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   590         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   591         QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
       
   592 
       
   593         audioFiles.at(i)->close();
       
   594         audioFiles.at(i)->open(QIODevice::ReadOnly);
       
   595         audioFiles.at(i)->seek(WavHeader::headerLength());
       
   596 
       
   597         QIODevice* feed = audioOutput.start();
       
   598 
       
   599         // Check that QAudioOutput immediately transitions to IdleState
       
   600         QVERIFY2((stateSignal.count() == 1),
       
   601                 QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   602         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
       
   603         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
       
   604         QVERIFY(audioOutput.periodSize() > 0);
       
   605         stateSignal.clear();
       
   606 
       
   607         // Check that 'elapsed' increases
       
   608         QTest::qWait(40);
       
   609         QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
       
   610         QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()");
       
   611 
       
   612         qint64 written = 0;
       
   613         bool firstBuffer = true;
       
   614         char buffer[AUDIO_BUFFER];
       
   615 
       
   616         while (written < audioFiles.at(i)->size()-WavHeader::headerLength()) {
       
   617 
       
   618             if (audioOutput.bytesFree() > audioOutput.periodSize()) {
       
   619                 qint64 len = audioFiles.at(i)->read(buffer,audioOutput.periodSize());
       
   620                 written += feed->write(buffer, len);
       
   621 
       
   622                 if (firstBuffer) {
       
   623                     // Check for transition to ActiveState when data is provided
       
   624                     QVERIFY2((stateSignal.count() == 1),
       
   625                             QString("didn't emit signal after receiving data, got %1 signals instead")
       
   626                             .arg(stateSignal.count()).toLocal8Bit().constData());
       
   627                     QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
       
   628                     QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
       
   629                     firstBuffer = false;
       
   630                 }
       
   631             } else
       
   632                 QTest::qWait(20);
       
   633         }
       
   634         stateSignal.clear();
       
   635 
       
   636         // Wait until playback finishes
       
   637         QTest::qWait(3000); // 3 seconds should be plenty
       
   638 
       
   639         QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
       
   640         QVERIFY2((stateSignal.count() == 1),
       
   641             QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   642         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
       
   643         stateSignal.clear();
       
   644 
       
   645         qint64 processedUs = audioOutput.processedUSecs();
       
   646 
       
   647         audioOutput.stop();
       
   648         QTest::qWait(40);
       
   649         QVERIFY2((stateSignal.count() == 1),
       
   650             QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   651         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
       
   652 
       
   653         QVERIFY2((processedUs == 2000000),
       
   654                 QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
       
   655         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
       
   656         QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
       
   657         QVERIFY2((notifySignal.count() > 15 && notifySignal.count() < 25),
       
   658                 QString("too many notify() signals emitted (%1)").arg(notifySignal.count()).toLocal8Bit().constData());
       
   659 
       
   660         audioFiles.at(i)->close();
       
   661     }
       
   662 }
       
   663 
       
   664 void tst_QAudioOutput::pushSuspendResume()
       
   665 {
       
   666     for(int i=0; i<audioFiles.count(); i++) {
       
   667         QAudioOutput audioOutput(testFormats.at(i), this);
       
   668 
       
   669         audioOutput.setNotifyInterval(100);
       
   670 
       
   671         QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
       
   672         QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   673 
       
   674         // Check that we are in the default state before calling start
       
   675         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   676         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   677         QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
       
   678 
       
   679         audioFiles.at(i)->close();
       
   680         audioFiles.at(i)->open(QIODevice::ReadOnly);
       
   681         audioFiles.at(i)->seek(WavHeader::headerLength());
       
   682 
       
   683         QIODevice* feed = audioOutput.start();
       
   684 
       
   685         // Check that QAudioOutput immediately transitions to IdleState
       
   686         QVERIFY2((stateSignal.count() == 1),
       
   687                 QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   688         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
       
   689         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
       
   690         QVERIFY(audioOutput.periodSize() > 0);
       
   691         stateSignal.clear();
       
   692 
       
   693         // Check that 'elapsed' increases
       
   694         QTest::qWait(40);
       
   695         QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
       
   696         QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()");
       
   697 
       
   698         qint64 written = 0;
       
   699         bool firstBuffer = true;
       
   700         char buffer[AUDIO_BUFFER];
       
   701 
       
   702         // Play half of the clip
       
   703         while (written < (audioFiles.at(i)->size()-WavHeader::headerLength())/2) {
       
   704 
       
   705             if (audioOutput.bytesFree() > audioOutput.periodSize()) {
       
   706                 qint64 len = audioFiles.at(i)->read(buffer,audioOutput.periodSize());
       
   707                 written += feed->write(buffer, len);
       
   708 
       
   709                 if (firstBuffer) {
       
   710                     // Check for transition to ActiveState when data is provided
       
   711                     QVERIFY2((stateSignal.count() == 1),
       
   712                             QString("didn't emit signal after receiving data, got %1 signals instead")
       
   713                             .arg(stateSignal.count()).toLocal8Bit().constData());
       
   714                     QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
       
   715                     QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
       
   716                     firstBuffer = false;
       
   717                 }
       
   718             } else
       
   719                 QTest::qWait(20);
       
   720         }
       
   721         stateSignal.clear();
       
   722 
       
   723         audioOutput.suspend();
       
   724 
       
   725         // Give backends running in separate threads a chance to suspend.
       
   726         QTest::qWait(100);
       
   727 
       
   728         QVERIFY2((stateSignal.count() == 1),
       
   729                 QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead")
       
   730                 .arg(stateSignal.count()).toLocal8Bit().constData());
       
   731         QVERIFY2((audioOutput.state() == QAudio::SuspendedState), "didn't transition to SuspendedState after suspend()");
       
   732         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after suspend()");
       
   733         stateSignal.clear();
       
   734 
       
   735         // Check that only 'elapsed', and not 'processed' increases while suspended
       
   736         qint64 elapsedUs = audioOutput.elapsedUSecs();
       
   737         qint64 processedUs = audioOutput.processedUSecs();
       
   738         QTest::qWait(1000);
       
   739         QVERIFY(audioOutput.elapsedUSecs() > elapsedUs);
       
   740         QVERIFY(audioOutput.processedUSecs() == processedUs);
       
   741 
       
   742         audioOutput.resume();
       
   743 
       
   744         // Give backends running in separate threads a chance to suspend.
       
   745         QTest::qWait(100);
       
   746 
       
   747         // Check that QAudioOutput immediately transitions to ActiveState
       
   748         QVERIFY2((stateSignal.count() == 1),
       
   749                 QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   750         QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()");
       
   751         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
       
   752         stateSignal.clear();
       
   753 
       
   754         // Play rest of the clip
       
   755         while (!audioFiles.at(i)->atEnd()) {
       
   756             if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
       
   757                 qint64 len = audioFiles.at(i)->read(buffer,audioOutput.periodSize());
       
   758                 written += feed->write(buffer, len);
       
   759             } else
       
   760                 QTest::qWait(20);
       
   761         }
       
   762         stateSignal.clear();
       
   763 
       
   764         // Wait until playback finishes
       
   765         QTest::qWait(1000); // 1 seconds should be plenty
       
   766 
       
   767         QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
       
   768         QVERIFY2((stateSignal.count() == 1),
       
   769             QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   770         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
       
   771         stateSignal.clear();
       
   772 
       
   773         processedUs = audioOutput.processedUSecs();
       
   774 
       
   775         audioOutput.stop();
       
   776         QTest::qWait(40);
       
   777         QVERIFY2((stateSignal.count() == 1),
       
   778             QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   779         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
       
   780 
       
   781         QVERIFY2((processedUs == 2000000),
       
   782                 QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
       
   783         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
       
   784         QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
       
   785 
       
   786         audioFiles.at(i)->close();
       
   787     }
       
   788 }
       
   789 
       
   790 void tst_QAudioOutput::pushUnderrun()
       
   791 {
       
   792     for(int i=0; i<audioFiles.count(); i++) {
       
   793         QAudioOutput audioOutput(testFormats.at(i), this);
       
   794 
       
   795         audioOutput.setNotifyInterval(100);
       
   796 
       
   797         QSignalSpy notifySignal(&audioOutput, SIGNAL(notify()));
       
   798         QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State)));
       
   799 
       
   800         // Check that we are in the default state before calling start
       
   801         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()");
       
   802         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()");
       
   803         QVERIFY2((audioOutput.elapsedUSecs() == qint64(0)),"elapsedUSecs() not zero on creation");
       
   804 
       
   805         audioFiles.at(i)->close();
       
   806         audioFiles.at(i)->open(QIODevice::ReadOnly);
       
   807         audioFiles.at(i)->seek(WavHeader::headerLength());
       
   808 
       
   809         QIODevice* feed = audioOutput.start();
       
   810 
       
   811         // Check that QAudioOutput immediately transitions to IdleState
       
   812         QVERIFY2((stateSignal.count() == 1),
       
   813                 QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   814         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()");
       
   815         QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()");
       
   816         QVERIFY(audioOutput.periodSize() > 0);
       
   817         stateSignal.clear();
       
   818 
       
   819         // Check that 'elapsed' increases
       
   820         QTest::qWait(40);
       
   821         QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()");
       
   822         QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()");
       
   823 
       
   824         qint64 written = 0;
       
   825         bool firstBuffer = true;
       
   826         char buffer[AUDIO_BUFFER];
       
   827 
       
   828         // Play half of the clip
       
   829         while (written < (audioFiles.at(i)->size()-WavHeader::headerLength())/2) {
       
   830 
       
   831             if (audioOutput.bytesFree() > audioOutput.periodSize()) {
       
   832                 qint64 len = audioFiles.at(i)->read(buffer,audioOutput.periodSize());
       
   833                 written += feed->write(buffer, len);
       
   834 
       
   835                 if (firstBuffer) {
       
   836                     // Check for transition to ActiveState when data is provided
       
   837                     QVERIFY2((stateSignal.count() == 1),
       
   838                             QString("didn't emit signal after receiving data, got %1 signals instead")
       
   839                             .arg(stateSignal.count()).toLocal8Bit().constData());
       
   840                     QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
       
   841                     QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
       
   842                     firstBuffer = false;
       
   843                 }
       
   844             } else
       
   845                 QTest::qWait(20);
       
   846         }
       
   847         stateSignal.clear();
       
   848 
       
   849         // Wait for data to be played
       
   850         QTest::qWait(1000);
       
   851 
       
   852         QVERIFY2((stateSignal.count() == 1),
       
   853                 QString("didn't emit IdleState signal after suspend(), got %1 signals instead")
       
   854                 .arg(stateSignal.count()).toLocal8Bit().constData());
       
   855         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState, no data");
       
   856         QVERIFY2((audioOutput.error() == QAudio::UnderrunError), "error state is not equal to QAudio::UnderrunError, no data");
       
   857         stateSignal.clear();
       
   858 
       
   859         firstBuffer = true;
       
   860         // Play rest of the clip
       
   861         while (!audioFiles.at(i)->atEnd()) {
       
   862             if (audioOutput.bytesFree() >= audioOutput.periodSize()) {
       
   863                 qint64 len = audioFiles.at(i)->read(buffer,audioOutput.periodSize());
       
   864                 written += feed->write(buffer, len);
       
   865                 if (firstBuffer) {
       
   866                     // Check for transition to ActiveState when data is provided
       
   867                     QVERIFY2((stateSignal.count() == 1),
       
   868                             QString("didn't emit signal after receiving data, got %1 signals instead")
       
   869                             .arg(stateSignal.count()).toLocal8Bit().constData());
       
   870                     QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data");
       
   871                     QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data");
       
   872                     firstBuffer = false;
       
   873                 }
       
   874             } else
       
   875                 QTest::qWait(20);
       
   876         }
       
   877         stateSignal.clear();
       
   878 
       
   879         // Wait until playback finishes
       
   880         QTest::qWait(1000); // 1 seconds should be plenty
       
   881 
       
   882         QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF");
       
   883         QVERIFY2((stateSignal.count() == 1),
       
   884             QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   885         QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF");
       
   886         stateSignal.clear();
       
   887 
       
   888         qint64 processedUs = audioOutput.processedUSecs();
       
   889 
       
   890         audioOutput.stop();
       
   891         QTest::qWait(40);
       
   892         QVERIFY2((stateSignal.count() == 1),
       
   893             QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData());
       
   894         QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()");
       
   895 
       
   896         QVERIFY2((processedUs == 2000000),
       
   897                 QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData());
       
   898         QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()");
       
   899         QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState");
       
   900 
       
   901         audioFiles.at(i)->close();
       
   902     }
       
   903 }
       
   904 
       
   905 void tst_QAudioOutput::cleanupTestCase()
       
   906 {
       
   907     QFile* file;
       
   908 
       
   909     foreach (file, audioFiles) {
       
   910         file->remove();
       
   911         delete file;
       
   912     }
       
   913 }
       
   914 
       
   915 QTEST_MAIN(tst_QAudioOutput)
       
   916 
       
   917 #include "tst_qaudiooutput.moc"