From 2a34e88c1e1ced28e75c487cd13402e1c9cf9fa3 Mon Sep 17 00:00:00 2001 From: Michael Goddard Date: Wed, 29 Jun 2011 13:38:46 +1000 Subject: Initial copy of QtMultimediaKit. Comes from original repo, with SHA1: 2c82d5611655e5967f5c5095af50c0991c4378b2 --- tests/auto/auto.pro | 11 + tests/auto/multimedia.pro | 41 + .../qabstractvideobuffer/qabstractvideobuffer.pro | 9 + .../tst_qabstractvideobuffer.cpp | 134 ++ .../qabstractvideosurface.pro | 9 + .../tst_qabstractvideosurface.cpp | 312 +++ .../qaudiocapturesource/qaudiocapturesource.pro | 9 + .../tst_qaudiocapturesource.cpp | 360 ++++ tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro | 9 + .../auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp | 207 ++ tests/auto/qaudioformat/qaudioformat.pro | 9 + tests/auto/qaudioformat/tst_qaudioformat.cpp | 184 ++ tests/auto/qaudioinput/qaudioinput.pro | 18 + tests/auto/qaudioinput/tst_qaudioinput.cpp | 814 ++++++++ tests/auto/qaudioinput/wavheader.cpp | 205 ++ tests/auto/qaudioinput/wavheader.h | 80 + tests/auto/qaudiooutput/qaudiooutput.pro | 18 + tests/auto/qaudiooutput/tst_qaudiooutput.cpp | 962 ++++++++++ tests/auto/qaudiooutput/wavheader.cpp | 205 ++ tests/auto/qaudiooutput/wavheader.h | 80 + tests/auto/qcamera/qcamera.pro | 15 + tests/auto/qcamera/tst_qcamera.cpp | 2012 ++++++++++++++++++++ tests/auto/qcamerabackend/qcamerabackend.pro | 15 + tests/auto/qcamerabackend/tst_qcamerabackend.cpp | 633 ++++++ tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro | 18 + .../qdeclarativeaudio/tst_qdeclarativeaudio.cpp | 1302 +++++++++++++ tests/auto/qdeclarativevideo/qdeclarativevideo.pro | 18 + .../qdeclarativevideo/tst_qdeclarativevideo.cpp | 992 ++++++++++ .../auto/qgraphicsvideoitem/qgraphicsvideoitem.pro | 12 + .../qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp | 675 +++++++ tests/auto/qmediacontent/qmediacontent.pro | 7 + tests/auto/qmediacontent/tst_qmediacontent.cpp | 176 ++ tests/auto/qmediaimageviewer/images.qrc | 9 + tests/auto/qmediaimageviewer/images/coverart.png | Bin 0 -> 230 bytes tests/auto/qmediaimageviewer/images/image.jpg | Bin 0 -> 2045 bytes tests/auto/qmediaimageviewer/images/image.png | Bin 0 -> 230 bytes tests/auto/qmediaimageviewer/images/invalid.png | 2 + tests/auto/qmediaimageviewer/images/poster.png | Bin 0 -> 230 bytes tests/auto/qmediaimageviewer/qmediaimageviewer.pro | 17 + .../qmediaimageviewer/tst_qmediaimageviewer.cpp | 1036 ++++++++++ tests/auto/qmediaobject/main.cpp | 77 + tests/auto/qmediaobject/qmediaobject.pro | 27 + tests/auto/qmediaobject/tst_qmediaobject.cpp | 359 ++++ tests/auto/qmediaobject/tst_qmediaobject.h | 177 ++ tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp | 278 +++ tests/auto/qmediaobject/tst_qmediaobject_mmf.h | 81 + tests/auto/qmediaobject/tst_qmediaobject_xa.cpp | 158 ++ tests/auto/qmediaobject/tst_qmediaobject_xa.h | 83 + tests/auto/qmediaplayer/main.cpp | 78 + tests/auto/qmediaplayer/qmediaplayer.pro | 25 + tests/auto/qmediaplayer/tst_qmediaplayer.cpp | 1019 ++++++++++ tests/auto/qmediaplayer/tst_qmediaplayer.h | 435 +++++ tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp | 1708 +++++++++++++++++ tests/auto/qmediaplayer/tst_qmediaplayer_s60.h | 137 ++ tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp | 1413 ++++++++++++++ tests/auto/qmediaplayer/tst_qmediaplayer_xa.h | 194 ++ .../qmediaplayerbackend/qmediaplayerbackend.pro | 23 + tests/auto/qmediaplayerbackend/testdata/test.wav | Bin 0 -> 88232 bytes .../tst_qmediaplayerbackend.cpp | 462 +++++ tests/auto/qmediaplaylist/qmediaplaylist.pro | 29 + tests/auto/qmediaplaylist/testdata/test.m3u | 11 + tests/auto/qmediaplaylist/testdata/testfile | 0 .../auto/qmediaplaylist/testdata/testfile2#suffix | 0 tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp | 666 +++++++ .../qmediaplaylistnavigator.pro | 9 + .../tst_qmediaplaylistnavigator.cpp | 318 ++++ .../auto/qmediapluginloader/qmediapluginloader.pro | 15 + .../qmediapluginloader/tst_qmediapluginloader.cpp | 123 ++ tests/auto/qmediarecorder/main.cpp | 80 + tests/auto/qmediarecorder/qmediarecorder.pro | 18 + tests/auto/qmediarecorder/s60common.h | 61 + tests/auto/qmediarecorder/tst_qmediarecorder.cpp | 796 ++++++++ tests/auto/qmediarecorder/tst_qmediarecorder.h | 516 +++++ .../auto/qmediarecorder/tst_qmediarecorder_mmf.cpp | 180 ++ tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h | 85 + .../auto/qmediarecorder/tst_qmediarecorder_xa.cpp | 323 ++++ tests/auto/qmediarecorder/tst_qmediarecorder_xa.h | 78 + tests/auto/qmediaresource/qmediaresource.pro | 9 + tests/auto/qmediaresource/tst_qmediaresource.cpp | 528 +++++ tests/auto/qmediaservice/qmediaservice.pro | 9 + tests/auto/qmediaservice/tst_qmediaservice.cpp | 196 ++ .../qmediaserviceprovider.pro | 9 + .../tst_qmediaserviceprovider.cpp | 489 +++++ tests/auto/qmediatimerange/qmediatimerange.pro | 9 + tests/auto/qmediatimerange/tst_qmediatimerange.cpp | 739 +++++++ .../qpaintervideosurface/qpaintervideosurface.pro | 11 + .../tst_qpaintervideosurface.cpp | 1249 ++++++++++++ tests/auto/qradiotuner/main.cpp | 79 + tests/auto/qradiotuner/qradiotuner.pro | 19 + tests/auto/qradiotuner/tst_qradiotuner.cpp | 275 +++ tests/auto/qradiotuner/tst_qradiotuner.h | 285 +++ tests/auto/qradiotuner/tst_qradiotuner_s60.cpp | 170 ++ tests/auto/qradiotuner/tst_qradiotuner_s60.h | 79 + tests/auto/qradiotuner/tst_qradiotuner_xa.cpp | 224 +++ tests/auto/qradiotuner/tst_qradiotuner_xa.h | 81 + tests/auto/qvideoframe/qvideoframe.pro | 9 + tests/auto/qvideoframe/tst_qvideoframe.cpp | 793 ++++++++ .../qvideosurfaceformat/qvideosurfaceformat.pro | 9 + .../tst_qvideosurfaceformat.cpp | 738 +++++++ tests/auto/qvideowidget/qvideowidget.pro | 10 + tests/auto/qvideowidget/tst_qvideowidget.cpp | 1567 +++++++++++++++ tests/tests.pro | 5 + 102 files changed, 28248 insertions(+) create mode 100644 tests/auto/auto.pro create mode 100644 tests/auto/multimedia.pro create mode 100644 tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro create mode 100644 tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp create mode 100644 tests/auto/qabstractvideosurface/qabstractvideosurface.pro create mode 100644 tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp create mode 100644 tests/auto/qaudiocapturesource/qaudiocapturesource.pro create mode 100644 tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp create mode 100644 tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro create mode 100644 tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp create mode 100644 tests/auto/qaudioformat/qaudioformat.pro create mode 100644 tests/auto/qaudioformat/tst_qaudioformat.cpp create mode 100644 tests/auto/qaudioinput/qaudioinput.pro create mode 100755 tests/auto/qaudioinput/tst_qaudioinput.cpp create mode 100755 tests/auto/qaudioinput/wavheader.cpp create mode 100755 tests/auto/qaudioinput/wavheader.h create mode 100644 tests/auto/qaudiooutput/qaudiooutput.pro create mode 100755 tests/auto/qaudiooutput/tst_qaudiooutput.cpp create mode 100755 tests/auto/qaudiooutput/wavheader.cpp create mode 100755 tests/auto/qaudiooutput/wavheader.h create mode 100644 tests/auto/qcamera/qcamera.pro create mode 100644 tests/auto/qcamera/tst_qcamera.cpp create mode 100644 tests/auto/qcamerabackend/qcamerabackend.pro create mode 100644 tests/auto/qcamerabackend/tst_qcamerabackend.cpp create mode 100644 tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro create mode 100644 tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp create mode 100644 tests/auto/qdeclarativevideo/qdeclarativevideo.pro create mode 100644 tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp create mode 100644 tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro create mode 100644 tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp create mode 100644 tests/auto/qmediacontent/qmediacontent.pro create mode 100644 tests/auto/qmediacontent/tst_qmediacontent.cpp create mode 100644 tests/auto/qmediaimageviewer/images.qrc create mode 100644 tests/auto/qmediaimageviewer/images/coverart.png create mode 100644 tests/auto/qmediaimageviewer/images/image.jpg create mode 100644 tests/auto/qmediaimageviewer/images/image.png create mode 100644 tests/auto/qmediaimageviewer/images/invalid.png create mode 100644 tests/auto/qmediaimageviewer/images/poster.png create mode 100644 tests/auto/qmediaimageviewer/qmediaimageviewer.pro create mode 100644 tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp create mode 100644 tests/auto/qmediaobject/main.cpp create mode 100644 tests/auto/qmediaobject/qmediaobject.pro create mode 100644 tests/auto/qmediaobject/tst_qmediaobject.cpp create mode 100644 tests/auto/qmediaobject/tst_qmediaobject.h create mode 100644 tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp create mode 100644 tests/auto/qmediaobject/tst_qmediaobject_mmf.h create mode 100644 tests/auto/qmediaobject/tst_qmediaobject_xa.cpp create mode 100644 tests/auto/qmediaobject/tst_qmediaobject_xa.h create mode 100755 tests/auto/qmediaplayer/main.cpp create mode 100644 tests/auto/qmediaplayer/qmediaplayer.pro create mode 100644 tests/auto/qmediaplayer/tst_qmediaplayer.cpp create mode 100755 tests/auto/qmediaplayer/tst_qmediaplayer.h create mode 100755 tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp create mode 100755 tests/auto/qmediaplayer/tst_qmediaplayer_s60.h create mode 100644 tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp create mode 100644 tests/auto/qmediaplayer/tst_qmediaplayer_xa.h create mode 100644 tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro create mode 100644 tests/auto/qmediaplayerbackend/testdata/test.wav create mode 100644 tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp create mode 100644 tests/auto/qmediaplaylist/qmediaplaylist.pro create mode 100644 tests/auto/qmediaplaylist/testdata/test.m3u create mode 100644 tests/auto/qmediaplaylist/testdata/testfile create mode 100644 tests/auto/qmediaplaylist/testdata/testfile2#suffix create mode 100644 tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp create mode 100644 tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro create mode 100644 tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp create mode 100644 tests/auto/qmediapluginloader/qmediapluginloader.pro create mode 100644 tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp create mode 100755 tests/auto/qmediarecorder/main.cpp create mode 100644 tests/auto/qmediarecorder/qmediarecorder.pro create mode 100755 tests/auto/qmediarecorder/s60common.h create mode 100644 tests/auto/qmediarecorder/tst_qmediarecorder.cpp create mode 100755 tests/auto/qmediarecorder/tst_qmediarecorder.h create mode 100755 tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp create mode 100755 tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h create mode 100755 tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp create mode 100755 tests/auto/qmediarecorder/tst_qmediarecorder_xa.h create mode 100644 tests/auto/qmediaresource/qmediaresource.pro create mode 100644 tests/auto/qmediaresource/tst_qmediaresource.cpp create mode 100644 tests/auto/qmediaservice/qmediaservice.pro create mode 100644 tests/auto/qmediaservice/tst_qmediaservice.cpp create mode 100644 tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro create mode 100644 tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp create mode 100644 tests/auto/qmediatimerange/qmediatimerange.pro create mode 100644 tests/auto/qmediatimerange/tst_qmediatimerange.cpp create mode 100644 tests/auto/qpaintervideosurface/qpaintervideosurface.pro create mode 100644 tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp create mode 100755 tests/auto/qradiotuner/main.cpp create mode 100644 tests/auto/qradiotuner/qradiotuner.pro create mode 100644 tests/auto/qradiotuner/tst_qradiotuner.cpp create mode 100644 tests/auto/qradiotuner/tst_qradiotuner.h create mode 100644 tests/auto/qradiotuner/tst_qradiotuner_s60.cpp create mode 100644 tests/auto/qradiotuner/tst_qradiotuner_s60.h create mode 100644 tests/auto/qradiotuner/tst_qradiotuner_xa.cpp create mode 100644 tests/auto/qradiotuner/tst_qradiotuner_xa.h create mode 100644 tests/auto/qvideoframe/qvideoframe.pro create mode 100644 tests/auto/qvideoframe/tst_qvideoframe.cpp create mode 100644 tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro create mode 100644 tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp create mode 100644 tests/auto/qvideowidget/qvideowidget.pro create mode 100644 tests/auto/qvideowidget/tst_qvideowidget.cpp create mode 100644 tests/tests.pro (limited to 'tests') diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro new file mode 100644 index 000000000..b3a5771a2 --- /dev/null +++ b/tests/auto/auto.pro @@ -0,0 +1,11 @@ +TEMPLATE = subdirs + +SUBDIRS+=multimedia.pro + +# These autotests consist of things such as static code checks +# which require that the autotest is run on the same machine +# doing the build - i.e. cross-compilation is not allowed. +win32|mac|linux-g++* { + # NOTE: Disabled until we have established which tests fall into this category + # !contains(QT_CONFIG,embedded):!maemo5:!maemo6:SUBDIRS+=host.pro +} diff --git a/tests/auto/multimedia.pro b/tests/auto/multimedia.pro new file mode 100644 index 000000000..cb6094388 --- /dev/null +++ b/tests/auto/multimedia.pro @@ -0,0 +1,41 @@ +# How do we require a module? +# requires(contains(mobility_modules,multimedia)) + +TEMPLATE = subdirs +SUBDIRS += \ + qabstractvideobuffer \ + qabstractvideosurface \ + qaudiocapturesource \ + qgraphicsvideoitem \ + qmediaimageviewer \ + qmediaobject \ + qmediaplayer \ + qmediaplayerbackend \ + qmediaplaylist \ + qmediaplaylistnavigator \ + qmediapluginloader \ + qmediarecorder \ + qmediaresource \ + qmediaservice \ + qmediaserviceprovider \ + qmediacontent \ + qradiotuner \ + qcamera \ + qpaintervideosurface \ + qvideowidget \ + qmediatimerange \ + qaudiodeviceinfo \ + qaudiooutput \ + qaudioinput \ + qaudioformat \ + qvideoframe \ + qvideosurfaceformat \ + qcamerabackend + +contains (QT_CONFIG, declarative) { + SUBDIRS += \ +# qsoundeffect \ + qdeclarativeaudio \ + qdeclarativevideo +} + diff --git a/tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro b/tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro new file mode 100644 index 000000000..e1fa50355 --- /dev/null +++ b/tests/auto/qabstractvideobuffer/qabstractvideobuffer.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qabstractvideobuffer +#CONFIG += testcase + +SOURCES += tst_qabstractvideobuffer.cpp + diff --git a/tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp b/tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp new file mode 100644 index 000000000..7e339eefb --- /dev/null +++ b/tests/auto/qabstractvideobuffer/tst_qabstractvideobuffer.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include + +#include + +class tst_QAbstractVideoBuffer : public QObject +{ + Q_OBJECT +public: + tst_QAbstractVideoBuffer(); + ~tst_QAbstractVideoBuffer(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void handleType_data(); + void handleType(); + void handle(); +}; + +class QtTestVideoBuffer : public QAbstractVideoBuffer +{ +public: + QtTestVideoBuffer(QAbstractVideoBuffer::HandleType type) : QAbstractVideoBuffer(type) {} + + MapMode mapMode() const { return NotMapped; } + + uchar *map(MapMode, int *, int *) { return 0; } + void unmap() {} +}; + +tst_QAbstractVideoBuffer::tst_QAbstractVideoBuffer() +{ +} + +tst_QAbstractVideoBuffer::~tst_QAbstractVideoBuffer() +{ +} + +void tst_QAbstractVideoBuffer::initTestCase() +{ +} + +void tst_QAbstractVideoBuffer::cleanupTestCase() +{ +} + +void tst_QAbstractVideoBuffer::init() +{ +} + +void tst_QAbstractVideoBuffer::cleanup() +{ +} + +void tst_QAbstractVideoBuffer::handleType_data() +{ + QTest::addColumn("type"); + + QTest::newRow("none") + << QAbstractVideoBuffer::NoHandle; + QTest::newRow("opengl") + << QAbstractVideoBuffer::GLTextureHandle; + QTest::newRow("user1") + << QAbstractVideoBuffer::UserHandle; + QTest::newRow("user2") + << QAbstractVideoBuffer::HandleType(QAbstractVideoBuffer::UserHandle + 1); +} + +void tst_QAbstractVideoBuffer::handleType() +{ + QFETCH(QAbstractVideoBuffer::HandleType, type); + + QtTestVideoBuffer buffer(type); + + QCOMPARE(buffer.handleType(), type); +} + +void tst_QAbstractVideoBuffer::handle() +{ + QtTestVideoBuffer buffer(QAbstractVideoBuffer::NoHandle); + + QVERIFY(buffer.handle().isNull()); +} + +QTEST_MAIN(tst_QAbstractVideoBuffer) + +#include "tst_qabstractvideobuffer.moc" diff --git a/tests/auto/qabstractvideosurface/qabstractvideosurface.pro b/tests/auto/qabstractvideosurface/qabstractvideosurface.pro new file mode 100644 index 000000000..1778b566b --- /dev/null +++ b/tests/auto/qabstractvideosurface/qabstractvideosurface.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qabstractvideosurface +#CONFIG += testcase + +SOURCES += tst_qabstractvideosurface.cpp + diff --git a/tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp b/tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp new file mode 100644 index 000000000..bef9c7f38 --- /dev/null +++ b/tests/auto/qabstractvideosurface/tst_qabstractvideosurface.cpp @@ -0,0 +1,312 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include + +#include +#include + +class tst_QAbstractVideoSurface : public QObject +{ + Q_OBJECT +public: + tst_QAbstractVideoSurface(); + ~tst_QAbstractVideoSurface(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void setError(); + void isFormatSupported_data(); + void isFormatSupported(); + void nearestFormat_data(); + void nearestFormat(); + void start_data(); + void start(); +}; + +typedef QMap SupportedFormatMap; + +Q_DECLARE_METATYPE(SupportedFormatMap) +Q_DECLARE_METATYPE(QVideoSurfaceFormat) +Q_DECLARE_METATYPE(QAbstractVideoSurface::Error); + +class QtTestVideoSurface : public QAbstractVideoSurface +{ + Q_OBJECT +public: + explicit QtTestVideoSurface(QObject *parent = 0) : QAbstractVideoSurface(parent) {} + explicit QtTestVideoSurface(SupportedFormatMap formats, QObject *parent = 0) + : QAbstractVideoSurface(parent), supportedFormats(formats) {} + + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const + { + return supportedFormats.values(handleType); + } + + bool present(const QVideoFrame &) { return false; } + + using QAbstractVideoSurface::setError; + +private: + SupportedFormatMap supportedFormats; +}; + +tst_QAbstractVideoSurface::tst_QAbstractVideoSurface() +{ +} + +tst_QAbstractVideoSurface::~tst_QAbstractVideoSurface() +{ +} + +void tst_QAbstractVideoSurface::initTestCase() +{ +} + +void tst_QAbstractVideoSurface::cleanupTestCase() +{ +} + +void tst_QAbstractVideoSurface::init() +{ +} + +void tst_QAbstractVideoSurface::cleanup() +{ +} + +void tst_QAbstractVideoSurface::setError() +{ + qRegisterMetaType(); + + QtTestVideoSurface surface; + + QCOMPARE(surface.error(), QAbstractVideoSurface::NoError); + + surface.setError(QAbstractVideoSurface::StoppedError); + QCOMPARE(surface.error(), QAbstractVideoSurface::StoppedError); + + surface.setError(QAbstractVideoSurface::ResourceError); + QCOMPARE(surface.error(), QAbstractVideoSurface::ResourceError); + + surface.setError(QAbstractVideoSurface::NoError); + QCOMPARE(surface.error(), QAbstractVideoSurface::NoError); +} + +void tst_QAbstractVideoSurface::isFormatSupported_data() +{ + QTest::addColumn("supportedFormats"); + QTest::addColumn("format"); + QTest::addColumn("supported"); + + SupportedFormatMap formats; + + QTest::newRow("no formats: rgb32") + << formats + << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_RGB32) + << false; + QTest::newRow("no formats: yv12") + << formats + << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_YV12) + << false; + QTest::newRow("no formats: rgb32 gl") + << formats + << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB32, + QAbstractVideoBuffer::GLTextureHandle) + << false; + QTest::newRow("no formats: rgb24 gl") + << formats + << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB24, + QAbstractVideoBuffer::GLTextureHandle) + << false; + + formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_RGB32); + formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_RGB24); + formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_YUV444); + formats.insertMulti(QAbstractVideoBuffer::GLTextureHandle, QVideoFrame::Format_RGB32); + + QTest::newRow("supported: rgb32") + << formats + << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_RGB32) + << true; + QTest::newRow("supported: rgb24") + << formats + << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_RGB24) + << true; + QTest::newRow("unsupported: yv12") + << formats + << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_YV12) + << false; + QTest::newRow("supported: rgb32 gl") + << formats + << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB32, + QAbstractVideoBuffer::GLTextureHandle) + << true; + QTest::newRow("unsupported: rgb24 gl") + << formats + << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB24, + QAbstractVideoBuffer::GLTextureHandle) + << false; + QTest::newRow("unsupported: yv12 gl") + << formats + << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_YV12, + QAbstractVideoBuffer::GLTextureHandle) + << false; + + formats.insertMulti(QAbstractVideoBuffer::NoHandle, QVideoFrame::Format_YV12); + formats.insertMulti(QAbstractVideoBuffer::GLTextureHandle, QVideoFrame::Format_RGB24); + + QTest::newRow("supported: yv12") + << formats + << QVideoSurfaceFormat(QSize(800, 600), QVideoFrame::Format_YV12) + << true; + QTest::newRow("supported: rgb24 gl") + << formats + << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB24, + QAbstractVideoBuffer::GLTextureHandle) + << true; +} + +void tst_QAbstractVideoSurface::isFormatSupported() +{ + QFETCH(SupportedFormatMap, supportedFormats); + QFETCH(QVideoSurfaceFormat, format); + QFETCH(bool, supported); + + QtTestVideoSurface surface(supportedFormats); + + QCOMPARE(surface.isFormatSupported(format), supported); +} + +void tst_QAbstractVideoSurface::nearestFormat_data() +{ + isFormatSupported_data(); +} + +void tst_QAbstractVideoSurface::nearestFormat() +{ + QFETCH(SupportedFormatMap, supportedFormats); + QFETCH(QVideoSurfaceFormat, format); + QFETCH(bool, supported); + + QtTestVideoSurface surface(supportedFormats); + + QCOMPARE(surface.nearestFormat(format) == format, supported); +} + +void tst_QAbstractVideoSurface::start_data() +{ + QTest::addColumn("format"); + + QTest::newRow("rgb32") << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB32); + QTest::newRow("yv12") << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_YV12); + QTest::newRow("rgb32 gl") << QVideoSurfaceFormat( + QSize(800, 600), + QVideoFrame::Format_RGB32, + QAbstractVideoBuffer::GLTextureHandle); +} + +void tst_QAbstractVideoSurface::start() +{ + QFETCH(QVideoSurfaceFormat, format); + + QtTestVideoSurface surface; + surface.setError(QAbstractVideoSurface::ResourceError); + + QSignalSpy formatSpy(&surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat))); + QSignalSpy activeSpy(&surface, SIGNAL(activeChanged(bool))); + + QVERIFY(!surface.isActive()); + QCOMPARE(surface.surfaceFormat(), QVideoSurfaceFormat()); + + QVERIFY(surface.start(format)); + + QVERIFY(surface.isActive()); + QCOMPARE(surface.surfaceFormat(), format); + + QCOMPARE(formatSpy.count(), 1); + QCOMPARE(qvariant_cast(formatSpy.last().at(0)), format); + + QCOMPARE(activeSpy.count(), 1); + QCOMPARE(activeSpy.last().at(0).toBool(), true); + + // error() is reset on a successful start. + QCOMPARE(surface.error(), QAbstractVideoSurface::NoError); + + surface.stop(); + + QVERIFY(!surface.isActive()); + QCOMPARE(surface.surfaceFormat(), QVideoSurfaceFormat()); + + QCOMPARE(formatSpy.count(), 2); + QCOMPARE(qvariant_cast(formatSpy.last().at(0)), QVideoSurfaceFormat()); + + QCOMPARE(activeSpy.count(), 2); + QCOMPARE(activeSpy.last().at(0).toBool(), false); +} + +QTEST_MAIN(tst_QAbstractVideoSurface) + +#include "tst_qabstractvideosurface.moc" diff --git a/tests/auto/qaudiocapturesource/qaudiocapturesource.pro b/tests/auto/qaudiocapturesource/qaudiocapturesource.pro new file mode 100644 index 000000000..df9c70eaf --- /dev/null +++ b/tests/auto/qaudiocapturesource/qaudiocapturesource.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qaudiocapturesource +# CONFIG += testcase + +SOURCES += tst_qaudiocapturesource.cpp + diff --git a/tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp b/tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp new file mode 100644 index 000000000..c8d9d3d7d --- /dev/null +++ b/tests/auto/qaudiocapturesource/tst_qaudiocapturesource.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include +#include + +#include + +#include +#include +#include +#include + +//TESTED_COMPONENT=src/multimedia + +QT_USE_NAMESPACE +class MockAudioEncoderControl : public QAudioEncoderControl +{ + Q_OBJECT +public: + MockAudioEncoderControl(QObject *parent = 0): + QAudioEncoderControl(parent) + { + m_codecs << "audio/pcm" << "audio/mpeg"; + m_descriptions << "Pulse Code Modulation" << "mp3 format"; + m_audioSettings.setCodec("audio/pcm"); + m_audioSettings.setSampleRate(8000); + m_freqs << 8000 << 11025 << 22050 << 44100; + } + + ~MockAudioEncoderControl() {} + + QStringList supportedAudioCodecs() const { return m_codecs; } + QString codecDescription(const QString &codecName) const { return m_descriptions.at(m_codecs.indexOf(codecName)); } + + QStringList supportedEncodingOptions(const QString &) const { return QStringList() << "bitrate"; } + QVariant encodingOption(const QString &, const QString &) const { return m_optionValue; } + void setEncodingOption(const QString &, const QString &, const QVariant &value) { m_optionValue = value; } + + QList supportedSampleRates(const QAudioEncoderSettings & = QAudioEncoderSettings(), + bool *continuous = 0) const + { + if (continuous) + *continuous = false; + return m_freqs; + } + QList supportedChannelCounts(const QAudioEncoderSettings & = QAudioEncoderSettings()) const { QList list; list << 1 << 2; return list; } + + QAudioEncoderSettings audioSettings() const { return m_audioSettings; } + void setAudioSettings(const QAudioEncoderSettings &settings) { m_audioSettings = settings;} + + QStringList m_codecs; + QStringList m_descriptions; + + QAudioEncoderSettings m_audioSettings; + + QList m_freqs; + QVariant m_optionValue; +}; + +class MockMediaRecorderControl : public QMediaRecorderControl +{ + Q_OBJECT +public: + MockMediaRecorderControl(QObject *parent = 0): + QMediaRecorderControl(parent), + m_state(QMediaRecorder::StoppedState), + m_position(0), + m_muted(false) {} + + ~MockMediaRecorderControl() {} + + QUrl outputLocation() const { return m_sink; } + bool setOutputLocation(const QUrl &sink) { m_sink = sink; return true; } + QMediaRecorder::State state() const { return m_state; } + qint64 duration() const { return m_position; } + void applySettings() {} + bool isMuted() const { return m_muted; } + +public slots: + void record() + { + m_state = QMediaRecorder::RecordingState; + m_position=1; + emit stateChanged(m_state); + emit durationChanged(m_position); + } + void pause() + { + m_state = QMediaRecorder::PausedState; + emit stateChanged(m_state); + } + + void stop() + { + m_position=0; + m_state = QMediaRecorder::StoppedState; + emit stateChanged(m_state); + } + + void setMuted(bool muted) + { + if (m_muted != muted) + emit mutedChanged(m_muted = muted); + } + +public: + QUrl m_sink; + QMediaRecorder::State m_state; + qint64 m_position; + bool m_muted; +}; + +class MockAudioEndpointSelector : public QAudioEndpointSelector +{ + Q_OBJECT +public: + MockAudioEndpointSelector(QObject *parent): + QAudioEndpointSelector(parent) + { + m_names << "device1" << "device2" << "device3"; + m_descriptions << "dev1 comment" << "dev2 comment" << "dev3 comment"; + m_audioInput = "device1"; + emit availableEndpointsChanged(); + } + ~MockAudioEndpointSelector() {}; + + QList availableEndpoints() const + { + return m_names; + } + + QString endpointDescription(const QString& name) const + { + QString desc; + + for(int i = 0; i < m_names.count(); i++) { + if (m_names.at(i).compare(name) == 0) { + desc = m_descriptions.at(i); + break; + } + } + return desc; + } + + QString defaultEndpoint() const + { + return m_names.at(0); + } + + QString activeEndpoint() const + { + return m_audioInput; + } + +public Q_SLOTS: + void setActiveEndpoint(const QString& name) + { + m_audioInput = name; + emit activeEndpointChanged(name); + } + +private: + QString m_audioInput; + QList m_names; + QList m_descriptions; +}; + + +class MockAudioSourceService : public QMediaService +{ + Q_OBJECT + +public: + MockAudioSourceService(): QMediaService(0), hasAudioDeviceControl(true) + { + mockAudioEncoderControl = new MockAudioEncoderControl(this); + mockMediaRecorderControl = new MockMediaRecorderControl(this); + mockAudioEndpointSelector = new MockAudioEndpointSelector(this); + } + + ~MockAudioSourceService() + { + delete mockAudioEncoderControl; + delete mockMediaRecorderControl; + delete mockAudioEndpointSelector; + } + + QMediaControl* requestControl(const char *iid) + { + if (qstrcmp(iid, QAudioEncoderControl_iid) == 0) + return mockAudioEncoderControl; + + if (qstrcmp(iid, QMediaRecorderControl_iid) == 0) + return mockMediaRecorderControl; + + if (hasAudioDeviceControl && qstrcmp(iid, QAudioEndpointSelector_iid) == 0) + return mockAudioEndpointSelector; + + return 0; + } + + void releaseControl(QMediaControl*) {} + + MockAudioEncoderControl *mockAudioEncoderControl; + MockMediaRecorderControl *mockMediaRecorderControl; + MockAudioEndpointSelector *mockAudioEndpointSelector; + bool hasAudioDeviceControl; +}; + +class MockProvider : public QMediaServiceProvider +{ +public: + MockProvider(MockAudioSourceService *service):mockService(service) {} + QMediaService *requestService(const QByteArray&, const QMediaServiceProviderHint &) + { + return mockService; + } + + void releaseService(QMediaService *) {} + + MockAudioSourceService *mockService; +}; + + +class tst_QAudioCaptureSource: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + //void testNullService(); + //void testNullControl(); + void testAudioSource(); + void testOptions(); + void testDevices(); + +private: + QAudioCaptureSource *audiosource; + MockAudioSourceService *mockAudioSourceService; + MockProvider *mockProvider; +}; + +void tst_QAudioCaptureSource::initTestCase() +{ + mockAudioSourceService = new MockAudioSourceService; + mockProvider = new MockProvider(mockAudioSourceService); +} + +void tst_QAudioCaptureSource::cleanupTestCase() +{ + delete audiosource; + delete mockProvider; +} +/* +void tst_QAudioCaptureSource::testNullService() +{ + MockProvider provider(0); + QAudioCaptureSource source(0, &provider); + + QCOMPARE(source.audioInputs().size(), 0); + QCOMPARE(source.defaultAudioInput(), QString()); + QCOMPARE(source.activeAudioInput(), QString()); +} +*/ +/* +void tst_QAudioCaptureSource::testNullControl() +{ + MockAudioSourceService service; + service.hasAudioDeviceControl = false; + MockProvider provider(&service); + QAudioCaptureSource source(0, &provider); + + QCOMPARE(source.audioInputs().size(), 0); + QCOMPARE(source.defaultAudioInput(), QString()); + QCOMPARE(source.activeAudioInput(), QString()); + + QCOMPARE(source.audioDescription("blah"), QString()); + + QSignalSpy deviceNameSpy(&source, SIGNAL(activeAudioInputChanged(QString))); + + source.setAudioInput("blah"); + QCOMPARE(deviceNameSpy.count(), 0); +} +*/ +void tst_QAudioCaptureSource::testAudioSource() +{ + audiosource = new QAudioCaptureSource(0, mockProvider); + + QCOMPARE(audiosource->service(),(QMediaService *) mockAudioSourceService); +} + +void tst_QAudioCaptureSource::testOptions() +{ + const QString codec(QLatin1String("mp3")); + + QStringList options = mockAudioSourceService->mockAudioEncoderControl->supportedEncodingOptions(codec); + QVERIFY(options.count() == 1); + mockAudioSourceService->mockAudioEncoderControl->setEncodingOption(codec, options.first(),8000); + QVERIFY(mockAudioSourceService->mockAudioEncoderControl->encodingOption(codec, options.first()).toInt() == 8000); +} + +void tst_QAudioCaptureSource::testDevices() +{ + QList devices = audiosource->audioInputs(); + QVERIFY(devices.size() > 0); + QVERIFY(devices.at(0).compare("device1") == 0); + QVERIFY(audiosource->audioDescription("device1").compare("dev1 comment") == 0); + QVERIFY(audiosource->defaultAudioInput() == "device1"); + + QSignalSpy checkSignal(audiosource, SIGNAL(activeAudioInputChanged(QString))); + audiosource->setAudioInput("device2"); + QVERIFY(audiosource->activeAudioInput().compare("device2") == 0); + QVERIFY(checkSignal.count() == 1); +} + +QTEST_MAIN(tst_QAudioCaptureSource) + +#include "tst_qaudiocapturesource.moc" diff --git a/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro b/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro new file mode 100644 index 000000000..1b2452419 --- /dev/null +++ b/tests/auto/qaudiodeviceinfo/qaudiodeviceinfo.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qaudiodeviceinfo +# CONFIG += testcase + +SOURCES += tst_qaudiodeviceinfo.cpp + diff --git a/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp b/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp new file mode 100644 index 000000000..29225bc62 --- /dev/null +++ b/tests/auto/qaudiodeviceinfo/tst_qaudiodeviceinfo.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + + +#include +#include +#include + +#include +#include + +//TESTED_COMPONENT=src/multimedia + +class tst_QAudioDeviceInfo : public QObject +{ + Q_OBJECT +public: + tst_QAudioDeviceInfo(QObject* parent=0) : QObject(parent) {} + +private slots: + void initTestCase(); + void checkAvailableDefaultInput(); + void checkAvailableDefaultOutput(); + void outputList(); + void codecs(); + void channels(); + void sampleSizes(); + void byteOrders(); + void sampleTypes(); + void frequencies(); + void isformat(); + void preferred(); + void nearest(); + +private: + bool available; + QAudioDeviceInfo* device; +}; + +void tst_QAudioDeviceInfo::initTestCase() +{ + // Only perform tests if audio output device exists! + QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + if(devices.size() > 0) + available = true; + else { + qWarning()<<"NOTE: no audio output device found, no test will be performed"; + available = false; + } +} + +void tst_QAudioDeviceInfo::checkAvailableDefaultInput() +{ + // Only perform tests if audio input device exists! + bool storeAvailable = available; + QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + if(devices.size() > 0) + available = true; + else { + qWarning()<<"NOTE: no audio input device found, no test will be performed"; + available = false; + } + if(available) + QVERIFY(!QAudioDeviceInfo::defaultInputDevice().isNull()); + available = storeAvailable; +} + +void tst_QAudioDeviceInfo::checkAvailableDefaultOutput() +{ + if(available) + QVERIFY(!QAudioDeviceInfo::defaultOutputDevice().isNull()); +} + +void tst_QAudioDeviceInfo::outputList() +{ + if(available) { + QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + QVERIFY(devices.size() > 0); + device = new QAudioDeviceInfo(devices.at(0)); + } +} + +void tst_QAudioDeviceInfo::codecs() +{ + if(available) { + QStringList avail = device->supportedCodecs(); + QVERIFY(avail.size() > 0); + } +} + +void tst_QAudioDeviceInfo::channels() +{ + if(available) { + QList avail = device->supportedChannels(); + QVERIFY(avail.size() > 0); + } +} + +void tst_QAudioDeviceInfo::sampleSizes() +{ + if(available) { + QList avail = device->supportedSampleSizes(); + QVERIFY(avail.size() > 0); + } +} + +void tst_QAudioDeviceInfo::byteOrders() +{ + if(available) { + QList avail = device->supportedByteOrders(); + QVERIFY(avail.size() > 0); + } +} + +void tst_QAudioDeviceInfo::sampleTypes() +{ + if(available) { + QList avail = device->supportedSampleTypes(); + QVERIFY(avail.size() > 0); + } +} + +void tst_QAudioDeviceInfo::frequencies() +{ + if(available) { + QList avail = device->supportedFrequencies(); + QVERIFY(avail.size() > 0); + } +} + +void tst_QAudioDeviceInfo::isformat() +{ + if(available) { + QAudioFormat format; + format.setFrequency(44100); + format.setChannels(2); + format.setSampleType(QAudioFormat::SignedInt); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setSampleSize(16); + format.setCodec("audio/pcm"); + + // Should always be true for these format + QVERIFY(device->isFormatSupported(format)); + } +} + +void tst_QAudioDeviceInfo::preferred() +{ + if(available) { + QAudioFormat format = device->preferredFormat(); + QVERIFY(format.isValid()); + } +} + +void tst_QAudioDeviceInfo::nearest() +{ + if(available) { + /* + QAudioFormat format1, format2; + format1.setFrequency(8000); + format2 = device->nearestFormat(format1); + QVERIFY(format2.frequency() == 44100); + */ + } +} + +QTEST_MAIN(tst_QAudioDeviceInfo) + +#include "tst_qaudiodeviceinfo.moc" diff --git a/tests/auto/qaudioformat/qaudioformat.pro b/tests/auto/qaudioformat/qaudioformat.pro new file mode 100644 index 000000000..568cad09a --- /dev/null +++ b/tests/auto/qaudioformat/qaudioformat.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qaudioformat +# CONFIG += testcase + +SOURCES += tst_qaudioformat.cpp + diff --git a/tests/auto/qaudioformat/tst_qaudioformat.cpp b/tests/auto/qaudioformat/tst_qaudioformat.cpp new file mode 100644 index 000000000..d543708ae --- /dev/null +++ b/tests/auto/qaudioformat/tst_qaudioformat.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + + +#include +#include +#include + +#include +#include + +//TESTED_COMPONENT=src/multimedia + +class tst_QAudioFormat : public QObject +{ + Q_OBJECT + +public: + tst_QAudioFormat(QObject* parent=0) : QObject(parent) {} + +private slots: + void checkNull(); + void checkFrequency(); + void checkChannels(); + void checkSampleSize(); + void checkCodec(); + void checkByteOrder(); + void checkSampleType(); + void checkEquality(); + void checkAssignment(); +}; + +void tst_QAudioFormat::checkNull() +{ + // Default constructed QAudioFormat is invalid. + QAudioFormat audioFormat0; + QVERIFY(!audioFormat0.isValid()); + + // validity is transferred + QAudioFormat audioFormat1(audioFormat0); + QVERIFY(!audioFormat1.isValid()); + + audioFormat0.setFrequency(44100); + audioFormat0.setChannels(2); + audioFormat0.setSampleSize(16); + audioFormat0.setCodec("audio/pcm"); + audioFormat0.setSampleType(QAudioFormat::SignedInt); + QVERIFY(audioFormat0.isValid()); +} + +void tst_QAudioFormat::checkFrequency() +{ + QAudioFormat audioFormat; + audioFormat.setFrequency(44100); + QVERIFY(audioFormat.frequency() == 44100); +} + +void tst_QAudioFormat::checkChannels() +{ + QAudioFormat audioFormat; + audioFormat.setChannels(2); + QVERIFY(audioFormat.channels() == 2); +} + +void tst_QAudioFormat::checkSampleSize() +{ + QAudioFormat audioFormat; + audioFormat.setSampleSize(16); + QVERIFY(audioFormat.sampleSize() == 16); +} + +void tst_QAudioFormat::checkCodec() +{ + QAudioFormat audioFormat; + audioFormat.setCodec(QString::fromLatin1("audio/pcm")); + QVERIFY(audioFormat.codec() == QString::fromLatin1("audio/pcm")); +} + +void tst_QAudioFormat::checkByteOrder() +{ + QAudioFormat audioFormat; + audioFormat.setByteOrder(QAudioFormat::LittleEndian); + QVERIFY(audioFormat.byteOrder() == QAudioFormat::LittleEndian); +} + +void tst_QAudioFormat::checkSampleType() +{ + QAudioFormat audioFormat; + audioFormat.setSampleType(QAudioFormat::SignedInt); + QVERIFY(audioFormat.sampleType() == QAudioFormat::SignedInt); +} + +void tst_QAudioFormat::checkEquality() +{ + QAudioFormat audioFormat0; + QAudioFormat audioFormat1; + + // Null formats are equivalent + QVERIFY(audioFormat0 == audioFormat1); + QVERIFY(!(audioFormat0 != audioFormat1)); + + // on filled formats + audioFormat0.setFrequency(8000); + audioFormat0.setChannels(1); + audioFormat0.setSampleSize(8); + audioFormat0.setCodec("audio/pcm"); + audioFormat0.setByteOrder(QAudioFormat::LittleEndian); + audioFormat0.setSampleType(QAudioFormat::UnSignedInt); + + audioFormat1.setFrequency(8000); + audioFormat1.setChannels(1); + audioFormat1.setSampleSize(8); + audioFormat1.setCodec("audio/pcm"); + audioFormat1.setByteOrder(QAudioFormat::LittleEndian); + audioFormat1.setSampleType(QAudioFormat::UnSignedInt); + + QVERIFY(audioFormat0 == audioFormat1); + QVERIFY(!(audioFormat0 != audioFormat1)); + + audioFormat0.setFrequency(44100); + QVERIFY(audioFormat0 != audioFormat1); + QVERIFY(!(audioFormat0 == audioFormat1)); +} + +void tst_QAudioFormat::checkAssignment() +{ + QAudioFormat audioFormat0; + QAudioFormat audioFormat1; + + audioFormat0.setFrequency(8000); + audioFormat0.setChannels(1); + audioFormat0.setSampleSize(8); + audioFormat0.setCodec("audio/pcm"); + audioFormat0.setByteOrder(QAudioFormat::LittleEndian); + audioFormat0.setSampleType(QAudioFormat::UnSignedInt); + + audioFormat1 = audioFormat0; + QVERIFY(audioFormat1 == audioFormat0); + + QAudioFormat audioFormat2(audioFormat0); + QVERIFY(audioFormat2 == audioFormat0); +} + +QTEST_MAIN(tst_QAudioFormat) + +#include "tst_qaudioformat.moc" diff --git a/tests/auto/qaudioinput/qaudioinput.pro b/tests/auto/qaudioinput/qaudioinput.pro new file mode 100644 index 000000000..96aca17c7 --- /dev/null +++ b/tests/auto/qaudioinput/qaudioinput.pro @@ -0,0 +1,18 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qaudioinput +# CONFIG += testcase + +wince*{ + DEFINES += SRCDIR=\\\"\\\" + QT += gui +} else { + !symbian:DEFINES += SRCDIR=\\\"$$PWD/\\\" +} + +HEADERS += wavheader.h +SOURCES += wavheader.cpp tst_qaudioinput.cpp + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qaudioinput/tst_qaudioinput.cpp b/tests/auto/qaudioinput/tst_qaudioinput.cpp new file mode 100755 index 000000000..fb5f2e229 --- /dev/null +++ b/tests/auto/qaudioinput/tst_qaudioinput.cpp @@ -0,0 +1,814 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include +#include + +#include "wavheader.h" + +//TESTED_COMPONENT=src/multimedia + +#define AUDIO_BUFFER 192000 + +#if defined(Q_OS_SYMBIAN) +#define SRCDIR "" +#endif + +#ifndef QTRY_VERIFY2 +#define QTRY_VERIFY2(__expr,__msg) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY2(__expr,__msg); \ + } while(0) +#endif + +Q_DECLARE_METATYPE(QAudioFormat) + +class tst_QAudioInput : public QObject +{ + Q_OBJECT +public: + tst_QAudioInput(QObject* parent=0) : QObject(parent) {} + +private slots: + void initTestCase(); + + void format(); + void invalidFormat_data(); + void invalidFormat(); + + void bufferSize(); + + void notifyInterval(); + void disableNotifyInterval(); + + void stopWhileStopped(); + void suspendWhileStopped(); + void resumeWhileStopped(); + + void pull(); + void pullSuspendResume(); + + void push(); + void pushSuspendResume(); + + void reset(); + + void cleanupTestCase(); + +private: + QString formatToFileName(const QAudioFormat &format); + QString workingDir(); + + QAudioDeviceInfo audioDevice; + QList testFormats; + QList audioFiles; + + QScopedPointer m_byteArray; + QScopedPointer m_buffer; +}; + +QString tst_QAudioInput::formatToFileName(const QAudioFormat &format) +{ + const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian) + ? QString("LE") : QString("BE"); + + const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt) + ? QString("signed") : QString("unsigned"); + + return QString("%1_%2_%3_%4_%5") + .arg(format.frequency()) + .arg(format.sampleSize()) + .arg(formatSigned) + .arg(formatEndian) + .arg(format.channels()); +} + + +QString tst_QAudioInput::workingDir() +{ + QDir working(QString(SRCDIR)); + + if (working.exists()) + return QString(SRCDIR); + + return QDir::currentPath(); +} + +void tst_QAudioInput::initTestCase() +{ + qRegisterMetaType(); + + // Only perform tests if audio output device exists + const QList devices = + QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + + if (devices.size() <= 0) + QSKIP("No audio backend", SkipAll); + + audioDevice = QAudioDeviceInfo::defaultInputDevice(); + + + QAudioFormat format; + + format.setCodec("audio/pcm"); + + if (audioDevice.isFormatSupported(audioDevice.preferredFormat())) + testFormats.append(audioDevice.preferredFormat()); + + // PCM 8000 mono S8 + format.setFrequency(8000); + format.setSampleSize(8); + format.setSampleType(QAudioFormat::SignedInt); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setChannels(1); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 11025 mono S16LE + format.setFrequency(11025); + format.setSampleSize(16); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 22050 mono S16LE + format.setFrequency(22050); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 22050 stereo S16LE + format.setChannels(2); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 44100 stereo S16LE + format.setFrequency(44100); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 48000 stereo S16LE + format.setFrequency(48000); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + QVERIFY(testFormats.size()); + + foreach (format, testFormats) { + QFile* file = new QFile(workingDir() + formatToFileName(format) + QString(".wav")); + audioFiles.append(file); + } +} + +void tst_QAudioInput::format() +{ + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QAudioFormat requested = audioDevice.preferredFormat(); + QAudioFormat actual = audioInput.format(); + + QVERIFY2((requested.channels() == actual.channels()), + QString("channels: requested=%1, actual=%2").arg(requested.channels()).arg(actual.channels()).toLocal8Bit().constData()); + QVERIFY2((requested.frequency() == actual.frequency()), + QString("frequency: requested=%1, actual=%2").arg(requested.frequency()).arg(actual.frequency()).toLocal8Bit().constData()); + QVERIFY2((requested.sampleSize() == actual.sampleSize()), + QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData()); + QVERIFY2((requested.codec() == actual.codec()), + QString("codec: requested=%1, actual=%2").arg(requested.codec()).arg(actual.codec()).toLocal8Bit().constData()); + QVERIFY2((requested.byteOrder() == actual.byteOrder()), + QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData()); + QVERIFY2((requested.sampleType() == actual.sampleType()), + QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData()); +} + +void tst_QAudioInput::invalidFormat_data() +{ + QTest::addColumn("invalidFormat"); + + QAudioFormat format; + + QTest::newRow("Null Format") + << format; + + format = audioDevice.preferredFormat(); + format.setChannelCount(0); + QTest::newRow("Channel count 0") + << format; + + format = audioDevice.preferredFormat(); + format.setSampleRate(0); + QTest::newRow("Sample rate 0") + << format; + + format = audioDevice.preferredFormat(); + format.setSampleSize(0); + QTest::newRow("Sample size 0") + << format; +} + +void tst_QAudioInput::invalidFormat() +{ + QFETCH(QAudioFormat, invalidFormat); + + QVERIFY2(!audioDevice.isFormatSupported(invalidFormat), + "isFormatSupported() is returning true on an invalid format"); + + QAudioInput audioInput(invalidFormat, this); + + // Check that we are in the default state before calling start + QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + audioInput.start(); + // Check that error is raised + QTRY_VERIFY2((audioInput.error() == QAudio::OpenError),"error() was not set to QAudio::OpenError after start()"); +} + +void tst_QAudioInput::bufferSize() +{ + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation"); + + audioInput.setBufferSize(512); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(512)"); + QVERIFY2((audioInput.bufferSize() == 512), + QString("bufferSize: requested=512, actual=%2").arg(audioInput.bufferSize()).toLocal8Bit().constData()); + + audioInput.setBufferSize(4096); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(4096)"); + QVERIFY2((audioInput.bufferSize() == 4096), + QString("bufferSize: requested=4096, actual=%2").arg(audioInput.bufferSize()).toLocal8Bit().constData()); + + audioInput.setBufferSize(8192); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(8192)"); + QVERIFY2((audioInput.bufferSize() == 8192), + QString("bufferSize: requested=8192, actual=%2").arg(audioInput.bufferSize()).toLocal8Bit().constData()); +} + +void tst_QAudioInput::notifyInterval() +{ + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation"); + + audioInput.setNotifyInterval(50); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(50)"); + QVERIFY2((audioInput.notifyInterval() == 50), + QString("notifyInterval: requested=50, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData()); + + audioInput.setNotifyInterval(100); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(100)"); + QVERIFY2((audioInput.notifyInterval() == 100), + QString("notifyInterval: requested=100, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData()); + + audioInput.setNotifyInterval(250); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(250)"); + QVERIFY2((audioInput.notifyInterval() == 250), + QString("notifyInterval: requested=250, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData()); + + audioInput.setNotifyInterval(1000); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(1000)"); + QVERIFY2((audioInput.notifyInterval() == 1000), + QString("notifyInterval: requested=1000, actual=%2").arg(audioInput.notifyInterval()).toLocal8Bit().constData()); +} + +void tst_QAudioInput::disableNotifyInterval() +{ + // Sets an invalid notification interval (QAudioInput::setNotifyInterval(0)) + // Checks that + // - No error is raised (QAudioInput::error() returns QAudio::NoError) + // - if <= 0, set to zero and disable notify signal + + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation"); + + audioInput.setNotifyInterval(0); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(0)"); + QVERIFY2((audioInput.notifyInterval() == 0), + "notifyInterval() is not zero after setNotifyInterval(0)"); + + audioInput.setNotifyInterval(-1); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(-1)"); + QVERIFY2((audioInput.notifyInterval() == 0), + "notifyInterval() is not zero after setNotifyInterval(-1)"); + + //start and run to check if notify() is emitted + if (audioFiles.size() > 0) { + QAudioInput audioInputCheck(testFormats.at(0), this); + audioInputCheck.setNotifyInterval(0); + QSignalSpy notifySignal(&audioInputCheck, SIGNAL(notify())); + audioFiles.at(0)->open(QIODevice::WriteOnly); + audioInputCheck.start(audioFiles.at(0)); + QTest::qWait(3000); // 3 seconds should be plenty + audioInputCheck.stop(); + QVERIFY2((notifySignal.count() == 0), + QString("didn't disable notify interval: shouldn't have got any but got %1").arg(notifySignal.count()).toLocal8Bit().constData()); + audioFiles.at(0)->close(); + } +} + +void tst_QAudioInput::stopWhileStopped() +{ + // Calls QAudioInput::stop() when object is already in StoppedState + // Checks that + // - No state change occurs + // - No error is raised (QAudioInput::error() returns QAudio::NoError) + + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State))); + audioInput.stop(); + + // Check that no state transition occurred + QVERIFY2((stateSignal.count() == 0), "stop() while stopped is emitting a signal and it shouldn't"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()"); +} + +void tst_QAudioInput::suspendWhileStopped() +{ + // Calls QAudioInput::suspend() when object is already in StoppedState + // Checks that + // - No state change occurs + // - No error is raised (QAudioInput::error() returns QAudio::NoError) + + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State))); + audioInput.suspend(); + + // Check that no state transition occurred + QVERIFY2((stateSignal.count() == 0), "stop() while suspended is emitting a signal and it shouldn't"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()"); +} + +void tst_QAudioInput::resumeWhileStopped() +{ + // Calls QAudioInput::resume() when object is already in StoppedState + // Checks that + // - No state change occurs + // - No error is raised (QAudioInput::error() returns QAudio::NoError) + + QAudioInput audioInput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioInput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + QSignalSpy stateSignal(&audioInput, SIGNAL(stateChanged(QAudio::State))); + audioInput.resume(); + + // Check that no state transition occurred + QVERIFY2((stateSignal.count() == 0), "resume() while stopped is emitting a signal and it shouldn't"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after resume()"); +} + +void tst_QAudioInput::pull() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::WriteOnly); + WavHeader wavHeader(testFormats.at(i)); + QVERIFY(wavHeader.write(*audioFiles.at(i))); + + audioInput.start(audioFiles.at(i)); + // Check that QAudioInput immediately transitions to ActiveState or IdleState + QTRY_VERIFY2((stateSignal.count() > 0),"didn't emit signals on start()"); + QVERIFY2((audioInput.state() == QAudio::ActiveState || audioInput.state() == QAudio::IdleState), + "didn't transition to ActiveState or IdleState after start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioInput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + + // Allow some recording to happen + QTest::qWait(3000); // 3 seconds should be plenty + + stateSignal.clear(); + + qint64 processedUs = audioInput.processedUSecs(); + + audioInput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs > 2800000 && processedUs < 3200000), + QString("processedUSecs() doesn't fall in acceptable range, should be 3040000 (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + QVERIFY2((notifySignal.count() > 20 && notifySignal.count() < 40), + QString("notify() signals emitted (%1) should be 30").arg(notifySignal.count()).toLocal8Bit().constData()); + + WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength()); + audioFiles.at(i)->close(); + } +} + +void tst_QAudioInput::pullSuspendResume() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::WriteOnly); + WavHeader wavHeader(testFormats.at(i)); + QVERIFY(wavHeader.write(*audioFiles.at(i))); + + audioInput.start(audioFiles.at(i)); + // Check that QAudioInput immediately transitions to ActiveState or IdleState + QTRY_VERIFY2((stateSignal.count() > 0),"didn't emit signals on start()"); + QVERIFY2((audioInput.state() == QAudio::ActiveState || audioInput.state() == QAudio::IdleState), + "didn't transition to ActiveState or IdleState after start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioInput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + + // Allow some recording to happen + QTest::qWait(3000); // 3 seconds should be plenty + + QVERIFY2((audioInput.state() == QAudio::ActiveState), + "didn't transition to ActiveState after some recording"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after some recording"); + + stateSignal.clear(); + + audioInput.suspend(); + + // Give backends running in separate threads a chance to suspend. + QTest::qWait(100); + + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::SuspendedState), "didn't transitions to SuspendedState after stop()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + stateSignal.clear(); + + // Check that only 'elapsed', and not 'processed' increases while suspended + qint64 elapsedUs = audioInput.elapsedUSecs(); + qint64 processedUs = audioInput.processedUSecs(); + QTest::qWait(1000); + QVERIFY(audioInput.elapsedUSecs() > elapsedUs); + QVERIFY(audioInput.processedUSecs() == processedUs); + + audioInput.resume(); + + // Give backends running in separate threads a chance to resume. + QTest::qWait(100); + + // Check that QAudioInput immediately transitions to ActiveState + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()"); + stateSignal.clear(); + + processedUs = audioInput.processedUSecs(); + + audioInput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs > 2800000 && processedUs < 3200000), + QString("processedUSecs() doesn't fall in acceptable range, should be 3040000 (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + QVERIFY2((notifySignal.count() > 20 && notifySignal.count() < 40), + QString("notify() signals emitted (%1) should be 30").arg(notifySignal.count()).toLocal8Bit().constData()); + + WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength()); + audioFiles.at(i)->close(); + } +} + +void tst_QAudioInput::push() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::WriteOnly); + WavHeader wavHeader(testFormats.at(i)); + QVERIFY(wavHeader.write(*audioFiles.at(i))); + + QIODevice* feed = audioInput.start(); + + // Check that QAudioInput immediately transitions to IdleState + QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit IdleState signal on start()"); + QVERIFY2((audioInput.state() == QAudio::IdleState), + "didn't transition to IdleState after start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioInput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + + qint64 totalBytesRead = 0; + bool firstBuffer = true; + QByteArray buffer(AUDIO_BUFFER, 0); + qint64 len = (testFormats.at(i).frequency()*testFormats.at(i).channels()*(testFormats.at(i).sampleSize()/8)*2); // 2 seconds + while (totalBytesRead < len) { + if (audioInput.bytesReady() >= audioInput.periodSize()) { + qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize()); + audioFiles.at(i)->write(buffer.constData(),bytesRead); + totalBytesRead+=bytesRead; + if (firstBuffer && bytesRead) { + // Check for transition to ActiveState when data is provided + QVERIFY2((stateSignal.count() == 1),"didn't emit ActiveState signal on data"); + QVERIFY2((audioInput.state() == QAudio::ActiveState), + "didn't transition to ActiveState after data"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + firstBuffer = false; + } + } else + QTest::qWait(20); + } + + QTest::qWait(1000); + + stateSignal.clear(); + + qint64 processedUs = audioInput.processedUSecs(); + + audioInput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs > 1800000 && processedUs < 2200000), + QString("processedUSecs() doesn't fall in acceptable range, should be 2040000 (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + QVERIFY2((notifySignal.count() > 20 && notifySignal.count() < 40), + QString("notify() signals emitted (%1) should be 30").arg(notifySignal.count()).toLocal8Bit().constData()); + + WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength()); + audioFiles.at(i)->close(); + } +} + +void tst_QAudioInput::pushSuspendResume() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::WriteOnly); + WavHeader wavHeader(testFormats.at(i)); + QVERIFY(wavHeader.write(*audioFiles.at(i))); + + QIODevice* feed = audioInput.start(); + + // Check that QAudioInput immediately transitions to IdleState + QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit IdleState signal on start()"); + QVERIFY2((audioInput.state() == QAudio::IdleState), + "didn't transition to IdleState after start()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioInput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioInput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + + qint64 totalBytesRead = 0; + bool firstBuffer = true; + QByteArray buffer(AUDIO_BUFFER, 0); + qint64 len = (testFormats.at(i).frequency()*testFormats.at(i).channels()*(testFormats.at(i).sampleSize()/8)); // 1 seconds + while (totalBytesRead < len) { + if (audioInput.bytesReady() >= audioInput.periodSize()) { + qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize()); + audioFiles.at(i)->write(buffer.constData(),bytesRead); + totalBytesRead+=bytesRead; + if (firstBuffer && bytesRead) { + // Check for transition to ActiveState when data is provided + QVERIFY2((stateSignal.count() == 1),"didn't emit ActiveState signal on data"); + QVERIFY2((audioInput.state() == QAudio::ActiveState), + "didn't transition to ActiveState after data"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + firstBuffer = false; + } + } else + QTest::qWait(20); + } + stateSignal.clear(); + + audioInput.suspend(); + + // Give backends running in separate threads a chance to suspend + QTest::qWait(100); + + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::SuspendedState), "didn't transitions to SuspendedState after stop()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + stateSignal.clear(); + + // Check that only 'elapsed', and not 'processed' increases while suspended + qint64 elapsedUs = audioInput.elapsedUSecs(); + qint64 processedUs = audioInput.processedUSecs(); + QTest::qWait(1000); + QVERIFY(audioInput.elapsedUSecs() > elapsedUs); + QVERIFY(audioInput.processedUSecs() == processedUs); + + audioInput.resume(); + + // Give backends running in separate threads a chance to resume. + QTest::qWait(100); + + // Check that QAudioInput immediately transitions to Active or IdleState + QVERIFY2((stateSignal.count() > 0),"didn't emit signals on resume()"); + QVERIFY2((audioInput.state() == QAudio::ActiveState || audioInput.state() == QAudio::IdleState), + "didn't transition to ActiveState or IdleState after resume()"); + QVERIFY2((audioInput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()"); + QVERIFY(audioInput.periodSize() > 0); + + // Let it play out what is in buffer and go to Idle before continue + QTest::qWait(1000); + stateSignal.clear(); + + // Read another seconds worth + totalBytesRead = 0; + firstBuffer = true; + while (totalBytesRead < len) { + if (audioInput.bytesReady() >= audioInput.periodSize()) { + qint64 bytesRead = feed->read(buffer.data(), audioInput.periodSize()); + audioFiles.at(i)->write(buffer.constData(),bytesRead); + totalBytesRead+=bytesRead; + } else + QTest::qWait(20); + } + stateSignal.clear(); + + processedUs = audioInput.processedUSecs(); + + audioInput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs > 1800000 && processedUs < 2200000), + QString("processedUSecs() doesn't fall in acceptable range, should be 2040000 (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioInput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + + WavHeader::writeDataLength(*audioFiles.at(i),audioFiles.at(i)->pos()-WavHeader::headerLength()); + audioFiles.at(i)->close(); + } +} + +void tst_QAudioInput::reset() +{ + for(int i=0; i 0); + QTest::qWait(500); + QVERIFY(audioInput.bytesReady() > 0); + stateSignal.clear(); + + audioInput.reset(); + QTRY_VERIFY2((stateSignal.count() == 1),"didn't emit StoppedState signal after reset()"); + QVERIFY2((audioInput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after reset()"); + QVERIFY2((audioInput.bytesReady() == 0), "buffer not cleared after reset()"); + } +} + +void tst_QAudioInput::cleanupTestCase() +{ + QFile* file; + + foreach (file, audioFiles) { + file->remove(); + delete file; + } +} + +QTEST_MAIN(tst_QAudioInput) + +#include "tst_qaudioinput.moc" diff --git a/tests/auto/qaudioinput/wavheader.cpp b/tests/auto/qaudioinput/wavheader.cpp new file mode 100755 index 000000000..26fcd6f98 --- /dev/null +++ b/tests/auto/qaudioinput/wavheader.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +#include +#include "wavheader.h" + + +struct chunk +{ + char id[4]; + quint32 size; +}; + +struct RIFFHeader +{ + chunk descriptor; // "RIFF" + char type[4]; // "WAVE" +}; + +struct WAVEHeader +{ + chunk descriptor; + quint16 audioFormat; + quint16 numChannels; + quint32 sampleRate; + quint32 byteRate; + quint16 blockAlign; + quint16 bitsPerSample; +}; + +struct DATAHeader +{ + chunk descriptor; +}; + +struct CombinedHeader +{ + RIFFHeader riff; + WAVEHeader wave; + DATAHeader data; +}; + +static const int HeaderLength = sizeof(CombinedHeader); + + +WavHeader::WavHeader(const QAudioFormat &format, qint64 dataLength) + : m_format(format) + , m_dataLength(dataLength) +{ + +} + +bool WavHeader::read(QIODevice &device) +{ + bool result = true; + + if (!device.isSequential()) + result = device.seek(0); + // else, assume that current position is the start of the header + + if (result) { + CombinedHeader header; + result = (device.read(reinterpret_cast(&header), HeaderLength) == HeaderLength); + if (result) { + if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 + || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) + && memcmp(&header.riff.type, "WAVE", 4) == 0 + && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 + && header.wave.audioFormat == 1 // PCM + ) { + if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) + m_format.setByteOrder(QAudioFormat::LittleEndian); + else + m_format.setByteOrder(QAudioFormat::BigEndian); + + m_format.setChannels(qFromLittleEndian(header.wave.numChannels)); + m_format.setCodec("audio/pcm"); + m_format.setFrequency(qFromLittleEndian(header.wave.sampleRate)); + m_format.setSampleSize(qFromLittleEndian(header.wave.bitsPerSample)); + + switch(header.wave.bitsPerSample) { + case 8: + m_format.setSampleType(QAudioFormat::UnSignedInt); + break; + case 16: + m_format.setSampleType(QAudioFormat::SignedInt); + break; + default: + result = false; + } + + m_dataLength = device.size() - HeaderLength; + } else { + result = false; + } + } + } + + return result; +} + +bool WavHeader::write(QIODevice &device) +{ + CombinedHeader header; + + memset(&header, 0, HeaderLength); + + // RIFF header + if (m_format.byteOrder() == QAudioFormat::LittleEndian) + memcpy(header.riff.descriptor.id,"RIFF",4); + else + memcpy(header.riff.descriptor.id,"RIFX",4); + qToLittleEndian(quint32(m_dataLength + HeaderLength - 8), + reinterpret_cast(&header.riff.descriptor.size)); + memcpy(header.riff.type, "WAVE",4); + + // WAVE header + memcpy(header.wave.descriptor.id,"fmt ",4); + qToLittleEndian(quint32(16), + reinterpret_cast(&header.wave.descriptor.size)); + qToLittleEndian(quint16(1), + reinterpret_cast(&header.wave.audioFormat)); + qToLittleEndian(quint16(m_format.channels()), + reinterpret_cast(&header.wave.numChannels)); + qToLittleEndian(quint32(m_format.frequency()), + reinterpret_cast(&header.wave.sampleRate)); + qToLittleEndian(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8), + reinterpret_cast(&header.wave.byteRate)); + qToLittleEndian(quint16(m_format.channels() * m_format.sampleSize() / 8), + reinterpret_cast(&header.wave.blockAlign)); + qToLittleEndian(quint16(m_format.sampleSize()), + reinterpret_cast(&header.wave.bitsPerSample)); + + // DATA header + memcpy(header.data.descriptor.id,"data",4); + qToLittleEndian(quint32(m_dataLength), + reinterpret_cast(&header.data.descriptor.size)); + + return (device.write(reinterpret_cast(&header), HeaderLength) == HeaderLength); +} + +const QAudioFormat& WavHeader::format() const +{ + return m_format; +} + +qint64 WavHeader::dataLength() const +{ + return m_dataLength; +} + +qint64 WavHeader::headerLength() +{ + return HeaderLength; +} + +bool WavHeader::writeDataLength(QIODevice &device, qint64 dataLength) +{ + bool result = false; + if (!device.isSequential()) { + device.seek(40); + unsigned char dataLengthLE[4]; + qToLittleEndian(quint32(dataLength), dataLengthLE); + result = (device.write(reinterpret_cast(dataLengthLE), 4) == 4); + } + return result; +} diff --git a/tests/auto/qaudioinput/wavheader.h b/tests/auto/qaudioinput/wavheader.h new file mode 100755 index 000000000..4136da027 --- /dev/null +++ b/tests/auto/qaudioinput/wavheader.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + + +#ifndef WAVHEADER_H +#define WAVHEADER_H + +#include +#include +#include + +/** + * Helper class for parsing WAV file headers. + * + * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ + */ +class WavHeader +{ +public: + WavHeader(const QAudioFormat &format = QAudioFormat(), + qint64 dataLength = 0); + + // Reads WAV header and seeks to start of data + bool read(QIODevice &device); + + // Writes WAV header + bool write(QIODevice &device); + + const QAudioFormat& format() const; + qint64 dataLength() const; + + static qint64 headerLength(); + + static bool writeDataLength(QIODevice &device, qint64 dataLength); + +private: + QAudioFormat m_format; + qint64 m_dataLength; +}; + +#endif + diff --git a/tests/auto/qaudiooutput/qaudiooutput.pro b/tests/auto/qaudiooutput/qaudiooutput.pro new file mode 100644 index 000000000..b99128c77 --- /dev/null +++ b/tests/auto/qaudiooutput/qaudiooutput.pro @@ -0,0 +1,18 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qaudiooutput +# CONFIG += testcase + +wince*: { + DEFINES += SRCDIR=\\\"\\\" + QT += gui +} else { + !symbian:DEFINES += SRCDIR=\\\"$$PWD/\\\" +} + +HEADERS += wavheader.h +SOURCES += wavheader.cpp tst_qaudiooutput.cpp + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qaudiooutput/tst_qaudiooutput.cpp b/tests/auto/qaudiooutput/tst_qaudiooutput.cpp new file mode 100755 index 000000000..2590af39d --- /dev/null +++ b/tests/auto/qaudiooutput/tst_qaudiooutput.cpp @@ -0,0 +1,962 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include +#include +#include +#include + +#include "wavheader.h" + +#define AUDIO_BUFFER 192000 + +#if defined(Q_OS_SYMBIAN) +#define SRCDIR "" +#endif + +#ifndef QTRY_VERIFY2 +#define QTRY_VERIFY2(__expr,__msg) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY2(__expr,__msg); \ + } while(0) +#endif + +Q_DECLARE_METATYPE(QAudioFormat) + +class tst_QAudioOutput : public QObject +{ + Q_OBJECT +public: + tst_QAudioOutput(QObject* parent=0) : QObject(parent) {} + +private slots: + void initTestCase(); + + void format(); + void invalidFormat_data(); + void invalidFormat(); + + void bufferSize(); + + void notifyInterval(); + void disableNotifyInterval(); + + void stopWhileStopped(); + void suspendWhileStopped(); + void resumeWhileStopped(); + + void pull(); + void pullSuspendResume(); + + void push(); + void pushSuspendResume(); + void pushUnderrun(); + + void cleanupTestCase(); + +private: + QString formatToFileName(const QAudioFormat &format); + QString workingDir(); + void createSineWaveData(const QAudioFormat &format, qint64 length, int frequency = 440); + + QAudioDeviceInfo audioDevice; + QList testFormats; + QList audioFiles; + + QScopedPointer m_byteArray; + QScopedPointer m_buffer; +}; + +QString tst_QAudioOutput::formatToFileName(const QAudioFormat &format) +{ + const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian) + ? QString("LE") : QString("BE"); + + const QString formatSigned = (format.sampleType() == QAudioFormat::SignedInt) + ? QString("signed") : QString("unsigned"); + + return QString("%1_%2_%3_%4_%5") + .arg(format.frequency()) + .arg(format.sampleSize()) + .arg(formatSigned) + .arg(formatEndian) + .arg(format.channels()); +} + + +QString tst_QAudioOutput::workingDir() +{ + QDir working(QString(SRCDIR)); + + if (working.exists()) + return QString(SRCDIR); + + return QDir::currentPath(); +} + +void tst_QAudioOutput::createSineWaveData(const QAudioFormat &format, qint64 length, int frequency) +{ + const int channelBytes = format.sampleSize() / 8; + const int sampleBytes = format.channels() * channelBytes; + + Q_ASSERT(length % sampleBytes == 0); + Q_UNUSED(sampleBytes) // suppress warning in release builds + + m_byteArray.reset(new QByteArray(length, 0)); + unsigned char *ptr = reinterpret_cast(m_byteArray->data()); + int sampleIndex = 0; + + while (length) { + const qreal x = qSin(2 * M_PI * frequency * qreal(sampleIndex % format.frequency()) / format.frequency()); + for (int i=0; i((1.0 + x) / 2 * 255); + *reinterpret_cast(ptr) = value; + } else if (format.sampleSize() == 8 && format.sampleType() == QAudioFormat::SignedInt) { + const qint8 value = static_cast(x * 127); + *reinterpret_cast(ptr) = value; + } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::UnSignedInt) { + quint16 value = static_cast((1.0 + x) / 2 * 65535); + if (format.byteOrder() == QAudioFormat::LittleEndian) + qToLittleEndian(value, ptr); + else + qToBigEndian(value, ptr); + } else if (format.sampleSize() == 16 && format.sampleType() == QAudioFormat::SignedInt) { + qint16 value = static_cast(x * 32767); + if (format.byteOrder() == QAudioFormat::LittleEndian) + qToLittleEndian(value, ptr); + else + qToBigEndian(value, ptr); + } + + ptr += channelBytes; + length -= channelBytes; + } + ++sampleIndex; + } + + m_buffer.reset(new QBuffer(m_byteArray.data(), this)); + Q_ASSERT(m_buffer->open(QIODevice::ReadOnly)); +} + +void tst_QAudioOutput::initTestCase() +{ + qRegisterMetaType(); + + // Only perform tests if audio output device exists + const QList devices = + QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + + if (devices.size() <= 0) + QSKIP("No audio backend", SkipAll); + + audioDevice = QAudioDeviceInfo::defaultOutputDevice(); + + + QAudioFormat format; + + format.setCodec("audio/pcm"); + + if (audioDevice.isFormatSupported(audioDevice.preferredFormat())) + testFormats.append(audioDevice.preferredFormat()); + + // PCM 8000 mono S8 + format.setFrequency(8000); + format.setSampleSize(8); + format.setSampleType(QAudioFormat::SignedInt); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setChannels(1); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 11025 mono S16LE + format.setFrequency(11025); + format.setSampleSize(16); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 22050 mono S16LE + format.setFrequency(22050); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 22050 stereo S16LE + format.setChannels(2); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 44100 stereo S16LE + format.setFrequency(44100); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + // PCM 48000 stereo S16LE + format.setFrequency(48000); + if (audioDevice.isFormatSupported(format)) + testFormats.append(format); + + QVERIFY(testFormats.size()); + + foreach (format, testFormats) { + qint64 len = (format.frequency()*format.channels()*(format.sampleSize()/8)*2); // 2 seconds + createSineWaveData(format, len); + // Write generate sine wave data to file + QFile* file = new QFile(workingDir() + QString("generated") + formatToFileName(format) + QString(".wav")); + if (file->open(QIODevice::WriteOnly)) { + WavHeader wavHeader(format, len); + wavHeader.write(*file); + file->write(m_byteArray->data(), len); + file->close(); + audioFiles.append(file); + } + } +} + +void tst_QAudioOutput::format() +{ + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QAudioFormat requested = audioDevice.preferredFormat(); + QAudioFormat actual = audioOutput.format(); + + QVERIFY2((requested.channels() == actual.channels()), + QString("channels: requested=%1, actual=%2").arg(requested.channels()).arg(actual.channels()).toLocal8Bit().constData()); + QVERIFY2((requested.frequency() == actual.frequency()), + QString("frequency: requested=%1, actual=%2").arg(requested.frequency()).arg(actual.frequency()).toLocal8Bit().constData()); + QVERIFY2((requested.sampleSize() == actual.sampleSize()), + QString("sampleSize: requested=%1, actual=%2").arg(requested.sampleSize()).arg(actual.sampleSize()).toLocal8Bit().constData()); + QVERIFY2((requested.codec() == actual.codec()), + QString("codec: requested=%1, actual=%2").arg(requested.codec()).arg(actual.codec()).toLocal8Bit().constData()); + QVERIFY2((requested.byteOrder() == actual.byteOrder()), + QString("byteOrder: requested=%1, actual=%2").arg(requested.byteOrder()).arg(actual.byteOrder()).toLocal8Bit().constData()); + QVERIFY2((requested.sampleType() == actual.sampleType()), + QString("sampleType: requested=%1, actual=%2").arg(requested.sampleType()).arg(actual.sampleType()).toLocal8Bit().constData()); +} + +void tst_QAudioOutput::invalidFormat_data() +{ + QTest::addColumn("invalidFormat"); + + QAudioFormat format; + + QTest::newRow("Null Format") + << format; + + format = audioDevice.preferredFormat(); + format.setChannelCount(0); + QTest::newRow("Channel count 0") + << format; + + format = audioDevice.preferredFormat(); + format.setSampleRate(0); + QTest::newRow("Sample rate 0") + << format; + + format = audioDevice.preferredFormat(); + format.setSampleSize(0); + QTest::newRow("Sample size 0") + << format; +} + +void tst_QAudioOutput::invalidFormat() +{ + QFETCH(QAudioFormat, invalidFormat); + + QVERIFY2(!audioDevice.isFormatSupported(invalidFormat), + "isFormatSupported() is returning true on an invalid format"); + + QAudioOutput audioOutput(invalidFormat, this); + + // Check that we are in the default state before calling start + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + audioOutput.start(); + // Check that error is raised + QTRY_VERIFY2((audioOutput.error() == QAudio::OpenError),"error() was not set to QAudio::OpenError after start()"); +} + +void tst_QAudioOutput::bufferSize() +{ + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation"); + + audioOutput.setBufferSize(512); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(512)"); + QVERIFY2((audioOutput.bufferSize() == 512), + QString("bufferSize: requested=512, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData()); + + audioOutput.setBufferSize(4096); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(4096)"); + QVERIFY2((audioOutput.bufferSize() == 4096), + QString("bufferSize: requested=4096, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData()); + + audioOutput.setBufferSize(8192); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setBufferSize(8192)"); + QVERIFY2((audioOutput.bufferSize() == 8192), + QString("bufferSize: requested=8192, actual=%2").arg(audioOutput.bufferSize()).toLocal8Bit().constData()); +} + +void tst_QAudioOutput::notifyInterval() +{ + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation"); + + audioOutput.setNotifyInterval(50); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(50)"); + QVERIFY2((audioOutput.notifyInterval() == 50), + QString("notifyInterval: requested=50, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData()); + + audioOutput.setNotifyInterval(100); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(100)"); + QVERIFY2((audioOutput.notifyInterval() == 100), + QString("notifyInterval: requested=100, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData()); + + audioOutput.setNotifyInterval(250); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(250)"); + QVERIFY2((audioOutput.notifyInterval() == 250), + QString("notifyInterval: requested=250, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData()); + + audioOutput.setNotifyInterval(1000); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(1000)"); + QVERIFY2((audioOutput.notifyInterval() == 1000), + QString("notifyInterval: requested=1000, actual=%2").arg(audioOutput.notifyInterval()).toLocal8Bit().constData()); +} + +void tst_QAudioOutput::disableNotifyInterval() +{ + // Sets an invalid notification interval (QAudioOutput::setNotifyInterval(0)) + // Checks that + // - No error is raised (QAudioOutput::error() returns QAudio::NoError) + // - if <= 0, set to zero and disable notify signal + + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError on creation"); + + audioOutput.setNotifyInterval(0); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(0)"); + QVERIFY2((audioOutput.notifyInterval() == 0), + "notifyInterval() is not zero after setNotifyInterval(0)"); + + audioOutput.setNotifyInterval(-1); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after setNotifyInterval(-1)"); + QVERIFY2((audioOutput.notifyInterval() == 0), + "notifyInterval() is not zero after setNotifyInterval(-1)"); + + //start and run to check if notify() is emitted + if (audioFiles.size() > 0) { + QAudioOutput audioOutputCheck(testFormats.at(0), this); + audioOutputCheck.setNotifyInterval(0); + QSignalSpy notifySignal(&audioOutputCheck, SIGNAL(notify())); + audioFiles.at(0)->open(QIODevice::ReadOnly); + audioOutputCheck.start(audioFiles.at(0)); + QTest::qWait(3000); // 3 seconds should be plenty + audioOutputCheck.stop(); + QVERIFY2((notifySignal.count() == 0), + QString("didn't disable notify interval: shouldn't have got any but got %1").arg(notifySignal.count()).toLocal8Bit().constData()); + audioFiles.at(0)->close(); + } +} + +void tst_QAudioOutput::stopWhileStopped() +{ + // Calls QAudioOutput::stop() when object is already in StoppedState + // Checks that + // - No state change occurs + // - No error is raised (QAudioOutput::error() returns QAudio::NoError) + + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State))); + audioOutput.stop(); + + // Check that no state transition occurred + QVERIFY2((stateSignal.count() == 0), "stop() while stopped is emitting a signal and it shouldn't"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()"); +} + +void tst_QAudioOutput::suspendWhileStopped() +{ + // Calls QAudioOutput::suspend() when object is already in StoppedState + // Checks that + // - No state change occurs + // - No error is raised (QAudioOutput::error() returns QAudio::NoError) + + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State))); + audioOutput.suspend(); + + // Check that no state transition occurred + QVERIFY2((stateSignal.count() == 0), "stop() while suspended is emitting a signal and it shouldn't"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after stop()"); +} + +void tst_QAudioOutput::resumeWhileStopped() +{ + // Calls QAudioOutput::resume() when object is already in StoppedState + // Checks that + // - No state change occurs + // - No error is raised (QAudioOutput::error() returns QAudio::NoError) + + QAudioOutput audioOutput(audioDevice.preferredFormat(), this); + + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "state() was not set to StoppedState before start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError before start()"); + + QSignalSpy stateSignal(&audioOutput, SIGNAL(stateChanged(QAudio::State))); + audioOutput.resume(); + + // Check that no state transition occurred + QVERIFY2((stateSignal.count() == 0), "resume() while stopped is emitting a signal and it shouldn't"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() was not set to QAudio::NoError after resume()"); +} + +void tst_QAudioOutput::pull() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::ReadOnly); + audioFiles.at(i)->seek(WavHeader::headerLength()); + + audioOutput.start(audioFiles.at(i)); + // Check that QAudioOutput immediately transitions to ActiveState + QTRY_VERIFY2((stateSignal.count() == 1), + QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioOutput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + + // Wait until playback finishes + QTest::qWait(3000); // 3 seconds should be plenty + + QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF"); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); + stateSignal.clear(); + + qint64 processedUs = audioOutput.processedUSecs(); + + audioOutput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs == 2000000), + QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + QVERIFY2((notifySignal.count() > 15 && notifySignal.count() < 25), + QString("too many notify() signals emitted (%1)").arg(notifySignal.count()).toLocal8Bit().constData()); + + audioFiles.at(i)->close(); + } +} + +void tst_QAudioOutput::pullSuspendResume() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::ReadOnly); + audioFiles.at(i)->seek(WavHeader::headerLength()); + + audioOutput.start(audioFiles.at(i)); + // Check that QAudioOutput immediately transitions to ActiveState + QTRY_VERIFY2((stateSignal.count() == 1), + QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioOutput.periodSize() > 0); + stateSignal.clear(); + + // Wait for half of clip to play + QTest::qWait(1000); + + audioOutput.suspend(); + + // Give backends running in separate threads a chance to suspend. + QTest::qWait(100); + + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::SuspendedState), "didn't transition to SuspendedState after suspend()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after suspend()"); + stateSignal.clear(); + + // Check that only 'elapsed', and not 'processed' increases while suspended + qint64 elapsedUs = audioOutput.elapsedUSecs(); + qint64 processedUs = audioOutput.processedUSecs(); + QTest::qWait(1000); + QVERIFY(audioOutput.elapsedUSecs() > elapsedUs); + QVERIFY(audioOutput.processedUSecs() == processedUs); + + audioOutput.resume(); + + // Give backends running in separate threads a chance to suspend. + QTest::qWait(100); + + // Check that QAudioOutput immediately transitions to ActiveState + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()"); + stateSignal.clear(); + + // Wait until playback finishes + QTest::qWait(3000); // 3 seconds should be plenty + + QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF"); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); + stateSignal.clear(); + + processedUs = audioOutput.processedUSecs(); + + audioOutput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs == 2000000), + QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + + audioFiles.at(i)->close(); + } +} + +void tst_QAudioOutput::push() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::ReadOnly); + audioFiles.at(i)->seek(WavHeader::headerLength()); + + QIODevice* feed = audioOutput.start(); + + // Check that QAudioOutput immediately transitions to IdleState + QTRY_VERIFY2((stateSignal.count() == 1), + QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioOutput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()"); + + qint64 written = 0; + bool firstBuffer = true; + QByteArray buffer(AUDIO_BUFFER, 0); + + while (written < audioFiles.at(i)->size()-WavHeader::headerLength()) { + + if (audioOutput.bytesFree() >= audioOutput.periodSize()) { + qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize()); + written += feed->write(buffer.constData(), len); + + if (firstBuffer) { + // Check for transition to ActiveState when data is provided + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after receiving data, got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data"); + firstBuffer = false; + } + } else + QTest::qWait(20); + } + stateSignal.clear(); + + // Wait until playback finishes + QTest::qWait(3000); // 3 seconds should be plenty + + QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF"); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); + stateSignal.clear(); + + qint64 processedUs = audioOutput.processedUSecs(); + + audioOutput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs == 2000000), + QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + QVERIFY2((notifySignal.count() > 15 && notifySignal.count() < 25), + QString("too many notify() signals emitted (%1)").arg(notifySignal.count()).toLocal8Bit().constData()); + + audioFiles.at(i)->close(); + } +} + +void tst_QAudioOutput::pushSuspendResume() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::ReadOnly); + audioFiles.at(i)->seek(WavHeader::headerLength()); + + QIODevice* feed = audioOutput.start(); + + // Check that QAudioOutput immediately transitions to IdleState + QTRY_VERIFY2((stateSignal.count() == 1), + QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioOutput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()"); + + qint64 written = 0; + bool firstBuffer = true; + QByteArray buffer(AUDIO_BUFFER, 0); + + // Play half of the clip + while (written < (audioFiles.at(i)->size()-WavHeader::headerLength())/2) { + + if (audioOutput.bytesFree() >= audioOutput.periodSize()) { + qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize()); + written += feed->write(buffer.constData(), len); + + if (firstBuffer) { + // Check for transition to ActiveState when data is provided + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after receiving data, got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data"); + firstBuffer = false; + } + } else + QTest::qWait(20); + } + stateSignal.clear(); + + audioOutput.suspend(); + + // Give backends running in separate threads a chance to suspend. + QTest::qWait(100); + + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit SuspendedState signal after suspend(), got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::SuspendedState), "didn't transition to SuspendedState after suspend()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after suspend()"); + stateSignal.clear(); + + // Check that only 'elapsed', and not 'processed' increases while suspended + qint64 elapsedUs = audioOutput.elapsedUSecs(); + qint64 processedUs = audioOutput.processedUSecs(); + QTest::qWait(1000); + QVERIFY(audioOutput.elapsedUSecs() > elapsedUs); + QVERIFY(audioOutput.processedUSecs() == processedUs); + + audioOutput.resume(); + + // Give backends running in separate threads a chance to suspend. + QTest::qWait(100); + + // Check that QAudioOutput immediately transitions to ActiveState + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after resume()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()"); + stateSignal.clear(); + + // Play rest of the clip + while (!audioFiles.at(i)->atEnd()) { + if (audioOutput.bytesFree() >= audioOutput.periodSize()) { + qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize()); + written += feed->write(buffer.constData(), len); + } else + QTest::qWait(20); + } + stateSignal.clear(); + + // Wait until playback finishes + QTest::qWait(1000); // 1 seconds should be plenty + + QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF"); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); + stateSignal.clear(); + + processedUs = audioOutput.processedUSecs(); + + audioOutput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs == 2000000), + QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + + audioFiles.at(i)->close(); + } +} + +void tst_QAudioOutput::pushUnderrun() +{ + for(int i=0; iclose(); + audioFiles.at(i)->open(QIODevice::ReadOnly); + audioFiles.at(i)->seek(WavHeader::headerLength()); + + QIODevice* feed = audioOutput.start(); + + // Check that QAudioOutput immediately transitions to IdleState + QTRY_VERIFY2((stateSignal.count() == 1), + QString("didn't emit signal on start(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after start()"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after start()"); + QVERIFY(audioOutput.periodSize() > 0); + stateSignal.clear(); + + // Check that 'elapsed' increases + QTest::qWait(40); + QVERIFY2((audioOutput.elapsedUSecs() > 0), "elapsedUSecs() is still zero after start()"); + QVERIFY2((audioOutput.processedUSecs() == qint64(0)), "processedUSecs() is not zero after start()"); + + qint64 written = 0; + bool firstBuffer = true; + QByteArray buffer(AUDIO_BUFFER, 0); + + // Play half of the clip + while (written < (audioFiles.at(i)->size()-WavHeader::headerLength())/2) { + + if (audioOutput.bytesFree() >= audioOutput.periodSize()) { + qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize()); + written += feed->write(buffer.constData(), len); + + if (firstBuffer) { + // Check for transition to ActiveState when data is provided + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after receiving data, got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data"); + firstBuffer = false; + } + } else + QTest::qWait(20); + } + stateSignal.clear(); + + // Wait for data to be played + QTest::qWait(1000); + + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit IdleState signal after suspend(), got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState, no data"); + QVERIFY2((audioOutput.error() == QAudio::UnderrunError), "error state is not equal to QAudio::UnderrunError, no data"); + stateSignal.clear(); + + firstBuffer = true; + // Play rest of the clip + while (!audioFiles.at(i)->atEnd()) { + if (audioOutput.bytesFree() >= audioOutput.periodSize()) { + qint64 len = audioFiles.at(i)->read(buffer.data(),audioOutput.periodSize()); + written += feed->write(buffer.constData(), len); + if (firstBuffer) { + // Check for transition to ActiveState when data is provided + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit signal after receiving data, got %1 signals instead") + .arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::ActiveState), "didn't transition to ActiveState after receiving data"); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after receiving data"); + firstBuffer = false; + } + } else + QTest::qWait(20); + } + stateSignal.clear(); + + // Wait until playback finishes + QTest::qWait(1000); // 1 seconds should be plenty + + QVERIFY2(audioFiles.at(i)->atEnd(), "didn't play to EOF"); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit IdleState signal when at EOF, got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transitions to IdleState when at EOF"); + stateSignal.clear(); + + qint64 processedUs = audioOutput.processedUSecs(); + + audioOutput.stop(); + QTest::qWait(40); + QVERIFY2((stateSignal.count() == 1), + QString("didn't emit StoppedState signal after stop(), got %1 signals instead").arg(stateSignal.count()).toLocal8Bit().constData()); + QVERIFY2((audioOutput.state() == QAudio::StoppedState), "didn't transitions to StoppedState after stop()"); + + QVERIFY2((processedUs == 2000000), + QString("processedUSecs() doesn't equal file duration in us (%1)").arg(processedUs).toLocal8Bit().constData()); + QVERIFY2((audioOutput.error() == QAudio::NoError), "error() is not QAudio::NoError after stop()"); + QVERIFY2((audioOutput.elapsedUSecs() == (qint64)0), "elapsedUSecs() not equal to zero in StoppedState"); + + audioFiles.at(i)->close(); + } +} + +void tst_QAudioOutput::cleanupTestCase() +{ + QFile* file; + + foreach (file, audioFiles) { + file->remove(); + delete file; + } +} + +QTEST_MAIN(tst_QAudioOutput) + +#include "tst_qaudiooutput.moc" diff --git a/tests/auto/qaudiooutput/wavheader.cpp b/tests/auto/qaudiooutput/wavheader.cpp new file mode 100755 index 000000000..26fcd6f98 --- /dev/null +++ b/tests/auto/qaudiooutput/wavheader.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +#include +#include "wavheader.h" + + +struct chunk +{ + char id[4]; + quint32 size; +}; + +struct RIFFHeader +{ + chunk descriptor; // "RIFF" + char type[4]; // "WAVE" +}; + +struct WAVEHeader +{ + chunk descriptor; + quint16 audioFormat; + quint16 numChannels; + quint32 sampleRate; + quint32 byteRate; + quint16 blockAlign; + quint16 bitsPerSample; +}; + +struct DATAHeader +{ + chunk descriptor; +}; + +struct CombinedHeader +{ + RIFFHeader riff; + WAVEHeader wave; + DATAHeader data; +}; + +static const int HeaderLength = sizeof(CombinedHeader); + + +WavHeader::WavHeader(const QAudioFormat &format, qint64 dataLength) + : m_format(format) + , m_dataLength(dataLength) +{ + +} + +bool WavHeader::read(QIODevice &device) +{ + bool result = true; + + if (!device.isSequential()) + result = device.seek(0); + // else, assume that current position is the start of the header + + if (result) { + CombinedHeader header; + result = (device.read(reinterpret_cast(&header), HeaderLength) == HeaderLength); + if (result) { + if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 + || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) + && memcmp(&header.riff.type, "WAVE", 4) == 0 + && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 + && header.wave.audioFormat == 1 // PCM + ) { + if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) + m_format.setByteOrder(QAudioFormat::LittleEndian); + else + m_format.setByteOrder(QAudioFormat::BigEndian); + + m_format.setChannels(qFromLittleEndian(header.wave.numChannels)); + m_format.setCodec("audio/pcm"); + m_format.setFrequency(qFromLittleEndian(header.wave.sampleRate)); + m_format.setSampleSize(qFromLittleEndian(header.wave.bitsPerSample)); + + switch(header.wave.bitsPerSample) { + case 8: + m_format.setSampleType(QAudioFormat::UnSignedInt); + break; + case 16: + m_format.setSampleType(QAudioFormat::SignedInt); + break; + default: + result = false; + } + + m_dataLength = device.size() - HeaderLength; + } else { + result = false; + } + } + } + + return result; +} + +bool WavHeader::write(QIODevice &device) +{ + CombinedHeader header; + + memset(&header, 0, HeaderLength); + + // RIFF header + if (m_format.byteOrder() == QAudioFormat::LittleEndian) + memcpy(header.riff.descriptor.id,"RIFF",4); + else + memcpy(header.riff.descriptor.id,"RIFX",4); + qToLittleEndian(quint32(m_dataLength + HeaderLength - 8), + reinterpret_cast(&header.riff.descriptor.size)); + memcpy(header.riff.type, "WAVE",4); + + // WAVE header + memcpy(header.wave.descriptor.id,"fmt ",4); + qToLittleEndian(quint32(16), + reinterpret_cast(&header.wave.descriptor.size)); + qToLittleEndian(quint16(1), + reinterpret_cast(&header.wave.audioFormat)); + qToLittleEndian(quint16(m_format.channels()), + reinterpret_cast(&header.wave.numChannels)); + qToLittleEndian(quint32(m_format.frequency()), + reinterpret_cast(&header.wave.sampleRate)); + qToLittleEndian(quint32(m_format.frequency() * m_format.channels() * m_format.sampleSize() / 8), + reinterpret_cast(&header.wave.byteRate)); + qToLittleEndian(quint16(m_format.channels() * m_format.sampleSize() / 8), + reinterpret_cast(&header.wave.blockAlign)); + qToLittleEndian(quint16(m_format.sampleSize()), + reinterpret_cast(&header.wave.bitsPerSample)); + + // DATA header + memcpy(header.data.descriptor.id,"data",4); + qToLittleEndian(quint32(m_dataLength), + reinterpret_cast(&header.data.descriptor.size)); + + return (device.write(reinterpret_cast(&header), HeaderLength) == HeaderLength); +} + +const QAudioFormat& WavHeader::format() const +{ + return m_format; +} + +qint64 WavHeader::dataLength() const +{ + return m_dataLength; +} + +qint64 WavHeader::headerLength() +{ + return HeaderLength; +} + +bool WavHeader::writeDataLength(QIODevice &device, qint64 dataLength) +{ + bool result = false; + if (!device.isSequential()) { + device.seek(40); + unsigned char dataLengthLE[4]; + qToLittleEndian(quint32(dataLength), dataLengthLE); + result = (device.write(reinterpret_cast(dataLengthLE), 4) == 4); + } + return result; +} diff --git a/tests/auto/qaudiooutput/wavheader.h b/tests/auto/qaudiooutput/wavheader.h new file mode 100755 index 000000000..5212eca67 --- /dev/null +++ b/tests/auto/qaudiooutput/wavheader.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + + +#ifndef WAVHEADER_H +#define WAVHEADER_H + +#include +#include +#include + +/** + * Helper class for parsing WAV file headers. + * + * See https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ + */ +class WavHeader +{ +public: + WavHeader(const QAudioFormat &format = QAudioFormat(), + qint64 dataLength = 0); + + // Reads WAV header and seeks to start of data + bool read(QIODevice &device); + + // Writes WAV header + bool write(QIODevice &device); + + const QAudioFormat& format() const; + qint64 dataLength() const; + + static qint64 headerLength(); + + static bool writeDataLength(QIODevice &device, qint64 dataLength); + +private: + QAudioFormat m_format; + qint64 m_dataLength; +}; + +#endif + diff --git a/tests/auto/qcamera/qcamera.pro b/tests/auto/qcamera/qcamera.pro new file mode 100644 index 000000000..6ebbe3182 --- /dev/null +++ b/tests/auto/qcamera/qcamera.pro @@ -0,0 +1,15 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qcamera +# CONFIG += testcase + +SOURCES += tst_qcamera.cpp + +symbian { + TARGET.CAPABILITY = ALL -TCB + TARGET.EPOCHEAPSIZE = 0x20000 0x3000000 +} + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qcamera/tst_qcamera.cpp b/tests/auto/qcamera/tst_qcamera.cpp new file mode 100644 index 000000000..010309a0d --- /dev/null +++ b/tests/auto/qcamera/tst_qcamera.cpp @@ -0,0 +1,2012 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE +class MockCaptureControl; + +Q_DECLARE_METATYPE(QtMultimediaKit::MetaData) + +class MockCameraControl : public QCameraControl +{ + friend class MockCaptureControl; + Q_OBJECT +public: + MockCameraControl(QObject *parent = 0): + QCameraControl(parent), + m_state(QCamera::UnloadedState), + m_captureMode(QCamera::CaptureStillImage), + m_status(QCamera::UnloadedStatus), + m_propertyChangesSupported(false) + { + } + + ~MockCameraControl() {} + + void start() { m_state = QCamera::ActiveState; } + virtual void stop() { m_state = QCamera::UnloadedState; } + QCamera::State state() const { return m_state; } + void setState(QCamera::State state) { + if (m_state != state) { + m_state = state; + + switch (state) { + case QCamera::UnloadedState: + m_status = QCamera::UnloadedStatus; + break; + case QCamera::LoadedState: + m_status = QCamera::LoadedStatus; + break; + case QCamera::ActiveState: + m_status = QCamera::ActiveStatus; + break; + default: + emit error(QCamera::NotSupportedFeatureError, "State not supported."); + return; + } + + emit stateChanged(m_state); + emit statusChanged(m_status); + } + } + + QCamera::Status status() const { return m_status; } + + QCamera::CaptureMode captureMode() const { return m_captureMode; } + void setCaptureMode(QCamera::CaptureMode mode) + { + if (m_captureMode != mode) { + if (m_state == QCamera::ActiveState) + QVERIFY(m_propertyChangesSupported); + m_captureMode = mode; + emit captureModeChanged(mode); + } + } + + bool isCaptureModeSupported(QCamera::CaptureMode mode) const + { + return mode == QCamera::CaptureStillImage || mode == QCamera::CaptureVideo; + } + + QCamera::LockTypes supportedLocks() const + { + return QCamera::LockExposure | QCamera::LockFocus | QCamera::LockWhiteBalance; + } + + bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const + { + Q_UNUSED(changeType); + Q_UNUSED(status); + return m_propertyChangesSupported; + } + + QCamera::State m_state; + QCamera::CaptureMode m_captureMode; + QCamera::Status m_status; + bool m_propertyChangesSupported; +}; + + +class MockCameraLocksControl : public QCameraLocksControl +{ + Q_OBJECT +public: + MockCameraLocksControl(QObject *parent = 0): + QCameraLocksControl(parent), + m_focusLock(QCamera::Unlocked), + m_exposureLock(QCamera::Unlocked) + { + } + + ~MockCameraLocksControl() {} + + QCamera::LockTypes supportedLocks() const + { + return QCamera::LockExposure | QCamera::LockFocus; + } + + QCamera::LockStatus lockStatus(QCamera::LockType lock) const + { + switch (lock) { + case QCamera::LockExposure: + return m_exposureLock; + case QCamera::LockFocus: + return m_focusLock; + default: + return QCamera::Unlocked; + } + } + + void searchAndLock(QCamera::LockTypes locks) + { + if (locks & QCamera::LockExposure) { + QCamera::LockStatus newStatus = locks & QCamera::LockFocus ? QCamera::Searching : QCamera::Locked; + + if (newStatus != m_exposureLock) + emit lockStatusChanged(QCamera::LockExposure, + m_exposureLock = newStatus, + QCamera::UserRequest); + } + + if (locks & QCamera::LockFocus) { + emit lockStatusChanged(QCamera::LockFocus, + m_focusLock = QCamera::Searching, + QCamera::UserRequest); + + QTimer::singleShot(5, this, SLOT(focused())); + } + } + + void unlock(QCamera::LockTypes locks) { + if (locks & QCamera::LockFocus && m_focusLock != QCamera::Unlocked) { + emit lockStatusChanged(QCamera::LockFocus, + m_focusLock = QCamera::Unlocked, + QCamera::UserRequest); + } + + if (locks & QCamera::LockExposure && m_exposureLock != QCamera::Unlocked) { + emit lockStatusChanged(QCamera::LockExposure, + m_exposureLock = QCamera::Unlocked, + QCamera::UserRequest); + } + } + +private slots: + void focused() + { + if (m_focusLock == QCamera::Searching) { + emit lockStatusChanged(QCamera::LockFocus, + m_focusLock = QCamera::Locked, + QCamera::UserRequest); + } + + if (m_exposureLock == QCamera::Searching) { + emit lockStatusChanged(QCamera::LockExposure, + m_exposureLock = QCamera::Locked, + QCamera::UserRequest); + } + } + + +private: + QCamera::LockStatus m_focusLock; + QCamera::LockStatus m_exposureLock; +}; + +class MockCaptureControl : public QCameraImageCaptureControl +{ + Q_OBJECT +public: + MockCaptureControl(MockCameraControl *cameraControl, QObject *parent = 0) + :QCameraImageCaptureControl(parent), m_cameraControl(cameraControl), m_captureRequest(0), m_ready(true), m_captureCanceled(false) + { + } + + ~MockCaptureControl() + { + } + + QCameraImageCapture::DriveMode driveMode() const { return QCameraImageCapture::SingleImageCapture; } + void setDriveMode(QCameraImageCapture::DriveMode) {} + + bool isReadyForCapture() const { return m_ready && m_cameraControl->state() == QCamera::ActiveState; } + + int capture(const QString &fileName) + { + if (isReadyForCapture()) { + m_fileName = fileName; + m_captureRequest++; + emit readyForCaptureChanged(m_ready = false); + QTimer::singleShot(5, this, SLOT(captured())); + return m_captureRequest; + } else { + emit error(-1, QCameraImageCapture::NotReadyError, + QLatin1String("Could not capture in stopped state")); + } + + return -1; + } + + void cancelCapture() + { + m_captureCanceled = true; + } + +private Q_SLOTS: + void captured() + { + if (!m_captureCanceled) { + emit imageCaptured(m_captureRequest, QImage()); + + emit imageMetadataAvailable(m_captureRequest, + QtMultimediaKit::FocalLengthIn35mmFilm, + QVariant(50)); + + emit imageMetadataAvailable(m_captureRequest, + QtMultimediaKit::DateTimeOriginal, + QVariant(QDateTime::currentDateTime())); + + emit imageMetadataAvailable(m_captureRequest, + QLatin1String("Answer to the Ultimate Question of Life, the Universe, and Everything"), + QVariant(42)); + } + + if (!m_ready) + emit readyForCaptureChanged(m_ready = true); + + if (!m_captureCanceled) + emit imageSaved(m_captureRequest, m_fileName); + + m_captureCanceled = false; + } + +private: + MockCameraControl *m_cameraControl; + QString m_fileName; + int m_captureRequest; + bool m_ready; + bool m_captureCanceled; +}; + +class MockCaptureDestinationControl : public QCameraCaptureDestinationControl +{ + Q_OBJECT +public: + MockCaptureDestinationControl(QObject *parent = 0): + QCameraCaptureDestinationControl(parent), + m_destination(QCameraImageCapture::CaptureToFile) + { + } + + bool isCaptureDestinationSupported(QCameraImageCapture::CaptureDestinations destination) const + { + return destination == QCameraImageCapture::CaptureToBuffer || + destination == QCameraImageCapture::CaptureToFile; + } + + QCameraImageCapture::CaptureDestinations captureDestination() const + { + return m_destination; + } + + void setCaptureDestination(QCameraImageCapture::CaptureDestinations destination) + { + if (isCaptureDestinationSupported(destination) && destination != m_destination) { + m_destination = destination; + emit captureDestinationChanged(m_destination); + } + } + +private: + QCameraImageCapture::CaptureDestinations m_destination; +}; + +class MockCaptureBufferFormatControl : public QCameraCaptureBufferFormatControl +{ + Q_OBJECT +public: + MockCaptureBufferFormatControl(QObject *parent = 0): + QCameraCaptureBufferFormatControl(parent), + m_format(QVideoFrame::Format_Jpeg) + { + } + + QList supportedBufferFormats() const + { + return QList() + << QVideoFrame::Format_Jpeg + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_AdobeDng; + } + + QVideoFrame::PixelFormat bufferFormat() const + { + return m_format; + } + + void setBufferFormat(QVideoFrame::PixelFormat format) + { + if (format != m_format && supportedBufferFormats().contains(format)) { + m_format = format; + emit bufferFormatChanged(m_format); + } + } + +private: + QVideoFrame::PixelFormat m_format; +}; + +class MockCameraExposureControl : public QCameraExposureControl +{ + Q_OBJECT +public: + MockCameraExposureControl(QObject *parent = 0): + QCameraExposureControl(parent), + m_aperture(2.8), + m_shutterSpeed(0.01), + m_isoSensitivity(100), + m_meteringMode(QCameraExposure::MeteringMatrix), + m_exposureCompensation(0), + m_exposureMode(QCameraExposure::ExposureAuto), + m_flashMode(QCameraExposure::FlashAuto) + { + } + + ~MockCameraExposureControl() {} + + QCameraExposure::FlashModes flashMode() const + { + return m_flashMode; + } + + void setFlashMode(QCameraExposure::FlashModes mode) + { + if (isFlashModeSupported(mode)) { + m_flashMode = mode; + } + } + + bool isFlashModeSupported(QCameraExposure::FlashModes mode) const + { + return mode & (QCameraExposure::FlashAuto | QCameraExposure::FlashOff | QCameraExposure::FlashOn); + } + + bool isFlashReady() const + { + return true; + } + + QCameraExposure::ExposureMode exposureMode() const + { + return m_exposureMode; + } + + void setExposureMode(QCameraExposure::ExposureMode mode) + { + if (isExposureModeSupported(mode)) + m_exposureMode = mode; + } + + bool isExposureModeSupported(QCameraExposure::ExposureMode mode) const + { + return mode == QCameraExposure::ExposureAuto || + mode == QCameraExposure::ExposureManual; + } + + bool isParameterSupported(ExposureParameter parameter) const + { + switch (parameter) { + case QCameraExposureControl::ExposureCompensation: + case QCameraExposureControl::ISO: + case QCameraExposureControl::Aperture: + case QCameraExposureControl::ShutterSpeed: + return true; + default: + return false; + } + } + + QVariant exposureParameter(ExposureParameter parameter) const + { + switch (parameter) { + case QCameraExposureControl::ExposureCompensation: + return QVariant(m_exposureCompensation); + case QCameraExposureControl::ISO: + return QVariant(m_isoSensitivity); + case QCameraExposureControl::Aperture: + return QVariant(m_aperture); + case QCameraExposureControl::ShutterSpeed: + return QVariant(m_shutterSpeed); + default: + return QVariant(); + } + } + + QVariantList supportedParameterRange(ExposureParameter parameter) const + { + QVariantList res; + switch (parameter) { + case QCameraExposureControl::ExposureCompensation: + res << -2.0 << 2.0; + break; + case QCameraExposureControl::ISO: + res << 100 << 200 << 400 << 800; + break; + case QCameraExposureControl::Aperture: + res << 2.8 << 4.0 << 5.6 << 8.0 << 11.0 << 16.0; + break; + case QCameraExposureControl::ShutterSpeed: + res << 0.001 << 0.01 << 0.1 << 1.0; + break; + default: + break; + } + + return res; + } + + ParameterFlags exposureParameterFlags(ExposureParameter parameter) const + { + ParameterFlags res = 0; + switch (parameter) { + case QCameraExposureControl::ExposureCompensation: + case QCameraExposureControl::Aperture: + case QCameraExposureControl::ShutterSpeed: + res |= ContinuousRange; + default: + break; + } + + return res; + } + + bool setExposureParameter(ExposureParameter parameter, const QVariant& value) + { + switch (parameter) { + case QCameraExposureControl::ExposureCompensation: + m_exposureCompensation = qBound(-2.0, value.toReal(), 2.0); + break; + case QCameraExposureControl::ISO: + m_isoSensitivity = 100*qRound(qBound(100, value.toInt(), 800)/100.0); + break; + case QCameraExposureControl::Aperture: + m_aperture = qBound(2.8, value.toReal(), 16.0); + break; + case QCameraExposureControl::ShutterSpeed: + m_shutterSpeed = qBound(0.001, value.toReal(), 1.0); + break; + default: + return false; + } + + return true; + } + + QString extendedParameterName(ExposureParameter) + { + return QString(); + } + + QCameraExposure::MeteringMode meteringMode() const + { + return m_meteringMode; + } + + void setMeteringMode(QCameraExposure::MeteringMode mode) + { + if (isMeteringModeSupported(mode)) + m_meteringMode = mode; + } + + bool isMeteringModeSupported(QCameraExposure::MeteringMode mode) const + { + return mode == QCameraExposure::MeteringAverage + || mode == QCameraExposure::MeteringMatrix; + } + +private: + qreal m_aperture; + qreal m_shutterSpeed; + int m_isoSensitivity; + QCameraExposure::MeteringMode m_meteringMode; + qreal m_exposureCompensation; + QCameraExposure::ExposureMode m_exposureMode; + QCameraExposure::FlashModes m_flashMode; +}; + +class MockCameraFlashControl : public QCameraFlashControl +{ + Q_OBJECT +public: + MockCameraFlashControl(QObject *parent = 0): + QCameraFlashControl(parent), + m_flashMode(QCameraExposure::FlashAuto) + { + } + + ~MockCameraFlashControl() {} + + QCameraExposure::FlashModes flashMode() const + { + return m_flashMode; + } + + void setFlashMode(QCameraExposure::FlashModes mode) + { + if (isFlashModeSupported(mode)) { + m_flashMode = mode; + } + } + + bool isFlashModeSupported(QCameraExposure::FlashModes mode) const + { + return mode & (QCameraExposure::FlashAuto | QCameraExposure::FlashOff | QCameraExposure::FlashOn); + } + + bool isFlashReady() const + { + return true; + } + +private: + QCameraExposure::FlashModes m_flashMode; +}; + + +class MockCameraFocusControl : public QCameraFocusControl +{ + Q_OBJECT +public: + MockCameraFocusControl(QObject *parent = 0): + QCameraFocusControl(parent), + m_opticalZoom(1.0), + m_digitalZoom(1.0), + m_focusMode(QCameraFocus::AutoFocus), + m_focusPointMode(QCameraFocus::FocusPointAuto), + m_focusPoint(0.5, 0.5) + { + } + + ~MockCameraFocusControl() {} + + QCameraFocus::FocusMode focusMode() const + { + return m_focusMode; + } + + void setFocusMode(QCameraFocus::FocusMode mode) + { + if (isFocusModeSupported(mode)) + m_focusMode = mode; + } + + bool isFocusModeSupported(QCameraFocus::FocusMode mode) const + { + return mode == QCameraFocus::AutoFocus || mode == QCameraFocus::ContinuousFocus; + } + + qreal maximumOpticalZoom() const + { + return 3.0; + } + + qreal maximumDigitalZoom() const + { + return 4.0; + } + + qreal opticalZoom() const + { + return m_opticalZoom; + } + + qreal digitalZoom() const + { + return m_digitalZoom; + } + + void zoomTo(qreal optical, qreal digital) + { + optical = qBound(1.0, optical, maximumOpticalZoom()); + digital = qBound(1.0, digital, maximumDigitalZoom()); + + if (!qFuzzyCompare(digital, m_digitalZoom)) { + m_digitalZoom = digital; + emit digitalZoomChanged(m_digitalZoom); + } + + if (!qFuzzyCompare(optical, m_opticalZoom)) { + m_opticalZoom = optical; + emit opticalZoomChanged(m_opticalZoom); + } + } + + QCameraFocus::FocusPointMode focusPointMode() const + { + return m_focusPointMode; + } + + void setFocusPointMode(QCameraFocus::FocusPointMode mode) + { + if (isFocusPointModeSupported(mode)) + m_focusPointMode = mode; + } + + bool isFocusPointModeSupported(QCameraFocus::FocusPointMode mode) const + { + switch (mode) { + case QCameraFocus::FocusPointAuto: + case QCameraFocus::FocusPointCenter: + case QCameraFocus::FocusPointCustom: + return true; + default: + return false; + } + } + + QPointF customFocusPoint() const + { + return m_focusPoint; + } + + void setCustomFocusPoint(const QPointF &point) + { + m_focusPoint = point; + } + + QCameraFocusZoneList focusZones() const { return QCameraFocusZoneList() << QCameraFocusZone(QRectF(0.45, 0.45, 0.1, 0.1)); } + + +private: + qreal m_opticalZoom; + qreal m_digitalZoom; + QCameraFocus::FocusMode m_focusMode; + QCameraFocus::FocusPointMode m_focusPointMode; + QPointF m_focusPoint; +}; + +class MockImageProcessingControl : public QCameraImageProcessingControl +{ + Q_OBJECT +public: + MockImageProcessingControl(QObject *parent = 0) + : QCameraImageProcessingControl(parent) + { + m_supportedWhiteBalance.insert(QCameraImageProcessing::WhiteBalanceAuto); + } + + QCameraImageProcessing::WhiteBalanceMode whiteBalanceMode() const { return m_whiteBalanceMode; } + void setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceMode mode) { m_whiteBalanceMode = mode; } + + bool isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceMode mode) const { + return m_supportedWhiteBalance.contains(mode); } + + void setSupportedWhiteBalanceModes(QSet modes) { + m_supportedWhiteBalance = modes; } + + bool isProcessingParameterSupported(ProcessingParameter parameter) const + { + return parameter == Contrast || parameter == Sharpening || parameter == ColorTemperature; + } + QVariant processingParameter(ProcessingParameter parameter) const + { + switch (parameter) { + case Contrast: + return m_contrast; + case Sharpening: + return m_sharpeningLevel; + case ColorTemperature: + return m_manualWhiteBalance; + default: + return QVariant(); + } + } + void setProcessingParameter(ProcessingParameter parameter, QVariant value) + { + switch (parameter) { + case Contrast: + m_contrast = value; + break; + case Sharpening: + m_sharpeningLevel = value; + break; + case ColorTemperature: + m_manualWhiteBalance = value; + break; + default: + break; + } + } + + +private: + QCameraImageProcessing::WhiteBalanceMode m_whiteBalanceMode; + QSet m_supportedWhiteBalance; + QVariant m_manualWhiteBalance; + QVariant m_contrast; + QVariant m_sharpeningLevel; +}; + +class MockImageEncoderControl : public QImageEncoderControl +{ +public: + MockImageEncoderControl(QObject *parent = 0) + : QImageEncoderControl(parent) + { + } + + QList supportedResolutions(const QImageEncoderSettings & = QImageEncoderSettings(), + bool *continuous = 0) const + { + if (continuous) + *continuous = true; + + return m_supportedResolutions; + } + + void setSupportedResolutions(const QList &resolutions) { + m_supportedResolutions = resolutions; } + + QStringList supportedImageCodecs() const { return m_supportedCodecs; } + void setSupportedImageCodecs(const QStringList &codecs) { m_supportedCodecs = codecs; } + + QString imageCodecDescription(const QString &codecName) const { + return m_codecDescriptions.value(codecName); } + void setImageCodecDescriptions(const QMap &descriptions) { + m_codecDescriptions = descriptions; } + + QImageEncoderSettings imageSettings() const { return m_settings; } + void setImageSettings(const QImageEncoderSettings &settings) { m_settings = settings; } + +private: + QImageEncoderSettings m_settings; + + QList m_supportedResolutions; + QStringList m_supportedCodecs; + QMap m_codecDescriptions; +}; + +class MockVideoSurface : public QAbstractVideoSurface +{ +public: + QList supportedPixelFormats( + const QAbstractVideoBuffer::HandleType) const + { + return QList(); + } + + bool present(const QVideoFrame &) { return false; } +}; + +class MockVideoRendererControl : public QVideoRendererControl +{ +public: + MockVideoRendererControl(QObject *parent) : QVideoRendererControl(parent), m_surface(0) {} + + QAbstractVideoSurface *surface() const { return m_surface; } + void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; } + + QAbstractVideoSurface *m_surface; +}; + +class MockVideoWindowControl : public QVideoWindowControl +{ +public: + MockVideoWindowControl(QObject *parent) : QVideoWindowControl(parent) {} + WId winId() const { return 0; } + void setWinId(WId) {} + QRect displayRect() const { return QRect(); } + void setDisplayRect(const QRect &) {} + bool isFullScreen() const { return false; } + void setFullScreen(bool) {} + void repaint() {} + QSize nativeSize() const { return QSize(); } + Qt::AspectRatioMode aspectRatioMode() const { return Qt::KeepAspectRatio; } + void setAspectRatioMode(Qt::AspectRatioMode) {} + int brightness() const { return 0; } + void setBrightness(int) {} + int contrast() const { return 0; } + void setContrast(int) {} + int hue() const { return 0; } + void setHue(int) {} + int saturation() const { return 0; } + void setSaturation(int) {} +}; + +class MockSimpleCameraService : public QMediaService +{ + Q_OBJECT + +public: + MockSimpleCameraService(): QMediaService(0) + { + mockControl = new MockCameraControl(this); + } + + ~MockSimpleCameraService() + { + } + + QMediaControl* requestControl(const char *iid) + { + if (qstrcmp(iid, QCameraControl_iid) == 0) + return mockControl; + return 0; + } + + void releaseControl(QMediaControl*) {} + + MockCameraControl *mockControl; +}; + +class MockCameraService : public QMediaService +{ + Q_OBJECT + +public: + MockCameraService(): QMediaService(0) + { + mockControl = new MockCameraControl(this); + mockLocksControl = new MockCameraLocksControl(this); + mockExposureControl = new MockCameraExposureControl(this); + mockFlashControl = new MockCameraFlashControl(this); + mockFocusControl = new MockCameraFocusControl(this); + mockCaptureControl = new MockCaptureControl(mockControl, this); + mockCaptureBufferControl = new MockCaptureBufferFormatControl(this); + mockCaptureDestinationControl = new MockCaptureDestinationControl(this); + mockImageProcessingControl = new MockImageProcessingControl(this); + mockImageEncoderControl = new MockImageEncoderControl(this); + rendererControl = new MockVideoRendererControl(this); + windowControl = new MockVideoWindowControl(this); + rendererRef = 0; + windowRef = 0; + } + + ~MockCameraService() + { + } + + QMediaControl* requestControl(const char *iid) + { + if (qstrcmp(iid, QCameraControl_iid) == 0) + return mockControl; + + if (qstrcmp(iid, QCameraLocksControl_iid) == 0) + return mockLocksControl; + + if (qstrcmp(iid, QCameraExposureControl_iid) == 0) + return mockExposureControl; + + if (qstrcmp(iid, QCameraFlashControl_iid) == 0) + return mockFlashControl; + + if (qstrcmp(iid, QCameraFocusControl_iid) == 0) + return mockFocusControl; + + if (qstrcmp(iid, QCameraImageCaptureControl_iid) == 0) + return mockCaptureControl; + + if (qstrcmp(iid, QCameraCaptureBufferFormatControl_iid) == 0) + return mockCaptureBufferControl; + + if (qstrcmp(iid, QCameraCaptureDestinationControl_iid) == 0) + return mockCaptureDestinationControl; + + if (qstrcmp(iid, QCameraImageProcessingControl_iid) == 0) + return mockImageProcessingControl; + + if (qstrcmp(iid, QImageEncoderControl_iid) == 0) + return mockImageEncoderControl; + + if (qstrcmp(iid, QVideoRendererControl_iid) == 0) { + if (rendererRef == 0) { + rendererRef += 1; + return rendererControl; + } + } else if (qstrcmp(iid, QVideoWindowControl_iid) == 0) { + if (windowRef == 0) { + windowRef += 1; + return windowControl; + } + } + return 0; + } + + void releaseControl(QMediaControl *control) + { + if (control == rendererControl) + rendererRef -= 1; + else if (control == windowControl) + windowRef -= 1; + } + + MockCameraControl *mockControl; + MockCameraLocksControl *mockLocksControl; + MockCaptureControl *mockCaptureControl; + MockCaptureBufferFormatControl *mockCaptureBufferControl; + MockCaptureDestinationControl *mockCaptureDestinationControl; + MockCameraExposureControl *mockExposureControl; + MockCameraFlashControl *mockFlashControl; + MockCameraFocusControl *mockFocusControl; + MockImageProcessingControl *mockImageProcessingControl; + MockImageEncoderControl *mockImageEncoderControl; + MockVideoRendererControl *rendererControl; + MockVideoWindowControl *windowControl; + int rendererRef; + int windowRef; +}; + +class MockProvider : public QMediaServiceProvider +{ +public: + QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &) + { + return service; + } + + void releaseService(QMediaService *) {} + + QMediaService *service; +}; + + +class tst_QCamera: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testAvailableDevices(); + void testDeviceDescription(); + void testCtorWithDevice(); + void testSimpleCamera(); + void testSimpleCameraWhiteBalance(); + void testSimpleCameraExposure(); + void testSimpleCameraFocus(); + void testSimpleCameraCapture(); + void testSimpleCameraLock(); + void testSimpleCaptureDestination(); + void testSimpleCaptureFormat(); + + void testCameraWhiteBalance(); + void testCameraExposure(); + void testCameraFocus(); + void testCameraCapture(); + void testCameraCaptureMetadata(); + void testImageSettings(); + void testCameraLock(); + void testCameraLockCancel(); + void testCameraEncodingProperyChange(); + void testCaptureDestination(); + void testCaptureFormat(); + + + void testSetVideoOutput(); + void testSetVideoOutputNoService(); + void testSetVideoOutputNoControl(); + void testSetVideoOutputDestruction(); + + void testEnumDebug(); + +private: + MockSimpleCameraService *mockSimpleCameraService; + MockProvider *provider; +}; + +void tst_QCamera::initTestCase() +{ + provider = new MockProvider; + mockSimpleCameraService = new MockSimpleCameraService; + provider->service = mockSimpleCameraService; + qRegisterMetaType("QtMultimediaKit::MetaData"); +} + +void tst_QCamera::cleanupTestCase() +{ + delete mockSimpleCameraService; + delete provider; +} + +void tst_QCamera::testAvailableDevices() +{ + int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count(); + + QVERIFY(QCamera::availableDevices().count() == deviceCount); +} + +void tst_QCamera::testDeviceDescription() +{ + int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count(); + + if (deviceCount == 0) + QVERIFY(QCamera::deviceDescription(QByteArray("random")).isNull()); + else { + foreach (const QByteArray &device, QCamera::availableDevices()) + QVERIFY(QCamera::deviceDescription(device).length() > 0); + } +} + +void tst_QCamera::testCtorWithDevice() +{ + int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count(); + QCamera *camera = 0; + + if (deviceCount == 0) { + camera = new QCamera("random"); + QVERIFY(camera->error() == QCamera::ServiceMissingError); + } + else { + camera = new QCamera(QCamera::availableDevices().first()); + QVERIFY(camera->error() == QCamera::NoError); + } + + delete camera; +} + +void tst_QCamera::testSimpleCamera() +{ + QCamera camera(0, provider); + QCOMPARE(camera.service(), (QMediaService*)mockSimpleCameraService); + + QCOMPARE(camera.state(), QCamera::UnloadedState); + camera.start(); + QCOMPARE(camera.state(), QCamera::ActiveState); + camera.stop(); + QCOMPARE(camera.state(), QCamera::LoadedState); + camera.unload(); + QCOMPARE(camera.state(), QCamera::UnloadedState); + camera.load(); + QCOMPARE(camera.state(), QCamera::LoadedState); +} + +void tst_QCamera::testSimpleCameraWhiteBalance() +{ + QCamera camera(0, provider); + + //only WhiteBalanceAuto is supported + QVERIFY(!camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceAuto)); + QVERIFY(!camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceCloudy)); + QCOMPARE(camera.imageProcessing()->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceAuto); + camera.imageProcessing()->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceCloudy); + QCOMPARE(camera.imageProcessing()->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceAuto); + QCOMPARE(camera.imageProcessing()->manualWhiteBalance(), 0); + camera.imageProcessing()->setManualWhiteBalance(5000); + QCOMPARE(camera.imageProcessing()->manualWhiteBalance(), 0); +} + +void tst_QCamera::testSimpleCameraExposure() +{ + QCamera camera(0, provider); + QCameraExposure *cameraExposure = camera.exposure(); + QVERIFY(cameraExposure != 0); + + QVERIFY(!cameraExposure->isExposureModeSupported(QCameraExposure::ExposureAuto)); + QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureAuto); + cameraExposure->setExposureMode(QCameraExposure::ExposureManual);//should be ignored + QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureAuto); + + QVERIFY(!cameraExposure->isFlashModeSupported(QCameraExposure::FlashOff)); + QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOff); + QCOMPARE(cameraExposure->isFlashReady(), false); + cameraExposure->setFlashMode(QCameraExposure::FlashOn); + QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOff); + + QVERIFY(!cameraExposure->isMeteringModeSupported(QCameraExposure::MeteringAverage)); + QVERIFY(!cameraExposure->isMeteringModeSupported(QCameraExposure::MeteringSpot)); + QVERIFY(!cameraExposure->isMeteringModeSupported(QCameraExposure::MeteringMatrix)); + QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringMatrix); + cameraExposure->setMeteringMode(QCameraExposure::MeteringSpot); + QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringMatrix); + + QCOMPARE(cameraExposure->exposureCompensation(), 0.0); + cameraExposure->setExposureCompensation(2.0); + QCOMPARE(cameraExposure->exposureCompensation(), 0.0); + + QCOMPARE(cameraExposure->isoSensitivity(), -1); + QVERIFY(cameraExposure->supportedIsoSensitivities().isEmpty()); + cameraExposure->setManualIsoSensitivity(100); + QCOMPARE(cameraExposure->isoSensitivity(), -1); + cameraExposure->setAutoIsoSensitivity(); + QCOMPARE(cameraExposure->isoSensitivity(), -1); + + QVERIFY(cameraExposure->aperture() < 0); + QVERIFY(cameraExposure->supportedApertures().isEmpty()); + cameraExposure->setAutoAperture(); + QVERIFY(cameraExposure->aperture() < 0); + cameraExposure->setManualAperture(5.6); + QVERIFY(cameraExposure->aperture() < 0); + + QVERIFY(cameraExposure->shutterSpeed() < 0); + QVERIFY(cameraExposure->supportedShutterSpeeds().isEmpty()); + cameraExposure->setAutoShutterSpeed(); + QVERIFY(cameraExposure->shutterSpeed() < 0); + cameraExposure->setManualShutterSpeed(1/128.0); + QVERIFY(cameraExposure->shutterSpeed() < 0); +} + +void tst_QCamera::testSimpleCameraFocus() +{ + QCamera camera(0, provider); + + QCameraFocus *cameraFocus = camera.focus(); + QVERIFY(cameraFocus != 0); + + QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::AutoFocus)); + QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::ContinuousFocus)); + QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::InfinityFocus)); + + QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus); + QTest::ignoreMessage(QtWarningMsg, "Focus points mode selection is not supported"); + cameraFocus->setFocusMode(QCameraFocus::ContinuousFocus); + QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus); + + QCOMPARE(cameraFocus->maximumOpticalZoom(), 1.0); + QCOMPARE(cameraFocus->maximumDigitalZoom(), 1.0); + QCOMPARE(cameraFocus->opticalZoom(), 1.0); + QCOMPARE(cameraFocus->digitalZoom(), 1.0); + + QTest::ignoreMessage(QtWarningMsg, "The camera doesn't support zooming."); + cameraFocus->zoomTo(100.0, 100.0); + QCOMPARE(cameraFocus->opticalZoom(), 1.0); + QCOMPARE(cameraFocus->digitalZoom(), 1.0); + + + QVERIFY(!cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointAuto)); + QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointAuto); + + + cameraFocus->setFocusPointMode( QCameraFocus::FocusPointCenter ); + QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointAuto); + + QCOMPARE(cameraFocus->customFocusPoint(), QPointF(0.5, 0.5)); + QTest::ignoreMessage(QtWarningMsg, "Focus points selection is not supported"); + cameraFocus->setCustomFocusPoint(QPointF(1.0, 1.0)); + QCOMPARE(cameraFocus->customFocusPoint(), QPointF(0.5, 0.5)); +} + +void tst_QCamera::testSimpleCameraCapture() +{ + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QVERIFY(!imageCapture.isReadyForCapture()); + QVERIFY(!imageCapture.isAvailable()); + + QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError); + QVERIFY(imageCapture.errorString().isEmpty()); + + QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString))); + imageCapture.capture(QString::fromLatin1("/dev/null")); + QCOMPARE(errorSignal.size(), 1); + QCOMPARE(imageCapture.error(), QCameraImageCapture::NotSupportedFeatureError); + QVERIFY(!imageCapture.errorString().isEmpty()); +} + +void tst_QCamera::testSimpleCameraLock() +{ + QCamera camera(0, provider); + QCOMPARE(camera.lockStatus(), QCamera::Unlocked); + QCOMPARE(camera.lockStatus(QCamera::LockExposure), QCamera::Unlocked); + QCOMPARE(camera.lockStatus(QCamera::LockFocus), QCamera::Unlocked); + QCOMPARE(camera.lockStatus(QCamera::LockWhiteBalance), QCamera::Unlocked); + + QSignalSpy lockedSignal(&camera, SIGNAL(locked())); + QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed())); + QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason))); + + camera.searchAndLock(); + QCOMPARE(camera.lockStatus(), QCamera::Locked); + QCOMPARE(camera.lockStatus(QCamera::LockExposure), QCamera::Locked); + QCOMPARE(camera.lockStatus(QCamera::LockFocus), QCamera::Locked); + QCOMPARE(camera.lockStatus(QCamera::LockWhiteBalance), QCamera::Locked); + QCOMPARE(lockedSignal.count(), 1); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); + + lockedSignal.clear(); + lockFailedSignal.clear(); + lockStatusChangedSignal.clear(); + + camera.unlock(); + QCOMPARE(camera.lockStatus(), QCamera::Unlocked); + QCOMPARE(camera.lockStatus(QCamera::LockExposure), QCamera::Unlocked); + QCOMPARE(camera.lockStatus(QCamera::LockFocus), QCamera::Unlocked); + QCOMPARE(camera.lockStatus(QCamera::LockWhiteBalance), QCamera::Unlocked); + + QCOMPARE(lockedSignal.count(), 0); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); +} + +void tst_QCamera::testSimpleCaptureDestination() +{ + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile)); + QVERIFY(!imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)); + QVERIFY(!imageCapture.isCaptureDestinationSupported( + QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)); + + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile); + imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer); + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile); +} + +void tst_QCamera::testSimpleCaptureFormat() +{ + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Invalid); + QVERIFY(imageCapture.supportedBufferFormats().isEmpty()); + + imageCapture.setBufferFormat(QVideoFrame::Format_AdobeDng); + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Invalid); +} + +void tst_QCamera::testCaptureDestination() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile)); + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)); + QVERIFY(!imageCapture.isCaptureDestinationSupported( + QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)); + + QSignalSpy destinationChangedSignal(&imageCapture, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations))); + + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile); + imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer); + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToBuffer); + QCOMPARE(destinationChangedSignal.size(), 1); + QCOMPARE(destinationChangedSignal.first().first().value(), + QCameraImageCapture::CaptureToBuffer); + + //not supported combination + imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile); + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToBuffer); + QCOMPARE(destinationChangedSignal.size(), 1); +} + +void tst_QCamera::testCaptureFormat() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QSignalSpy formatChangedSignal(&imageCapture, SIGNAL(bufferFormatChanged(QVideoFrame::PixelFormat))); + + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg); + QCOMPARE(imageCapture.supportedBufferFormats().size(), 3); + + imageCapture.setBufferFormat(QVideoFrame::Format_AdobeDng); + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_AdobeDng); + + QCOMPARE(formatChangedSignal.size(), 1); + QCOMPARE(formatChangedSignal.first().first().value(), + QVideoFrame::Format_AdobeDng); + + imageCapture.setBufferFormat(QVideoFrame::Format_Y16); + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_AdobeDng); + + QCOMPARE(formatChangedSignal.size(), 1); +} + + +void tst_QCamera::testCameraCapture() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + + QVERIFY(!imageCapture.isReadyForCapture()); + + QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage))); + QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString))); + + imageCapture.capture(QString::fromLatin1("/dev/null")); + QCOMPARE(capturedSignal.size(), 0); + QCOMPARE(errorSignal.size(), 1); + QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError); + + errorSignal.clear(); + + camera.start(); + QVERIFY(imageCapture.isReadyForCapture()); + QCOMPARE(errorSignal.size(), 0); + + imageCapture.capture(QString::fromLatin1("/dev/null")); + + for (int i=0; i<100 && capturedSignal.isEmpty(); i++) + QTest::qWait(10); + + QCOMPARE(capturedSignal.size(), 1); + QCOMPARE(errorSignal.size(), 0); + QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError); +} + +void tst_QCamera::testCameraCaptureMetadata() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QSignalSpy metadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant))); + QSignalSpy extendedMetadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,QString,QVariant))); + QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); + + camera.start(); + int id = imageCapture.capture(QString::fromLatin1("/dev/null")); + + for (int i=0; i<100 && savedSignal.isEmpty(); i++) + QTest::qWait(10); + + QCOMPARE(savedSignal.size(), 1); + + QCOMPARE(metadataSignal.size(), 2); + + QVariantList metadata = metadataSignal[0]; + QCOMPARE(metadata[0].toInt(), id); + QCOMPARE(metadata[1].value(), QtMultimediaKit::FocalLengthIn35mmFilm); + QCOMPARE(metadata[2].value().toInt(), 50); + + metadata = metadataSignal[1]; + QCOMPARE(metadata[0].toInt(), id); + QCOMPARE(metadata[1].value(), QtMultimediaKit::DateTimeOriginal); + QDateTime captureTime = metadata[2].value().value(); + QVERIFY(qAbs(captureTime.secsTo(QDateTime::currentDateTime()) < 5)); //it should not takes more than 5 seconds for signal to arrive here + + QCOMPARE(extendedMetadataSignal.size(), 1); + metadata = extendedMetadataSignal.first(); + QCOMPARE(metadata[0].toInt(), id); + QCOMPARE(metadata[1].toString(), QLatin1String("Answer to the Ultimate Question of Life, the Universe, and Everything")); + QCOMPARE(metadata[2].value().toInt(), 42); +} + + +void tst_QCamera::testCameraWhiteBalance() +{ + QSet whiteBalanceModes; + whiteBalanceModes << QCameraImageProcessing::WhiteBalanceAuto; + whiteBalanceModes << QCameraImageProcessing::WhiteBalanceFlash; + whiteBalanceModes << QCameraImageProcessing::WhiteBalanceIncandescent; + + MockCameraService service; + service.mockImageProcessingControl->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceFlash); + service.mockImageProcessingControl->setSupportedWhiteBalanceModes(whiteBalanceModes); + service.mockImageProcessingControl->setProcessingParameter( + QCameraImageProcessingControl::ColorTemperature, + QVariant(34)); + + MockProvider provider; + provider.service = &service; + + QCamera camera(0, &provider); + QCameraImageProcessing *cameraImageProcessing = camera.imageProcessing(); + + QCOMPARE(cameraImageProcessing->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceFlash); + QVERIFY(camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceAuto)); + QVERIFY(camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceFlash)); + QVERIFY(camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceIncandescent)); + QVERIFY(!camera.imageProcessing()->isWhiteBalanceModeSupported(QCameraImageProcessing::WhiteBalanceCloudy)); + + cameraImageProcessing->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceIncandescent); + QCOMPARE(cameraImageProcessing->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceIncandescent); + + cameraImageProcessing->setWhiteBalanceMode(QCameraImageProcessing::WhiteBalanceManual); + QCOMPARE(cameraImageProcessing->whiteBalanceMode(), QCameraImageProcessing::WhiteBalanceManual); + QCOMPARE(cameraImageProcessing->manualWhiteBalance(), 34); + + cameraImageProcessing->setManualWhiteBalance(432); + QCOMPARE(cameraImageProcessing->manualWhiteBalance(), 432); +} + +void tst_QCamera::testCameraExposure() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + + QCameraExposure *cameraExposure = camera.exposure(); + QVERIFY(cameraExposure != 0); + + QVERIFY(cameraExposure->isExposureModeSupported(QCameraExposure::ExposureAuto)); + QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureAuto); + cameraExposure->setExposureMode(QCameraExposure::ExposureManual); + QCOMPARE(cameraExposure->exposureMode(), QCameraExposure::ExposureManual); + + QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashAuto); + QCOMPARE(cameraExposure->isFlashReady(), true); + cameraExposure->setFlashMode(QCameraExposure::FlashOn); + QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOn); + + cameraExposure->setFlashMode(QCameraExposure::FlashRedEyeReduction); // not expected to be supported + QCOMPARE(cameraExposure->flashMode(), QCameraExposure::FlashOn); + + QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringMatrix); + cameraExposure->setMeteringMode(QCameraExposure::MeteringAverage); + QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringAverage); + cameraExposure->setMeteringMode(QCameraExposure::MeteringSpot); + QCOMPARE(cameraExposure->meteringMode(), QCameraExposure::MeteringAverage); + + + QCOMPARE(cameraExposure->exposureCompensation(), 0.0); + cameraExposure->setExposureCompensation(2.0); + QCOMPARE(cameraExposure->exposureCompensation(), 2.0); + + int minIso = cameraExposure->supportedIsoSensitivities().first(); + int maxIso = cameraExposure->supportedIsoSensitivities().last(); + QVERIFY(cameraExposure->isoSensitivity() > 0); + QVERIFY(minIso > 0); + QVERIFY(maxIso > 0); + cameraExposure->setManualIsoSensitivity(minIso); + QCOMPARE(cameraExposure->isoSensitivity(), minIso); + cameraExposure->setManualIsoSensitivity(maxIso*10); + QCOMPARE(cameraExposure->isoSensitivity(), maxIso); + cameraExposure->setManualIsoSensitivity(-10); + QCOMPARE(cameraExposure->isoSensitivity(), minIso); + cameraExposure->setAutoIsoSensitivity(); + QCOMPARE(cameraExposure->isoSensitivity(), 100); + + qreal minAperture = cameraExposure->supportedApertures().first(); + qreal maxAperture = cameraExposure->supportedApertures().last(); + QVERIFY(minAperture > 0); + QVERIFY(maxAperture > 0); + QVERIFY(cameraExposure->aperture() >= minAperture); + QVERIFY(cameraExposure->aperture() <= maxAperture); + + cameraExposure->setAutoAperture(); + QVERIFY(cameraExposure->aperture() >= minAperture); + QVERIFY(cameraExposure->aperture() <= maxAperture); + + cameraExposure->setManualAperture(0); + QCOMPARE(cameraExposure->aperture(), minAperture); + + cameraExposure->setManualAperture(10000); + QCOMPARE(cameraExposure->aperture(), maxAperture); + + + qreal minShutterSpeed = cameraExposure->supportedShutterSpeeds().first(); + qreal maxShutterSpeed = cameraExposure->supportedShutterSpeeds().last(); + QVERIFY(minShutterSpeed > 0); + QVERIFY(maxShutterSpeed > 0); + QVERIFY(cameraExposure->shutterSpeed() >= minShutterSpeed); + QVERIFY(cameraExposure->shutterSpeed() <= maxShutterSpeed); + + cameraExposure->setAutoShutterSpeed(); + QVERIFY(cameraExposure->shutterSpeed() >= minShutterSpeed); + QVERIFY(cameraExposure->shutterSpeed() <= maxShutterSpeed); + + cameraExposure->setManualShutterSpeed(0); + QCOMPARE(cameraExposure->shutterSpeed(), minShutterSpeed); + + cameraExposure->setManualShutterSpeed(10000); + QCOMPARE(cameraExposure->shutterSpeed(), maxShutterSpeed); +} + +void tst_QCamera::testCameraFocus() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + + QCameraFocus *cameraFocus = camera.focus(); + QVERIFY(cameraFocus != 0); + + QVERIFY(cameraFocus->isFocusModeSupported(QCameraFocus::AutoFocus)); + QVERIFY(cameraFocus->isFocusModeSupported(QCameraFocus::ContinuousFocus)); + QVERIFY(!cameraFocus->isFocusModeSupported(QCameraFocus::InfinityFocus)); + + QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus); + cameraFocus->setFocusMode(QCameraFocus::ManualFocus); + QCOMPARE(cameraFocus->focusMode(), QCameraFocus::AutoFocus); + cameraFocus->setFocusMode(QCameraFocus::ContinuousFocus); + QCOMPARE(cameraFocus->focusMode(), QCameraFocus::ContinuousFocus); + + QVERIFY(cameraFocus->maximumOpticalZoom() >= 1.0); + QVERIFY(cameraFocus->maximumDigitalZoom() >= 1.0); + QCOMPARE(cameraFocus->opticalZoom(), 1.0); + QCOMPARE(cameraFocus->digitalZoom(), 1.0); + cameraFocus->zoomTo(0.5, 1.0); + QCOMPARE(cameraFocus->opticalZoom(), 1.0); + QCOMPARE(cameraFocus->digitalZoom(), 1.0); + cameraFocus->zoomTo(2.0, 0.5); + QCOMPARE(cameraFocus->opticalZoom(), 2.0); + QCOMPARE(cameraFocus->digitalZoom(), 1.0); + cameraFocus->zoomTo(2.0, 2.5); + QCOMPARE(cameraFocus->opticalZoom(), 2.0); + QCOMPARE(cameraFocus->digitalZoom(), 2.5); + cameraFocus->zoomTo(2000000.0, 1000000.0); + QVERIFY(qFuzzyCompare(cameraFocus->opticalZoom(), cameraFocus->maximumOpticalZoom())); + QVERIFY(qFuzzyCompare(cameraFocus->digitalZoom(), cameraFocus->maximumDigitalZoom())); + + QVERIFY(cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointAuto)); + QVERIFY(cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointCenter)); + QVERIFY(cameraFocus->isFocusPointModeSupported(QCameraFocus::FocusPointCustom)); + QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointAuto); + + cameraFocus->setFocusPointMode( QCameraFocus::FocusPointCenter ); + QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointCenter); + + cameraFocus->setFocusPointMode( QCameraFocus::FocusPointFaceDetection ); + QCOMPARE(cameraFocus->focusPointMode(), QCameraFocus::FocusPointCenter); + + QCOMPARE(cameraFocus->customFocusPoint(), QPointF(0.5, 0.5)); + cameraFocus->setCustomFocusPoint(QPointF(1.0, 1.0)); + QCOMPARE(cameraFocus->customFocusPoint(), QPointF(1.0, 1.0)); +} + +void tst_QCamera::testImageSettings() +{ + QImageEncoderSettings settings; + QVERIFY(settings.isNull()); + QVERIFY(settings == QImageEncoderSettings()); + + QCOMPARE(settings.codec(), QString()); + settings.setCodec(QLatin1String("codecName")); + QCOMPARE(settings.codec(), QLatin1String("codecName")); + QVERIFY(!settings.isNull()); + QVERIFY(settings != QImageEncoderSettings()); + + settings = QImageEncoderSettings(); + QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality); + settings.setQuality(QtMultimediaKit::HighQuality); + QCOMPARE(settings.quality(), QtMultimediaKit::HighQuality); + QVERIFY(!settings.isNull()); + + settings = QImageEncoderSettings(); + QCOMPARE(settings.resolution(), QSize()); + settings.setResolution(QSize(320,240)); + QCOMPARE(settings.resolution(), QSize(320,240)); + settings.setResolution(800,600); + QCOMPARE(settings.resolution(), QSize(800,600)); + QVERIFY(!settings.isNull()); + + settings = QImageEncoderSettings(); + QVERIFY(settings.isNull()); + QCOMPARE(settings.codec(), QString()); + QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality); + QCOMPARE(settings.resolution(), QSize()); + + { + QImageEncoderSettings settings1; + QImageEncoderSettings settings2; + QCOMPARE(settings2, settings1); + + settings2 = settings1; + QCOMPARE(settings2, settings1); + QVERIFY(settings2.isNull()); + + settings1.setQuality(QtMultimediaKit::HighQuality); + + QVERIFY(settings2.isNull()); + QVERIFY(!settings1.isNull()); + QVERIFY(settings1 != settings2); + } + + { + QImageEncoderSettings settings1; + QImageEncoderSettings settings2(settings1); + QCOMPARE(settings2, settings1); + + settings2 = settings1; + QCOMPARE(settings2, settings1); + QVERIFY(settings2.isNull()); + + settings1.setQuality(QtMultimediaKit::HighQuality); + + QVERIFY(settings2.isNull()); + QVERIFY(!settings1.isNull()); + QVERIFY(settings1 != settings2); + } + + QImageEncoderSettings settings1; + QImageEncoderSettings settings2; + + settings1 = QImageEncoderSettings(); + settings1.setResolution(800,600); + settings2 = QImageEncoderSettings(); + settings2.setResolution(QSize(800,600)); + QVERIFY(settings1 == settings2); + settings2.setResolution(QSize(400,300)); + QVERIFY(settings1 != settings2); + + settings1 = QImageEncoderSettings(); + settings1.setCodec("codec1"); + settings2 = QImageEncoderSettings(); + settings2.setCodec("codec1"); + QVERIFY(settings1 == settings2); + settings2.setCodec("codec2"); + QVERIFY(settings1 != settings2); + + settings1 = QImageEncoderSettings(); + settings1.setQuality(QtMultimediaKit::NormalQuality); + settings2 = QImageEncoderSettings(); + settings2.setQuality(QtMultimediaKit::NormalQuality); + QVERIFY(settings1 == settings2); + settings2.setQuality(QtMultimediaKit::LowQuality); + QVERIFY(settings1 != settings2); +} + +void tst_QCamera::testCameraLock() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + + camera.focus()->setFocusMode(QCameraFocus::AutoFocus); + + QCOMPARE(camera.lockStatus(), QCamera::Unlocked); + + QSignalSpy lockedSignal(&camera, SIGNAL(locked())); + QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed())); + QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason))); + + camera.searchAndLock(); + QCOMPARE(camera.lockStatus(), QCamera::Searching); + QCOMPARE(lockedSignal.count(), 0); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); + + lockedSignal.clear(); + lockFailedSignal.clear(); + lockStatusChangedSignal.clear(); + + for (int i=0; i<200 && camera.lockStatus() == QCamera::Searching; i++) + QTest::qWait(10); + + QCOMPARE(camera.lockStatus(), QCamera::Locked); + QCOMPARE(lockedSignal.count(), 1); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); + + lockedSignal.clear(); + lockFailedSignal.clear(); + lockStatusChangedSignal.clear(); + + camera.searchAndLock(); + QCOMPARE(camera.lockStatus(), QCamera::Searching); + QCOMPARE(lockedSignal.count(), 0); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); + + lockedSignal.clear(); + lockFailedSignal.clear(); + lockStatusChangedSignal.clear(); + + camera.unlock(); + QCOMPARE(camera.lockStatus(), QCamera::Unlocked); + QCOMPARE(lockedSignal.count(), 0); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); +} + +void tst_QCamera::testCameraLockCancel() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + + camera.focus()->setFocusMode(QCameraFocus::AutoFocus); + + QCOMPARE(camera.lockStatus(), QCamera::Unlocked); + + QSignalSpy lockedSignal(&camera, SIGNAL(locked())); + QSignalSpy lockFailedSignal(&camera, SIGNAL(lockFailed())); + QSignalSpy lockStatusChangedSignal(&camera, SIGNAL(lockStatusChanged(QCamera::LockStatus, QCamera::LockChangeReason))); + camera.searchAndLock(); + QCOMPARE(camera.lockStatus(), QCamera::Searching); + QCOMPARE(lockedSignal.count(), 0); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); + + lockedSignal.clear(); + lockFailedSignal.clear(); + lockStatusChangedSignal.clear(); + + camera.unlock(); + QCOMPARE(camera.lockStatus(), QCamera::Unlocked); + QCOMPARE(lockedSignal.count(), 0); + QCOMPARE(lockFailedSignal.count(), 0); + QCOMPARE(lockStatusChangedSignal.count(), 1); +} + +void tst_QCamera::testCameraEncodingProperyChange() +{ + MockCameraService service; + provider->service = &service; + QCamera camera(0, provider); + QCameraImageCapture imageCapture(&camera); + + QSignalSpy stateChangedSignal(&camera, SIGNAL(stateChanged(QCamera::State))); + QSignalSpy statusChangedSignal(&camera, SIGNAL(statusChanged(QCamera::Status))); + + camera.start(); + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::ActiveStatus); + + QCOMPARE(stateChangedSignal.count(), 1); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + camera.setCaptureMode(QCamera::CaptureVideo); + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::LoadedStatus); + + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + QTest::qWait(10); + + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + //backens should not be stopped since the capture mode is Video + imageCapture.setEncodingSettings(QImageEncoderSettings()); + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 0); + + camera.setCaptureMode(QCamera::CaptureStillImage); + QTest::qWait(10); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + //the settings change should trigger camera stop/start + imageCapture.setEncodingSettings(QImageEncoderSettings()); + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::LoadedStatus); + + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + QTest::qWait(10); + + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + //the settings change should trigger camera stop/start only once + camera.setCaptureMode(QCamera::CaptureVideo); + camera.setCaptureMode(QCamera::CaptureStillImage); + imageCapture.setEncodingSettings(QImageEncoderSettings()); + imageCapture.setEncodingSettings(QImageEncoderSettings()); + + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::LoadedStatus); + + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + QTest::qWait(10); + + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + //setting the viewfinder should also trigget backend to be restarted: + camera.setViewfinder(new QGraphicsVideoItem()); + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(camera.status(), QCamera::LoadedStatus); + + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 1); + + QTest::qWait(10); + + service.mockControl->m_propertyChangesSupported = true; + //the changes to encoding settings, + //capture mode and encoding parameters should not trigger service restart + stateChangedSignal.clear(); + statusChangedSignal.clear(); + + camera.setCaptureMode(QCamera::CaptureVideo); + camera.setCaptureMode(QCamera::CaptureStillImage); + imageCapture.setEncodingSettings(QImageEncoderSettings()); + imageCapture.setEncodingSettings(QImageEncoderSettings()); + camera.setViewfinder(new QGraphicsVideoItem()); + + QCOMPARE(stateChangedSignal.count(), 0); + QCOMPARE(statusChangedSignal.count(), 0); + +} + +void tst_QCamera::testSetVideoOutput() +{ + QVideoWidget widget; + QGraphicsVideoItem item; + MockVideoSurface surface; + + MockCameraService service; + MockProvider provider; + provider.service = &service; + QCamera camera(0, &provider); + + camera.setViewfinder(&widget); + QVERIFY(widget.mediaObject() == &camera); + + camera.setViewfinder(&item); + QVERIFY(widget.mediaObject() == 0); + QVERIFY(item.mediaObject() == &camera); + + camera.setViewfinder(reinterpret_cast(0)); + QVERIFY(item.mediaObject() == 0); + + camera.setViewfinder(&widget); + QVERIFY(widget.mediaObject() == &camera); + + camera.setViewfinder(reinterpret_cast(0)); + QVERIFY(widget.mediaObject() == 0); + + camera.setViewfinder(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + + camera.setViewfinder(reinterpret_cast(0)); + QVERIFY(service.rendererControl->surface() == 0); + + camera.setViewfinder(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + + camera.setViewfinder(&widget); + QVERIFY(service.rendererControl->surface() == 0); + QVERIFY(widget.mediaObject() == &camera); + + camera.setViewfinder(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + QVERIFY(widget.mediaObject() == 0); +} + + +void tst_QCamera::testSetVideoOutputNoService() +{ + QVideoWidget widget; + QGraphicsVideoItem item; + MockVideoSurface surface; + + MockProvider provider; + provider.service = 0; + QCamera camera(0, &provider); + + camera.setViewfinder(&widget); + QVERIFY(widget.mediaObject() == 0); + + camera.setViewfinder(&item); + QVERIFY(item.mediaObject() == 0); + + camera.setViewfinder(&surface); + // Nothing we can verify here other than it doesn't assert. +} + +void tst_QCamera::testSetVideoOutputNoControl() +{ + QVideoWidget widget; + QGraphicsVideoItem item; + MockVideoSurface surface; + + MockCameraService service; + service.rendererRef = 1; + service.windowRef = 1; + + MockProvider provider; + provider.service = &service; + QCamera camera(0, &provider); + + camera.setViewfinder(&widget); + QVERIFY(widget.mediaObject() == 0); + + camera.setViewfinder(&item); + QVERIFY(item.mediaObject() == 0); + + camera.setViewfinder(&surface); + QVERIFY(service.rendererControl->surface() == 0); +} + +void tst_QCamera::testSetVideoOutputDestruction() +{ + MockVideoSurface surface; + + MockCameraService service; + MockProvider provider; + provider.service = &service; + + { + QCamera camera(0, &provider); + camera.setViewfinder(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + QCOMPARE(service.rendererRef, 1); + } + QVERIFY(service.rendererControl->surface() == 0); + QCOMPARE(service.rendererRef, 0); +} + +void tst_QCamera::testEnumDebug() +{ + QTest::ignoreMessage(QtDebugMsg, "QCamera::ActiveState "); + qDebug() << QCamera::ActiveState; + QTest::ignoreMessage(QtDebugMsg, "QCamera::ActiveStatus "); + qDebug() << QCamera::ActiveStatus; + QTest::ignoreMessage(QtDebugMsg, "QCamera::CaptureVideo "); + qDebug() << QCamera::CaptureVideo; + QTest::ignoreMessage(QtDebugMsg, "QCamera::CameraError "); + qDebug() << QCamera::CameraError; + QTest::ignoreMessage(QtDebugMsg, "QCamera::Unlocked "); + qDebug() << QCamera::Unlocked; + QTest::ignoreMessage(QtDebugMsg, "QCamera::LockAcquired "); + qDebug() << QCamera::LockAcquired; + QTest::ignoreMessage(QtDebugMsg, "QCamera::NoLock "); + qDebug() << QCamera::NoLock; + QTest::ignoreMessage(QtDebugMsg, "QCamera::LockExposure "); + qDebug() << QCamera::LockExposure; +} + +QTEST_MAIN(tst_QCamera) + +#include "tst_qcamera.moc" diff --git a/tests/auto/qcamerabackend/qcamerabackend.pro b/tests/auto/qcamerabackend/qcamerabackend.pro new file mode 100644 index 000000000..80e853d8b --- /dev/null +++ b/tests/auto/qcamerabackend/qcamerabackend.pro @@ -0,0 +1,15 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qcamerabackend +# CONFIG += testcase + +SOURCES += tst_qcamerabackend.cpp + +symbian { + TARGET.CAPABILITY = ALL -TCB + TARGET.EPOCHEAPSIZE = 0x20000 0x3000000 +} + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/qcamerabackend/tst_qcamerabackend.cpp new file mode 100644 index 000000000..3fe3c7520 --- /dev/null +++ b/tests/auto/qcamerabackend/tst_qcamerabackend.cpp @@ -0,0 +1,633 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +// Eventually these will make it into qtestcase.h +// but we might need to tweak the timeout values here. +#ifndef QTRY_COMPARE +#define QTRY_COMPARE(__expr, __expected) \ + do { \ + const int __step = 50; \ + const int __timeout = 10000; \ + if ((__expr) != (__expected)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QCOMPARE(__expr, __expected); \ + } while(0) +#endif + +#ifndef QTRY_VERIFY +#define QTRY_VERIFY(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 10000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY(__expr); \ + } while(0) +#endif + + +#define QTRY_WAIT(code, __expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 10000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + do { code } while(0); \ + QTest::qWait(__step); \ + } \ + } while(0) + + +/* + This is the backend conformance test. + + Since it relies on platform media framework and sound hardware + it may be less stable. +*/ + + +Q_DECLARE_METATYPE(QtMultimediaKit::MetaData) +Q_DECLARE_METATYPE(QVideoFrame) + +class tst_QCameraBackend: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testAvailableDevices(); + void testDeviceDescription(); + void testCtorWithDevice(); + + void testCameraStates(); + void testCaptureMode(); + void testCameraCapture(); + void testCaptureToBuffer(); + void testCameraCaptureMetadata(); + void testExposureCompensation(); + void testExposureMode(); +private: +}; + +void tst_QCameraBackend::initTestCase() +{ + qRegisterMetaType("QtMultimediaKit::MetaData"); + + QCamera camera; + if (!camera.isAvailable()) + QSKIP("Camera is not available", SkipAll); +} + +void tst_QCameraBackend::cleanupTestCase() +{ +} + +void tst_QCameraBackend::testAvailableDevices() +{ + int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count(); + QCOMPARE(QCamera::availableDevices().count(), deviceCount); +} + +void tst_QCameraBackend::testDeviceDescription() +{ + int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count(); + + if (deviceCount == 0) + QVERIFY(QCamera::deviceDescription(QByteArray("random")).isNull()); + else { + foreach (const QByteArray &device, QCamera::availableDevices()) + QVERIFY(QCamera::deviceDescription(device).length() > 0); + } +} + +void tst_QCameraBackend::testCtorWithDevice() +{ + int deviceCount = QMediaServiceProvider::defaultServiceProvider()->devices(QByteArray(Q_MEDIASERVICE_CAMERA)).count(); + QCamera *camera = 0; + + if (deviceCount == 0) { + camera = new QCamera("random"); + QCOMPARE(camera->error(), QCamera::ServiceMissingError); + } + else { + camera = new QCamera(QCamera::availableDevices().first()); + QCOMPARE(camera->error(), QCamera::NoError); + } + + delete camera; +} + +void tst_QCameraBackend::testCameraStates() +{ + QCamera camera; + QCameraImageCapture imageCapture(&camera); + + QSignalSpy errorSignal(&camera, SIGNAL(error(QCamera::Error))); + QSignalSpy stateChangedSignal(&camera, SIGNAL(stateChanged(QCamera::State))); + QSignalSpy statusChangedSignal(&camera, SIGNAL(statusChanged(QCamera::Status))); + + QCOMPARE(camera.state(), QCamera::UnloadedState); + QCOMPARE(camera.status(), QCamera::UnloadedStatus); + + camera.load(); + QCOMPARE(camera.state(), QCamera::LoadedState); + QCOMPARE(stateChangedSignal.count(), 1); + QCOMPARE(stateChangedSignal.last().first().value(), QCamera::LoadedState); + QVERIFY(stateChangedSignal.count() > 0); + + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); + QCOMPARE(statusChangedSignal.last().first().value(), QCamera::LoadedStatus); + + camera.unload(); + QCOMPARE(camera.state(), QCamera::UnloadedState); + QCOMPARE(stateChangedSignal.last().first().value(), QCamera::UnloadedState); + QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus); + QCOMPARE(statusChangedSignal.last().first().value(), QCamera::UnloadedStatus); + + camera.start(); + QCOMPARE(camera.state(), QCamera::ActiveState); + QCOMPARE(stateChangedSignal.last().first().value(), QCamera::ActiveState); + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(statusChangedSignal.last().first().value(), QCamera::ActiveStatus); + + camera.stop(); + QCOMPARE(camera.state(), QCamera::LoadedState); + QCOMPARE(stateChangedSignal.last().first().value(), QCamera::LoadedState); + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); + QCOMPARE(statusChangedSignal.last().first().value(), QCamera::LoadedStatus); + + camera.unload(); + QCOMPARE(camera.state(), QCamera::UnloadedState); + QCOMPARE(stateChangedSignal.last().first().value(), QCamera::UnloadedState); + QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus); + QCOMPARE(statusChangedSignal.last().first().value(), QCamera::UnloadedStatus); + + QCOMPARE(camera.errorString(), QString()); + QCOMPARE(errorSignal.count(), 0); +} + +void tst_QCameraBackend::testCaptureMode() +{ + QCamera camera; + + QSignalSpy errorSignal(&camera, SIGNAL(error(QCamera::Error))); + QSignalSpy stateChangedSignal(&camera, SIGNAL(stateChanged(QCamera::State))); + QSignalSpy captureModeSignal(&camera, SIGNAL(captureModeChanged(QCamera::CaptureMode))); + + QCOMPARE(camera.captureMode(), QCamera::CaptureStillImage); + + if (!camera.isCaptureModeSupported(QCamera::CaptureVideo)) { + camera.setCaptureMode(QCamera::CaptureVideo); + QCOMPARE(camera.captureMode(), QCamera::CaptureStillImage); + QSKIP("Video capture not supported", SkipAll); + } + + camera.setCaptureMode(QCamera::CaptureVideo); + QCOMPARE(camera.captureMode(), QCamera::CaptureVideo); + QTRY_COMPARE(captureModeSignal.size(), 1); + QCOMPARE(captureModeSignal.last().first().value(), QCamera::CaptureVideo); + captureModeSignal.clear(); + + camera.load(); + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); + //capture mode should still be video + QCOMPARE(camera.captureMode(), QCamera::CaptureVideo); + + //it should be possible to switch capture mode in Loaded state + camera.setCaptureMode(QCamera::CaptureStillImage); + QTRY_COMPARE(captureModeSignal.size(), 1); + QCOMPARE(captureModeSignal.last().first().value(), QCamera::CaptureStillImage); + captureModeSignal.clear(); + + camera.setCaptureMode(QCamera::CaptureVideo); + QTRY_COMPARE(captureModeSignal.size(), 1); + QCOMPARE(captureModeSignal.last().first().value(), QCamera::CaptureVideo); + captureModeSignal.clear(); + + camera.start(); + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + //capture mode should still be video + QCOMPARE(camera.captureMode(), QCamera::CaptureVideo); + + stateChangedSignal.clear(); + //it should be possible to switch capture mode in Active state + camera.setCaptureMode(QCamera::CaptureStillImage); + //camera may leave Active status, but should return to Active + QTest::qWait(10); //camera may leave Active status async + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(camera.captureMode(), QCamera::CaptureStillImage); + QVERIFY2(stateChangedSignal.isEmpty(), "camera should not change the state during capture mode changes"); + + QCOMPARE(captureModeSignal.size(), 1); + QCOMPARE(captureModeSignal.last().first().value(), QCamera::CaptureStillImage); + captureModeSignal.clear(); + + camera.setCaptureMode(QCamera::CaptureVideo); + //camera may leave Active status, but should return to Active + QTest::qWait(10); //camera may leave Active status async + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(camera.captureMode(), QCamera::CaptureVideo); + + QVERIFY2(stateChangedSignal.isEmpty(), "camera should not change the state during capture mode changes"); + + QCOMPARE(captureModeSignal.size(), 1); + QCOMPARE(captureModeSignal.last().first().value(), QCamera::CaptureVideo); + captureModeSignal.clear(); + + camera.stop(); + QCOMPARE(camera.captureMode(), QCamera::CaptureVideo); + camera.unload(); + QCOMPARE(camera.captureMode(), QCamera::CaptureVideo); + + QVERIFY2(errorSignal.isEmpty(), QString("Camera error: %1").arg(camera.errorString()).toLocal8Bit()); +} + +void tst_QCameraBackend::testCameraCapture() +{ + QCamera camera; + QCameraImageCapture imageCapture(&camera); + //prevents camera to flash during the test + camera.exposure()->setFlashMode(QCameraExposure::FlashOff); + + QVERIFY(!imageCapture.isReadyForCapture()); + + QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage))); + QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); + QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString))); + + imageCapture.capture(); + QTRY_COMPARE(errorSignal.size(), 1); + QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError); + QCOMPARE(capturedSignal.size(), 0); + errorSignal.clear(); + + camera.start(); + + QTRY_VERIFY(imageCapture.isReadyForCapture()); + QCOMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(errorSignal.size(), 0); + + int id = imageCapture.capture(); + + QTRY_VERIFY(!savedSignal.isEmpty()); + + QCOMPARE(capturedSignal.size(), 1); + QCOMPARE(capturedSignal.last().first().toInt(), id); + QCOMPARE(errorSignal.size(), 0); + QCOMPARE(imageCapture.error(), QCameraImageCapture::NoError); + + QCOMPARE(savedSignal.last().first().toInt(), id); + QString location = savedSignal.last().last().toString(); + QVERIFY(!location.isEmpty()); + QVERIFY(QFileInfo(location).exists()); + QImageReader reader(location); + reader.setScaledSize(QSize(320,240)); + QVERIFY(!reader.read().isNull()); + + QFile(location).remove(); +} + + +void tst_QCameraBackend::testCaptureToBuffer() +{ + QCamera camera; + QCameraImageCapture imageCapture(&camera); + camera.exposure()->setFlashMode(QCameraExposure::FlashOff); + + camera.load(); + +#ifdef Q_WS_MAEMO_6 + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)); +#endif + + if (!imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)) + QSKIP("Buffer capture not supported", SkipAll); + + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); + + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg); + + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToFile)); + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer)); + QVERIFY(imageCapture.isCaptureDestinationSupported( + QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)); + + QSignalSpy destinationChangedSignal(&imageCapture, SIGNAL(captureDestinationChanged(QCameraImageCapture::CaptureDestinations))); + + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToFile); + imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer); + QCOMPARE(imageCapture.captureDestination(), QCameraImageCapture::CaptureToBuffer); + QCOMPARE(destinationChangedSignal.size(), 1); + QCOMPARE(destinationChangedSignal.first().first().value(), + QCameraImageCapture::CaptureToBuffer); + + QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage))); + QSignalSpy imageAvailableSignal(&imageCapture, SIGNAL(imageAvailable(int,QVideoFrame))); + QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); + QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int, QCameraImageCapture::Error,QString))); + + camera.start(); + QTRY_VERIFY(imageCapture.isReadyForCapture()); + + int id = imageCapture.capture(); + QTRY_VERIFY(!imageAvailableSignal.isEmpty()); + + QVERIFY(errorSignal.isEmpty()); + QVERIFY(!capturedSignal.isEmpty()); + QVERIFY(!imageAvailableSignal.isEmpty()); + + QTest::qWait(2000); + QVERIFY(savedSignal.isEmpty()); + + QCOMPARE(capturedSignal.first().first().toInt(), id); + QCOMPARE(imageAvailableSignal.first().first().toInt(), id); + + QVideoFrame frame = imageAvailableSignal.first().last().value(); + QVERIFY(frame.isValid()); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Jpeg); + QVERIFY(!frame.size().isEmpty()); + QVERIFY(frame.map(QAbstractVideoBuffer::ReadOnly)); + QByteArray data((const char *)frame.bits(), frame.mappedBytes()); + frame.unmap(); + frame = QVideoFrame(); + + QVERIFY(!data.isEmpty()); + QBuffer buffer; + buffer.setData(data); + buffer.open(QIODevice::ReadOnly); + QImageReader reader(&buffer, "JPG"); + reader.setScaledSize(QSize(640,480)); + QImage img(reader.read()); + QVERIFY(!img.isNull()); + + capturedSignal.clear(); + imageAvailableSignal.clear(); + savedSignal.clear(); + + //Capture to yuv buffer +#ifdef Q_WS_MAEMO_6 + QVERIFY(imageCapture.supportedBufferFormats().contains(QVideoFrame::Format_UYVY)); +#endif + + if (imageCapture.supportedBufferFormats().contains(QVideoFrame::Format_UYVY)) { + imageCapture.setBufferFormat(QVideoFrame::Format_UYVY); + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_UYVY); + + id = imageCapture.capture(); + QTRY_VERIFY(!imageAvailableSignal.isEmpty()); + + QVERIFY(errorSignal.isEmpty()); + QVERIFY(!capturedSignal.isEmpty()); + QVERIFY(!imageAvailableSignal.isEmpty()); + QVERIFY(savedSignal.isEmpty()); + + QTest::qWait(2000); + QVERIFY(savedSignal.isEmpty()); + + frame = imageAvailableSignal.first().last().value(); + QVERIFY(frame.isValid()); + + qDebug() << frame.pixelFormat(); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_UYVY); + QVERIFY(!frame.size().isEmpty()); + frame = QVideoFrame(); + + capturedSignal.clear(); + imageAvailableSignal.clear(); + savedSignal.clear(); + + imageCapture.setBufferFormat(QVideoFrame::Format_Jpeg); + QCOMPARE(imageCapture.bufferFormat(), QVideoFrame::Format_Jpeg); + } + + //Try to capture to both buffer and file +#ifdef Q_WS_MAEMO_6 + QVERIFY(imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)); +#endif + if (imageCapture.isCaptureDestinationSupported(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile)) { + imageCapture.setCaptureDestination(QCameraImageCapture::CaptureToBuffer | QCameraImageCapture::CaptureToFile); + + int oldId = id; + id = imageCapture.capture(); + QVERIFY(id != oldId); + QTRY_VERIFY(!savedSignal.isEmpty()); + + QVERIFY(errorSignal.isEmpty()); + QVERIFY(!capturedSignal.isEmpty()); + QVERIFY(!imageAvailableSignal.isEmpty()); + QVERIFY(!savedSignal.isEmpty()); + + QCOMPARE(capturedSignal.first().first().toInt(), id); + QCOMPARE(imageAvailableSignal.first().first().toInt(), id); + + frame = imageAvailableSignal.first().last().value(); + QVERIFY(frame.isValid()); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Jpeg); + QVERIFY(!frame.size().isEmpty()); + + QString fileName = savedSignal.first().last().toString(); + QVERIFY(QFileInfo(fileName).exists()); + } +} + +void tst_QCameraBackend::testCameraCaptureMetadata() +{ +#ifndef Q_WS_MAEMO_6 + QSKIP("Capture metadata is supported only on harmattan", SkipAll); +#endif + + QCamera camera; + QCameraImageCapture imageCapture(&camera); + camera.exposure()->setFlashMode(QCameraExposure::FlashOff); + + QSignalSpy metadataSignal(&imageCapture, SIGNAL(imageMetadataAvailable(int,QtMultimediaKit::MetaData,QVariant))); + QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); + + camera.start(); + + QTRY_VERIFY(imageCapture.isReadyForCapture()); + + int id = imageCapture.capture(QString::fromLatin1("/dev/null")); + QTRY_VERIFY(!savedSignal.isEmpty()); + QVERIFY(!metadataSignal.isEmpty()); + QCOMPARE(metadataSignal.first().first().toInt(), id); +} + +void tst_QCameraBackend::testExposureCompensation() +{ +#if !defined(Q_WS_MAEMO_6) && !defined(Q_WS_MAEMO_5) && !defined(Q_OS_SYMBIAN) + QSKIP("Capture exposure parameters are supported only on mobile platforms", SkipAll); +#endif + + QCamera camera; + QCameraExposure *exposure = camera.exposure(); + + QSignalSpy exposureCompensationSignal(exposure, SIGNAL(exposureCompensationChanged(qreal))); + +#ifdef Q_OS_SYMBIAN + // Camera needs to be started, see: QTMOBILITY-1566 + camera.load(); + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); +#endif // Q_OS_SYMBIAN + + //it should be possible to set exposure parameters in Unloaded state + QCOMPARE(exposure->exposureCompensation()+1.0, 1.0); + exposure->setExposureCompensation(1.0); + QCOMPARE(exposure->exposureCompensation(), 1.0); + QTRY_COMPARE(exposureCompensationSignal.count(), 1); + QCOMPARE(exposureCompensationSignal.last().first().toReal(), 1.0); + + //exposureCompensationChanged should not be emitted when value is not changed + exposure->setExposureCompensation(1.0); + QTest::qWait(50); + QCOMPARE(exposureCompensationSignal.count(), 1); + + //exposure compensation should be preserved during load/start + camera.load(); + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); + + QCOMPARE(exposure->exposureCompensation(), 1.0); + + exposureCompensationSignal.clear(); + exposure->setExposureCompensation(-1.0); + QCOMPARE(exposure->exposureCompensation(), -1.0); + QTRY_COMPARE(exposureCompensationSignal.count(), 1); + QCOMPARE(exposureCompensationSignal.last().first().toReal(), -1.0); + + camera.start(); + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + + QCOMPARE(exposure->exposureCompensation(), -1.0); + + exposureCompensationSignal.clear(); + exposure->setExposureCompensation(1.0); + QCOMPARE(exposure->exposureCompensation(), 1.0); + QTRY_COMPARE(exposureCompensationSignal.count(), 1); + QCOMPARE(exposureCompensationSignal.last().first().toReal(), 1.0); +} + +void tst_QCameraBackend::testExposureMode() +{ +#if !defined(Q_WS_MAEMO_6) && !defined(Q_WS_MAEMO_5) && !defined(Q_OS_SYMBIAN) + QSKIP("Capture exposure parameters are supported only on mobile platforms", SkipAll); +#endif + + QCamera camera; + QCameraExposure *exposure = camera.exposure(); + +#ifdef Q_WS_MAEMO_6 + QEXPECT_FAIL("", "Camerabin reports Manual exposure instead of Auto", Continue); +#endif + QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto); + +#ifdef Q_OS_SYMBIAN + // Camera needs to be started, see: QTMOBILITY-1566 + camera.load(); + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); +#endif // Q_OS_SYMBIAN + + // Night + exposure->setExposureMode(QCameraExposure::ExposureNight); + QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureNight); + camera.start(); + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureNight); + + camera.unload(); + QTRY_COMPARE(camera.status(), QCamera::UnloadedStatus); + +#ifdef Q_OS_SYMBIAN + // Camera needs to be started, see: QTMOBILITY-1566 + camera.load(); + QTRY_COMPARE(camera.status(), QCamera::LoadedStatus); +#endif // Q_OS_SYMBIAN + + // Auto + exposure->setExposureMode(QCameraExposure::ExposureAuto); + QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto); + camera.start(); + QTRY_COMPARE(camera.status(), QCamera::ActiveStatus); + QCOMPARE(exposure->exposureMode(), QCameraExposure::ExposureAuto); +} + +QTEST_MAIN(tst_QCameraBackend) + +#include "tst_qcamerabackend.moc" diff --git a/tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro b/tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro new file mode 100644 index 000000000..a7ab28581 --- /dev/null +++ b/tests/auto/qdeclarativeaudio/qdeclarativeaudio.pro @@ -0,0 +1,18 @@ +load(qttest_p4) + +QT += multimediakit-private declarative + +# TARGET = tst_qdeclarativeaudio +# CONFIG += testcase + +HEADERS += \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativeaudio_p.h \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase_p.h \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediametadata_p.h + +SOURCES += \ + tst_qdeclarativeaudio.cpp \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativeaudio.cpp \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase.cpp + +INCLUDEPATH += $$QT.multimediakit.sources/../imports/multimedia diff --git a/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp new file mode 100644 index 000000000..df7025f6f --- /dev/null +++ b/tests/auto/qdeclarativeaudio/tst_qdeclarativeaudio.cpp @@ -0,0 +1,1302 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=plugins/declarative/multimedia + +#include + +#include "qdeclarativeaudio_p.h" +#include "qdeclarativemediametadata_p.h" + +#include +#include +#include +#include + +#include + +class tst_QDeclarativeAudio : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void nullPlayerControl(); + void nullMetaDataControl(); + void nullService(); + + void source(); + void autoLoad(); + void playing(); + void paused(); + void duration(); + void position(); + void volume(); + void muted(); + void bufferProgress(); + void seekable(); + void playbackRate(); + void status(); + void metaData_data(); + void metaData(); + void error(); + void loops(); +}; + +Q_DECLARE_METATYPE(QtMultimediaKit::MetaData); +Q_DECLARE_METATYPE(QDeclarativeAudio::Error); + +class QtTestMediaPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT +public: + QtTestMediaPlayerControl(QObject *parent = 0) + : QMediaPlayerControl(parent) + , m_state(QMediaPlayer::StoppedState) + , m_mediaStatus(QMediaPlayer::NoMedia) + , m_duration(0) + , m_position(0) + , m_playbackRate(1.0) + , m_volume(50) + , m_bufferStatus(0) + , m_muted(false) + , m_audioAvailable(false) + , m_videoAvailable(false) + , m_seekable(false) + { + } + + QMediaPlayer::State state() const { return m_state; } + void updateState(QMediaPlayer::State state) { emit stateChanged(m_state = state); } + + QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; } + void updateMediaStatus(QMediaPlayer::MediaStatus status) { + emit mediaStatusChanged(m_mediaStatus = status); } + void updateMediaStatus(QMediaPlayer::MediaStatus status, QMediaPlayer::State state) + { + m_mediaStatus = status; + m_state = state; + + emit mediaStatusChanged(m_mediaStatus); + emit stateChanged(m_state); + } + + qint64 duration() const { return m_duration; } + void setDuration(qint64 duration) { emit durationChanged(m_duration = duration); } + + qint64 position() const { return m_position; } + void setPosition(qint64 position) { emit positionChanged(m_position = position); } + + int volume() const { return m_volume; } + void setVolume(int volume) { emit volumeChanged(m_volume = volume); } + + bool isMuted() const { return m_muted; } + void setMuted(bool muted) { emit mutedChanged(m_muted = muted); } + + int bufferStatus() const { return m_bufferStatus; } + void setBufferStatus(int status) { emit bufferStatusChanged(m_bufferStatus = status); } + + bool isAudioAvailable() const { return m_audioAvailable; } + void setAudioAvailable(bool available) { + emit audioAvailableChanged(m_audioAvailable = available); } + bool isVideoAvailable() const { return m_videoAvailable; } + void setVideoAvailable(bool available) { + emit videoAvailableChanged(m_videoAvailable = available); } + + bool isSeekable() const { return m_seekable; } + void setSeekable(bool seekable) { emit seekableChanged(m_seekable = seekable); } + + QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); } + + qreal playbackRate() const { return m_playbackRate; } + void setPlaybackRate(qreal rate) { emit playbackRateChanged(m_playbackRate = rate); } + + QMediaContent media() const { return m_media; } + const QIODevice *mediaStream() const { return 0; } + void setMedia(const QMediaContent &media, QIODevice *) + { + m_media = media; + + m_mediaStatus = m_media.isNull() + ? QMediaPlayer::NoMedia + : QMediaPlayer::LoadingMedia; + + emit mediaChanged(m_media); + emit mediaStatusChanged(m_mediaStatus); + } + + void play() + { + m_state = QMediaPlayer::PlayingState; + if (m_mediaStatus == QMediaPlayer::EndOfMedia) + updateMediaStatus(QMediaPlayer::LoadedMedia); + emit stateChanged(m_state); + } + void pause() { emit stateChanged(m_state = QMediaPlayer::PausedState); } + void stop() { emit stateChanged(m_state = QMediaPlayer::StoppedState); } + + void emitError(QMediaPlayer::Error err, const QString &errorString) { + emit error(err, errorString); } + +private: + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_mediaStatus; + qint64 m_duration; + qint64 m_position; + qreal m_playbackRate; + int m_volume; + int m_bufferStatus; + bool m_muted; + bool m_audioAvailable; + bool m_videoAvailable; + bool m_seekable; + QMediaContent m_media; +}; + +class QtTestMetaDataControl : public QMetaDataReaderControl +{ + Q_OBJECT +public: + QtTestMetaDataControl(QObject *parent = 0) + : QMetaDataReaderControl(parent) + { + } + + bool isMetaDataAvailable() const { return true; } + + QVariant metaData(QtMultimediaKit::MetaData key) const { return m_metaData.value(key); } + void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value) { + m_metaData.insert(key, value); emit metaDataChanged(); } + + QList availableMetaData() const { return m_metaData.keys(); } + + QVariant extendedMetaData(const QString &) const { return QVariant(); } + QStringList availableExtendedMetaData() const { return QStringList(); } + +private: + QMap m_metaData; +}; + +class QtTestMediaService : public QMediaService +{ + Q_OBJECT +public: + QtTestMediaService( + QtTestMediaPlayerControl *playerControl, + QtTestMetaDataControl *metaDataControl, + QObject *parent) + : QMediaService(parent) + , playerControl(playerControl) + , metaDataControl(metaDataControl) + { + } + + QMediaControl *requestControl(const char *name) + { + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return playerControl; + else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) + return metaDataControl; + else + return 0; + } + + void releaseControl(QMediaControl *) {} + + QtTestMediaPlayerControl *playerControl; + QtTestMetaDataControl *metaDataControl; +}; + +class QtTestMediaServiceProvider : public QMediaServiceProvider +{ + Q_OBJECT +public: + QtTestMediaServiceProvider() + : service(new QtTestMediaService( + new QtTestMediaPlayerControl(this), new QtTestMetaDataControl(this), this)) + { + setDefaultServiceProvider(this); + } + + QtTestMediaServiceProvider(QtTestMediaService *service) + : service(service) + { + setDefaultServiceProvider(this); + } + + QtTestMediaServiceProvider( + QtTestMediaPlayerControl *playerControl, QtTestMetaDataControl *metaDataControl) + : service(new QtTestMediaService(playerControl, metaDataControl, this)) + { + setDefaultServiceProvider(this); + } + + ~QtTestMediaServiceProvider() + { + setDefaultServiceProvider(0); + } + + QMediaService *requestService( + const QByteArray &type, + const QMediaServiceProviderHint & = QMediaServiceProviderHint()) + { + requestedService = type; + + return service; + } + + void releaseService(QMediaService *) {} + + inline QtTestMediaPlayerControl *playerControl() { return service->playerControl; } + inline QtTestMetaDataControl *metaDataControl() { return service->metaDataControl; } + + QtTestMediaService *service; + QByteArray requestedService; +}; + +void tst_QDeclarativeAudio::initTestCase() +{ + qRegisterMetaType(); +} + +void tst_QDeclarativeAudio::nullPlayerControl() +{ + QtTestMetaDataControl metaDataControl; + QtTestMediaServiceProvider provider(0, &metaDataControl); + + QDeclarativeAudio audio; + audio.classBegin(); + + QCOMPARE(audio.source(), QUrl()); + audio.setSource(QUrl("http://example.com")); + QCOMPARE(audio.source(), QUrl("http://example.com")); + + QCOMPARE(audio.isPlaying(), false); + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + audio.setPlaying(false); + audio.play(); + QCOMPARE(audio.isPlaying(), false); + + QCOMPARE(audio.isPaused(), false); + audio.pause(); + QCOMPARE(audio.isPaused(), false); + audio.setPaused(true); + QCOMPARE(audio.isPaused(), true); + + QCOMPARE(audio.duration(), 0); + + QCOMPARE(audio.position(), 0); + audio.setPosition(10000); + QCOMPARE(audio.position(), 10000); + + 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(), true); + + QCOMPARE(audio.bufferProgress(), qreal(0)); + + QCOMPARE(audio.isSeekable(), false); + + QCOMPARE(audio.playbackRate(), qreal(1.0)); + + QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia); + + QCOMPARE(audio.error(), QDeclarativeAudio::ServiceMissing); +} + +void tst_QDeclarativeAudio::nullMetaDataControl() +{ + QtTestMediaPlayerControl playerControl; + QtTestMediaServiceProvider provider(&playerControl, 0); + + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QVERIFY(audio.metaData()); +} + +void tst_QDeclarativeAudio::nullService() +{ + QtTestMediaServiceProvider provider(0); + + QDeclarativeAudio audio; + audio.classBegin(); + + QCOMPARE(audio.source(), QUrl()); + audio.setSource(QUrl("http://example.com")); + QCOMPARE(audio.source(), QUrl("http://example.com")); + + QCOMPARE(audio.isPlaying(), false); + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + audio.setPlaying(false); + audio.play(); + QCOMPARE(audio.isPlaying(), false); + + QCOMPARE(audio.isPaused(), false); + audio.pause(); + QCOMPARE(audio.isPaused(), false); + audio.setPaused(true); + QCOMPARE(audio.isPaused(), true); + + QCOMPARE(audio.duration(), 0); + + QCOMPARE(audio.position(), 0); + audio.setPosition(10000); + QCOMPARE(audio.position(), 10000); + + 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(), true); + + QCOMPARE(audio.bufferProgress(), qreal(0)); + + QCOMPARE(audio.isSeekable(), false); + + QCOMPARE(audio.playbackRate(), qreal(1.0)); + + QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia); + + QCOMPARE(audio.error(), QDeclarativeAudio::ServiceMissing); + + QVERIFY(audio.metaData()); +} + +void tst_QDeclarativeAudio::source() +{ + const QUrl url1("http://example.com"); + const QUrl url2("file:///local/path"); + const QUrl url3; + + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(sourceChanged())); + + audio.setSource(url1); + QCOMPARE(audio.source(), url1); + QCOMPARE(provider.playerControl()->media().canonicalUrl(), url1); + QCOMPARE(spy.count(), 1); + + audio.setSource(url2); + QCOMPARE(audio.source(), url2); + QCOMPARE(provider.playerControl()->media().canonicalUrl(), url2); + QCOMPARE(spy.count(), 2); + + audio.setSource(url3); + QCOMPARE(audio.source(), url3); + QCOMPARE(provider.playerControl()->media().canonicalUrl(), url3); + QCOMPARE(spy.count(), 3); +} + +void tst_QDeclarativeAudio::autoLoad() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + 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_QDeclarativeAudio::playing() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + + QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged())); + QSignalSpy startedSpy(&audio, SIGNAL(started())); + QSignalSpy stoppedSpy(&audio, SIGNAL(stopped())); + + int playingChanged = 0; + int started = 0; + int stopped = 0; + + audio.componentComplete(); + audio.setSource(QUrl("http://example.com")); + + QCOMPARE(audio.isPlaying(), false); + + // setPlaying(true) when stopped. + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when playing. + audio.setPlaying(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // play() when stopped. + audio.play(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(stoppedSpy.count(), stopped); + + // stop() when playing. + audio.stop(); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // stop() when stopped. + audio.stop(); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when stopped. + audio.setPlaying(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); + + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(true) when playing. + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); + + // play() when playing. + audio.play(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); +} + +void tst_QDeclarativeAudio::paused() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + + QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged())); + QSignalSpy pausedChangedSpy(&audio, SIGNAL(pausedChanged())); + QSignalSpy startedSpy(&audio, SIGNAL(started())); + QSignalSpy pausedSpy(&audio, SIGNAL(paused())); + QSignalSpy resumedSpy(&audio, SIGNAL(resumed())); + QSignalSpy stoppedSpy(&audio, SIGNAL(stopped())); + + int playingChanged = 0; + int pausedChanged = 0; + int started = 0; + int paused = 0; + int resumed = 0; + int stopped = 0; + + audio.componentComplete(); + audio.setSource(QUrl("http://example.com")); + + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), false); + + // setPlaying(true) when stopped. + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when playing. + audio.setPaused(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when paused. + audio.setPaused(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // pause() when paused. + audio.pause(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(false) when paused. + audio.setPaused(false); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), ++resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(false) when playing. + audio.setPaused(false); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // pause() when playing. + audio.pause(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when paused. + audio.setPlaying(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // setPaused(true) when stopped and paused. + audio.setPaused(true); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(false) when stopped and paused. + audio.setPaused(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when stopped. + audio.setPaused(true); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(true) when stopped and paused. + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // play() when paused. + audio.play(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), ++resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when playing. + audio.setPaused(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // stop() when paused. + audio.stop(); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // setPaused(true) when stopped. + audio.setPaused(true); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // stop() when stopped and paused. + audio.stop(); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // pause() when stopped. + audio.pause(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when paused. + audio.setPlaying(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // pause() when stopped and paused. + audio.pause(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when paused. + audio.setPlaying(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(audio.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // play() when stopped and paused. + audio.play(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(audio.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); +} + +void tst_QDeclarativeAudio::duration() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(durationChanged())); + + QCOMPARE(audio.duration(), 0); + + provider.playerControl()->setDuration(4040); + QCOMPARE(audio.duration(), 4040); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setDuration(-129); + QCOMPARE(audio.duration(), -129); + QCOMPARE(spy.count(), 2); + + provider.playerControl()->setDuration(0); + QCOMPARE(audio.duration(), 0); + QCOMPARE(spy.count(), 3); + + // Unnecessary duration changed signals aren't filtered. + provider.playerControl()->setDuration(0); + QCOMPARE(audio.duration(), 0); + QCOMPARE(spy.count(), 4); +} + +void tst_QDeclarativeAudio::position() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(positionChanged())); + + QCOMPARE(audio.position(), 0); + + // QDeclarativeAudio won't bound set positions to the duration. A media service may though. + QCOMPARE(audio.duration(), 0); + + audio.setPosition(450); + QCOMPARE(audio.position(), 450); + QCOMPARE(provider.playerControl()->position(), qint64(450)); + QCOMPARE(spy.count(), 1); + + audio.setPosition(-5403); + QCOMPARE(audio.position(), -5403); + QCOMPARE(provider.playerControl()->position(), qint64(-5403)); + QCOMPARE(spy.count(), 2); + + audio.setPosition(-5403); + QCOMPARE(audio.position(), -5403); + QCOMPARE(provider.playerControl()->position(), qint64(-5403)); + 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(), 3); + + connect(&audio, SIGNAL(positionChanged()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + provider.playerControl()->updateState(QMediaPlayer::PlayingState); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5 + + provider.playerControl()->updateState(QMediaPlayer::PausedState); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(spy.count() < 6); +} + +void tst_QDeclarativeAudio::volume() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(volumeChanged())); + + QCOMPARE(audio.volume(), qreal(1.0)); + + audio.setVolume(0.7); + QCOMPARE(audio.volume(), qreal(0.7)); + QCOMPARE(provider.playerControl()->volume(), 70); + QCOMPARE(spy.count(), 1); + + audio.setVolume(0.7); + QCOMPARE(audio.volume(), qreal(0.7)); + QCOMPARE(provider.playerControl()->volume(), 70); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setVolume(30); + QCOMPARE(audio.volume(), qreal(0.3)); + QCOMPARE(spy.count(), 2); +} + +void tst_QDeclarativeAudio::muted() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(mutedChanged())); + + QCOMPARE(audio.isMuted(), false); + + audio.setMuted(true); + QCOMPARE(audio.isMuted(), true); + QCOMPARE(provider.playerControl()->isMuted(), true); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setMuted(false); + QCOMPARE(audio.isMuted(), false); + QCOMPARE(spy.count(), 2); + + audio.setMuted(false); + QCOMPARE(audio.isMuted(), false); + QCOMPARE(provider.playerControl()->isMuted(), false); + QCOMPARE(spy.count(), 3); +} + +void tst_QDeclarativeAudio::bufferProgress() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(bufferProgressChanged())); + + QCOMPARE(audio.bufferProgress(), qreal(0.0)); + + provider.playerControl()->setBufferStatus(20); + QCOMPARE(audio.bufferProgress(), qreal(0.2)); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setBufferStatus(20); + QCOMPARE(audio.bufferProgress(), qreal(0.2)); + QCOMPARE(spy.count(), 2); + + provider.playerControl()->setBufferStatus(40); + QCOMPARE(audio.bufferProgress(), qreal(0.4)); + QCOMPARE(spy.count(), 3); + + connect(&audio, SIGNAL(positionChanged()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + provider.playerControl()->updateMediaStatus( + QMediaPlayer::BufferingMedia, QMediaPlayer::PlayingState); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5 + + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(spy.count() < 6); +} + +void tst_QDeclarativeAudio::seekable() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(seekableChanged())); + + QCOMPARE(audio.isSeekable(), false); + + provider.playerControl()->setSeekable(true); + QCOMPARE(audio.isSeekable(), true); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setSeekable(true); + QCOMPARE(audio.isSeekable(), true); + QCOMPARE(spy.count(), 2); + + provider.playerControl()->setSeekable(false); + QCOMPARE(audio.isSeekable(), false); + QCOMPARE(spy.count(), 3); +} + +void tst_QDeclarativeAudio::playbackRate() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(&audio, SIGNAL(playbackRateChanged())); + + QCOMPARE(audio.playbackRate(), qreal(1.0)); + + audio.setPlaybackRate(0.5); + QCOMPARE(audio.playbackRate(), qreal(0.5)); + QCOMPARE(provider.playerControl()->playbackRate(), qreal(0.5)); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setPlaybackRate(2.0); + QCOMPARE(provider.playerControl()->playbackRate(), qreal(2.0)); + QCOMPARE(spy.count(), 2); + + audio.setPlaybackRate(2.0); + QCOMPARE(audio.playbackRate(), qreal(2.0)); + QCOMPARE(provider.playerControl()->playbackRate(), qreal(2.0)); + QCOMPARE(spy.count(), 3); +} + +void tst_QDeclarativeAudio::status() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy statusChangedSpy(&audio, SIGNAL(statusChanged())); + + QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia); + + // Set media, start loading. + provider.playerControl()->updateMediaStatus(QMediaPlayer::LoadingMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Loading); + QCOMPARE(statusChangedSpy.count(), 1); + + // Finish loading. + provider.playerControl()->updateMediaStatus(QMediaPlayer::LoadedMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Loaded); + QCOMPARE(statusChangedSpy.count(), 2); + + // Play, start buffering. + provider.playerControl()->updateMediaStatus( + QMediaPlayer::StalledMedia, QMediaPlayer::PlayingState); + QCOMPARE(audio.status(), QDeclarativeAudio::Stalled); + QCOMPARE(statusChangedSpy.count(), 3); + + // Enough data buffered to proceed. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Buffering); + QCOMPARE(statusChangedSpy.count(), 4); + + // Errant second buffering status changed. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Buffering); + QCOMPARE(statusChangedSpy.count(), 4); + + // Buffer full. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Buffered); + QCOMPARE(statusChangedSpy.count(), 5); + + // Buffer getting low. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Buffering); + QCOMPARE(statusChangedSpy.count(), 6); + + // Buffer full. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia); + QCOMPARE(audio.status(), QDeclarativeAudio::Buffered); + QCOMPARE(statusChangedSpy.count(), 7); + + // Finished. + provider.playerControl()->updateMediaStatus( + QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + QCOMPARE(audio.status(), QDeclarativeAudio::EndOfMedia); + QCOMPARE(statusChangedSpy.count(), 8); +} + +void tst_QDeclarativeAudio::metaData_data() +{ + QTest::addColumn("propertyName"); + QTest::addColumn("propertyKey"); + QTest::addColumn("value"); + + QTest::newRow("title") + << QByteArray("title") + << QtMultimediaKit::Title + << QVariant(QString::fromLatin1("This is a title")); + + QTest::newRow("genre") + << QByteArray("genre") + << QtMultimediaKit::Genre + << QVariant(QString::fromLatin1("rock")); + + QTest::newRow("trackNumber") + << QByteArray("trackNumber") + << QtMultimediaKit::TrackNumber + << QVariant(8); +} + +void tst_QDeclarativeAudio::metaData() +{ + QFETCH(QByteArray, propertyName); + QFETCH(QtMultimediaKit::MetaData, propertyKey); + QFETCH(QVariant, value); + + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy spy(audio.metaData(), SIGNAL(metaDataChanged())); + + const int index = audio.metaData()->metaObject()->indexOfProperty(propertyName.constData()); + QVERIFY(index != -1); + + QMetaProperty property = audio.metaData()->metaObject()->property(index); + QCOMPARE(property.read(&audio), QVariant()); + + property.write(audio.metaData(), value); + QCOMPARE(property.read(audio.metaData()), QVariant()); + QCOMPARE(provider.metaDataControl()->metaData(propertyKey), QVariant()); + QCOMPARE(spy.count(), 0); + + provider.metaDataControl()->setMetaData(propertyKey, value); + QCOMPARE(property.read(audio.metaData()), value); + QCOMPARE(spy.count(), 1); +} + +void tst_QDeclarativeAudio::error() +{ + const QString errorString = QLatin1String("Failed to open device."); + + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + audio.classBegin(); + audio.componentComplete(); + + QSignalSpy errorSpy(&audio, SIGNAL(error(QDeclarativeAudio::Error,QString))); + QSignalSpy errorChangedSpy(&audio, SIGNAL(errorChanged())); + + QCOMPARE(audio.error(), QDeclarativeAudio::NoError); + QCOMPARE(audio.errorString(), QString()); + + provider.playerControl()->emitError(QMediaPlayer::ResourceError, errorString); + + QCOMPARE(audio.error(), QDeclarativeAudio::ResourceError); + QCOMPARE(audio.errorString(), errorString); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 1); + + // Changing the source resets the error properties. + audio.setSource(QUrl("http://example.com")); + QCOMPARE(audio.error(), QDeclarativeAudio::NoError); + QCOMPARE(audio.errorString(), QString()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 2); + + // But isn't noisy. + audio.setSource(QUrl("file:///file/path")); + QCOMPARE(audio.error(), QDeclarativeAudio::NoError); + QCOMPARE(audio.errorString(), QString()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 2); +} + +void tst_QDeclarativeAudio::loops() +{ + QtTestMediaServiceProvider provider; + QDeclarativeAudio audio; + + QSignalSpy loopsChangedSpy(&audio, SIGNAL(loopCountChanged())); + QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged())); + QSignalSpy stoppedSpy(&audio, SIGNAL(stopped())); + + int playingChanged = 0; + int stopped = 0; + int loopsChanged = 0; + + audio.classBegin(); + audio.componentComplete(); + + QCOMPARE(audio.isPlaying(), false); + + //setLoopCount(3) when stopped. + audio.setLoopCount(3); + QCOMPARE(audio.loopCount(), 3); + QCOMPARE(loopsChangedSpy.count(), ++loopsChanged); + + //play till end + audio.play(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + + // setPlaying(true) when playing. + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(stoppedSpy.count(), stopped); + + provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + + //play to end + provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + //play to end + provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // stop when playing + audio.play(); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + audio.stop(); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(stoppedSpy.count(), ++stopped); + + //setPlaying(true) with infinite loop + audio.setLoopCount(-1); + QCOMPARE(audio.loopCount(), -1); + QCOMPARE(loopsChangedSpy.count(), ++loopsChanged); + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + provider.playerControl()->updateMediaStatus(QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + + // play() when playing. + audio.play(); + QCOMPARE(audio.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when playing in infinite loop. + audio.setPlaying(false); + QCOMPARE(audio.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(stoppedSpy.count(), ++stopped); +} + +QTEST_MAIN(tst_QDeclarativeAudio) + +#include "tst_qdeclarativeaudio.moc" diff --git a/tests/auto/qdeclarativevideo/qdeclarativevideo.pro b/tests/auto/qdeclarativevideo/qdeclarativevideo.pro new file mode 100644 index 000000000..15e58d8a5 --- /dev/null +++ b/tests/auto/qdeclarativevideo/qdeclarativevideo.pro @@ -0,0 +1,18 @@ +load(qttest_p4) + +QT += multimediakit-private declarative + +# TARGET = tst_qdeclarativevideo +# CONFIG += testcase + +HEADERS += \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativevideo_p.h \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase_p.h \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediametadata_p.h + +SOURCES += \ + tst_qdeclarativevideo.cpp \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativevideo.cpp \ + $$QT.multimediakit.sources/../imports/multimedia/qdeclarativemediabase.cpp + +INCLUDEPATH += $$QT.multimediakit.sources/../imports/multimedia diff --git a/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp b/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp new file mode 100644 index 000000000..1f48a5c11 --- /dev/null +++ b/tests/auto/qdeclarativevideo/tst_qdeclarativevideo.cpp @@ -0,0 +1,992 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=plugins/declarative/multimedia + +#include + +#include "qdeclarativevideo_p.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class tst_QDeclarativeVideo : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void nullPlayerControl(); + void nullService(); + + void playing(); + void paused(); + void error(); + + void hasAudio(); + void hasVideo(); + void fillMode(); + void geometry(); +}; + +Q_DECLARE_METATYPE(QtMultimediaKit::MetaData); +Q_DECLARE_METATYPE(QDeclarativeVideo::Error); + +class QtTestMediaPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT +public: + QtTestMediaPlayerControl(QObject *parent = 0) + : QMediaPlayerControl(parent) + , m_state(QMediaPlayer::StoppedState) + , m_mediaStatus(QMediaPlayer::NoMedia) + , m_duration(0) + , m_position(0) + , m_playbackRate(1.0) + , m_volume(50) + , m_bufferStatus(0) + , m_muted(false) + , m_audioAvailable(false) + , m_videoAvailable(false) + , m_seekable(false) + { + } + + QMediaPlayer::State state() const { return m_state; } + void updateState(QMediaPlayer::State state) { emit stateChanged(m_state = state); } + + QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; } + void updateMediaStatus(QMediaPlayer::MediaStatus status) { + emit mediaStatusChanged(m_mediaStatus = status); } + void updateMediaStatus(QMediaPlayer::MediaStatus status, QMediaPlayer::State state) + { + m_mediaStatus = status; + m_state = state; + + emit mediaStatusChanged(m_mediaStatus); + emit stateChanged(m_state); + } + + qint64 duration() const { return m_duration; } + void setDuration(qint64 duration) { emit durationChanged(m_duration = duration); } + + qint64 position() const { return m_position; } + void setPosition(qint64 position) { emit positionChanged(m_position = position); } + + int volume() const { return m_volume; } + void setVolume(int volume) { emit volumeChanged(m_volume = volume); } + + bool isMuted() const { return m_muted; } + void setMuted(bool muted) { emit mutedChanged(m_muted = muted); } + + int bufferStatus() const { return m_bufferStatus; } + void setBufferStatus(int status) { emit bufferStatusChanged(m_bufferStatus = status); } + + bool isAudioAvailable() const { return m_audioAvailable; } + void setAudioAvailable(bool available) { + emit audioAvailableChanged(m_audioAvailable = available); } + bool isVideoAvailable() const { return m_videoAvailable; } + void setVideoAvailable(bool available) { + emit videoAvailableChanged(m_videoAvailable = available); } + + bool isSeekable() const { return m_seekable; } + void setSeekable(bool seekable) { emit seekableChanged(m_seekable = seekable); } + + QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); } + + qreal playbackRate() const { return m_playbackRate; } + void setPlaybackRate(qreal rate) { emit playbackRateChanged(m_playbackRate = rate); } + + QMediaContent media() const { return m_media; } + const QIODevice *mediaStream() const { return 0; } + void setMedia(const QMediaContent &media, QIODevice *) + { + m_media = media; + + m_mediaStatus = m_media.isNull() + ? QMediaPlayer::NoMedia + : QMediaPlayer::LoadingMedia; + + emit mediaChanged(m_media); + emit mediaStatusChanged(m_mediaStatus); + } + + void play() { emit stateChanged(m_state = QMediaPlayer::PlayingState); } + void pause() { emit stateChanged(m_state = QMediaPlayer::PausedState); } + void stop() { emit stateChanged(m_state = QMediaPlayer::StoppedState); } + + void emitError(QMediaPlayer::Error err, const QString &errorString) { + emit error(err, errorString); } + +private: + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_mediaStatus; + qint64 m_duration; + qint64 m_position; + qreal m_playbackRate; + int m_volume; + int m_bufferStatus; + bool m_muted; + bool m_audioAvailable; + bool m_videoAvailable; + bool m_seekable; + QMediaContent m_media; +}; + +class QtTestRendererControl : public QVideoRendererControl +{ +public: + QtTestRendererControl(QObject *parent ) : QVideoRendererControl(parent), m_surface(0) {} + + QAbstractVideoSurface *surface() const { return m_surface; } + void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; } + +private: + QAbstractVideoSurface *m_surface; +}; + +class QtTestWindowControl : public QVideoWindowControl +{ +public: + QtTestWindowControl(QObject *parent) + : QVideoWindowControl(parent) + , m_winId(0) + , m_repaintCount(0) + , m_brightness(0) + , m_contrast(0) + , m_saturation(0) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_fullScreen(0) + { + } + + WId winId() const { return m_winId; } + void setWinId(WId id) { m_winId = id; } + + QRect displayRect() const { return m_displayRect; } + void setDisplayRect(const QRect &rect) { m_displayRect = rect; } + + bool isFullScreen() const { return m_fullScreen; } + void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); } + + int repaintCount() const { return m_repaintCount; } + void setRepaintCount(int count) { m_repaintCount = count; } + void repaint() { ++m_repaintCount; } + + QSize nativeSize() const { return m_nativeSize; } + void setNativeSize(const QSize &size) { m_nativeSize = size; emit nativeSizeChanged(); } + + Qt::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; } + void setAspectRatioMode(Qt::AspectRatioMode mode) { m_aspectRatioMode = mode; } + + int brightness() const { return m_brightness; } + void setBrightness(int brightness) { emit brightnessChanged(m_brightness = brightness); } + + int contrast() const { return m_contrast; } + void setContrast(int contrast) { emit contrastChanged(m_contrast = contrast); } + + int hue() const { return m_hue; } + void setHue(int hue) { emit hueChanged(m_hue = hue); } + + int saturation() const { return m_saturation; } + void setSaturation(int saturation) { emit saturationChanged(m_saturation = saturation); } + +private: + WId m_winId; + int m_repaintCount; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; + Qt::AspectRatioMode m_aspectRatioMode; + QRect m_displayRect; + QSize m_nativeSize; + bool m_fullScreen; +}; + +class QtTestMediaService : public QMediaService +{ + Q_OBJECT +public: + QtTestMediaService( + QtTestMediaPlayerControl *playerControl, + QtTestRendererControl *rendererControl, + QtTestWindowControl *windowControl, + QObject *parent) + : QMediaService(parent) + , playerControl(playerControl) + , rendererControl(rendererControl) + , windowControl(windowControl) + { + } + + QMediaControl *requestControl(const char *name) + { + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return playerControl; + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return rendererControl; + else if (qstrcmp(name, QVideoWindowControl_iid) == 0) + return windowControl; + else + return 0; + } + + void releaseControl(QMediaControl *) {} + + QtTestMediaPlayerControl *playerControl; + QtTestRendererControl *rendererControl; + QtTestWindowControl *windowControl; +}; + +class QtTestMediaServiceProvider : public QMediaServiceProvider +{ + Q_OBJECT +public: + QtTestMediaServiceProvider() + : service( + new QtTestMediaService( + new QtTestMediaPlayerControl(this), + new QtTestRendererControl(this), + new QtTestWindowControl(this), + this)) + { + setDefaultServiceProvider(this); + } + + QtTestMediaServiceProvider(QtTestMediaService *service) + : service(service) + { + setDefaultServiceProvider(this); + } + + QtTestMediaServiceProvider( + QtTestMediaPlayerControl *playerControl, + QtTestRendererControl *rendererControl, + QtTestWindowControl *windowControl) + : service(new QtTestMediaService(playerControl, rendererControl, windowControl, this)) + { + setDefaultServiceProvider(this); + } + + ~QtTestMediaServiceProvider() + { + setDefaultServiceProvider(0); + } + + QMediaService *requestService( + const QByteArray &type, + const QMediaServiceProviderHint & = QMediaServiceProviderHint()) + { + requestedService = type; + + return service; + } + + void releaseService(QMediaService *) {} + + inline QtTestMediaPlayerControl *playerControl() { return service->playerControl; } + inline QtTestRendererControl *rendererControl() { return service->rendererControl; } + + QtTestMediaService *service; + QByteArray requestedService; +}; + + +void tst_QDeclarativeVideo::initTestCase() +{ + qRegisterMetaType(); +} + +void tst_QDeclarativeVideo::nullPlayerControl() +{ + QtTestMediaServiceProvider provider(0, 0, 0); + + QDeclarativeVideo video; + video.classBegin(); + + QCOMPARE(video.source(), QUrl()); + video.setSource(QUrl("http://example.com")); + QCOMPARE(video.source(), QUrl("http://example.com")); + + QCOMPARE(video.isPlaying(), false); + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + video.setPlaying(false); + video.play(); + QCOMPARE(video.isPlaying(), false); + + QCOMPARE(video.isPaused(), false); + video.pause(); + QCOMPARE(video.isPaused(), false); + video.setPaused(true); + QCOMPARE(video.isPaused(), true); + + QCOMPARE(video.duration(), 0); + + QCOMPARE(video.position(), 0); + video.setPosition(10000); + QCOMPARE(video.position(), 10000); + + 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(), true); + + QCOMPARE(video.bufferProgress(), qreal(0)); + + QCOMPARE(video.isSeekable(), false); + + QCOMPARE(video.playbackRate(), qreal(1.0)); + + QCOMPARE(video.hasAudio(), false); + QCOMPARE(video.hasVideo(), false); + + QCOMPARE(video.status(), QDeclarativeVideo::NoMedia); + + QCOMPARE(video.error(), QDeclarativeVideo::ServiceMissing); +} + +void tst_QDeclarativeVideo::nullService() +{ + QtTestMediaServiceProvider provider(0); + + QDeclarativeVideo video; + video.classBegin(); + + QCOMPARE(video.source(), QUrl()); + video.setSource(QUrl("http://example.com")); + QCOMPARE(video.source(), QUrl("http://example.com")); + + QCOMPARE(video.isPlaying(), false); + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + video.setPlaying(false); + video.play(); + QCOMPARE(video.isPlaying(), false); + + QCOMPARE(video.isPaused(), false); + video.pause(); + QCOMPARE(video.isPaused(), false); + video.setPaused(true); + QCOMPARE(video.isPaused(), true); + + QCOMPARE(video.duration(), 0); + + QCOMPARE(video.position(), 0); + video.setPosition(10000); + QCOMPARE(video.position(), 10000); + + 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(), true); + + QCOMPARE(video.bufferProgress(), qreal(0)); + + QCOMPARE(video.isSeekable(), false); + + QCOMPARE(video.playbackRate(), qreal(1.0)); + + QCOMPARE(video.hasAudio(), false); + QCOMPARE(video.hasVideo(), false); + + QCOMPARE(video.status(), QDeclarativeVideo::NoMedia); + + QCOMPARE(video.error(), QDeclarativeVideo::ServiceMissing); + + QCOMPARE(video.metaObject()->indexOfProperty("title"), -1); + QCOMPARE(video.metaObject()->indexOfProperty("genre"), -1); + QCOMPARE(video.metaObject()->indexOfProperty("description"), -1); +} + +void tst_QDeclarativeVideo::playing() +{ + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + video.setSource(QUrl("http://example.com")); + + QSignalSpy playingChangedSpy(&video, SIGNAL(playingChanged())); + QSignalSpy startedSpy(&video, SIGNAL(started())); + QSignalSpy stoppedSpy(&video, SIGNAL(stopped())); + + int playingChanged = 0; + int started = 0; + int stopped = 0; + + QCOMPARE(video.isPlaying(), false); + + // setPlaying(true) when stopped. + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when playing. + video.setPlaying(false); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // play() when stopped. + video.play(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(stoppedSpy.count(), stopped); + + // stop() when playing. + video.stop(); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // stop() when stopped. + video.stop(); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when stopped. + video.setPlaying(false); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); + + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(true) when playing. + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); + + // play() when playing. + video.play(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(stoppedSpy.count(), stopped); +} + +void tst_QDeclarativeVideo::paused() +{ + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + video.setSource(QUrl("http://example.com")); + + QSignalSpy playingChangedSpy(&video, SIGNAL(playingChanged())); + QSignalSpy pausedChangedSpy(&video, SIGNAL(pausedChanged())); + QSignalSpy startedSpy(&video, SIGNAL(started())); + QSignalSpy pausedSpy(&video, SIGNAL(paused())); + QSignalSpy resumedSpy(&video, SIGNAL(resumed())); + QSignalSpy stoppedSpy(&video, SIGNAL(stopped())); + + int playingChanged = 0; + int pausedChanged = 0; + int started = 0; + int paused = 0; + int resumed = 0; + int stopped = 0; + + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), false); + + // setPlaying(true) when stopped. + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when playing. + video.setPaused(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when paused. + video.setPaused(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // pause() when paused. + video.pause(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(false) when paused. + video.setPaused(false); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), ++resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(false) when playing. + video.setPaused(false); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // pause() when playing. + video.pause(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when paused. + video.setPlaying(false); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // setPaused(true) when stopped and paused. + video.setPaused(true); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(false) when stopped and paused. + video.setPaused(false); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when stopped. + video.setPaused(true); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(true) when stopped and paused. + video.setPlaying(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // play() when paused. + video.play(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), ++resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPaused(true) when playing. + video.setPaused(true); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // stop() when paused. + video.stop(); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // setPaused(true) when stopped. + video.setPaused(true); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // stop() when stopped and paused. + video.stop(); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // pause() when stopped. + video.pause(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when paused. + video.setPlaying(false); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // pause() when stopped and paused. + video.pause(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), ++paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); + + // setPlaying(false) when paused. + video.setPlaying(false); + QCOMPARE(video.isPlaying(), false); + QCOMPARE(video.isPaused(), true); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), pausedChanged); + QCOMPARE(startedSpy.count(), started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), ++stopped); + + // play() when stopped and paused. + video.play(); + QCOMPARE(video.isPlaying(), true); + QCOMPARE(video.isPaused(), false); + QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState); + QCOMPARE(playingChangedSpy.count(), ++playingChanged); + QCOMPARE(pausedChangedSpy.count(), ++pausedChanged); + QCOMPARE(startedSpy.count(), ++started); + QCOMPARE(pausedSpy.count(), paused); + QCOMPARE(resumedSpy.count(), resumed); + QCOMPARE(stoppedSpy.count(), stopped); +} + +void tst_QDeclarativeVideo::error() +{ + const QString errorString = QLatin1String("Failed to open device."); + + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + + QSignalSpy errorSpy(&video, SIGNAL(error(QDeclarativeVideo::Error,QString))); + QSignalSpy errorChangedSpy(&video, SIGNAL(errorChanged())); + + QCOMPARE(video.error(), QDeclarativeVideo::NoError); + QCOMPARE(video.errorString(), QString()); + + provider.playerControl()->emitError(QMediaPlayer::ResourceError, errorString); + + QCOMPARE(video.error(), QDeclarativeVideo::ResourceError); + QCOMPARE(video.errorString(), errorString); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 1); + + // Changing the source resets the error properties. + video.setSource(QUrl("http://example.com")); + QCOMPARE(video.error(), QDeclarativeVideo::NoError); + QCOMPARE(video.errorString(), QString()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 2); + + // But isn't noisy. + video.setSource(QUrl("file:///file/path")); + QCOMPARE(video.error(), QDeclarativeVideo::NoError); + QCOMPARE(video.errorString(), QString()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 2); +} + + +void tst_QDeclarativeVideo::hasAudio() +{ + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + + QSignalSpy spy(&video, SIGNAL(hasAudioChanged())); + + QCOMPARE(video.hasAudio(), false); + + provider.playerControl()->setAudioAvailable(true); + QCOMPARE(video.hasAudio(), true); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setAudioAvailable(true); + QCOMPARE(video.hasAudio(), true); + QCOMPARE(spy.count(), 2); + + provider.playerControl()->setAudioAvailable(false); + QCOMPARE(video.hasAudio(), false); + QCOMPARE(spy.count(), 3); +} + +void tst_QDeclarativeVideo::hasVideo() +{ + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + + QSignalSpy spy(&video, SIGNAL(hasVideoChanged())); + + QCOMPARE(video.hasVideo(), false); + + provider.playerControl()->setVideoAvailable(true); + QCOMPARE(video.hasVideo(), true); + QCOMPARE(spy.count(), 1); + + provider.playerControl()->setVideoAvailable(true); + QCOMPARE(video.hasVideo(), true); + QCOMPARE(spy.count(), 2); + + provider.playerControl()->setVideoAvailable(false); + QCOMPARE(video.hasVideo(), false); + QCOMPARE(spy.count(), 3); +} + +void tst_QDeclarativeVideo::fillMode() +{ + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + + QList children = video.childItems(); + QCOMPARE(children.count(), 1); + QGraphicsVideoItem *videoItem = qgraphicsitem_cast(children.first()); + QVERIFY(videoItem != 0); + + QCOMPARE(video.fillMode(), QDeclarativeVideo::PreserveAspectFit); + + video.setFillMode(QDeclarativeVideo::PreserveAspectCrop); + QCOMPARE(video.fillMode(), QDeclarativeVideo::PreserveAspectCrop); + QCOMPARE(videoItem->aspectRatioMode(), Qt::KeepAspectRatioByExpanding); + + video.setFillMode(QDeclarativeVideo::Stretch); + QCOMPARE(video.fillMode(), QDeclarativeVideo::Stretch); + QCOMPARE(videoItem->aspectRatioMode(), Qt::IgnoreAspectRatio); + + video.setFillMode(QDeclarativeVideo::PreserveAspectFit); + QCOMPARE(video.fillMode(), QDeclarativeVideo::PreserveAspectFit); + QCOMPARE(videoItem->aspectRatioMode(), Qt::KeepAspectRatio); +} + +void tst_QDeclarativeVideo::geometry() +{ + QtTestMediaServiceProvider provider; + QDeclarativeVideo video; + video.classBegin(); + video.componentComplete(); + + QList children = video.childItems(); + QCOMPARE(children.count(), 1); + QGraphicsVideoItem *videoItem = qgraphicsitem_cast(children.first()); + QVERIFY(videoItem != 0); + + { // Surface setup is deferred until after the first paint. + QImage image(320, 240, QImage::Format_RGB32); + QPainter painter(&image); + + videoItem->paint(&painter, 0); + } + + QAbstractVideoSurface *surface = provider.rendererControl()->surface(); + + //video item can use overlay, QAbstractVideoSurface is not used than. + if (surface) { + QVideoSurfaceFormat format(QSize(640, 480), QVideoFrame::Format_RGB32); + + QVERIFY(surface->start(format)); + QCoreApplication::processEvents(); + + QCOMPARE(video.implicitWidth(), qreal(640)); + QCOMPARE(video.implicitHeight(), qreal(480)); + } + + video.setWidth(560); + video.setHeight(328); + + QCOMPARE(videoItem->size().width(), qreal(560)); + QCOMPARE(videoItem->size().height(), qreal(328)); +} + +QTEST_MAIN(tst_QDeclarativeVideo) + +#include "tst_qdeclarativevideo.moc" diff --git a/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro b/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro new file mode 100644 index 000000000..1d8735d42 --- /dev/null +++ b/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro @@ -0,0 +1,12 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qgraphicsvideoitem +# CONFIG += testcase + +SOURCES += tst_qgraphicsvideoitem.cpp + +symbian: TARGET.CAPABILITY = ReadDeviceData WriteDeviceData + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp new file mode 100644 index 000000000..2e7b97df8 --- /dev/null +++ b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp @@ -0,0 +1,675 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include "qgraphicsvideoitem.h" +#include +#include "qmediaobject.h" +#include "qmediaservice.h" +#include +#include "qvideorenderercontrol.h" + +#include +#include + +#include +#include +#include + +QT_USE_NAMESPACE +class tst_QGraphicsVideoItem : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void nullObject(); + void nullService(); + void noOutputs(); + void serviceDestroyed(); + void mediaObjectDestroyed(); + void setMediaObject(); + + void show(); + + void aspectRatioMode(); + void offset(); + void size(); + void nativeSize_data(); + void nativeSize(); + + void boundingRect_data(); + void boundingRect(); + + void paint(); +}; + +Q_DECLARE_METATYPE(const uchar *) +Q_DECLARE_METATYPE(Qt::AspectRatioMode) + +class QtTestRendererControl : public QVideoRendererControl +{ +public: + QtTestRendererControl() + : m_surface(0) + { + } + + QAbstractVideoSurface *surface() const { return m_surface; } + void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; } + +private: + QAbstractVideoSurface *m_surface; +}; + +class QtTestVideoService : public QMediaService +{ + Q_OBJECT +public: + QtTestVideoService( + QtTestRendererControl *renderer) + : QMediaService(0) + , rendererRef(0) + , rendererControl(renderer) + { + } + + ~QtTestVideoService() + { + delete rendererControl; + } + + QMediaControl *requestControl(const char *name) + { + if (qstrcmp(name, QVideoRendererControl_iid) == 0 && rendererControl) { + rendererRef += 1; + + return rendererControl; + } else { + return 0; + } + } + + void releaseControl(QMediaControl *control) + { + Q_ASSERT(control); + + if (control == rendererControl) { + rendererRef -= 1; + + if (rendererRef == 0) + rendererControl->setSurface(0); + } + } + + int rendererRef; + QtTestRendererControl *rendererControl; +}; + +class QtTestVideoObject : public QMediaObject +{ + Q_OBJECT +public: + QtTestVideoObject(QtTestRendererControl *renderer) + : QMediaObject(0, new QtTestVideoService(renderer)) + { + testService = qobject_cast(service()); + } + + QtTestVideoObject(QtTestVideoService *service): + QMediaObject(0, service), + testService(service) + { + } + + ~QtTestVideoObject() + { + delete testService; + } + + QtTestVideoService *testService; +}; + +class QtTestGraphicsVideoItem : public QGraphicsVideoItem +{ +public: + QtTestGraphicsVideoItem(QGraphicsItem *parent = 0) + : QGraphicsVideoItem(parent) + , m_paintCount(0) + { + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + ++m_paintCount; + + QTestEventLoop::instance().exitLoop(); + + QGraphicsVideoItem::paint(painter, option, widget); + } + + bool waitForPaint(int secs) + { + const int paintCount = m_paintCount; + + QTestEventLoop::instance().enterLoop(secs); + + return m_paintCount != paintCount; + } + + int paintCount() const + { + return m_paintCount; + } + +private: + int m_paintCount; +}; + +void tst_QGraphicsVideoItem::initTestCase() +{ + qRegisterMetaType(); +} + +void tst_QGraphicsVideoItem::nullObject() +{ + QGraphicsVideoItem item(0); + + QVERIFY(item.boundingRect().isEmpty()); +} + +void tst_QGraphicsVideoItem::nullService() +{ + QtTestVideoService *service = 0; + + QtTestVideoObject object(service); + + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + object.bind(item); + + QVERIFY(item->boundingRect().isEmpty()); + + item->hide(); + item->show(); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); +} + +void tst_QGraphicsVideoItem::noOutputs() +{ + QtTestRendererControl *control = 0; + QtTestVideoObject object(control); + + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + object.bind(item); + + QVERIFY(item->boundingRect().isEmpty()); + + item->hide(); + item->show(); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); +} + +void tst_QGraphicsVideoItem::serviceDestroyed() +{ + QtTestVideoObject object(new QtTestRendererControl); + + QGraphicsVideoItem item; + object.bind(&item); + + QCOMPARE(object.testService->rendererRef, 1); + + QtTestVideoService *service = object.testService; + object.testService = 0; + + delete service; + + QCOMPARE(item.mediaObject(), static_cast(&object)); + QVERIFY(item.boundingRect().isEmpty()); +} + +void tst_QGraphicsVideoItem::mediaObjectDestroyed() +{ + QtTestVideoObject *object = new QtTestVideoObject(new QtTestRendererControl); + + QGraphicsVideoItem item; + object->bind(&item); + + QCOMPARE(object->testService->rendererRef, 1); + + delete object; + object = 0; + + QCOMPARE(item.mediaObject(), static_cast(object)); + QVERIFY(item.boundingRect().isEmpty()); +} + +void tst_QGraphicsVideoItem::setMediaObject() +{ + QMediaObject *nullObject = 0; + QtTestVideoObject object(new QtTestRendererControl); + + QGraphicsVideoItem item; + + QCOMPARE(item.mediaObject(), nullObject); + QCOMPARE(object.testService->rendererRef, 0); + + object.bind(&item); + QCOMPARE(item.mediaObject(), static_cast(&object)); + QCOMPARE(object.testService->rendererRef, 1); + QVERIFY(object.testService->rendererControl->surface() == 0); + + { // Surface setup is deferred until after the first paint. + QImage image(320, 240, QImage::Format_RGB32); + QPainter painter(&image); + + item.paint(&painter, 0); + } + QVERIFY(object.testService->rendererControl->surface() != 0); + + object.unbind(&item); + QCOMPARE(item.mediaObject(), nullObject); + + QCOMPARE(object.testService->rendererRef, 0); + QVERIFY(object.testService->rendererControl->surface() == 0); + + item.setVisible(false); + + object.bind(&item); + QCOMPARE(item.mediaObject(), static_cast(&object)); + QCOMPARE(object.testService->rendererRef, 1); + QVERIFY(object.testService->rendererControl->surface() != 0); +} + +void tst_QGraphicsVideoItem::show() +{ + QtTestVideoObject object(new QtTestRendererControl); + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + object.bind(item); + + // Graphics items are visible by default + QCOMPARE(object.testService->rendererRef, 1); + QVERIFY(object.testService->rendererControl->surface() == 0); + + item->hide(); + QCOMPARE(object.testService->rendererRef, 1); + + item->show(); + QCOMPARE(object.testService->rendererRef, 1); + QVERIFY(object.testService->rendererControl->surface() == 0); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); + + QVERIFY(item->paintCount() || item->waitForPaint(1)); + QVERIFY(object.testService->rendererControl->surface() != 0); + + QVERIFY(item->boundingRect().isEmpty()); + + QVideoSurfaceFormat format(QSize(320,240),QVideoFrame::Format_RGB32); + QVERIFY(object.testService->rendererControl->surface()->start(format)); + + QCoreApplication::processEvents(); + QVERIFY(!item->boundingRect().isEmpty()); +} + +void tst_QGraphicsVideoItem::aspectRatioMode() +{ + QGraphicsVideoItem item; + + QCOMPARE(item.aspectRatioMode(), Qt::KeepAspectRatio); + + item.setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(item.aspectRatioMode(), Qt::IgnoreAspectRatio); + + item.setAspectRatioMode(Qt::KeepAspectRatioByExpanding); + QCOMPARE(item.aspectRatioMode(), Qt::KeepAspectRatioByExpanding); + + item.setAspectRatioMode(Qt::KeepAspectRatio); + QCOMPARE(item.aspectRatioMode(), Qt::KeepAspectRatio); +} + +void tst_QGraphicsVideoItem::offset() +{ + QGraphicsVideoItem item; + + QCOMPARE(item.offset(), QPointF(0, 0)); + + item.setOffset(QPointF(-32.4, 43.0)); + QCOMPARE(item.offset(), QPointF(-32.4, 43.0)); + + item.setOffset(QPointF(1, 1)); + QCOMPARE(item.offset(), QPointF(1, 1)); + + item.setOffset(QPointF(12, -30.4)); + QCOMPARE(item.offset(), QPointF(12, -30.4)); + + item.setOffset(QPointF(-90.4, -75)); + QCOMPARE(item.offset(), QPointF(-90.4, -75)); +} + +void tst_QGraphicsVideoItem::size() +{ + QGraphicsVideoItem item; + + QCOMPARE(item.size(), QSizeF(320, 240)); + + item.setSize(QSizeF(542.5, 436.3)); + QCOMPARE(item.size(), QSizeF(542.5, 436.3)); + + item.setSize(QSizeF(-43, 12)); + QCOMPARE(item.size(), QSizeF(0, 0)); + + item.setSize(QSizeF(54, -9)); + QCOMPARE(item.size(), QSizeF(0, 0)); + + item.setSize(QSizeF(-90, -65)); + QCOMPARE(item.size(), QSizeF(0, 0)); + + item.setSize(QSizeF(1000, 1000)); + QCOMPARE(item.size(), QSizeF(1000, 1000)); +} + +void tst_QGraphicsVideoItem::nativeSize_data() +{ + QTest::addColumn("frameSize"); + QTest::addColumn("viewport"); + QTest::addColumn("pixelAspectRatio"); + QTest::addColumn("nativeSize"); + + QTest::newRow("640x480") + << QSize(640, 480) + << QRect(0, 0, 640, 480) + << QSize(1, 1) + << QSizeF(640, 480); + + QTest::newRow("800x600, (80,60, 640x480) viewport") + << QSize(800, 600) + << QRect(80, 60, 640, 480) + << QSize(1, 1) + << QSizeF(640, 480); + + QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3") + << QSize(800, 600) + << QRect(80, 60, 640, 480) + << QSize(4, 3) + << QSizeF(853, 480); +} + +void tst_QGraphicsVideoItem::nativeSize() +{ + QFETCH(QSize, frameSize); + QFETCH(QRect, viewport); + QFETCH(QSize, pixelAspectRatio); + QFETCH(QSizeF, nativeSize); + + QtTestVideoObject object(new QtTestRendererControl); + QGraphicsVideoItem item; + object.bind(&item); + + QCOMPARE(item.nativeSize(), QSizeF()); + + QSignalSpy spy(&item, SIGNAL(nativeSizeChanged(QSizeF))); + + QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32); + format.setViewport(viewport); + format.setPixelAspectRatio(pixelAspectRatio); + + { // Surface setup is deferred until after the first paint. + QImage image(320, 240, QImage::Format_RGB32); + QPainter painter(&image); + + item.paint(&painter, 0); + } + QVERIFY(object.testService->rendererControl->surface() != 0); + QVERIFY(object.testService->rendererControl->surface()->start(format)); + + QCoreApplication::processEvents(); + QCOMPARE(item.nativeSize(), nativeSize); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().first().toSizeF(), nativeSize); + + object.testService->rendererControl->surface()->stop(); + + QCoreApplication::processEvents(); + QVERIFY(item.nativeSize().isEmpty()); + QCOMPARE(spy.count(), 2); + QVERIFY(spy.last().first().toSizeF().isEmpty()); +} + +void tst_QGraphicsVideoItem::boundingRect_data() +{ + QTest::addColumn("frameSize"); + QTest::addColumn("offset"); + QTest::addColumn("size"); + QTest::addColumn("aspectRatioMode"); + QTest::addColumn("expectedRect"); + + + QTest::newRow("640x480: (0,0 640x480), Keep") + << QSize(640, 480) + << QPointF(0, 0) + << QSizeF(640, 480) + << Qt::KeepAspectRatio + << QRectF(0, 0, 640, 480); + + QTest::newRow("800x600, (0,0, 640x480), Keep") + << QSize(800, 600) + << QPointF(0, 0) + << QSizeF(640, 480) + << Qt::KeepAspectRatio + << QRectF(0, 0, 640, 480); + + QTest::newRow("800x600, (0,0, 640x480), KeepByExpanding") + << QSize(800, 600) + << QPointF(0, 0) + << QSizeF(640, 480) + << Qt::KeepAspectRatioByExpanding + << QRectF(0, 0, 640, 480); + + QTest::newRow("800x600, (0,0, 640x480), Ignore") + << QSize(800, 600) + << QPointF(0, 0) + << QSizeF(640, 480) + << Qt::IgnoreAspectRatio + << QRectF(0, 0, 640, 480); + + QTest::newRow("800x600, (100,100, 640x480), Keep") + << QSize(800, 600) + << QPointF(100, 100) + << QSizeF(640, 480) + << Qt::KeepAspectRatio + << QRectF(100, 100, 640, 480); + + QTest::newRow("800x600, (100,-100, 640x480), KeepByExpanding") + << QSize(800, 600) + << QPointF(100, -100) + << QSizeF(640, 480) + << Qt::KeepAspectRatioByExpanding + << QRectF(100, -100, 640, 480); + + QTest::newRow("800x600, (-100,-100, 640x480), Ignore") + << QSize(800, 600) + << QPointF(-100, -100) + << QSizeF(640, 480) + << Qt::IgnoreAspectRatio + << QRectF(-100, -100, 640, 480); + + QTest::newRow("800x600, (0,0, 1920x1024), Keep") + << QSize(800, 600) + << QPointF(0, 0) + << QSizeF(1920, 1024) + << Qt::KeepAspectRatio + << QRectF(832.0 / 3, 0, 4096.0 / 3, 1024); + + QTest::newRow("800x600, (0,0, 1920x1024), KeepByExpanding") + << QSize(800, 600) + << QPointF(0, 0) + << QSizeF(1920, 1024) + << Qt::KeepAspectRatioByExpanding + << QRectF(0, 0, 1920, 1024); + + QTest::newRow("800x600, (0,0, 1920x1024), Ignore") + << QSize(800, 600) + << QPointF(0, 0) + << QSizeF(1920, 1024) + << Qt::IgnoreAspectRatio + << QRectF(0, 0, 1920, 1024); + + QTest::newRow("800x600, (100,100, 1920x1024), Keep") + << QSize(800, 600) + << QPointF(100, 100) + << QSizeF(1920, 1024) + << Qt::KeepAspectRatio + << QRectF(100 + 832.0 / 3, 100, 4096.0 / 3, 1024); + + QTest::newRow("800x600, (100,-100, 1920x1024), KeepByExpanding") + << QSize(800, 600) + << QPointF(100, -100) + << QSizeF(1920, 1024) + << Qt::KeepAspectRatioByExpanding + << QRectF(100, -100, 1920, 1024); + + QTest::newRow("800x600, (-100,-100, 1920x1024), Ignore") + << QSize(800, 600) + << QPointF(-100, -100) + << QSizeF(1920, 1024) + << Qt::IgnoreAspectRatio + << QRectF(-100, -100, 1920, 1024); +} + +void tst_QGraphicsVideoItem::boundingRect() +{ + QFETCH(QSize, frameSize); + QFETCH(QPointF, offset); + QFETCH(QSizeF, size); + QFETCH(Qt::AspectRatioMode, aspectRatioMode); + QFETCH(QRectF, expectedRect); + + QtTestVideoObject object(new QtTestRendererControl); + QGraphicsVideoItem item; + object.bind(&item); + + item.setOffset(offset); + item.setSize(size); + item.setAspectRatioMode(aspectRatioMode); + + QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32); + + { // Surface setup is deferred until after the first paint. + QImage image(320, 240, QImage::Format_RGB32); + QPainter painter(&image); + + item.paint(&painter, 0); + } + QVERIFY(object.testService->rendererControl->surface() != 0); + QVERIFY(object.testService->rendererControl->surface()->start(format)); + + QCoreApplication::processEvents(); + QCOMPARE(item.boundingRect(), expectedRect); +} + +static const uchar rgb32ImageData[] = +{ + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00 +}; + +void tst_QGraphicsVideoItem::paint() +{ + QtTestVideoObject object(new QtTestRendererControl); + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + object.bind(item); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); + QVERIFY(item->waitForPaint(1)); + + QPainterVideoSurface *surface = qobject_cast( + object.testService->rendererControl->surface()); + if (!surface) + QSKIP("QGraphicsVideoItem is not QPainterVideoSurface based", SkipAll); + + QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32); + + QVERIFY(surface->start(format)); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); + + QVERIFY(item->waitForPaint(1)); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); + + QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32); + + frame.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes()); + frame.unmap(); + + QVERIFY(surface->present(frame)); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), false); + + QVERIFY(item->waitForPaint(1)); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); +} + + +QTEST_MAIN(tst_QGraphicsVideoItem) + +#include "tst_qgraphicsvideoitem.moc" diff --git a/tests/auto/qmediacontent/qmediacontent.pro b/tests/auto/qmediacontent/qmediacontent.pro new file mode 100644 index 000000000..47d9cea67 --- /dev/null +++ b/tests/auto/qmediacontent/qmediacontent.pro @@ -0,0 +1,7 @@ +load(qttest_p4) + +QT += multimediakit-private network +# TARGET = tst_qmediacontent +# CONFIG += testcase + +SOURCES += tst_qmediacontent.cpp diff --git a/tests/auto/qmediacontent/tst_qmediacontent.cpp b/tests/auto/qmediacontent/tst_qmediacontent.cpp new file mode 100644 index 000000000..b350cf175 --- /dev/null +++ b/tests/auto/qmediacontent/tst_qmediacontent.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include +#include + +#include + +//TESTED_COMPONENT=src/multimedia + +QT_USE_NAMESPACE +class tst_QMediaContent : public QObject +{ + Q_OBJECT + +private slots: + void testNull(); + void testUrlCtor(); + void testRequestCtor(); + void testResourceCtor(); + void testResourceListCtor(); + void testCopy(); + void testAssignment(); + void testEquality(); + void testResources(); +}; + +void tst_QMediaContent::testNull() +{ + QMediaContent media; + + QCOMPARE(media.isNull(), true); + QCOMPARE(media.canonicalUrl(), QUrl()); + QCOMPARE(media.canonicalResource(), QMediaResource()); + QCOMPARE(media.resources(), QMediaResourceList()); +} + +void tst_QMediaContent::testUrlCtor() +{ + QMediaContent media(QUrl("http://example.com/movie.mov")); + + QCOMPARE(media.canonicalUrl(), QUrl("http://example.com/movie.mov")); + QCOMPARE(media.canonicalResource().url(), QUrl("http://example.com/movie.mov")); +} + +void tst_QMediaContent::testRequestCtor() +{ + QNetworkRequest request(QUrl("http://example.com/movie.mov")); + request.setAttribute(QNetworkRequest::User, QVariant(1234)); + + QMediaContent media(request); + + QCOMPARE(media.canonicalUrl(), QUrl("http://example.com/movie.mov")); + QCOMPARE(media.canonicalResource().request(), request); + QCOMPARE(media.canonicalResource().url(), QUrl("http://example.com/movie.mov")); +} + +void tst_QMediaContent::testResourceCtor() +{ + QMediaContent media(QMediaResource(QUrl("http://example.com/movie.mov"))); + + QCOMPARE(media.canonicalResource(), QMediaResource(QUrl("http://example.com/movie.mov"))); +} + +void tst_QMediaContent::testResourceListCtor() +{ + QMediaResourceList resourceList; + resourceList << QMediaResource(QUrl("http://example.com/movie.mov")); + + QMediaContent media(resourceList); + + QCOMPARE(media.canonicalUrl(), QUrl("http://example.com/movie.mov")); + QCOMPARE(media.canonicalResource().url(), QUrl("http://example.com/movie.mov")); +} + +void tst_QMediaContent::testCopy() +{ + QMediaContent media1(QMediaResource(QUrl("http://example.com/movie.mov"))); + QMediaContent media2(media1); + + QVERIFY(media1 == media2); +} + +void tst_QMediaContent::testAssignment() +{ + QMediaContent media1(QMediaResource(QUrl("http://example.com/movie.mov"))); + QMediaContent media2; + QMediaContent media3; + + media2 = media1; + QVERIFY(media2 == media1); + + media2 = media3; + QVERIFY(media2 == media3); +} + +void tst_QMediaContent::testEquality() +{ + QMediaContent media1; + QMediaContent media2; + QMediaContent media3(QMediaResource(QUrl("http://example.com/movie.mov"))); + QMediaContent media4(QMediaResource(QUrl("http://example.com/movie.mov"))); + QMediaContent media5(QMediaResource(QUrl("file:///some/where/over/the/rainbow.mp3"))); + + // null == null + QCOMPARE(media1 == media2, true); + QCOMPARE(media1 != media2, false); + + // null != something + QCOMPARE(media1 == media3, false); + QCOMPARE(media1 != media3, true); + + // equiv + QCOMPARE(media3 == media4, true); + QCOMPARE(media3 != media4, false); + + // not equiv + QCOMPARE(media4 == media5, false); + QCOMPARE(media4 != media5, true); +} + +void tst_QMediaContent::testResources() +{ + QMediaResourceList resourceList; + + resourceList << QMediaResource(QUrl("http://example.com/movie-main.mov")); + resourceList << QMediaResource(QUrl("http://example.com/movie-big.mov")); + QMediaContent media(resourceList); + + QMediaResourceList res = media.resources(); + QCOMPARE(res.size(), 2); + QCOMPARE(res[0], QMediaResource(QUrl("http://example.com/movie-main.mov"))); + QCOMPARE(res[1], QMediaResource(QUrl("http://example.com/movie-big.mov"))); +} + +QTEST_MAIN(tst_QMediaContent) + +#include "tst_qmediacontent.moc" diff --git a/tests/auto/qmediaimageviewer/images.qrc b/tests/auto/qmediaimageviewer/images.qrc new file mode 100644 index 000000000..508de1369 --- /dev/null +++ b/tests/auto/qmediaimageviewer/images.qrc @@ -0,0 +1,9 @@ + + + images/coverart.png + images/image.jpg + images/image.png + images/invalid.png + images/poster.png + + diff --git a/tests/auto/qmediaimageviewer/images/coverart.png b/tests/auto/qmediaimageviewer/images/coverart.png new file mode 100644 index 000000000..a24db1b13 Binary files /dev/null and b/tests/auto/qmediaimageviewer/images/coverart.png differ diff --git a/tests/auto/qmediaimageviewer/images/image.jpg b/tests/auto/qmediaimageviewer/images/image.jpg new file mode 100644 index 000000000..8771224cb Binary files /dev/null and b/tests/auto/qmediaimageviewer/images/image.jpg differ diff --git a/tests/auto/qmediaimageviewer/images/image.png b/tests/auto/qmediaimageviewer/images/image.png new file mode 100644 index 000000000..a24db1b13 Binary files /dev/null and b/tests/auto/qmediaimageviewer/images/image.png differ diff --git a/tests/auto/qmediaimageviewer/images/invalid.png b/tests/auto/qmediaimageviewer/images/invalid.png new file mode 100644 index 000000000..3aba327ee --- /dev/null +++ b/tests/auto/qmediaimageviewer/images/invalid.png @@ -0,0 +1,2 @@ +This is not really a PNG file. + diff --git a/tests/auto/qmediaimageviewer/images/poster.png b/tests/auto/qmediaimageviewer/images/poster.png new file mode 100644 index 000000000..a24db1b13 Binary files /dev/null and b/tests/auto/qmediaimageviewer/images/poster.png differ diff --git a/tests/auto/qmediaimageviewer/qmediaimageviewer.pro b/tests/auto/qmediaimageviewer/qmediaimageviewer.pro new file mode 100644 index 000000000..dab1d2462 --- /dev/null +++ b/tests/auto/qmediaimageviewer/qmediaimageviewer.pro @@ -0,0 +1,17 @@ +load(qttest_p4) + +QT += multimediakit-private network + +# TARGET = tst_qmediaimageviewer +# CONFIG += testcase + +SOURCES += tst_qmediaimageviewer.cpp + +RESOURCES += \ + images.qrc + +!contains(QT_CONFIG, no-jpeg):DEFINES += QTEST_HAVE_JPEG + +wince* { + !contains(QT_CONFIG, no-jpeg): DEPLOYMENT_PLUGIN += qjpeg +} diff --git a/tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp b/tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp new file mode 100644 index 000000000..2bd56cf39 --- /dev/null +++ b/tests/auto/qmediaimageviewer/tst_qmediaimageviewer.cpp @@ -0,0 +1,1036 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +QT_USE_NAMESPACE +class QtTestNetworkAccessManager; + +class tst_QMediaImageViewer : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + + void isValid(); + void timeout(); + void setMedia_data(); + void setMedia(); + void setConsecutiveMedia(); + void setInvalidMedia(); + void playlist(); + void multiplePlaylists(); + void invalidPlaylist(); + void elapsedTime(); + void rendererControl(); + void setVideoOutput(); + void debugEnums(); + +public: + tst_QMediaImageViewer() : m_network(0) {} + +private: + QUrl imageUrl(const char *fileName) const { + return QUrl(QLatin1String("qrc:///images/") + QLatin1String(fileName)); } + QString imageFileName(const char *fileName) { + return QLatin1String(":/images/") + QLatin1String(fileName); } + + QtTestNetworkAccessManager *m_network; + QString m_fileProtocol; +}; + +class QtTestVideoSurface : public QAbstractVideoSurface +{ +public: + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const { + QList formats; + if (handleType == QAbstractVideoBuffer::NoHandle) { + formats << QVideoFrame::Format_RGB32; + } + return formats; + } + + QVideoFrame frame() const { return m_frame; } + + bool present(const QVideoFrame &frame) { m_frame = frame; return true; } + +private: + QVideoFrame m_frame; +}; + +class QtTestNetworkReply : public QNetworkReply +{ +public: + QtTestNetworkReply( + const QNetworkRequest &request, + const QByteArray &mimeType, + QObject *parent) + : QNetworkReply(parent) + { + setRequest(request); + setOperation(QNetworkAccessManager::HeadOperation); + setRawHeader("content-type", mimeType); + + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + + QtTestNetworkReply( + const QNetworkRequest &request, + const QByteArray &mimeType, + const QString &fileName, + QObject *parent) + : QNetworkReply(parent) + , m_file(fileName) + { + setRequest(request); + setOperation(QNetworkAccessManager::GetOperation); + setRawHeader("content-type", mimeType); + + if (m_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) { + setOpenMode(QIODevice::ReadOnly); + } + + QCoreApplication::postEvent(this, new QEvent(QEvent::User)); + } + + void abort() { m_file.close(); } + + bool atEnd () const { return m_file.atEnd(); } + qint64 bytesAvailable() const { return m_file.bytesAvailable() + QIODevice::bytesAvailable(); } + void close() { m_file.close(); setOpenMode(QIODevice::NotOpen); } + bool isSequential() const { return true; } + bool open(OpenMode) { return false; } + qint64 pos() const { return 0; } + bool seek(qint64) { return false; } + qint64 size() const { return m_file.size(); } + qint64 readData(char * data, qint64 maxSize) { return m_file.read(data, maxSize); } + qint64 writeData(const char *, qint64) { return -1; } + +protected: + void customEvent(QEvent *event) + { + if (event->type() == QEvent::User) { + event->accept(); + emit finished(); + } + } + +private: + QFile m_file; +}; + +class QtTestNetworkAccessManager : public QNetworkAccessManager +{ +public: + QtTestNetworkAccessManager(QObject *parent = 0) + : QNetworkAccessManager(parent) + { + } + + void appendDocument(const QUrl &url, const QByteArray &mimeType, const QString &fileName) + { + m_documents.append(Document(url, mimeType, fileName)); + } + +protected: + QNetworkReply *createRequest( + Operation op, const QNetworkRequest &request, QIODevice *outgoingData = 0) + { + foreach (const Document &document, m_documents) { + if (document.url == request.url()) { + if (op == GetOperation) { + return new QtTestNetworkReply( + request, document.mimeType, document.fileName, this); + } else if (op == HeadOperation) { + return new QtTestNetworkReply(request, document.mimeType, this); + } + } + } + return QNetworkAccessManager::createRequest(op, request, outgoingData); + } + +private: + struct Document + { + Document(const QUrl url, const QByteArray mimeType, const QString &fileName) + : url(url), mimeType(mimeType), fileName(fileName) + { + } + + QUrl url; + QByteArray mimeType; + QString fileName; + }; + + QList m_documents; +}; + +void tst_QMediaImageViewer::initTestCase() +{ + qRegisterMetaType(); + qRegisterMetaType(); + + m_network = new QtTestNetworkAccessManager(this); + + m_network->appendDocument( + QUrl(QLatin1String("test://image/png?id=1")), + "image/png", + imageFileName("image.png")); + m_network->appendDocument( + QUrl(QLatin1String("test://image/png?id=2")), + QByteArray(), + imageFileName("image.png")); + m_network->appendDocument( + QUrl(QLatin1String("test://image/invalid?id=1")), + "image/png", + imageFileName("invalid.png")); + m_network->appendDocument( + QUrl(QLatin1String("test://image/invalid?id=2")), + QByteArray(), + imageFileName("invalid.png")); +#ifdef QTEST_HAVE_JPEG + m_network->appendDocument( + QUrl(QLatin1String("test://image/jpeg?id=1")), + "image/jpeg", + imageFileName("image.jpg")); +#endif + m_network->appendDocument( + QUrl(QLatin1String("test://music/songs/mp3?id=1")), + "audio/mpeg", + QString()); + m_network->appendDocument( + QUrl(QLatin1String("test://music/covers/small?id=1")), + "image/png", + imageFileName("coverart.png")); + m_network->appendDocument( + QUrl(QLatin1String("test://music/covers/large?id=1")), + "image/png", + imageFileName("coverart.png")); + m_network->appendDocument( + QUrl(QLatin1String("test://video/movies/mp4?id=1")), + "video/mp4", + QString()); + m_network->appendDocument( + QUrl(QLatin1String("test://video/posters/png?id=1")), + "image/png", + imageFileName("poster.png")); +} + +void tst_QMediaImageViewer::isValid() +{ + QMediaImageViewer viewer; + + QVERIFY(viewer.service() != 0); +} + +void tst_QMediaImageViewer::timeout() +{ + QMediaImageViewer viewer; + + QCOMPARE(viewer.timeout(), 3000); + + viewer.setTimeout(0); + QCOMPARE(viewer.timeout(), 0); + + viewer.setTimeout(45); + QCOMPARE(viewer.timeout(), 45); + + viewer.setTimeout(-3000); + QCOMPARE(viewer.timeout(), 0); +} + +void tst_QMediaImageViewer::setMedia_data() +{ + QTest::addColumn("media"); + + { + QMediaContent media(imageUrl("image.png")); + + QTest::newRow("file: png image") + << media; + } { + QMediaContent media(QUrl(QLatin1String("test://image/png?id=1"))); + + QTest::newRow("network: png image") + << media; + } { + QMediaContent media(QMediaResource( + QUrl(QLatin1String("test://image/png?id=1")), QLatin1String("image/png"))); + + QTest::newRow("network: png image, explicit mime type") + << media; + } { + QMediaContent media(QUrl(QLatin1String("test://image/png?id=2"))); + + QTest::newRow("network: png image, no mime type") + << media; +#ifdef QTEST_HAVE_JPEG + } { + QMediaContent media(imageUrl("image.jpg")); + + QTest::newRow("file: jpg image") + << media; + } { + QMediaContent media(QUrl(QLatin1String("test://image/jpeg?id=1"))); + + QTest::newRow("network: jpg image") + << media; +#endif + } +} + +void tst_QMediaImageViewer::setMedia() +{ + QFETCH(QMediaContent, media); + + QMediaImageViewer viewer; + + QMediaImageViewerService *service = qobject_cast(viewer.service()); + service->setNetworkManager(m_network); + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + viewer.setMedia(media); + QCOMPARE(viewer.media(), media); + + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); +} + +void tst_QMediaImageViewer::setConsecutiveMedia() +{ + QMediaContent fileMedia1(imageUrl("image.png")); + QMediaContent fileMedia2(imageUrl("coverart.png")); + QMediaContent networkMedia1(QUrl(QLatin1String("test://image/png?id=1"))); + QMediaContent networkMedia2(QUrl(QLatin1String("test://image/png?id=2"))); + + QMediaImageViewer viewer; + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + viewer.setMedia(fileMedia1); + viewer.setMedia(fileMedia2); + + QCOMPARE(viewer.media(), fileMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.media(), fileMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + + QMediaImageViewerService *service = qobject_cast(viewer.service()); + service->setNetworkManager(m_network); + + viewer.setMedia(networkMedia1); + viewer.setMedia(networkMedia2); + + QCOMPARE(viewer.media(), networkMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.media(), networkMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + + viewer.setMedia(fileMedia1); + viewer.setMedia(networkMedia2); + + QCOMPARE(viewer.media(), networkMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.media(), networkMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + + viewer.setMedia(networkMedia1); + viewer.setMedia(fileMedia2); + + QCOMPARE(viewer.media(), fileMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.media(), fileMedia2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); +} + +void tst_QMediaImageViewer::setInvalidMedia() +{ + QMediaImageViewer viewer; + + QMediaImageViewerService *service = qobject_cast(viewer.service()); + service->setNetworkManager(m_network); + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + { + QMediaContent media(imageUrl("invalid.png")); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaContent media(imageUrl("deleted.png")); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaResource invalidResource(imageUrl("invalid.png")); + QMediaResource deletedResource(imageUrl("deleted.png")); + QMediaContent media(QMediaResourceList() << invalidResource << deletedResource); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaResource resource(imageUrl("image.png"), QLatin1String("audio/mpeg")); + QMediaContent media(resource); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaResource audioResource(imageUrl("image.png"), QLatin1String("audio/mpeg")); + QMediaResource invalidResource(imageUrl("invalid.png")); + QMediaContent media(QMediaResourceList() << audioResource << invalidResource); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaContent media(QUrl(QLatin1String("test://image/invalid?id=1"))); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaContent media(QUrl(QLatin1String("test://image/invalid?id=2"))); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } { + QMediaContent media(QUrl(QLatin1String("test://image/invalid?id=3"))); + + viewer.setMedia(media); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::InvalidMedia); + QCOMPARE(viewer.media(), media); + } +} + +void tst_QMediaImageViewer::playlist() +{ + QMediaContent imageMedia(imageUrl("image.png")); + QMediaContent posterMedia(imageUrl("poster.png")); + QMediaContent coverArtMedia(imageUrl("coverart.png")); + + QMediaImageViewer viewer; + viewer.setTimeout(250); + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + QSignalSpy stateSpy(&viewer, SIGNAL(stateChanged(QMediaImageViewer::State))); + + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + + // No playlist so can't exit stopped state. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 0); + viewer.pause(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 0); + + QMediaPlaylist playlist; + viewer.setPlaylist(&playlist); + + // Empty playlist so can't exit stopped state. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 0); + viewer.pause(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 0); + + playlist.addMedia(imageMedia); + playlist.addMedia(posterMedia); + playlist.addMedia(coverArtMedia); + + // Play progresses immediately to the first image and starts loading. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(qvariant_cast(stateSpy.last().value(0)), + QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(viewer.media(), imageMedia); + + // Image is loaded asynchronously. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 0); + + // Time out causes progression to second image, which starts loading. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + QCOMPARE(playlist.currentIndex(), 1); + QCOMPARE(viewer.media(), posterMedia); + + // Image is loaded asynchronously. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 1); + + // Pausing stops progression at current image. + viewer.pause(); + QCOMPARE(viewer.state(), QMediaImageViewer::PausedState); + QCOMPARE(stateSpy.count(), 2); + QCOMPARE(qvariant_cast(stateSpy.last().value(0)), + QMediaImageViewer::PausedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 1); + + // No time out. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::PausedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 1); + + // Resuming playback does not immediately progress to the next item + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 1); + + // Time out causes progression to next image, which starts loading. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + QCOMPARE(playlist.currentIndex(), 2); + QCOMPARE(viewer.media(), coverArtMedia); + + // Image is loaded asynchronously. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 2); + + // Time out causes progression to end of list + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 4); + QCOMPARE(qvariant_cast(stateSpy.last().value(0)), + QMediaImageViewer::StoppedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia); + QCOMPARE(playlist.currentIndex(), -1); + QCOMPARE(viewer.media(), QMediaContent()); + + // Stopped, no time out. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia); + QCOMPARE(playlist.currentIndex(), -1); + + // Play progresses immediately to the first image and starts loading. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(stateSpy.count(), 5); + QCOMPARE(qvariant_cast(stateSpy.last().value(0)), + QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(viewer.media(), imageMedia); + + // Image is loaded asynchronously. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 0); + + // Stop ends progress, but retains current index. + viewer.stop(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 6); + QCOMPARE(qvariant_cast(stateSpy.last().value(0)), + QMediaImageViewer::StoppedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(viewer.media(), imageMedia); + + // Stoppped, No time out. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(viewer.media(), imageMedia); + + // Stop when already stopped doesn't emit additional signals. + viewer.stop(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 6); + + viewer.play(); + QCOMPARE(stateSpy.count(), 7); + + // Play when already playing doesn't emit additional signals. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(stateSpy.count(), 7); + + playlist.next(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + // Pausing while loading, doesn't stop loading. + viewer.pause(); + QCOMPARE(viewer.state(), QMediaImageViewer::PausedState); + QCOMPARE(stateSpy.count(), 8); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::PausedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadedMedia); + + // Pause while paused doesn't emit additional signals. + viewer.pause(); + QCOMPARE(viewer.state(), QMediaImageViewer::PausedState); + QCOMPARE(stateSpy.count(), 8); + + // Calling setMedia stops the playlist. + viewer.setMedia(imageMedia); + QCOMPARE(viewer.media(), imageMedia); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(stateSpy.count(), 9); + QCOMPARE(qvariant_cast(stateSpy.last().value(0)), + QMediaImageViewer::StoppedState); + +} + +void tst_QMediaImageViewer::multiplePlaylists() +{ + QMediaContent imageMedia(imageUrl("image.png")); + QMediaContent posterMedia(imageUrl("poster.png")); + QMediaContent coverArtMedia(imageUrl("coverart.png")); + + QMediaImageViewer viewer; + + QMediaPlaylist *playlist1 = new QMediaPlaylist; + viewer.setPlaylist(playlist1); + playlist1->addMedia(imageMedia); + playlist1->addMedia(posterMedia); + + playlist1->setCurrentIndex(0); + QCOMPARE(viewer.media(), imageMedia); + + QMediaPlaylist *playlist2 = new QMediaPlaylist; + + viewer.setPlaylist(playlist2); + playlist2->addMedia(coverArtMedia); + + QVERIFY(viewer.media().isNull()); + + playlist2->setCurrentIndex(0); + QCOMPARE(viewer.media(), coverArtMedia); + + delete playlist2; + QVERIFY(viewer.media().isNull()); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + + viewer.setPlaylist(playlist1); + playlist1->setCurrentIndex(0); + QCOMPARE(viewer.media(), imageMedia); + + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + + delete playlist1; + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); +} + + +void tst_QMediaImageViewer::invalidPlaylist() +{ + QMediaContent imageMedia(imageUrl("image.png")); + QMediaContent invalidMedia(imageUrl("invalid.png")); + + QMediaImageViewer viewer; + viewer.setTimeout(250); + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + QSignalSpy stateSpy(&viewer, SIGNAL(stateChanged(QMediaImageViewer::State))); + QSignalSpy statusSpy(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus))); + + QMediaPlaylist playlist; + viewer.setPlaylist(&playlist); + playlist.addMedia(invalidMedia); + playlist.addMedia(imageMedia); + playlist.addMedia(invalidMedia); + + // Test play initially tries to load the first invalid image. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + QCOMPARE(viewer.media(), invalidMedia); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(statusSpy.count(), 1); + QCOMPARE(qvariant_cast(statusSpy.value(0).value(0)), + QMediaImageViewer::LoadingMedia); + + // Test status is changed to InvalidMedia, and loading of the next image is started immediately. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::LoadingMedia); + QCOMPARE(viewer.media(), imageMedia); + QCOMPARE(playlist.currentIndex(), 1); + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(qvariant_cast(statusSpy.value(1).value(0)), + QMediaImageViewer::InvalidMedia); + QCOMPARE(qvariant_cast(statusSpy.value(2).value(0)), + QMediaImageViewer::LoadingMedia); + + // Test if the last image is invalid, the image viewer is stopped. + playlist.next(); + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia); + QCOMPARE(playlist.currentIndex(), -1); + QCOMPARE(stateSpy.count(), 2); + + playlist.setCurrentIndex(2); + QTestEventLoop::instance().enterLoop(2); + + // Test play immediately moves to the next item if the current one is invalid, and no state + // change signals are emitted if the viewer never effectively moves from the StoppedState. + viewer.play(); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + QCOMPARE(viewer.mediaStatus(), QMediaImageViewer::NoMedia); + QCOMPARE(playlist.currentIndex(), -1); + QCOMPARE(stateSpy.count(), 2); +} + +void tst_QMediaImageViewer::elapsedTime() +{ + QMediaContent imageMedia(imageUrl("image.png")); + + QMediaImageViewer viewer; + viewer.setTimeout(250); + viewer.setNotifyInterval(150); + + QSignalSpy spy(&viewer, SIGNAL(elapsedTimeChanged(int))); + + connect(&viewer, SIGNAL(elapsedTimeChanged(int)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + + QMediaPlaylist playlist; + viewer.setPlaylist(&playlist); + playlist.addMedia(imageMedia); + + QCOMPARE(viewer.elapsedTime(), 0); + + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(spy.count(), 0); + + viewer.play(); + QCOMPARE(viewer.elapsedTime(), 0); + + // Emits an initial elapsed time at 0 milliseconds signal when the image is loaded. + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().value(0).toInt(), 0); + + // Emits a scheduled signal after the notify interval is up. The exact time will be a little + // fuzzy. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(spy.count(), 2); + QVERIFY(spy.last().value(0).toInt() != 0); + + // Pausing will emit a signal with the elapsed time when paused. + viewer.pause(); + QCOMPARE(spy.count(), 3); + QCOMPARE(viewer.elapsedTime(), spy.last().value(0).toInt()); + + // No elapsed time signals will be emitted while paused. + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(spy.count(), 3); + + // Stopping a paused viewer resets the elapsed time to 0 with signals emitted. + viewer.stop(); + QCOMPARE(viewer.elapsedTime(), 0); + QCOMPARE(spy.count(), 4); + QCOMPARE(spy.last().value(0).toInt(), 0); + + disconnect(&viewer, SIGNAL(elapsedTimeChanged(int)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + // Play until end. + viewer.play(); + QTestEventLoop::instance().enterLoop(2); + + // Verify at least two more signals are emitted. + // The second to last at the instant the timeout expired, and the last as it's reset when the + // current media is cleared. + QVERIFY(spy.count() >= 5); + QCOMPARE(spy.value(spy.count() - 2).value(0).toInt(), 250); + QCOMPARE(spy.value(spy.count() - 1).value(0).toInt(), 0); + + viewer.play(); + QTestEventLoop::instance().enterLoop(2); + + // Test extending the timeout applies to an already loaded image. + viewer.setTimeout(10000); + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::PlayingState); + + // Test reducing the timeout applies to an already loaded image. + viewer.setTimeout(1000); + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(viewer.state(), QMediaImageViewer::StoppedState); + +} + +void tst_QMediaImageViewer::rendererControl() +{ + QtTestVideoSurface surfaceA; + QtTestVideoSurface surfaceB; + QAbstractVideoSurface *nullSurface = 0; + + QMediaImageViewer viewer; + + QMediaService *service = viewer.service(); + if (service == 0) + QSKIP("Image viewer object has no service.", SkipSingle); + + QMediaControl *mediaControl = service->requestControl(QVideoRendererControl_iid); + QVERIFY(mediaControl != 0); + + QVideoRendererControl *rendererControl = qobject_cast(mediaControl); + QVERIFY(rendererControl != 0); + + rendererControl->setSurface(&surfaceA); + QCOMPARE(rendererControl->surface(), (QAbstractVideoSurface *)&surfaceA); + + // Load an image so the viewer has some dimensions to work with. + viewer.setMedia(QMediaContent(imageUrl("image.png"))); + + connect(&viewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(2); + + if (viewer.mediaStatus() != QMediaImageViewer::LoadedMedia) + QSKIP("failed to load test image", SkipSingle); + + QCOMPARE(surfaceA.isActive(), true); + + { + QVideoSurfaceFormat format = surfaceA.surfaceFormat(); + QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(format.pixelFormat(), QVideoFrame::Format_RGB32); + QCOMPARE(format.frameSize(), QSize(75, 50)); + + QVideoFrame frame = surfaceA.frame(); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_RGB32); + QCOMPARE(frame.size(), QSize(75, 50)); + } + // Test clearing the output stops the video surface. + service->releaseControl(rendererControl); + QCOMPARE(surfaceA.isActive(), false); + + // Test reseting the output restarts it. + mediaControl = service->requestControl(QVideoRendererControl_iid); + QVERIFY(mediaControl != 0); + + rendererControl = qobject_cast(mediaControl); + rendererControl->setSurface(&surfaceA); + QVERIFY(rendererControl != 0); + { + QVideoSurfaceFormat format = surfaceA.surfaceFormat(); + QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(format.pixelFormat(), QVideoFrame::Format_RGB32); + QCOMPARE(format.frameSize(), QSize(75, 50)); + + QVideoFrame frame = surfaceA.frame(); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_RGB32); + QCOMPARE(frame.size(), QSize(75, 50)); + } + + // Test changing the surface while viewing an image stops the old surface and starts + // the new one and presents the image. + rendererControl->setSurface(&surfaceB); + QCOMPARE(rendererControl->surface(), (QAbstractVideoSurface*)&surfaceB); + + QCOMPARE(surfaceA.isActive(), false); + QCOMPARE(surfaceB.isActive(), true); + + QVideoSurfaceFormat format = surfaceB.surfaceFormat(); + QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(format.pixelFormat(), QVideoFrame::Format_RGB32); + QCOMPARE(format.frameSize(), QSize(75, 50)); + + QVideoFrame frame = surfaceB.frame(); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_RGB32); + QCOMPARE(frame.size(), QSize(75, 50)); + + // Test setting null media stops the surface. + viewer.setMedia(QMediaContent()); + QCOMPARE(surfaceB.isActive(), false); + + // Test the renderer control accepts a null surface. + rendererControl->setSurface(0); + QCOMPARE(rendererControl->surface(), nullSurface); +} + +void tst_QMediaImageViewer::setVideoOutput() +{ + QMediaImageViewer imageViewer; + imageViewer.setMedia(QMediaContent(imageUrl("image.png"))); + + connect(&imageViewer, SIGNAL(mediaStatusChanged(QMediaImageViewer::MediaStatus)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(2); + + if (imageViewer.mediaStatus() != QMediaImageViewer::LoadedMedia) + QSKIP("failed to load test image", SkipSingle); + + QVideoWidget widget; + QGraphicsVideoItem item; + QtTestVideoSurface surface; + + imageViewer.setVideoOutput(&widget); + QVERIFY(widget.mediaObject() == &imageViewer); + + imageViewer.setVideoOutput(&item); + QVERIFY(widget.mediaObject() == 0); + QVERIFY(item.mediaObject() == &imageViewer); + + imageViewer.setVideoOutput(reinterpret_cast(0)); + QVERIFY(item.mediaObject() == 0); + + imageViewer.setVideoOutput(&widget); + QVERIFY(widget.mediaObject() == &imageViewer); + + imageViewer.setVideoOutput(reinterpret_cast(0)); + QVERIFY(widget.mediaObject() == 0); + + imageViewer.setVideoOutput(&surface); + QVERIFY(surface.isActive()); + + imageViewer.setVideoOutput(reinterpret_cast(0)); + QVERIFY(!surface.isActive()); + + imageViewer.setVideoOutput(&surface); + QVERIFY(surface.isActive()); + + imageViewer.setVideoOutput(&widget); + QVERIFY(!surface.isActive()); + QVERIFY(widget.mediaObject() == &imageViewer); + + imageViewer.setVideoOutput(&surface); + QVERIFY(surface.isActive()); + QVERIFY(widget.mediaObject() == 0); +} + +void tst_QMediaImageViewer::debugEnums() +{ + QTest::ignoreMessage(QtDebugMsg, "QMediaImageViewer::PlayingState "); + qDebug() << QMediaImageViewer::PlayingState; + QTest::ignoreMessage(QtDebugMsg, "QMediaImageViewer::NoMedia "); + qDebug() << QMediaImageViewer::NoMedia; +} + +QTEST_MAIN(tst_QMediaImageViewer) + +#include "tst_qmediaimageviewer.moc" diff --git a/tests/auto/qmediaobject/main.cpp b/tests/auto/qmediaobject/main.cpp new file mode 100644 index 000000000..4dc763f11 --- /dev/null +++ b/tests/auto/qmediaobject/main.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#include +#include + +#include "tst_qmediaobject.h" +#ifdef Q_OS_SYMBIAN +#include "tst_qmediaobject_xa.h" +#include "tst_qmediaobject_mmf.h" +#endif + +int main(int argc, char**argv) +{ + QApplication app(argc,argv); + int ret; + tst_QMediaObject test_api; + ret = QTest::qExec(&test_api, argc, argv); +#ifdef Q_OS_SYMBIAN + char *new_argv[3]; + QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_xa.log"; + QByteArray bytes = str.toAscii(); + char arg1[] = "-o"; + new_argv[0] = argv[0]; + new_argv[1] = arg1; + new_argv[2] = bytes.data(); + tst_QMetadata_xa test_xa; + ret = QTest::qExec(&test_xa, 3, new_argv); + char *new_argv1[3]; + QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log"; + QByteArray bytes1 = str1.toAscii(); + char arg2[] = "-o"; + new_argv1[0] = argv[0]; + new_argv1[1] = arg2; + new_argv1[2] = bytes1.data(); + tst_QMediaObject_mmf test_mmf; + ret = QTest::qExec(&test_mmf, 3, new_argv1); +#endif + return ret; +} diff --git a/tests/auto/qmediaobject/qmediaobject.pro b/tests/auto/qmediaobject/qmediaobject.pro new file mode 100644 index 000000000..756603ad7 --- /dev/null +++ b/tests/auto/qmediaobject/qmediaobject.pro @@ -0,0 +1,27 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediaobject +# CONFIG += testcase + +symbian { + HEADERS += tst_qmediaobject_xa.h + SOURCES += tst_qmediaobject_xa.cpp + TARGET.CAPABILITY = ALL -TCB + + testFiles.sources = testfiles/* + testFiles.path = /Data/testfiles + DEPLOYMENT += testFiles + HEADERS += tst_qmediaobject_mmf.h + SOURCES += tst_qmediaobject_mmf.cpp + TARGET.CAPABILITY = ALL -TCB + + testFiles.sources = testfiles/* + testFiles.path = /Data/testfiles + DEPLOYMENT += testFiles +} + +HEADERS+= tst_qmediaobject.h +SOURCES += main.cpp tst_qmediaobject.cpp + diff --git a/tests/auto/qmediaobject/tst_qmediaobject.cpp b/tests/auto/qmediaobject/tst_qmediaobject.cpp new file mode 100644 index 000000000..b286c4ed9 --- /dev/null +++ b/tests/auto/qmediaobject/tst_qmediaobject.cpp @@ -0,0 +1,359 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include "tst_qmediaobject.h" + +QT_USE_NAMESPACE + +void tst_QMediaObject::propertyWatch() +{ + QtTestMediaObject object; + object.setNotifyInterval(0); + + QEventLoop loop; + connect(&object, SIGNAL(aChanged(int)), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&object, SIGNAL(bChanged(int)), &QTestEventLoop::instance(), SLOT(exitLoop())); + connect(&object, SIGNAL(cChanged(int)), &QTestEventLoop::instance(), SLOT(exitLoop())); + + QSignalSpy aSpy(&object, SIGNAL(aChanged(int))); + QSignalSpy bSpy(&object, SIGNAL(bChanged(int))); + QSignalSpy cSpy(&object, SIGNAL(cChanged(int))); + + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(aSpy.count(), 0); + QCOMPARE(bSpy.count(), 0); + QCOMPARE(cSpy.count(), 0); + + int aCount = 0; + int bCount = 0; + int cCount = 0; + + object.addPropertyWatch("a"); + + QTestEventLoop::instance().enterLoop(1); + + QVERIFY(aSpy.count() > aCount); + QCOMPARE(bSpy.count(), 0); + QCOMPARE(cSpy.count(), 0); + QCOMPARE(aSpy.last().value(0).toInt(), 0); + + aCount = aSpy.count(); + + object.setA(54); + object.setB(342); + object.setC(233); + + QTestEventLoop::instance().enterLoop(1); + + QVERIFY(aSpy.count() > aCount); + QCOMPARE(bSpy.count(), 0); + QCOMPARE(cSpy.count(), 0); + QCOMPARE(aSpy.last().value(0).toInt(), 54); + + aCount = aSpy.count(); + + object.addPropertyWatch("b"); + object.addPropertyWatch("d"); + object.removePropertyWatch("e"); + object.setA(43); + object.setB(235); + object.setC(90); + + QTestEventLoop::instance().enterLoop(1); + + QVERIFY(aSpy.count() > aCount); + QVERIFY(bSpy.count() > bCount); + QCOMPARE(cSpy.count(), 0); + QCOMPARE(aSpy.last().value(0).toInt(), 43); + QCOMPARE(bSpy.last().value(0).toInt(), 235); + + aCount = aSpy.count(); + bCount = bSpy.count(); + + object.removePropertyWatch("a"); + object.addPropertyWatch("c"); + object.addPropertyWatch("e"); + + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(aSpy.count(), aCount); + QVERIFY(bSpy.count() > bCount); + QVERIFY(cSpy.count() > cCount); + QCOMPARE(bSpy.last().value(0).toInt(), 235); + QCOMPARE(cSpy.last().value(0).toInt(), 90); + + bCount = bSpy.count(); + cCount = cSpy.count(); + + object.setA(435); + object.setC(9845); + + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(aSpy.count(), aCount); + QVERIFY(bSpy.count() > bCount); + QVERIFY(cSpy.count() > cCount); + QCOMPARE(bSpy.last().value(0).toInt(), 235); + QCOMPARE(cSpy.last().value(0).toInt(), 9845); + + bCount = bSpy.count(); + cCount = cSpy.count(); + + object.setA(8432); + object.setB(324); + object.setC(443); + object.removePropertyWatch("c"); + object.removePropertyWatch("d"); + + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(aSpy.count(), aCount); + QVERIFY(bSpy.count() > bCount); + QCOMPARE(cSpy.count(), cCount); + QCOMPARE(bSpy.last().value(0).toInt(), 324); + QCOMPARE(cSpy.last().value(0).toInt(), 9845); + + bCount = bSpy.count(); + + object.removePropertyWatch("b"); + + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(aSpy.count(), aCount); + QCOMPARE(bSpy.count(), bCount); + QCOMPARE(cSpy.count(), cCount); +} + +void tst_QMediaObject::setupNotifyTests() +{ + QTest::addColumn("interval"); + QTest::addColumn("count"); + + QTest::newRow("single 750ms") + << 750 + << 1; + QTest::newRow("single 600ms") + << 600 + << 1; + QTest::newRow("x3 300ms") + << 300 + << 3; + QTest::newRow("x5 180ms") + << 180 + << 5; +} + +void tst_QMediaObject::notifySignals_data() +{ + setupNotifyTests(); +} + +void tst_QMediaObject::notifySignals() +{ + QFETCH(int, interval); + QFETCH(int, count); + + QtTestMediaObject object; + object.setNotifyInterval(interval); + object.addPropertyWatch("a"); + + QSignalSpy spy(&object, SIGNAL(aChanged(int))); + + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(spy.count(), count); +} + +void tst_QMediaObject::notifyInterval_data() +{ + setupNotifyTests(); +} + +void tst_QMediaObject::notifyInterval() +{ + QFETCH(int, interval); + + QtTestMediaObject object; + QSignalSpy spy(&object, SIGNAL(notifyIntervalChanged(int))); + + object.setNotifyInterval(interval); + QCOMPARE(object.notifyInterval(), interval); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().value(0).toInt(), interval); + + object.setNotifyInterval(interval); + QCOMPARE(object.notifyInterval(), interval); + QCOMPARE(spy.count(), 1); +} + +void tst_QMediaObject::nullMetaDataControl() +{ + const QString titleKey(QLatin1String("Title")); + const QString title(QLatin1String("Host of Seraphim")); + + QtTestMetaDataService service; + service.hasMetaData = false; + + QtTestMediaObject object(&service); + + QSignalSpy spy(&object, SIGNAL(metaDataChanged())); + + QCOMPARE(object.isMetaDataAvailable(), false); + + QCOMPARE(object.metaData(QtMultimediaKit::Title).toString(), QString()); + QCOMPARE(object.extendedMetaData(titleKey).toString(), QString()); + QCOMPARE(object.availableMetaData(), QList()); + QCOMPARE(object.availableExtendedMetaData(), QStringList()); + QCOMPARE(spy.count(), 0); +} + +void tst_QMediaObject::isMetaDataAvailable() +{ + QtTestMetaDataService service; + service.metaData.setMetaDataAvailable(false); + + QtTestMediaObject object(&service); + QCOMPARE(object.isMetaDataAvailable(), false); + + QSignalSpy spy(&object, SIGNAL(metaDataAvailableChanged(bool))); + service.metaData.setMetaDataAvailable(true); + + QCOMPARE(object.isMetaDataAvailable(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toBool(), true); + + service.metaData.setMetaDataAvailable(false); + + QCOMPARE(object.isMetaDataAvailable(), false); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.at(1).at(0).toBool(), false); +} + +void tst_QMediaObject::metaDataChanged() +{ + QtTestMetaDataService service; + QtTestMediaObject object(&service); + + QSignalSpy spy(&object, SIGNAL(metaDataChanged())); + + service.metaData.metaDataChanged(); + QCOMPARE(spy.count(), 1); + + service.metaData.metaDataChanged(); + QCOMPARE(spy.count(), 2); +} + +void tst_QMediaObject::metaData_data() +{ + QTest::addColumn("artist"); + QTest::addColumn("title"); + QTest::addColumn("genre"); + + QTest::newRow("") + << QString::fromLatin1("Dead Can Dance") + << QString::fromLatin1("Host of Seraphim") + << QString::fromLatin1("Awesome"); +} + +void tst_QMediaObject::metaData() +{ + QFETCH(QString, artist); + QFETCH(QString, title); + QFETCH(QString, genre); + + QtTestMetaDataService service; + service.metaData.populateMetaData(); + + QtTestMediaObject object(&service); + QVERIFY(object.availableMetaData().isEmpty()); + + service.metaData.m_data.insert(QtMultimediaKit::AlbumArtist, artist); + service.metaData.m_data.insert(QtMultimediaKit::Title, title); + service.metaData.m_data.insert(QtMultimediaKit::Genre, genre); + + QCOMPARE(object.metaData(QtMultimediaKit::AlbumArtist).toString(), artist); + QCOMPARE(object.metaData(QtMultimediaKit::Title).toString(), title); + + QList metaDataKeys = object.availableMetaData(); + QCOMPARE(metaDataKeys.size(), 3); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::AlbumArtist)); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::Title)); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::Genre)); +} + +void tst_QMediaObject::extendedMetaData() +{ + QFETCH(QString, artist); + QFETCH(QString, title); + QFETCH(QString, genre); + + QtTestMetaDataService service; + QtTestMediaObject object(&service); + QVERIFY(object.availableExtendedMetaData().isEmpty()); + + service.metaData.m_extendedData.insert(QLatin1String("Artist"), artist); + service.metaData.m_extendedData.insert(QLatin1String("Title"), title); + service.metaData.m_extendedData.insert(QLatin1String("Genre"), genre); + + QCOMPARE(object.extendedMetaData(QLatin1String("Artist")).toString(), artist); + QCOMPARE(object.extendedMetaData(QLatin1String("Title")).toString(), title); + + QStringList extendedKeys = object.availableExtendedMetaData(); + QCOMPARE(extendedKeys.size(), 3); + QVERIFY(extendedKeys.contains(QLatin1String("Artist"))); + QVERIFY(extendedKeys.contains(QLatin1String("Title"))); + QVERIFY(extendedKeys.contains(QLatin1String("Genre"))); +} + +void tst_QMediaObject::availability() +{ + QtTestMediaObject nullObject(0); + QCOMPARE(nullObject.isAvailable(), false); + QCOMPARE(nullObject.availabilityError(), QtMultimediaKit::ServiceMissingError); + + QtTestMetaDataService service; + QtTestMediaObject object(&service); + QCOMPARE(object.isAvailable(), true); + QCOMPARE(object.availabilityError(), QtMultimediaKit::NoError); +} diff --git a/tests/auto/qmediaobject/tst_qmediaobject.h b/tests/auto/qmediaobject/tst_qmediaobject.h new file mode 100644 index 000000000..3b46f752f --- /dev/null +++ b/tests/auto/qmediaobject/tst_qmediaobject.h @@ -0,0 +1,177 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QMEDIAOBJECT_H +#define TST_QMEDIAOBJECT_H + +#include + +#include + +#include +#include +#include + +//TESTED_COMPONENT=src/multimedia + +QT_USE_NAMESPACE +class tst_QMediaObject : public QObject +{ + Q_OBJECT + +private slots: + void propertyWatch(); + void notifySignals_data(); + void notifySignals(); + void notifyInterval_data(); + void notifyInterval(); + + void nullMetaDataControl(); + void isMetaDataAvailable(); + void metaDataChanged(); + void metaData_data(); + void metaData(); + void availability(); + void extendedMetaData_data() { metaData_data(); } + void extendedMetaData(); + + +private: + void setupNotifyTests(); +}; + +class QtTestMetaDataProvider : public QMetaDataReaderControl +{ + Q_OBJECT +public: + QtTestMetaDataProvider(QObject *parent = 0) + : QMetaDataReaderControl(parent) + , m_available(false) + { + } + + bool isMetaDataAvailable() const { return m_available; } + void setMetaDataAvailable(bool available) { + if (m_available != available) + emit metaDataAvailableChanged(m_available = available); + } + QList availableMetaData() const { return m_data.keys(); } + + + QVariant metaData(QtMultimediaKit::MetaData key) const { return m_data.value(key); } + + QVariant extendedMetaData(const QString &key) const { return m_extendedData.value(key); } + + QStringList availableExtendedMetaData() const { return m_extendedData.keys(); } + + using QMetaDataReaderControl::metaDataChanged; + + void populateMetaData() + { + m_available = true; + } + + bool m_available; + QMap m_data; + QMap m_extendedData; +}; + +class QtTestMetaDataService : public QMediaService +{ + Q_OBJECT +public: + QtTestMetaDataService(QObject *parent = 0):QMediaService(parent), metaDataRef(0), hasMetaData(true) + { + } + + QMediaControl *requestControl(const char *iid) + { + if (hasMetaData && qstrcmp(iid, QMetaDataReaderControl_iid) == 0) + return &metaData; + else + return 0; + } + + void releaseControl(QMediaControl *) + { + } + + QtTestMetaDataProvider metaData; + int metaDataRef; + bool hasMetaData; +}; + +class QtTestMediaObject : public QMediaObject +{ + Q_OBJECT + Q_PROPERTY(int a READ a WRITE setA NOTIFY aChanged) + Q_PROPERTY(int b READ b WRITE setB NOTIFY bChanged) + Q_PROPERTY(int c READ c WRITE setC NOTIFY cChanged) + Q_PROPERTY(int d READ d WRITE setD) +public: + QtTestMediaObject(QMediaService *service = 0): QMediaObject(0, service), m_a(0), m_b(0), m_c(0), m_d(0) {} + + using QMediaObject::addPropertyWatch; + using QMediaObject::removePropertyWatch; + + int a() const { return m_a; } + void setA(int a) { m_a = a; } + + int b() const { return m_b; } + void setB(int b) { m_b = b; } + + int c() const { return m_c; } + void setC(int c) { m_c = c; } + + int d() const { return m_d; } + void setD(int d) { m_d = d; } + +Q_SIGNALS: + void aChanged(int a); + void bChanged(int b); + void cChanged(int c); + +private: + int m_a; + int m_b; + int m_c; + int m_d; +}; +#endif //TST_QMEDIAOBJECT_H \ No newline at end of file diff --git a/tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp b/tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp new file mode 100644 index 000000000..7cf5622a5 --- /dev/null +++ b/tests/auto/qmediaobject/tst_qmediaobject_mmf.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#include + +QT_USE_NAMESPACE + +void tst_QMediaObject_mmf::initTestCase_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("mediaContent"); + QTest::addColumn("metaDataAvailable"); + + QTest::newRow("TestDataNull") + << false // valid + << QMediaContent() // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_amr.amr") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_amr.amr")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_flash_video.flv") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_flash_video.flv")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_invalid_extension_mp4.xyz") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_invalid_extension_mp4.xyz")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_invalid_extension_wav.xyz") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_invalid_extension_wav.xyz")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_mp3.mp3") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_mp3.mp3")) // mediaContent +#if !defined(__WINS__) || !defined(__WINSCW__) + << true; // metaDataAvailable +#else + << false; // metaDataAvailable +#endif // !defined(__WINS__) || defined(__WINSCW__) + + QTest::newRow("test_mp3_no_metadata.mp3") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_mp3_no_metadata.mp3")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_mp4.mp4") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_mp4.mp4")) // mediaContent +#if defined(__WINS__) || defined(__WINSCW__) + << true; // metaDataAvailable +#else + << false; // metaDataAvailable +#endif // !defined(__WINS__) || defined(__WINSCW__) + + QTest::newRow("test_wav.wav") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_wav.wav")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test_wmv9.wmv") + << true // valid + << QMediaContent(QUrl("file:///C:/data/testfiles/test_wmv9.wmv")) // mediaContent + << false; // metaDataAvailable + + QTest::newRow("test youtube stream") + << true // valid + << QMediaContent(QUrl("rtsp://v3.cache4.c.youtube.com/CkgLENy73wIaPwlU2rm7yu8PFhMYESARFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRaDkNsaWNrVGh1bWJuYWlsYPi6_IXT2rvpSgw=/0/0/0/video.3gp")) // mediaContent + << false; // metaDataAvailable +} + +void tst_QMediaObject_mmf::initTestCase() +{ +} + +void tst_QMediaObject_mmf::cleanupTestCase() +{ +} + +void tst_QMediaObject_mmf::init() +{ + qRegisterMetaType("QMediaContent"); +} + +void tst_QMediaObject_mmf::cleanup() +{ +} + +void tst_QMediaObject_mmf::isMetaDataAvailable() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(bool, metaDataAvailable); + QMediaPlayer player; + + player.setMedia(mediaContent); + QTest::qWait(700); + QVERIFY(player.isMetaDataAvailable() == metaDataAvailable); +} + +void tst_QMediaObject_mmf::metaData() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(bool, metaDataAvailable); + QMediaPlayer player; + + player.setMedia(mediaContent); + QTest::qWait(700); + const QString artist(QLatin1String("Artist")); + const QString title(QLatin1String("Title")); + + if (player.isMetaDataAvailable()) { + QCOMPARE(player.metaData(QtMultimediaKit::AlbumArtist).toString(), artist); + QCOMPARE(player.metaData(QtMultimediaKit::Title).toString(), title); + } +} + +void tst_QMediaObject_mmf::availableMetaData() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(bool, metaDataAvailable); + QMediaPlayer player; + + player.setMedia(mediaContent); + QTest::qWait(700); + + if (player.isMetaDataAvailable()) { + QList metaDataKeys = player.availableMetaData(); + QVERIFY(metaDataKeys.count() > 0); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::AlbumArtist)); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::Title)); + } +} + +void tst_QMediaObject_mmf::extendedMetaData() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QMediaPlayer player; + + player.setMedia(mediaContent); + QTest::qWait(700); + const QString artist(QLatin1String("Artist")); + const QString title(QLatin1String("Title")); + + if (player.isMetaDataAvailable()) { + QCOMPARE(player.extendedMetaData(metaDataKeyAsString(QtMultimediaKit::AlbumArtist)).toString(), artist); + QCOMPARE(player.extendedMetaData(metaDataKeyAsString(QtMultimediaKit::Title)).toString(), title); + } +} + +void tst_QMediaObject_mmf::availableExtendedMetaData() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QMediaPlayer player; + + player.setMedia(mediaContent); + QTest::qWait(700); + const QString artist(QLatin1String("Artist")); + const QString title(QLatin1String("Title")); + + if (player.isMetaDataAvailable()) { + QStringList metaDataKeys = player.availableExtendedMetaData(); + QVERIFY(metaDataKeys.count() > 0); +/* qWarning() << "metaDataKeys.count: " << metaDataKeys.count(); + int count = metaDataKeys.count(); + count = count-1; + int i = 0; + while(count >= i) + { + qWarning() << "metaDataKeys "< +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class tst_QMediaObject_mmf : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase_data(); + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void isMetaDataAvailable(); + void metaData(); + void availableMetaData(); + void extendedMetaData(); + void availableExtendedMetaData(); + +private: + QString metaDataKeyAsString(QtMultimediaKit::MetaData key) const; +}; + +#endif // TST_QMEDIAOBJECT_MMF_H diff --git a/tests/auto/qmediaobject/tst_qmediaobject_xa.cpp b/tests/auto/qmediaobject/tst_qmediaobject_xa.cpp new file mode 100644 index 000000000..810a414b8 --- /dev/null +++ b/tests/auto/qmediaobject/tst_qmediaobject_xa.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include "tst_qmediaobject_xa.h" + +QT_USE_NAMESPACE + +#define WAIT_FOR_CONDITION(a,e) \ + for (int _i = 0; _i < 500; _i += 1) { \ + if ((a) == (e)) break; \ + QTest::qWait(10);} + + +#define WAIT_LONG_FOR_CONDITION(a,e) \ + for (int _i = 0; _i < 1800; _i += 1) { \ + if ((a) == (e)) break; \ + QTest::qWait(100);} + +Q_DECLARE_METATYPE(QtMultimediaKit::MetaData) + +void tst_QMetadata_xa::initTestCase_data() +{ + QTest::addColumn("mediaContent"); + QTest::addColumn("count"); + QTest::addColumn("key"); + QTest::addColumn("intValue"); + QTest::addColumn("strValue"); + + QTest::newRow("testmp3.mp3 - No Metadata") + << QMediaContent(QUrl("file:///C:/data/testfiles/test.mp3")) // mediaContent + << 0 //count + << QtMultimediaKit::Title //key - irrelavant when count 0 + << qint64(-1) //intValue + << QString(); //strValue + + QTest::newRow("JapJap.mp3 - Title") + << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent + << -1 //count - ignore + << QtMultimediaKit::Title //key + << qint64(-1) //intValue + << QString("JapJap");//strValue + + QTest::newRow("JapJap.mp3 - Artist") + << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent + << -1 //count - ignore + << QtMultimediaKit::AlbumArtist //key + << qint64(-1) //intValue + << QString("Screaming trees");//strValue + + QTest::newRow("JapJap.mp3 - Album") + << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent + << -1 //count - ignore + << QtMultimediaKit::AlbumTitle //key + << qint64(-1) //intValue + << QString("Sweet oblivion"); //strValue + + QTest::newRow("JapJap.mp3 - CoverArt") + << QMediaContent(QUrl("file:///C:/data/testfiles/JapJap.mp3")) // mediaContent + << -1 //count - ignore + << QtMultimediaKit::CoverArtImage //key + << qint64(28521) //intValue + << QString("C:/data/testfiles/JapJapCoverArt.jpeg"); //strValue +} + +void tst_QMetadata_xa::initTestCase() +{ + m_player = new QMediaPlayer(); + + // Symbian back end needs coecontrol for creation. + m_widget = new QVideoWidget(); + //m_widget->setMediaObject(m_player); + m_widget->show(); + runonce = false; +} + +void tst_QMetadata_xa::cleanupTestCase() +{ + delete m_player; + delete m_widget; +} + +void tst_QMetadata_xa::init() +{ + qRegisterMetaType("QMediaContent"); + qRegisterMetaType("QtMultimediaKit::MetaData"); +} + +void tst_QMetadata_xa::cleanup() +{ +} + +void tst_QMetadata_xa::testMetadata() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(int, count); + QFETCH_GLOBAL(QtMultimediaKit::MetaData, key); + QFETCH_GLOBAL(QString, strValue); + QFETCH_GLOBAL(qint64, intValue); + + QSignalSpy spy(m_player, SIGNAL(metaDataAvailableChanged(bool))); + m_player->setMedia(mediaContent); + + WAIT_FOR_CONDITION(spy.count(), 1); + //get metadata count + QList mdList = m_player->availableMetaData (); + QStringList amdList = m_player->availableExtendedMetaData(); + + int numMetadataItems = mdList.size() + amdList.size(); + if (count>=0) //-1 indicate ignore count + QVERIFY(count==numMetadataItems); + + if (numMetadataItems>0 && !strValue.isEmpty()) { + QVariant val = m_player->metaData(key); + + if(key == QtMultimediaKit::CoverArtImage) + val.value().save(strValue); + else + QVERIFY(strValue == val.toString()); + } +} diff --git a/tests/auto/qmediaobject/tst_qmediaobject_xa.h b/tests/auto/qmediaobject/tst_qmediaobject_xa.h new file mode 100644 index 000000000..81dc85095 --- /dev/null +++ b/tests/auto/qmediaobject/tst_qmediaobject_xa.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#ifndef TST_QMEDIAOBJECT_XA_H +#define TST_QMEDIAOBJECT_XA_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +class tst_QMetadata_xa: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase_data(); + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void testMetadata(); + + +private: + void displayImage(QImage); + QMediaPlayer *m_player; + QVideoWidget *m_widget; + bool runonce; +}; + +#endif //TST_QMEDIAOBJECT_XA_H diff --git a/tests/auto/qmediaplayer/main.cpp b/tests/auto/qmediaplayer/main.cpp new file mode 100755 index 000000000..b4dd5c470 --- /dev/null +++ b/tests/auto/qmediaplayer/main.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#include +#include + +#include "tst_qmediaplayer.h" + +#ifdef Q_OS_SYMBIAN +#include "tst_qmediaplayer_xa.h" +#include "tst_qmediaplayer_s60.h" +#endif + +int main(int argc, char**argv) +{ + QApplication app(argc,argv); + int ret; + tst_QMediaPlayer test_api; + ret = QTest::qExec(&test_api, argc, argv); +#ifdef Q_OS_SYMBIAN + char *new_argv[3]; + QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log"; + QByteArray bytes = str.toAscii(); + char arg1[] = "-o"; + new_argv[0] = argv[0]; + new_argv[1] = arg1; + new_argv[2] = bytes.data(); + tst_QMediaPlayer_xa test_xa; + ret = QTest::qExec(&test_xa, 3, new_argv); + char *new_argv1[3]; + QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log"; + QByteArray bytes1 = str1.toAscii(); + char arg2[] = "-o"; + new_argv1[0] = argv[0]; + new_argv1[1] = arg2; + new_argv1[2] = bytes1.data(); + tst_QMediaPlayer_s60 test_s60; + ret = QTest::qExec(&test_s60, 3, new_argv1); +#endif + return ret; +} diff --git a/tests/auto/qmediaplayer/qmediaplayer.pro b/tests/auto/qmediaplayer/qmediaplayer.pro new file mode 100644 index 000000000..b624afd91 --- /dev/null +++ b/tests/auto/qmediaplayer/qmediaplayer.pro @@ -0,0 +1,25 @@ +load(qttest_p4) + +QT += network multimediakit-private + +# TARGET = tst_qmediaplayer +# CONFIG += testcase + +symbian { + TARGET.CAPABILITY = NetworkServices + testFiles.sources = testfiles/* + testFiles.path = /Data/testfiles + DEPLOYMENT += testFiles + contains(openmaxal_symbian_enabled, no) { + DEFINES += HAS_OPENMAXAL_MEDIAPLAY_BACKEND + HEADERS += tst_qmediaplayer_xa.h + SOURCES += tst_qmediaplayer_xa.cpp + } else { + HEADERS += tst_qmediaplayer_s60.h + SOURCES += tst_qmediaplayer_s60.cpp + } +} + +HEADERS += tst_qmediaplayer.h +SOURCES += main.cpp tst_qmediaplayer.cpp + diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp new file mode 100644 index 000000000..4cef0e354 --- /dev/null +++ b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp @@ -0,0 +1,1019 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include "tst_qmediaplayer.h" + +#include +#include + +// Encouraging successful diversity through copy and paste. +#ifndef QTRY_COMPARE +#define QTRY_COMPARE(__expr, __expected) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if ((__expr) != (__expected)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QCOMPARE(__expr, __expected); \ + } while(0) +#endif + +#ifndef QTRY_VERIFY +#define QTRY_VERIFY(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY(__expr); \ + } while(0) +#endif + +QT_USE_NAMESPACE + +void tst_QMediaPlayer::initTestCase_data() +{ + QTest::addColumn("valid"); + QTest::addColumn("state"); + QTest::addColumn("status"); + QTest::addColumn("mediaContent"); + QTest::addColumn("duration"); + QTest::addColumn("position"); + QTest::addColumn("seekable"); + QTest::addColumn("volume"); + QTest::addColumn("muted"); + QTest::addColumn("videoAvailable"); + QTest::addColumn("bufferStatus"); + QTest::addColumn("playbackRate"); + QTest::addColumn("error"); + QTest::addColumn("errorString"); + + QTest::newRow("invalid") << false << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus << + QMediaContent() << qint64(0) << qint64(0) << false << 0 << false << false << 0 << + qreal(0) << QMediaPlayer::NoError << QString(); + QTest::newRow("valid+null") << true << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus << + QMediaContent() << qint64(0) << qint64(0) << false << 0 << false << false << 50 << + qreal(0) << QMediaPlayer::NoError << QString(); + QTest::newRow("valid+content+stopped") << true << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus << + QMediaContent(QUrl("file:///some.mp3")) << qint64(0) << qint64(0) << false << 50 << false << false << 0 << + qreal(1) << QMediaPlayer::NoError << QString(); + QTest::newRow("valid+content+playing") << true << QMediaPlayer::PlayingState << QMediaPlayer::LoadedMedia << + QMediaContent(QUrl("file:///some.mp3")) << qint64(10000) << qint64(10) << true << 50 << true << false << 0 << + qreal(1) << QMediaPlayer::NoError << QString(); + QTest::newRow("valid+content+paused") << true << QMediaPlayer::PausedState << QMediaPlayer::LoadedMedia << + QMediaContent(QUrl("file:///some.mp3")) << qint64(10000) << qint64(10) << true << 50 << true << false << 0 << + qreal(1) << QMediaPlayer::NoError << QString(); + QTest::newRow("valud+streaming") << true << QMediaPlayer::PlayingState << QMediaPlayer::LoadedMedia << + QMediaContent(QUrl("http://example.com/stream")) << qint64(10000) << qint64(10000) << false << 50 << false << true << 0 << + qreal(1) << QMediaPlayer::NoError << QString(); + QTest::newRow("valid+error") << true << QMediaPlayer::StoppedState << QMediaPlayer::UnknownMediaStatus << + QMediaContent(QUrl("http://example.com/stream")) << qint64(0) << qint64(0) << false << 50 << false << false << 0 << + qreal(0) << QMediaPlayer::ResourceError << QString("Resource unavailable"); +} + +void tst_QMediaPlayer::initTestCase() +{ + qRegisterMetaType("QMediaPlayer::State"); + qRegisterMetaType("QMediaPlayer::Error"); + qRegisterMetaType("QMediaPlayer::MediaStatus"); + qRegisterMetaType("QMediaContent"); + + mockService = new MockPlayerService; + mockProvider = new MockProvider(mockService); + player = new QMediaPlayer(0, 0, mockProvider); +} + +void tst_QMediaPlayer::cleanupTestCase() +{ + delete player; +} + +void tst_QMediaPlayer::init() +{ + mockService->reset(); +} + +void tst_QMediaPlayer::cleanup() +{ +} + +void tst_QMediaPlayer::testNullService() +{ + MockProvider provider(0); + QMediaPlayer player(0, 0, &provider); + + const QIODevice *nullDevice = 0; + + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(player.mediaStream(), nullDevice); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(player.duration(), qint64(-1)); + QCOMPARE(player.position(), qint64(0)); + QCOMPARE(player.volume(), 0); + QCOMPARE(player.isMuted(), false); + QCOMPARE(player.isVideoAvailable(), false); + QCOMPARE(player.bufferStatus(), 0); + QCOMPARE(player.isSeekable(), false); + QCOMPARE(player.playbackRate(), qreal(0)); + QCOMPARE(player.error(), QMediaPlayer::ServiceMissingError); + QCOMPARE(player.isAvailable(), false); + QCOMPARE(player.availabilityError(), QtMultimediaKit::ServiceMissingError); + + { + QFETCH_GLOBAL(QMediaContent, mediaContent); + + QSignalSpy spy(&player, SIGNAL(mediaChanged(QMediaContent))); + QFile file; + + player.setMedia(mediaContent, &file); + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(player.mediaStream(), nullDevice); + QCOMPARE(spy.count(), 0); + } { + QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + player.play(); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + + player.pause(); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + + player.stop(); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + } { + QFETCH_GLOBAL(int, volume); + QFETCH_GLOBAL(bool, muted); + + QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int))); + QSignalSpy mutingSpy(&player, SIGNAL(mutedChanged(bool))); + + player.setVolume(volume); + QCOMPARE(player.volume(), 0); + QCOMPARE(volumeSpy.count(), 0); + + player.setMuted(muted); + QCOMPARE(player.isMuted(), false); + QCOMPARE(mutingSpy.count(), 0); + } { + QFETCH_GLOBAL(qint64, position); + + QSignalSpy spy(&player, SIGNAL(positionChanged(qint64))); + + player.setPosition(position); + QCOMPARE(player.position(), qint64(0)); + QCOMPARE(spy.count(), 0); + } { + QFETCH_GLOBAL(qreal, playbackRate); + + QSignalSpy spy(&player, SIGNAL(playbackRateChanged(qreal))); + + player.setPlaybackRate(playbackRate); + QCOMPARE(player.playbackRate(), qreal(0)); + QCOMPARE(spy.count(), 0); + } { + QMediaPlaylist playlist; + player.setPlaylist(&playlist); + + QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + playlist.addMedia(QUrl("http://example.com/stream")); + playlist.addMedia(QUrl("file:///some.mp3")); + + playlist.setCurrentIndex(0); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(mediaSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + + playlist.next(); + QCOMPARE(playlist.currentIndex(), 1); + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(mediaSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + } +} + +void tst_QMediaPlayer::testValid() +{ + /* + QFETCH_GLOBAL(bool, valid); + + mockService->setIsValid(valid); + QCOMPARE(player->isValid(), valid); + */ +} + +void tst_QMediaPlayer::testMedia() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + + mockService->setMedia(mediaContent); + QCOMPARE(player->media(), mediaContent); + + QBuffer stream; + player->setMedia(mediaContent, &stream); + QCOMPARE(player->media(), mediaContent); + QCOMPARE((QBuffer*)player->mediaStream(), &stream); +} + +void tst_QMediaPlayer::testDuration() +{ + QFETCH_GLOBAL(qint64, duration); + + mockService->setDuration(duration); + QVERIFY(player->duration() == duration); +} + +void tst_QMediaPlayer::testPosition() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, seekable); + QFETCH_GLOBAL(qint64, position); + QFETCH_GLOBAL(qint64, duration); + + mockService->setIsValid(valid); + mockService->setSeekable(seekable); + mockService->setPosition(position); + mockService->setDuration(duration); + QVERIFY(player->isSeekable() == seekable); + QVERIFY(player->position() == position); + QVERIFY(player->duration() == duration); + + if (seekable) { + { QSignalSpy spy(player, SIGNAL(positionChanged(qint64))); + player->setPosition(position); + QCOMPARE(player->position(), position); + QCOMPARE(spy.count(), 0); } + + mockService->setPosition(position); + { QSignalSpy spy(player, SIGNAL(positionChanged(qint64))); + player->setPosition(0); + QCOMPARE(player->position(), qint64(0)); + QCOMPARE(spy.count(), position == 0 ? 0 : 1); } + + mockService->setPosition(position); + { QSignalSpy spy(player, SIGNAL(positionChanged(qint64))); + player->setPosition(duration); + QCOMPARE(player->position(), duration); + QCOMPARE(spy.count(), position == duration ? 0 : 1); } + + mockService->setPosition(position); + { QSignalSpy spy(player, SIGNAL(positionChanged(qint64))); + player->setPosition(-1); + QCOMPARE(player->position(), qint64(0)); + QCOMPARE(spy.count(), position == 0 ? 0 : 1); } + + mockService->setPosition(position); + { QSignalSpy spy(player, SIGNAL(positionChanged(qint64))); + player->setPosition(duration + 1); + QCOMPARE(player->position(), duration); + QCOMPARE(spy.count(), position == duration ? 0 : 1); } + } + else { + QSignalSpy spy(player, SIGNAL(positionChanged(qint64))); + player->setPosition(position); + + QCOMPARE(player->position(), position); + QCOMPARE(spy.count(), 0); + } +} + +void tst_QMediaPlayer::testVolume() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(int, volume); + + mockService->setVolume(volume); + QVERIFY(player->volume() == volume); + + if (valid) { + { QSignalSpy spy(player, SIGNAL(volumeChanged(int))); + player->setVolume(10); + QCOMPARE(player->volume(), 10); + QCOMPARE(spy.count(), 1); } + + { QSignalSpy spy(player, SIGNAL(volumeChanged(int))); + player->setVolume(-1000); + QCOMPARE(player->volume(), 0); + QCOMPARE(spy.count(), 1); } + + { QSignalSpy spy(player, SIGNAL(volumeChanged(int))); + player->setVolume(100); + QCOMPARE(player->volume(), 100); + QCOMPARE(spy.count(), 1); } + + { QSignalSpy spy(player, SIGNAL(volumeChanged(int))); + player->setVolume(1000); + QCOMPARE(player->volume(), 100); + QCOMPARE(spy.count(), 0); } + } +} + +void tst_QMediaPlayer::testMuted() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, muted); + QFETCH_GLOBAL(int, volume); + + if (valid) { + mockService->setMuted(muted); + mockService->setVolume(volume); + QVERIFY(player->isMuted() == muted); + + QSignalSpy spy(player, SIGNAL(mutedChanged(bool))); + player->setMuted(!muted); + QCOMPARE(player->isMuted(), !muted); + QCOMPARE(player->volume(), volume); + QCOMPARE(spy.count(), 1); + } +} + +void tst_QMediaPlayer::testVideoAvailable() +{ + QFETCH_GLOBAL(bool, videoAvailable); + + mockService->setVideoAvailable(videoAvailable); + QVERIFY(player->isVideoAvailable() == videoAvailable); +} + +void tst_QMediaPlayer::testBufferStatus() +{ + QFETCH_GLOBAL(int, bufferStatus); + + mockService->setBufferStatus(bufferStatus); + QVERIFY(player->bufferStatus() == bufferStatus); +} + +void tst_QMediaPlayer::testSeekable() +{ + QFETCH_GLOBAL(bool, seekable); + + mockService->setSeekable(seekable); + QVERIFY(player->isSeekable() == seekable); +} + +void tst_QMediaPlayer::testPlaybackRate() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(qreal, playbackRate); + + if (valid) { + mockService->setPlaybackRate(playbackRate); + QVERIFY(player->playbackRate() == playbackRate); + + QSignalSpy spy(player, SIGNAL(playbackRateChanged(qreal))); + player->setPlaybackRate(playbackRate + 0.5f); + QCOMPARE(player->playbackRate(), playbackRate + 0.5f); + QCOMPARE(spy.count(), 1); + } +} + +void tst_QMediaPlayer::testError() +{ + QFETCH_GLOBAL(QMediaPlayer::Error, error); + + mockService->setError(error); + QVERIFY(player->error() == error); +} + +void tst_QMediaPlayer::testErrorString() +{ + QFETCH_GLOBAL(QString, errorString); + + mockService->setErrorString(errorString); + QVERIFY(player->errorString() == errorString); +} + +void tst_QMediaPlayer::testIsAvailable() +{ + QCOMPARE(player->isAvailable(), true); + QCOMPARE(player->availabilityError(), QtMultimediaKit::NoError); +} + +void tst_QMediaPlayer::testService() +{ + /* + QFETCH_GLOBAL(bool, valid); + + mockService->setIsValid(valid); + + if (valid) + QVERIFY(player->service() != 0); + else + QVERIFY(player->service() == 0); + */ +} + +void tst_QMediaPlayer::testPlay() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + + mockService->setIsValid(valid); + mockService->setState(state); + mockService->setMedia(mediaContent); + QVERIFY(player->state() == state); + QVERIFY(player->media() == mediaContent); + + QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State))); + + player->play(); + + if (!valid || mediaContent.isNull()) { + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + } + else { + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(spy.count(), state == QMediaPlayer::PlayingState ? 0 : 1); + } +} + +void tst_QMediaPlayer::testPause() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + + mockService->setIsValid(valid); + mockService->setState(state); + mockService->setMedia(mediaContent); + QVERIFY(player->state() == state); + QVERIFY(player->media() == mediaContent); + + QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State))); + + player->pause(); + + if (!valid || mediaContent.isNull()) { + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + } + else { + QCOMPARE(player->state(), QMediaPlayer::PausedState); + QCOMPARE(spy.count(), state == QMediaPlayer::PausedState ? 0 : 1); + } +} + +void tst_QMediaPlayer::testStop() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + + mockService->setState(state); + mockService->setMedia(mediaContent); + QVERIFY(player->state() == state); + QVERIFY(player->media() == mediaContent); + + QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State))); + + player->stop(); + + if (mediaContent.isNull() || state == QMediaPlayer::StoppedState) { + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + } + else { + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 1); + } +} + +void tst_QMediaPlayer::testMediaStatus() +{ + QFETCH_GLOBAL(int, bufferStatus); + int bufferSignals = 0; + + player->setNotifyInterval(10); + + mockService->setMediaStatus(QMediaPlayer::NoMedia); + mockService->setBufferStatus(bufferStatus); + + AutoConnection connection( + player, SIGNAL(bufferStatusChanged(int)), + &QTestEventLoop::instance(), SLOT(exitLoop())); + + QSignalSpy statusSpy(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + QSignalSpy bufferSpy(player, SIGNAL(bufferStatusChanged(int))); + + QCOMPARE(player->mediaStatus(), QMediaPlayer::NoMedia); + + mockService->setMediaStatus(QMediaPlayer::LoadingMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadingMedia); + QCOMPARE(statusSpy.count(), 1); + + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::LoadingMedia); + + mockService->setMediaStatus(QMediaPlayer::LoadedMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(statusSpy.count(), 2); + + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::LoadedMedia); + + // Verify the bufferStatusChanged() signal isn't being emitted. + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(bufferSpy.count(), 0); + + mockService->setMediaStatus(QMediaPlayer::StalledMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::StalledMedia); + QCOMPARE(statusSpy.count(), 3); + + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::StalledMedia); + + // Verify the bufferStatusChanged() signal is being emitted. + QTestEventLoop::instance().enterLoop(1); + QVERIFY(bufferSpy.count() > bufferSignals); + QCOMPARE(bufferSpy.last().value(0).toInt(), bufferStatus); + bufferSignals = bufferSpy.count(); + + mockService->setMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferingMedia); + QCOMPARE(statusSpy.count(), 4); + + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::BufferingMedia); + + // Verify the bufferStatusChanged() signal is being emitted. + QTestEventLoop::instance().enterLoop(1); + QVERIFY(bufferSpy.count() > bufferSignals); + QCOMPARE(bufferSpy.last().value(0).toInt(), bufferStatus); + bufferSignals = bufferSpy.count(); + + mockService->setMediaStatus(QMediaPlayer::BufferedMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(statusSpy.count(), 5); + + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::BufferedMedia); + + // Verify the bufferStatusChanged() signal isn't being emitted. + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(bufferSpy.count(), bufferSignals); + + mockService->setMediaStatus(QMediaPlayer::EndOfMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE(statusSpy.count(), 6); + + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::EndOfMedia); +} + +void tst_QMediaPlayer::testPlaylist() +{ + QMediaContent content0(QUrl(QLatin1String("test://audio/song1.mp3"))); + QMediaContent content1(QUrl(QLatin1String("test://audio/song2.mp3"))); + QMediaContent content2(QUrl(QLatin1String("test://video/movie1.mp4"))); + QMediaContent content3(QUrl(QLatin1String("test://video/movie2.mp4"))); + QMediaContent content4(QUrl(QLatin1String("test://image/photo.jpg"))); + + mockService->setIsValid(true); + mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::NoMedia); + + QMediaPlaylist *playlist = new QMediaPlaylist; + player->setPlaylist(playlist); + + QSignalSpy stateSpy(player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy mediaSpy(player, SIGNAL(mediaChanged(QMediaContent))); + + // Test the player does nothing with an empty playlist attached. + player->play(); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(player->media(), QMediaContent()); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(mediaSpy.count(), 0); + + playlist->addMedia(content0); + playlist->addMedia(content1); + playlist->addMedia(content2); + playlist->addMedia(content3); + + // Test changing the playlist position, changes the current media, but not the playing state. + playlist->setCurrentIndex(1); + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(mediaSpy.count(), 1); + + // Test playing starts with the current media. + player->play(); + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(mediaSpy.count(), 1); + + // Test pausing doesn't change the current media. + player->pause(); + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 2); + QCOMPARE(mediaSpy.count(), 1); + + // Test stopping doesn't change the current media. + player->stop(); + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 3); + QCOMPARE(mediaSpy.count(), 1); + + // Test when the player service reaches the end of the current media, the player moves onto + // the next item without stopping. + player->play(); + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 4); + QCOMPARE(mediaSpy.count(), 1); + + mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia); + QCOMPARE(player->media(), content2); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 4); + QCOMPARE(mediaSpy.count(), 2); + + // Test skipping the current media doesn't change the state. + playlist->next(); + QCOMPARE(player->media(), content3); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 4); + QCOMPARE(mediaSpy.count(), 3); + + // Test changing the current media while paused doesn't change the state. + player->pause(); + mockService->setMediaStatus(QMediaPlayer::BufferedMedia); + QCOMPARE(player->media(), content3); + QCOMPARE(player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 5); + QCOMPARE(mediaSpy.count(), 3); + + playlist->previous(); + QCOMPARE(player->media(), content2); + QCOMPARE(player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 5); + QCOMPARE(mediaSpy.count(), 4); + + // Test changing the current media while stopped doesn't change the state. + player->stop(); + mockService->setMediaStatus(QMediaPlayer::LoadedMedia); + QCOMPARE(player->media(), content2); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 6); + QCOMPARE(mediaSpy.count(), 4); + + playlist->next(); + QCOMPARE(player->media(), content3); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 6); + QCOMPARE(mediaSpy.count(), 5); + + // Test the player is stopped and the current media cleared when it reaches the end of the last + // item in the playlist. + player->play(); + QCOMPARE(player->media(), content3); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 7); + QCOMPARE(mediaSpy.count(), 5); + + // Double up the signals to ensure some noise doesn't destabalize things. + mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia); + mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia); + QCOMPARE(player->media(), QMediaContent()); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 8); + QCOMPARE(mediaSpy.count(), 6); + + // Test starts playing from the start of the playlist if there is no current media selected. + player->play(); + QCOMPARE(player->media(), content0); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 9); + QCOMPARE(mediaSpy.count(), 7); + + // Test deleting the playlist stops the player and clears the media it set. + delete playlist; + QCOMPARE(player->media(), QMediaContent()); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 10); + QCOMPARE(mediaSpy.count(), 8); + + // Test the player works as normal with the playlist removed. + player->play(); + QCOMPARE(player->media(), QMediaContent()); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 10); + QCOMPARE(mediaSpy.count(), 8); + + player->setMedia(content1); + player->play(); + + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 11); + QCOMPARE(mediaSpy.count(), 9); + + // Test the player can bind to playlist again + playlist = new QMediaPlaylist; + player->setPlaylist(playlist); + + QCOMPARE(player->media(), QMediaContent()); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + + playlist->addMedia(content0); + playlist->addMedia(content1); + playlist->addMedia(content2); + playlist->addMedia(content3); + + playlist->setCurrentIndex(1); + QCOMPARE(player->media(), content1); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + + // Test attaching the new playlist, + // player should detach the current one + QMediaPlaylist *playlist2 = new QMediaPlaylist; + playlist2->addMedia(content1); + playlist2->addMedia(content2); + playlist2->addMedia(content3); + playlist2->setCurrentIndex(2); + + player->play(); + player->setPlaylist(playlist2); + QCOMPARE(player->media(), playlist2->currentMedia()); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + + playlist2->setCurrentIndex(1); + QCOMPARE(player->media(), playlist2->currentMedia()); + + { + QMediaPlaylist playlist; + playlist.addMedia(content1); + playlist.addMedia(content2); + playlist.addMedia(content3); + playlist.setCurrentIndex(1); + + player->setPlaylist(&playlist); + QCOMPARE(player->playlist(), &playlist); + QCOMPARE(player->media(), content2); + } //playlist should be detached now + + QVERIFY(player->playlist() == 0); + QCOMPARE(player->media(), QMediaContent()); + + // Test when the player service encounters an invalid media, the player moves onto + // the next item without stopping + { + QSignalSpy ss(player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy ms(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + player->setPlaylist(playlist); + player->play(); + QCOMPARE(ss.count(), 1); + + mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::InvalidMedia); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QCOMPARE(player->mediaStatus(), QMediaPlayer::InvalidMedia); + QCOMPARE(ss.count(), 1); + QCOMPARE(ms.count(), 1); + + // NOTE: status should begin transitioning through to BufferedMedia. + QCOMPARE(player->media(), content2); + } + +} + +void tst_QMediaPlayer::testNetworkAccess() +{ + QNetworkConfigurationManager manager; + QList configs = manager.allConfigurations(); + + if (configs.count() >= 1) { + QSignalSpy spy(player, SIGNAL(networkConfigurationChanged(QNetworkConfiguration))); + int index = qFloor((configs.count())/2); + player->setNetworkConfigurations(configs); + mockService->selectCurrentConfiguration(configs.at(index)); + + QVERIFY(spy.count() == 1); + QList args = spy.takeFirst(); + QNetworkConfiguration config = args.at(0).value(); + QCOMPARE(config.identifier() , configs.at(index).identifier()); + QCOMPARE(player->currentNetworkConfiguration().identifier() , config.identifier()); + } + + // invalidate current network configuration + QSignalSpy spy(player, SIGNAL(networkConfigurationChanged(QNetworkConfiguration))); + mockService->selectCurrentConfiguration(QNetworkConfiguration()); + QVERIFY(spy.count() == 1); + QList args = spy.takeFirst(); + QNetworkConfiguration config = args.at(0).value(); + QVERIFY(config.isValid() == false); + QVERIFY(player->currentNetworkConfiguration().isValid() == false); +} + +void tst_QMediaPlayer::testSetVideoOutput() +{ + QVideoWidget widget; + QGraphicsVideoItem item; + MockVideoSurface surface; + + MockPlayerService service; + MockProvider provider(&service); + provider.deleteServiceOnRelease = false; + QMediaPlayer player(0, 0, &provider); + + player.setVideoOutput(&widget); + QVERIFY(widget.mediaObject() == &player); + + player.setVideoOutput(&item); + QVERIFY(widget.mediaObject() == 0); + QVERIFY(item.mediaObject() == &player); + + player.setVideoOutput(reinterpret_cast(0)); + QVERIFY(item.mediaObject() == 0); + + player.setVideoOutput(&widget); + QVERIFY(widget.mediaObject() == &player); + + player.setVideoOutput(reinterpret_cast(0)); + QVERIFY(widget.mediaObject() == 0); + + player.setVideoOutput(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + + player.setVideoOutput(reinterpret_cast(0)); + QVERIFY(service.rendererControl->surface() == 0); + + player.setVideoOutput(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + + player.setVideoOutput(&widget); + QVERIFY(service.rendererControl->surface() == 0); + QVERIFY(widget.mediaObject() == &player); + + player.setVideoOutput(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + QVERIFY(widget.mediaObject() == 0); +} + + +void tst_QMediaPlayer::testSetVideoOutputNoService() +{ + QVideoWidget widget; + QGraphicsVideoItem item; + MockVideoSurface surface; + + MockProvider provider(0); + QMediaPlayer player(0, 0, &provider); + + player.setVideoOutput(&widget); + QVERIFY(widget.mediaObject() == 0); + + player.setVideoOutput(&item); + QVERIFY(item.mediaObject() == 0); + + player.setVideoOutput(&surface); + // Nothing we can verify here other than it doesn't assert. +} + +void tst_QMediaPlayer::testSetVideoOutputNoControl() +{ + QVideoWidget widget; + QGraphicsVideoItem item; + MockVideoSurface surface; + + MockPlayerService service; + service.rendererRef = 1; + service.windowRef = 1; + + MockProvider provider(&service); + provider.deleteServiceOnRelease = false; + QMediaPlayer player(0, 0, &provider); + + player.setVideoOutput(&widget); + QVERIFY(widget.mediaObject() == 0); + + player.setVideoOutput(&item); + QVERIFY(item.mediaObject() == 0); + + player.setVideoOutput(&surface); + QVERIFY(service.rendererControl->surface() == 0); +} + +void tst_QMediaPlayer::testSetVideoOutputDestruction() +{ + MockVideoSurface surface; + + MockPlayerService service; + MockProvider provider(&service); + provider.deleteServiceOnRelease = false; + + { + QMediaPlayer player(0, 0, &provider); + player.setVideoOutput(&surface); + QVERIFY(service.rendererControl->surface() == &surface); + QCOMPARE(service.rendererRef, 1); + } + QVERIFY(service.rendererControl->surface() == 0); + QCOMPARE(service.rendererRef, 0); +} + +void tst_QMediaPlayer::testPositionPropertyWatch() +{ + QMediaContent content0(QUrl(QLatin1String("test://audio/song1.mp3"))); + QMediaContent content1(QUrl(QLatin1String("test://audio/song2.mp3"))); + + mockService->setIsValid(true); + mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::NoMedia); + + QMediaPlaylist *playlist = new QMediaPlaylist; + + playlist->addMedia(content0); + playlist->addMedia(content1); + + player->setPlaylist(playlist); + player->setNotifyInterval(5); + + player->play(); + QSignalSpy positionSpy(player, SIGNAL(positionChanged(qint64))); + playlist->next(); + QCOMPARE(player->state(), QMediaPlayer::PlayingState); + QTRY_VERIFY(positionSpy.count() > 0); + + playlist->next(); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + + positionSpy.clear(); + QTRY_COMPARE(positionSpy.count(), 0); +} + +void tst_QMediaPlayer::debugEnums() +{ + QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::PlayingState "); + qDebug() << QMediaPlayer::PlayingState; + QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::NoMedia "); + qDebug() << QMediaPlayer::NoMedia; + QTest::ignoreMessage(QtDebugMsg, "QMediaPlayer::NetworkError "); + qDebug() << QMediaPlayer::NetworkError; +} + + diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.h b/tests/auto/qmediaplayer/tst_qmediaplayer.h new file mode 100755 index 000000000..6371ac3ff --- /dev/null +++ b/tests/auto/qmediaplayer/tst_qmediaplayer.h @@ -0,0 +1,435 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QMEDIAPLAYER_H +#define TST_QMEDIAPLAYER_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +class AutoConnection +{ +public: + AutoConnection(QObject *sender, const char *signal, QObject *receiver, const char *method) + : sender(sender), signal(signal), receiver(receiver), method(method) + { + QObject::connect(sender, signal, receiver, method); + } + + ~AutoConnection() + { + QObject::disconnect(sender, signal, receiver, method); + } + +private: + QObject *sender; + const char *signal; + QObject *receiver; + const char *method; +}; + + +class MockPlayerControl : public QMediaPlayerControl +{ + friend class MockPlayerService; + +public: + MockPlayerControl():QMediaPlayerControl(0) {} + + QMediaPlayer::State state() const { return _state; } + QMediaPlayer::MediaStatus mediaStatus() const { return _mediaStatus; } + + qint64 duration() const { return _duration; } + + qint64 position() const { return _position; } + + void setPosition(qint64 position) { if (position != _position) emit positionChanged(_position = position); } + + int volume() const { return _volume; } + void setVolume(int volume) { emit volumeChanged(_volume = volume); } + + bool isMuted() const { return _muted; } + void setMuted(bool muted) { if (muted != _muted) emit mutedChanged(_muted = muted); } + + int bufferStatus() const { return _bufferStatus; } + + bool isAudioAvailable() const { return _audioAvailable; } + bool isVideoAvailable() const { return _videoAvailable; } + + bool isSeekable() const { return _isSeekable; } + QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(_seekRange.first, _seekRange.second); } + void setSeekRange(qint64 minimum, qint64 maximum) { _seekRange = qMakePair(minimum, maximum); } + + qreal playbackRate() const { return _playbackRate; } + void setPlaybackRate(qreal rate) { if (rate != _playbackRate) emit playbackRateChanged(_playbackRate = rate); } + + QMediaContent media() const { return _media; } + void setMedia(const QMediaContent &content, QIODevice *stream) + { + _stream = stream; + _media = content; + if (_state != QMediaPlayer::StoppedState) { + _mediaStatus = _media.isNull() ? QMediaPlayer::NoMedia : QMediaPlayer::LoadingMedia; + emit stateChanged(_state = QMediaPlayer::StoppedState); + emit mediaStatusChanged(_mediaStatus); + } + emit mediaChanged(_media = content); + } + QIODevice *mediaStream() const { return _stream; } + + void play() { if (_isValid && !_media.isNull() && _state != QMediaPlayer::PlayingState) emit stateChanged(_state = QMediaPlayer::PlayingState); } + void pause() { if (_isValid && !_media.isNull() && _state != QMediaPlayer::PausedState) emit stateChanged(_state = QMediaPlayer::PausedState); } + void stop() { if (_state != QMediaPlayer::StoppedState) emit stateChanged(_state = QMediaPlayer::StoppedState); } + + QMediaPlayer::State _state; + QMediaPlayer::MediaStatus _mediaStatus; + QMediaPlayer::Error _error; + qint64 _duration; + qint64 _position; + int _volume; + bool _muted; + int _bufferStatus; + bool _audioAvailable; + bool _videoAvailable; + bool _isSeekable; + QPair _seekRange; + qreal _playbackRate; + QMediaContent _media; + QIODevice *_stream; + bool _isValid; + QString _errorString; +}; + +class MockVideoSurface : public QAbstractVideoSurface +{ +public: + QList supportedPixelFormats( + const QAbstractVideoBuffer::HandleType) const + { + return QList(); + } + + bool present(const QVideoFrame &) { return false; } +}; + +class MockVideoRendererControl : public QVideoRendererControl +{ +public: + MockVideoRendererControl() : m_surface(0) {} + + QAbstractVideoSurface *surface() const { return m_surface; } + void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; } + + QAbstractVideoSurface *m_surface; +}; + +class MockVideoWindowControl : public QVideoWindowControl +{ +public: + WId winId() const { return 0; } + void setWinId(WId) {} + QRect displayRect() const { return QRect(); } + void setDisplayRect(const QRect &) {} + bool isFullScreen() const { return false; } + void setFullScreen(bool) {} + void repaint() {} + QSize nativeSize() const { return QSize(); } + Qt::AspectRatioMode aspectRatioMode() const { return Qt::KeepAspectRatio; } + void setAspectRatioMode(Qt::AspectRatioMode) {} + int brightness() const { return 0; } + void setBrightness(int) {} + int contrast() const { return 0; } + void setContrast(int) {} + int hue() const { return 0; } + void setHue(int) {} + int saturation() const { return 0; } + void setSaturation(int) {} +}; + +class MockStreamsControl : public QMediaStreamsControl +{ +public: + MockStreamsControl(QObject *parent = 0) : QMediaStreamsControl(parent) {} + + int streamCount() { return _streams.count(); } + void setStreamCount(int count) { _streams.resize(count); } + + StreamType streamType(int index) { return _streams.at(index).type; } + void setStreamType(int index, StreamType type) { _streams[index].type = type; } + + QVariant metaData(int index, QtMultimediaKit::MetaData key) { + return _streams.at(index).metaData.value(key); } + void setMetaData(int index, QtMultimediaKit::MetaData key, const QVariant &value) { + _streams[index].metaData.insert(key, value); } + + bool isActive(int index) { return _streams.at(index).active; } + void setActive(int index, bool state) { _streams[index].active = state; } + +private: + struct Stream + { + Stream() : type(UnknownStream), active(false) {} + StreamType type; + QMap metaData; + bool active; + }; + + QVector _streams; +}; + +class MockNetworkAccessControl : public QMediaNetworkAccessControl +{ + friend class MockPlayerService; + +public: + MockNetworkAccessControl() {} + ~MockNetworkAccessControl() {} + + void setConfigurations(const QList &configurations) + { + _configurations = configurations; + _current = QNetworkConfiguration(); + } + + QNetworkConfiguration currentConfiguration() const + { + return _current; + } + +private: + void setCurrentConfiguration(QNetworkConfiguration configuration) + { + if (_configurations.contains(configuration)) + emit configurationChanged(_current = configuration); + else + emit configurationChanged(_current = QNetworkConfiguration()); + } + + QList _configurations; + QNetworkConfiguration _current; +}; + +Q_DECLARE_METATYPE(QNetworkConfiguration) + +class MockPlayerService : public QMediaService +{ + Q_OBJECT + +public: + MockPlayerService():QMediaService(0) + { + mockControl = new MockPlayerControl; + mockStreamsControl = new MockStreamsControl; + mockNetworkControl = new MockNetworkAccessControl; + rendererControl = new MockVideoRendererControl; + windowControl = new MockVideoWindowControl; + rendererRef = 0; + windowRef = 0; + } + + ~MockPlayerService() + { + delete mockControl; + delete mockStreamsControl; + delete mockNetworkControl; + delete rendererControl; + delete windowControl; + } + + QMediaControl* requestControl(const char *iid) + { + if (qstrcmp(iid, QMediaPlayerControl_iid) == 0) { + return mockControl; + } else if (qstrcmp(iid, QVideoRendererControl_iid) == 0) { + if (rendererRef == 0) { + rendererRef += 1; + return rendererControl; + } + } else if (qstrcmp(iid, QVideoWindowControl_iid) == 0) { + if (windowRef == 0) { + windowRef += 1; + return windowControl; + } + } + + + if (qstrcmp(iid, QMediaNetworkAccessControl_iid) == 0) + return mockNetworkControl; + return 0; + } + + void releaseControl(QMediaControl *control) + { + if (control == rendererControl) + rendererRef -= 1; + else if (control == windowControl) + windowRef -= 1; + } + + void setState(QMediaPlayer::State state) { emit mockControl->stateChanged(mockControl->_state = state); } + void setState(QMediaPlayer::State state, QMediaPlayer::MediaStatus status) { + mockControl->_state = state; + mockControl->_mediaStatus = status; + emit mockControl->mediaStatusChanged(status); + emit mockControl->stateChanged(state); + } + void setMediaStatus(QMediaPlayer::MediaStatus status) { emit mockControl->mediaStatusChanged(mockControl->_mediaStatus = status); } + void setIsValid(bool isValid) { mockControl->_isValid = isValid; } + void setMedia(QMediaContent media) { mockControl->_media = media; } + void setDuration(qint64 duration) { mockControl->_duration = duration; } + void setPosition(qint64 position) { mockControl->_position = position; } + void setSeekable(bool seekable) { mockControl->_isSeekable = seekable; } + void setVolume(int volume) { mockControl->_volume = volume; } + void setMuted(bool muted) { mockControl->_muted = muted; } + void setVideoAvailable(bool videoAvailable) { mockControl->_videoAvailable = videoAvailable; } + void setBufferStatus(int bufferStatus) { mockControl->_bufferStatus = bufferStatus; } + void setPlaybackRate(qreal playbackRate) { mockControl->_playbackRate = playbackRate; } + void setError(QMediaPlayer::Error error) { mockControl->_error = error; emit mockControl->error(mockControl->_error, mockControl->_errorString); } + void setErrorString(QString errorString) { mockControl->_errorString = errorString; emit mockControl->error(mockControl->_error, mockControl->_errorString); } + + void selectCurrentConfiguration(QNetworkConfiguration config) { mockNetworkControl->setCurrentConfiguration(config); } + + void reset() + { + mockControl->_state = QMediaPlayer::StoppedState; + mockControl->_mediaStatus = QMediaPlayer::UnknownMediaStatus; + mockControl->_error = QMediaPlayer::NoError; + mockControl->_duration = 0; + mockControl->_position = 0; + mockControl->_volume = 0; + mockControl->_muted = false; + mockControl->_bufferStatus = 0; + mockControl->_videoAvailable = false; + mockControl->_isSeekable = false; + mockControl->_playbackRate = 0.0; + mockControl->_media = QMediaContent(); + mockControl->_stream = 0; + mockControl->_isValid = false; + mockControl->_errorString = QString(); + + mockNetworkControl->_current = QNetworkConfiguration(); + mockNetworkControl->_configurations = QList(); + } + + MockPlayerControl *mockControl; + MockStreamsControl *mockStreamsControl; + MockNetworkAccessControl *mockNetworkControl; + MockVideoRendererControl *rendererControl; + MockVideoWindowControl *windowControl; + int rendererRef; + int windowRef; +}; + +class MockProvider : public QMediaServiceProvider +{ +public: + MockProvider(MockPlayerService *service):mockService(service), deleteServiceOnRelease(true) {} + QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &) + { + return mockService; + } + + void releaseService(QMediaService *service) { if (deleteServiceOnRelease) delete service; } + + MockPlayerService *mockService; + bool deleteServiceOnRelease; +}; + +class tst_QMediaPlayer: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase_data(); + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void testNullService(); + void testValid(); + void testMedia(); + void testDuration(); + void testPosition(); + void testVolume(); + void testMuted(); + void testIsAvailable(); + void testVideoAvailable(); + void testBufferStatus(); + void testSeekable(); + void testPlaybackRate(); + void testError(); + void testErrorString(); + void testService(); + void testPlay(); + void testPause(); + void testStop(); + void testMediaStatus(); + void testPlaylist(); + void testNetworkAccess(); + void testSetVideoOutput(); + void testSetVideoOutputNoService(); + void testSetVideoOutputNoControl(); + void testSetVideoOutputDestruction(); + void testPositionPropertyWatch(); + void debugEnums(); + +private: + MockProvider *mockProvider; + MockPlayerService *mockService; + QMediaPlayer *player; +}; + +#endif //TST_QMEDIAPLAYER_H diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp new file mode 100755 index 000000000..f30934a96 --- /dev/null +++ b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.cpp @@ -0,0 +1,1708 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include "tst_qmediaplayer_s60.h" +#include + +static const QString TestFilePath = QLatin1String("c:/data/testfiles/"); + +// Comment out the following line if the test device does not have network +// access. +#define TEST_DEVICE_HAS_NETWORK_ACCESS + +QT_USE_NAMESPACE + +void tst_QMediaPlayer_s60::initTestCase_data() +{ +#ifdef __WINSCW__ + initTestCase_data_default_winscw(); +#else + initTestCase_data_default_armv5(); +#endif +} + +void tst_QMediaPlayer_s60::initTestCase_data_default_armv5() +{ + QTest::addColumn("valid"); + QTest::addColumn("streamable"); + QTest::addColumn("state"); + QTest::addColumn("status"); + QTest::addColumn("mediaContent"); + QTest::addColumn("duration"); + QTest::addColumn("position"); + QTest::addColumn("seekable"); + QTest::addColumn("seekableWhilePlaying"); + QTest::addColumn("volume"); + QTest::addColumn("videoAvailable"); + QTest::addColumn("audioAvailable"); + QTest::addColumn("playbackRate"); + QTest::addColumn("error"); + QTest::addColumn("errorString"); + + QTest::newRow("TestDataNull") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::NoMedia // status + << QMediaContent() // mediaContent + << qint64(-1) // duration + << qint64(0) // position + << false // seekable + << false // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_3gp.3gp") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status LoadedMedia + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_3gp.3gp")) // mediaContent + << qint64(46860) // duration + << qint64(23430) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_mp4.mp4") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4")) // mediaContent + << qint64(2701) // duration + << qint64(1351) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_wmv9.wmv") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_wmv9.wmv")) // mediaContent + << qint64(169389) // duration + << qint64(84695) // position (duration/2) + << true // seekable + << false // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_AAC.dat") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_AAC.dat")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_amr.amr") + << true // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_amr.amr")) // mediaContent + << qint64(14400) // duration + << qint64(7200) // position + << true // seekable + << false // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_mp3.mp3") + << true // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp3.mp3")) // mediaContent + << qint64(102044) //qint64(102044) duration + << qint64(51022) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + +#ifdef TEST_DEVICE_HAS_NETWORK_ACCESS + QTest::newRow("test_stream 3gp") + << false // valid + << true //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl("rtsp://v3.cache4.c.youtube.com/CkgLENy73wIaPwlU2rm7yu8PFhMYESARFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRaDkNsaWNrVGh1bWJuYWlsYPi6_IXT2rvpSgw=/0/0/0/video.3gp")) // mediaContent + << qint64(103000) // duration + << qint64(0) // position + << false // seekable + << false // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("RTSP link to H.263/AMR") + << false // valid + << true //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl("rtsp://v7.cache8.c.youtube.com/CiILENy73wIaGQnNUH6lxLd0MRMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp")) // mediaContent + << qint64(249000) // duration + << qint64(0) // position + << false // seekable + << false // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("RTSP link to MPEG-4/AAC") + << false // valid + << true //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl("rtsp://v8.cache1.c.youtube.com/CiILENy73wIaGQnNUH6lxLd0MRMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp")) // mediaContent + << qint64(249000) // duration + << qint64(0) // position + << false // seekable + << false // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString +#endif // TEST_DEVICE_HAS_NETWORK_ACCESS +} + +void tst_QMediaPlayer_s60::initTestCase_data_default_winscw() +{ + QTest::addColumn("valid"); + QTest::addColumn("streamable"); + QTest::addColumn("state"); + QTest::addColumn("status"); + QTest::addColumn("mediaContent"); + QTest::addColumn("duration"); + QTest::addColumn("position"); + QTest::addColumn("seekable"); + QTest::addColumn("seekableWhilePlaying"); + QTest::addColumn("volume"); + QTest::addColumn("videoAvailable"); + QTest::addColumn("audioAvailable"); + QTest::addColumn("playbackRate"); + QTest::addColumn("error"); + QTest::addColumn("errorString"); + + QTest::newRow("TestDataNull") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::NoMedia // status + << QMediaContent() // mediaContent + << qint64(-1) // duration + << qint64(0) // position + << false // seekable + << false // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_3GPP.dat") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_3GPP.dat")) // mediaContent + << qint64(7200) // duration + << qint64(3600) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_3gp.3gp") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_3gp.3gp")) // mediaContent + << qint64(46860) // duration + << qint64(23430) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_mp4.mp4") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4")) // mediaContent + << qint64(2701) // duration + << qint64(1351) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::FormatError // error + << QString(); // errorString + + QTest::newRow("test_MP4.dat") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MP4.dat")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::AccessDeniedError// error + << QString(); // errorString + + QTest::newRow("test_wmv9.wmv") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_wmv9.wmv")) // mediaContent + << qint64(169389) // duration + << qint64(84695) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::FormatError // error + << QString(); // errorString + + QTest::newRow("test_h264_qcif.264") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_h264_qcif.264")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_RM.dat") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_RM.dat")) // mediaContent + << qint64(20245) // duration + << qint64(10123) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_SWF.dat") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_SWF.dat")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_WMV.dat") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_WMV.dat")) // mediaContent + << qint64(3098) // duration + << qint64(1549) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying, on emulator codec leaks memory and causes alloc panic on dtor + << 50 // volume + << true // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::FormatError // error + << QString(); // errorString + + QTest::newRow("test_WMA.dat") + << false //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_WMA.dat")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::AccessDeniedError // error + << QString(); // errorString + + QTest::newRow("test_flash_video.flv") + << false // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_flash_video.flv")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_MXMF.dat") + << true //valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MXMF.dat")) // mediaContent + << qint64(31980) // duration + << qint64(15990) // position (duration/2) + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true //audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_amr.amr") + << true // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_amr.amr")) // mediaContent + << qint64(14402) // duration + << qint64(7200) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_AMR.dat") + << true // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_AMR.dat")) // mediaContent + << qint64(38509) // duration + << qint64(19255) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_mp3.mp3") + << false // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_mp3.mp3")) // mediaContent + << qint64(-1) //qint64(102044) duration + << qint64(0) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_MP3.dat") + << false // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MP3.dat")) // mediaContent + << qint64(-1) //qint64(102044) duration + << qint64(0) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_MIDI.dat") + << true // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_MIDI.dat")) // mediaContent + << qint64(32782) // duration + << qint64(16391) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + + QTest::newRow("test_ACC.dat") + << false // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::InvalidMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_ACC.dat")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << false // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::ResourceError // error + << QString(); // errorString + + QTest::newRow("test_WAV.dat") + << true // valid + << false //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl::fromLocalFile(TestFilePath + "test_WAV.dat")) // mediaContent + << qint64(2864) // duration + << qint64(1432) // position + << true // seekable + << true // seekableWhilePlaying + << 50 // volume + << false // videoAvailable + << true // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::NoError // error + << QString(); // errorString + +#ifdef TEST_DEVICE_HAS_NETWORK_ACCESS + QTest::newRow("test_stream") + << false // valid + << true //streamable + << QMediaPlayer::StoppedState // state + << QMediaPlayer::LoadedMedia // status + << QMediaContent(QUrl("rtsp://v3.cache4.c.youtube.com/CkgLENy73wIaPwlU2rm7yu8PFhMYESARFEIJbXYtZ29vZ2xlSARSB3JlbGF0ZWRaDkNsaWNrVGh1bWJuYWlsYPi6_IXT2rvpSgw=/0/0/0/video.3gp")) // mediaContent + << qint64(-1) // duration + << qint64(0) // position + << false // seekable + << false // seekableWhilePlaying + << 50 // volume + << true // videoAvailable + << false // audioAvailable + << qreal(0) // playbackRate + << QMediaPlayer::AccessDeniedError // error + << QString(); // errorString +#endif +} + +void tst_QMediaPlayer_s60::initTestCase() +{ + m_player = new QMediaPlayer(); + + // Symbian back end needs coecontrol for creation. + m_widget = new QVideoWidget(); + m_player->setVideoOutput(m_widget); + m_widget->show(); + runonce = false; +} + +void tst_QMediaPlayer_s60::cleanupTestCase() +{ + delete m_player; + delete m_widget; +} + +void tst_QMediaPlayer_s60::init() +{ + qRegisterMetaType("QMediaPlayer::State"); + qRegisterMetaType("QMediaPlayer::Error"); + qRegisterMetaType("QMediaPlayer::MediaStatus"); + qRegisterMetaType("QMediaContent"); +} + +void tst_QMediaPlayer_s60::cleanup() +{ +} + +void tst_QMediaPlayer_s60::testNullService() +{ + if(runonce) + return; + MockProvider_s60 provider(0); + QMediaPlayer player(0, 0, &provider); + + const QIODevice *nullDevice = 0; + + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(player.mediaStream(), nullDevice); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(player.duration(), qint64(-1)); + QCOMPARE(player.position(), qint64(0)); + QCOMPARE(player.volume(), 0); + QCOMPARE(player.isMuted(), false); + QCOMPARE(player.isVideoAvailable(), false); + QCOMPARE(player.bufferStatus(), 0); + QCOMPARE(player.isSeekable(), false); + QCOMPARE(player.playbackRate(), qreal(0)); + QCOMPARE(player.error(), QMediaPlayer::ServiceMissingError); + + { + QFETCH_GLOBAL(QMediaContent, mediaContent); + + QSignalSpy spy(&player, SIGNAL(mediaChanged(QMediaContent))); + QFile file; + + player.setMedia(mediaContent, &file); + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(player.mediaStream(), nullDevice); + QCOMPARE(spy.count(), 0); + } { + QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + player.play(); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + + player.pause(); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + + player.stop(); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + } { + QFETCH_GLOBAL(int, volume); + + QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int))); + QSignalSpy mutingSpy(&player, SIGNAL(mutedChanged(bool))); + + player.setVolume(volume); + QCOMPARE(player.volume(), 0); + QCOMPARE(volumeSpy.count(), 0); + + player.setMuted(false); + QCOMPARE(player.isMuted(), false); + QCOMPARE(mutingSpy.count(), 0); + } { + QFETCH_GLOBAL(qint64, position); + + QSignalSpy spy(&player, SIGNAL(positionChanged(qint64))); + + player.setPosition(position); + QCOMPARE(player.position(), qint64(0)); + QCOMPARE(spy.count(), 0); + } { + QFETCH_GLOBAL(qreal, playbackRate); + + QSignalSpy spy(&player, SIGNAL(playbackRateChanged(qreal))); + + player.setPlaybackRate(playbackRate); + QCOMPARE(player.playbackRate(), qreal(0)); + QCOMPARE(spy.count(), 0); + } { + QMediaPlaylist playlist; + player.setPlaylist(&playlist); + + QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + playlist.addMedia(QUrl("http://example.com/stream")); + playlist.addMedia(QUrl("file:///some.mp3")); + + playlist.setCurrentIndex(0); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(mediaSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + + playlist.next(); + QCOMPARE(playlist.currentIndex(), 1); + QCOMPARE(player.media(), QMediaContent()); + QCOMPARE(mediaSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + } + runonce = true; +} + +void tst_QMediaPlayer_s60::testMedia() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + m_player->setMedia(mediaContent); + QTest::qWait(500); + QCOMPARE(m_player->media(), mediaContent); +} + + +void tst_QMediaPlayer_s60::testDuration() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(qint64, duration); + QFETCH_GLOBAL(bool, valid); + + QSignalSpy spy(m_player, SIGNAL(durationChanged(qint64))); + m_player->setMedia(mediaContent); + + if(valid) { + WAIT_FOR_CONDITION(spy.count(), 1); + } else { + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia)); + } + + QVERIFY(m_player->duration() == duration); +} + +void tst_QMediaPlayer_s60::testPosition() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(qint64, duration); + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, seekable); + QFETCH_GLOBAL(qint64, position); + QFETCH_GLOBAL(QMediaPlayer::MediaStatus, status); + + m_player->setMedia(mediaContent); + + if (valid) { + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + QCOMPARE(m_player->isSeekable(), seekable); + //QCOMPARE(m_player->mediaStatus(), status); + QVERIFY(m_player->mediaStatus() == status); + + // preset position + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(position); + QCOMPARE(m_player->position(), position); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), position);} + + // same pos second time + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(position); + QCOMPARE(m_player->position(), position); + QCOMPARE(spy.count(), 0);} + + //zero pos + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(0); + QCOMPARE(m_player->position(), qint64(0)); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0));} + + //end pos + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(duration); + QCOMPARE(m_player->position(), duration); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), duration);} + + //negative pos + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(qint64(-1)); + QCOMPARE(m_player->position(), qint64(0)); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0));} + + //over duration + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(duration+1); + QCOMPARE(m_player->position(), duration); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), duration);} + + } else { + if (valid) + WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia) + else + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia)) + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->isSeekable(), seekable); + QCOMPARE(m_player->mediaStatus(), status); + } +} + +void tst_QMediaPlayer_s60::testPositionWhilePlaying() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(qint64, duration); + QFETCH_GLOBAL(bool, seekableWhilePlaying); + QFETCH_GLOBAL(bool, seekable); + QFETCH_GLOBAL(qint64, position); + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, streamable); + QFETCH_GLOBAL(QMediaPlayer::MediaStatus, status); + + m_player->setMedia(mediaContent); + + if (streamable) { + WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + } else { + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + } + + //qDebug()<<""; + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->isSeekable(), seekable); + QCOMPARE(m_player->mediaStatus(), status); + + if (seekableWhilePlaying && valid) { + QCOMPARE(m_player->isSeekable(), seekableWhilePlaying); + + // preset position + //qDebug()<<"preset"; + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(position); + WAIT_FOR_CONDITION(spy.count(), 2); + QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia || + m_player->mediaStatus() == QMediaPlayer::BufferedMedia || + m_player->mediaStatus() == QMediaPlayer::EndOfMedia || + m_player->mediaStatus() == QMediaPlayer::LoadedMedia); + + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->position()>=position); + QVERIFY(spy.count()!=0);} + + //reset position + m_player->stop(); + m_player->setPosition(position); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + //zero pos + //qDebug()<<"zero"; + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(0); + WAIT_FOR_CONDITION(spy.count(), 2); + QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia || + m_player->mediaStatus() == QMediaPlayer::BufferedMedia || + m_player->mediaStatus() == QMediaPlayer::EndOfMedia || + m_player->mediaStatus() == QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->position() >= qint64(0)); + QVERIFY(spy.count()!=0);} + + //reset position + m_player->stop(); + m_player->setPosition(position); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + //end pos + //qDebug()<<"dur"; + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(duration); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->position(), qint64(0)); + QVERIFY(spy.count()!=0);} + + //reset position + m_player->stop(); + m_player->setPosition(position); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + //negative pos + //qDebug()<<"negavite"; + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(qint64(-1)); + WAIT_FOR_CONDITION(spy.count(), 2); + QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia || + m_player->mediaStatus() == QMediaPlayer::BufferedMedia || + m_player->mediaStatus() == QMediaPlayer::EndOfMedia || + m_player->mediaStatus() == QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->position() >= qint64(0)); + QVERIFY(spy.count()!=0);} + + //reset position + m_player->stop(); + m_player->setPosition(position); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + //over duration + //qDebug()<<"over"; + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(duration+1); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + // s60 MP3 controller has a weard feature to reduce position by ~200 when position + // is set over the duration, therefore we skip it here + if (!mediaContent.canonicalUrl().path().endsWith("mp3")) { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->position(), qint64(0)); + QVERIFY(spy.count()!=0);} + } + } else + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + //qDebug()<<"end"; +} + + +void tst_QMediaPlayer_s60::testVolume() +{ + QFETCH_GLOBAL(int, volume); + + // preset volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // same volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + int currentVolume = m_player->volume(); + m_player->setVolume(currentVolume); + QCOMPARE(m_player->volume(), currentVolume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 0);} + + // zero volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(0); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // max volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(100); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // negative volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(int(-1)); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // over max volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(1000); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} +} + +void tst_QMediaPlayer_s60::testVolumeWhilePlaying() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(int, volume); + QFETCH_GLOBAL(bool, valid); + + if (valid) { + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + // preset volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // same volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + int currentVolume = m_player->volume(); + m_player->setVolume(currentVolume); + QCOMPARE(m_player->volume(), currentVolume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 0);} + + // zero volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(0); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // max volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(100); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // negative volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(int(-1)); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + // over max volume + { QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(1000); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1);} + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + } +} + + +void tst_QMediaPlayer_s60::testMuted() +{ + QFETCH_GLOBAL(int, volume); + + //reset mute & volume + m_player->setMuted(false); + m_player->setVolume(0); + QVERIFY(m_player->isMuted() == false); + QCOMPARE(m_player->volume(), 0); + + // set muted + {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == true);} + + // set muted again + {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 0); + QVERIFY(m_player->isMuted() == true);} + + // unmute + {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(false); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == false);} + + // set volume while muted + {QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool))); + QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int))); + m_player->setMuted(true); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(muteSpy.count(), 1); + QCOMPARE(volumeSpy.count(), 1); + QVERIFY(m_player->isMuted() == true);} +} + +void tst_QMediaPlayer_s60::testMutedWhilePlaying() +{ + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(int, volume); + QFETCH_GLOBAL(bool, valid); + + if (valid) { + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + //reset mute & volume + m_player->setMuted(false); + m_player->setVolume(65); + QVERIFY(m_player->isMuted() == false); + QCOMPARE(m_player->volume(), 65); + + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + // set muted + {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == true);} + + // set muted again + {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 0); + QVERIFY(m_player->isMuted() == true);} + + // unmute + {QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(false); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == false);} + + // set volume while muted + {QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool))); + QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int))); + m_player->setMuted(true); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(muteSpy.count(), 1); + QCOMPARE(volumeSpy.count(), 1); + QVERIFY(m_player->isMuted() == true);} + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + } +} + + +void tst_QMediaPlayer_s60::testVideoAndAudioAvailability() +{ + QFETCH_GLOBAL(bool, videoAvailable); + QFETCH_GLOBAL(bool, audioAvailable); + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(QMediaContent, mediaContent); + + if(valid) { + QSignalSpy audioAvailableSpy(m_player, SIGNAL(audioAvailableChanged(bool))); + QSignalSpy videoAvailableSpy(m_player, SIGNAL(videoAvailableChanged(bool))); + + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + QVERIFY(m_player->isVideoAvailable() == videoAvailable); + QVERIFY(m_player->isAudioAvailable() == audioAvailable); + + QCOMPARE(audioAvailableSpy.count(), 1); + QCOMPARE(videoAvailableSpy.count(), 1); + } +} + +void tst_QMediaPlayer_s60::testError() +{ + QFETCH_GLOBAL(QMediaPlayer::Error, error); + QFETCH_GLOBAL(bool, videoAvailable); + QFETCH_GLOBAL(bool, audioAvailable); + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + QFETCH_GLOBAL(QMediaPlayer::MediaStatus, status); + + QSignalSpy errorSpy(m_player, SIGNAL(error(QMediaPlayer::Error))); + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_player->mediaStatus() == status); + QVERIFY(m_player->state() == state); + QVERIFY(m_player->error() == error); + if (error != QMediaPlayer::NoError) { + QVERIFY(errorSpy.count()!=0); + } +} + +void tst_QMediaPlayer_s60::testPlay() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, streamable); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_player->state() == state); + QVERIFY(m_player->media() == mediaContent); + QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + + if(valid) { + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(spy.count(), state == QMediaPlayer::PlayingState ? 0 : 1); + + //Play->Play + {QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 0);} + + //Play->Pause + {QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 1);} + + //Play->Stop + {m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + if (m_player->mediaStatus() != QMediaPlayer::EndOfMedia) { + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 1); + } else { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 4); + }} + } else if (streamable) { + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 2); + } else { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); +} + +void tst_QMediaPlayer_s60::testPause() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, streamable); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_player->state() == state); + QVERIFY(m_player->media() == mediaContent); + QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + + if(valid) { + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(spy.count(), 1); + + //Pause->Play + {QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 1);} + + //Pause->Pause + {m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 0);} + + //Pause->Stop + {QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 1);} + } else if (streamable) { + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 2); + } else { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + } +} + +void tst_QMediaPlayer_s60::testStop() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_player->state() == state); + QVERIFY(m_player->media() == mediaContent); + + QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + + if(valid) { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + + //Stop->Play + {QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 1);} + + //Stop->Pause + {m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 1);} + + //Stop->Stop + {m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 0);} + } else { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + } +} + +void tst_QMediaPlayer_s60::testMediaStatus() +{ + QFETCH_GLOBAL(bool, videoAvailable); + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, streamable); + QFETCH_GLOBAL(QMediaContent, mediaContent); + + QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + mediaStatusList list(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + + if(valid) { + if (videoAvailable) { + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(list.count(), 3); + QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia); + QCOMPARE(list.at(2), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + m_player->play(); + {WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia);} + QCOMPARE(statusSpy.count(), 5); + QCOMPARE(list.count(), 5); + QCOMPARE(list.at(3), QMediaPlayer::BufferingMedia); + QCOMPARE(list.at(4), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + {WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);} + QVERIFY(statusSpy.count() == 6); + QVERIFY(list.count() == 6); + QCOMPARE(list.last(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + }else { + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(list.count(), 3); + QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia); + QCOMPARE(list.at(2), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + m_player->play(); + {WAIT_LONG_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia);} + QVERIFY(statusSpy.count() == 4); + QVERIFY(list.count() == 4); + QCOMPARE(list.last(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + } + } else if (mediaContent.isNull()) { + QCOMPARE(statusSpy.count(), 2); + QCOMPARE(list.count(), 2); + QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(list.at(1), QMediaPlayer::NoMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia); + m_player->play(); + QCOMPARE(statusSpy.count(), 2); + QCOMPARE(list.count(), 2); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia); + } else if (streamable) { + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(list.count(), 3); + QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia); + QCOMPARE(list.at(2), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(list.count(), 3); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + } else { + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(list.count(), 3); + QCOMPARE(list.at(0), QMediaPlayer::UnknownMediaStatus); + QCOMPARE(list.at(1), QMediaPlayer::LoadingMedia); + QCOMPARE(list.at(2), QMediaPlayer::InvalidMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::InvalidMedia); + m_player->play(); + QCOMPARE(statusSpy.count(), 3); + QCOMPARE(list.count(), 3); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::InvalidMedia); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); +} + +void tst_QMediaPlayer_s60::testPlaylist() +{ + if(!runonce) { + QMediaContent content0(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4")); + QMediaContent content1(QUrl::fromLocalFile(TestFilePath + "test_WAV.dat")); + QMediaContent content2(QUrl::fromLocalFile(TestFilePath + "test_mp4.mp4")); + QMediaContent content3(QUrl::fromLocalFile(TestFilePath + "test_WAV.dat")); + QMediaContent content4(QUrl::fromLocalFile(TestFilePath + "test_MIDI.dat")); + + QMediaPlaylist *playlist = new QMediaPlaylist(m_player); + m_player->setPlaylist(playlist); + + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy mediaSpy(m_player, SIGNAL(mediaChanged(QMediaContent))); + + // Test the player does nothing with an empty playlist attached. + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->media(), QMediaContent()); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(mediaSpy.count(), 0); + + playlist->addMedia(content0); + playlist->addMedia(content1); + playlist->addMedia(content2); + playlist->addMedia(content3); + + // Test changing the playlist position, changes the current media, but not the playing state. + playlist->setCurrentIndex(1); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->media(), content1); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(stateSpy.count(), 0); + QCOMPARE(mediaSpy.count(), 1); + + // Test playing starts with the current media. + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->media(), content1); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(mediaSpy.count(), 1); + + // Test pausing doesn't change the current media. + m_player->pause(); + QCOMPARE(m_player->media(), content1); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 2); + QCOMPARE(mediaSpy.count(), 1); + + // Test stopping doesn't change the current media. + m_player->stop(); + QCOMPARE(m_player->media(), content1); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(stateSpy.count(), 3); + QCOMPARE(mediaSpy.count(), 1); + + // Test when the player service reaches the end of the current media, the player moves onto + // the next item without stopping. + m_player->play(); + QCOMPARE(m_player->media(), content1); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 4); + QCOMPARE(mediaSpy.count(), 1); + + WAIT_FOR_CONDITION(mediaSpy.count(), 2); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->media(), content2); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 6); + QCOMPARE(mediaSpy.count(), 2); + + // Test skipping the current media doesn't change the state. + playlist->next(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->media(), content3); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 6); + QCOMPARE(mediaSpy.count(), 3); + + // Test changing the current media while paused doesn't change the state. + m_player->pause(); + QCOMPARE(m_player->media(), content3); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 7); + QCOMPARE(mediaSpy.count(), 3); + + playlist->previous(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->media(), content2); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 7); + QCOMPARE(mediaSpy.count(), 4); + + // Test changing the current media while stopped doesn't change the state. + m_player->stop(); + QCOMPARE(m_player->media(), content2); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(stateSpy.count(), 8); + QCOMPARE(mediaSpy.count(), 4); + + playlist->next(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->media(), content3); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(stateSpy.count(), 8); + QCOMPARE(mediaSpy.count(), 5); + + // Test the player is stopped and the current media cleared when it reaches the end of the last + // item in the playlist. + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->media(), content3); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 9); + QCOMPARE(mediaSpy.count(), 5); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->media(), QMediaContent()); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia); + QCOMPARE(stateSpy.count(), 10); + QCOMPARE(mediaSpy.count(), 6); + + // Test starts playing from the start of the playlist if there is no current media selected. + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->media(), content0); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 11); + QCOMPARE(mediaSpy.count(), 7); + + // Test deleting the playlist stops the player and clears the media it set. + delete playlist; + QCOMPARE(m_player->media(), QMediaContent()); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia); + QCOMPARE(stateSpy.count(), 12); + QCOMPARE(mediaSpy.count(), 8); + + // Test the player works as normal with the playlist removed. + m_player->play(); + QCOMPARE(m_player->media(), QMediaContent()); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::NoMedia); + QCOMPARE(stateSpy.count(), 12); + QCOMPARE(mediaSpy.count(), 8); + + m_player->setMedia(content1); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia) + QCOMPARE(m_player->media(), content1); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->mediaStatus() == (QMediaPlayer::BufferedMedia||QMediaPlayer::BufferingMedia)); + QCOMPARE(stateSpy.count(), 13); + QCOMPARE(mediaSpy.count(), 9); + m_player->stop(); + runonce = true; + } +} + +void tst_QMediaPlayer_s60::testStreamControl() +{ + QFETCH_GLOBAL(bool, valid); + QFETCH_GLOBAL(bool, streamable); + QFETCH_GLOBAL(QMediaContent, mediaContent); + QFETCH_GLOBAL(QMediaPlayer::State, state); + QFETCH_GLOBAL(bool, videoAvailable); + QFETCH_GLOBAL(bool, audioAvailable); + + QMediaStreamsControl* m_streamControl = (QMediaStreamsControl*)(m_player->service()->requestControl(QMediaStreamsControl_iid)); + if(m_streamControl) { + if (valid || streamable) { + if (audioAvailable && !videoAvailable) { + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_streamControl->streamCount() == 1); + QVERIFY(m_streamControl->streamType(1) == QMediaStreamsControl::AudioStream); + QVERIFY(m_streamControl->isActive(1) == true); + QCOMPARE(streamInfoSpy.count(), 1); + }else if (audioAvailable && videoAvailable){ + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_streamControl->streamCount() == 2); + QVERIFY(m_streamControl->streamType(1) == QMediaStreamsControl::VideoStream); + QVERIFY(m_streamControl->isActive(2) == true); + QCOMPARE(streamInfoSpy.count(), 1); + }else if (!audioAvailable && videoAvailable) { + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QVERIFY(m_streamControl->streamCount() == 1); + QVERIFY(m_streamControl->streamType(1) == QMediaStreamsControl::VideoStream); + QVERIFY(m_streamControl->isActive(2) == true); + QCOMPARE(streamInfoSpy.count(), 1); + } + + // Test that streamsChanged signal do not get emitted when adding same media + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + m_player->setMedia(mediaContent); + WAIT_FOR_CONDITION(m_player->mediaStatus(), (QMediaPlayer::NoMedia || QMediaPlayer::InvalidMedia || QMediaPlayer::LoadedMedia)); + QCOMPARE(streamInfoSpy.count(), 0); + } + } +} diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_s60.h b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.h new file mode 100755 index 000000000..1ebe42588 --- /dev/null +++ b/tests/auto/qmediaplayer/tst_qmediaplayer_s60.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QMEDIAPLAYER_S60_H +#define TST_QMEDIAPLAYER_S60_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +#define WAIT_FOR_CONDITION(a,e) \ + for (int _i = 0; _i < 500; _i += 1) { \ + if ((a) == (e)) break; \ + QTest::qWait(10);} + + +#define WAIT_LONG_FOR_CONDITION(a,e) \ + for (int _i = 0; _i < 1800; _i += 1) { \ + if ((a) == (e)) break; \ + QTest::qWait(100);} + +class mediaStatusList : public QObject, public QList +{ + Q_OBJECT +public slots: + void mediaStatus(QMediaPlayer::MediaStatus status) { + append(status); + } + +public: + mediaStatusList(QObject *obj, const char *aSignal) + : QObject() + { + connect(obj, aSignal, this, SLOT(mediaStatus(QMediaPlayer::MediaStatus))); + } +}; + +class MockProvider_s60 : public QMediaServiceProvider +{ +public: + MockProvider_s60(QMediaService *service):mockService(service) {} + QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &) + { + return mockService; + } + + void releaseService(QMediaService *service) { delete service; } + + QMediaService *mockService; +}; + +class tst_QMediaPlayer_s60: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase_data(); + void initTestCase_data_default_winscw(); + void initTestCase_data_default_armv5(); + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void testNullService(); + void testMedia(); + void testDuration(); + void testPosition(); + void testPositionWhilePlaying(); + void testVolume(); + void testVolumeWhilePlaying(); + void testMuted(); + void testMutedWhilePlaying(); + void testVideoAndAudioAvailability(); + void testError(); + void testPlay(); + void testPause(); + void testStop(); + void testMediaStatus(); + void testPlaylist(); + void testStreamControl(); + +private: + QMediaPlayer *m_player; + QVideoWidget *m_widget; + bool runonce; +}; + +#endif // TST_QMEDIAPLAYER_S60_H diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp new file mode 100644 index 000000000..403fe5457 --- /dev/null +++ b/tests/auto/qmediaplayer/tst_qmediaplayer_xa.cpp @@ -0,0 +1,1413 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include "tst_QMediaPlayer_xa.h" + +QT_USE_NAMESPACE + +#define QTEST_MAIN_XA(TestObject) \ + int main(int argc, char *argv[]) { \ + char *new_argv[3]; \ + QApplication app(argc, argv); \ + \ + QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + ".log"; \ + QByteArray bytes = str.toAscii(); \ + \ + char arg1[] = "-o"; \ + \ + new_argv[0] = argv[0]; \ + new_argv[1] = arg1; \ + new_argv[2] = bytes.data(); \ + \ + TestObject tc; \ + return QTest::qExec(&tc, 3, new_argv); \ + } + +#define WAIT_FOR_CONDITION(a,e) \ + for (int _i = 0; _i < 500; _i += 1) { \ + if ((a) == (e)) break; \ + QTest::qWait(10);} + +#define WAIT_FOR_EITHER_CONDITION(a,e,f) \ + for (int _i = 0; _i < 500; _i += 1) { \ + if (((a) == (e)) || ((a) == (f))) break; \ + QTest::qWait(10);} + +#define WAIT_FOR_CONDITION1(a) \ + for (int _i = 0; _i < 500; _i += 1) { \ + if (a) break; \ + QTest::qWait(10);} + + +#define WAIT_LONG_FOR_CONDITION(a,e) \ + for (int _i = 0; _i < 1800; _i += 1) { \ + if ((a) == (e)) break; \ + QTest::qWait(10);} + +#define WAIT_LONG_FOR_CONDITION1(a) \ + for (int _i = 0; _i < 1800; _i += 1) { \ + if (a) break; \ + QTest::qWait(100);} + +tst_QMediaPlayer_xa::tst_QMediaPlayer_xa(): m_player(NULL), m_widget(NULL), m_windowWidget(NULL) +{ + audioOnlyContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test.mp3")); + videoOnlyContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test_video.3gp")); + audioVideoContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test.3gp")); + audioVideoAltContent = new QMediaContent(QUrl("file:///C:/data/testfiles/test_alt.3gp")); + //streamingContent = new QMediaContent(QUrl("rtsp://10.48.2.51/Copyright_Free_Test_Content/Clips/Video/3GP/176x144/h263/h263_176x144_15fps_384kbps_AAC-LC_128kbps_mono_44.1kHz.3gp")); + streamingContent3gp = new QMediaContent(QUrl("http://www.mobileplayground.co.uk/video/Crazy Frog.3gp")); + audioStreamingContent = new QMediaContent(QUrl("http://myopusradio.com:8000/easy")); + mediaContent = audioVideoContent; +} + +tst_QMediaPlayer_xa::~tst_QMediaPlayer_xa() +{ + delete audioOnlyContent; + delete videoOnlyContent; + delete audioVideoContent; + delete audioVideoAltContent; +} + +void tst_QMediaPlayer_xa::initTestCase_data() +{ +} + +void tst_QMediaPlayer_xa::initTestCase() +{ + m_player = new QMediaPlayer(); + + // Symbian back end needs coecontrol for creation. + m_widget = new QVideoWidget(); + m_widget->setGeometry ( 0, 100, 350, 250 ); + m_player->setVideoOutput(m_widget); + m_widget->showNormal(); +} + +void tst_QMediaPlayer_xa::cleanupTestCase() +{ + delete m_player; + delete m_widget; + delete m_windowWidget; +} + +void tst_QMediaPlayer_xa::resetPlayer() +{ + delete m_player; + m_player = new QMediaPlayer(); + m_player->setVideoOutput(m_widget); +} + +void tst_QMediaPlayer_xa::resetPlayer_WindowControl() +{ + delete m_player; + m_player = new QMediaPlayer(); + + if(!m_windowWidget) { + m_windowWidget = new QWidget(); + m_windowWidget->showMaximized(); + } + + QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid)); + if (windowControl) + windowControl->setWinId(m_windowWidget->winId()); +} + +void tst_QMediaPlayer_xa::init() +{ + qRegisterMetaType("QMediaPlayer::State"); + qRegisterMetaType("QMediaPlayer::Error"); + qRegisterMetaType("QMediaPlayer::MediaStatus"); + qRegisterMetaType("QMediaContent"); + updateLog("QT MediaPlayer Auto Test Cases", true); +} + +void tst_QMediaPlayer_xa::cleanup() +{ +} + + +void tst_QMediaPlayer_xa::testMedia() +{ + updateLog("*****testMedia"); + + setAudioVideoContent(); + + QTest::qWait(500); + QCOMPARE(m_player->media(), *mediaContent); + + updateLog("*****testMedia: PASSED"); +} + + +void tst_QMediaPlayer_xa::testDuration() +{ + updateLog("*****testDuration"); + + resetPlayer(); + + QSignalSpy spy(m_player, SIGNAL(durationChanged(qint64))); + setAudioVideoContent(); + + WAIT_FOR_CONDITION1(spy.count()>0); + + QVERIFY(m_player->duration() == duration); + + updateLog("*****testDuration: PASSED"); +} + +void tst_QMediaPlayer_xa::testPosition() +{ + updateLog("*****testPosition"); + resetPlayer(); + + qint64 position = 60000; + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + QCOMPARE(m_player->isSeekable(), true); + + // preset position + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(position); + WAIT_FOR_CONDITION(spy.count(), 1); + QCOMPARE(m_player->position(), position); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), position); + } + + // same pos second time + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(position); + QCOMPARE(m_player->position(), position); + QCOMPARE(spy.count(), 0); + } + + //zero pos + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(0); + QCOMPARE(m_player->position(), qint64(0)); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0)); + } + + //end pos + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(duration); + QCOMPARE(m_player->position(), duration); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), duration); + } + + //negative pos + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(qint64(-1)); + QCOMPARE(m_player->position(), qint64(0)); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), qint64(0)); + } + + //over duration + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->setPosition(duration+1); + QCOMPARE(m_player->position(), duration); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toLongLong(), duration); + } + +} + + +void tst_QMediaPlayer_xa::testPositionWhilePlaying() +{ + updateLog("*****testPositionWhilePlaying"); + resetPlayer(); + + qint64 position = 60000; + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + // preset position + { + QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(position); + WAIT_FOR_CONDITION1(spy.count()>0); + QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia || m_player->mediaStatus() == QMediaPlayer::BufferedMedia); + + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->position()>=position); + QVERIFY(spy.count()!=0); + } + + //reset position + m_player->stop(); + m_player->setPosition(position); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + //zero pos + { QSignalSpy spy(m_player, SIGNAL(positionChanged(qint64))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + m_player->setPosition(0); + WAIT_FOR_CONDITION1(spy.count()>0); + QVERIFY(m_player->mediaStatus() == QMediaPlayer::BufferingMedia || + m_player->mediaStatus() == QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QVERIFY(m_player->position() >= qint64(0)); + QVERIFY(spy.count()!=0); + } + + //reset position + m_player->stop(); + m_player->setPosition(position); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testPositionWhilePlaying: PASSED"); +} + + +void tst_QMediaPlayer_xa::testVolume() +{ + updateLog("*****testVolume"); + + int volume = 20; + + // preset volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // same volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + int currentVolume = m_player->volume(); + m_player->setVolume(currentVolume); + QCOMPARE(m_player->volume(), currentVolume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 0); + } + + // zero volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(0); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // max volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(100); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // negative volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(int(-1)); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // over max volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(1000); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + updateLog("*****testVolume: PASSED"); +} + +void tst_QMediaPlayer_xa::testVolumeWhilePlaying() +{ + updateLog("*****testVideoAndAudioAvailability"); + resetPlayer(); + + int volume = 20; + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + // preset volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // same volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + int currentVolume = m_player->volume(); + m_player->setVolume(currentVolume); + QCOMPARE(m_player->volume(), currentVolume); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 0); + } + + // zero volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(0); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // max volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(100); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // negative volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(int(-1)); + QCOMPARE(m_player->volume(), 0); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + // over max volume + { + QSignalSpy spy(m_player, SIGNAL(volumeChanged(int))); + m_player->setVolume(1000); + QCOMPARE(m_player->volume(), 100); + QCOMPARE(m_player->isMuted(), false); + QCOMPARE(spy.count(), 1); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testVideoAndAudioAvailability: PASSED"); +} + + +void tst_QMediaPlayer_xa::testMuted() +{ + updateLog("*****testMuted"); + + int volume = 20; + + //reset mute & volume + m_player->setMuted(false); + m_player->setVolume(0); + QVERIFY(m_player->isMuted() == false); + QCOMPARE(m_player->volume(), 0); + + // set muted + { + QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == true); + } + + // set muted again + { + QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 0); + QVERIFY(m_player->isMuted() == true); + } + + // unmute + { + QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(false); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == false); + } + + // set volume while muted + { + QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool))); + QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int))); + m_player->setMuted(true); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(muteSpy.count(), 1); + QCOMPARE(volumeSpy.count(), 1); + QVERIFY(m_player->isMuted() == true); + } + + updateLog("*****testMuted: PASSED"); +} + +void tst_QMediaPlayer_xa::testMutedWhilePlaying() +{ + updateLog("*****testMutedWhilePlaying"); + resetPlayer(); + + int volume = 20; + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + //reset mute & volume + m_player->setMuted(false); + m_player->setVolume(65); + QVERIFY(m_player->isMuted() == false); + QCOMPARE(m_player->volume(), 65); + + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + // set muted + { + QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == true); + } + + // set muted again + { + QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(true); + QCOMPARE(spy.count(), 0); + QVERIFY(m_player->isMuted() == true); + } + + // unmute + { + QSignalSpy spy(m_player, SIGNAL(mutedChanged(bool))); + m_player->setMuted(false); + QCOMPARE(spy.count(), 1); + QVERIFY(m_player->isMuted() == false); + } + + // set volume while muted + { + QSignalSpy muteSpy(m_player, SIGNAL(mutedChanged(bool))); + QSignalSpy volumeSpy(m_player, SIGNAL(volumeChanged(int))); + m_player->setMuted(true); + m_player->setVolume(volume); + QCOMPARE(m_player->volume(), volume); + QCOMPARE(muteSpy.count(), 1); + QCOMPARE(volumeSpy.count(), 1); + QVERIFY(m_player->isMuted() == true); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + + updateLog("*****testMutedWhilePlaying: PASSED"); +} + +void tst_QMediaPlayer_xa::testVideoAndAudioAvailability() +{ + updateLog("*****testVideoAndAudioAvailability"); + resetPlayer(); + + QList arguments; + + + setVideoOnlyContent(); + + + QSignalSpy audioAvailableSpy(m_player, SIGNAL(audioAvailableChanged(bool))); + QSignalSpy videoAvailableSpy(m_player, SIGNAL(videoAvailableChanged(bool))); + + setAudioOnlyContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + updateLog("SetMedia: audioOnlyContent"); + WAIT_FOR_CONDITION(m_player->isAudioAvailable(), true); + updateLog("\t isAudioAvailable() == true"); + QVERIFY(m_player->isVideoAvailable() == false); + updateLog("\t isVideoAvailable() == false"); + QCOMPARE(audioAvailableSpy.count(), 1); + arguments = audioAvailableSpy.takeFirst(); + QVERIFY(arguments.at(0).toBool() == true); + updateLog("\t audioAvailableChanged(true)"); + QCOMPARE(videoAvailableSpy.count(), 1); + arguments = videoAvailableSpy.takeFirst(); + QVERIFY(arguments.at(0).toBool() == false); + updateLog("\t videoAvailableChanged(false)"); + + setVideoOnlyContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + updateLog("SetMedia: videoOnlyContent"); + WAIT_FOR_CONDITION(m_player->isVideoAvailable(), true); + updateLog("\t isVideoAvailable() == true"); + QVERIFY(m_player->isAudioAvailable() == false); + updateLog("\t isAudioAvailable() == false"); + QCOMPARE(audioAvailableSpy.count(), 1); + arguments = audioAvailableSpy.takeFirst(); + QVERIFY(arguments.at(0).toBool() == false); + updateLog("\t audioAvailableChanged(false)"); + QCOMPARE(videoAvailableSpy.count(), 1); + arguments = videoAvailableSpy.takeFirst(); + QVERIFY(arguments.at(0).toBool() == true); + updateLog("\t videoAvailableChanged(true)"); + + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + updateLog("SetMedia: audioVideoContent"); + WAIT_FOR_CONDITION(m_player->isAudioAvailable(), true); + updateLog("\t isAudioAvailable() == true"); + QCOMPARE(audioAvailableSpy.count(), 1); + arguments = audioAvailableSpy.takeFirst(); + QVERIFY(arguments.at(0).toBool() == true); + updateLog("\t audioAvailableChanged(true)"); + QCOMPARE(videoAvailableSpy.count(), 0); + + updateLog("*****testVideoAndAudioAvailability: PASSED"); + +} + +void tst_QMediaPlayer_xa::testStreamInformation() +{ + updateLog("*****testStreamInformation"); + resetPlayer(); + QMediaStreamsControl* m_streamControl = (QMediaStreamsControl*)(m_player->service()->requestControl(QMediaStreamsControl_iid)); + setVideoOnlyContent(); + + if(m_streamControl) + { + { + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + setAudioOnlyContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_streamControl->streamCount() == 1); + QCOMPARE(streamInfoSpy.count(), 1); + } + + { + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_streamControl->streamCount() == 2); + QCOMPARE(streamInfoSpy.count(), 1); + } + + { + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + setAudioVideoContent(); //set alternate content + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_streamControl->streamCount() == 2); + QCOMPARE(streamInfoSpy.count(), 1); + } + + { + QSignalSpy streamInfoSpy(m_streamControl, SIGNAL(streamsChanged())); + setVideoOnlyContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_streamControl->streamCount() == 1); + QCOMPARE(streamInfoSpy.count(), 1); + } + + updateLog("*****testStreamInformation: PASSED"); + } +} + +void tst_QMediaPlayer_xa::testPlay() +{ + updateLog("*****testPlay"); + resetPlayer(); + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_player->media() == *mediaContent); + QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + + //Play->Play + { + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 0); + } + + //Play->Pause + { + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 1); + } + + //Play->Stop + { + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 1); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testPlay: PASSED"); +} + +void tst_QMediaPlayer_xa::testPause() +{ + updateLog("*****testPause"); + resetPlayer(); + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_player->media() == *mediaContent); + QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + // at present there is no support for stop->pause state transition. TODO: uncomment when support added + //QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + //QCOMPARE(spy.count(), 1); + + //Pause->Play + { + //QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 1); + } + + //Pause->Pause + { + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 0); + } + + //Pause->Stop + { + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 1); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testPause: PASSED"); + +} + +void tst_QMediaPlayer_xa::testStop() +{ + updateLog("*****testStop"); + resetPlayer(); + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_player->media() == *mediaContent); + + QSignalSpy spy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(spy.count(), 0); + + //Stop->Play + { + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->play(); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + QCOMPARE(stateSpy.count(), 1); + } + // at present there is no support for stop->pause state transition. TODO: uncomment when support added + //Stop->Pause +/* { + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->pause(); + QCOMPARE(m_player->state(), QMediaPlayer::PausedState); + QCOMPARE(stateSpy.count(), 1); + } +*/ + //Stop->Stop + { + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QSignalSpy stateSpy(m_player, SIGNAL(stateChanged(QMediaPlayer::State))); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(stateSpy.count(), 0); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testStop: PASSED"); +} + +void tst_QMediaPlayer_xa::testMediaStatus() +{ + updateLog("*****testMediaStatus"); + resetPlayer(); + + QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(statusSpy.count()>0); + + { + QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QVERIFY(statusSpy.count()>0); + } + + { + QSignalSpy statusSpy(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + m_player->setPosition(duration - 10); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QVERIFY(statusSpy.count()>0); + } + + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testMediaStatus: PASSED"); +} + +void tst_QMediaPlayer_xa::testBufferStatus() +{ + updateLog("*****testBufferStatus"); + resetPlayer(); + m_player->setNotifyInterval(50); //Since default interval is 1 sec,could not receive any bufferStatusChanged SIGNAL,hence checking for 50milliseconds + QSignalSpy spy(m_player, SIGNAL(bufferStatusChanged(int))); + // setStreamingContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + WAIT_FOR_CONDITION(m_player->bufferStatus(), 100); + QVERIFY(spy.count()>0); + updateLog("*****testBufferStatus: PASSED"); +} + +void tst_QMediaPlayer_xa::testPlaybackRate() +{ + updateLog("*****testPlaybackRate"); + + resetPlayer(); + + qreal playbackRate = 1.5; + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + m_player->setPlaybackRate(playbackRate); + QVERIFY(m_player->playbackRate() == playbackRate); + + QSignalSpy spy(m_player, SIGNAL(playbackRateChanged(qreal))); + m_player->setPlaybackRate(playbackRate + 0.5f); + QCOMPARE(m_player->playbackRate(), playbackRate + 0.5f); + QCOMPARE(spy.count(), 1); + + updateLog("*****testPlaybackRate: PASSED"); +} + +void tst_QMediaPlayer_xa::testPlaybackRateWhilePlaying() +{ + updateLog("*****testPlaybackRateWhilePlaying"); + resetPlayer(); + + qreal playbackRate = 1.5; + + setAudioVideoContent(); + + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + m_player->setPlaybackRate(playbackRate); + QVERIFY(m_player->playbackRate() == playbackRate); + + QSignalSpy spy(m_player, SIGNAL(playbackRateChanged(qreal))); + m_player->setPlaybackRate(playbackRate + 0.5f); + QCOMPARE(m_player->playbackRate(), playbackRate + 0.5f); + QCOMPARE(spy.count(), 1); + + updateLog("*****testPlaybackRateWhilePlaying: PASSED"); +} + +void tst_QMediaPlayer_xa::testSeekable() +{ + updateLog("*****testBufferStatus"); + resetPlayer(); + QSignalSpy spy(m_player, SIGNAL(seekableChanged(bool))); + setAudioVideoContent(); + qint64 position = 1000; + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_player->isSeekable()==true); + m_player->setPosition(position); + QCOMPARE(spy.count(), 0); + QVERIFY(m_player->isSeekable()==true); + + updateLog("*****testBufferStatus: PASSED"); + +} + +void tst_QMediaPlayer_xa::testAspectRatioMode() +{ + updateLog("*****testBufferStatus"); + resetPlayer(); + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVideoWidgetControl* m_videoWidgetControl = (QVideoWidgetControl*)(m_player->service()->requestControl(QVideoWidgetControl_iid)); + + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::KeepAspectRatio); //default + + QTest::qWait(5000); //wait for 5 seconds + + { + m_videoWidgetControl->setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::IgnoreAspectRatio); + QTest::qWait(5000); //wait for 5 seconds + } + + { + m_videoWidgetControl->setAspectRatioMode(Qt::KeepAspectRatioByExpanding); + QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::KeepAspectRatioByExpanding); + QTest::qWait(5000); //wait for 5 seconds + } + { + m_videoWidgetControl->setAspectRatioMode(Qt::KeepAspectRatio); + QCOMPARE(m_videoWidgetControl->aspectRatioMode(), Qt::KeepAspectRatio); + QTest::qWait(5000); //wait for 5 seconds + } + + updateLog("*****testBufferStatus: PASSED"); + +} + +void tst_QMediaPlayer_xa::testFullScreen() +{ + updateLog("*****testFullScreen"); + resetPlayer(); + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVideoWidgetControl* m_videoWidgetControl = (QVideoWidgetControl*)(m_player->service()->requestControl(QVideoWidgetControl_iid)); + + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + //m_widget->resize(50, 50); + m_widget->showNormal(); + QTest::qWait(10000); //wait for 5 seconds + + + if(m_videoWidgetControl) + { + QSignalSpy spy(m_videoWidgetControl, SIGNAL(fullScreenChanged(bool))); + m_videoWidgetControl->setFullScreen(true); + QTest::qWait(10000); //wait for 5 seconds + QCOMPARE(m_videoWidgetControl->isFullScreen(), true); + QCOMPARE(spy.count(), 1); + } + + + if(m_videoWidgetControl) + { + QSignalSpy spy(m_videoWidgetControl, SIGNAL(fullScreenChanged(bool))); + m_videoWidgetControl->setFullScreen(false); + QCOMPARE(m_videoWidgetControl->isFullScreen(), false); + QTest::qWait(10000); //wait for 5 seconds + QCOMPARE(spy.count(), 1); + } + + updateLog("*****testFullScreen: PASSED"); +} + +void tst_QMediaPlayer_xa::testWindowControl_NativeSize() +{ + updateLog("*****testWindowControl_NativeSize"); + resetPlayer_WindowControl(); + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVERIFY(m_player->media() == *mediaContent); + m_player->play(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid)); + if (windowControl) + { + QSize size = windowControl->nativeSize(); + } + + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + updateLog("*****testWindowControl_NativeSize: PASSED"); +} + +void tst_QMediaPlayer_xa::testWindowControl_AspectRatioMode() +{ + updateLog("*****testWindowControl_AspectRatioMode"); + resetPlayer_WindowControl(); + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid)); + + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + QCOMPARE(windowControl->aspectRatioMode(), Qt::KeepAspectRatio); //default + + QTest::qWait(5000); //wait for 5 seconds + + { + windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(windowControl->aspectRatioMode(), Qt::IgnoreAspectRatio); + QTest::qWait(5000); //wait for 5 seconds + } + + { + windowControl->setAspectRatioMode(Qt::KeepAspectRatioByExpanding); + QCOMPARE(windowControl->aspectRatioMode(), Qt::KeepAspectRatioByExpanding); + QTest::qWait(5000); //wait for 5 seconds + } + { + windowControl->setAspectRatioMode(Qt::KeepAspectRatio); + QCOMPARE(windowControl->aspectRatioMode(), Qt::KeepAspectRatio); + QTest::qWait(5000); //wait for 5 seconds + } + + updateLog("*****testWindowControl_AspectRatioMode: PASSED"); + +} + +void tst_QMediaPlayer_xa::testWindowControl_FullScreen() +{ + updateLog("*****testWindowControl_FullScreen"); + resetPlayer_WindowControl(); + setAudioVideoContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QVideoWindowControl* windowControl = (QVideoWindowControl*)(m_player->service()->requestControl(QVideoWindowControl_iid)); + + m_player->play(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + + //m_windowWidget->resize(250, 350); + m_windowWidget->showNormal(); + QTest::qWait(10000); //wait for 5 seconds + + if(windowControl) + { + QSignalSpy spy(windowControl, SIGNAL(fullScreenChanged(bool))); + windowControl->setFullScreen(true); + QTest::qWait(10000); //wait for 5 seconds + QCOMPARE(windowControl->isFullScreen(), true); + QCOMPARE(spy.count(), 1); + } + + + if(windowControl) + { + QSignalSpy spy(windowControl, SIGNAL(fullScreenChanged(bool))); + windowControl->setFullScreen(false); + QCOMPARE(windowControl->isFullScreen(), false); + QTest::qWait(10000); //wait for 5 seconds + QCOMPARE(spy.count(), 1); + } + + updateLog("*****testWindowControl_FullScreen: PASSED"); +} + + +//adding access-point testcase + + +void tst_QMediaPlayer_xa::testSetconfigurationsAP() +{ + updateLog("*****testSetconfigurationsAP"); + resetPlayer(); + + //Passing only valid Accesspoint in QList + QList configs; + accesspointlist = manager.allConfigurations(); + for (int i=0; i<=accesspointlist.size()-1;i++) + qDebug()<<"accesspointlist"<< accesspointlist.at(i).name(); + configs<setNetworkConfigurations(configs); + setStreamingContent3gp(); + m_player->play(); + QTest::qWait(100000); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name()); + updateLog("*****testSetconfigurationsAP: PASSED"); + +} + + +void tst_QMediaPlayer_xa::testSetAccesspoint() +{ + updateLog("*****testSetAccesspoint"); + resetPlayer(); + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + + setStreamingContent3gp(); + QTest::qWait(200000); + m_player->play(); + QTest::qWait(10000); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name()); + + updateLog("*****testSetAccesspoint: PASSED"); +} + + +void tst_QMediaPlayer_xa::testGetAccesspoint() +{ + updateLog("*****testGetAccesspoint"); + resetPlayer(); + //getting information about the current configured accesspoint without setting any configurations + QNetworkConfiguration getaccespoint; + getaccespoint = m_player->currentNetworkConfiguration(); + QCOMPARE(getaccespoint.name(),QString("")); + updateLog("*****testGetAccesspoint: "); +} + + +void tst_QMediaPlayer_xa::testDiffmediacontentAP() +{ + updateLog("*****streaming Different mediacontent files via AP"); + resetPlayer(); + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + //first mediacontent file + setAudioStreamingContent(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + QTest::qWait(30000); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + //second mediacontent file + setStreamingContent3gp(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + QTest::qWait(20000); + QCOMPARE(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name()); + QNetworkConfiguration getaccespoint; + getaccespoint = m_player->currentNetworkConfiguration(); + QCOMPARE(getaccespoint.name(), QString("MMMW")); + + updateLog("*****testDiffmediacontentAP: PASSED"); +} + + +void tst_QMediaPlayer_xa::testInvalidaddressAP() +{ + updateLog("*****testInvalidaddressAP"); + resetPlayer(); + //setting all invalid accesspoint + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + QNetworkConfiguration getaccespoint; + getaccespoint = m_player->currentNetworkConfiguration(); + QCOMPARE(getaccespoint.name(), QString("")); + + updateLog("*****testInvalidaddressAP: PASSED"); +} + + + +void tst_QMediaPlayer_xa::testMultipleAccesspoints() +{ + updateLog("*****testMultipleAccesspoints"); + resetPlayer(); + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + setStreamingContent3gp(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QTest::qWait(20000); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name()); + //Second configuration list + QList secconfigs; + secaccesspoint = manager.allConfigurations(); + secconfigs<setNetworkConfigurations(secconfigs); + setStreamingContent3gp(); + // setAudioStreamingContent(); + QTest::qWait(30000); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QTest::qWait(10000); + updateLog("*****testSetAccesspoint: PASSED"); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(5).name()); + QNetworkConfiguration getaccespoint; + getaccespoint = m_player->currentNetworkConfiguration(); + QCOMPARE(getaccespoint.name(), QString("Mobile Office")); + + updateLog("*****testMultipleAccesspoints: PASSED"); +} + + +void tst_QMediaPlayer_xa::testReconnectAPWhilestreaming() +{ + updateLog("*****testReconnectAPWhilestreaming"); + resetPlayer(); + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + setAudioStreamingContent(); + m_player->play(); + QTest::qWait(200000); + configs<setNetworkConfigurations(configs); + m_player->play(); + QTest::qWait(20000); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::EndOfMedia); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name()); + QNetworkConfiguration getaccespoint; + getaccespoint = m_player->currentNetworkConfiguration(); + QCOMPARE(getaccespoint.name(), QString("MMMW")); + updateLog("*****testReconnectAPWhilestreaming: PASSED"); +} + + +void tst_QMediaPlayer_xa::teststreampausestream() +{ + updateLog("*****teststreampausestream"); + resetPlayer(); + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + setStreamingContent3gp(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QTest::qWait(10000); + m_player->pause(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PausedState); + + //Setting up the accesspoint when the player is in paused state + QList secconfigs; + secaccesspoint = manager.allConfigurations(); + secconfigs<setNetworkConfigurations(secconfigs); + m_player->play(); + QTest::qWait(20000); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + QCOMPARE((m_player->currentNetworkConfiguration()).name(), accesspointlist.at(8).name()); + m_player->stop(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::StoppedState); + setStreamingContent3gp(); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(m_player->mediaStatus(), QMediaPlayer::LoadedMedia); + m_player->play(); + QTest::qWait(20000); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + m_player->stop(); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(5).name()); + + updateLog("*****teststreampausestream: PASSED"); +} + + + +void tst_QMediaPlayer_xa::testStressAccessPoint() +{ + updateLog("*****testStressAccessPoint"); + resetPlayer(); + for (int i=0; i<=50; i++) { + QList configs; + accesspointlist = manager.allConfigurations(); + configs<setNetworkConfigurations(configs); + setStreamingContent3gp(); + m_player->play(); + QTest::qWait(20000); + WAIT_LONG_FOR_CONDITION(m_player->state(), QMediaPlayer::PlayingState); + WAIT_FOR_CONDITION(m_player->mediaStatus(), QMediaPlayer::BufferedMedia); + m_player->stop(); + QCOMPARE(m_player->state(), QMediaPlayer::StoppedState); + QCOMPARE((m_player->currentNetworkConfiguration().name()), accesspointlist.at(8).name()); + resetPlayer(); + } + + updateLog("*****testStressAccessPoint: PASSED"); +} + + + +void tst_QMediaPlayer_xa::updateLog(QString log, bool delFile) +{ + QString logFileName = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_detailed.log"; + if(delFile) + { + QFile::remove(logFileName); + } + + QFile f(logFileName); + + if( !f.open( QIODevice::WriteOnly | QIODevice::Append ) ) + { + return; + } + + QTextStream ts( &f ); + + ts< +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE +class mediaStatusList; +/* +class mediaStatusList : public QObject, public QList +{ + Q_OBJECT +public slots: + void mediaStatus(QMediaPlayer::MediaStatus status) { + append(status); + } + +public: + mediaStatusList(QObject *obj, const char *aSignal) + : QObject() + { + connect(obj, aSignal, this, SLOT(mediaStatus(QMediaPlayer::MediaStatus))); + } +}; +*/ +class tst_QMediaPlayer_xa: public QObject +{ + Q_OBJECT + +public: + tst_QMediaPlayer_xa(); + ~tst_QMediaPlayer_xa(); + +private slots: + void initTestCase_data(); + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + + void testMediaStatus(); + void testBufferStatus(); + void testPositionWhilePlaying(); + void testFullScreen(); + void testWindowControl_FullScreen(); + void testSeekable(); + void testStreamInformation(); + void testAspectRatioMode(); + void testMedia(); + void testDuration(); + void testPosition(); + void testVolume(); + void testVolumeWhilePlaying(); + void testMuted(); + void testMutedWhilePlaying(); + void testVideoAndAudioAvailability(); + void testPlay(); + void testPause(); + void testStop(); + void testPlaybackRate(); + void testPlaybackRateWhilePlaying(); + void testWindowControl_NativeSize(); + void testWindowControl_AspectRatioMode(); + void testSetconfigurationsAP(); + void testSetAccesspoint(); + void testGetAccesspoint(); + void testDiffmediacontentAP(); + void testInvalidaddressAP(); + void testMultipleAccesspoints(); + void testReconnectAPWhilestreaming(); + void teststreampausestream(); + void testStressAccessPoint(); + +private: + + void resetPlayer(); + void resetPlayer_WindowControl(); + + void updateLog(QString str, bool delFile=false); + void setAudioOnlyContent() + { + mediaContent = audioOnlyContent; + + m_player->setMedia(*mediaContent); + } + + void setVideoOnlyContent() + { + mediaContent = videoOnlyContent; + duration = 60000; + + m_player->setMedia(*mediaContent); + } + + void setAudioVideoContent() + { + if (mediaContent == audioVideoContent) { + mediaContent = audioVideoAltContent; + duration = 101840; + } else { + mediaContent = audioVideoContent; + duration = 141000; + } + m_player->setMedia(*mediaContent); + } + + void setStreamingContent3gp() + { + mediaContent = streamingContent3gp; + + m_player->setMedia(*mediaContent); + } + + void setAudioStreamingContent() + { + mediaContent = audioStreamingContent; + + m_player->setMedia(*mediaContent); + } + + + QMediaContent* audioOnlyContent; + QMediaContent* videoOnlyContent; + QMediaContent* audioVideoContent; + QMediaContent* audioVideoAltContent; + QMediaContent* mediaContent; + QMediaContent* streamingContent3gp; + QMediaContent* audioStreamingContent; + //for access-point requirement + QList accesspointlist; + QList secaccesspoint; + QNetworkConfigurationManager manager; + + qint64 duration; + QMediaPlayer *m_player; + QVideoWidget *m_widget; + QWidget *m_windowWidget; +}; + +#endif // TST_QMEDIAPLAYER_XA_H diff --git a/tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro b/tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro new file mode 100644 index 000000000..5d6c46b77 --- /dev/null +++ b/tests/auto/qmediaplayerbackend/qmediaplayerbackend.pro @@ -0,0 +1,23 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediaplayerbackend +# CONFIG += testcase + +symbian*: { + PLAYLIST_TESTDATA.sources = testdata/* + PLAYLIST_TESTDATA.path = testdata + DEPLOYMENT += PLAYLIST_TESTDATA +} + +wince* { + DEFINES+= TESTDATA_DIR=\\\"./\\\" +}else:!symbian { + DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\" +} + +SOURCES += \ + tst_qmediaplayerbackend.cpp + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qmediaplayerbackend/testdata/test.wav b/tests/auto/qmediaplayerbackend/testdata/test.wav new file mode 100644 index 000000000..4dd022661 Binary files /dev/null and b/tests/auto/qmediaplayerbackend/testdata/test.wav differ diff --git a/tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp new file mode 100644 index 000000000..ec46dfa14 --- /dev/null +++ b/tests/auto/qmediaplayerbackend/tst_qmediaplayerbackend.cpp @@ -0,0 +1,462 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include +#include +#include "qmediaservice.h" +#include "qmediaplayer.h" + +//TESTED_COMPONENT=src/multimedia + +#ifndef TESTDATA_DIR +#define TESTDATA_DIR "./" +#endif + +QT_USE_NAMESPACE + +// Eventually these will make it into qtestcase.h +// but we might need to tweak the timeout values here. +#ifndef QTRY_COMPARE +#define QTRY_COMPARE(__expr, __expected) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if ((__expr) != (__expected)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QCOMPARE(__expr, __expected); \ + } while(0) +#endif + +#ifndef QTRY_VERIFY +#define QTRY_VERIFY(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY(__expr); \ + } while(0) +#endif + + +#define QTRY_WAIT(code, __expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 5000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + do { code } while(0); \ + QTest::qWait(__step); \ + } \ + } while(0) + + +/* + This is the backend conformance test. + + Since it relies on platform media framework and sound hardware + it may be less stable. +*/ + +class tst_QMediaPlayerBackend : public QObject +{ + Q_OBJECT +public slots: + void init(); + void cleanup(); + void initTestCase(); + +private slots: + void construction(); + void loadMedia(); + void unloadMedia(); + void playPauseStop(); + void processEOS(); + void volumeAndMuted(); + void volumeAcrossFiles_data(); + void volumeAcrossFiles(); + +private: + //one second local wav file + QMediaContent localWavFile; +}; + +void tst_QMediaPlayerBackend::init() +{ +} + +void tst_QMediaPlayerBackend::initTestCase() +{ + QFileInfo wavFile(QLatin1String(TESTDATA_DIR "testdata/test.wav")); + QVERIFY(wavFile.exists()); + + localWavFile = QMediaContent(QUrl::fromLocalFile(wavFile.absoluteFilePath())); + + qRegisterMetaType(); +} + +void tst_QMediaPlayerBackend::cleanup() +{ +} + +void tst_QMediaPlayerBackend::construction() +{ + QMediaPlayer player; + QVERIFY(player.isAvailable()); +} + +void tst_QMediaPlayerBackend::loadMedia() +{ + QMediaPlayer player; + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::NoMedia); + + QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent))); + + player.setMedia(localWavFile); + + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + + QVERIFY(player.mediaStatus() != QMediaPlayer::NoMedia); + QVERIFY(player.mediaStatus() != QMediaPlayer::InvalidMedia); + QVERIFY(player.media() == localWavFile); + + QCOMPARE(stateSpy.count(), 0); + QVERIFY(statusSpy.count() > 0); + QCOMPARE(mediaSpy.count(), 1); + QCOMPARE(mediaSpy.last()[0].value(), localWavFile); + + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia); + + QVERIFY(player.isAudioAvailable()); + QVERIFY(!player.isVideoAvailable()); +} + +void tst_QMediaPlayerBackend::unloadMedia() +{ + QMediaPlayer player; + player.setNotifyInterval(50); + + QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + QSignalSpy mediaSpy(&player, SIGNAL(mediaChanged(QMediaContent))); + QSignalSpy positionSpy(&player, SIGNAL(positionChanged(qint64))); + QSignalSpy durationSpy(&player, SIGNAL(positionChanged(qint64))); + + player.setMedia(localWavFile); + + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia); + + QVERIFY(player.position() == 0); + QVERIFY(player.duration() > 0); + + player.play(); + + QTest::qWait(250); + QVERIFY(player.position() > 0); + QVERIFY(player.duration() > 0); + + stateSpy.clear(); + statusSpy.clear(); + mediaSpy.clear(); + positionSpy.clear(); + durationSpy.clear(); + + player.setMedia(QMediaContent()); + + QVERIFY(player.position() <= 0); + QVERIFY(player.duration() <= 0); + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::NoMedia); + QCOMPARE(player.media(), QMediaContent()); + + QVERIFY(!stateSpy.isEmpty()); + QVERIFY(!statusSpy.isEmpty()); + QVERIFY(!mediaSpy.isEmpty()); + QVERIFY(!positionSpy.isEmpty()); +} + + +void tst_QMediaPlayerBackend::playPauseStop() +{ + QMediaPlayer player; + player.setNotifyInterval(50); + + QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + QSignalSpy positionSpy(&player, SIGNAL(positionChanged(qint64))); + + player.setMedia(localWavFile); + + QCOMPARE(player.position(), qint64(0)); + + player.play(); + + QCOMPARE(player.state(), QMediaPlayer::PlayingState); + + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia); + + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(stateSpy.last()[0].value(), QMediaPlayer::PlayingState); + QTRY_VERIFY(statusSpy.count() > 0 && + statusSpy.last()[0].value() == QMediaPlayer::BufferedMedia); + + QTest::qWait(500); + QVERIFY(player.position() > 0); + QVERIFY(player.duration() > 0); + QVERIFY(positionSpy.count() > 0); + QVERIFY(positionSpy.last()[0].value() > 0); + + stateSpy.clear(); + statusSpy.clear(); + + player.pause(); + + QCOMPARE(player.state(), QMediaPlayer::PausedState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia); + + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(stateSpy.last()[0].value(), QMediaPlayer::PausedState); + + stateSpy.clear(); + statusSpy.clear(); + + player.stop(); + + QCOMPARE(player.state(), QMediaPlayer::StoppedState); + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia); + + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(stateSpy.last()[0].value(), QMediaPlayer::StoppedState); + //it's allowed to emit statusChanged() signal async + QTRY_COMPARE(statusSpy.count(), 1); + QCOMPARE(statusSpy.last()[0].value(), QMediaPlayer::LoadedMedia); + + //ensure the position is reset to 0 at stop and positionChanged(0) is emitted + QCOMPARE(player.position(), qint64(0)); + QCOMPARE(positionSpy.last()[0].value(), qint64(0)); + QVERIFY(player.duration() > 0); +} + + +void tst_QMediaPlayerBackend::processEOS() +{ + QMediaPlayer player; + player.setNotifyInterval(50); + + QSignalSpy stateSpy(&player, SIGNAL(stateChanged(QMediaPlayer::State))); + QSignalSpy statusSpy(&player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + QSignalSpy positionSpy(&player, SIGNAL(positionChanged(qint64))); + + player.setMedia(localWavFile); + + player.play(); + player.setPosition(900); + + //wait up to 5 seconds for EOS + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::EndOfMedia); + + QVERIFY(statusSpy.count() > 0); + QCOMPARE(statusSpy.last()[0].value(), QMediaPlayer::EndOfMedia); + + //at EOS the position stays at the end of file + QVERIFY(player.position() > 900); + + stateSpy.clear(); + statusSpy.clear(); + + player.play(); + + //position is reset to start + QTRY_VERIFY(player.position() < 100); + + QCOMPARE(player.state(), QMediaPlayer::PlayingState); + QCOMPARE(player.mediaStatus(), QMediaPlayer::BufferedMedia); + + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(stateSpy.last()[0].value(), QMediaPlayer::PlayingState); + QVERIFY(statusSpy.count() > 0); + QCOMPARE(statusSpy.last()[0].value(), QMediaPlayer::BufferedMedia); + + player.setPosition(900); + //wait up to 5 seconds for EOS + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::EndOfMedia); + + //ensure the positionChanged() signal is emitted + QVERIFY(positionSpy.count() > 0); + + QCOMPARE(player.mediaStatus(), QMediaPlayer::EndOfMedia); + //position stays at the end of file + QVERIFY(player.position() > 900); + + //after setPosition EndOfMedia status should be reset to Loaded + stateSpy.clear(); + statusSpy.clear(); + player.setPosition(500); + + //this transition can be async, so allow backend to perform it + QTRY_COMPARE(player.mediaStatus(), QMediaPlayer::LoadedMedia); + + QCOMPARE(stateSpy.count(), 0); + QTRY_VERIFY(statusSpy.count() > 0 && + statusSpy.last()[0].value() == QMediaPlayer::LoadedMedia); +} + +void tst_QMediaPlayerBackend::volumeAndMuted() +{ + //volume and muted properties should be independent + QMediaPlayer player; + QVERIFY(player.volume() > 0); + QVERIFY(!player.isMuted()); + + player.setMedia(localWavFile); + player.pause(); + + QVERIFY(player.volume() > 0); + QVERIFY(!player.isMuted()); + + QSignalSpy volumeSpy(&player, SIGNAL(volumeChanged(int))); + QSignalSpy mutedSpy(&player, SIGNAL(mutedChanged(bool))); + + //setting volume to 0 should not trigger muted + player.setVolume(0); + QTRY_COMPARE(player.volume(), 0); + QVERIFY(!player.isMuted()); + QCOMPARE(volumeSpy.count(), 1); + QCOMPARE(volumeSpy.last()[0].toInt(), player.volume()); + QCOMPARE(mutedSpy.count(), 0); + + player.setVolume(50); + QTRY_COMPARE(player.volume(), 50); + QVERIFY(!player.isMuted()); + QCOMPARE(volumeSpy.count(), 2); + QCOMPARE(volumeSpy.last()[0].toInt(), player.volume()); + QCOMPARE(mutedSpy.count(), 0); + + player.setMuted(true); + QTRY_VERIFY(player.isMuted()); + QVERIFY(player.volume() > 0); + QCOMPARE(volumeSpy.count(), 2); + QCOMPARE(mutedSpy.count(), 1); + QCOMPARE(mutedSpy.last()[0].toBool(), player.isMuted()); + + player.setMuted(false); + QTRY_VERIFY(!player.isMuted()); + QVERIFY(player.volume() > 0); + QCOMPARE(volumeSpy.count(), 2); + QCOMPARE(mutedSpy.count(), 2); + QCOMPARE(mutedSpy.last()[0].toBool(), player.isMuted()); + +} + +void tst_QMediaPlayerBackend::volumeAcrossFiles_data() +{ + QTest::addColumn("volume"); + QTest::addColumn("muted"); + + QTest::newRow("100 unmuted") << 100 << false; + QTest::newRow("50 unmuted") << 50 << false; + QTest::newRow("0 unmuted") << 0 << false; + QTest::newRow("100 muted") << 100 << true; + QTest::newRow("50 muted") << 50 << true; + QTest::newRow("0 muted") << 0 << true; +} + +void tst_QMediaPlayerBackend::volumeAcrossFiles() +{ + QFETCH(int, volume); + QFETCH(bool, muted); + + QMediaPlayer player; + + //volume and muted should not be preserved between player instances + QVERIFY(player.volume() > 0); + QVERIFY(!player.isMuted()); + + player.setVolume(volume); + player.setMuted(muted); + + QTRY_COMPARE(player.volume(), volume); + QTRY_COMPARE(player.isMuted(), muted); + + player.setMedia(localWavFile); + QCOMPARE(player.volume(), volume); + QCOMPARE(player.isMuted(), muted); + + player.pause(); + + //to ensure the backend doesn't change volume/muted + //async during file loading. + QTest::qWait(50); + + QCOMPARE(player.volume(), volume); + QCOMPARE(player.isMuted(), muted); + + player.setMedia(QMediaContent()); + QTest::qWait(50); + QCOMPARE(player.volume(), volume); + QCOMPARE(player.isMuted(), muted); + + player.setMedia(localWavFile); + player.pause(); + + QTest::qWait(50); + + QCOMPARE(player.volume(), volume); + QCOMPARE(player.isMuted(), muted); +} + + +QTEST_MAIN(tst_QMediaPlayerBackend) +#include "tst_qmediaplayerbackend.moc" + diff --git a/tests/auto/qmediaplaylist/qmediaplaylist.pro b/tests/auto/qmediaplaylist/qmediaplaylist.pro new file mode 100644 index 000000000..bd1ad114e --- /dev/null +++ b/tests/auto/qmediaplaylist/qmediaplaylist.pro @@ -0,0 +1,29 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediaplaylist +# CONFIG += testcase + +symbian*: { + PLAYLIST_TESTDATA.sources = testdata/* + PLAYLIST_TESTDATA.path = testdata + DEPLOYMENT += PLAYLIST_TESTDATA +} + +wince* { + DEFINES+= TESTDATA_DIR=\\\"./\\\" +}else:!symbian { + DEFINES += TESTDATA_DIR=\\\"$$PWD/\\\" +} + +HEADERS += \ + $$QT.multimediakit.sources/../plugins/m3u/qm3uhandler.h + +SOURCES += \ + tst_qmediaplaylist.cpp \ + $$QT.multimediakit.sources/../plugins/m3u/qm3uhandler.cpp + +INCLUDEPATH += $$QT.multimediakit.sources/../plugins/m3u + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qmediaplaylist/testdata/test.m3u b/tests/auto/qmediaplaylist/testdata/test.m3u new file mode 100644 index 000000000..e5cb7c828 --- /dev/null +++ b/tests/auto/qmediaplaylist/testdata/test.m3u @@ -0,0 +1,11 @@ +#comment + +http://test.host/path + http://test.host/path +testfile + + +testdir/testfile +/testdir/testfile +file://path/name#suffix +testfile2#suffix diff --git a/tests/auto/qmediaplaylist/testdata/testfile b/tests/auto/qmediaplaylist/testdata/testfile new file mode 100644 index 000000000..e69de29bb diff --git a/tests/auto/qmediaplaylist/testdata/testfile2#suffix b/tests/auto/qmediaplaylist/testdata/testfile2#suffix new file mode 100644 index 000000000..e69de29bb diff --git a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp new file mode 100644 index 000000000..1a0395a54 --- /dev/null +++ b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp @@ -0,0 +1,666 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include +#include +#include "qmediaservice.h" +#include "qmediaplaylist.h" +#include "qmediaplaylistcontrol.h" +#include "qmediaplaylistnavigator.h" +#include + +#include "qm3uhandler.h" + +//TESTED_COMPONENT=src/multimedia + +#ifndef TESTDATA_DIR +#define TESTDATA_DIR "./" +#endif + +QT_USE_NAMESPACE +class MockReadOnlyPlaylistProvider : public QMediaPlaylistProvider +{ + Q_OBJECT +public: + MockReadOnlyPlaylistProvider(QObject *parent) + :QMediaPlaylistProvider(parent) + { + m_items.append(QMediaContent(QUrl(QLatin1String("file:///1")))); + m_items.append(QMediaContent(QUrl(QLatin1String("file:///2")))); + m_items.append(QMediaContent(QUrl(QLatin1String("file:///3")))); + } + + int mediaCount() const { return m_items.size(); } + QMediaContent media(int index) const + { + return index >=0 && index < mediaCount() ? m_items.at(index) : QMediaContent(); + } + +private: + QList m_items; +}; + +class MockPlaylistControl : public QMediaPlaylistControl +{ + Q_OBJECT +public: + MockPlaylistControl(QObject *parent) : QMediaPlaylistControl(parent) + { + m_navigator = new QMediaPlaylistNavigator(new MockReadOnlyPlaylistProvider(this), this); + } + + ~MockPlaylistControl() + { + } + + QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); } + bool setPlaylistProvider(QMediaPlaylistProvider *playlist) { m_navigator->setPlaylist(playlist); return true; } + + int currentIndex() const { return m_navigator->currentIndex(); } + void setCurrentIndex(int position) { m_navigator->jump(position); } + int nextIndex(int steps) const { return m_navigator->nextIndex(steps); } + int previousIndex(int steps) const { return m_navigator->previousIndex(steps); } + + void next() { m_navigator->next(); } + void previous() { m_navigator->previous(); } + + QMediaPlaylist::PlaybackMode playbackMode() const { return m_navigator->playbackMode(); } + void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) { m_navigator->setPlaybackMode(mode); } + +private: + QMediaPlaylistNavigator *m_navigator; +}; + +class MockPlaylistService : public QMediaService +{ + Q_OBJECT + +public: + MockPlaylistService():QMediaService(0) + { + mockControl = new MockPlaylistControl(this); + } + + ~MockPlaylistService() + { + } + + QMediaControl* requestControl(const char *iid) + { + if (qstrcmp(iid, QMediaPlaylistControl_iid) == 0) + return mockControl; + return 0; + } + + void releaseControl(QMediaControl *) + { + } + + MockPlaylistControl *mockControl; +}; + +class MockReadOnlyPlaylistObject : public QMediaObject +{ + Q_OBJECT +public: + MockReadOnlyPlaylistObject(QObject *parent = 0) + :QMediaObject(parent, new MockPlaylistService) + { + } +}; + + +class tst_QMediaPlaylist : public QObject +{ + Q_OBJECT +public slots: + void init(); + void cleanup(); + void initTestCase(); + +private slots: + void construction(); + void append(); + void insert(); + void clear(); + void removeMedia(); + void currentItem(); + void saveAndLoad(); + void loadM3uFile(); + void playbackMode(); + void playbackMode_data(); + void shuffle(); + void readOnlyPlaylist(); + void setMediaObject(); + +private: + QMediaContent content1; + QMediaContent content2; + QMediaContent content3; +}; + +void tst_QMediaPlaylist::init() +{ +} + +void tst_QMediaPlaylist::initTestCase() +{ + content1 = QMediaContent(QUrl(QLatin1String("file:///1"))); + content2 = QMediaContent(QUrl(QLatin1String("file:///2"))); + content3 = QMediaContent(QUrl(QLatin1String("file:///3"))); + + QMediaPluginLoader::setStaticPlugins(QLatin1String("playlistformats"), QObjectList() << new QM3uPlaylistPlugin(this)); +} + +void tst_QMediaPlaylist::cleanup() +{ +} + +void tst_QMediaPlaylist::construction() +{ + QMediaPlaylist playlist; + QCOMPARE(playlist.mediaCount(), 0); + QVERIFY(playlist.isEmpty()); +} + +void tst_QMediaPlaylist::append() +{ + QMediaPlaylist playlist; + QVERIFY(!playlist.isReadOnly()); + + playlist.addMedia(content1); + QCOMPARE(playlist.mediaCount(), 1); + QCOMPARE(playlist.media(0), content1); + + QSignalSpy aboutToBeInsertedSignalSpy(&playlist, SIGNAL(mediaAboutToBeInserted(int,int))); + QSignalSpy insertedSignalSpy(&playlist, SIGNAL(mediaInserted(int,int))); + playlist.addMedia(content2); + QCOMPARE(playlist.mediaCount(), 2); + QCOMPARE(playlist.media(1), content2); + + QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy.first()[0].toInt(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy.first()[1].toInt(), 1); + + QCOMPARE(insertedSignalSpy.count(), 1); + QCOMPARE(insertedSignalSpy.first()[0].toInt(), 1); + QCOMPARE(insertedSignalSpy.first()[1].toInt(), 1); + + aboutToBeInsertedSignalSpy.clear(); + insertedSignalSpy.clear(); + + QMediaContent content4(QUrl(QLatin1String("file:///4"))); + QMediaContent content5(QUrl(QLatin1String("file:///5"))); + playlist.addMedia(QList() << content3 << content4 << content5); + QCOMPARE(playlist.mediaCount(), 5); + QCOMPARE(playlist.media(2), content3); + QCOMPARE(playlist.media(3), content4); + QCOMPARE(playlist.media(4), content5); + + QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy[0][0].toInt(), 2); + QCOMPARE(aboutToBeInsertedSignalSpy[0][1].toInt(), 4); + + QCOMPARE(insertedSignalSpy.count(), 1); + QCOMPARE(insertedSignalSpy[0][0].toInt(), 2); + QCOMPARE(insertedSignalSpy[0][1].toInt(), 4); + + aboutToBeInsertedSignalSpy.clear(); + insertedSignalSpy.clear(); + + playlist.addMedia(QList()); + QCOMPARE(aboutToBeInsertedSignalSpy.count(), 0); + QCOMPARE(insertedSignalSpy.count(), 0); +} + +void tst_QMediaPlaylist::insert() +{ + QMediaPlaylist playlist; + QVERIFY(!playlist.isReadOnly()); + + playlist.addMedia(content1); + QCOMPARE(playlist.mediaCount(), 1); + QCOMPARE(playlist.media(0), content1); + + playlist.addMedia(content2); + QCOMPARE(playlist.mediaCount(), 2); + QCOMPARE(playlist.media(1), content2); + + QSignalSpy aboutToBeInsertedSignalSpy(&playlist, SIGNAL(mediaAboutToBeInserted(int,int))); + QSignalSpy insertedSignalSpy(&playlist, SIGNAL(mediaInserted(int,int))); + + playlist.insertMedia(1, content3); + QCOMPARE(playlist.mediaCount(), 3); + QCOMPARE(playlist.media(0), content1); + QCOMPARE(playlist.media(1), content3); + QCOMPARE(playlist.media(2), content2); + + QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy.first()[0].toInt(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy.first()[1].toInt(), 1); + + QCOMPARE(insertedSignalSpy.count(), 1); + QCOMPARE(insertedSignalSpy.first()[0].toInt(), 1); + QCOMPARE(insertedSignalSpy.first()[1].toInt(), 1); + + aboutToBeInsertedSignalSpy.clear(); + insertedSignalSpy.clear(); + + QMediaContent content4(QUrl(QLatin1String("file:///4"))); + QMediaContent content5(QUrl(QLatin1String("file:///5"))); + playlist.insertMedia(1, QList() << content4 << content5); + + QCOMPARE(playlist.media(0), content1); + QCOMPARE(playlist.media(1), content4); + QCOMPARE(playlist.media(2), content5); + QCOMPARE(playlist.media(3), content3); + QCOMPARE(playlist.media(4), content2); + QCOMPARE(aboutToBeInsertedSignalSpy.count(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy[0][0].toInt(), 1); + QCOMPARE(aboutToBeInsertedSignalSpy[0][1].toInt(), 2); + + QCOMPARE(insertedSignalSpy.count(), 1); + QCOMPARE(insertedSignalSpy[0][0].toInt(), 1); + QCOMPARE(insertedSignalSpy[0][1].toInt(), 2); + + aboutToBeInsertedSignalSpy.clear(); + insertedSignalSpy.clear(); + + playlist.insertMedia(1, QList()); + QCOMPARE(aboutToBeInsertedSignalSpy.count(), 0); + QCOMPARE(insertedSignalSpy.count(), 0); +} + + +void tst_QMediaPlaylist::currentItem() +{ + QMediaPlaylist playlist; + playlist.addMedia(content1); + playlist.addMedia(content2); + + QCOMPARE(playlist.currentIndex(), -1); + QCOMPARE(playlist.currentMedia(), QMediaContent()); + + QCOMPARE(playlist.nextIndex(), 0); + QCOMPARE(playlist.nextIndex(2), 1); + QCOMPARE(playlist.previousIndex(), 1); + QCOMPARE(playlist.previousIndex(2), 0); + + playlist.setCurrentIndex(0); + QCOMPARE(playlist.currentIndex(), 0); + QCOMPARE(playlist.currentMedia(), content1); + + QCOMPARE(playlist.nextIndex(), 1); + QCOMPARE(playlist.nextIndex(2), -1); + QCOMPARE(playlist.previousIndex(), -1); + QCOMPARE(playlist.previousIndex(2), -1); + + playlist.setCurrentIndex(1); + QCOMPARE(playlist.currentIndex(), 1); + QCOMPARE(playlist.currentMedia(), content2); + + QCOMPARE(playlist.nextIndex(), -1); + QCOMPARE(playlist.nextIndex(2), -1); + QCOMPARE(playlist.previousIndex(), 0); + QCOMPARE(playlist.previousIndex(2), -1); + + QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range "); + playlist.setCurrentIndex(2); + + QCOMPARE(playlist.currentIndex(), -1); + QCOMPARE(playlist.currentMedia(), QMediaContent()); +} + +void tst_QMediaPlaylist::clear() +{ + QMediaPlaylist playlist; + playlist.addMedia(content1); + playlist.addMedia(content2); + + playlist.clear(); + QVERIFY(playlist.isEmpty()); + QCOMPARE(playlist.mediaCount(), 0); +} + +void tst_QMediaPlaylist::removeMedia() +{ + QMediaPlaylist playlist; + playlist.addMedia(content1); + playlist.addMedia(content2); + playlist.addMedia(content3); + + QSignalSpy aboutToBeRemovedSignalSpy(&playlist, SIGNAL(mediaAboutToBeRemoved(int,int))); + QSignalSpy removedSignalSpy(&playlist, SIGNAL(mediaRemoved(int,int))); + playlist.removeMedia(1); + QCOMPARE(playlist.mediaCount(), 2); + QCOMPARE(playlist.media(1), content3); + + QCOMPARE(aboutToBeRemovedSignalSpy.count(), 1); + QCOMPARE(aboutToBeRemovedSignalSpy.first()[0].toInt(), 1); + QCOMPARE(aboutToBeRemovedSignalSpy.first()[1].toInt(), 1); + + QCOMPARE(removedSignalSpy.count(), 1); + QCOMPARE(removedSignalSpy.first()[0].toInt(), 1); + QCOMPARE(removedSignalSpy.first()[1].toInt(), 1); + + aboutToBeRemovedSignalSpy.clear(); + removedSignalSpy.clear(); + + playlist.removeMedia(0,1); + QVERIFY(playlist.isEmpty()); + + QCOMPARE(aboutToBeRemovedSignalSpy.count(), 1); + QCOMPARE(aboutToBeRemovedSignalSpy.first()[0].toInt(), 0); + QCOMPARE(aboutToBeRemovedSignalSpy.first()[1].toInt(), 1); + + QCOMPARE(removedSignalSpy.count(), 1); + QCOMPARE(removedSignalSpy.first()[0].toInt(), 0); + QCOMPARE(removedSignalSpy.first()[1].toInt(), 1); + + + playlist.addMedia(content1); + playlist.addMedia(content2); + playlist.addMedia(content3); + + playlist.removeMedia(0,1); + QCOMPARE(playlist.mediaCount(), 1); + QCOMPARE(playlist.media(0), content3); +} + +void tst_QMediaPlaylist::saveAndLoad() +{ + QMediaPlaylist playlist; + playlist.addMedia(content1); + playlist.addMedia(content2); + playlist.addMedia(content3); + + QCOMPARE(playlist.error(), QMediaPlaylist::NoError); + QVERIFY(playlist.errorString().isEmpty()); + + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + + bool res = playlist.save(&buffer, "unsupported_format"); + QVERIFY(!res); + QVERIFY(playlist.error() != QMediaPlaylist::NoError); + QVERIFY(!playlist.errorString().isEmpty()); + + QSignalSpy errorSignal(&playlist, SIGNAL(loadFailed())); + playlist.load(&buffer, "unsupported_format"); + QCOMPARE(errorSignal.size(), 1); + QVERIFY(playlist.error() != QMediaPlaylist::NoError); + QVERIFY(!playlist.errorString().isEmpty()); + + res = playlist.save(QUrl(QLatin1String("tmp.unsupported_format")), "unsupported_format"); + QVERIFY(!res); + QVERIFY(playlist.error() != QMediaPlaylist::NoError); + QVERIFY(!playlist.errorString().isEmpty()); + + errorSignal.clear(); + playlist.load(QUrl(QLatin1String("tmp.unsupported_format")), "unsupported_format"); + QCOMPARE(errorSignal.size(), 1); + QVERIFY(playlist.error() != QMediaPlaylist::NoError); + QVERIFY(!playlist.errorString().isEmpty()); + + res = playlist.save(&buffer, "m3u"); + + QVERIFY(res); + QVERIFY(buffer.pos() > 0); + buffer.seek(0); + + QMediaPlaylist playlist2; + playlist2.load(&buffer, "m3u"); + QCOMPARE(playlist.error(), QMediaPlaylist::NoError); + + QCOMPARE(playlist.mediaCount(), playlist2.mediaCount()); + QCOMPARE(playlist.media(0), playlist2.media(0)); + QCOMPARE(playlist.media(1), playlist2.media(1)); + QCOMPARE(playlist.media(3), playlist2.media(3)); +#ifdef Q_OS_SYMBIAN + res = playlist.save(QUrl(QLatin1String("file:///c:/data/test_m3u.m3u")), "m3u"); +#else + res = playlist.save(QUrl(QLatin1String("tmp.m3u")), "m3u"); +#endif + QVERIFY(res); + + playlist2.clear(); + QVERIFY(playlist2.isEmpty()); +#ifdef Q_OS_SYMBIAN + playlist2.load(QUrl(QLatin1String("file:///c:/data/test_m3u.m3u")), "m3u"); +#else + playlist2.load(QUrl(QLatin1String("tmp.m3u")), "m3u"); +#endif + QCOMPARE(playlist.error(), QMediaPlaylist::NoError); + + QCOMPARE(playlist.mediaCount(), playlist2.mediaCount()); + QCOMPARE(playlist.media(0), playlist2.media(0)); + QCOMPARE(playlist.media(1), playlist2.media(1)); + QCOMPARE(playlist.media(3), playlist2.media(3)); +} + +void tst_QMediaPlaylist::loadM3uFile() +{ + QMediaPlaylist playlist; + + playlist.load(QUrl::fromLocalFile(QLatin1String(TESTDATA_DIR "testdata/missing_file.m3u"))); + QVERIFY(playlist.error() != QMediaPlaylist::NoError); + + playlist.load(QUrl::fromLocalFile(QLatin1String(TESTDATA_DIR "testdata/test.m3u"))); + QCOMPARE(playlist.error(), QMediaPlaylist::NoError); + QCOMPARE(playlist.mediaCount(), 7); + + QCOMPARE(playlist.media(0).canonicalUrl(), QUrl(QLatin1String("http://test.host/path"))); + QCOMPARE(playlist.media(1).canonicalUrl(), QUrl(QLatin1String("http://test.host/path"))); + QCOMPARE(playlist.media(2).canonicalUrl(), + QUrl(QLatin1String("file://" TESTDATA_DIR "testdata/testfile"))); + QCOMPARE(playlist.media(3).canonicalUrl(), + QUrl(QLatin1String("file://" TESTDATA_DIR "testdata/testdir/testfile"))); + QCOMPARE(playlist.media(4).canonicalUrl(), QUrl(QLatin1String("file:///testdir/testfile"))); + QCOMPARE(playlist.media(5).canonicalUrl(), QUrl(QLatin1String("file://path/name#suffix"))); + //ensure #2 suffix is not stripped from path + QCOMPARE(playlist.media(6).canonicalUrl(), QUrl::fromLocalFile(TESTDATA_DIR "testdata/testfile2#suffix")); +} + +void tst_QMediaPlaylist::playbackMode_data() +{ + QTest::addColumn("playbackMode"); + QTest::addColumn("expectedPrevious"); + QTest::addColumn("pos"); + QTest::addColumn("expectedNext"); + + QTest::newRow("Sequential, 0") << QMediaPlaylist::Sequential << -1 << 0 << 1; + QTest::newRow("Sequential, 1") << QMediaPlaylist::Sequential << 0 << 1 << 2; + QTest::newRow("Sequential, 2") << QMediaPlaylist::Sequential << 1 << 2 << -1; + + QTest::newRow("Loop, 0") << QMediaPlaylist::Loop << 2 << 0 << 1; + QTest::newRow("Loop, 1") << QMediaPlaylist::Loop << 0 << 1 << 2; + QTest::newRow("Lopp, 2") << QMediaPlaylist::Loop << 1 << 2 << 0; + + QTest::newRow("ItemOnce, 1") << QMediaPlaylist::CurrentItemOnce << -1 << 1 << -1; + QTest::newRow("ItemInLoop, 1") << QMediaPlaylist::CurrentItemInLoop << 1 << 1 << 1; + +} + +void tst_QMediaPlaylist::playbackMode() +{ + QFETCH(QMediaPlaylist::PlaybackMode, playbackMode); + QFETCH(int, expectedPrevious); + QFETCH(int, pos); + QFETCH(int, expectedNext); + + QMediaPlaylist playlist; + playlist.addMedia(content1); + playlist.addMedia(content2); + playlist.addMedia(content3); + + QCOMPARE(playlist.playbackMode(), QMediaPlaylist::Sequential); + QCOMPARE(playlist.currentIndex(), -1); + + playlist.setPlaybackMode(playbackMode); + QCOMPARE(playlist.playbackMode(), playbackMode); + + playlist.setCurrentIndex(pos); + QCOMPARE(playlist.currentIndex(), pos); + QCOMPARE(playlist.nextIndex(), expectedNext); + QCOMPARE(playlist.previousIndex(), expectedPrevious); + + playlist.next(); + QCOMPARE(playlist.currentIndex(), expectedNext); + + playlist.setCurrentIndex(pos); + playlist.previous(); + QCOMPARE(playlist.currentIndex(), expectedPrevious); +} + +void tst_QMediaPlaylist::shuffle() +{ + QMediaPlaylist playlist; + QList contentList; + + for (int i=0; i<100; i++) { + QMediaContent content(QUrl(QString::number(i))); + contentList.append(content); + playlist.addMedia(content); + } + + playlist.shuffle(); + + QList shuffledContentList; + for (int i=0; i() << content1 << content2)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(!playlist.insertMedia(1, content1)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(!playlist.insertMedia(1, QList() << content1 << content2)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(!playlist.removeMedia(1)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(!playlist.removeMedia(0,2)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(!playlist.clear()); + QCOMPARE(playlist.mediaCount(), 3); + + //but it is still allowed to append/insert an empty list + QVERIFY(playlist.addMedia(QList())); + QVERIFY(playlist.insertMedia(1, QList())); + + playlist.shuffle(); + //it's still the same + QCOMPARE(playlist.media(0), content1); + QCOMPARE(playlist.media(1), content2); + QCOMPARE(playlist.media(2), content3); + QCOMPARE(playlist.media(3), QMediaContent()); + + + //load to read only playlist should fail, + //unless underlaying provider supports it + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + buffer.write(QByteArray("file:///1\nfile:///2")); + buffer.seek(0); + + QSignalSpy errorSignal(&playlist, SIGNAL(loadFailed())); + playlist.load(&buffer, "m3u"); + QCOMPARE(errorSignal.size(), 1); + QCOMPARE(playlist.error(), QMediaPlaylist::AccessDeniedError); + QVERIFY(!playlist.errorString().isEmpty()); + QCOMPARE(playlist.mediaCount(), 3); + + errorSignal.clear(); + playlist.load(QUrl(QLatin1String("tmp.m3u")), "m3u"); + + QCOMPARE(errorSignal.size(), 1); + QCOMPARE(playlist.error(), QMediaPlaylist::AccessDeniedError); + QVERIFY(!playlist.errorString().isEmpty()); + QCOMPARE(playlist.mediaCount(), 3); +} + +void tst_QMediaPlaylist::setMediaObject() +{ + MockReadOnlyPlaylistObject mediaObject; + + QMediaPlaylist playlist; + QVERIFY(playlist.mediaObject() == 0); + QVERIFY(!playlist.isReadOnly()); + + mediaObject.bind(&playlist); + QCOMPARE(playlist.mediaObject(), qobject_cast(&mediaObject)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(playlist.isReadOnly()); + + mediaObject.unbind(&playlist); + QVERIFY(playlist.mediaObject() == 0); + QCOMPARE(playlist.mediaCount(), 0); + QVERIFY(!playlist.isReadOnly()); + + mediaObject.bind(&playlist); + QCOMPARE(playlist.mediaObject(), qobject_cast(&mediaObject)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(playlist.isReadOnly()); +} + +QTEST_MAIN(tst_QMediaPlaylist) +#include "tst_qmediaplaylist.moc" + diff --git a/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro b/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro new file mode 100644 index 000000000..f5252c63b --- /dev/null +++ b/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediaplaylistnavigator +# CONFIG += testcase + +SOURCES += tst_qmediaplaylistnavigator.cpp + diff --git a/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp new file mode 100644 index 000000000..f6d19a950 --- /dev/null +++ b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include +#include "qlocalmediaplaylistprovider.h" +#include "qmediaplaylistnavigator.h" + +QT_USE_NAMESPACE +class tst_QMediaPlaylistNavigator : public QObject +{ + Q_OBJECT +public slots: + void init(); + void cleanup(); + +private slots: + void construction(); + void setPlaylist(); + void linearPlayback(); + void loopPlayback(); + void currentItemOnce(); + void currentItemInLoop(); + void randomPlayback(); +}; + +void tst_QMediaPlaylistNavigator::init() +{ +} + +void tst_QMediaPlaylistNavigator::cleanup() +{ +} + +void tst_QMediaPlaylistNavigator::construction() +{ + QLocalMediaPlaylistProvider playlist; + QCOMPARE(playlist.mediaCount(), 0); + + QMediaPlaylistNavigator navigator(&playlist); + QVERIFY(navigator.currentItem().isNull()); + QCOMPARE(navigator.currentIndex(), -1); +} + +void tst_QMediaPlaylistNavigator::setPlaylist() +{ + QMediaPlaylistNavigator navigator(0); + QVERIFY(navigator.playlist() != 0); + QCOMPARE(navigator.playlist()->mediaCount(), 0); + QCOMPARE(navigator.playlist()->media(0), QMediaContent()); + QVERIFY(navigator.playlist()->isReadOnly() ); + + QLocalMediaPlaylistProvider playlist; + QCOMPARE(playlist.mediaCount(), 0); + + navigator.setPlaylist(&playlist); + QCOMPARE(navigator.playlist(), (QMediaPlaylistProvider*)&playlist); + QCOMPARE(navigator.playlist()->mediaCount(), 0); + QVERIFY(!navigator.playlist()->isReadOnly() ); +} + +void tst_QMediaPlaylistNavigator::linearPlayback() +{ + QLocalMediaPlaylistProvider playlist; + QMediaPlaylistNavigator navigator(&playlist); + + navigator.setPlaybackMode(QMediaPlaylist::Sequential); + QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range "); + navigator.jump(0);//it's ok to have warning here + QVERIFY(navigator.currentItem().isNull()); + QCOMPARE(navigator.currentIndex(), -1); + + QMediaContent content1(QUrl(QLatin1String("file:///1"))); + playlist.addMedia(content1); + navigator.jump(0); + QVERIFY(!navigator.currentItem().isNull()); + + QCOMPARE(navigator.currentIndex(), 0); + QCOMPARE(navigator.currentItem(), content1); + QCOMPARE(navigator.nextItem(), QMediaContent()); + QCOMPARE(navigator.nextItem(2), QMediaContent()); + QCOMPARE(navigator.previousItem(), QMediaContent()); + QCOMPARE(navigator.previousItem(2), QMediaContent()); + + QMediaContent content2(QUrl(QLatin1String("file:///2"))); + playlist.addMedia(content2); + QCOMPARE(navigator.currentIndex(), 0); + QCOMPARE(navigator.currentItem(), content1); + QCOMPARE(navigator.nextItem(), content2); + QCOMPARE(navigator.nextItem(2), QMediaContent()); + QCOMPARE(navigator.previousItem(), QMediaContent()); + QCOMPARE(navigator.previousItem(2), QMediaContent()); + + navigator.jump(1); + QCOMPARE(navigator.currentIndex(), 1); + QCOMPARE(navigator.currentItem(), content2); + QCOMPARE(navigator.nextItem(), QMediaContent()); + QCOMPARE(navigator.nextItem(2), QMediaContent()); + QCOMPARE(navigator.previousItem(), content1); + QCOMPARE(navigator.previousItem(2), QMediaContent()); + + navigator.jump(0); + navigator.next(); + QCOMPARE(navigator.currentIndex(), 1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), -1); + navigator.next();//jump to the first item + QCOMPARE(navigator.currentIndex(), 0); + + navigator.previous(); + QCOMPARE(navigator.currentIndex(), -1); + navigator.previous();//jump to the last item + QCOMPARE(navigator.currentIndex(), 1); +} + +void tst_QMediaPlaylistNavigator::loopPlayback() +{ + QLocalMediaPlaylistProvider playlist; + QMediaPlaylistNavigator navigator(&playlist); + + navigator.setPlaybackMode(QMediaPlaylist::Loop); + QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range "); + navigator.jump(0); + QVERIFY(navigator.currentItem().isNull()); + QCOMPARE(navigator.currentIndex(), -1); + + QMediaContent content1(QUrl(QLatin1String("file:///1"))); + playlist.addMedia(content1); + navigator.jump(0); + QVERIFY(!navigator.currentItem().isNull()); + + QCOMPARE(navigator.currentIndex(), 0); + QCOMPARE(navigator.currentItem(), content1); + QCOMPARE(navigator.nextItem(), content1); + QCOMPARE(navigator.nextItem(2), content1); + QCOMPARE(navigator.previousItem(), content1); + QCOMPARE(navigator.previousItem(2), content1); + + QMediaContent content2(QUrl(QLatin1String("file:///2"))); + playlist.addMedia(content2); + QCOMPARE(navigator.currentIndex(), 0); + QCOMPARE(navigator.currentItem(), content1); + QCOMPARE(navigator.nextItem(), content2); + QCOMPARE(navigator.nextItem(2), content1); //loop over end of the list + QCOMPARE(navigator.previousItem(), content2); + QCOMPARE(navigator.previousItem(2), content1); + + navigator.jump(1); + QCOMPARE(navigator.currentIndex(), 1); + QCOMPARE(navigator.currentItem(), content2); + QCOMPARE(navigator.nextItem(), content1); + QCOMPARE(navigator.nextItem(2), content2); + QCOMPARE(navigator.previousItem(), content1); + QCOMPARE(navigator.previousItem(2), content2); + + navigator.jump(0); + navigator.next(); + QCOMPARE(navigator.currentIndex(), 1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), 0); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), 1); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), 0); +} + +void tst_QMediaPlaylistNavigator::currentItemOnce() +{ + QLocalMediaPlaylistProvider playlist; + QMediaPlaylistNavigator navigator(&playlist); + + navigator.setPlaybackMode(QMediaPlaylist::CurrentItemOnce); + + QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemOnce); + QCOMPARE(navigator.currentIndex(), -1); + + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///1")))); + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///2")))); + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///3")))); + + QCOMPARE(navigator.currentIndex(), -1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), -1); + + navigator.jump(1); + QCOMPARE(navigator.currentIndex(), 1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), -1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), -1); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), -1); + navigator.jump(1); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), -1); +} + +void tst_QMediaPlaylistNavigator::currentItemInLoop() +{ + QLocalMediaPlaylistProvider playlist; + QMediaPlaylistNavigator navigator(&playlist); + + navigator.setPlaybackMode(QMediaPlaylist::CurrentItemInLoop); + + QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemInLoop); + QCOMPARE(navigator.currentIndex(), -1); + + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///1")))); + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///2")))); + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///3")))); + + QCOMPARE(navigator.currentIndex(), -1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), -1); + navigator.jump(1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), 1); + navigator.next(); + QCOMPARE(navigator.currentIndex(), 1); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), 1); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), 1); +} + +void tst_QMediaPlaylistNavigator::randomPlayback() +{ + QLocalMediaPlaylistProvider playlist; + QMediaPlaylistNavigator navigator(&playlist); + + navigator.setPlaybackMode(QMediaPlaylist::Random); + + QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random); + QCOMPARE(navigator.currentIndex(), -1); + + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///1")))); + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///2")))); + playlist.addMedia(QMediaContent(QUrl(QLatin1String("file:///3")))); + + playlist.shuffle(); + + QCOMPARE(navigator.currentIndex(), -1); + navigator.next(); + int pos1 = navigator.currentIndex(); + navigator.next(); + int pos2 = navigator.currentIndex(); + navigator.next(); + int pos3 = navigator.currentIndex(); + + QVERIFY(pos1 != -1); + QVERIFY(pos2 != -1); + QVERIFY(pos3 != -1); + + navigator.previous(); + QCOMPARE(navigator.currentIndex(), pos2); + navigator.next(); + QCOMPARE(navigator.currentIndex(), pos3); + navigator.next(); + int pos4 = navigator.currentIndex(); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), pos3); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), pos2); + navigator.previous(); + QCOMPARE(navigator.currentIndex(), pos1); + navigator.previous(); + int pos0 = navigator.currentIndex(); + QVERIFY(pos0 != -1); + navigator.next(); + navigator.next(); + navigator.next(); + navigator.next(); + QCOMPARE(navigator.currentIndex(), pos4); + +} + +QTEST_MAIN(tst_QMediaPlaylistNavigator) +#include "tst_qmediaplaylistnavigator.moc" diff --git a/tests/auto/qmediapluginloader/qmediapluginloader.pro b/tests/auto/qmediapluginloader/qmediapluginloader.pro new file mode 100644 index 000000000..55f134495 --- /dev/null +++ b/tests/auto/qmediapluginloader/qmediapluginloader.pro @@ -0,0 +1,15 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediapluginloader +# CONFIG += testcase + +SOURCES += tst_qmediapluginloader.cpp + +wince* { + PLUGIN_DEPLOY.sources = $$OUTPUT_DIR/plugins/mediaservice/*.dll + PLUGIN_DEPLOY.path = mediaservice + DEPLOYMENT += PLUGIN_DEPLOY +} + diff --git a/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp new file mode 100644 index 000000000..5d6bb7c8c --- /dev/null +++ b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include +#include + +QT_USE_NAMESPACE + +class tst_QMediaPluginLoader : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testInstance(); + void testInstances(); + void testInvalidKey(); + +private: + QMediaPluginLoader *loader; +}; + +void tst_QMediaPluginLoader::initTestCase() +{ + loader = new QMediaPluginLoader(QMediaServiceProviderFactoryInterface_iid, + QLatin1String("/mediaservice"), + Qt::CaseInsensitive); +} + +void tst_QMediaPluginLoader::cleanupTestCase() +{ + delete loader; +} + +void tst_QMediaPluginLoader::testInstance() +{ + const QStringList keys = loader->keys(); + + if (keys.isEmpty()) // Test is invalidated, skip. + QSKIP("No plug-ins available", SkipAll); + + foreach (const QString &key, keys) + QVERIFY(loader->instance(key) != 0); +} + +void tst_QMediaPluginLoader::testInstances() +{ + const QStringList keys = loader->keys(); + + if (keys.isEmpty()) // Test is invalidated, skip. + QSKIP("No plug-ins available", SkipAll); + + foreach (const QString &key, keys) + QVERIFY(loader->instances(key).size() > 0); +} + +// Last so as to not interfere with the other tests if there is a failure. +void tst_QMediaPluginLoader::testInvalidKey() +{ + const QString key(QLatin1String("invalid-key")); + + // This test assumes there is no 'invalid-key' in the key list, verify that. + if (loader->keys().contains(key)) + QSKIP("a plug-in includes the invalid key", SkipAll); + + QVERIFY(loader->instance(key) == 0); + + // Test looking up the key hasn't inserted it into the list. See QMap::operator[]. + QVERIFY(!loader->keys().contains(key)); + + QVERIFY(loader->instances(key).isEmpty()); + QVERIFY(!loader->keys().contains(key)); +} + +QTEST_MAIN(tst_QMediaPluginLoader) + +#include "tst_qmediapluginloader.moc" diff --git a/tests/auto/qmediarecorder/main.cpp b/tests/auto/qmediarecorder/main.cpp new file mode 100755 index 000000000..816a55ea7 --- /dev/null +++ b/tests/auto/qmediarecorder/main.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#include +#include + +#include "tst_qmediarecorder.h" + +#ifdef Q_OS_SYMBIAN +#include "s60common.h" +#include "tst_qmediarecorder_xa.h" +#include "tst_qmediarecorder_mmf.h" +#endif + +int main(int argc, char**argv) +{ + QApplication app(argc,argv); + int ret; + tst_QMediaRecorder test_api; + ret = QTest::qExec(&test_api, argc, argv); +#ifdef Q_OS_SYMBIAN + char *new_argv[3]; + QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + ".log"; + QByteArray bytes = str.toAscii(); + char arg1[] = "-o"; + new_argv[0] = argv[0]; + new_argv[1] = arg1; + new_argv[2] = bytes.data(); + tst_QMediaRecorder_xa test_xa; + ret = QTest::qExec(&test_xa, 3, new_argv); + char *new_argv1[3]; + QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log"; + QByteArray bytes1 = str1.toAscii(); + char arg2[] = "-o"; + new_argv1[0] = argv[0]; + new_argv1[1] = arg2; + new_argv1[2] = bytes1.data(); + tst_QMediaRecorder_mmf test_mmf; + ret = QTest::qExec(&test_mmf, 3, new_argv1); + +#endif + return ret; +} diff --git a/tests/auto/qmediarecorder/qmediarecorder.pro b/tests/auto/qmediarecorder/qmediarecorder.pro new file mode 100644 index 000000000..41e708fe7 --- /dev/null +++ b/tests/auto/qmediarecorder/qmediarecorder.pro @@ -0,0 +1,18 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediarecorder +# CONFIG += testcase + +symbian { + HEADERS += s60common.h + HEADERS += tst_qmediarecorder_xa.h + SOURCES += tst_qmediarecorder_xa.cpp + HEADERS += tst_qmediarecorder_mmf.h + SOURCES += tst_qmediarecorder_mmf.cpp + TARGET.CAPABILITY = UserEnvironment ReadDeviceData WriteDeviceData AllFiles +} +HEADERS += tst_qmediarecorder.h +SOURCES += main.cpp tst_qmediarecorder.cpp + diff --git a/tests/auto/qmediarecorder/s60common.h b/tests/auto/qmediarecorder/s60common.h new file mode 100755 index 000000000..4e55004f8 --- /dev/null +++ b/tests/auto/qmediarecorder/s60common.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#ifndef S60COMMON_H +#define S60COMMON_H + +QT_USE_NAMESPACE + +#define QTRY_COMPARE(a,e) \ + for (int _i = 0; _i < 5000; _i += 100) { \ + if ((a) == (e)) break; \ + QTest::qWait(100); \ + } \ + QCOMPARE(a, e) + +#define QTRY_VERIFY(a) \ + for (int _i = 0; _i < 5000; _i += 100) { \ + if (a) break; \ + QTest::qWait(100); \ + } \ + QVERIFY(a) + +#endif //S60COMMON_H diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder.cpp b/tests/auto/qmediarecorder/tst_qmediarecorder.cpp new file mode 100644 index 000000000..b006efb4a --- /dev/null +++ b/tests/auto/qmediarecorder/tst_qmediarecorder.cpp @@ -0,0 +1,796 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include "tst_qmediarecorder.h" + +QT_USE_NAMESPACE + +void tst_QMediaRecorder::initTestCase() +{ + qRegisterMetaType("QMediaRecorder::State"); + qRegisterMetaType("QMediaRecorder::Error"); + + mock = new MockProvider(this); + service = new MockService(this, mock); + object = new MockObject(this, service); + capture = new QMediaRecorder(object); + + audio = qobject_cast(service->requestControl(QAudioEndpointSelector_iid)); + encode = qobject_cast(service->requestControl(QAudioEncoderControl_iid)); + videoEncode = qobject_cast(service->requestControl(QVideoEncoderControl_iid)); +} + +void tst_QMediaRecorder::cleanupTestCase() +{ + delete capture; + delete object; + delete service; + delete mock; +} + +void tst_QMediaRecorder::testNullService() +{ + const QString id(QLatin1String("application/x-format")); + + MockObject object(0, 0); + QMediaRecorder recorder(&object); + + QCOMPARE(recorder.outputLocation(), QUrl()); + QCOMPARE(recorder.state(), QMediaRecorder::StoppedState); + QCOMPARE(recorder.error(), QMediaRecorder::NoError); + QCOMPARE(recorder.duration(), qint64(0)); + QCOMPARE(recorder.supportedContainers(), QStringList()); + QCOMPARE(recorder.containerDescription(id), QString()); + QCOMPARE(recorder.supportedAudioCodecs(), QStringList()); + QCOMPARE(recorder.audioCodecDescription(id), QString()); + QCOMPARE(recorder.supportedAudioSampleRates(), QList()); + QCOMPARE(recorder.supportedVideoCodecs(), QStringList()); + QCOMPARE(recorder.videoCodecDescription(id), QString()); + bool continuous = true; + QCOMPARE(recorder.supportedResolutions(QVideoEncoderSettings(), &continuous), QList()); + QCOMPARE(continuous, false); + continuous = true; + QCOMPARE(recorder.supportedFrameRates(QVideoEncoderSettings(), &continuous), QList()); + QCOMPARE(continuous, false); + QCOMPARE(recorder.audioSettings(), QAudioEncoderSettings()); + QCOMPARE(recorder.videoSettings(), QVideoEncoderSettings()); + QCOMPARE(recorder.containerMimeType(), QString()); + QVERIFY(!recorder.isMuted()); + recorder.setMuted(true); + QVERIFY(!recorder.isMuted()); +} + +void tst_QMediaRecorder::testNullControls() +{ + const QString id(QLatin1String("application/x-format")); + + MockService service(0, 0); + service.hasControls = false; + MockObject object(0, &service); + QMediaRecorder recorder(&object); + + QCOMPARE(recorder.outputLocation(), QUrl()); + QCOMPARE(recorder.state(), QMediaRecorder::StoppedState); + QCOMPARE(recorder.error(), QMediaRecorder::NoError); + QCOMPARE(recorder.duration(), qint64(0)); + QCOMPARE(recorder.supportedContainers(), QStringList()); + QCOMPARE(recorder.containerDescription(id), QString()); + QCOMPARE(recorder.supportedAudioCodecs(), QStringList()); + QCOMPARE(recorder.audioCodecDescription(id), QString()); + QCOMPARE(recorder.supportedAudioSampleRates(), QList()); + QCOMPARE(recorder.supportedVideoCodecs(), QStringList()); + QCOMPARE(recorder.videoCodecDescription(id), QString()); + bool continuous = true; + QCOMPARE(recorder.supportedResolutions(QVideoEncoderSettings(), &continuous), QList()); + QCOMPARE(continuous, false); + continuous = true; + QCOMPARE(recorder.supportedFrameRates(QVideoEncoderSettings(), &continuous), QList()); + QCOMPARE(continuous, false); + QCOMPARE(recorder.audioSettings(), QAudioEncoderSettings()); + QCOMPARE(recorder.videoSettings(), QVideoEncoderSettings()); + QCOMPARE(recorder.containerMimeType(), QString()); + + recorder.setOutputLocation(QUrl("file://test/save/file.mp4")); + QCOMPARE(recorder.outputLocation(), QUrl()); + + QAudioEncoderSettings audio; + audio.setCodec(id); + audio.setQuality(QtMultimediaKit::LowQuality); + + QVideoEncoderSettings video; + video.setCodec(id); + video.setResolution(640, 480); + + recorder.setEncodingSettings(audio, video, id); + + QCOMPARE(recorder.audioSettings(), QAudioEncoderSettings()); + QCOMPARE(recorder.videoSettings(), QVideoEncoderSettings()); + QCOMPARE(recorder.containerMimeType(), QString()); + + QSignalSpy spy(&recorder, SIGNAL(stateChanged(QMediaRecorder::State))); + + recorder.record(); + QCOMPARE(recorder.state(), QMediaRecorder::StoppedState); + QCOMPARE(recorder.error(), QMediaRecorder::NoError); + QCOMPARE(spy.count(), 0); + + recorder.pause(); + QCOMPARE(recorder.state(), QMediaRecorder::StoppedState); + QCOMPARE(recorder.error(), QMediaRecorder::NoError); + QCOMPARE(spy.count(), 0); + + recorder.stop(); + QCOMPARE(recorder.state(), QMediaRecorder::StoppedState); + QCOMPARE(recorder.error(), QMediaRecorder::NoError); + QCOMPARE(spy.count(), 0); +} + +void tst_QMediaRecorder::testError() +{ + const QString errorString(QLatin1String("format error")); + + QSignalSpy spy(capture, SIGNAL(error(QMediaRecorder::Error))); + + QCOMPARE(capture->error(), QMediaRecorder::NoError); + QCOMPARE(capture->errorString(), QString()); + + mock->error(QMediaRecorder::FormatError, errorString); + QCOMPARE(capture->error(), QMediaRecorder::FormatError); + QCOMPARE(capture->errorString(), errorString); + QCOMPARE(spy.count(), 1); + + QCOMPARE(spy.last()[0].value(), QMediaRecorder::FormatError); +} + +void tst_QMediaRecorder::testSink() +{ + capture->setOutputLocation(QUrl("test.tmp")); + QUrl s = capture->outputLocation(); + QCOMPARE(s.toString(), QString("test.tmp")); +} + +void tst_QMediaRecorder::testRecord() +{ + QSignalSpy stateSignal(capture,SIGNAL(stateChanged(QMediaRecorder::State))); + QSignalSpy progressSignal(capture, SIGNAL(durationChanged(qint64))); + capture->record(); + QCOMPARE(capture->state(), QMediaRecorder::RecordingState); + QCOMPARE(capture->error(), QMediaRecorder::NoError); + QCOMPARE(capture->errorString(), QString()); + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(stateSignal.count(), 1); + QCOMPARE(stateSignal.last()[0].value(), QMediaRecorder::RecordingState); + QVERIFY(progressSignal.count() > 0); + capture->pause(); + QCOMPARE(capture->state(), QMediaRecorder::PausedState); + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(stateSignal.count(), 2); + capture->stop(); + QCOMPARE(capture->state(), QMediaRecorder::StoppedState); + QTestEventLoop::instance().enterLoop(1); + QCOMPARE(stateSignal.count(), 3); + mock->stop(); + QCOMPARE(stateSignal.count(), 3); + +} + +void tst_QMediaRecorder::testMute() +{ + QSignalSpy mutedChanged(capture, SIGNAL(mutedChanged(bool))); + QVERIFY(!capture->isMuted()); + capture->setMuted(true); + + QCOMPARE(mutedChanged.size(), 1); + QCOMPARE(mutedChanged[0][0].toBool(), true); + QVERIFY(capture->isMuted()); + + capture->setMuted(false); + + QCOMPARE(mutedChanged.size(), 2); + QCOMPARE(mutedChanged[1][0].toBool(), false); + QVERIFY(!capture->isMuted()); + + capture->setMuted(false); + QCOMPARE(mutedChanged.size(), 2); +} + +void tst_QMediaRecorder::testAudioDeviceControl() +{ + QSignalSpy readSignal(audio,SIGNAL(activeEndpointChanged(QString))); + QVERIFY(audio->availableEndpoints().size() == 3); + QVERIFY(audio->defaultEndpoint().compare("device1") == 0); + audio->setActiveEndpoint("device2"); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(audio->activeEndpoint().compare("device2") == 0); + QVERIFY(readSignal.count() == 1); + QVERIFY(audio->endpointDescription("device2").compare("dev2 comment") == 0); +} + +void tst_QMediaRecorder::testAudioEncodeControl() +{ + QStringList codecs = capture->supportedAudioCodecs(); + QVERIFY(codecs.count() == 2); + QVERIFY(capture->audioCodecDescription("audio/pcm") == "Pulse Code Modulation"); + QStringList options = encode->supportedEncodingOptions("audio/mpeg"); + QCOMPARE(options.count(), 4); + QVERIFY(encode->encodingOption("audio/mpeg","bitrate").isNull()); + encode->setEncodingOption("audio/mpeg", "bitrate", QString("vbr")); + QCOMPARE(encode->encodingOption("audio/mpeg","bitrate").toString(), QString("vbr")); + QCOMPARE(capture->supportedAudioSampleRates(), QList() << 44100); +} + +void tst_QMediaRecorder::testMediaFormatsControl() +{ + QCOMPARE(capture->supportedContainers(), QStringList() << "wav" << "mp3" << "mov"); + + QCOMPARE(capture->containerDescription("wav"), QString("WAV format")); + QCOMPARE(capture->containerDescription("mp3"), QString("MP3 format")); + QCOMPARE(capture->containerDescription("ogg"), QString()); +} + +void tst_QMediaRecorder::testVideoEncodeControl() +{ + bool continuous = false; + QList sizes = capture->supportedResolutions(QVideoEncoderSettings(), &continuous); + QCOMPARE(sizes.count(), 2); + QCOMPARE(continuous, true); + + QList rates = capture->supportedFrameRates(QVideoEncoderSettings(), &continuous); + QCOMPARE(rates.count(), 3); + QCOMPARE(continuous, false); + + QStringList vCodecs = capture->supportedVideoCodecs(); + QVERIFY(vCodecs.count() == 2); + QCOMPARE(capture->videoCodecDescription("video/3gpp"), QString("video/3gpp")); + + QStringList options = videoEncode->supportedEncodingOptions("video/3gpp"); + QCOMPARE(options.count(), 2); + + QVERIFY(encode->encodingOption("video/3gpp","me").isNull()); + encode->setEncodingOption("video/3gpp", "me", QString("dia")); + QCOMPARE(encode->encodingOption("video/3gpp","me").toString(), QString("dia")); + +} + +void tst_QMediaRecorder::testEncodingSettings() +{ + QAudioEncoderSettings audioSettings = capture->audioSettings(); + QCOMPARE(audioSettings.codec(), QString("audio/pcm")); + QCOMPARE(audioSettings.bitRate(), 128*1024); + QCOMPARE(audioSettings.sampleRate(), -1); + QCOMPARE(audioSettings.quality(), QtMultimediaKit::NormalQuality); + QCOMPARE(audioSettings.channelCount(), -1); + + QCOMPARE(audioSettings.encodingMode(), QtMultimediaKit::ConstantQualityEncoding); + + QVideoEncoderSettings videoSettings = capture->videoSettings(); + QCOMPARE(videoSettings.codec(), QString()); + QCOMPARE(videoSettings.bitRate(), -1); + QCOMPARE(videoSettings.resolution(), QSize()); + QCOMPARE(videoSettings.frameRate(), 0.0); + QCOMPARE(videoSettings.quality(), QtMultimediaKit::NormalQuality); + QCOMPARE(videoSettings.encodingMode(), QtMultimediaKit::ConstantQualityEncoding); + + QString format = capture->containerMimeType(); + QCOMPARE(format, QString()); + + audioSettings.setCodec("audio/mpeg"); + audioSettings.setSampleRate(44100); + audioSettings.setBitRate(256*1024); + audioSettings.setQuality(QtMultimediaKit::HighQuality); + audioSettings.setEncodingMode(QtMultimediaKit::AverageBitRateEncoding); + + videoSettings.setCodec("video/3gpp"); + videoSettings.setBitRate(800); + videoSettings.setFrameRate(24*1024); + videoSettings.setResolution(QSize(800,600)); + videoSettings.setQuality(QtMultimediaKit::HighQuality); + audioSettings.setEncodingMode(QtMultimediaKit::TwoPassEncoding); + + format = QString("mov"); + + capture->setEncodingSettings(audioSettings,videoSettings,format); + + QCOMPARE(capture->audioSettings(), audioSettings); + QCOMPARE(capture->videoSettings(), videoSettings); + QCOMPARE(capture->containerMimeType(), format); +} + +void tst_QMediaRecorder::testAudioSettings() +{ + QAudioEncoderSettings settings; + QVERIFY(settings.isNull()); + QVERIFY(settings == QAudioEncoderSettings()); + + QCOMPARE(settings.codec(), QString()); + settings.setCodec(QLatin1String("codecName")); + QCOMPARE(settings.codec(), QLatin1String("codecName")); + QVERIFY(!settings.isNull()); + QVERIFY(settings != QAudioEncoderSettings()); + + settings = QAudioEncoderSettings(); + QCOMPARE(settings.bitRate(), -1); + settings.setBitRate(128000); + QCOMPARE(settings.bitRate(), 128000); + QVERIFY(!settings.isNull()); + + settings = QAudioEncoderSettings(); + QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality); + settings.setQuality(QtMultimediaKit::HighQuality); + QCOMPARE(settings.quality(), QtMultimediaKit::HighQuality); + QVERIFY(!settings.isNull()); + + settings = QAudioEncoderSettings(); + QCOMPARE(settings.sampleRate(), -1); + settings.setSampleRate(44100); + QCOMPARE(settings.sampleRate(), 44100); + QVERIFY(!settings.isNull()); + + settings = QAudioEncoderSettings(); + QCOMPARE(settings.channelCount(), -1); + settings.setChannelCount(2); + QCOMPARE(settings.channelCount(), 2); + QVERIFY(!settings.isNull()); + + settings = QAudioEncoderSettings(); + QVERIFY(settings.isNull()); + QCOMPARE(settings.codec(), QString()); + QCOMPARE(settings.bitRate(), -1); + QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality); + QCOMPARE(settings.sampleRate(), -1); + + { + QAudioEncoderSettings settings1; + QAudioEncoderSettings settings2; + QCOMPARE(settings2, settings1); + + settings2 = settings1; + QCOMPARE(settings2, settings1); + QVERIFY(settings2.isNull()); + + settings1.setQuality(QtMultimediaKit::HighQuality); + + QVERIFY(settings2.isNull()); + QVERIFY(!settings1.isNull()); + QVERIFY(settings1 != settings2); + } + + { + QAudioEncoderSettings settings1; + QAudioEncoderSettings settings2(settings1); + QCOMPARE(settings2, settings1); + + settings2 = settings1; + QCOMPARE(settings2, settings1); + QVERIFY(settings2.isNull()); + + settings1.setQuality(QtMultimediaKit::HighQuality); + + QVERIFY(settings2.isNull()); + QVERIFY(!settings1.isNull()); + QVERIFY(settings1 != settings2); + } + + QAudioEncoderSettings settings1; + settings1.setBitRate(1); + QAudioEncoderSettings settings2; + settings2.setBitRate(1); + QVERIFY(settings1 == settings2); + settings2.setBitRate(2); + QVERIFY(settings1 != settings2); + + settings1 = QAudioEncoderSettings(); + settings1.setChannelCount(1); + settings2 = QAudioEncoderSettings(); + settings2.setChannelCount(1); + QVERIFY(settings1 == settings2); + settings2.setChannelCount(2); + QVERIFY(settings1 != settings2); + + settings1 = QAudioEncoderSettings(); + settings1.setCodec("codec1"); + settings2 = QAudioEncoderSettings(); + settings2.setCodec("codec1"); + QVERIFY(settings1 == settings2); + settings2.setCodec("codec2"); + QVERIFY(settings1 != settings2); + + settings1 = QAudioEncoderSettings(); + settings1.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding); + settings2 = QAudioEncoderSettings(); + settings2.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding); + QVERIFY(settings1 == settings2); + settings2.setEncodingMode(QtMultimediaKit::TwoPassEncoding); + QVERIFY(settings1 != settings2); + + settings1 = QAudioEncoderSettings(); + settings1.setQuality(QtMultimediaKit::NormalQuality); + settings2 = QAudioEncoderSettings(); + settings2.setQuality(QtMultimediaKit::NormalQuality); + QVERIFY(settings1 == settings2); + settings2.setQuality(QtMultimediaKit::LowQuality); + QVERIFY(settings1 != settings2); + + settings1 = QAudioEncoderSettings(); + settings1.setSampleRate(1); + settings2 = QAudioEncoderSettings(); + settings2.setSampleRate(1); + QVERIFY(settings1 == settings2); + settings2.setSampleRate(2); + QVERIFY(settings1 != settings2); +} + +void tst_QMediaRecorder::testVideoSettings() +{ + QVideoEncoderSettings settings; + QVERIFY(settings.isNull()); + QVERIFY(settings == QVideoEncoderSettings()); + + QCOMPARE(settings.codec(), QString()); + settings.setCodec(QLatin1String("codecName")); + QCOMPARE(settings.codec(), QLatin1String("codecName")); + QVERIFY(!settings.isNull()); + QVERIFY(settings != QVideoEncoderSettings()); + + settings = QVideoEncoderSettings(); + QCOMPARE(settings.bitRate(), -1); + settings.setBitRate(128000); + QCOMPARE(settings.bitRate(), 128000); + QVERIFY(!settings.isNull()); + + settings = QVideoEncoderSettings(); + QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality); + settings.setQuality(QtMultimediaKit::HighQuality); + QCOMPARE(settings.quality(), QtMultimediaKit::HighQuality); + QVERIFY(!settings.isNull()); + + settings = QVideoEncoderSettings(); + QCOMPARE(settings.frameRate(), qreal()); + settings.setFrameRate(30000.0/10001); + QVERIFY(qFuzzyCompare(settings.frameRate(), qreal(30000.0/10001))); + settings.setFrameRate(24.0); + QVERIFY(qFuzzyCompare(settings.frameRate(), qreal(24.0))); + QVERIFY(!settings.isNull()); + + settings = QVideoEncoderSettings(); + QCOMPARE(settings.resolution(), QSize()); + settings.setResolution(QSize(320,240)); + QCOMPARE(settings.resolution(), QSize(320,240)); + settings.setResolution(800,600); + QCOMPARE(settings.resolution(), QSize(800,600)); + QVERIFY(!settings.isNull()); + + settings = QVideoEncoderSettings(); + QVERIFY(settings.isNull()); + QCOMPARE(settings.codec(), QString()); + QCOMPARE(settings.bitRate(), -1); + QCOMPARE(settings.quality(), QtMultimediaKit::NormalQuality); + QCOMPARE(settings.frameRate(), qreal()); + QCOMPARE(settings.resolution(), QSize()); + + { + QVideoEncoderSettings settings1; + QVideoEncoderSettings settings2; + QCOMPARE(settings2, settings1); + + settings2 = settings1; + QCOMPARE(settings2, settings1); + QVERIFY(settings2.isNull()); + + settings1.setQuality(QtMultimediaKit::HighQuality); + + QVERIFY(settings2.isNull()); + QVERIFY(!settings1.isNull()); + QVERIFY(settings1 != settings2); + } + + { + QVideoEncoderSettings settings1; + QVideoEncoderSettings settings2(settings1); + QCOMPARE(settings2, settings1); + + settings2 = settings1; + QCOMPARE(settings2, settings1); + QVERIFY(settings2.isNull()); + + settings1.setQuality(QtMultimediaKit::HighQuality); + + QVERIFY(settings2.isNull()); + QVERIFY(!settings1.isNull()); + QVERIFY(settings1 != settings2); + } + + QVideoEncoderSettings settings1; + settings1.setBitRate(1); + QVideoEncoderSettings settings2; + settings2.setBitRate(1); + QVERIFY(settings1 == settings2); + settings2.setBitRate(2); + QVERIFY(settings1 != settings2); + + settings1 = QVideoEncoderSettings(); + settings1.setResolution(800,600); + settings2 = QVideoEncoderSettings(); + settings2.setResolution(QSize(800,600)); + QVERIFY(settings1 == settings2); + settings2.setResolution(QSize(400,300)); + QVERIFY(settings1 != settings2); + + settings1 = QVideoEncoderSettings(); + settings1.setCodec("codec1"); + settings2 = QVideoEncoderSettings(); + settings2.setCodec("codec1"); + QVERIFY(settings1 == settings2); + settings2.setCodec("codec2"); + QVERIFY(settings1 != settings2); + + settings1 = QVideoEncoderSettings(); + settings1.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding); + settings2 = QVideoEncoderSettings(); + settings2.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding); + QVERIFY(settings1 == settings2); + settings2.setEncodingMode(QtMultimediaKit::TwoPassEncoding); + QVERIFY(settings1 != settings2); + + settings1 = QVideoEncoderSettings(); + settings1.setQuality(QtMultimediaKit::NormalQuality); + settings2 = QVideoEncoderSettings(); + settings2.setQuality(QtMultimediaKit::NormalQuality); + QVERIFY(settings1 == settings2); + settings2.setQuality(QtMultimediaKit::LowQuality); + QVERIFY(settings1 != settings2); + + settings1 = QVideoEncoderSettings(); + settings1.setFrameRate(1); + settings2 = QVideoEncoderSettings(); + settings2.setFrameRate(1); + QVERIFY(settings1 == settings2); + settings2.setFrameRate(2); + QVERIFY(settings1 != settings2); +} + + +void tst_QMediaRecorder::nullMetaDataControl() +{ + const QString titleKey(QLatin1String("Title")); + const QString title(QLatin1String("Host of Seraphim")); + + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + service.hasControls = false; + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + + QSignalSpy spy(&recorder, SIGNAL(metaDataChanged())); + + QCOMPARE(recorder.isMetaDataAvailable(), false); + QCOMPARE(recorder.isMetaDataWritable(), false); + + recorder.setMetaData(QtMultimediaKit::Title, title); + recorder.setExtendedMetaData(titleKey, title); + + QCOMPARE(recorder.metaData(QtMultimediaKit::Title).toString(), QString()); + QCOMPARE(recorder.extendedMetaData(titleKey).toString(), QString()); + QCOMPARE(recorder.availableMetaData(), QList()); + QCOMPARE(recorder.availableExtendedMetaData(), QStringList()); + QCOMPARE(spy.count(), 0); +} + +void tst_QMediaRecorder::isMetaDataAvailable() +{ + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + service.mockMetaDataControl->setMetaDataAvailable(false); + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + QCOMPARE(recorder.isMetaDataAvailable(), false); + + QSignalSpy spy(&recorder, SIGNAL(metaDataAvailableChanged(bool))); + service.mockMetaDataControl->setMetaDataAvailable(true); + + QCOMPARE(recorder.isMetaDataAvailable(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toBool(), true); + + service.mockMetaDataControl->setMetaDataAvailable(false); + + QCOMPARE(recorder.isMetaDataAvailable(), false); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.at(1).at(0).toBool(), false); +} + +void tst_QMediaRecorder::isWritable() +{ + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + service.mockMetaDataControl->setWritable(false); + + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + + QSignalSpy spy(&recorder, SIGNAL(metaDataWritableChanged(bool))); + + QCOMPARE(recorder.isMetaDataWritable(), false); + + service.mockMetaDataControl->setWritable(true); + + QCOMPARE(recorder.isMetaDataWritable(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toBool(), true); + + service.mockMetaDataControl->setWritable(false); + + QCOMPARE(recorder.isMetaDataWritable(), false); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.at(1).at(0).toBool(), false); +} + +void tst_QMediaRecorder::metaDataChanged() +{ + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + + QSignalSpy spy(&recorder, SIGNAL(metaDataChanged())); + + service.mockMetaDataControl->metaDataChanged(); + QCOMPARE(spy.count(), 1); + + service.mockMetaDataControl->metaDataChanged(); + QCOMPARE(spy.count(), 2); +} + +void tst_QMediaRecorder::metaData_data() +{ + QTest::addColumn("artist"); + QTest::addColumn("title"); + QTest::addColumn("genre"); + + QTest::newRow("") + << QString::fromLatin1("Dead Can Dance") + << QString::fromLatin1("Host of Seraphim") + << QString::fromLatin1("Awesome"); +} + +void tst_QMediaRecorder::metaData() +{ + QFETCH(QString, artist); + QFETCH(QString, title); + QFETCH(QString, genre); + + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + service.mockMetaDataControl->populateMetaData(); + + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + QVERIFY(object.availableMetaData().isEmpty()); + + service.mockMetaDataControl->m_data.insert(QtMultimediaKit::AlbumArtist, artist); + service.mockMetaDataControl->m_data.insert(QtMultimediaKit::Title, title); + service.mockMetaDataControl->m_data.insert(QtMultimediaKit::Genre, genre); + + QCOMPARE(recorder.metaData(QtMultimediaKit::AlbumArtist).toString(), artist); + QCOMPARE(recorder.metaData(QtMultimediaKit::Title).toString(), title); + + QList metaDataKeys = recorder.availableMetaData(); + QCOMPARE(metaDataKeys.size(), 3); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::AlbumArtist)); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::Title)); + QVERIFY(metaDataKeys.contains(QtMultimediaKit::Genre)); +} + +void tst_QMediaRecorder::setMetaData_data() +{ + QTest::addColumn("title"); + + QTest::newRow("") + << QString::fromLatin1("In the Kingdom of the Blind the One eyed are Kings"); +} + +void tst_QMediaRecorder::setMetaData() +{ + QFETCH(QString, title); + + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + service.mockMetaDataControl->populateMetaData(); + + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + + recorder.setMetaData(QtMultimediaKit::Title, title); + QCOMPARE(recorder.metaData(QtMultimediaKit::Title).toString(), title); + QCOMPARE(service.mockMetaDataControl->m_data.value(QtMultimediaKit::Title).toString(), title); +} + +void tst_QMediaRecorder::extendedMetaData() +{ + QFETCH(QString, artist); + QFETCH(QString, title); + QFETCH(QString, genre); + + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + QVERIFY(recorder.availableExtendedMetaData().isEmpty()); + + service.mockMetaDataControl->m_extendedData.insert(QLatin1String("Artist"), artist); + service.mockMetaDataControl->m_extendedData.insert(QLatin1String("Title"), title); + service.mockMetaDataControl->m_extendedData.insert(QLatin1String("Genre"), genre); + + QCOMPARE(recorder.extendedMetaData(QLatin1String("Artist")).toString(), artist); + QCOMPARE(recorder.extendedMetaData(QLatin1String("Title")).toString(), title); + + QStringList extendedKeys = recorder.availableExtendedMetaData(); + QCOMPARE(extendedKeys.size(), 3); + QVERIFY(extendedKeys.contains(QLatin1String("Artist"))); + QVERIFY(extendedKeys.contains(QLatin1String("Title"))); + QVERIFY(extendedKeys.contains(QLatin1String("Genre"))); +} + +void tst_QMediaRecorder::setExtendedMetaData() +{ + MockProvider recorderControl(0); + MockService service(0, &recorderControl); + service.mockMetaDataControl->populateMetaData(); + + MockObject object(0, &service); + + QMediaRecorder recorder(&object); + + QString title(QLatin1String("In the Kingdom of the Blind the One eyed are Kings")); + + recorder.setExtendedMetaData(QLatin1String("Title"), title); + QCOMPARE(recorder.extendedMetaData(QLatin1String("Title")).toString(), title); + QCOMPARE(service.mockMetaDataControl->m_extendedData.value(QLatin1String("Title")).toString(), title); +} diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder.h b/tests/auto/qmediarecorder/tst_qmediarecorder.h new file mode 100755 index 000000000..4ac7bfbab --- /dev/null +++ b/tests/auto/qmediarecorder/tst_qmediarecorder.h @@ -0,0 +1,516 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QMEDIARECORDER_H +#define TST_QMEDIARECORDER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_USE_NAMESPACE +class MockMediaContainerControl : public QMediaContainerControl +{ + Q_OBJECT +public: + MockMediaContainerControl(QObject *parent): + QMediaContainerControl(parent) + { + m_supportedContainers.append("wav"); + m_supportedContainers.append("mp3"); + m_supportedContainers.append("mov"); + + m_descriptions.insert("wav", "WAV format"); + m_descriptions.insert("mp3", "MP3 format"); + m_descriptions.insert("mov", "MOV format"); + } + + virtual ~MockMediaContainerControl() {}; + + QStringList supportedContainers() const + { + return m_supportedContainers; + } + + QString containerMimeType() const + { + return m_format; + } + + void setContainerMimeType(const QString &formatMimeType) + { + if (m_supportedContainers.contains(formatMimeType)) + m_format = formatMimeType; + } + + QString containerDescription(const QString &formatMimeType) const + { + return m_descriptions.value(formatMimeType); + } + +private: + QStringList m_supportedContainers; + QMap m_descriptions; + QString m_format; +}; + +class MockVideoEncodeProvider : public QVideoEncoderControl +{ + Q_OBJECT +public: + MockVideoEncodeProvider(QObject *parent): + QVideoEncoderControl(parent) + { + m_supportedEncodeOptions.insert("video/3gpp", QStringList() << "quantizer" << "me"); + m_supportedEncodeOptions.insert("video/H264", QStringList() << "quantizer" << "me" << "bframes"); + m_videoCodecs << "video/3gpp" << "video/H264"; + m_sizes << QSize(320,240) << QSize(640,480); + m_framerates << 30 << 15 << 1; + } + ~MockVideoEncodeProvider() {} + + QVideoEncoderSettings videoSettings() const { return m_videoSettings; } + void setVideoSettings(const QVideoEncoderSettings &settings) { m_videoSettings = settings; }; + + QList supportedResolutions(const QVideoEncoderSettings & = QVideoEncoderSettings(), + bool *continuous = 0) const + { + if (continuous) + *continuous = true; + + return m_sizes; + } + + QList supportedFrameRates(const QVideoEncoderSettings & = QVideoEncoderSettings(), + bool *continuous = 0) const + { + if (continuous) + *continuous = false; + + return m_framerates; + } + + QStringList supportedVideoCodecs() const { return m_videoCodecs; } + QString videoCodecDescription(const QString &codecName) const { return codecName; } + + QStringList supportedEncodingOptions(const QString &codec) const + { + return m_supportedEncodeOptions.value(codec); + } + + QVariant encodingOption(const QString &codec, const QString &name) const + { + return m_encodeOptions[codec].value(name); + } + + void setEncodingOption(const QString &codec, const QString &name, const QVariant &value) + { + m_encodeOptions[codec][name] = value; + } + +private: + QVideoEncoderSettings m_videoSettings; + + QMap m_supportedEncodeOptions; + QMap< QString, QMap > m_encodeOptions; + + QStringList m_videoCodecs; + QList m_sizes; + QList m_framerates; +}; + +class MockAudioEncodeProvider : public QAudioEncoderControl +{ + Q_OBJECT +public: + MockAudioEncodeProvider(QObject *parent): + QAudioEncoderControl(parent) + { + m_codecs << "audio/pcm" << "audio/mpeg"; + m_supportedEncodeOptions.insert("audio/pcm", QStringList()); + m_supportedEncodeOptions.insert("audio/mpeg", QStringList() << "quality" << "bitrate" << "mode" << "vbr"); + m_audioSettings.setCodec("audio/pcm"); + m_audioSettings.setBitRate(128*1024); + } + + ~MockAudioEncodeProvider() {} + + QAudioEncoderSettings audioSettings() const { return m_audioSettings; } + void setAudioSettings(const QAudioEncoderSettings &settings) { m_audioSettings = settings; } + + QList supportedSampleRates(const QAudioEncoderSettings & = QAudioEncoderSettings(), bool *continuous = 0) const + { + if (continuous) + *continuous = false; + + return QList() << 44100; + } + + QStringList supportedAudioCodecs() const + { + return m_codecs; + } + + QString codecDescription(const QString &codecName) const + { + if (codecName == "audio/pcm") + return QString("Pulse Code Modulation"); + + if (codecName == "audio/mpeg") + return QString("MP3 audio format"); + + return QString(); + } + + + QStringList supportedEncodingOptions(const QString &codec) const + { + return m_supportedEncodeOptions.value(codec); + } + + QVariant encodingOption(const QString &codec, const QString &name) const + { + return m_encodeOptions[codec].value(name); + } + + void setEncodingOption(const QString &codec, const QString &name, const QVariant &value) + { + m_encodeOptions[codec][name] = value; + } + +private: + QAudioEncoderSettings m_audioSettings; + + QStringList m_codecs; + QStringList m_codecsDesc; + + QMap m_supportedEncodeOptions; + QMap< QString, QMap > m_encodeOptions; + +}; + +class MockAudioEndpointSelectorProvider : public QAudioEndpointSelector +{ + Q_OBJECT +public: + MockAudioEndpointSelectorProvider(QObject *parent): + QAudioEndpointSelector(parent) + { + m_names << "device1" << "device2" << "device3"; + m_descriptions << "dev1 comment" << "dev2 comment" << "dev3 comment"; + emit availableEndpointsChanged(); + } + ~MockAudioEndpointSelectorProvider() {}; + + QList availableEndpoints() const + { + return m_names; + } + + QString endpointDescription(const QString& name) const + { + QString desc; + + for(int i = 0; i < m_names.count(); i++) { + if (m_names.at(i).compare(name) == 0) { + desc = m_descriptions.at(i); + break; + } + } + return desc; + } + + QString defaultEndpoint() const + { + return m_names.at(0); + } + + QString activeEndpoint() const + { + return m_audioInput; + } + +public Q_SLOTS: + + void setActiveEndpoint(const QString& name) + { + m_audioInput = name; + emit activeEndpointChanged(name); + } + +private: + QString m_audioInput; + QList m_names; + QList m_descriptions; +}; + +class MockProvider : public QMediaRecorderControl +{ + Q_OBJECT + +public: + MockProvider(QObject *parent): + QMediaRecorderControl(parent), + m_state(QMediaRecorder::StoppedState), + m_position(0), + m_muted(false) {} + + QUrl outputLocation() const + { + return m_sink; + } + + bool setOutputLocation(const QUrl &sink) + { + m_sink = sink; + return true; + } + + QMediaRecorder::State state() const + { + return m_state; + } + + qint64 duration() const + { + return m_position; + } + + bool isMuted() const + { + return m_muted; + } + + void applySettings() {} + + using QMediaRecorderControl::error; + +public slots: + void record() + { + m_state = QMediaRecorder::RecordingState; + m_position=1; + emit stateChanged(m_state); + emit durationChanged(m_position); + } + + void pause() + { + m_state = QMediaRecorder::PausedState; + emit stateChanged(m_state); + } + + void stop() + { + m_position=0; + m_state = QMediaRecorder::StoppedState; + emit stateChanged(m_state); + } + + void setMuted(bool muted) + { + if (m_muted != muted) + emit mutedChanged(m_muted = muted); + } + +public: + QUrl m_sink; + QMediaRecorder::State m_state; + qint64 m_position; + bool m_muted; +}; + + +class QtTestMetaDataProvider : public QMetaDataWriterControl +{ + Q_OBJECT +public: + QtTestMetaDataProvider(QObject *parent = 0) + : QMetaDataWriterControl(parent) + , m_available(false) + , m_writable(false) + { + } + + bool isMetaDataAvailable() const { return m_available; } + void setMetaDataAvailable(bool available) { + if (m_available != available) + emit metaDataAvailableChanged(m_available = available); + } + QList availableMetaData() const { return m_data.keys(); } + + bool isWritable() const { return m_writable; } + void setWritable(bool writable) { emit writableChanged(m_writable = writable); } + + QVariant metaData(QtMultimediaKit::MetaData key) const { return m_data.value(key); } + void setMetaData(QtMultimediaKit::MetaData key, const QVariant &value) { + m_data.insert(key, value); } + + QVariant extendedMetaData(const QString &key) const { return m_extendedData.value(key); } + void setExtendedMetaData(const QString &key, const QVariant &value) { + m_extendedData.insert(key, value); } + + QStringList availableExtendedMetaData() const { return m_extendedData.keys(); } + + using QMetaDataWriterControl::metaDataChanged; + + void populateMetaData() + { + m_available = true; + } + + bool m_available; + bool m_writable; + QMap m_data; + QMap m_extendedData; +}; + +class MockService : public QMediaService +{ + Q_OBJECT +public: + MockService(QObject *parent, QMediaControl *control): + QMediaService(parent), + mockControl(control), + hasControls(true) + { + mockAudioEndpointSelector = new MockAudioEndpointSelectorProvider(parent); + mockAudioEncodeControl = new MockAudioEncodeProvider(parent); + mockFormatControl = new MockMediaContainerControl(parent); + mockVideoEncodeControl = new MockVideoEncodeProvider(parent); + mockMetaDataControl = new QtTestMetaDataProvider(parent); + } + + QMediaControl* requestControl(const char *name) + { + if(hasControls && qstrcmp(name,QAudioEncoderControl_iid) == 0) + return mockAudioEncodeControl; + if(hasControls && qstrcmp(name,QAudioEndpointSelector_iid) == 0) + return mockAudioEndpointSelector; + if(hasControls && qstrcmp(name,QMediaRecorderControl_iid) == 0) + return mockControl; + if(hasControls && qstrcmp(name,QMediaContainerControl_iid) == 0) + return mockFormatControl; + if(hasControls && qstrcmp(name,QVideoEncoderControl_iid) == 0) + return mockVideoEncodeControl; + if (hasControls && qstrcmp(name, QMetaDataWriterControl_iid) == 0) + return mockMetaDataControl; + + return 0; + } + + void releaseControl(QMediaControl*) {} + + QMediaControl *mockControl; + QAudioEndpointSelector *mockAudioEndpointSelector; + QAudioEncoderControl *mockAudioEncodeControl; + QMediaContainerControl *mockFormatControl; + QVideoEncoderControl *mockVideoEncodeControl; + QtTestMetaDataProvider *mockMetaDataControl; + bool hasControls; +}; + +class MockObject : public QMediaObject +{ + Q_OBJECT +public: + MockObject(QObject *parent, MockService *service): + QMediaObject(parent, service) + { + } +}; + +class tst_QMediaRecorder: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testNullService(); + void testNullControls(); + void testError(); + void testSink(); + void testRecord(); + void testMute(); + void testAudioDeviceControl(); + void testAudioEncodeControl(); + void testMediaFormatsControl(); + void testVideoEncodeControl(); + void testEncodingSettings(); + void testAudioSettings(); + void testVideoSettings(); + + void nullMetaDataControl(); + void isMetaDataAvailable(); + void isWritable(); + void metaDataChanged(); + void metaData_data(); + void metaData(); + void setMetaData_data(); + void setMetaData(); + void extendedMetaData_data() { metaData_data(); } + void extendedMetaData(); + void setExtendedMetaData_data() { extendedMetaData_data(); } + void setExtendedMetaData(); + +private: + QAudioEncoderControl* encode; + QAudioEndpointSelector* audio; + MockObject *object; + MockService *service; + MockProvider *mock; + QMediaRecorder *capture; + QVideoEncoderControl* videoEncode; +}; +#endif //TST_QMEDIARECORDER_H diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp new file mode 100755 index 000000000..48327bdd0 --- /dev/null +++ b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#include "tst_qmediarecorder_mmf.h" + +QT_USE_NAMESPACE + +void tst_QMediaRecorder_mmf::initTestCase() +{ + qRegisterMetaType("QMediaRecorder::State"); + qRegisterMetaType("QMediaRecorder::Error"); + + captureSource = new QAudioCaptureSource; + audiocapture = new QMediaRecorder(captureSource); + + QVERIFY(captureSource->service()); + + audioEndpoint = qobject_cast(captureSource->service()->requestControl(QAudioEndpointSelector_iid)); + audioEncoder = qobject_cast(captureSource->service()->requestControl(QAudioEncoderControl_iid)); +} + +void tst_QMediaRecorder_mmf::cleanupTestCase() +{ + delete audiocapture; + delete captureSource; +} + +QUrl tst_QMediaRecorder_mmf::recordPathAudio(QDir outputDir) +{ + int lastImage = 0; + int fileCount = 0; + foreach( QString fileName, outputDir.entryList(QStringList() << "testclip_*.amr") ) { + int imgNumber = fileName.mid(5, fileName.size()-9).toInt(); + lastImage = qMax(lastImage, imgNumber); + if (outputDir.exists(fileName)) + fileCount+=1; + } + lastImage+=fileCount; + + QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath()+QString("/testclip_%1.amr").arg(lastImage+1,4,10,QLatin1Char('0')))); + return location; +} + +void tst_QMediaRecorder_mmf::testAudioSink() +{ + audiocapture->setOutputLocation(QUrl("test.tmp")); + QUrl s = audiocapture->outputLocation(); + QCOMPARE(s.toString(), QString("test.tmp")); +} + +void tst_QMediaRecorder_mmf::testAudioRecord() +{ + QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State))); + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QTest::qWait(500); // wait for recorder to initialize itself + audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath())); + audiocapture->record(); + QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState); + QCOMPARE(audiocapture->error(), QMediaRecorder::NoError); + QCOMPARE(audiocapture->errorString(), QString()); + QCOMPARE(stateSignal.count(), 1); + audiocapture->pause(); + QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState); + QCOMPARE(stateSignal.count(), 2); + audiocapture->stop(); + QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QCOMPARE(stateSignal.count(), 3); +} + +void tst_QMediaRecorder_mmf::testAudioRecordWithAMR() +{ + QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State))); + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + audiocapture->setOutputLocation(recordPathAudio(QDir::rootPath())); + QAudioEncoderSettings audioSettings; + QVideoEncoderSettings videoSettings; + audioSettings.setCodec("AMR"); + QString format = audiocapture->containerMimeType(); + format = QString("audio/amr"); + audiocapture->setEncodingSettings(audioSettings,videoSettings,format); + audiocapture->record(); + QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState); + QCOMPARE(audiocapture->error(), QMediaRecorder::NoError); + QCOMPARE(audiocapture->errorString(), QString()); + QCOMPARE(stateSignal.count(), 1); + audiocapture->pause(); + QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState); + QCOMPARE(stateSignal.count(), 2); + audiocapture->stop(); + QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QCOMPARE(stateSignal.count(), 3); +} + +void tst_QMediaRecorder_mmf::testAudioEndPointSelector() +{ + QSignalSpy audioSignal(audioEndpoint,SIGNAL(activeEndpointChanged(QString))); + QVERIFY(audioEndpoint->availableEndpoints().count() == 1); + QVERIFY(audioEndpoint->defaultEndpoint().compare("default") == 0); + audioEndpoint->setActiveEndpoint("device2"); + QVERIFY(audioEndpoint->activeEndpoint().compare("device2") == 0); + QVERIFY(audioSignal.count() == 1); + QVERIFY(audioEndpoint->endpointDescription("device2").compare("") == 0); +} + +void tst_QMediaRecorder_mmf::testAudioEncoderControl() +{ + QStringList codecs = audiocapture->supportedAudioCodecs(); + QVERIFY(codecs.count() == 2); + QVERIFY(audiocapture->audioCodecDescription("PCM") == "Pulse code modulation"); + QStringList options = audioEncoder->supportedEncodingOptions("PCM"); + QCOMPARE(options.count(), 3); + QCOMPARE(audiocapture->supportedAudioSampleRates().count(), 12); + audioEncoder->setEncodingOption("PCM", "channels", QVariant(2)); + QCOMPARE(audioEncoder->encodingOption("PCM","channels").toInt(), 2); + audioEncoder->setEncodingOption("PCM", "quality", QVariant(int(QtMultimediaKit::NormalQuality))); + QCOMPARE(audioEncoder->encodingOption("PCM","quality").toInt(), int(QtMultimediaKit::NormalQuality)); + audioEncoder->setEncodingOption("PCM", "samplerate", QVariant(44100)); + QCOMPARE(audioEncoder->encodingOption("PCM","samplerate").toInt(), 44100); +} + +void tst_QMediaRecorder_mmf::testMediaFormatsControl() +{ + //audioocontainer types + // Containers supported are dynamically queried from MMF. We cannot guarentee that 2 platforms + // will support the same set. + //QCOMPARE(audiocapture->supportedContainers(), QStringList() << "audio/wav" << "audio/amr"); + QCOMPARE(audiocapture->containerDescription("audio/wav"), QString("WAV Write Format")); + QCOMPARE(audiocapture->containerDescription("audio/amr"), QString("AMR Write Format")); +} + +void tst_QMediaRecorder_mmf::testDefaultAudioEncodingSettings() +{ + QAudioEncoderSettings audioSettings = audiocapture->audioSettings(); + QCOMPARE(audioSettings.codec(), QString("AMR")); + QString format = audiocapture->containerMimeType(); + QCOMPARE(format, QString("audio/amr")); +} diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h new file mode 100755 index 000000000..83058a214 --- /dev/null +++ b/tests/auto/qmediarecorder/tst_qmediarecorder_mmf.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QMEDIARECORDER_MMF +#define TST_QMEDIARECORDER_MMF + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "s60common.h" + +QT_USE_NAMESPACE +class tst_QMediaRecorder_mmf: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testAudioSink(); + void testAudioRecord(); + void testAudioRecordWithAMR(); + void testAudioEndPointSelector(); + void testAudioEncoderControl(); + void testMediaFormatsControl(); + void testDefaultAudioEncodingSettings(); + +private: + QUrl recordPathAudio(QDir outputDir); + + QAudioEncoderControl *audioEncoder; + QAudioEndpointSelector *audioEndpoint; + QMediaRecorder *audiocapture; + QAudioCaptureSource *captureSource; +}; +#endif diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp new file mode 100755 index 000000000..b8777b4fc --- /dev/null +++ b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include "tst_qmediarecorder_xa.h" + +QT_USE_NAMESPACE + +void tst_QMediaRecorder_xa::initTestCase() +{ + audiosource = new QAudioCaptureSource; + audiocapture = new QMediaRecorder(audiosource); +} + +void tst_QMediaRecorder_xa::cleanupTestCase() +{ + delete audiocapture; + delete audiosource; +} + +void tst_QMediaRecorder_xa::testMediaRecorderObject() +{ + //audioocontainer types + QCOMPARE(audiocapture->audioCodecDescription("pcm"), QString("pcm")); + QCOMPARE(audiocapture->audioCodecDescription("amr"), QString("amr")); + QCOMPARE(audiocapture->audioCodecDescription("aac"), QString("aac")); + QCOMPARE(audiocapture->containerDescription("audio/wav"), QString("wav container")); + QCOMPARE(audiocapture->containerDescription("audio/amr"), QString("amr File format")); + QCOMPARE(audiocapture->containerDescription("audio/mpeg"), QString("mpeg container")); + QCOMPARE(audiocapture->containerMimeType(), QString("audio/wav")); + QCOMPARE(audiocapture->error(), QMediaRecorder::NoError); + QCOMPARE(audiocapture->errorString(), QString()); + QCOMPARE(audiocapture->outputLocation().toLocalFile(), QString()); + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QCOMPARE(audiocapture->supportedAudioCodecs().count(), 3); // "pcm", "amr", "aac" + QAudioEncoderSettings settings; + settings.setCodec("pcm"); + QCOMPARE(audiocapture->supportedAudioSampleRates(settings).count(), 5); + bool isContinuous; + audiocapture->supportedAudioSampleRates(settings, &isContinuous); + QCOMPARE(isContinuous, false); + QCOMPARE(audiocapture->supportedContainers().count(), 3); // "audio/wav", "audio/amr", "audio/mpeg" +} + +void tst_QMediaRecorder_xa::testDefaultAudioEncodingSettings() +{ + QAudioEncoderSettings audioSettings = audiocapture->audioSettings(); + QCOMPARE(audioSettings.codec(), QString("pcm")); + QCOMPARE(audiocapture->containerMimeType(), QString("audio/wav")); + QCOMPARE(audioSettings.bitRate(), 0); + QCOMPARE(audioSettings.channelCount(), -1); + QCOMPARE(audioSettings.encodingMode(), QtMultimediaKit::ConstantQualityEncoding); + QCOMPARE(audioSettings.quality(), QtMultimediaKit::NormalQuality); + QCOMPARE(audioSettings.sampleRate(), -1); +} + +void tst_QMediaRecorder_xa::testAudioRecordingLocationOnly() +{ + QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State))); + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QTest::qWait(500); // wait for recorder to initialize itself + audiocapture->setOutputLocation(nextFileName(QDir::rootPath(), "locationonly", "wav")); + audiocapture->record(); + QTRY_COMPARE(stateSignal.count(), 1); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState); + QCOMPARE(audiocapture->error(), QMediaRecorder::NoError); + QCOMPARE(audiocapture->errorString(), QString()); + QCOMPARE(stateSignal.count(), 1); + QTest::qWait(5000); // wait for 5 seconds + audiocapture->pause(); + QTRY_COMPARE(stateSignal.count(), 2); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState); + QCOMPARE(stateSignal.count(), 2); + audiocapture->stop(); + QTRY_COMPARE(stateSignal.count(), 3); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QCOMPARE(stateSignal.count(), 3); +} + +void tst_QMediaRecorder_xa::testAudioRecording_data() +{ + QTest::addColumn("mime"); // "audio/wav", "audio/amr", "audio/mpeg" + QTest::addColumn("codec"); // "pcm", "amr", "aac" + QTest::addColumn("filename_desc"); + QTest::addColumn("filename_ext"); // "wav", "amr", "mp4" + QTest::addColumn("settings"); + QTest::addColumn("bitrate"); + QTest::addColumn("samplerate"); + QTest::addColumn("channels"); + + QTest::newRow("wav default") << "audio/wav" << "pcm" << "default" << "wav" << "default" << 0 << 0 << 0; + QTest::newRow("amr default") << "audio/amr" << "amr" << "default" << "amr" << "default" << 4750 << 8000 << -1; + QTest::newRow("aac default") << "audio/mpeg" << "aac" << "default" << "mp4" << "default" << 0 << 48000 << -1; + QTest::newRow("wav 08kHz Mono") << "audio/wav" << "pcm" << "Sr08kHzMono" << "wav" << "user" << 0 << 8000 << 1; + QTest::newRow("wav 08kHz Stereo") << "audio/wav" << "pcm" << "Sr08kHzStereo" << "wav" << "user" << 0 << 8000 << 2; + QTest::newRow("wav 16kHz Mono") << "audio/wav" << "pcm" << "Sr16kHzMono" << "wav" << "user" << 0 << 16000 << 1; + QTest::newRow("wav 16kHz Stereo") << "audio/wav" << "pcm" << "Sr16kHzStereo" << "wav" << "user" << 0 << 16000 << 2; + QTest::newRow("wav 32kHz Mono") << "audio/wav" << "pcm" << "Sr32kHzMono" << "wav" << "user" << 0 << 32000 << 1; + QTest::newRow("wav 32kHz Stereo") << "audio/wav" << "pcm" << "Sr32kHzStereo" << "wav" << "user" << 0<< 32000 << 2; + QTest::newRow("wav 48kHz Mono") << "audio/wav" << "pcm" << "Sr48kHzMono" << "wav" << "user" << 0 << 48000 << 1; + QTest::newRow("wav 48kHz Stereo") << "audio/wav" << "pcm" << "Sr48kHzStereo" << "wav" << "user" << 0 << 48000 << 2; + QTest::newRow("amr Br04750bps") << "audio/amr" << "amr" << "Br04750bps" << "amr" << "user" << 4750 << 8000 << 1; + QTest::newRow("amr Br05150bps") << "audio/amr" << "amr" << "Br05150bps" << "amr" << "user" << 5150 << 8000 << 1; + QTest::newRow("amr Br05900bps") << "audio/amr" << "amr" << "Br05900bps" << "amr" << "user" << 5900 << 8000 << 1; + QTest::newRow("amr Br06700bps") << "audio/amr" << "amr" << "Br06700bps" << "amr" << "user" << 6700 << 8000 << 1; + QTest::newRow("amr Br07400bps") << "audio/amr" << "amr" << "Br07400bps" << "amr" << "user" << 7400 << 8000 << 1; + QTest::newRow("amr Br07950bps") << "audio/amr" << "amr" << "Br07950bps" << "amr" << "user" << 7950 << 8000 << 1; + QTest::newRow("amr Br10200bps") << "audio/amr" << "amr" << "Br10200bps" << "amr" << "user" << 10200 << 8000 << 1; + QTest::newRow("amr Br12200bps") << "audio/amr" << "amr" << "Br12200bps" << "amr" << "user" << 10200 << 8000 << 1; + QTest::newRow("amr verylowqual") << "audio/amr" << "amr" << "verylowqual" << "amr" << "preset" << -1 << 8000 << -1; + QTest::newRow("amr lowqual") << "audio/amr" << "amr" << "lowqual" << "amr" << "preset" << -2 << 8000 << -1; + QTest::newRow("amr normalqual") << "audio/amr" << "amr" << "normalqual" << "amr" << "preset" << -3 << 8000 << -1; + QTest::newRow("amr highqual") << "audio/amr" << "amr" << "highqual" << "amr" << "preset" << -4 << 8000 << -1; + QTest::newRow("amr veryhighqual") << "audio/amr" << "amr" << "veryhighqual" << "amr" << "preset" << -5 << 8000 << -1; + + // Combinations supported for sample rate 8kHz + QTest::newRow("aac Br32k Sr8kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr8kHzMono" << "mp4" << "user" << 32000 << 8000 << 1; + QTest::newRow("aac Br32k Sr8kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr8kHzStereo" << "mp4" << "user" << 32000 << 8000 << 2; + QTest::newRow("aac Br64k Sr8kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr8kHzStereo" << "mp4" << "user" << 64000 << 8000 << 2; + // Combinations supported for sample rate 16kHz + QTest::newRow("aac Br32k Sr16kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr16kHzMono" << "mp4" << "user" << 32000 << 16000 << 1; + QTest::newRow("aac Br64k Sr16kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr16kHzMonoo" << "mp4" << "user" << 64000 << 16000 << 1; + QTest::newRow("aac Br32k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr16kHzStereo" << "mp4" << "user" << 32000 << 16000 << 2; + QTest::newRow("aac Br64k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr16kHzStereo" << "mp4" << "user" << 64000 << 16000 << 2; + QTest::newRow("aac Br96k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr16kHzStereo" << "mp4" << "user" << 96000 << 16000 << 2; + QTest::newRow("aac Br128k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr16kHzStereo" << "mp4" << "user" << 128000 << 16000 << 2; + QTest::newRow("aac Br160k Sr16kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr16kHzStereo" << "mp4" << "user" << 160000 << 16000 << 2; + // Combinations supported for sample rate 24kHz + QTest::newRow("aac Br32k Sr24kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr24kHzMono" << "mp4" << "user" << 32000 << 24000 << 1; + QTest::newRow("aac Br64k Sr24kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr24kHzMono" << "mp4" << "user" << 64000 << 24000 << 1; + QTest::newRow("aac Br96k Sr24kHz Mono") << "audio/mpeg" << "aac" << "Br96kSr24kHzMono" << "mp4" << "user" << 96000 << 24000 << 1; + QTest::newRow("aac Br32k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr24kHzStereo" << "mp4" << "user" << 32000 << 24000 << 2; + QTest::newRow("aac Br64k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr24kHzStereo" << "mp4" << "user" << 64000 << 24000 << 2; + QTest::newRow("aac Br96k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr24kHzStereo" << "mp4" << "user" << 96000 << 24000 << 2; + QTest::newRow("aac Br128k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr24kHzStereo" << "mp4" << "user" << 128000 << 24000 << 2; + QTest::newRow("aac Br160k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr24kHzStereo" << "mp4" << "user" << 160000 << 24000 << 2; + QTest::newRow("aac Br192k Sr24kHz Stereo") << "audio/mpeg" << "aac" << "Br192kSr24kHzStereo" << "mp4" << "user" << 192000 << 24000 << 2; + // Combinations supported for sample rate 32kHz + QTest::newRow("aac Br32k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr32kHzMono" << "mp4" << "user" << 32000 << 32000 << 1; + QTest::newRow("aac Br64k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr32kHzMono" << "mp4" << "user" << 64000 << 32000 << 1; + QTest::newRow("aac Br96k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br96kSr32kHzMono" << "mp4" << "user" << 96000 << 32000 << 1; + QTest::newRow("aac Br128k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br128kSr32kHzMono" << "mp4" << "user" << 128000 << 32000 << 1; + QTest::newRow("aac Br160k Sr32kHz Mono") << "audio/mpeg" << "aac" << "Br160kSr32kHzMono" << "mp4" << "user" << 160000 << 32000 << 1; + QTest::newRow("aac Br32k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr32kHzStereo" << "mp4" << "user" << 32000 << 32000 << 2; + QTest::newRow("aac Br64k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr32kHzStereo" << "mp4" << "user" << 64000 << 32000 << 2; + QTest::newRow("aac Br96k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr32kHzStereo" << "mp4" << "user" << 96000 << 32000 << 2; + QTest::newRow("aac Br128k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr32kHzStereo" << "mp4" << "user" << 128000 << 32000 << 2; + QTest::newRow("aac Br160k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr32kHzStereo" << "mp4" << "user" << 160000 << 32000 << 2; + QTest::newRow("aac Br192k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br192kSr32kHzStereo" << "mp4" << "user" << 192000 << 32000 << 2; + QTest::newRow("aac Br224k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br224kSr32kHzStereo" << "mp4" << "user" << 224000 << 32000 << 2; + QTest::newRow("aac Br256k Sr32kHz Stereo") << "audio/mpeg" << "aac" << "Br256kSr32kHzStereo" << "mp4" << "user" << 256000 << 32000 << 2; + // Combinations supported for sample rate 48kHz + QTest::newRow("aac Br32k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br32kSr48kHzMono" << "mp4" << "user" << 32000 << 48000 << 1; + QTest::newRow("aac Br64k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br64kSr48kHzMono" << "mp4" << "user" << 64000 << 48000 << 1; + QTest::newRow("aac Br96k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br96kSr48kHzMono" << "mp4" << "user" << 96000 << 48000 << 1; + QTest::newRow("aac Br128k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br128kSr48kHzMono" << "mp4" << "user" << 128000 << 48000 << 1; + QTest::newRow("aac Br160k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br160kSr48kHzMono" << "mp4" << "user" << 160000 << 48000 << 1; + QTest::newRow("aac Br192k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br192kSr48kHzMono" << "mp4" << "user" << 192000 << 48000 << 1; + QTest::newRow("aac Br224k Sr48kHz Mono") << "audio/mpeg" << "aac" << "Br224kSr48kHzMono" << "mp4" << "user" << 224000 << 48000 << 1; + QTest::newRow("aac Br32k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br32kSr48kHzStereo" << "mp4" << "user" << 32000 << 48000 << 2; + QTest::newRow("aac Br64k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br64kSr48kHzStereo" << "mp4" << "user" << 64000 << 48000 << 2; + QTest::newRow("aac Br96k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br96kSr48kHzStereo" << "mp4" << "user" << 96000 << 48000 << 2; + QTest::newRow("aac Br128k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br128kSr48kHzStereo" << "mp4" << "user" << 128000 << 48000 << 2; + QTest::newRow("aac Br160k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br160kSr48kHzStereo" << "mp4" << "user" << 160000 << 48000 << 2; + QTest::newRow("aac Br192k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br192kSr48kHzStereo" << "mp4" << "user" << 192000 << 48000 << 2; + QTest::newRow("aac Br224k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br224kSr48kHzStereo" << "mp4" << "user" << 224000 << 48000 << 2; + QTest::newRow("aac Br256k Sr48kHz Stereo") << "audio/mpeg" << "aac" << "Br256kSr48kHzStereo" << "mp4" << "user" << 256000 << 48000 << 2; + QTest::newRow("aac verylowqual") << "audio/mpeg" << "aac" << "verylowqual" << "mp4" << "preset" << -1 << 8000 << -1; + QTest::newRow("aac lowqual") << "audio/mpeg" << "aac" << "lowqual" << "mp4" << "preset" << -2 << 24000 << -1; + QTest::newRow("aac normalqual") << "audio/mpeg" << "aac" << "normalqual" << "mp4" << "preset" << -3 << 32000 << -1; + QTest::newRow("aac highqual") << "audio/mpeg" << "aac" << "highqual" << "mp4" << "preset" << -4 << 48000 << -1; + QTest::newRow("aac veryhighqual") << "audio/mpeg" << "aac" << "veryhighqual" << "mp4" << "preset" << -5 << 48000 << -1; + } + +void tst_QMediaRecorder_xa::testAudioRecording() +{ + QFETCH(QString, mime); + QFETCH(QString, codec); + QFETCH(QString, filename_desc); + QFETCH(QString, filename_ext); + QFETCH(QString, settings); + + QSignalSpy stateSignal(audiocapture,SIGNAL(stateChanged(QMediaRecorder::State))); + audiocapture->setOutputLocation(nextFileName(QDir::rootPath(), filename_desc, filename_ext)); + QAudioEncoderSettings audioSettings; + audioSettings.setCodec(codec); + if (settings.compare("default") == 0) { + audioSettings.setSampleRate(-1); + } + else if (settings.compare("user") == 0) { + QFETCH(int, bitrate); + QFETCH(int, samplerate); + QFETCH(int, channels); + audioSettings.setEncodingMode(QtMultimediaKit::ConstantBitRateEncoding); + if (bitrate > 0) + audioSettings.setBitRate(bitrate); + if (samplerate > 0) + audioSettings.setSampleRate(samplerate); + if ((channels > 0) || (channels == -1)) + audioSettings.setChannelCount(channels); + } + else if (settings.compare("preset") == 0) { + QFETCH(int, bitrate); + QFETCH(int, samplerate); + QFETCH(int, channels); + audioSettings.setEncodingMode(QtMultimediaKit::ConstantQualityEncoding); + QtMultimediaKit::EncodingQuality quality = QtMultimediaKit::NormalQuality; + switch(bitrate) { + case -1: + quality = QtMultimediaKit::VeryLowQuality; + break; + case -2: + quality = QtMultimediaKit::LowQuality; + break; + default: + case -3: + quality = QtMultimediaKit::NormalQuality; + break; + case -4: + quality = QtMultimediaKit::HighQuality; + break; + case -5: + quality = QtMultimediaKit::VeryHighQuality; + break; + } + audioSettings.setQuality(quality); + if (samplerate > 0) + audioSettings.setSampleRate(samplerate); + if ((channels > 0) || (channels == -1)) + audioSettings.setChannelCount(channels); + } + QVideoEncoderSettings videoSettings; + audiocapture->setEncodingSettings(audioSettings, videoSettings, mime); + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QTest::qWait(500); // wait for recorder to initialize itself + int expectedSignalCount = 1; + audiocapture->record(); + QTRY_COMPARE(stateSignal.count(), expectedSignalCount); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::RecordingState); + QCOMPARE(audiocapture->error(), QMediaRecorder::NoError); + QCOMPARE(audiocapture->errorString(), QString()); + QCOMPARE(stateSignal.count(), expectedSignalCount); + QTest::qWait(5000); // wait for 5 seconds + // If we are not testing aac recording to mp4 container + if (!((mime.compare("audio/mpeg") == 0) && (codec.compare("aac") == 0))) { + expectedSignalCount++; + audiocapture->pause(); + QTRY_COMPARE(stateSignal.count(), expectedSignalCount); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::PausedState); + QCOMPARE(stateSignal.count(), expectedSignalCount); + } + expectedSignalCount++; + audiocapture->stop(); + QTRY_COMPARE(stateSignal.count(), expectedSignalCount); // wait for callbacks to complete in symbian API + QCOMPARE(audiocapture->state(), QMediaRecorder::StoppedState); + QCOMPARE(stateSignal.count(), expectedSignalCount); + /* testAudioRecording() function gets executed for each rown in the table. + * If and when all tests in the table passes, test log will just contain one + * entry 'PASS : tst_QMediaRecorder_xa::testAudioRecording()'. To figure out + * which test in the loop completed successfully, just print a debug message + * which also goes into the test log generated.*/ + qDebug() << "----> PASS"; +} + +void tst_QMediaRecorder_xa::testOutputLocation() +{ + audiocapture->setOutputLocation(QUrl("test.wav")); + QUrl s = audiocapture->outputLocation(); + QCOMPARE(s.toString(), QString("test.wav")); +} + +QUrl tst_QMediaRecorder_xa::nextFileName(QDir outputDir, QString appendName, QString ext) +{ + int lastImage = 0; + int fileCount = 0; + foreach( QString fileName, outputDir.entryList(QStringList() << "testclip_*." + ext) ) { + int imgNumber = fileName.mid(5, fileName.size()-9).toInt(); + lastImage = qMax(lastImage, imgNumber); + if (outputDir.exists(fileName)) + fileCount+=1; + } + lastImage+=fileCount; + + QUrl location(QDir::toNativeSeparators(outputDir.canonicalPath() + QString("/testclip_%1").arg(lastImage+1 , 4, 10, QLatin1Char('0')) + appendName + "." + ext)); + return location; +} diff --git a/tests/auto/qmediarecorder/tst_qmediarecorder_xa.h b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.h new file mode 100755 index 000000000..c7fe415e4 --- /dev/null +++ b/tests/auto/qmediarecorder/tst_qmediarecorder_xa.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#ifndef TST_QMEDIARECORDER_XA_H +#define TST_QMEDIARECORDER_XA_H + +#include +#include +#include + +#include "s60common.h" + +QT_USE_NAMESPACE + +class tst_QMediaRecorder_xa: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testMediaRecorderObject(); //1 + void testDefaultAudioEncodingSettings(); //2 + void testOutputLocation(); //3 + void testAudioRecordingLocationOnly(); //4 + void testAudioRecording_data(); //5 + void testAudioRecording(); //6 + +private: + QUrl nextFileName(QDir outputDir, QString appendName, QString ext); + +private: + QAudioCaptureSource* audiosource; + QMediaRecorder* audiocapture; + +}; + +#endif /* TST_QMEDIARECORDER_XA_H */ diff --git a/tests/auto/qmediaresource/qmediaresource.pro b/tests/auto/qmediaresource/qmediaresource.pro new file mode 100644 index 000000000..dcd2a2f45 --- /dev/null +++ b/tests/auto/qmediaresource/qmediaresource.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += network multimediakit-private + +# TARGET = tst_qmediaresource +# CONFIG += testcase + +SOURCES += tst_qmediaresource.cpp + diff --git a/tests/auto/qmediaresource/tst_qmediaresource.cpp b/tests/auto/qmediaresource/tst_qmediaresource.cpp new file mode 100644 index 000000000..602b1fba4 --- /dev/null +++ b/tests/auto/qmediaresource/tst_qmediaresource.cpp @@ -0,0 +1,528 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include + +#include "qmediaresource.h" + +QT_USE_NAMESPACE +class tst_QMediaResource : public QObject +{ + Q_OBJECT +private slots: + void constructNull(); + void construct_data(); + void construct(); + void setResolution(); + void equality(); + void copy(); + void assign(); +}; + +void tst_QMediaResource::constructNull() +{ + QMediaResource resource; + + QCOMPARE(resource.isNull(), true); + QCOMPARE(resource.url(), QUrl()); + QCOMPARE(resource.request(), QNetworkRequest()); + QCOMPARE(resource.mimeType(), QString()); + QCOMPARE(resource.language(), QString()); + QCOMPARE(resource.audioCodec(), QString()); + QCOMPARE(resource.videoCodec(), QString()); + QCOMPARE(resource.dataSize(), qint64(0)); + QCOMPARE(resource.audioBitRate(), 0); + QCOMPARE(resource.sampleRate(), 0); + QCOMPARE(resource.channelCount(), 0); + QCOMPARE(resource.videoBitRate(), 0); + QCOMPARE(resource.resolution(), QSize()); +} + +void tst_QMediaResource::construct_data() +{ + QTest::addColumn("url"); + QTest::addColumn("request"); + QTest::addColumn("mimeType"); + QTest::addColumn("language"); + QTest::addColumn("audioCodec"); + QTest::addColumn("videoCodec"); + QTest::addColumn("dataSize"); + QTest::addColumn("audioBitRate"); + QTest::addColumn("sampleRate"); + QTest::addColumn("channelCount"); + QTest::addColumn("videoBitRate"); + QTest::addColumn("resolution"); + + QTest::newRow("audio content") + << QUrl(QString::fromLatin1("http:://test.com/test.mp3")) + << QNetworkRequest(QUrl(QString::fromLatin1("http:://test.com/test.mp3"))) + << QString::fromLatin1("audio/mpeg") + << QString::fromLatin1("eng") + << QString::fromLatin1("mp3") + << QString() + << qint64(5465433) + << 128000 + << 44100 + << 2 + << 0 + << QSize(); + QTest::newRow("image content") + << QUrl(QString::fromLatin1("http:://test.com/test.jpg")) + << QNetworkRequest(QUrl(QString::fromLatin1("http:://test.com/test.jpg"))) + << QString::fromLatin1("image/jpeg") + << QString() + << QString() + << QString() + << qint64(23600) + << 0 + << 0 + << 0 + << 0 + << QSize(640, 480); + QTest::newRow("video content") + << QUrl(QString::fromLatin1("http:://test.com/test.mp4")) + << QNetworkRequest(QUrl(QString::fromLatin1("http:://test.com/test.mp4"))) + << QString::fromLatin1("video/mp4") + << QString() + << QString::fromLatin1("aac") + << QString::fromLatin1("h264") + << qint64(36245851) + << 96000 + << 44000 + << 5 + << 750000 + << QSize(720, 576); + QTest::newRow("thumbnail") + << QUrl(QString::fromLatin1("file::///thumbs/test.png")) + << QNetworkRequest(QUrl(QString::fromLatin1("file::///thumbs/test.png"))) + << QString::fromLatin1("image/png") + << QString() + << QString() + << QString() + << qint64(2360) + << 0 + << 0 + << 0 + << 0 + << QSize(128, 128); +} + +void tst_QMediaResource::construct() +{ + QFETCH(QUrl, url); + QFETCH(QNetworkRequest, request); + QFETCH(QString, mimeType); + QFETCH(QString, language); + QFETCH(QString, audioCodec); + QFETCH(QString, videoCodec); + QFETCH(qint64, dataSize); + QFETCH(int, audioBitRate); + QFETCH(int, sampleRate); + QFETCH(int, channelCount); + QFETCH(int, videoBitRate); + QFETCH(QSize, resolution); + + { + QMediaResource resource(url); + + QCOMPARE(resource.isNull(), false); + QCOMPARE(resource.url(), url); + QCOMPARE(resource.mimeType(), QString()); + QCOMPARE(resource.language(), QString()); + QCOMPARE(resource.audioCodec(), QString()); + QCOMPARE(resource.videoCodec(), QString()); + QCOMPARE(resource.dataSize(), qint64(0)); + QCOMPARE(resource.audioBitRate(), 0); + QCOMPARE(resource.sampleRate(), 0); + QCOMPARE(resource.channelCount(), 0); + QCOMPARE(resource.videoBitRate(), 0); + QCOMPARE(resource.resolution(), QSize()); + } + { + QMediaResource resource(url, mimeType); + + QCOMPARE(resource.isNull(), false); + QCOMPARE(resource.url(), url); + QCOMPARE(resource.request(), request); + QCOMPARE(resource.mimeType(), mimeType); + QCOMPARE(resource.language(), QString()); + QCOMPARE(resource.audioCodec(), QString()); + QCOMPARE(resource.videoCodec(), QString()); + QCOMPARE(resource.dataSize(), qint64(0)); + QCOMPARE(resource.audioBitRate(), 0); + QCOMPARE(resource.sampleRate(), 0); + QCOMPARE(resource.channelCount(), 0); + QCOMPARE(resource.videoBitRate(), 0); + QCOMPARE(resource.resolution(), QSize()); + + resource.setLanguage(language); + resource.setAudioCodec(audioCodec); + resource.setVideoCodec(videoCodec); + resource.setDataSize(dataSize); + resource.setAudioBitRate(audioBitRate); + resource.setSampleRate(sampleRate); + resource.setChannelCount(channelCount); + resource.setVideoBitRate(videoBitRate); + resource.setResolution(resolution); + + QCOMPARE(resource.language(), language); + QCOMPARE(resource.audioCodec(), audioCodec); + QCOMPARE(resource.videoCodec(), videoCodec); + QCOMPARE(resource.dataSize(), dataSize); + QCOMPARE(resource.audioBitRate(), audioBitRate); + QCOMPARE(resource.sampleRate(), sampleRate); + QCOMPARE(resource.channelCount(), channelCount); + QCOMPARE(resource.videoBitRate(), videoBitRate); + QCOMPARE(resource.resolution(), resolution); + } + { + QMediaResource resource(request, mimeType); + + QCOMPARE(resource.isNull(), false); + QCOMPARE(resource.url(), url); + QCOMPARE(resource.request(), request); + QCOMPARE(resource.mimeType(), mimeType); + QCOMPARE(resource.language(), QString()); + QCOMPARE(resource.audioCodec(), QString()); + QCOMPARE(resource.videoCodec(), QString()); + QCOMPARE(resource.dataSize(), qint64(0)); + QCOMPARE(resource.audioBitRate(), 0); + QCOMPARE(resource.sampleRate(), 0); + QCOMPARE(resource.channelCount(), 0); + QCOMPARE(resource.videoBitRate(), 0); + QCOMPARE(resource.resolution(), QSize()); + + resource.setLanguage(language); + resource.setAudioCodec(audioCodec); + resource.setVideoCodec(videoCodec); + resource.setDataSize(dataSize); + resource.setAudioBitRate(audioBitRate); + resource.setSampleRate(sampleRate); + resource.setChannelCount(channelCount); + resource.setVideoBitRate(videoBitRate); + resource.setResolution(resolution); + + QCOMPARE(resource.language(), language); + QCOMPARE(resource.audioCodec(), audioCodec); + QCOMPARE(resource.videoCodec(), videoCodec); + QCOMPARE(resource.dataSize(), dataSize); + QCOMPARE(resource.audioBitRate(), audioBitRate); + QCOMPARE(resource.sampleRate(), sampleRate); + QCOMPARE(resource.channelCount(), channelCount); + QCOMPARE(resource.videoBitRate(), videoBitRate); + QCOMPARE(resource.resolution(), resolution); + } +} + +void tst_QMediaResource::setResolution() +{ + QMediaResource resource( + QUrl(QString::fromLatin1("file::///thumbs/test.png")), + QString::fromLatin1("image/png")); + + QCOMPARE(resource.resolution(), QSize()); + + resource.setResolution(QSize(120, 80)); + QCOMPARE(resource.resolution(), QSize(120, 80)); + + resource.setResolution(QSize(-1, 23)); + QCOMPARE(resource.resolution(), QSize(-1, 23)); + + resource.setResolution(QSize(-43, 34)); + QCOMPARE(resource.resolution(), QSize(-43, 34)); + + resource.setResolution(QSize(64, -1)); + QCOMPARE(resource.resolution(), QSize(64, -1)); + + resource.setResolution(QSize(64, -83)); + QCOMPARE(resource.resolution(), QSize(64, -83)); + + resource.setResolution(QSize(-12, -83)); + QCOMPARE(resource.resolution(), QSize(-12, -83)); + + resource.setResolution(QSize()); + QCOMPARE(resource.resolution(), QSize(-1, -1)); + + resource.setResolution(120, 80); + QCOMPARE(resource.resolution(), QSize(120, 80)); + + resource.setResolution(-1, 23); + QCOMPARE(resource.resolution(), QSize(-1, 23)); + + resource.setResolution(-43, 34); + QCOMPARE(resource.resolution(), QSize(-43, 34)); + + resource.setResolution(64, -1); + QCOMPARE(resource.resolution(), QSize(64, -1)); + + resource.setResolution(64, -83); + QCOMPARE(resource.resolution(), QSize(64, -83)); + + resource.setResolution(-12, -83); + QCOMPARE(resource.resolution(), QSize(-12, -83)); + + resource.setResolution(-1, -1); + QCOMPARE(resource.resolution(), QSize()); +} + +void tst_QMediaResource::equality() +{ + QMediaResource resource1( + QUrl(QString::fromLatin1("http://test.com/test.mp4")), + QString::fromLatin1("video/mp4")); + QMediaResource resource2( + QUrl(QString::fromLatin1("http://test.com/test.mp4")), + QString::fromLatin1("video/mp4")); + QMediaResource resource3( + QUrl(QString::fromLatin1("file:///thumbs/test.jpg"))); + QMediaResource resource4( + QUrl(QString::fromLatin1("file:///thumbs/test.jpg"))); + QMediaResource resource5( + QUrl(QString::fromLatin1("http://test.com/test.mp3")), + QString::fromLatin1("audio/mpeg")); + + QNetworkRequest request(QUrl("http://test.com/test.mp3")); + QString requestMimeType("audio/mp3"); + + QMediaResource requestResource1(request, requestMimeType); + QMediaResource requestResource2(request, requestMimeType); + + QCOMPARE(requestResource1 == requestResource2, true); + QCOMPARE(requestResource1 != requestResource2, false); + QCOMPARE(requestResource1 != resource5, true); + + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + QCOMPARE(resource3 == resource4, true); + QCOMPARE(resource3 != resource4, false); + + QCOMPARE(resource1 == resource3, false); + QCOMPARE(resource1 != resource3, true); + + QCOMPARE(resource1 == resource5, false); + QCOMPARE(resource1 != resource5, true); + + resource1.setAudioCodec(QString::fromLatin1("mp3")); + resource2.setAudioCodec(QString::fromLatin1("aac")); + + // Not equal differing audio codecs. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + + resource1.setAudioCodec(QString::fromLatin1("aac")); + + // Equal. + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource1.setVideoCodec(QString()); + + // Equal. + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource1.setVideoCodec(QString::fromLatin1("h264")); + + // Not equal differing video codecs. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + + resource2.setVideoCodec(QString::fromLatin1("h264")); + + // Equal. + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource2.setDataSize(0); + + // Equal. + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource1.setDataSize(546423); + + // Not equal differing video codecs. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + + resource2.setDataSize(546423); + + // Equal. + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource1.setAudioBitRate(96000); + resource1.setSampleRate(48000); + resource2.setSampleRate(44100); + resource1.setChannelCount(0); + resource1.setVideoBitRate(900000); + resource2.setLanguage(QString::fromLatin1("eng")); + + // Not equal, audio bit rate, sample rate, video bit rate, and + // language. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + + resource2.setAudioBitRate(96000); + resource1.setSampleRate(44100); + + // Not equal, differing video bit rate, and language. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + + resource2.setVideoBitRate(900000); + resource1.setLanguage(QString::fromLatin1("eng")); + + // Equal + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource1.setResolution(QSize()); + + // Equal + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource2.setResolution(-1, -1); + + // Equal + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); + + resource1.setResolution(QSize(-640, -480)); + + // Not equal, differing resolution. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + resource1.setResolution(QSize(640, 480)); + resource2.setResolution(QSize(800, 600)); + + // Not equal, differing resolution. + QCOMPARE(resource1 == resource2, false); + QCOMPARE(resource1 != resource2, true); + + resource1.setResolution(800, 600); + + // Equal + QCOMPARE(resource1 == resource2, true); + QCOMPARE(resource1 != resource2, false); +} + +void tst_QMediaResource::copy() +{ + const QUrl url(QString::fromLatin1("http://test.com/test.mp4")); + const QString mimeType(QLatin1String("video/mp4")); + const QString amrCodec(QLatin1String("amr")); + const QString mp3Codec(QLatin1String("mp3")); + const QString aacCodec(QLatin1String("aac")); + const QString h264Codec(QLatin1String("h264")); + + QMediaResource original(url, mimeType); + original.setAudioCodec(amrCodec); + + QMediaResource copy(original); + + QCOMPARE(copy.url(), url); + QCOMPARE(copy.mimeType(), mimeType); + QCOMPARE(copy.audioCodec(), amrCodec); + + QCOMPARE(original == copy, true); + QCOMPARE(original != copy, false); + + original.setAudioCodec(mp3Codec); + + QCOMPARE(copy.audioCodec(), amrCodec); + QCOMPARE(original == copy, false); + QCOMPARE(original != copy, true); + + copy.setAudioCodec(aacCodec); + copy.setVideoCodec(h264Codec); + + QCOMPARE(copy.url(), url); + QCOMPARE(copy.mimeType(), mimeType); + + QCOMPARE(original.audioCodec(), mp3Codec); +} + +void tst_QMediaResource::assign() +{ + const QUrl url(QString::fromLatin1("http://test.com/test.mp4")); + const QString mimeType(QLatin1String("video/mp4")); + const QString amrCodec(QLatin1String("amr")); + const QString mp3Codec(QLatin1String("mp3")); + const QString aacCodec(QLatin1String("aac")); + const QString h264Codec(QLatin1String("h264")); + + QMediaResource copy(QUrl(QString::fromLatin1("file:///thumbs/test.jpg"))); + + QMediaResource original(url, mimeType); + original.setAudioCodec(amrCodec); + + copy = original; + + QCOMPARE(copy.url(), url); + QCOMPARE(copy.mimeType(), mimeType); + QCOMPARE(copy.audioCodec(), amrCodec); + + QCOMPARE(original == copy, true); + QCOMPARE(original != copy, false); + + original.setAudioCodec(mp3Codec); + + QCOMPARE(copy.audioCodec(), amrCodec); + QCOMPARE(original == copy, false); + QCOMPARE(original != copy, true); + + copy.setAudioCodec(aacCodec); + copy.setVideoCodec(h264Codec); + + QCOMPARE(copy.url(), url); + QCOMPARE(copy.mimeType(), mimeType); + + QCOMPARE(original.audioCodec(), mp3Codec); +} + +QTEST_MAIN(tst_QMediaResource) + +#include "tst_qmediaresource.moc" diff --git a/tests/auto/qmediaservice/qmediaservice.pro b/tests/auto/qmediaservice/qmediaservice.pro new file mode 100644 index 000000000..d0397ad66 --- /dev/null +++ b/tests/auto/qmediaservice/qmediaservice.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediaservice +# CONFIG += testcase + +SOURCES += tst_qmediaservice.cpp + diff --git a/tests/auto/qmediaservice/tst_qmediaservice.cpp b/tests/auto/qmediaservice/tst_qmediaservice.cpp new file mode 100644 index 000000000..9c23d6dc0 --- /dev/null +++ b/tests/auto/qmediaservice/tst_qmediaservice.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QtTestMediaService; + +class tst_QMediaService : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + + void control_iid(); + void control(); +}; + + +class QtTestMediaControlA : public QMediaControl +{ + Q_OBJECT +}; + +#define QtTestMediaControlA_iid "com.nokia.QtTestMediaControlA" +Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlA, QtTestMediaControlA_iid) + +class QtTestMediaControlB : public QMediaControl +{ + Q_OBJECT +}; + +#define QtTestMediaControlB_iid "com.nokia.QtTestMediaControlB" +Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlB, QtTestMediaControlB_iid) + + +class QtTestMediaControlC : public QMediaControl +{ + Q_OBJECT +}; + +#define QtTestMediaControlC_iid "com.nokia.QtTestMediaControlC" +Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlC, QtTestMediaControlA_iid) // Yes A. + +class QtTestMediaControlD : public QMediaControl +{ + Q_OBJECT +}; + +#define QtTestMediaControlD_iid "com.nokia.QtTestMediaControlD" +Q_MEDIA_DECLARE_CONTROL(QtTestMediaControlD, QtTestMediaControlD_iid) + +class QtTestMediaControlE : public QMediaControl +{ + Q_OBJECT +}; + +class QtTestMediaService : public QMediaService +{ + Q_OBJECT +public: + QtTestMediaService() + : QMediaService(0) + , refA(0) + , refB(0) + , refC(0) + { + } + + QMediaControl *requestControl(const char *name) + { + if (strcmp(name, QtTestMediaControlA_iid) == 0) { + refA += 1; + + return &controlA; + } else if (strcmp(name, QtTestMediaControlB_iid) == 0) { + refB += 1; + + return &controlB; + } else if (strcmp(name, QtTestMediaControlC_iid) == 0) { + refA += 1; + + return &controlA; + } else { + return 0; + } + } + + void releaseControl(QMediaControl *control) + { + if (control == &controlA) + refA -= 1; + else if (control == &controlB) + refB -= 1; + else if (control == &controlC) + refC -= 1; + } + + using QMediaService::requestControl; + + int refA; + int refB; + int refC; + QtTestMediaControlA controlA; + QtTestMediaControlB controlB; + QtTestMediaControlC controlC; +}; + +void tst_QMediaService::initTestCase() +{ +} + +void tst_QMediaService::control_iid() +{ + const char *nullString = 0; + + // Default implementation. + QCOMPARE(qmediacontrol_iid(), nullString); + + // Partial template. + QVERIFY(qstrcmp(qmediacontrol_iid(), QtTestMediaControlA_iid) == 0); +} + +void tst_QMediaService::control() +{ + QtTestMediaService service; + + QtTestMediaControlA *controlA = service.requestControl(); + QCOMPARE(controlA, &service.controlA); + service.releaseControl(controlA); + + QtTestMediaControlB *controlB = service.requestControl(); + QCOMPARE(controlB, &service.controlB); + service.releaseControl(controlB); + + QVERIFY(!service.requestControl()); // Faulty implementation returns A. + QCOMPARE(service.refA, 0); // Verify the control was released. + + QVERIFY(!service.requestControl()); // No control of that type. +} + +QT_END_NAMESPACE + +QT_USE_NAMESPACE + +QTEST_MAIN(tst_QMediaService) + +#include "tst_qmediaservice.moc" diff --git a/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro b/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro new file mode 100644 index 000000000..d107ff74f --- /dev/null +++ b/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediaserviceprovider +# CONFIG += testcase + +SOURCES += tst_qmediaserviceprovider.cpp + diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp new file mode 100644 index 000000000..6e33a0412 --- /dev/null +++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE +class MockMediaService : public QMediaService +{ + Q_OBJECT +public: + MockMediaService(const QString& name, QObject *parent = 0) : QMediaService(parent) + { setObjectName(name); } + ~MockMediaService() {} + + QMediaControl* requestControl(const char *) {return 0;} + void releaseControl(QMediaControl *) {} +}; + +class MockServicePlugin1 : public QMediaServiceProviderPlugin, + public QMediaServiceSupportedFormatsInterface, + public QMediaServiceSupportedDevicesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedFormatsInterface) + Q_INTERFACES(QMediaServiceSupportedDevicesInterface) +public: + QStringList keys() const + { + return QStringList() << + QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); + } + + QMediaService* create(QString const& key) + { + if (keys().contains(key)) + return new MockMediaService("MockServicePlugin1"); + else + return 0; + } + + void release(QMediaService *service) + { + delete service; + } + + QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + { + if (codecs.contains(QLatin1String("mpeg4"))) + return QtMultimediaKit::NotSupported; + + if (mimeType == "audio/ogg") { + return QtMultimediaKit::ProbablySupported; + } + + return QtMultimediaKit::MaybeSupported; + } + + QStringList supportedMimeTypes() const + { + return QStringList("audio/ogg"); + } + + QList devices(const QByteArray &service) const + { + QList res; + return res; + } + + QString deviceDescription(const QByteArray &service, const QByteArray &device) + { + if (devices(service).contains(device)) + return QString(device)+" description"; + else + return QString(); + } +}; + +class MockServicePlugin2 : public QMediaServiceProviderPlugin, + public QMediaServiceSupportedFormatsInterface, + public QMediaServiceFeaturesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedFormatsInterface) + Q_INTERFACES(QMediaServiceFeaturesInterface) +public: + QStringList keys() const + { + return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) + << QLatin1String(Q_MEDIASERVICE_RADIO); + } + + QMediaService* create(QString const& key) + { + if (keys().contains(key)) + return new MockMediaService("MockServicePlugin2"); + else + return 0; + } + + void release(QMediaService *service) + { + delete service; + } + + QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + { + Q_UNUSED(codecs); + + if (mimeType == "audio/wav") + return QtMultimediaKit::PreferredService; + + return QtMultimediaKit::NotSupported; + } + + QStringList supportedMimeTypes() const + { + return QStringList("audio/wav"); + } + + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const + { + if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) + return QMediaServiceProviderHint::LowLatencyPlayback; + else + return 0; + } +}; + + +class MockServicePlugin3 : public QMediaServiceProviderPlugin, + public QMediaServiceSupportedDevicesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedDevicesInterface) +public: + QStringList keys() const + { + return QStringList() << + QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) << + QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE); + } + + QMediaService* create(QString const& key) + { + if (keys().contains(key)) + return new MockMediaService("MockServicePlugin3"); + else + return 0; + } + + void release(QMediaService *service) + { + delete service; + } + + QList devices(const QByteArray &service) const + { + QList res; + if (service == QByteArray(Q_MEDIASERVICE_AUDIOSOURCE)) + res << "audiosource1" << "audiosource2"; + + return res; + } + + QString deviceDescription(const QByteArray &service, const QByteArray &device) + { + if (devices(service).contains(device)) + return QString(device)+" description"; + else + return QString(); + } +}; + +class MockServicePlugin4 : public QMediaServiceProviderPlugin, + public QMediaServiceSupportedFormatsInterface, + public QMediaServiceFeaturesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedFormatsInterface) + Q_INTERFACES(QMediaServiceFeaturesInterface) +public: + QStringList keys() const + { + return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); + } + + QMediaService* create(QString const& key) + { + if (keys().contains(key)) + return new MockMediaService("MockServicePlugin4"); + else + return 0; + } + + void release(QMediaService *service) + { + delete service; + } + + QtMultimediaKit::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + { + if (codecs.contains(QLatin1String("jpeg2000"))) + return QtMultimediaKit::NotSupported; + + if (supportedMimeTypes().contains(mimeType)) + return QtMultimediaKit::ProbablySupported; + + return QtMultimediaKit::MaybeSupported; + } + + QStringList supportedMimeTypes() const + { + return QStringList() << "video/mp4" << "video/quicktime"; + } + + QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const + { + if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) + return QMediaServiceProviderHint::StreamPlayback; + else + return 0; + } +}; + + + +class MockMediaServiceProvider : public QMediaServiceProvider +{ + QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &) + { + Q_UNUSED(type); + return 0; + } + + void releaseService(QMediaService *service) + { + Q_UNUSED(service); + } +}; + + +class tst_QMediaServiceProvider : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + +private slots: + void testDefaultProviderAvailable(); + void testObtainService(); + void testHasSupport(); + void testSupportedMimeTypes(); + void testProviderHints(); + +private: + QObjectList plugins; +}; + +void tst_QMediaServiceProvider::initTestCase() +{ + plugins << new MockServicePlugin1; + plugins << new MockServicePlugin2; + plugins << new MockServicePlugin3; + plugins << new MockServicePlugin4; + + QMediaPluginLoader::setStaticPlugins(QLatin1String("mediaservice"), plugins); +} + +void tst_QMediaServiceProvider::testDefaultProviderAvailable() +{ + // Must always be a default provider available + QVERIFY(QMediaServiceProvider::defaultServiceProvider() != 0); +} + +void tst_QMediaServiceProvider::testObtainService() +{ + QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); + + if (provider == 0) + QSKIP("No default provider", SkipSingle); + + QMediaService *service = 0; + + // Player + service = provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER); + QVERIFY(service != 0); + provider->releaseService(service); +} + +void tst_QMediaServiceProvider::testHasSupport() +{ + MockMediaServiceProvider mockProvider; + QCOMPARE(mockProvider.hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()), + QtMultimediaKit::MaybeSupported); + + QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); + + if (provider == 0) + QSKIP("No default provider", SkipSingle); + + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()), + QtMultimediaKit::MaybeSupported); + + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/ogg", QStringList()), + QtMultimediaKit::ProbablySupported); + + //while the service returns PreferredService, provider should return ProbablySupported + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/wav", QStringList()), + QtMultimediaKit::ProbablySupported); + + //even while all the plugins with "hasSupport" returned NotSupported, + //MockServicePlugin3 has no "hasSupport" interface, so MaybeSupported + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/avi", + QStringList() << "mpeg4"), + QtMultimediaKit::MaybeSupported); + + QCOMPARE(provider->hasSupport(QByteArray("non existing service"), "video/ogv", QStringList()), + QtMultimediaKit::NotSupported); + + QCOMPARE(QMediaPlayer::hasSupport("video/ogv"), QtMultimediaKit::MaybeSupported); + QCOMPARE(QMediaPlayer::hasSupport("audio/ogg"), QtMultimediaKit::ProbablySupported); + QCOMPARE(QMediaPlayer::hasSupport("audio/wav"), QtMultimediaKit::ProbablySupported); + + //test low latency flag support + QCOMPARE(QMediaPlayer::hasSupport("audio/wav", QStringList(), QMediaPlayer::LowLatency), + QtMultimediaKit::ProbablySupported); + //plugin1 probably supports audio/ogg, it checked because it doesn't provide features iface + QCOMPARE(QMediaPlayer::hasSupport("audio/ogg", QStringList(), QMediaPlayer::LowLatency), + QtMultimediaKit::ProbablySupported); + //Plugin4 is not checked here, sine it's known not support low latency + QCOMPARE(QMediaPlayer::hasSupport("video/quicktime", QStringList(), QMediaPlayer::LowLatency), + QtMultimediaKit::MaybeSupported); + + //test streaming flag support + QCOMPARE(QMediaPlayer::hasSupport("video/quicktime", QStringList(), QMediaPlayer::StreamPlayback), + QtMultimediaKit::ProbablySupported); + //Plugin2 is not checked here, sine it's known not support streaming + QCOMPARE(QMediaPlayer::hasSupport("audio/wav", QStringList(), QMediaPlayer::StreamPlayback), + QtMultimediaKit::MaybeSupported); + + //ensure the correct media player plugin is chosen for mime type + QMediaPlayer simplePlayer(0, QMediaPlayer::LowLatency); + QCOMPARE(simplePlayer.service()->objectName(), QLatin1String("MockServicePlugin2")); + + QMediaPlayer mediaPlayer; + QVERIFY(mediaPlayer.service()->objectName() != QLatin1String("MockServicePlugin2")); + + QMediaPlayer streamPlayer(0, QMediaPlayer::StreamPlayback); + QCOMPARE(streamPlayer.service()->objectName(), QLatin1String("MockServicePlugin4")); +} + +void tst_QMediaServiceProvider::testSupportedMimeTypes() +{ + QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); + + if (provider == 0) + QSKIP("No default provider", SkipSingle); + + QVERIFY(provider->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)).contains("audio/ogg")); + QVERIFY(!provider->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)).contains("audio/mp3")); +} + +void tst_QMediaServiceProvider::testProviderHints() +{ + { + QMediaServiceProviderHint hint; + QVERIFY(hint.isNull()); + QCOMPARE(hint.type(), QMediaServiceProviderHint::Null); + QVERIFY(hint.device().isEmpty()); + QVERIFY(hint.mimeType().isEmpty()); + QVERIFY(hint.codecs().isEmpty()); + QCOMPARE(hint.features(), 0); + } + + { + QByteArray deviceName(QByteArray("testDevice")); + QMediaServiceProviderHint hint(deviceName); + QVERIFY(!hint.isNull()); + QCOMPARE(hint.type(), QMediaServiceProviderHint::Device); + QCOMPARE(hint.device(), deviceName); + QVERIFY(hint.mimeType().isEmpty()); + QVERIFY(hint.codecs().isEmpty()); + QCOMPARE(hint.features(), 0); + } + + { + QMediaServiceProviderHint hint(QMediaServiceProviderHint::LowLatencyPlayback); + QVERIFY(!hint.isNull()); + QCOMPARE(hint.type(), QMediaServiceProviderHint::SupportedFeatures); + QVERIFY(hint.device().isEmpty()); + QVERIFY(hint.mimeType().isEmpty()); + QVERIFY(hint.codecs().isEmpty()); + QCOMPARE(hint.features(), QMediaServiceProviderHint::LowLatencyPlayback); + } + + { + QString mimeType(QLatin1String("video/ogg")); + QStringList codecs; + codecs << "theora" << "vorbis"; + + QMediaServiceProviderHint hint(mimeType,codecs); + QVERIFY(!hint.isNull()); + QCOMPARE(hint.type(), QMediaServiceProviderHint::ContentType); + QVERIFY(hint.device().isEmpty()); + QCOMPARE(hint.mimeType(), mimeType); + QCOMPARE(hint.codecs(), codecs); + + QMediaServiceProviderHint hint2(hint); + + QVERIFY(!hint2.isNull()); + QCOMPARE(hint2.type(), QMediaServiceProviderHint::ContentType); + QVERIFY(hint2.device().isEmpty()); + QCOMPARE(hint2.mimeType(), mimeType); + QCOMPARE(hint2.codecs(), codecs); + + QMediaServiceProviderHint hint3; + QVERIFY(hint3.isNull()); + hint3 = hint; + QVERIFY(!hint3.isNull()); + QCOMPARE(hint3.type(), QMediaServiceProviderHint::ContentType); + QVERIFY(hint3.device().isEmpty()); + QCOMPARE(hint3.mimeType(), mimeType); + QCOMPARE(hint3.codecs(), codecs); + + QCOMPARE(hint, hint2); + QCOMPARE(hint3, hint2); + + QMediaServiceProviderHint hint4(mimeType,codecs); + QCOMPARE(hint, hint4); + + QMediaServiceProviderHint hint5(mimeType,QStringList()); + QVERIFY(hint != hint5); + } +} + +QTEST_MAIN(tst_QMediaServiceProvider) + +#include "tst_qmediaserviceprovider.moc" diff --git a/tests/auto/qmediatimerange/qmediatimerange.pro b/tests/auto/qmediatimerange/qmediatimerange.pro new file mode 100644 index 000000000..004bf373d --- /dev/null +++ b/tests/auto/qmediatimerange/qmediatimerange.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qmediatimerange +# CONFIG += testcase + +SOURCES += tst_qmediatimerange.cpp + diff --git a/tests/auto/qmediatimerange/tst_qmediatimerange.cpp b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp new file mode 100644 index 000000000..2dfdd1be5 --- /dev/null +++ b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp @@ -0,0 +1,739 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QMediaTimeRange: public QObject +{ + Q_OBJECT + +public slots: + +private slots: + void testCtor(); + void testGetters(); + void testAssignment(); + void testNormalize(); + void testTranslated(); + void testEarliestLatest(); + void testContains(); + void testAddInterval(); + void testAddTimeRange(); + void testRemoveInterval(); + void testRemoveTimeRange(); + void testClear(); + void testComparisons(); + void testArithmetic(); +}; + +void tst_QMediaTimeRange::testCtor() +{ + // Default Ctor + QMediaTimeRange a; + QVERIFY(a.isEmpty()); + + // (qint, qint) Ctor + QMediaTimeRange b(10, 20); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 20); + + // Interval Ctor + QMediaTimeRange c(QMediaTimeInterval(30, 40)); + + QVERIFY(!c.isEmpty()); + QVERIFY(c.isContinuous()); + QVERIFY(c.earliestTime() == 30); + QVERIFY(c.latestTime() == 40); + + // Abnormal Interval Ctor + QMediaTimeRange d(QMediaTimeInterval(20, 10)); + + QVERIFY(d.isEmpty()); + + // Copy Ctor + QMediaTimeRange e(b); + + QVERIFY(!e.isEmpty()); + QVERIFY(e.isContinuous()); + QVERIFY(e.earliestTime() == 10); + QVERIFY(e.latestTime() == 20); +} + +void tst_QMediaTimeRange::testGetters() +{ + QMediaTimeRange x; + + // isEmpty + QVERIFY(x.isEmpty()); + + x.addInterval(10, 20); + + // isEmpty + isContinuous + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + + x.addInterval(30, 40); + + // isEmpty + isContinuous + intervals + start + end + QVERIFY(!x.isEmpty()); + QVERIFY(!x.isContinuous()); + QVERIFY(x.intervals().count() == 2); + QVERIFY(x.intervals()[0].start() == 10); + QVERIFY(x.intervals()[0].end() == 20); + QVERIFY(x.intervals()[1].start() == 30); + QVERIFY(x.intervals()[1].end() == 40); +} + +void tst_QMediaTimeRange::testAssignment() +{ + QMediaTimeRange x; + + // Range Assignment + x = QMediaTimeRange(10, 20); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 20); + + // Interval Assignment + x = QMediaTimeInterval(30, 40); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 30); + QVERIFY(x.latestTime() == 40); + + // Shared Data Check + QMediaTimeRange y; + + y = x; + y.addInterval(10, 20); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 30); + QVERIFY(x.latestTime() == 40); +} + +void tst_QMediaTimeRange::testNormalize() +{ + QMediaTimeInterval x(20, 10); + + QVERIFY(!x.isNormal()); + + x = x.normalized(); + + QVERIFY(x.isNormal()); + QVERIFY(x.start() == 10); + QVERIFY(x.end() == 20); +} + +void tst_QMediaTimeRange::testTranslated() +{ + QMediaTimeInterval x(10, 20); + x = x.translated(10); + + QVERIFY(x.start() == 20); + QVERIFY(x.end() == 30); +} + +void tst_QMediaTimeRange::testEarliestLatest() +{ + // Test over a single interval + QMediaTimeRange x(30, 40); + + QVERIFY(x.earliestTime() == 30); + QVERIFY(x.latestTime() == 40); + + // Test over multiple intervals + x.addInterval(50, 60); + + QVERIFY(x.earliestTime() == 30); + QVERIFY(x.latestTime() == 60); +} + +void tst_QMediaTimeRange::testContains() +{ + // Test over a single interval + QMediaTimeRange x(10, 20); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.contains(15)); + QVERIFY(x.contains(10)); + QVERIFY(x.contains(20)); + QVERIFY(!x.contains(25)); + + // Test over multiple intervals + x.addInterval(40, 50); + + QVERIFY(!x.isEmpty()); + QVERIFY(!x.isContinuous()); + QVERIFY(x.contains(15)); + QVERIFY(x.contains(45)); + QVERIFY(!x.contains(30)); + + // Test over a concrete interval + QMediaTimeInterval y(10, 20); + QVERIFY(y.contains(15)); + QVERIFY(y.contains(10)); + QVERIFY(y.contains(20)); + QVERIFY(!y.contains(25)); +} + +void tst_QMediaTimeRange::testAddInterval() +{ + // All intervals Overlap + QMediaTimeRange x; + x.addInterval(10, 40); + x.addInterval(30, 50); + x.addInterval(20, 60); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 60); + + // 1 adjacent interval, 1 encompassed interval + x = QMediaTimeRange(); + x.addInterval(10, 40); + x.addInterval(20, 30); + x.addInterval(41, 50); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 50); + + // 1 overlapping interval, 1 disjoint interval + x = QMediaTimeRange(); + x.addInterval(10, 30); + x.addInterval(20, 40); + x.addInterval(50, 60); + + QVERIFY(!x.isEmpty()); + QVERIFY(!x.isContinuous()); + QVERIFY(x.intervals().count() == 2); + QVERIFY(x.intervals()[0].start() == 10); + QVERIFY(x.intervals()[0].end() == 40); + QVERIFY(x.intervals()[1].start() == 50); + QVERIFY(x.intervals()[1].end() == 60); + + // Identical Add + x = QMediaTimeRange(); + x.addInterval(10, 20); + x.addInterval(10, 20); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 20); + + // Multi-Merge + x = QMediaTimeRange(); + x.addInterval(10, 20); + x.addInterval(30, 40); + x.addInterval(50, 60); + x.addInterval(15, 55); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 60); + + // Interval Parameter - All intervals Overlap + x = QMediaTimeRange(); + x.addInterval(QMediaTimeInterval(10, 40)); + x.addInterval(QMediaTimeInterval(30, 50)); + x.addInterval(QMediaTimeInterval(20, 60)); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 60); + + // Interval Parameter - Abnormal Interval + x = QMediaTimeRange(); + x.addInterval(QMediaTimeInterval(20, 10)); + + QVERIFY(x.isEmpty()); +} + +void tst_QMediaTimeRange::testAddTimeRange() +{ + // Add Time Range uses Add Interval internally, + // so in this test the focus is on combinations of number + // of intervals added, rather than the different types of + // merges which can occur. + QMediaTimeRange a, b; + + // Add Single into Single + a = QMediaTimeRange(10, 30); + b = QMediaTimeRange(20, 40); + + b.addTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 40); + + // Add Multiple into Single + a = QMediaTimeRange(); + a.addInterval(10, 30); + a.addInterval(40, 60); + + b = QMediaTimeRange(20, 50); + + b.addTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 60); + + // Add Single into Multiple + a = QMediaTimeRange(20, 50); + + b = QMediaTimeRange(); + b.addInterval(10, 30); + b.addInterval(40, 60); + + b.addTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 60); + + // Add Multiple into Multiple + a = QMediaTimeRange(); + a.addInterval(10, 30); + a.addInterval(40, 70); + a.addInterval(80, 100); + + b = QMediaTimeRange(); + b.addInterval(20, 50); + b.addInterval(60, 90); + + b.addTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 100); + + // Add Nothing to Single + a = QMediaTimeRange(); + b = QMediaTimeRange(10, 20); + + b.addTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 20); + + // Add Single to Nothing + a = QMediaTimeRange(10, 20); + b = QMediaTimeRange(); + + b.addTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 20); + + // Add Nothing to Nothing + a = QMediaTimeRange(); + b = QMediaTimeRange(); + + b.addTimeRange(a); + + QVERIFY(b.isEmpty()); +} + +void tst_QMediaTimeRange::testRemoveInterval() +{ + // Removing an interval, causing a split + QMediaTimeRange x; + x.addInterval(10, 50); + x.removeInterval(20, 40); + + QVERIFY(!x.isEmpty()); + QVERIFY(!x.isContinuous()); + QVERIFY(x.intervals().count() == 2); + QVERIFY(x.intervals()[0].start() == 10); + QVERIFY(x.intervals()[0].end() == 19); + QVERIFY(x.intervals()[1].start() == 41); + QVERIFY(x.intervals()[1].end() == 50); + + // Removing an interval, causing a deletion + x = QMediaTimeRange(); + x.addInterval(20, 30); + x.removeInterval(10, 40); + + QVERIFY(x.isEmpty()); + + // Removing an interval, causing a tail trim + x = QMediaTimeRange(); + x.addInterval(20, 40); + x.removeInterval(30, 50); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 20); + QVERIFY(x.latestTime() == 29); + + // Removing an interval, causing a head trim + x = QMediaTimeRange(); + x.addInterval(20, 40); + x.removeInterval(10, 30); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 31); + QVERIFY(x.latestTime() == 40); + + // Identical Remove + x = QMediaTimeRange(); + x.addInterval(10, 20); + x.removeInterval(10, 20); + + QVERIFY(x.isEmpty()); + + // Multi-Trim + x = QMediaTimeRange(); + x.addInterval(10, 20); + x.addInterval(30, 40); + x.removeInterval(15, 35); + + QVERIFY(!x.isEmpty()); + QVERIFY(!x.isContinuous()); + QVERIFY(x.intervals().count() == 2); + QVERIFY(x.intervals()[0].start() == 10); + QVERIFY(x.intervals()[0].end() == 14); + QVERIFY(x.intervals()[1].start() == 36); + QVERIFY(x.intervals()[1].end() == 40); + + // Multi-Delete + x = QMediaTimeRange(); + x.addInterval(10, 20); + x.addInterval(30, 40); + x.addInterval(50, 60); + x.removeInterval(10, 60); + + QVERIFY(x.isEmpty()); + + // Interval Parameter - Removing an interval, causing a split + x = QMediaTimeRange(); + x.addInterval(10, 50); + x.removeInterval(QMediaTimeInterval(20, 40)); + + QVERIFY(!x.isEmpty()); + QVERIFY(!x.isContinuous()); + QVERIFY(x.intervals().count() == 2); + QVERIFY(x.intervals()[0].start() == 10); + QVERIFY(x.intervals()[0].end() == 19); + QVERIFY(x.intervals()[1].start() == 41); + QVERIFY(x.intervals()[1].end() == 50); + + // Interval Parameter - Abnormal Interval + x = QMediaTimeRange(); + x.addInterval(10, 40); + x.removeInterval(QMediaTimeInterval(30, 20)); + + QVERIFY(!x.isEmpty()); + QVERIFY(x.isContinuous()); + QVERIFY(x.earliestTime() == 10); + QVERIFY(x.latestTime() == 40); +} + +void tst_QMediaTimeRange::testRemoveTimeRange() +{ + // Remove Time Range uses Remove Interval internally, + // so in this test the focus is on combinations of number + // of intervals removed, rather than the different types of + // deletions which can occur. + QMediaTimeRange a, b; + + // Remove Single from Single + a = QMediaTimeRange(10, 30); + b = QMediaTimeRange(20, 40); + + b.removeTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 31); + QVERIFY(b.latestTime() == 40); + + // Remove Multiple from Single + a = QMediaTimeRange(); + a.addInterval(10, 30); + a.addInterval(40, 60); + + b = QMediaTimeRange(20, 50); + + b.removeTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 31); + QVERIFY(b.latestTime() == 39); + + // Remove Single from Multiple + a = QMediaTimeRange(20, 50); + + b = QMediaTimeRange(); + b.addInterval(10, 30); + b.addInterval(40, 60); + + b.removeTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(!b.isContinuous()); + QVERIFY(b.intervals().count() == 2); + QVERIFY(b.intervals()[0].start() == 10); + QVERIFY(b.intervals()[0].end() == 19); + QVERIFY(b.intervals()[1].start() == 51); + QVERIFY(b.intervals()[1].end() == 60); + + // Remove Multiple from Multiple + a = QMediaTimeRange(); + a.addInterval(20, 50); + a.addInterval(50, 90); + + + b = QMediaTimeRange(); + b.addInterval(10, 30); + b.addInterval(40, 70); + b.addInterval(80, 100); + + b.removeTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(!b.isContinuous()); + QVERIFY(b.intervals().count() == 2); + QVERIFY(b.intervals()[0].start() == 10); + QVERIFY(b.intervals()[0].end() == 19); + QVERIFY(b.intervals()[1].start() == 91); + QVERIFY(b.intervals()[1].end() == 100); + + // Remove Nothing from Single + a = QMediaTimeRange(); + b = QMediaTimeRange(10, 20); + + b.removeTimeRange(a); + + QVERIFY(!b.isEmpty()); + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 10); + QVERIFY(b.latestTime() == 20); + + // Remove Single from Nothing + a = QMediaTimeRange(10, 20); + b = QMediaTimeRange(); + + b.removeTimeRange(a); + + QVERIFY(b.isEmpty()); + + // Remove Nothing from Nothing + a = QMediaTimeRange(); + b = QMediaTimeRange(); + + b.removeTimeRange(a); + + QVERIFY(b.isEmpty()); +} + +void tst_QMediaTimeRange::testClear() +{ + QMediaTimeRange x; + + // Clear Nothing + x.clear(); + + QVERIFY(x.isEmpty()); + + // Clear Single + x = QMediaTimeRange(10, 20); + x.clear(); + + QVERIFY(x.isEmpty()); + + // Clear Multiple + x = QMediaTimeRange(); + x.addInterval(10, 20); + x.addInterval(30, 40); + x.clear(); + + QVERIFY(x.isEmpty()); +} + +void tst_QMediaTimeRange::testComparisons() +{ + // Interval equality + QVERIFY(QMediaTimeInterval(10, 20) == QMediaTimeInterval(10, 20)); + QVERIFY(QMediaTimeInterval(10, 20) != QMediaTimeInterval(10, 30)); + QVERIFY(!(QMediaTimeInterval(10, 20) != QMediaTimeInterval(10, 20))); + QVERIFY(!(QMediaTimeInterval(10, 20) == QMediaTimeInterval(10, 30))); + + // Time range equality - Single Interval + QMediaTimeRange a(10, 20), b(20, 30), c(10, 20); + + QVERIFY(a == c); + QVERIFY(!(a == b)); + QVERIFY(a != b); + QVERIFY(!(a != c)); + + // Time Range Equality - Multiple Intervals + QMediaTimeRange x, y, z; + + x.addInterval(10, 20); + x.addInterval(30, 40); + x.addInterval(50, 60); + + y.addInterval(10, 20); + y.addInterval(35, 45); + y.addInterval(50, 60); + + z.addInterval(10, 20); + z.addInterval(30, 40); + z.addInterval(50, 60); + + QVERIFY(x == z); + QVERIFY(!(x == y)); + QVERIFY(x != y); + QVERIFY(!(x != z)); +} + +void tst_QMediaTimeRange::testArithmetic() +{ + QMediaTimeRange a(10, 20), b(20, 30); + + // Test += + a += b; + + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 30); + + // Test -= + a -= b; + + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 19); + + // Test += and -= on intervals + a -= QMediaTimeInterval(10, 20); + a += QMediaTimeInterval(40, 50); + + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 40); + QVERIFY(a.latestTime() == 50); + + // Test Interval + Interval + a = QMediaTimeInterval(10, 20) + QMediaTimeInterval(20, 30); + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 30); + + // Test Range + Interval + a = a + QMediaTimeInterval(30, 40); + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 40); + + // Test Interval + Range + a = QMediaTimeInterval(40, 50) + a; + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 50); + + // Test Range + Range + a = a + QMediaTimeRange(50, 60); + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 60); + + // Test Range - Interval + a = a - QMediaTimeInterval(50, 60); + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 49); + + // Test Range - Range + a = a - QMediaTimeRange(40, 50); + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 39); + + // Test Interval - Range + b = QMediaTimeInterval(0, 20) - a; + QVERIFY(b.isContinuous()); + QVERIFY(b.earliestTime() == 0); + QVERIFY(b.latestTime() == 9); + + // Test Interval - Interval + a = QMediaTimeInterval(10, 20) - QMediaTimeInterval(15, 30); + QVERIFY(a.isContinuous()); + QVERIFY(a.earliestTime() == 10); + QVERIFY(a.latestTime() == 14); +} + +QTEST_MAIN(tst_QMediaTimeRange) + +#include "tst_qmediatimerange.moc" diff --git a/tests/auto/qpaintervideosurface/qpaintervideosurface.pro b/tests/auto/qpaintervideosurface/qpaintervideosurface.pro new file mode 100644 index 000000000..a6c686d6d --- /dev/null +++ b/tests/auto/qpaintervideosurface/qpaintervideosurface.pro @@ -0,0 +1,11 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qpaintervideosurface +# CONFIG += testcase + +contains(QT_CONFIG, opengl): QT += opengl + +SOURCES += tst_qpaintervideosurface.cpp + diff --git a/tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp new file mode 100644 index 000000000..6c220c3db --- /dev/null +++ b/tests/auto/qpaintervideosurface/tst_qpaintervideosurface.cpp @@ -0,0 +1,1249 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include +#include + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#include +#include +#endif + +QT_USE_NAMESPACE +class tst_QPainterVideoSurface : public QObject +{ + Q_OBJECT +private slots: + void cleanup() {} + void cleanupTestCase() {} + + void colors(); + + void supportedFormat_data(); + void supportedFormat(); + + void present_data(); + void present(); + void presentOpaqueFrame(); + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + + void shaderType(); + + void shaderTypeStarted_data(); + void shaderTypeStarted(); + + void shaderSupportedFormat_data(); + void shaderSupportedFormat(); + + void shaderPresent_data(); + void shaderPresent(); + void shaderPresentOpaqueFrame_data(); + void shaderPresentOpaqueFrame(); + void shaderPresentGLFrame_data(); + void shaderPresentGLFrame(); +#endif +}; + +Q_DECLARE_METATYPE(const uchar *) + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +Q_DECLARE_METATYPE(QPainterVideoSurface::ShaderType); + +class QtTestGLVideoBuffer : public QAbstractVideoBuffer +{ +public: + QtTestGLVideoBuffer() + : QAbstractVideoBuffer(GLTextureHandle) + , m_textureId(0) + { + glGenTextures(1, &m_textureId); + } + + ~QtTestGLVideoBuffer() + { + glDeleteTextures(1, &m_textureId); + } + + GLuint textureId() const { return m_textureId; } + + QVariant handle() const { return m_textureId; } + + uchar *map(MapMode, int *, int *) { return 0; } + void unmap() {} + MapMode mapMode() const { return NotMapped; } + +private: + GLuint m_textureId; +}; + +#endif + +class QtTestOpaqueVideoBuffer : public QAbstractVideoBuffer +{ +public: + QtTestOpaqueVideoBuffer() + : QAbstractVideoBuffer(UserHandle) + {} + + uchar *map(MapMode, int *, int *) { return 0; } + void unmap() {} + MapMode mapMode() const { return NotMapped; } +}; + +void tst_QPainterVideoSurface::colors() +{ + QPainterVideoSurface surface; + + QCOMPARE(surface.brightness(), 0); + QCOMPARE(surface.contrast(), 0); + QCOMPARE(surface.hue(), 0); + QCOMPARE(surface.saturation(), 0); + + surface.setBrightness(56); + QCOMPARE(surface.brightness(), 56); + + surface.setContrast(43); + QCOMPARE(surface.contrast(), 43); + + surface.setHue(-84); + QCOMPARE(surface.hue(), -84); + + surface.setSaturation(100); + QCOMPARE(surface.saturation(), 100); +} + +static const uchar rgb32ImageData[] = +{ + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00 +}; + +static const uchar argb32ImageData[] = +{ + 0x00, 0xff, 0x00, 0x00, 0xcc, 0x00, 0xff, 0xcc, + 0x77, 0x00, 0x00, 0x77, 0x00, 0xff, 0xff, 0x00 +}; + +static const uchar rgb24ImageData[] = +{ + 0x00, 0xff, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, + 0xcc, 0x00, 0xcc, 0x77, 0xff, 0x77, 0x00, 0x00 +}; + +static const uchar rgb565ImageData[] = +{ + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00 +}; + +static const uchar yuvPlanarImageData[] = +{ + 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0x0f, 0x0f, 0xff, 0x0f, 0x00, + 0x00, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0x00, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, + 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0x0f, + 0x00, 0x0f, 0xff, 0x0f, 0x0f, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x0f, 0x0f, 0x00, + 0x0f, 0x00, 0x00, 0x0f, + 0x0f, 0x00, 0x00, 0x0f, + 0x00, 0x0f, 0x0f, 0x00, + 0x00, 0x0f, 0x0f, 0x00, + 0x0f, 0x00, 0x00, 0x0f, + 0x0f, 0x00, 0x00, 0x0f, + 0x00, 0x0f, 0x0f, 0x00, +}; + +void tst_QPainterVideoSurface::supportedFormat_data() +{ + QTest::addColumn("handleType"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("frameSize"); + QTest::addColumn("supportedPixelFormat"); + QTest::addColumn("supportedFormat"); + + QTest::newRow("rgb32 640x480") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB32 + << QSize(640, 480) + << true + << true; + QTest::newRow("rgb32 -640x480") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB32 + << QSize(-640, 480) + << true + << false; + QTest::newRow("rgb24 1024x768") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB24 + << QSize(1024, 768) +#ifndef QT_OPENGL_ES + << true + << true; +#else + << false + << false; +#endif + QTest::newRow("rgb24 -1024x-768") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB24 + << QSize(-1024, -768) +#ifndef QT_OPENGL_ES + << true +#else + << false +#endif + << false; + QTest::newRow("rgb565 0x0") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB565 + << QSize(0, 0) + << true + << false; + QTest::newRow("YUV420P 640x480") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_YUV420P + << QSize(640, 480) + << false + << false; + QTest::newRow("YUV420P 640x-480") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_YUV420P + << QSize(640, -480) + << false + << false; + QTest::newRow("Y8 640x480") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_Y8 + << QSize(640, 480) + << false + << false; + QTest::newRow("Texture: rgb32 640x480") + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB32 + << QSize(640, 480) + << false + << false; + QTest::newRow("Texture: rgb32 -640x480") + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB32 + << QSize(-640, 480) + << false + << false; + QTest::newRow("rgb565 32x32") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB565 + << QSize(32, 32) + << true + << true; + QTest::newRow("rgb565 0x0") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB565 + << QSize(0, 0) + << true + << false; + QTest::newRow("argb32 256x256") + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_ARGB32 + << QSize(256, 256) + << true + << true; + QTest::newRow("Texture: rgb24 1024x768") + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB24 + << QSize(1024, 768) + << false + << false; + QTest::newRow("Texture: rgb24 -1024x-768") + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB24 + << QSize(-1024, -768) + << false + << false; + QTest::newRow("Texture: YUV420P 640x480") + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_YUV420P + << QSize(640, 480) + << false + << false; + QTest::newRow("Texture: YUV420P 640x-480") + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_YUV420P + << QSize(640, -480) + << false + << false; + QTest::newRow("User Buffer: rgb32 256x256") + << QAbstractVideoBuffer::UserHandle + << QVideoFrame::Format_RGB32 + << QSize(256, 256) + << false + << false; +#if !defined(Q_OS_MAC) + QTest::newRow("Pixmap: rgb32 640x480") + << QAbstractVideoBuffer::QPixmapHandle + << QVideoFrame::Format_RGB32 + << QSize(640, 480) + << true + << true; + QTest::newRow("Pixmap: YUV420P 640x480") + << QAbstractVideoBuffer::QPixmapHandle + << QVideoFrame::Format_YUV420P + << QSize(640, 480) + << false + << true; +#endif +} + +void tst_QPainterVideoSurface::supportedFormat() +{ + QFETCH(QAbstractVideoBuffer::HandleType, handleType); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(QSize, frameSize); + QFETCH(bool, supportedPixelFormat); + QFETCH(bool, supportedFormat); + + QPainterVideoSurface surface; + + const QList pixelFormats = surface.supportedPixelFormats(handleType); + + QCOMPARE(pixelFormats.contains(pixelFormat), QBool(supportedPixelFormat)); + + QVideoSurfaceFormat format(frameSize, pixelFormat, handleType); + + QCOMPARE(surface.isFormatSupported(format), supportedFormat); + QCOMPARE(surface.start(format), supportedFormat); +} + +void tst_QPainterVideoSurface::present_data() +{ + QTest::addColumn("pixelFormatA"); + QTest::addColumn("frameSizeA"); + QTest::addColumn("frameDataA"); + QTest::addColumn("bytesA"); + QTest::addColumn("bytesPerLineA"); + QTest::addColumn("pixelFormatB"); + QTest::addColumn("frameSizeB"); + QTest::addColumn("frameDataB"); + QTest::addColumn("bytesB"); + QTest::addColumn("bytesPerLineB"); + + QTest::newRow("rgb32 -> argb32") + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8 + << QVideoFrame::Format_ARGB32 + << QSize(2, 2) + << static_cast(argb32ImageData) + << int(sizeof(argb32ImageData)) + << 8; + +#ifndef QT_OPENGL_ES + QTest::newRow("rgb32 -> rgb24") + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8 + << QVideoFrame::Format_RGB24 + << QSize(2, 2) + << static_cast(rgb24ImageData) + << int(sizeof(rgb24ImageData)) + << 8; +#endif + + QTest::newRow("rgb32 -> rgb565") + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8 + << QVideoFrame::Format_RGB565 + << QSize(2, 2) + << static_cast(rgb565ImageData) + << int(sizeof(rgb565ImageData)) + << 4; + +#ifndef QT_OPENGL_ES + QTest::newRow("rgb24 -> rgb565") + << QVideoFrame::Format_RGB24 + << QSize(2, 2) + << static_cast(rgb24ImageData) + << int(sizeof(rgb24ImageData)) + << 8 + << QVideoFrame::Format_RGB565 + << QSize(2, 2) + << static_cast(rgb565ImageData) + << int(sizeof(rgb565ImageData)) + << 4; +#endif +} + +void tst_QPainterVideoSurface::present() +{ + QFETCH(QVideoFrame::PixelFormat, pixelFormatA); + QFETCH(QSize, frameSizeA); + QFETCH(const uchar *, frameDataA); + QFETCH(int, bytesA); + QFETCH(int, bytesPerLineA); + QFETCH(QVideoFrame::PixelFormat, pixelFormatB); + QFETCH(QSize, frameSizeB); + QFETCH(const uchar *, frameDataB); + QFETCH(int, bytesB); + QFETCH(int, bytesPerLineB); + + QPainterVideoSurface surface; + + QImage image(320, 240, QImage::Format_RGB32); + + QSignalSpy frameSpy(&surface, SIGNAL(frameChanged())); + + const QList pixelFormats = surface.supportedPixelFormats(); + + { // Test painting before started. + QPainter painter(&image); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + + QVideoSurfaceFormat formatA(frameSizeA, pixelFormatA); + + QVERIFY(surface.start(formatA)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + { // Test painting before receiving a frame. + QPainter painter(&image); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.error(), QAbstractVideoSurface::NoError); + + QVideoFrame frameA(bytesA, frameSizeA, bytesPerLineA, pixelFormatA); + + frameA.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frameA.bits(), frameDataA, frameA.mappedBytes()); + frameA.unmap(); + + QVERIFY(surface.present(frameA)); + QCOMPARE(surface.isReady(), false); + QCOMPARE(frameSpy.count(), 1); + + { + QPainter painter(&image); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), false); + + { // Test repainting before receiving another frame. + QPainter painter(&image); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), false); + + // Not ready. + QVERIFY(!surface.present(frameA)); + QCOMPARE(frameSpy.count(), 1); + + surface.setReady(true); + QCOMPARE(surface.isReady(), true); + QVERIFY(surface.present(frameA)); + QCOMPARE(frameSpy.count(), 2); + + // Try switching to a different format after starting. + QVideoSurfaceFormat formatB(frameSizeB, pixelFormatB); + + QVERIFY(surface.start(formatB)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + QVideoFrame frameB(bytesB, frameSizeB, bytesPerLineB, pixelFormatB); + + frameB.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frameB.bits(), frameDataB, frameB.mappedBytes()); + frameB.unmap(); + + QVERIFY(surface.present(frameB)); + QCOMPARE(surface.isReady(), false); + QCOMPARE(frameSpy.count(), 3); + + { + QPainter painter(&image); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QVERIFY(surface.isActive()); + + surface.stop(); + + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + + // Try presenting a frame while stopped. + QVERIFY(!surface.present(frameB)); + QCOMPARE(surface.isReady(), false); + QCOMPARE(surface.error(), QAbstractVideoSurface::StoppedError); + + // Try presenting a frame with a different format. + QVERIFY(surface.start(formatB)); + QVERIFY(!surface.present(frameA)); + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError); +} + +void tst_QPainterVideoSurface::presentOpaqueFrame() +{ + QPainterVideoSurface surface; + + QImage image(320, 240, QImage::Format_RGB32); + + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + + QVERIFY(surface.start(format)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + QVideoFrame frame(new QtTestOpaqueVideoBuffer, QSize(64, 64), QVideoFrame::Format_RGB32); + + if (surface.present(frame)) { + QPainter painter(&image); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError); +} + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + +void tst_QPainterVideoSurface::shaderType() +{ + QPainterVideoSurface surface; + QGLWidget widget; + widget.makeCurrent(); + + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(surface.supportedShaderTypes(), QPainterVideoSurface::NoShaders); + + surface.setGLContext(const_cast(widget.context())); + QCOMPARE(surface.glContext(), widget.context()); + + { + QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged())); + + surface.setShaderType(QPainterVideoSurface::NoShaders); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(spy.count(), 0); + } + +#ifndef QT_OPENGL_ES + if (surface.supportedShaderTypes() & QPainterVideoSurface::FragmentProgramShader) { + QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged())); + + surface.setShaderType(QPainterVideoSurface::FragmentProgramShader); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::FragmentProgramShader); + QCOMPARE(spy.count(), 1); + + surface.setShaderType(QPainterVideoSurface::FragmentProgramShader); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::FragmentProgramShader); + QCOMPARE(spy.count(), 1); + } +#endif + + if (surface.supportedShaderTypes() & QPainterVideoSurface::GlslShader) { + QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged())); + + surface.setShaderType(QPainterVideoSurface::GlslShader); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::GlslShader); + QCOMPARE(spy.count(), 1); + + surface.setShaderType(QPainterVideoSurface::GlslShader); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::GlslShader); + QCOMPARE(spy.count(), 1); + } + + { + QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged())); + + surface.setGLContext(const_cast(widget.context())); + QCOMPARE(surface.glContext(), widget.context()); + QCOMPARE(spy.count(), 0); + } + + surface.setGLContext(0); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(surface.supportedShaderTypes(), QPainterVideoSurface::NoShaders); + + { + QSignalSpy spy(&surface, SIGNAL(supportedFormatsChanged())); + + surface.setShaderType(QPainterVideoSurface::NoShaders); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(spy.count(), 0); + +#ifndef QT_OPENGL_ES + surface.setShaderType(QPainterVideoSurface::FragmentProgramShader); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(spy.count(), 0); +#endif + + surface.setShaderType(QPainterVideoSurface::GlslShader); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(spy.count(), 0); + } +} + +void tst_QPainterVideoSurface::shaderTypeStarted_data() +{ + QTest::addColumn("shaderType"); + +#ifndef QT_OPENGL_ES + QTest::newRow("ARBfp") + << QPainterVideoSurface::FragmentProgramShader; +#endif + QTest::newRow("GLSL") + << QPainterVideoSurface::GlslShader; +} + +void tst_QPainterVideoSurface::shaderTypeStarted() +{ + QFETCH(QPainterVideoSurface::ShaderType, shaderType); + + QGLWidget widget; + widget.makeCurrent(); + + QPainterVideoSurface surface; + + surface.setGLContext(const_cast(widget.context())); + + if (!(surface.supportedShaderTypes() & shaderType)) + QSKIP("Shader type unsupported on this platform", SkipSingle); + + surface.setShaderType(shaderType); + QCOMPARE(surface.shaderType(), shaderType); + + QVERIFY(surface.start(QVideoSurfaceFormat(QSize(640, 480), QVideoFrame::Format_RGB32))); + { + QSignalSpy spy(&surface, SIGNAL(activeChanged(bool))); + + surface.setShaderType(QPainterVideoSurface::NoShaders); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(surface.isActive(), false); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().value(0).toBool(), false); + } + + QVERIFY(surface.start(QVideoSurfaceFormat(QSize(640, 480), QVideoFrame::Format_RGB32))); + { + QSignalSpy spy(&surface, SIGNAL(activeChanged(bool))); + + surface.setShaderType(QPainterVideoSurface::NoShaders); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(surface.isActive(), true); + QCOMPARE(spy.count(), 0); + + surface.setShaderType(shaderType); + QCOMPARE(surface.shaderType(), shaderType); + QCOMPARE(surface.isActive(), false); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().value(0).toBool(), false); + } + + QVERIFY(surface.start(QVideoSurfaceFormat(QSize(640, 480), QVideoFrame::Format_RGB32))); + { + QSignalSpy spy(&surface, SIGNAL(activeChanged(bool))); + + surface.setShaderType(shaderType); + QCOMPARE(surface.shaderType(), shaderType); + QCOMPARE(surface.isActive(), true); + QCOMPARE(spy.count(), 0); + + surface.setGLContext(0); + QCOMPARE(surface.shaderType(), QPainterVideoSurface::NoShaders); + QCOMPARE(surface.isActive(), false); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().value(0).toBool(), false); + } +} + +void tst_QPainterVideoSurface::shaderSupportedFormat_data() +{ + QTest::addColumn("shaderType"); + QTest::addColumn("handleType"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("frameSize"); + QTest::addColumn("supportedPixelFormat"); + QTest::addColumn("supportedFormat"); + + QList > types; + + +#ifndef QT_OPENGL_ES + types << qMakePair(QPainterVideoSurface::FragmentProgramShader, QByteArray("ARBfp: ")); +#endif + types << qMakePair(QPainterVideoSurface::GlslShader, QByteArray("GLSL: ")); + + QPair type; + foreach (type, types) { + QTest::newRow((type.second + "rgb32 640x480").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB32 + << QSize(640, 480) + << true + << true; + QTest::newRow((type.second + "rgb32 -640x480").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB32 + << QSize(-640, 480) + << true + << false; + QTest::newRow((type.second + "rgb565 32x32").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB565 + << QSize(32, 32) + << true + << true; + QTest::newRow((type.second + "rgb565 0x0").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB565 + << QSize(0, 0) + << true + << false; + QTest::newRow((type.second + "argb32 256x256").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_ARGB32 + << QSize(256, 256) + << true + << true; + QTest::newRow((type.second + "rgb24 1024x768").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB24 + << QSize(1024, 768) +#ifndef QT_OPENGL_ES + << true + << true; +#else + << false + << false; +#endif + QTest::newRow((type.second + "rgb24 -1024x-768").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_RGB24 + << QSize(-1024, -768) +#ifndef QT_OPENGL_ES + << true +#else + << false +#endif + << false; +#ifndef Q_WS_MAC + QTest::newRow((type.second + "YUV420P 640x480").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_YUV420P + << QSize(640, 480) + << true + << true; + QTest::newRow((type.second + "YUV420P 640x-480").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_YUV420P + << QSize(640, -480) + << true + << false; +#endif + QTest::newRow((type.second + "Y8 640x480").constData()) + << type.first + << QAbstractVideoBuffer::NoHandle + << QVideoFrame::Format_Y8 + << QSize(640, 480) + << false + << false; + QTest::newRow((type.second + "Texture: rgb32 640x480").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB32 + << QSize(640, 480) + << true + << true; + QTest::newRow((type.second + "Texture: rgb32 -640x480").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB32 + << QSize(-640, 480) + << true + << false; +#ifndef Q_WS_MAC + QTest::newRow((type.second + "Texture: rgb565 32x32").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB565 + << QSize(32, 32) + << false + << false; + QTest::newRow((type.second + "Texture: rgb565 0x0").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB565 + << QSize(0, 0) + << false + << false; +#endif + QTest::newRow((type.second + "Texture argb32 256x256").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_ARGB32 + << QSize(256, 256) + << true + << true; +#ifndef Q_WS_MAC + QTest::newRow((type.second + "Texture: rgb24 1024x768").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB24 + << QSize(1024, 768) + << false + << false; + QTest::newRow((type.second + "Texture: rgb24 -1024x-768").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_RGB24 + << QSize(-1024, -768) + << false + << false; + QTest::newRow((type.second + "Texture: YUV420P 640x480").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_YUV420P + << QSize(640, 480) + << false + << false; + QTest::newRow((type.second + "Texture: YUV420P 640x-480").constData()) + << type.first + << QAbstractVideoBuffer::GLTextureHandle + << QVideoFrame::Format_YUV420P + << QSize(640, -480) + << false + << false; +#endif + QTest::newRow(type.second + "User Buffer: rgb32 256x256") + << type.first + << QAbstractVideoBuffer::UserHandle + << QVideoFrame::Format_RGB32 + << QSize(256, 256) + << false + << false; + } +} + +void tst_QPainterVideoSurface::shaderSupportedFormat() +{ + QFETCH(QPainterVideoSurface::ShaderType, shaderType); + QFETCH(QAbstractVideoBuffer::HandleType, handleType); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(QSize, frameSize); + QFETCH(bool, supportedPixelFormat); + QFETCH(bool, supportedFormat); + + QGLWidget widget; + widget.makeCurrent(); + + QPainterVideoSurface surface; + surface.setGLContext(const_cast(widget.context())); + + + if (!(surface.supportedShaderTypes() & shaderType)) + QSKIP("Shader type not supported on this platform", SkipSingle); + + surface.setShaderType(shaderType); + if (surface.shaderType() != shaderType) + QSKIP("Shader type couldn't be set", SkipSingle); + + const QList pixelFormats = surface.supportedPixelFormats(handleType); + + QCOMPARE(pixelFormats.contains(pixelFormat), QBool(supportedPixelFormat)); + + QVideoSurfaceFormat format(frameSize, pixelFormat, handleType); + + QCOMPARE(surface.isFormatSupported(format), supportedFormat); + QCOMPARE(surface.start(format), supportedFormat); +} + +void tst_QPainterVideoSurface::shaderPresent_data() +{ + QTest::addColumn("shaderType"); + QTest::addColumn("pixelFormatA"); + QTest::addColumn("frameSizeA"); + QTest::addColumn("frameDataA"); + QTest::addColumn("bytesA"); + QTest::addColumn("bytesPerLineA"); + QTest::addColumn("pixelFormatB"); + QTest::addColumn("frameSizeB"); + QTest::addColumn("frameDataB"); + QTest::addColumn("bytesB"); + QTest::addColumn("bytesPerLineB"); + + QList > types; +#ifndef QT_OPENGL_ES + types << qMakePair(QPainterVideoSurface::FragmentProgramShader, QByteArray("ARBfp: ")); +#endif + types << qMakePair(QPainterVideoSurface::GlslShader, QByteArray("GLSL: ")); + + QPair type; + foreach (type, types) { + QTest::newRow((type.second + "rgb32 -> argb32").constData()) + << type.first + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8 + << QVideoFrame::Format_ARGB32 + << QSize(2, 2) + << static_cast(argb32ImageData) + << int(sizeof(argb32ImageData)) + << 8; + + QTest::newRow((type.second + "rgb32 -> rgb565").constData()) + << type.first + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8 + << QVideoFrame::Format_RGB565 + << QSize(2, 2) + << static_cast(rgb565ImageData) + << int(sizeof(rgb565ImageData)) + << 4; +#ifndef Q_WS_MAC + QTest::newRow((type.second + "rgb32 -> yuv420p").constData()) + << type.first + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8 + << QVideoFrame::Format_YUV420P + << QSize(8, 8) + << static_cast(yuvPlanarImageData) + << int(sizeof(yuvPlanarImageData)) + << 8; + + QTest::newRow((type.second + "yv12 -> rgb32").constData()) + << type.first + << QVideoFrame::Format_YV12 + << QSize(8, 8) + << static_cast(yuvPlanarImageData) + << int(sizeof(yuvPlanarImageData)) + << 8 + << QVideoFrame::Format_RGB32 + << QSize(2, 2) + << static_cast(rgb32ImageData) + << int(sizeof(rgb32ImageData)) + << 8; +#endif + } +} + +void tst_QPainterVideoSurface::shaderPresent() +{ + QFETCH(QPainterVideoSurface::ShaderType, shaderType); + QFETCH(QVideoFrame::PixelFormat, pixelFormatA); + QFETCH(QSize, frameSizeA); + QFETCH(const uchar *, frameDataA); + QFETCH(int, bytesA); + QFETCH(int, bytesPerLineA); + QFETCH(QVideoFrame::PixelFormat, pixelFormatB); + QFETCH(QSize, frameSizeB); + QFETCH(const uchar *, frameDataB); + QFETCH(int, bytesB); + QFETCH(int, bytesPerLineB); + + QGLWidget widget; + widget.makeCurrent(); + + QPainterVideoSurface surface; + surface.setGLContext(const_cast(widget.context())); + + if (!(surface.supportedShaderTypes() & shaderType)) + QSKIP("Shader type unsupported on this platform", SkipSingle); + + surface.setShaderType(shaderType); + if (surface.shaderType() != shaderType) + QSKIP("Shader type couldn't be set", SkipSingle); + + QSignalSpy frameSpy(&surface, SIGNAL(frameChanged())); + + { // Test painting before starting the surface. + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.error(), QAbstractVideoSurface::NoError); + + QVideoSurfaceFormat formatA(frameSizeA, pixelFormatA); + + QVERIFY(surface.start(formatA)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + // Test painting before receiving a frame. + { + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + QVideoFrame frameA(bytesA, frameSizeA, bytesPerLineA, pixelFormatA); + + frameA.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frameA.bits(), frameDataA, frameA.mappedBytes()); + frameA.unmap(); + + QVERIFY(surface.present(frameA)); + QCOMPARE(surface.isReady(), false); + QCOMPARE(frameSpy.count(), 1); + + { + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), false); + + { // Test repainting before receiving another frame. + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), false); + + // Not ready. + QVERIFY(!surface.present(frameA)); + QCOMPARE(frameSpy.count(), 1); + + surface.setReady(true); + QCOMPARE(surface.isReady(), true); + QVERIFY(surface.present(frameA)); + QCOMPARE(frameSpy.count(), 2); + + // Try switching to a different format after starting. + QVideoSurfaceFormat formatB(frameSizeB, pixelFormatB); + + QVERIFY(surface.start(formatB)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + QVideoFrame frameB(bytesB, frameSizeB, bytesPerLineB, pixelFormatB); + + frameB.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frameB.bits(), frameDataB, frameB.mappedBytes()); + frameB.unmap(); + + QVERIFY(surface.present(frameB)); + QCOMPARE(surface.isReady(), false); + QCOMPARE(frameSpy.count(), 3); + + { + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + QCOMPARE(surface.isActive(), true); + + surface.stop(); + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + + // Try presenting a frame while stopped. + QVERIFY(!surface.present(frameB)); + QCOMPARE(surface.isReady(), false); + QCOMPARE(surface.error(), QAbstractVideoSurface::StoppedError); + + // Try stopping while already stopped. + surface.stop(); + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + + // Try presenting a frame with a different format. + QVERIFY(surface.start(formatB)); + QVERIFY(!surface.present(frameA)); + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError); +} + +void tst_QPainterVideoSurface::shaderPresentOpaqueFrame_data() +{ + QTest::addColumn("shaderType"); + +#ifndef QT_OPENGL_ES + QTest::newRow("ARBfp") + << QPainterVideoSurface::FragmentProgramShader; +#endif + QTest::newRow("GLSL") + << QPainterVideoSurface::GlslShader; +} + +void tst_QPainterVideoSurface::shaderPresentOpaqueFrame() +{ + QFETCH(QPainterVideoSurface::ShaderType, shaderType); + + QGLWidget widget; + widget.makeCurrent(); + + QPainterVideoSurface surface; + surface.setGLContext(const_cast(widget.context())); + + if (!(surface.supportedShaderTypes() & shaderType)) + QSKIP("Shader type unsupported on this platform", SkipSingle); + + surface.setShaderType(shaderType); + if (surface.shaderType() != shaderType) + QSKIP("Shader type couldn't be set", SkipSingle); + + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + + QVERIFY(surface.start(format)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + QVideoFrame frame(new QtTestOpaqueVideoBuffer, QSize(64, 64), QVideoFrame::Format_RGB32); + + if (surface.present(frame)) { + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + + QCOMPARE(surface.isActive(), false); + QCOMPARE(surface.isReady(), false); + QCOMPARE(surface.error(), QAbstractVideoSurface::IncorrectFormatError); +} + +void tst_QPainterVideoSurface::shaderPresentGLFrame_data() +{ + QTest::addColumn("shaderType"); + +#ifndef QT_OPENGL_ES + QTest::newRow("ARBfp") + << QPainterVideoSurface::FragmentProgramShader; +#endif + QTest::newRow("GLSL") + << QPainterVideoSurface::GlslShader; +} + +void tst_QPainterVideoSurface::shaderPresentGLFrame() +{ + QFETCH(QPainterVideoSurface::ShaderType, shaderType); + + QGLWidget widget; + widget.makeCurrent(); + + QPainterVideoSurface surface; + surface.setGLContext(const_cast(widget.context())); + + if (!(surface.supportedShaderTypes() & shaderType)) + QSKIP("Shader type unsupported on this platform", SkipSingle); + + surface.setShaderType(shaderType); + if (surface.shaderType() != shaderType) + QSKIP("Shader type couldn't be set", SkipSingle); + + QVideoSurfaceFormat format( + QSize(2, 2), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle); + + QVERIFY(surface.start(format)); + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), true); + + QtTestGLVideoBuffer *buffer = new QtTestGLVideoBuffer; + + glBindTexture(GL_TEXTURE_2D, buffer->textureId()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb32ImageData); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + QVideoFrame frame(buffer, QSize(2, 2), QVideoFrame::Format_RGB32); + + QVERIFY(surface.present(frame)); + + { + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), false); + + { + QPainter painter(&widget); + surface.paint(&painter, QRect(0, 0, 320, 240)); + } + + QCOMPARE(surface.isActive(), true); + QCOMPARE(surface.isReady(), false); +} + +#endif + +QTEST_MAIN(tst_QPainterVideoSurface) + +#include "tst_qpaintervideosurface.moc" diff --git a/tests/auto/qradiotuner/main.cpp b/tests/auto/qradiotuner/main.cpp new file mode 100755 index 000000000..f161c8fd6 --- /dev/null +++ b/tests/auto/qradiotuner/main.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#include +#include + +#include "tst_qradiotuner.h" + +#ifdef Q_OS_SYMBIAN +#include "tst_qradiotuner_xa.h" +#include "tst_qradiotuner_s60.h" +#endif + +int main(int argc, char**argv) +{ + QApplication app(argc,argv); + int ret; + tst_QRadioTuner test_api; + ret = QTest::qExec(&test_api, argc, argv); +#ifdef Q_OS_SYMBIAN + char *new_argv[3]; + QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_xa.log"; + QByteArray bytes = str.toAscii(); + char arg1[] = "-o"; + new_argv[0] = argv[0]; + new_argv[1] = arg1; + new_argv[2] = bytes.data(); + tst_QXARadio_xa test_xa; + ret = QTest::qExec(&test_xa, 3, new_argv); + char *new_argv1[3]; + QString str1 = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + "_s60.log"; + QByteArray bytes1 = str1.toAscii(); + char arg2[] = "-o"; + new_argv1[0] = argv[0]; + new_argv1[1] = arg2; + new_argv1[2] = bytes1.data(); + tst_QRadioTuner_s60 test_s60; + ret = QTest::qExec(&test_s60, 3, new_argv1); + +#endif + return ret; +} diff --git a/tests/auto/qradiotuner/qradiotuner.pro b/tests/auto/qradiotuner/qradiotuner.pro new file mode 100644 index 000000000..b80043801 --- /dev/null +++ b/tests/auto/qradiotuner/qradiotuner.pro @@ -0,0 +1,19 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qradiotuner +# CONFIG += testcase + +symbian { + HEADERS += tst_qradiotuner_xa.h + SOURCES += tst_qradiotuner_xa.cpp + TARGET.CAPABILITY = ALL -TCB + HEADERS += tst_qradiotuner_s60.h + SOURCES += tst_qradiotuner_s60.cpp + +} + +HEADERS += tst_qradiotuner.h +SOURCES += main.cpp tst_qradiotuner.cpp + diff --git a/tests/auto/qradiotuner/tst_qradiotuner.cpp b/tests/auto/qradiotuner/tst_qradiotuner.cpp new file mode 100644 index 000000000..647cd7775 --- /dev/null +++ b/tests/auto/qradiotuner/tst_qradiotuner.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include "tst_qradiotuner.h" + +QT_USE_NAMESPACE + +void tst_QRadioTuner::initTestCase() +{ + qRegisterMetaType("QRadioTuner::State"); + qRegisterMetaType("QRadioTuner::Band"); + + mock = new MockControl(this); + service = new MockService(this, mock); + provider = new MockProvider(service); + radio = new QRadioTuner(0,provider); + QVERIFY(radio->service() != 0); + + QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State))); + + QCOMPARE(radio->state(), QRadioTuner::StoppedState); + radio->start(); + QCOMPARE(radio->state(), QRadioTuner::ActiveState); + + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(stateSpy.first()[0].value(), QRadioTuner::ActiveState); +} + +void tst_QRadioTuner::cleanupTestCase() +{ + QVERIFY(radio->error() == QRadioTuner::NoError); + QVERIFY(radio->errorString().isEmpty()); + + QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State))); + + radio->stop(); + QCOMPARE(radio->state(), QRadioTuner::StoppedState); + QCOMPARE(stateSpy.count(), 1); + + QCOMPARE(stateSpy.first()[0].value(), QRadioTuner::StoppedState); + + delete radio; + delete service; + delete provider; +} + +void tst_QRadioTuner::testNullService() +{ + const QPair nullRange(0, 0); + + MockProvider provider(0); + QRadioTuner radio(0, &provider); + + radio.start(); + QCOMPARE(radio.error(), QRadioTuner::ResourceError); + QCOMPARE(radio.errorString(), QString()); + QCOMPARE(radio.band(), QRadioTuner::FM); + QCOMPARE(radio.isBandSupported(QRadioTuner::AM), false); + QCOMPARE(radio.isBandSupported(QRadioTuner::FM), false); + QCOMPARE(radio.frequency(), 0); + QCOMPARE(radio.frequencyStep(QRadioTuner::AM), 0); + QCOMPARE(radio.frequencyStep(QRadioTuner::FM), 0); + QCOMPARE(radio.frequencyRange(QRadioTuner::AM), nullRange); + QCOMPARE(radio.frequencyRange(QRadioTuner::FM), nullRange); + QCOMPARE(radio.isStereo(), false); + QCOMPARE(radio.stereoMode(), QRadioTuner::Auto); + QCOMPARE(radio.signalStrength(), 0); + QCOMPARE(radio.volume(), 0); + QCOMPARE(radio.isMuted(), false); + QCOMPARE(radio.isSearching(), false); + radio.stop(); +} + +void tst_QRadioTuner::testNullControl() +{ + const QPair nullRange(0, 0); + + MockService service(0, 0); + MockProvider provider(&service); + QRadioTuner radio(0, &provider); + + radio.start(); + + QCOMPARE(radio.error(), QRadioTuner::ResourceError); + QCOMPARE(radio.errorString(), QString()); + + QCOMPARE(radio.band(), QRadioTuner::FM); + QCOMPARE(radio.isBandSupported(QRadioTuner::AM), false); + QCOMPARE(radio.isBandSupported(QRadioTuner::FM), false); + QCOMPARE(radio.frequency(), 0); + QCOMPARE(radio.frequencyStep(QRadioTuner::AM), 0); + QCOMPARE(radio.frequencyStep(QRadioTuner::FM), 0); + QCOMPARE(radio.frequencyRange(QRadioTuner::AM), nullRange); + QCOMPARE(radio.frequencyRange(QRadioTuner::FM), nullRange); + { + QSignalSpy bandSpy(&radio, SIGNAL(bandChanged(QRadioTuner::Band))); + QSignalSpy frequencySpy(&radio, SIGNAL(frequencyChanged(int))); + + radio.setFrequency(107500); + QCOMPARE(radio.band(), QRadioTuner::FM); + QCOMPARE(radio.frequency(), 0); + QCOMPARE(bandSpy.count(), 0); + QCOMPARE(frequencySpy.count(), 0); + + radio.setBand(QRadioTuner::AM); + QCOMPARE(radio.band(), QRadioTuner::FM); + QCOMPARE(radio.frequency(), 0); + QCOMPARE(bandSpy.count(), 0); + QCOMPARE(frequencySpy.count(), 0); + } + QCOMPARE(radio.isStereo(), false); + QCOMPARE(radio.stereoMode(), QRadioTuner::Auto); + + radio.setStereoMode(QRadioTuner::ForceStereo); + QCOMPARE(radio.stereoMode(), QRadioTuner::Auto); + + QCOMPARE(radio.signalStrength(), 0); + + QCOMPARE(radio.volume(), 0); + QCOMPARE(radio.isMuted(), false); + { + QSignalSpy volumeSpy(&radio, SIGNAL(volumeChanged(int))); + QSignalSpy muteSpy(&radio, SIGNAL(mutedChanged(bool))); + + radio.setVolume(76); + QCOMPARE(radio.volume(), 0); + QCOMPARE(volumeSpy.count(), 0); + + radio.setMuted(true); + QCOMPARE(radio.isMuted(), false); + QCOMPARE(muteSpy.count(), 0); + } + QCOMPARE(radio.isSearching(), false); + { + QSignalSpy spy(&radio, SIGNAL(searchingChanged(bool))); + + radio.searchBackward(); + QCOMPARE(radio.isSearching(), false); + QCOMPARE(spy.count(), 0); + + radio.searchForward(); + QCOMPARE(radio.isSearching(), false); + QCOMPARE(spy.count(), 0); + + radio.cancelSearch(); + QCOMPARE(radio.isSearching(), false); + QCOMPARE(spy.count(), 0); + } + + radio.stop(); +} + +void tst_QRadioTuner::testBand() +{ + QVERIFY(radio->isBandSupported(QRadioTuner::FM)); + QVERIFY(!radio->isBandSupported(QRadioTuner::SW)); + + if(radio->isBandSupported(QRadioTuner::AM)) { + QSignalSpy readSignal(radio, SIGNAL(bandChanged(QRadioTuner::Band))); + radio->setBand(QRadioTuner::AM); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->band() == QRadioTuner::AM); + QVERIFY(readSignal.count() == 1); + } +} + +void tst_QRadioTuner::testFrequency() +{ + QSignalSpy readSignal(radio, SIGNAL(frequencyChanged(int))); + radio->setFrequency(104500000); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->frequency() == 104500000); + QVERIFY(readSignal.count() == 1); + + QVERIFY(radio->frequencyStep(QRadioTuner::FM) == 1); + QPair test = radio->frequencyRange(QRadioTuner::FM); + QVERIFY(test.first == 1); + QVERIFY(test.second == 2); +} + +void tst_QRadioTuner::testMute() +{ + QSignalSpy readSignal(radio, SIGNAL(mutedChanged(bool))); + radio->setMuted(true); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->isMuted()); + QVERIFY(readSignal.count() == 1); +} + +void tst_QRadioTuner::testSearch() +{ + QSignalSpy readSignal(radio, SIGNAL(searchingChanged(bool))); + QVERIFY(!radio->isSearching()); + + radio->searchForward(); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->isSearching()); + QVERIFY(readSignal.count() == 1); + + radio->cancelSearch(); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!radio->isSearching()); + QVERIFY(readSignal.count() == 2); + + radio->searchBackward(); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->isSearching()); + QVERIFY(readSignal.count() == 3); + + radio->cancelSearch(); + QVERIFY(!radio->isSearching()); +} + +void tst_QRadioTuner::testVolume() +{ + QVERIFY(radio->volume() == 100); + QSignalSpy readSignal(radio, SIGNAL(volumeChanged(int))); + radio->setVolume(50); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->volume() == 50); + QVERIFY(readSignal.count() == 1); +} + +void tst_QRadioTuner::testSignal() +{ + QVERIFY(radio->signalStrength() == 0); + // There is no set of this only a get, do nothing else. +} + +void tst_QRadioTuner::testStereo() +{ + QVERIFY(radio->isStereo()); + radio->setStereoMode(QRadioTuner::ForceMono); + QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono); +} diff --git a/tests/auto/qradiotuner/tst_qradiotuner.h b/tests/auto/qradiotuner/tst_qradiotuner.h new file mode 100644 index 000000000..970036c08 --- /dev/null +++ b/tests/auto/qradiotuner/tst_qradiotuner.h @@ -0,0 +1,285 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QRADIOTUNER_H +#define TST_QRADIOTUNER_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE +class MockControl : public QRadioTunerControl +{ + Q_OBJECT + +public: + MockControl(QObject *parent): + QRadioTunerControl(parent), + m_active(false), + m_searching(false),m_muted(false),m_stereo(true), + m_volume(100),m_signal(0),m_frequency(0), + m_band(QRadioTuner::FM) {} + + QRadioTuner::State state() const + { + return m_active ? QRadioTuner::ActiveState : QRadioTuner::StoppedState; + } + bool isAvailable() const + { + return true; + } + QtMultimediaKit::AvailabilityError availabilityError() const + { + return QtMultimediaKit::NoError; + } + + QRadioTuner::Band band() const + { + return m_band; + } + + void setBand(QRadioTuner::Band b) + { + m_band = b; + emit bandChanged(m_band); + } + + bool isBandSupported(QRadioTuner::Band b) const + { + if(b == QRadioTuner::FM || b == QRadioTuner::AM) return true; + + return false; + } + + int frequency() const + { + return m_frequency; + } + + QPair frequencyRange(QRadioTuner::Band) const + { + return qMakePair(1,2); + } + + int frequencyStep(QRadioTuner::Band) const + { + return 1; + } + + void setFrequency(int frequency) + { + m_frequency = frequency; + emit frequencyChanged(m_frequency); + } + + bool isStereo() const + { + return m_stereo; + } + + void setStereo(bool stereo) + { + emit stereoStatusChanged(m_stereo = stereo); + } + + + QRadioTuner::StereoMode stereoMode() const + { + return m_stereoMode; + } + + void setStereoMode(QRadioTuner::StereoMode mode) + { + m_stereoMode = mode; + } + + QRadioTuner::Error error() const + { + return QRadioTuner::NoError; + } + + QString errorString() const + { + return QString(); + } + + int signalStrength() const + { + return m_signal; + } + + int volume() const + { + return m_volume; + } + + void setVolume(int volume) + { + m_volume = volume; + emit volumeChanged(m_volume); + } + + bool isMuted() const + { + return m_muted; + } + + void setMuted(bool muted) + { + m_muted = muted; + emit mutedChanged(m_muted); + } + + bool isSearching() const + { + return m_searching; + } + + void searchForward() + { + m_searching = true; + emit searchingChanged(m_searching); + } + + void searchBackward() + { + m_searching = true; + emit searchingChanged(m_searching); + } + + void cancelSearch() + { + m_searching = false; + emit searchingChanged(m_searching); + } + + void start() + { + if (!m_active) { + m_active = true; + emit stateChanged(state()); + } + } + + void stop() + { + if (m_active) { + m_active = false; + emit stateChanged(state()); + } + } + +public: + bool m_active; + bool m_searching; + bool m_muted; + bool m_stereo; + int m_volume; + int m_signal; + int m_frequency; + QRadioTuner::StereoMode m_stereoMode; + QRadioTuner::Band m_band; +}; + +class MockService : public QMediaService +{ + Q_OBJECT +public: + MockService(QObject *parent, QMediaControl *control): + QMediaService(parent), + mockControl(control) {} + + QMediaControl* requestControl(const char *) + { + return mockControl; + } + + void releaseControl(QMediaControl*) {} + + QMediaControl *mockControl; +}; + +class MockProvider : public QMediaServiceProvider +{ +public: + MockProvider(MockService *service):mockService(service) {} + QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &) + { + return mockService; + } + + void releaseService(QMediaService *) {} + + MockService *mockService; +}; + +class tst_QRadioTuner: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testNullService(); + void testNullControl(); + void testBand(); + void testFrequency(); + void testMute(); + void testSearch(); + void testVolume(); + void testSignal(); + void testStereo(); + +private: + MockControl *mock; + MockService *service; + MockProvider *provider; + QRadioTuner *radio; +}; +#endif diff --git a/tests/auto/qradiotuner/tst_qradiotuner_s60.cpp b/tests/auto/qradiotuner/tst_qradiotuner_s60.cpp new file mode 100644 index 000000000..3c3de22da --- /dev/null +++ b/tests/auto/qradiotuner/tst_qradiotuner_s60.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include "tst_qradiotuner_s60.h" + +#define QTRY_COMPARE_S60(a,e) \ + for (int _i = 0; _i < 5000; _i += 100) { \ + if ((a) == (e)) break; \ + QTest::qWait(100); \ + } + +void tst_QRadioTuner_s60::initTestCase() +{ + qRegisterMetaType("QRadioTuner::State"); + qRegisterMetaType("QRadioTuner::Band"); + + radio = new QRadioTuner(0); + QVERIFY(radio->service() != 0); + + QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State))); + + QCOMPARE(radio->state(), QRadioTuner::StoppedState); + radio->start(); + //QCOMPARE(radio->state(), QRadioTuner::ActiveState); + QTRY_COMPARE_S60(radio->state(), QRadioTuner::ActiveState); + + QCOMPARE(stateSpy.count(), 1); + QCOMPARE(stateSpy.first()[0].value(), QRadioTuner::ActiveState); +} + +void tst_QRadioTuner_s60::cleanupTestCase() +{ + QVERIFY(radio->error() == QRadioTuner::NoError); + QVERIFY(radio->errorString().isEmpty()); + + QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State))); + + radio->stop(); + QTRY_COMPARE_S60(radio->state(), QRadioTuner::StoppedState); + QCOMPARE(stateSpy.count(), 1); + + QCOMPARE(stateSpy.first()[0].value(), QRadioTuner::StoppedState); + + delete radio; +} + +void tst_QRadioTuner_s60::testBand() +{ + QVERIFY(radio->isBandSupported(QRadioTuner::FM)); + QVERIFY(!radio->isBandSupported(QRadioTuner::SW)); + + if(radio->isBandSupported(QRadioTuner::AM)) { + QSignalSpy readSignal(radio, SIGNAL(bandChanged(QRadioTuner::Band))); + radio->setBand(QRadioTuner::AM); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->band() == QRadioTuner::AM); + QVERIFY(readSignal.count() == 1); + } +} + +void tst_QRadioTuner_s60::testFrequency() +{ + QSignalSpy readSignal(radio, SIGNAL(frequencyChanged(int))); + radio->setFrequency(104500000); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->frequency() == 104500000); + QVERIFY(readSignal.count() == 1); + + // frequencyStep for FM radio is 100kHz (100000Hz) + QVERIFY(radio->frequencyStep(QRadioTuner::FM) == 100000); + QPair test = radio->frequencyRange(QRadioTuner::FM); + // frequency range for FM radio is 87,5MHz - 108MHz + QVERIFY(test.first == 87500000); + QVERIFY(test.second == 108000000); +} + +void tst_QRadioTuner_s60::testMute() +{ + QSignalSpy readSignal(radio, SIGNAL(mutedChanged(bool))); + radio->setMuted(true); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(radio->isMuted()); + QVERIFY(readSignal.count() == 1); +} + +void tst_QRadioTuner_s60::testSearch() +{ + QSignalSpy readSignal(radio, SIGNAL(searchingChanged(bool))); + QVERIFY(!radio->isSearching()); + + radio->searchForward(); + QVERIFY(radio->isSearching()); + QVERIFY(readSignal.count() == 1); + + radio->cancelSearch(); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(!radio->isSearching()); + QVERIFY(readSignal.count() == 2); + + radio->searchBackward(); + QVERIFY(radio->isSearching()); + QVERIFY(readSignal.count() == 3); + + radio->cancelSearch(); + QVERIFY(!radio->isSearching()); +} + +void tst_QRadioTuner_s60::testVolume() +{ + QVERIFY(radio->volume() == 50); + QSignalSpy readSignal(radio, SIGNAL(volumeChanged(int))); + radio->setVolume(70); + QTestEventLoop::instance().enterLoop(1); + QTRY_COMPARE_S60(radio->volume() , 70); + QTRY_COMPARE_S60(readSignal.count() ,1); +} + +void tst_QRadioTuner_s60::testSignal() +{ + int signalStrength = radio->signalStrength(); + QVERIFY(signalStrength == signalStrength); + // There is no set of this only a get, do nothing else. +} + +void tst_QRadioTuner_s60::testStereo() +{ + QVERIFY(radio->isStereo()); + radio->setStereoMode(QRadioTuner::ForceMono); + QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono); +} diff --git a/tests/auto/qradiotuner/tst_qradiotuner_s60.h b/tests/auto/qradiotuner/tst_qradiotuner_s60.h new file mode 100644 index 000000000..2767fcb59 --- /dev/null +++ b/tests/auto/qradiotuner/tst_qradiotuner_s60.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QRADIOTUNER_S60_H +#define TST_QRADIOTUNER_S60_H + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QRadioTuner_s60: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testBand(); + void testFrequency(); + void testMute(); + void testSearch(); + void testVolume(); + void testSignal(); + void testStereo(); + +private: + QRadioTuner *radio; +}; + +#endif diff --git a/tests/auto/qradiotuner/tst_qradiotuner_xa.cpp b/tests/auto/qradiotuner/tst_qradiotuner_xa.cpp new file mode 100644 index 000000000..dec65f839 --- /dev/null +++ b/tests/auto/qradiotuner/tst_qradiotuner_xa.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +#include "tst_qradiotuner_xa.h" + +QT_USE_NAMESPACE + +#define QTEST_MAIN_S60(TestObject) \ + int main(int argc, char *argv[]) { \ + char *new_argv[3]; \ + QApplication app(argc, argv); \ + \ + QString str = "C:\\data\\" + QFileInfo(QCoreApplication::applicationFilePath()).baseName() + ".log"; \ + QByteArray bytes = str.toAscii(); \ + \ + char arg1[] = "-o"; \ + \ + new_argv[0] = argv[0]; \ + new_argv[1] = arg1; \ + new_argv[2] = bytes.data(); \ + \ + TestObject tc; \ + return QTest::qExec(&tc, 3, new_argv); \ + } + +#define QTRY_COMPARE(a,e) \ + for (int _i = 0; _i < 5000; _i += 100) { \ + if ((a) == (e)) break; \ + QTest::qWait(100); \ + } \ +// QCOMPARE(a, e) + +void tst_QXARadio_xa::initTestCase() +{ + qRegisterMetaType("QRadioTuner::State"); + radio = new QRadioTuner(0); +// QVERIFY(radio->service() != 0); +// QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State))); + radio->start(); +// QTRY_COMPARE(stateSpy.count(), 1); // wait for callbacks to complete in symbian API +// QCOMPARE(radio->state(), QRadioTuner::ActiveState); + +} + +void tst_QXARadio_xa::cleanupTestCase() +{ + QVERIFY(radio->service() != 0); +} + +void tst_QXARadio_xa::testBand() +{ + qRegisterMetaType("QRadioTuner::Band"); + + QVERIFY(radio->isBandSupported(QRadioTuner::FM)); + QVERIFY(!radio->isBandSupported(QRadioTuner::SW)); + radio->setBand(QRadioTuner::FM); + QVERIFY(radio->band() == QRadioTuner::FM); + if(radio->isBandSupported(QRadioTuner::AM)) { + QSignalSpy readSignal(radio, SIGNAL(bandChanged(QRadioTuner::Band))); + radio->setBand(QRadioTuner::AM); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->band() == QRadioTuner::AM); + } +} + +void tst_QXARadio_xa::testFrequency() +{ + QSignalSpy readSignal(radio, SIGNAL(frequencyChanged(int))); + radio->setFrequency(90900000); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->frequency() == 90900000); + // frequencyStep for FM radio is 100kHz (100000Hz) + QVERIFY(radio->frequencyStep(QRadioTuner::FM) == 100000); + QPair test = radio->frequencyRange(QRadioTuner::FM); + // frequency range for FM radio is 87,5MHz - 108MHz + QVERIFY(test.first == 87500000); + QVERIFY(test.second == 108000000); +} + +void tst_QXARadio_xa::testMute() +{ + QSignalSpy readSignal(radio, SIGNAL(mutedChanged(bool))); + radio->setMuted(true); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->isMuted()); + QVERIFY(readSignal.count() == 1); +} + +void tst_QXARadio_xa::testSearch() +{ + QSignalSpy readSignal(radio, SIGNAL(searchingChanged(bool))); + QVERIFY(!radio->isSearching()); + + radio->searchForward(); + // Note: DON'T wait for callback to complete in symbian API + QVERIFY(radio->isSearching()); + + radio->cancelSearch(); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(!radio->isSearching()); + + radio->searchBackward(); + // Note: DON'T wait for callbacks to complete in symbian API + QVERIFY(radio->isSearching()); + + radio->cancelSearch(); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(!radio->isSearching()); +} + +void tst_QXARadio_xa::testVolume() +{ + QSignalSpy readSignal(radio, SIGNAL(volumeChanged(int))); + radio->setVolume(50); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->volume() == 50); +} + +void tst_QXARadio_xa::testSignal() +{ + QVERIFY(radio->signalStrength() != 0); + // There is no set of this only a get, do nothing else. +} + +void tst_QXARadio_xa::testStereo() +{ + // Default = Auto. Testing transition from auto to mono: + QVERIFY(radio->isStereo()); + QSignalSpy readSignal(radio, SIGNAL(stereoStatusChanged(bool))); + radio->setStereoMode(QRadioTuner::ForceMono); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono); +// QVERIFY(readSignal.count() == 1); + + // testing transition from mono to stereo: + radio->setStereoMode(QRadioTuner::ForceStereo); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->stereoMode() == QRadioTuner::ForceStereo); +// QVERIFY(readSignal.count() == 1); + + // testing transition from stereo to auto: + radio->setStereoMode(QRadioTuner::Auto); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->stereoMode() == QRadioTuner::Auto); + // QVERIFY(readSignal.count() == 1); + + // testing transition from auto to stereo: + radio->setStereoMode(QRadioTuner::ForceStereo); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->stereoMode() == QRadioTuner::ForceStereo); + // QVERIFY(readSignal.count() == 1); + + // testing transition from stereo to mono: + radio->setStereoMode(QRadioTuner::ForceMono); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->stereoMode() == QRadioTuner::ForceMono); + // QVERIFY(readSignal.count() == 1); + + // testing transition from mono to auto: + radio->setStereoMode(QRadioTuner::Auto); + QTRY_COMPARE(readSignal.count(), 1); // wait for callbacks to complete in symbian API + QVERIFY(radio->stereoMode() == QRadioTuner::Auto); +// QVERIFY(readSignal.count() == 1); + +} + +void tst_QXARadio_xa::testAvailability() +{ + QVERIFY(radio->isAvailable()); + QVERIFY(radio->availabilityError() == QtMultimediaKit::NoError); +} + +void tst_QXARadio_xa::testStopRadio() +{ + QVERIFY(radio->service() != 0); + QVERIFY(radio->error() == QRadioTuner::NoError); + QVERIFY(radio->errorString().isEmpty()); + + QSignalSpy stateSpy(radio, SIGNAL(stateChanged(QRadioTuner::State))); + + radio->stop(); + QTRY_COMPARE(stateSpy.count(), 1); // wait for callbacks to complete in symbian API + QCOMPARE(radio->state(), QRadioTuner::StoppedState); + +// delete radio; +} diff --git a/tests/auto/qradiotuner/tst_qradiotuner_xa.h b/tests/auto/qradiotuner/tst_qradiotuner_xa.h new file mode 100644 index 000000000..6cb7c7802 --- /dev/null +++ b/tests/auto/qradiotuner/tst_qradiotuner_xa.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ +#ifndef TST_QRADIOTUNER_XA_H +#define TST_QRADIOTUNER_XA_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +QT_USE_NAMESPACE + +class tst_QXARadio_xa: public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void testBand(); + void testFrequency(); + void testMute(); + void testSearch(); + void testVolume(); + void testSignal(); + void testStereo(); + void testAvailability(); + void testStopRadio(); + +private: + QRadioTuner *radio; +}; + +#endif // TST_QRADIOTUNER_XA_H diff --git a/tests/auto/qvideoframe/qvideoframe.pro b/tests/auto/qvideoframe/qvideoframe.pro new file mode 100644 index 000000000..03af898c8 --- /dev/null +++ b/tests/auto/qvideoframe/qvideoframe.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qvideoframe +# CONFIG += testcase + +SOURCES += tst_qvideoframe.cpp + diff --git a/tests/auto/qvideoframe/tst_qvideoframe.cpp b/tests/auto/qvideoframe/tst_qvideoframe.cpp new file mode 100644 index 000000000..58640b71a --- /dev/null +++ b/tests/auto/qvideoframe/tst_qvideoframe.cpp @@ -0,0 +1,793 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include + +#include +#include +#include + +class tst_QVideoFrame : public QObject +{ + Q_OBJECT +public: + tst_QVideoFrame(); + ~tst_QVideoFrame(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void create_data(); + void create(); + void createInvalid_data(); + void createInvalid(); + void createFromBuffer_data(); + void createFromBuffer(); + void createFromImage_data(); + void createFromImage(); + void createFromIncompatibleImage(); + void createNull(); + void destructor(); + void copy_data(); + void copy(); + void assign_data(); + void assign(); + void map_data(); + void map(); + void mapImage_data(); + void mapImage(); + void imageDetach(); + void formatConversion_data(); + void formatConversion(); +}; + +Q_DECLARE_METATYPE(QImage::Format) +Q_DECLARE_METATYPE(QVideoFrame) + +class QtTestVideoBuffer : public QObject, public QAbstractVideoBuffer +{ + Q_OBJECT +public: + QtTestVideoBuffer() + : QAbstractVideoBuffer(NoHandle) {} + explicit QtTestVideoBuffer(QAbstractVideoBuffer::HandleType type) + : QAbstractVideoBuffer(type) {} + + MapMode mapMode() const { return NotMapped; } + + uchar *map(MapMode, int *, int *) { return 0; } + void unmap() {} +}; + +tst_QVideoFrame::tst_QVideoFrame() +{ +} + +tst_QVideoFrame::~tst_QVideoFrame() +{ +} + +void tst_QVideoFrame::initTestCase() +{ +} + +void tst_QVideoFrame::cleanupTestCase() +{ +} + +void tst_QVideoFrame::init() +{ +} + +void tst_QVideoFrame::cleanup() +{ +} + +void tst_QVideoFrame::create_data() +{ + QTest::addColumn("size"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("bytes"); + QTest::addColumn("bytesPerLine"); + + QTest::newRow("64x64 ARGB32") + << QSize(64, 64) + << QVideoFrame::Format_ARGB32 + << 16384 + << 256; + QTest::newRow("32x256 YUV420P") + << QSize(32, 256) + << QVideoFrame::Format_YUV420P + << 13288 + << 32; +} + +void tst_QVideoFrame::create() +{ + QFETCH(QSize, size); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(int, bytes); + QFETCH(int, bytesPerLine); + + QVideoFrame frame(bytes, size, bytesPerLine, pixelFormat); + + QVERIFY(frame.isValid()); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::createInvalid_data() +{ + QTest::addColumn("size"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("bytes"); + QTest::addColumn("bytesPerLine"); + + QTest::newRow("64x64 ARGB32 0 size") + << QSize(64, 64) + << QVideoFrame::Format_ARGB32 + << 0 + << 45; + QTest::newRow("32x256 YUV420P negative size") + << QSize(32, 256) + << QVideoFrame::Format_YUV420P + << -13288 + << 32; +} + +void tst_QVideoFrame::createInvalid() +{ + QFETCH(QSize, size); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(int, bytes); + QFETCH(int, bytesPerLine); + + QVideoFrame frame(bytes, size, bytesPerLine, pixelFormat); + + QVERIFY(!frame.isValid()); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::createFromBuffer_data() +{ + QTest::addColumn("handleType"); + QTest::addColumn("size"); + QTest::addColumn("pixelFormat"); + + QTest::newRow("64x64 ARGB32 no handle") + << QAbstractVideoBuffer::NoHandle + << QSize(64, 64) + << QVideoFrame::Format_ARGB32; + QTest::newRow("64x64 ARGB32 gl handle") + << QAbstractVideoBuffer::GLTextureHandle + << QSize(64, 64) + << QVideoFrame::Format_ARGB32; + QTest::newRow("64x64 ARGB32 user handle") + << QAbstractVideoBuffer::UserHandle + << QSize(64, 64) + << QVideoFrame::Format_ARGB32; +} + +void tst_QVideoFrame::createFromBuffer() +{ + QFETCH(QAbstractVideoBuffer::HandleType, handleType); + QFETCH(QSize, size); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + + QVideoFrame frame(new QtTestVideoBuffer(handleType), size, pixelFormat); + + QVERIFY(frame.isValid()); + QCOMPARE(frame.handleType(), handleType); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::createFromImage_data() +{ + QTest::addColumn("size"); + QTest::addColumn("imageFormat"); + QTest::addColumn("pixelFormat"); + + QTest::newRow("64x64 RGB32") + << QSize(64, 64) + << QImage::Format_RGB32 + << QVideoFrame::Format_RGB32; + QTest::newRow("12x45 RGB16") + << QSize(12, 45) + << QImage::Format_RGB16 + << QVideoFrame::Format_RGB565; + QTest::newRow("19x46 ARGB32_Premultiplied") + << QSize(19, 46) + << QImage::Format_ARGB32_Premultiplied + << QVideoFrame::Format_ARGB32_Premultiplied; +} + +void tst_QVideoFrame::createFromImage() +{ + QFETCH(QSize, size); + QFETCH(QImage::Format, imageFormat); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + + const QImage image(size.width(), size.height(), imageFormat); + + QVideoFrame frame(image); + + QVERIFY(frame.isValid()); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::createFromIncompatibleImage() +{ + const QImage image(64, 64, QImage::Format_Mono); + + QVideoFrame frame(image); + + QVERIFY(!frame.isValid()); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Invalid); + QCOMPARE(frame.size(), QSize(64, 64)); + QCOMPARE(frame.width(), 64); + QCOMPARE(frame.height(), 64); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::createNull() +{ + QVideoFrame frame; + + QVERIFY(!frame.isValid()); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Invalid); + QCOMPARE(frame.size(), QSize()); + QCOMPARE(frame.width(), -1); + QCOMPARE(frame.height(), -1); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::destructor() +{ + QPointer buffer = new QtTestVideoBuffer; + + { + QVideoFrame frame(buffer, QSize(4, 1), QVideoFrame::Format_ARGB32); + } + + QVERIFY(buffer.isNull()); +} + +void tst_QVideoFrame::copy_data() +{ + QTest::addColumn("handleType"); + QTest::addColumn("size"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("fieldType"); + QTest::addColumn("startTime"); + QTest::addColumn("endTime"); + + QTest::newRow("64x64 ARGB32") + << QAbstractVideoBuffer::GLTextureHandle + << QSize(64, 64) + << QVideoFrame::Format_ARGB32 + << QVideoFrame::TopField + << qint64(63641740) + << qint64(63641954); + QTest::newRow("32x256 YUV420P") + << QAbstractVideoBuffer::UserHandle + << QSize(32, 256) + << QVideoFrame::Format_YUV420P + << QVideoFrame::InterlacedFrame + << qint64(12345) + << qint64(12389); +} + +void tst_QVideoFrame::copy() +{ + QFETCH(QAbstractVideoBuffer::HandleType, handleType); + QFETCH(QSize, size); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(QVideoFrame::FieldType, fieldType); + QFETCH(qint64, startTime); + QFETCH(qint64, endTime); + + QPointer buffer = new QtTestVideoBuffer(handleType); + + { + QVideoFrame frame(buffer, size, pixelFormat); + frame.setFieldType(QVideoFrame::FieldType(fieldType)); + frame.setStartTime(startTime); + frame.setEndTime(endTime); + + QVERIFY(frame.isValid()); + QCOMPARE(frame.handleType(), handleType); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), fieldType); + QCOMPARE(frame.startTime(), startTime); + QCOMPARE(frame.endTime(), endTime); + + { + QVideoFrame otherFrame(frame); + + QVERIFY(!buffer.isNull()); + + QVERIFY(otherFrame.isValid()); + QCOMPARE(otherFrame.handleType(), handleType); + QCOMPARE(otherFrame.pixelFormat(), pixelFormat); + QCOMPARE(otherFrame.size(), size); + QCOMPARE(otherFrame.width(), size.width()); + QCOMPARE(otherFrame.height(), size.height()); + QCOMPARE(otherFrame.fieldType(), fieldType); + QCOMPARE(otherFrame.startTime(), startTime); + QCOMPARE(otherFrame.endTime(), endTime); + + otherFrame.setEndTime(-1); + + QVERIFY(!buffer.isNull()); + + QVERIFY(otherFrame.isValid()); + QCOMPARE(otherFrame.handleType(), handleType); + QCOMPARE(otherFrame.pixelFormat(), pixelFormat); + QCOMPARE(otherFrame.size(), size); + QCOMPARE(otherFrame.width(), size.width()); + QCOMPARE(otherFrame.height(), size.height()); + QCOMPARE(otherFrame.fieldType(), fieldType); + QCOMPARE(otherFrame.startTime(), startTime); + QCOMPARE(otherFrame.endTime(), qint64(-1)); + } + + QVERIFY(!buffer.isNull()); + + QVERIFY(frame.isValid()); + QCOMPARE(frame.handleType(), handleType); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), fieldType); + QCOMPARE(frame.startTime(), startTime); + QCOMPARE(frame.endTime(), qint64(-1)); // Explicitly shared. + } + + QVERIFY(buffer.isNull()); +} + +void tst_QVideoFrame::assign_data() +{ + QTest::addColumn("handleType"); + QTest::addColumn("size"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("fieldType"); + QTest::addColumn("startTime"); + QTest::addColumn("endTime"); + + QTest::newRow("64x64 ARGB32") + << QAbstractVideoBuffer::GLTextureHandle + << QSize(64, 64) + << QVideoFrame::Format_ARGB32 + << QVideoFrame::TopField + << qint64(63641740) + << qint64(63641954); + QTest::newRow("32x256 YUV420P") + << QAbstractVideoBuffer::UserHandle + << QSize(32, 256) + << QVideoFrame::Format_YUV420P + << QVideoFrame::InterlacedFrame + << qint64(12345) + << qint64(12389); +} + +void tst_QVideoFrame::assign() +{ + QFETCH(QAbstractVideoBuffer::HandleType, handleType); + QFETCH(QSize, size); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(QVideoFrame::FieldType, fieldType); + QFETCH(qint64, startTime); + QFETCH(qint64, endTime); + + QPointer buffer = new QtTestVideoBuffer(handleType); + + QVideoFrame frame; + { + QVideoFrame otherFrame(buffer, size, pixelFormat); + otherFrame.setFieldType(fieldType); + otherFrame.setStartTime(startTime); + otherFrame.setEndTime(endTime); + + frame = otherFrame; + + QVERIFY(!buffer.isNull()); + + QVERIFY(otherFrame.isValid()); + QCOMPARE(otherFrame.handleType(), handleType); + QCOMPARE(otherFrame.pixelFormat(), pixelFormat); + QCOMPARE(otherFrame.size(), size); + QCOMPARE(otherFrame.width(), size.width()); + QCOMPARE(otherFrame.height(), size.height()); + QCOMPARE(otherFrame.fieldType(), fieldType); + QCOMPARE(otherFrame.startTime(), startTime); + QCOMPARE(otherFrame.endTime(), endTime); + + otherFrame.setStartTime(-1); + + QVERIFY(!buffer.isNull()); + + QVERIFY(otherFrame.isValid()); + QCOMPARE(otherFrame.handleType(), handleType); + QCOMPARE(otherFrame.pixelFormat(), pixelFormat); + QCOMPARE(otherFrame.size(), size); + QCOMPARE(otherFrame.width(), size.width()); + QCOMPARE(otherFrame.height(), size.height()); + QCOMPARE(otherFrame.fieldType(), fieldType); + QCOMPARE(otherFrame.startTime(), qint64(-1)); + QCOMPARE(otherFrame.endTime(), endTime); + } + + QVERIFY(!buffer.isNull()); + + QVERIFY(frame.isValid()); + QCOMPARE(frame.handleType(), handleType); + QCOMPARE(frame.pixelFormat(), pixelFormat); + QCOMPARE(frame.size(), size); + QCOMPARE(frame.width(), size.width()); + QCOMPARE(frame.height(), size.height()); + QCOMPARE(frame.fieldType(), fieldType); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), endTime); + + frame = QVideoFrame(); + + QVERIFY(buffer.isNull()); + + QVERIFY(!frame.isValid()); + QCOMPARE(frame.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(frame.pixelFormat(), QVideoFrame::Format_Invalid); + QCOMPARE(frame.size(), QSize()); + QCOMPARE(frame.width(), -1); + QCOMPARE(frame.height(), -1); + QCOMPARE(frame.fieldType(), QVideoFrame::ProgressiveFrame); + QCOMPARE(frame.startTime(), qint64(-1)); + QCOMPARE(frame.endTime(), qint64(-1)); +} + +void tst_QVideoFrame::map_data() +{ + QTest::addColumn("size"); + QTest::addColumn("mappedBytes"); + QTest::addColumn("bytesPerLine"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("mode"); + + QTest::newRow("read-only") + << QSize(64, 64) + << 16384 + << 256 + << QVideoFrame::Format_ARGB32 + << QAbstractVideoBuffer::ReadOnly; + + QTest::newRow("write-only") + << QSize(64, 64) + << 16384 + << 256 + << QVideoFrame::Format_ARGB32 + << QAbstractVideoBuffer::WriteOnly; + + QTest::newRow("read-write") + << QSize(64, 64) + << 16384 + << 256 + << QVideoFrame::Format_ARGB32 + << QAbstractVideoBuffer::ReadWrite; +} + +void tst_QVideoFrame::map() +{ + QFETCH(QSize, size); + QFETCH(int, mappedBytes); + QFETCH(int, bytesPerLine); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(QAbstractVideoBuffer::MapMode, mode); + + QVideoFrame frame(mappedBytes, size, bytesPerLine, pixelFormat); + + QVERIFY(!frame.bits()); + QCOMPARE(frame.mappedBytes(), 0); + QCOMPARE(frame.bytesPerLine(), 0); + QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped); + + QVERIFY(frame.map(mode)); + + QVERIFY(frame.bits()); + QCOMPARE(frame.mappedBytes(), mappedBytes); + QCOMPARE(frame.bytesPerLine(), bytesPerLine); + QCOMPARE(frame.mapMode(), mode); + + frame.unmap(); + + QVERIFY(!frame.bits()); + QCOMPARE(frame.mappedBytes(), 0); + QCOMPARE(frame.bytesPerLine(), 0); + QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped); +} + +void tst_QVideoFrame::mapImage_data() +{ + QTest::addColumn("size"); + QTest::addColumn("format"); + QTest::addColumn("mode"); + + QTest::newRow("read-only") + << QSize(64, 64) + << QImage::Format_ARGB32 + << QAbstractVideoBuffer::ReadOnly; + + QTest::newRow("write-only") + << QSize(15, 106) + << QImage::Format_RGB32 + << QAbstractVideoBuffer::WriteOnly; + + QTest::newRow("read-write") + << QSize(23, 111) + << QImage::Format_RGB16 + << QAbstractVideoBuffer::ReadWrite; +} + +void tst_QVideoFrame::mapImage() +{ + QFETCH(QSize, size); + QFETCH(QImage::Format, format); + QFETCH(QAbstractVideoBuffer::MapMode, mode); + + QImage image(size.width(), size.height(), format); + + QVideoFrame frame(image); + + QVERIFY(!frame.bits()); + QCOMPARE(frame.mappedBytes(), 0); + QCOMPARE(frame.bytesPerLine(), 0); + QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped); + + QVERIFY(frame.map(mode)); + + QVERIFY(frame.bits()); + QCOMPARE(frame.mappedBytes(), image.numBytes()); + QCOMPARE(frame.bytesPerLine(), image.bytesPerLine()); + QCOMPARE(frame.mapMode(), mode); + + frame.unmap(); + + QVERIFY(!frame.bits()); + QCOMPARE(frame.mappedBytes(), 0); + QCOMPARE(frame.bytesPerLine(), 0); + QCOMPARE(frame.mapMode(), QAbstractVideoBuffer::NotMapped); +} + +void tst_QVideoFrame::imageDetach() +{ + const uint red = qRgb(255, 0, 0); + const uint blue = qRgb(0, 0, 255); + + QImage image(8, 8, QImage::Format_RGB32); + + image.fill(red); + QCOMPARE(image.pixel(4, 4), red); + + QVideoFrame frame(image); + + QVERIFY(frame.map(QAbstractVideoBuffer::ReadWrite)); + + QImage frameImage(frame.bits(), 8, 8, frame.bytesPerLine(), QImage::Format_RGB32); + + QCOMPARE(frameImage.pixel(4, 4), red); + + frameImage.fill(blue); + QCOMPARE(frameImage.pixel(4, 4), blue); + + // Original image has detached and is therefore unchanged. + QCOMPARE(image.pixel(4, 4), red); +} + +void tst_QVideoFrame::formatConversion_data() +{ + QTest::addColumn("imageFormat"); + QTest::addColumn("pixelFormat"); + + QTest::newRow("QImage::Format_RGB32 | QVideoFrame::Format_RGB32") + << QImage::Format_RGB32 + << QVideoFrame::Format_RGB32; + QTest::newRow("QImage::Format_ARGB32 | QVideoFrame::Format_ARGB32") + << QImage::Format_ARGB32 + << QVideoFrame::Format_ARGB32; + QTest::newRow("QImage::Format_ARGB32_Premultiplied | QVideoFrame::Format_ARGB32_Premultiplied") + << QImage::Format_ARGB32_Premultiplied + << QVideoFrame::Format_ARGB32_Premultiplied; + QTest::newRow("QImage::Format_RGB16 | QVideoFrame::Format_RGB565") + << QImage::Format_RGB16 + << QVideoFrame::Format_RGB565; + QTest::newRow("QImage::Format_ARGB8565_Premultiplied | QVideoFrame::Format_ARGB8565_Premultiplied") + << QImage::Format_ARGB8565_Premultiplied + << QVideoFrame::Format_ARGB8565_Premultiplied; + QTest::newRow("QImage::Format_RGB555 | QVideoFrame::Format_RGB555") + << QImage::Format_RGB555 + << QVideoFrame::Format_RGB555; + QTest::newRow("QImage::Format_RGB888 | QVideoFrame::Format_RGB24") + << QImage::Format_RGB888 + << QVideoFrame::Format_RGB24; + + QTest::newRow("QImage::Format_MonoLSB") + << QImage::Format_MonoLSB + << QVideoFrame::Format_Invalid; + QTest::newRow("QImage::Format_Indexed8") + << QImage::Format_Indexed8 + << QVideoFrame::Format_Invalid; + QTest::newRow("QImage::Format_ARGB6666_Premultiplied") + << QImage::Format_ARGB6666_Premultiplied + << QVideoFrame::Format_Invalid; + QTest::newRow("QImage::Format_ARGB8555_Premultiplied") + << QImage::Format_ARGB8555_Premultiplied + << QVideoFrame::Format_Invalid; + QTest::newRow("QImage::Format_RGB666") + << QImage::Format_RGB666 + << QVideoFrame::Format_Invalid; + QTest::newRow("QImage::Format_RGB444") + << QImage::Format_RGB444 + << QVideoFrame::Format_Invalid; + QTest::newRow("QImage::Format_ARGB4444_Premultiplied") + << QImage::Format_ARGB4444_Premultiplied + << QVideoFrame::Format_Invalid; + + QTest::newRow("QVideoFrame::Format_BGRA32") + << QImage::Format_Invalid + << QVideoFrame::Format_BGRA32; + QTest::newRow("QVideoFrame::Format_BGRA32_Premultiplied") + << QImage::Format_Invalid + << QVideoFrame::Format_BGRA32_Premultiplied; + QTest::newRow("QVideoFrame::Format_BGR32") + << QImage::Format_Invalid + << QVideoFrame::Format_BGR32; + QTest::newRow("QVideoFrame::Format_BGR24") + << QImage::Format_Invalid + << QVideoFrame::Format_BGR24; + QTest::newRow("QVideoFrame::Format_BGR565") + << QImage::Format_Invalid + << QVideoFrame::Format_BGR565; + QTest::newRow("QVideoFrame::Format_BGR555") + << QImage::Format_Invalid + << QVideoFrame::Format_BGR555; + QTest::newRow("QVideoFrame::Format_BGRA5658_Premultiplied") + << QImage::Format_Invalid + << QVideoFrame::Format_BGRA5658_Premultiplied; + QTest::newRow("QVideoFrame::Format_AYUV444") + << QImage::Format_Invalid + << QVideoFrame::Format_AYUV444; + QTest::newRow("QVideoFrame::Format_AYUV444_Premultiplied") + << QImage::Format_Invalid + << QVideoFrame::Format_AYUV444_Premultiplied; + QTest::newRow("QVideoFrame::Format_YUV444") + << QImage::Format_Invalid + << QVideoFrame::Format_YUV420P; + QTest::newRow("QVideoFrame::Format_YV12") + << QImage::Format_Invalid + << QVideoFrame::Format_YV12; + QTest::newRow("QVideoFrame::Format_UYVY") + << QImage::Format_Invalid + << QVideoFrame::Format_UYVY; + QTest::newRow("QVideoFrame::Format_YUYV") + << QImage::Format_Invalid + << QVideoFrame::Format_YUYV; + QTest::newRow("QVideoFrame::Format_NV12") + << QImage::Format_Invalid + << QVideoFrame::Format_NV12; + QTest::newRow("QVideoFrame::Format_NV21") + << QImage::Format_Invalid + << QVideoFrame::Format_NV21; + QTest::newRow("QVideoFrame::Format_IMC1") + << QImage::Format_Invalid + << QVideoFrame::Format_IMC1; + QTest::newRow("QVideoFrame::Format_IMC2") + << QImage::Format_Invalid + << QVideoFrame::Format_IMC2; + QTest::newRow("QVideoFrame::Format_IMC3") + << QImage::Format_Invalid + << QVideoFrame::Format_IMC3; + QTest::newRow("QVideoFrame::Format_IMC4") + << QImage::Format_Invalid + << QVideoFrame::Format_IMC4; + QTest::newRow("QVideoFrame::Format_Y8") + << QImage::Format_Invalid + << QVideoFrame::Format_Y8; + QTest::newRow("QVideoFrame::Format_Y16") + << QImage::Format_Invalid + << QVideoFrame::Format_Y16; +} + +void tst_QVideoFrame::formatConversion() +{ + QFETCH(QImage::Format, imageFormat); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + + QCOMPARE(QVideoFrame::pixelFormatFromImageFormat(imageFormat) == pixelFormat, + imageFormat != QImage::Format_Invalid); + + QCOMPARE(QVideoFrame::imageFormatFromPixelFormat(pixelFormat) == imageFormat, + pixelFormat != QVideoFrame::Format_Invalid); +} + +QTEST_MAIN(tst_QVideoFrame) + +#include "tst_qvideoframe.moc" diff --git a/tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro b/tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro new file mode 100644 index 000000000..472d2cf9c --- /dev/null +++ b/tests/auto/qvideosurfaceformat/qvideosurfaceformat.pro @@ -0,0 +1,9 @@ +load(qttest_p4) + +QT += core multimediakit-private + +# TARGET = tst_qvideosurfaceformat +# CONFIG += testcase + +SOURCES += tst_qvideosurfaceformat.cpp + diff --git a/tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp b/tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp new file mode 100644 index 000000000..6a751ff20 --- /dev/null +++ b/tests/auto/qvideosurfaceformat/tst_qvideosurfaceformat.cpp @@ -0,0 +1,738 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include + +#include + +class tst_QVideoSurfaceFormat : public QObject +{ + Q_OBJECT +public: + tst_QVideoSurfaceFormat(); + ~tst_QVideoSurfaceFormat(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void constructNull(); + void construct_data(); + void construct(); + void frameSize_data(); + void frameSize(); + void viewport_data(); + void viewport(); + void scanLineDirection_data(); + void scanLineDirection(); + void frameRate_data(); + void frameRate(); + void yCbCrColorSpace_data(); + void yCbCrColorSpace(); + void pixelAspectRatio_data(); + void pixelAspectRatio(); + void sizeHint_data(); + void sizeHint(); + void staticPropertyNames(); + void dynamicProperty(); + void compare(); + void copy(); + void assign(); +}; + +tst_QVideoSurfaceFormat::tst_QVideoSurfaceFormat() +{ +} + +tst_QVideoSurfaceFormat::~tst_QVideoSurfaceFormat() +{ +} + +void tst_QVideoSurfaceFormat::initTestCase() +{ +} + +void tst_QVideoSurfaceFormat::cleanupTestCase() +{ +} + +void tst_QVideoSurfaceFormat::init() +{ +} + +void tst_QVideoSurfaceFormat::cleanup() +{ +} + +void tst_QVideoSurfaceFormat::constructNull() +{ + QVideoSurfaceFormat format; + + QVERIFY(!format.isValid()); + QCOMPARE(format.handleType(), QAbstractVideoBuffer::NoHandle); + QCOMPARE(format.pixelFormat(), QVideoFrame::Format_Invalid); + QCOMPARE(format.frameSize(), QSize()); + QCOMPARE(format.frameWidth(), -1); + QCOMPARE(format.frameHeight(), -1); + QCOMPARE(format.viewport(), QRect()); + QCOMPARE(format.scanLineDirection(), QVideoSurfaceFormat::TopToBottom); + QCOMPARE(format.frameRate(), 0.0); + QCOMPARE(format.pixelAspectRatio(), QSize(1, 1)); + QCOMPARE(format.yCbCrColorSpace(), QVideoSurfaceFormat::YCbCr_Undefined); +} + +void tst_QVideoSurfaceFormat::construct_data() +{ + QTest::addColumn("frameSize"); + QTest::addColumn("pixelFormat"); + QTest::addColumn("handleType"); + QTest::addColumn("valid"); + + QTest::newRow("32x32 rgb32 no handle") + << QSize(32, 32) + << QVideoFrame::Format_RGB32 + << QAbstractVideoBuffer::NoHandle + << true; + + QTest::newRow("1024x768 YUV444 GL texture") + << QSize(32, 32) + << QVideoFrame::Format_YUV444 + << QAbstractVideoBuffer::GLTextureHandle + << true; + + QTest::newRow("32x32 invalid no handle") + << QSize(32, 32) + << QVideoFrame::Format_Invalid + << QAbstractVideoBuffer::NoHandle + << false; + + QTest::newRow("invalid size, rgb32 no handle") + << QSize() + << QVideoFrame::Format_RGB32 + << QAbstractVideoBuffer::NoHandle + << false; + + QTest::newRow("0x0 rgb32 no handle") + << QSize(0,0) + << QVideoFrame::Format_RGB32 + << QAbstractVideoBuffer::NoHandle + << true; +} + +void tst_QVideoSurfaceFormat::construct() +{ + QFETCH(QSize, frameSize); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(QAbstractVideoBuffer::HandleType, handleType); + QFETCH(bool, valid); + + QRect viewport(QPoint(0, 0), frameSize); + + QVideoSurfaceFormat format(frameSize, pixelFormat, handleType); + + QCOMPARE(format.handleType(), handleType); + QCOMPARE(format.pixelFormat(), pixelFormat); + QCOMPARE(format.frameSize(), frameSize); + QCOMPARE(format.frameWidth(), frameSize.width()); + QCOMPARE(format.frameHeight(), frameSize.height()); + QCOMPARE(format.isValid(), valid); + QCOMPARE(format.viewport(), viewport); + QCOMPARE(format.scanLineDirection(), QVideoSurfaceFormat::TopToBottom); + QCOMPARE(format.frameRate(), 0.0); + QCOMPARE(format.pixelAspectRatio(), QSize(1, 1)); + QCOMPARE(format.yCbCrColorSpace(), QVideoSurfaceFormat::YCbCr_Undefined); +} + +void tst_QVideoSurfaceFormat::frameSize_data() +{ + QTest::addColumn("initialSize"); + QTest::addColumn("newSize"); + + QTest::newRow("grow") + << QSize(64, 64) + << QSize(1024, 1024); + QTest::newRow("shrink") + << QSize(1024, 1024) + << QSize(64, 64); + QTest::newRow("unchanged") + << QSize(512, 512) + << QSize(512, 512); +} + +void tst_QVideoSurfaceFormat::frameSize() +{ + QFETCH(QSize, initialSize); + QFETCH(QSize, newSize); + + QVideoSurfaceFormat format(initialSize, QVideoFrame::Format_RGB32); + + format.setFrameSize(newSize); + + QCOMPARE(format.frameSize(), newSize); + QCOMPARE(format.property("frameSize").toSize(), newSize); + QCOMPARE(format.frameWidth(), newSize.width()); + QCOMPARE(format.property("frameWidth").toInt(), newSize.width()); + QCOMPARE(format.frameHeight(), newSize.height()); + QCOMPARE(format.property("frameHeight").toInt(), newSize.height()); +} + +void tst_QVideoSurfaceFormat::viewport_data() +{ + QTest::addColumn("initialSize"); + QTest::addColumn("viewport"); + QTest::addColumn("newSize"); + QTest::addColumn("expectedViewport"); + + QTest::newRow("grow reset") + << QSize(64, 64) + << QRect(8, 8, 48, 48) + << QSize(1024, 1024) + << QRect(0, 0, 1024, 1024); + QTest::newRow("shrink reset") + << QSize(1024, 1024) + << QRect(8, 8, 1008, 1008) + << QSize(64, 64) + << QRect(0, 0, 64, 64); + QTest::newRow("unchanged reset") + << QSize(512, 512) + << QRect(8, 8, 496, 496) + << QSize(512, 512) + << QRect(0, 0, 512, 512); +} + +void tst_QVideoSurfaceFormat::viewport() +{ + QFETCH(QSize, initialSize); + QFETCH(QRect, viewport); + QFETCH(QSize, newSize); + QFETCH(QRect, expectedViewport); + + { + QRect initialViewport(QPoint(0, 0), initialSize); + + QVideoSurfaceFormat format(initialSize, QVideoFrame::Format_RGB32); + + format.setViewport(viewport); + + QCOMPARE(format.viewport(), viewport); + QCOMPARE(format.property("viewport").toRect(), viewport); + + format.setFrameSize(newSize); + + QCOMPARE(format.viewport(), expectedViewport); + QCOMPARE(format.property("viewport").toRect(), expectedViewport); + } + { + QVideoSurfaceFormat format(initialSize, QVideoFrame::Format_RGB32); + + format.setProperty("viewport", viewport); + + QCOMPARE(format.viewport(), viewport); + QCOMPARE(format.property("viewport").toRect(), viewport); + } +} + +void tst_QVideoSurfaceFormat::scanLineDirection_data() +{ + QTest::addColumn("direction"); + + QTest::newRow("top to bottom") + << QVideoSurfaceFormat::TopToBottom; + + QTest::newRow("bottom to top") + << QVideoSurfaceFormat::BottomToTop; +} + +void tst_QVideoSurfaceFormat::scanLineDirection() +{ + QFETCH(QVideoSurfaceFormat::Direction, direction); + + { + QVideoSurfaceFormat format(QSize(16, 16), QVideoFrame::Format_RGB32); + + format.setScanLineDirection(direction); + + QCOMPARE(format.scanLineDirection(), direction); + QCOMPARE( + qvariant_cast(format.property("scanLineDirection")), + direction); + } + { + QVideoSurfaceFormat format(QSize(16, 16), QVideoFrame::Format_RGB32); + + format.setProperty("scanLineDirection", qVariantFromValue(direction)); + + QCOMPARE(format.scanLineDirection(), direction); + QCOMPARE( + qvariant_cast(format.property("scanLineDirection")), + direction); + } +} + +void tst_QVideoSurfaceFormat::frameRate_data() +{ + QTest::addColumn("frameRate"); + + QTest::newRow("null") + << qreal(0.0); + QTest::newRow("1/1") + << qreal(1.0); + QTest::newRow("24/1") + << qreal(24.0); + QTest::newRow("15/2") + << qreal(7.5); +} + +void tst_QVideoSurfaceFormat::frameRate() +{ + QFETCH(qreal, frameRate); + + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + + format.setFrameRate(frameRate); + + QCOMPARE(format.frameRate(), frameRate); + QCOMPARE(qvariant_cast(format.property("frameRate")), frameRate); + } + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + + format.setFrameRate(frameRate); + format.setProperty("frameRate", frameRate); + + QCOMPARE(format.frameRate(), frameRate); + QCOMPARE(qvariant_cast(format.property("frameRate")), frameRate); + } +} + +void tst_QVideoSurfaceFormat::yCbCrColorSpace_data() +{ + QTest::addColumn("colorspace"); + + QTest::newRow("undefined") + << QVideoSurfaceFormat::YCbCr_Undefined; + QTest::newRow("bt709") + << QVideoSurfaceFormat::YCbCr_BT709; + QTest::newRow("xvYCC601") + << QVideoSurfaceFormat::YCbCr_xvYCC601; + QTest::newRow("JPEG") + << QVideoSurfaceFormat::YCbCr_JPEG; +} + +void tst_QVideoSurfaceFormat::yCbCrColorSpace() +{ + QFETCH(QVideoSurfaceFormat::YCbCrColorSpace, colorspace); + + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + format.setYCbCrColorSpace(colorspace); + + QCOMPARE(format.yCbCrColorSpace(), colorspace); + QCOMPARE(qvariant_cast(format.property("yCbCrColorSpace")), + colorspace); + } + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + format.setProperty("yCbCrColorSpace", qVariantFromValue(colorspace)); + + QCOMPARE(format.yCbCrColorSpace(), colorspace); + QCOMPARE(qvariant_cast(format.property("yCbCrColorSpace")), + colorspace); + } +} + +void tst_QVideoSurfaceFormat::pixelAspectRatio_data() +{ + QTest::addColumn("aspectRatio"); + + QTest::newRow("1:1") + << QSize(1, 1); + QTest::newRow("4:3") + << QSize(4, 3); + QTest::newRow("16:9") + << QSize(16, 9); +} + +void tst_QVideoSurfaceFormat::pixelAspectRatio() +{ + QFETCH(QSize, aspectRatio); + + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + format.setPixelAspectRatio(aspectRatio); + + QCOMPARE(format.pixelAspectRatio(), aspectRatio); + QCOMPARE(format.property("pixelAspectRatio").toSize(), aspectRatio); + } + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + format.setPixelAspectRatio(aspectRatio.width(), aspectRatio.height()); + + QCOMPARE(format.pixelAspectRatio(), aspectRatio); + QCOMPARE(format.property("pixelAspectRatio").toSize(), aspectRatio); + } + { + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + format.setProperty("pixelAspectRatio", aspectRatio); + + QCOMPARE(format.pixelAspectRatio(), aspectRatio); + QCOMPARE(format.property("pixelAspectRatio").toSize(), aspectRatio); + } +} + +void tst_QVideoSurfaceFormat::sizeHint_data() +{ + QTest::addColumn("frameSize"); + QTest::addColumn("viewport"); + QTest::addColumn("aspectRatio"); + QTest::addColumn("sizeHint"); + + QTest::newRow("(0, 0, 1024x768), 1:1") + << QSize(1024, 768) + << QRect(0, 0, 1024, 768) + << QSize(1, 1) + << QSize(1024, 768); + QTest::newRow("0, 0, 1024x768), 4:3") + << QSize(1024, 768) + << QRect(0, 0, 1024, 768) + << QSize(4, 3) + << QSize(1365, 768); + QTest::newRow("(168, 84, 800x600), 1:1") + << QSize(1024, 768) + << QRect(168, 84, 800, 600) + << QSize(1, 1) + << QSize(800, 600); + QTest::newRow("(168, 84, 800x600), 4:3") + << QSize(1024, 768) + << QRect(168, 84, 800, 600) + << QSize(4, 3) + << QSize(1066, 600); +} + +void tst_QVideoSurfaceFormat::sizeHint() +{ + QFETCH(QSize, frameSize); + QFETCH(QRect, viewport); + QFETCH(QSize, aspectRatio); + QFETCH(QSize, sizeHint); + + QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_RGB32); + format.setViewport(viewport); + format.setPixelAspectRatio(aspectRatio); + + QCOMPARE(format.sizeHint(), sizeHint); + QCOMPARE(format.property("sizeHint").toSize(), sizeHint); +} + +void tst_QVideoSurfaceFormat::staticPropertyNames() +{ + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + + QList propertyNames = format.propertyNames(); + + QVERIFY(propertyNames.contains("handleType")); + QVERIFY(propertyNames.contains("pixelFormat")); + QVERIFY(propertyNames.contains("frameSize")); + QVERIFY(propertyNames.contains("frameWidth")); + QVERIFY(propertyNames.contains("viewport")); + QVERIFY(propertyNames.contains("scanLineDirection")); + QVERIFY(propertyNames.contains("frameRate")); + QVERIFY(propertyNames.contains("pixelAspectRatio")); + QVERIFY(propertyNames.contains("yCbCrColorSpace")); + QVERIFY(propertyNames.contains("sizeHint")); + QCOMPARE(propertyNames.count(), 10); +} + +void tst_QVideoSurfaceFormat::dynamicProperty() +{ + QVideoSurfaceFormat format(QSize(64, 64), QVideoFrame::Format_RGB32); + + QCOMPARE(format.property("integer"), QVariant()); + QCOMPARE(format.property("size"), QVariant()); + QCOMPARE(format.property("string"), QVariant()); + QCOMPARE(format.property("null"), QVariant()); + + QList propertyNames = format.propertyNames(); + + QCOMPARE(propertyNames.count(QByteArray("integer")), 0); + QCOMPARE(propertyNames.count(QByteArray("string")), 0); + QCOMPARE(propertyNames.count(QByteArray("size")), 0); + QCOMPARE(propertyNames.count(QByteArray("null")), 0); + + format.setProperty("string", QString::fromLatin1("Hello")); + format.setProperty("integer", 198); + format.setProperty("size", QSize(43, 65)); + + QCOMPARE(format.property("integer").toInt(), 198); + QCOMPARE(format.property("size").toSize(), QSize(43, 65)); + QCOMPARE(format.property("string").toString(), QString::fromLatin1("Hello")); + + propertyNames = format.propertyNames(); + + QCOMPARE(propertyNames.count(QByteArray("integer")), 1); + QCOMPARE(propertyNames.count(QByteArray("string")), 1); + QCOMPARE(propertyNames.count(QByteArray("size")), 1); + + format.setProperty("integer", 125423); + format.setProperty("size", QSize(1, 986)); + + QCOMPARE(format.property("integer").toInt(), 125423); + QCOMPARE(format.property("size").toSize(), QSize(1, 986)); + QCOMPARE(format.property("string").toString(), QString::fromLatin1("Hello")); + + propertyNames = format.propertyNames(); + + QCOMPARE(propertyNames.count(QByteArray("integer")), 1); + QCOMPARE(propertyNames.count(QByteArray("string")), 1); + QCOMPARE(propertyNames.count(QByteArray("size")), 1); + + format.setProperty("string", QVariant()); + format.setProperty("size", QVariant()); + format.setProperty("null", QVariant()); + + QCOMPARE(format.property("integer").toInt(), 125423); + QCOMPARE(format.property("size"), QVariant()); + QCOMPARE(format.property("string"), QVariant()); + QCOMPARE(format.property("null"), QVariant()); + + propertyNames = format.propertyNames(); + + QCOMPARE(propertyNames.count(QByteArray("integer")), 1); + QCOMPARE(propertyNames.count(QByteArray("string")), 0); + QCOMPARE(propertyNames.count(QByteArray("size")), 0); + QCOMPARE(propertyNames.count(QByteArray("null")), 0); +} + +void tst_QVideoSurfaceFormat::compare() +{ + QVideoSurfaceFormat format1( + QSize(16, 16), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle); + QVideoSurfaceFormat format2( + QSize(16, 16), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle); + QVideoSurfaceFormat format3( + QSize(32, 32), QVideoFrame::Format_YUV444, QAbstractVideoBuffer::GLTextureHandle); + QVideoSurfaceFormat format4( + QSize(16, 16), QVideoFrame::Format_RGB32, QAbstractVideoBuffer::UserHandle); + + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + QCOMPARE(format1 == format3, false); + QCOMPARE(format1 != format3, true); + QCOMPARE(format1 == format4, false); + QCOMPARE(format1 != format4, true); + + format2.setFrameSize(1024, 768); + + // Not equal, frame size differs. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format1.setFrameSize(1024, 768); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format1.setViewport(QRect(0, 0, 800, 600)); + format2.setViewport(QRect(112, 84, 800, 600)); + + // Not equal, viewports differ. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format1.setViewport(QRect(112, 84, 800, 600)); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format2.setScanLineDirection(QVideoSurfaceFormat::BottomToTop); + + // Not equal scan line direction differs. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format1.setScanLineDirection(QVideoSurfaceFormat::BottomToTop); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format1.setFrameRate(7.5); + + // Not equal frame rate differs. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format2.setFrameRate(qreal(7.50001)); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format2.setPixelAspectRatio(4, 3); + + // Not equal pixel aspect ratio differs. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format1.setPixelAspectRatio(QSize(4, 3)); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format2.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_xvYCC601); + + // Not equal yuv color space differs. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format1.setYCbCrColorSpace(QVideoSurfaceFormat::YCbCr_xvYCC601); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format1.setProperty("integer", 12); + + // Not equal, property mismatch. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format2.setProperty("integer", 45); + + // Not equal, integer differs. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format2.setProperty("integer", 12); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format1.setProperty("string", QString::fromLatin1("Hello")); + format2.setProperty("size", QSize(12, 54)); + + // Not equal, property mismatch. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); + + format2.setProperty("string", QString::fromLatin1("Hello")); + format1.setProperty("size", QSize(12, 54)); + + // Equal. + QCOMPARE(format1 == format2, true); + QCOMPARE(format1 != format2, false); + + format1.setProperty("string", QVariant()); + + // Not equal, property mismatch. + QCOMPARE(format1 == format2, false); + QCOMPARE(format1 != format2, true); +} + + +void tst_QVideoSurfaceFormat::copy() +{ + QVideoSurfaceFormat original( + QSize(1024, 768), QVideoFrame::Format_ARGB32, QAbstractVideoBuffer::GLTextureHandle); + original.setScanLineDirection(QVideoSurfaceFormat::BottomToTop); + + QVideoSurfaceFormat copy(original); + + QCOMPARE(copy.handleType(), QAbstractVideoBuffer::GLTextureHandle); + QCOMPARE(copy.pixelFormat(), QVideoFrame::Format_ARGB32); + QCOMPARE(copy.frameSize(), QSize(1024, 768)); + QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::BottomToTop); + + QCOMPARE(original == copy, true); + QCOMPARE(original != copy, false); + + copy.setScanLineDirection(QVideoSurfaceFormat::TopToBottom); + + QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::TopToBottom); + + QCOMPARE(original.scanLineDirection(), QVideoSurfaceFormat::BottomToTop); + + QCOMPARE(original == copy, false); + QCOMPARE(original != copy, true); +} + +void tst_QVideoSurfaceFormat::assign() +{ + QVideoSurfaceFormat copy( + QSize(64, 64), QVideoFrame::Format_AYUV444, QAbstractVideoBuffer::UserHandle); + + QVideoSurfaceFormat original( + QSize(1024, 768), QVideoFrame::Format_ARGB32, QAbstractVideoBuffer::GLTextureHandle); + original.setScanLineDirection(QVideoSurfaceFormat::BottomToTop); + + copy = original; + + QCOMPARE(copy.handleType(), QAbstractVideoBuffer::GLTextureHandle); + QCOMPARE(copy.pixelFormat(), QVideoFrame::Format_ARGB32); + QCOMPARE(copy.frameSize(), QSize(1024, 768)); + QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::BottomToTop); + + QCOMPARE(original == copy, true); + QCOMPARE(original != copy, false); + + copy.setScanLineDirection(QVideoSurfaceFormat::TopToBottom); + + QCOMPARE(copy.scanLineDirection(), QVideoSurfaceFormat::TopToBottom); + + QCOMPARE(original.scanLineDirection(), QVideoSurfaceFormat::BottomToTop); + + QCOMPARE(original == copy, false); + QCOMPARE(original != copy, true); +} + +QTEST_MAIN(tst_QVideoSurfaceFormat) + +#include "tst_qvideosurfaceformat.moc" diff --git a/tests/auto/qvideowidget/qvideowidget.pro b/tests/auto/qvideowidget/qvideowidget.pro new file mode 100644 index 000000000..07fd03a02 --- /dev/null +++ b/tests/auto/qvideowidget/qvideowidget.pro @@ -0,0 +1,10 @@ +load(qttest_p4) + +QT += multimediakit-private + +# TARGET = tst_qvideowidget +# CONFIG += testcase + +SOURCES += tst_qvideowidget.cpp + +maemo*:CONFIG += insignificant_test diff --git a/tests/auto/qvideowidget/tst_qvideowidget.cpp b/tests/auto/qvideowidget/tst_qvideowidget.cpp new file mode 100644 index 000000000..3c5e1c6c6 --- /dev/null +++ b/tests/auto/qvideowidget/tst_qvideowidget.cpp @@ -0,0 +1,1567 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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$ +** +****************************************************************************/ + +//TESTED_COMPONENT=src/multimedia + +#include +#include + +#include "qvideowidget.h" + +#include "qmediaobject.h" +#include "qmediaservice.h" +#include +#include "qvideowindowcontrol.h" +#include "qvideowidgetcontrol.h" + +#include "qvideorenderercontrol.h" +#include +#include + +#include + +QT_USE_NAMESPACE +class tst_QVideoWidget : public QObject +{ + Q_OBJECT +private slots: + void nullObject(); + void nullService(); + void noOutputs(); + void serviceDestroyed(); + void objectDestroyed(); + void setMediaObject(); + + void showWindowControl(); + void fullScreenWindowControl(); + void aspectRatioWindowControl(); + void sizeHintWindowControl_data() { sizeHint_data(); } + void sizeHintWindowControl(); + void brightnessWindowControl_data() { color_data(); } + void brightnessWindowControl(); + void contrastWindowControl_data() { color_data(); } + void contrastWindowControl(); + void hueWindowControl_data() { color_data(); } + void hueWindowControl(); + void saturationWindowControl_data() { color_data(); } + void saturationWindowControl(); + + void showWidgetControl(); + void fullScreenWidgetControl(); + void aspectRatioWidgetControl(); + void sizeHintWidgetControl_data() { sizeHint_data(); } + void sizeHintWidgetControl(); + void brightnessWidgetControl_data() { color_data(); } + void brightnessWidgetControl(); + void contrastWidgetControl_data() { color_data(); } + void contrastWidgetControl(); + void hueWidgetControl_data() { color_data(); } + void hueWidgetControl(); + void saturationWidgetControl_data() { color_data(); } + void saturationWidgetControl(); + + void showRendererControl(); + void fullScreenRendererControl(); + void aspectRatioRendererControl(); + void sizeHintRendererControl_data(); + void sizeHintRendererControl(); + void brightnessRendererControl_data() { color_data(); } + void brightnessRendererControl(); + void contrastRendererControl_data() { color_data(); } + void contrastRendererControl(); + void hueRendererControl_data() { color_data(); } + void hueRendererControl(); + void saturationRendererControl_data() { color_data(); } + void saturationRendererControl(); + + void paintRendererControl(); + +private: + void sizeHint_data(); + void color_data(); +}; + +Q_DECLARE_METATYPE(Qt::AspectRatioMode) +Q_DECLARE_METATYPE(const uchar *) + +class QtTestWindowControl : public QVideoWindowControl +{ +public: + QtTestWindowControl() + : m_winId(0) + , m_repaintCount(0) + , m_brightness(0) + , m_contrast(0) + , m_saturation(0) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_fullScreen(0) + { + } + + WId winId() const { return m_winId; } + void setWinId(WId id) { m_winId = id; } + + QRect displayRect() const { return m_displayRect; } + void setDisplayRect(const QRect &rect) { m_displayRect = rect; } + + bool isFullScreen() const { return m_fullScreen; } + void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); } + + int repaintCount() const { return m_repaintCount; } + void setRepaintCount(int count) { m_repaintCount = count; } + void repaint() { ++m_repaintCount; } + + QSize nativeSize() const { return m_nativeSize; } + void setNativeSize(const QSize &size) { m_nativeSize = size; emit nativeSizeChanged(); } + + Qt::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; } + void setAspectRatioMode(Qt::AspectRatioMode mode) { m_aspectRatioMode = mode; } + + int brightness() const { return m_brightness; } + void setBrightness(int brightness) { emit brightnessChanged(m_brightness = brightness); } + + int contrast() const { return m_contrast; } + void setContrast(int contrast) { emit contrastChanged(m_contrast = contrast); } + + int hue() const { return m_hue; } + void setHue(int hue) { emit hueChanged(m_hue = hue); } + + int saturation() const { return m_saturation; } + void setSaturation(int saturation) { emit saturationChanged(m_saturation = saturation); } + +private: + WId m_winId; + int m_repaintCount; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; + Qt::AspectRatioMode m_aspectRatioMode; + QRect m_displayRect; + QSize m_nativeSize; + bool m_fullScreen; +}; + +class QtTestWidgetControl : public QVideoWidgetControl +{ +public: + QtTestWidgetControl() + : m_brightness(1.0) + , m_contrast(1.0) + , m_hue(1.0) + , m_saturation(1.0) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_fullScreen(false) + { + } + + bool isFullScreen() const { return m_fullScreen; } + void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); } + + Qt::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; } + void setAspectRatioMode(Qt::AspectRatioMode mode) { m_aspectRatioMode = mode; } + + int brightness() const { return m_brightness; } + void setBrightness(int brightness) { emit brightnessChanged(m_brightness = brightness); } + + int contrast() const { return m_contrast; } + void setContrast(int contrast) { emit contrastChanged(m_contrast = contrast); } + + int hue() const { return m_hue; } + void setHue(int hue) { emit hueChanged(m_hue = hue); } + + int saturation() const { return m_saturation; } + void setSaturation(int saturation) { emit saturationChanged(m_saturation = saturation); } + + void setSizeHint(const QSize &size) { m_widget.setSizeHint(size); } + + QWidget *videoWidget() { return &m_widget; } + +private: + class Widget : public QWidget + { + public: + QSize sizeHint() const { return m_sizeHint; } + void setSizeHint(const QSize &size) { m_sizeHint = size; updateGeometry(); } + private: + QSize m_sizeHint; + } m_widget; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; + Qt::AspectRatioMode m_aspectRatioMode; + QSize m_sizeHint; + bool m_fullScreen; +}; + +class QtTestRendererControl : public QVideoRendererControl +{ +public: + QtTestRendererControl() + : m_surface(0) + { + } + + QAbstractVideoSurface *surface() const { return m_surface; } + void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; } + +private: + QAbstractVideoSurface *m_surface; +}; + +class QtTestVideoService : public QMediaService +{ + Q_OBJECT +public: + QtTestVideoService( + QtTestWindowControl *window, + QtTestWidgetControl *widget, + QtTestRendererControl *renderer) + : QMediaService(0) + , windowRef(0) + , widgetRef(0) + , rendererRef(0) + , windowControl(window) + , widgetControl(widget) + , rendererControl(renderer) + { + } + + ~QtTestVideoService() + { + delete windowControl; + delete widgetControl; + delete rendererControl; + } + + QMediaControl *requestControl(const char *name) + { + if (qstrcmp(name, QVideoWindowControl_iid) == 0) { + if (windowControl) { + windowRef += 1; + + return windowControl; + } + } else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) { + if (widgetControl) { + widgetRef += 1; + + return widgetControl; + } + } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) { + if (rendererControl) { + rendererRef += 1; + + return rendererControl; + } + } + return 0; + } + + void releaseControl(QMediaControl *control) + { + Q_ASSERT(control); + + if (control == windowControl) + windowRef -= 1; + else if (control == widgetControl) + widgetRef -= 1; + else if (control == rendererControl) + rendererRef -= 1; + } + + int windowRef; + int widgetRef; + int rendererRef; + + QtTestWindowControl *windowControl; + QtTestWidgetControl *widgetControl; + QtTestRendererControl *rendererControl; +}; + +class QtTestVideoObject : public QMediaObject +{ + Q_OBJECT +public: + QtTestVideoObject( + QtTestWindowControl *window, + QtTestWidgetControl *widget, + QtTestRendererControl *renderer): + QMediaObject(0, new QtTestVideoService(window, widget, renderer)) + { + testService = qobject_cast(service()); + } + + QtTestVideoObject(QtTestVideoService *service): + QMediaObject(0, service), + testService(service) + { + } + + ~QtTestVideoObject() + { + delete testService; + } + + QtTestVideoService *testService; +}; + +void tst_QVideoWidget::nullObject() +{ + QVideoWidget widget; + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QVERIFY(widget.sizeHint().isEmpty()); + + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), true); + + widget.setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio); + + { + QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int))); + + widget.setBrightness(100); + QCOMPARE(widget.brightness(), 100); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), 100); + + widget.setBrightness(100); + QCOMPARE(widget.brightness(), 100); + QCOMPARE(spy.count(), 1); + + widget.setBrightness(-120); + QCOMPARE(widget.brightness(), -100); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), -100); + } { + QSignalSpy spy(&widget, SIGNAL(contrastChanged(int))); + + widget.setContrast(100); + QCOMPARE(widget.contrast(), 100); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), 100); + + widget.setContrast(100); + QCOMPARE(widget.contrast(), 100); + QCOMPARE(spy.count(), 1); + + widget.setContrast(-120); + QCOMPARE(widget.contrast(), -100); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), -100); + } { + QSignalSpy spy(&widget, SIGNAL(hueChanged(int))); + + widget.setHue(100); + QCOMPARE(widget.hue(), 100); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), 100); + + widget.setHue(100); + QCOMPARE(widget.hue(), 100); + QCOMPARE(spy.count(), 1); + + widget.setHue(-120); + QCOMPARE(widget.hue(), -100); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), -100); + } { + QSignalSpy spy(&widget, SIGNAL(saturationChanged(int))); + + widget.setSaturation(100); + QCOMPARE(widget.saturation(), 100); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), 100); + + widget.setSaturation(100); + QCOMPARE(widget.saturation(), 100); + QCOMPARE(spy.count(), 1); + + widget.setSaturation(-120); + QCOMPARE(widget.saturation(), -100); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), -100); + } +} + +void tst_QVideoWidget::nullService() +{ + QtTestVideoObject object(0); + + QVideoWidget widget; + object.bind(&widget); + + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QVERIFY(widget.sizeHint().isEmpty()); + + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), true); + + widget.setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio); + + widget.setBrightness(100); + QCOMPARE(widget.brightness(), 100); + + widget.setContrast(100); + QCOMPARE(widget.contrast(), 100); + + widget.setHue(100); + QCOMPARE(widget.hue(), 100); + + widget.setSaturation(100); + QCOMPARE(widget.saturation(), 100); +} + +void tst_QVideoWidget::noOutputs() +{ + QtTestVideoObject object(0, 0, 0); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QVERIFY(widget.sizeHint().isEmpty()); + + widget.setFullScreen(true); + QCOMPARE(widget.isFullScreen(), true); + + widget.setBrightness(100); + QCOMPARE(widget.brightness(), 100); + + widget.setContrast(100); + QCOMPARE(widget.contrast(), 100); + + widget.setHue(100); + QCOMPARE(widget.hue(), 100); + + widget.setSaturation(100); + QCOMPARE(widget.saturation(), 100); +} + +void tst_QVideoWidget::serviceDestroyed() +{ + QtTestVideoObject object(new QtTestWindowControl, new QtTestWidgetControl, 0); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + widget.setBrightness(100); + widget.setContrast(100); + widget.setHue(100); + widget.setSaturation(100); + + delete object.testService; + object.testService = 0; + + QCOMPARE(widget.mediaObject(), static_cast(&object)); + + QCOMPARE(widget.brightness(), 100); + QCOMPARE(widget.contrast(), 100); + QCOMPARE(widget.hue(), 100); + QCOMPARE(widget.saturation(), 100); + + widget.setFullScreen(true); + QCOMPARE(widget.isFullScreen(), true); +} + +void tst_QVideoWidget::objectDestroyed() +{ + QtTestVideoObject *object = new QtTestVideoObject( + new QtTestWindowControl, + new QtTestWidgetControl, + 0); + + QVideoWidget widget; + object->bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(object->testService->windowRef, 0); + QCOMPARE(object->testService->widgetRef, 1); + QCOMPARE(object->testService->rendererRef, 0); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + widget.setBrightness(100); + widget.setContrast(100); + widget.setHue(100); + widget.setSaturation(100); + + // Delete the media object without deleting the service. + QtTestVideoService *service = object->testService; + object->testService = 0; + + delete object; + object = 0; + + QCOMPARE(widget.mediaObject(), static_cast(object)); + + QCOMPARE(widget.brightness(), 100); + QCOMPARE(widget.contrast(), 100); + QCOMPARE(widget.hue(), 100); + QCOMPARE(widget.saturation(), 100); + + widget.setFullScreen(true); + QCOMPARE(widget.isFullScreen(), true); + + delete service; +} + +void tst_QVideoWidget::setMediaObject() +{ + QMediaObject *nullObject = 0; + QtTestVideoObject windowObject(new QtTestWindowControl, 0, 0); + QtTestVideoObject widgetObject(0, new QtTestWidgetControl, 0); + QtTestVideoObject rendererObject(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QCOMPARE(widget.mediaObject(), nullObject); + QCOMPARE(windowObject.testService->windowRef, 0); + QCOMPARE(widgetObject.testService->widgetRef, 0); + QCOMPARE(rendererObject.testService->rendererRef, 0); + + windowObject.bind(&widget); + QCOMPARE(widget.mediaObject(), static_cast(&windowObject)); + QCOMPARE(windowObject.testService->windowRef, 1); + QCOMPARE(widgetObject.testService->widgetRef, 0); + QCOMPARE(rendererObject.testService->rendererRef, 0); + QVERIFY(windowObject.testService->windowControl->winId() != 0); + + + widgetObject.bind(&widget); + QCOMPARE(widget.mediaObject(), static_cast(&widgetObject)); + QCOMPARE(windowObject.testService->windowRef, 0); + QCOMPARE(widgetObject.testService->widgetRef, 1); + QCOMPARE(rendererObject.testService->rendererRef, 0); + + QCoreApplication::processEvents(QEventLoop::AllEvents); + QCOMPARE(widgetObject.testService->widgetControl->videoWidget()->isVisible(), true); + + QCOMPARE(windowObject.testService->windowRef, 0); + QCOMPARE(widgetObject.testService->widgetRef, 1); + QCOMPARE(rendererObject.testService->rendererRef, 0); + + rendererObject.bind(&widget); + QCOMPARE(widget.mediaObject(), static_cast(&rendererObject)); + + QCOMPARE(windowObject.testService->windowRef, 0); + QCOMPARE(widgetObject.testService->widgetRef, 0); + QCOMPARE(rendererObject.testService->rendererRef, 1); + QVERIFY(rendererObject.testService->rendererControl->surface() != 0); + + rendererObject.unbind(&widget); + QCOMPARE(widget.mediaObject(), nullObject); + + QCOMPARE(windowObject.testService->windowRef, 0); + QCOMPARE(widgetObject.testService->widgetRef, 0); + QCOMPARE(rendererObject.testService->rendererRef, 0); +} + +void tst_QVideoWidget::showWindowControl() +{ + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setNativeSize(QSize(240, 180)); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QVERIFY(object.testService->windowControl->winId() != 0); + QVERIFY(object.testService->windowControl->repaintCount() > 0); + + widget.resize(640, 480); + QCOMPARE(object.testService->windowControl->displayRect(), QRect(0, 0, 640, 480)); + + widget.move(10, 10); + QCOMPARE(object.testService->windowControl->displayRect(), QRect(0, 0, 640, 480)); + + widget.hide(); +} + +void tst_QVideoWidget::showWidgetControl() +{ + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), true); + + widget.resize(640, 480); + + widget.move(10, 10); + + widget.hide(); + + QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), false); +} + +void tst_QVideoWidget::showRendererControl() +{ + QtTestVideoObject object(0, 0, new QtTestRendererControl); + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QVERIFY(object.testService->rendererControl->surface() != 0); + + widget.resize(640, 480); + + widget.move(10, 10); + + widget.hide(); +} + +void tst_QVideoWidget::aspectRatioWindowControl() +{ + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + // Test the aspect ratio defaults to keeping the aspect ratio. + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + + // Test the control has been informed of the aspect ratio change, post show. + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + QCOMPARE(object.testService->windowControl->aspectRatioMode(), Qt::KeepAspectRatio); + + // Test an aspect ratio change is enforced immediately while visible. + widget.setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio); + QCOMPARE(object.testService->windowControl->aspectRatioMode(), Qt::IgnoreAspectRatio); + + // Test an aspect ratio set while not visible is respected. + widget.hide(); + widget.setAspectRatioMode(Qt::KeepAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + widget.show(); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + QCOMPARE(object.testService->windowControl->aspectRatioMode(), Qt::KeepAspectRatio); +} + +void tst_QVideoWidget::aspectRatioWidgetControl() +{ + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + object.testService->widgetControl->setAspectRatioMode(Qt::IgnoreAspectRatio); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + // Test the aspect ratio defaults to keeping the aspect ratio. + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + + // Test the control has been informed of the aspect ratio change, post show. + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + QCOMPARE(object.testService->widgetControl->aspectRatioMode(), Qt::KeepAspectRatio); + + // Test an aspect ratio change is enforced immediately while visible. + widget.setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio); + QCOMPARE(object.testService->widgetControl->aspectRatioMode(), Qt::IgnoreAspectRatio); + + // Test an aspect ratio set while not visible is respected. + widget.hide(); + widget.setAspectRatioMode(Qt::KeepAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + widget.show(); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + QCOMPARE(object.testService->widgetControl->aspectRatioMode(), Qt::KeepAspectRatio); +} + +void tst_QVideoWidget::aspectRatioRendererControl() +{ + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + // Test the aspect ratio defaults to keeping the aspect ratio. + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + + // Test the control has been informed of the aspect ratio change, post show. + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + + // Test an aspect ratio change is enforced immediately while visible. + widget.setAspectRatioMode(Qt::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::IgnoreAspectRatio); + + // Test an aspect ratio set while not visible is respected. + widget.hide(); + widget.setAspectRatioMode(Qt::KeepAspectRatio); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); + widget.show(); + QCOMPARE(widget.aspectRatioMode(), Qt::KeepAspectRatio); +} + +void tst_QVideoWidget::sizeHint_data() +{ + QTest::addColumn("size"); + + QTest::newRow("720x576") + << QSize(720, 576); +} + +void tst_QVideoWidget::sizeHintWindowControl() +{ + QFETCH(QSize, size); + + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QVERIFY(widget.sizeHint().isEmpty()); + + object.testService->windowControl->setNativeSize(size); + QCOMPARE(widget.sizeHint(), size); +} + +void tst_QVideoWidget::sizeHintWidgetControl() +{ + QFETCH(QSize, size); + + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QVERIFY(widget.sizeHint().isEmpty()); + + object.testService->widgetControl->setSizeHint(size); + QCOMPARE(widget.sizeHint(), size); +} + +void tst_QVideoWidget::sizeHintRendererControl_data() +{ + QTest::addColumn("frameSize"); + QTest::addColumn("viewport"); + QTest::addColumn("pixelAspectRatio"); + QTest::addColumn("expectedSize"); + + QTest::newRow("640x480") + << QSize(640, 480) + << QRect(0, 0, 640, 480) + << QSize(1, 1) + << QSize(640, 480); + + QTest::newRow("800x600, (80,60, 640x480) viewport") + << QSize(800, 600) + << QRect(80, 60, 640, 480) + << QSize(1, 1) + << QSize(640, 480); + + QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3") + << QSize(800, 600) + << QRect(80, 60, 640, 480) + << QSize(4, 3) + << QSize(853, 480); + +} + +void tst_QVideoWidget::sizeHintRendererControl() +{ + QFETCH(QSize, frameSize); + QFETCH(QRect, viewport); + QFETCH(QSize, pixelAspectRatio); + QFETCH(QSize, expectedSize); + + QtTestVideoObject object(0, 0, new QtTestRendererControl); + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32); + format.setViewport(viewport); + format.setPixelAspectRatio(pixelAspectRatio); + + QVERIFY(object.testService->rendererControl->surface()->start(format)); + + QCOMPARE(widget.sizeHint(), expectedSize); +} + + +void tst_QVideoWidget::fullScreenWindowControl() +{ + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + QVideoWidget widget; + object.bind(&widget); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + Qt::WindowFlags windowFlags = widget.windowFlags(); + + QSignalSpy spy(&widget, SIGNAL(fullScreenChanged(bool))); + + // Test showing full screen with setFullScreen(true). + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->windowControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toBool(), true); + + // Test returning to normal with setFullScreen(false). + widget.setFullScreen(false); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->windowControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toBool(), false); + QCOMPARE(widget.windowFlags(), windowFlags); + + // Test showing full screen with showFullScreen(). + widget.showFullScreen(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->windowControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 3); + QCOMPARE(spy.value(2).value(0).toBool(), true); + + // Test returning to normal with showNormal(). + widget.showNormal(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->windowControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + QCOMPARE(spy.value(3).value(0).toBool(), false); + QCOMPARE(widget.windowFlags(), windowFlags); + + // Test setFullScreen(false) and showNormal() do nothing when isFullScreen() == false. + widget.setFullScreen(false); + QCOMPARE(object.testService->windowControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + widget.showNormal(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->windowControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + + // Test setFullScreen(true) and showFullScreen() do nothing when isFullScreen() == true. + widget.showFullScreen(); + QTest::qWaitForWindowShown(&widget); + widget.setFullScreen(true); + QCOMPARE(object.testService->windowControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 5); + widget.showFullScreen(); + QCOMPARE(object.testService->windowControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 5); + + // Test if the window control exits full screen mode, the widget follows suit. + object.testService->windowControl->setFullScreen(false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 6); + QCOMPARE(spy.value(5).value(0).toBool(), false); + + // Test if the window control enters full screen mode, the widget does nothing. + object.testService->windowControl->setFullScreen(false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 6); +} + +void tst_QVideoWidget::fullScreenWidgetControl() +{ + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + QVideoWidget widget; + object.bind(&widget); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + Qt::WindowFlags windowFlags = widget.windowFlags(); + + QSignalSpy spy(&widget, SIGNAL(fullScreenChanged(bool))); + + // Test showing full screen with setFullScreen(true). + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->widgetControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toBool(), true); + + // Test returning to normal with setFullScreen(false). + widget.setFullScreen(false); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->widgetControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toBool(), false); + QCOMPARE(widget.windowFlags(), windowFlags); + + // Test showing full screen with showFullScreen(). + widget.showFullScreen(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->widgetControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 3); + QCOMPARE(spy.value(2).value(0).toBool(), true); + + // Test returning to normal with showNormal(). + widget.showNormal(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(object.testService->widgetControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + QCOMPARE(spy.value(3).value(0).toBool(), false); + QCOMPARE(widget.windowFlags(), windowFlags); + + // Test setFullScreen(false) and showNormal() do nothing when isFullScreen() == false. + widget.setFullScreen(false); + QCOMPARE(object.testService->widgetControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + widget.showNormal(); + QCOMPARE(object.testService->widgetControl->isFullScreen(), false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + + // Test setFullScreen(true) and showFullScreen() do nothing when isFullScreen() == true. + widget.showFullScreen(); + QTest::qWaitForWindowShown(&widget); + widget.setFullScreen(true); + QCOMPARE(object.testService->widgetControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 5); + widget.showFullScreen(); + QCOMPARE(object.testService->widgetControl->isFullScreen(), true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 5); + + // Test if the window control exits full screen mode, the widget follows suit. + object.testService->widgetControl->setFullScreen(false); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 6); + QCOMPARE(spy.value(5).value(0).toBool(), false); + + // Test if the window control enters full screen mode, the widget does nothing. + object.testService->widgetControl->setFullScreen(false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 6); +} + + +void tst_QVideoWidget::fullScreenRendererControl() +{ + QtTestVideoObject object(0, 0, new QtTestRendererControl); + QVideoWidget widget; + object.bind(&widget); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + Qt::WindowFlags windowFlags = widget.windowFlags(); + + QSignalSpy spy(&widget, SIGNAL(fullScreenChanged(bool))); + + // Test showing full screen with setFullScreen(true). + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toBool(), true); + + // Test returning to normal with setFullScreen(false). + widget.setFullScreen(false); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toBool(), false); + QCOMPARE(widget.windowFlags(), windowFlags); + + // Test showing full screen with showFullScreen(). + widget.showFullScreen(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 3); + QCOMPARE(spy.value(2).value(0).toBool(), true); + + // Test returning to normal with showNormal(). + widget.showNormal(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + QCOMPARE(spy.value(3).value(0).toBool(), false); + QCOMPARE(widget.windowFlags(), windowFlags); + + // Test setFullScreen(false) and showNormal() do nothing when isFullScreen() == false. + widget.setFullScreen(false); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + widget.showNormal(); + QCOMPARE(widget.isFullScreen(), false); + QCOMPARE(spy.count(), 4); + + // Test setFullScreen(true) and showFullScreen() do nothing when isFullScreen() == true. + widget.showFullScreen(); + QTest::qWaitForWindowShown(&widget); + widget.setFullScreen(true); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 5); + widget.showFullScreen(); + QCOMPARE(widget.isFullScreen(), true); + QCOMPARE(spy.count(), 5); +} + + +void tst_QVideoWidget::color_data() +{ + QTest::addColumn("controlValue"); + QTest::addColumn("value"); + QTest::addColumn("expectedValue"); + + QTest::newRow("12") + << 0 + << 12 + << 12; + QTest::newRow("-56") + << 87 + << -56 + << -56; + QTest::newRow("100") + << 32 + << 100 + << 100; + QTest::newRow("1294") + << 0 + << 1294 + << 100; + QTest::newRow("-102") + << 34 + << -102 + << -100; +} + +void tst_QVideoWidget::brightnessWindowControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setBrightness(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + // Test the video widget resets the controls starting brightness to the default. + QCOMPARE(widget.brightness(), 0); + + QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int))); + + // Test the video widget sets the brightness value, bounded if necessary and emits a changed + // signal. + widget.setBrightness(value); + QCOMPARE(widget.brightness(), expectedValue); + QCOMPARE(object.testService->windowControl->brightness(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + // Test the changed signal isn't emitted if the value is unchanged. + widget.setBrightness(value); + QCOMPARE(widget.brightness(), expectedValue); + QCOMPARE(object.testService->windowControl->brightness(), expectedValue); + QCOMPARE(spy.count(), 1); + + // Test the changed signal is emitted if the brightness is changed internally. + object.testService->windowControl->setBrightness(controlValue); + QCOMPARE(widget.brightness(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::brightnessWidgetControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + object.testService->widgetControl->setBrightness(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(widget.brightness(), 0); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int))); + + widget.setBrightness(value); + QCOMPARE(widget.brightness(), expectedValue); + QCOMPARE(object.testService->widgetControl->brightness(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setBrightness(value); + QCOMPARE(widget.brightness(), expectedValue); + QCOMPARE(object.testService->widgetControl->brightness(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->widgetControl->setBrightness(controlValue); + QCOMPARE(widget.brightness(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::brightnessRendererControl() +{ + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QSignalSpy spy(&widget, SIGNAL(brightnessChanged(int))); + + widget.setBrightness(value); + QCOMPARE(widget.brightness(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setBrightness(value); + QCOMPARE(widget.brightness(), expectedValue); + QCOMPARE(spy.count(), 1); +} + +void tst_QVideoWidget::contrastWindowControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setContrast(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(widget.contrast(), 0); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.contrast(), 0); + + QSignalSpy spy(&widget, SIGNAL(contrastChanged(int))); + + widget.setContrast(value); + QCOMPARE(widget.contrast(), expectedValue); + QCOMPARE(object.testService->windowControl->contrast(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setContrast(value); + QCOMPARE(widget.contrast(), expectedValue); + QCOMPARE(object.testService->windowControl->contrast(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->windowControl->setContrast(controlValue); + QCOMPARE(widget.contrast(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::contrastWidgetControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + object.testService->widgetControl->setContrast(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + QCOMPARE(widget.contrast(), 0); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.contrast(), 0); + + QSignalSpy spy(&widget, SIGNAL(contrastChanged(int))); + + widget.setContrast(value); + QCOMPARE(widget.contrast(), expectedValue); + QCOMPARE(object.testService->widgetControl->contrast(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setContrast(value); + QCOMPARE(widget.contrast(), expectedValue); + QCOMPARE(object.testService->widgetControl->contrast(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->widgetControl->setContrast(controlValue); + QCOMPARE(widget.contrast(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::contrastRendererControl() +{ + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QSignalSpy spy(&widget, SIGNAL(contrastChanged(int))); + + widget.setContrast(value); + QCOMPARE(widget.contrast(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setContrast(value); + QCOMPARE(widget.contrast(), expectedValue); + QCOMPARE(spy.count(), 1); +} + +void tst_QVideoWidget::hueWindowControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setHue(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + QCOMPARE(widget.hue(), 0); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.hue(), 0); + + QSignalSpy spy(&widget, SIGNAL(hueChanged(int))); + + widget.setHue(value); + QCOMPARE(widget.hue(), expectedValue); + QCOMPARE(object.testService->windowControl->hue(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setHue(value); + QCOMPARE(widget.hue(), expectedValue); + QCOMPARE(object.testService->windowControl->hue(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->windowControl->setHue(controlValue); + QCOMPARE(widget.hue(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::hueWidgetControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + object.testService->widgetControl->setHue(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + QCOMPARE(widget.hue(), 0); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.hue(), 0); + + QSignalSpy spy(&widget, SIGNAL(hueChanged(int))); + + widget.setHue(value); + QCOMPARE(widget.hue(), expectedValue); + QCOMPARE(object.testService->widgetControl->hue(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setHue(value); + QCOMPARE(widget.hue(), expectedValue); + QCOMPARE(object.testService->widgetControl->hue(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->widgetControl->setHue(controlValue); + QCOMPARE(widget.hue(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::hueRendererControl() +{ + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QSignalSpy spy(&widget, SIGNAL(hueChanged(int))); + + widget.setHue(value); + QCOMPARE(widget.hue(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setHue(value); + QCOMPARE(widget.hue(), expectedValue); + QCOMPARE(spy.count(), 1); +} + +void tst_QVideoWidget::saturationWindowControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setSaturation(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + QCOMPARE(widget.saturation(), 0); + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.saturation(), 0); + + QSignalSpy spy(&widget, SIGNAL(saturationChanged(int))); + + widget.setSaturation(value); + QCOMPARE(widget.saturation(), expectedValue); + QCOMPARE(object.testService->windowControl->saturation(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setSaturation(value); + QCOMPARE(widget.saturation(), expectedValue); + QCOMPARE(object.testService->windowControl->saturation(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->windowControl->setSaturation(controlValue); + QCOMPARE(widget.saturation(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); +} + +void tst_QVideoWidget::saturationWidgetControl() +{ + QFETCH(int, controlValue); + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + object.testService->widgetControl->setSaturation(controlValue); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(widget.saturation(), 0); + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.saturation(), 0); + + QSignalSpy spy(&widget, SIGNAL(saturationChanged(int))); + + widget.setSaturation(value); + QCOMPARE(widget.saturation(), expectedValue); + QCOMPARE(object.testService->widgetControl->saturation(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setSaturation(value); + QCOMPARE(widget.saturation(), expectedValue); + QCOMPARE(object.testService->widgetControl->saturation(), expectedValue); + QCOMPARE(spy.count(), 1); + + object.testService->widgetControl->setSaturation(controlValue); + QCOMPARE(widget.saturation(), controlValue); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.value(1).value(0).toInt(), controlValue); + +} + +void tst_QVideoWidget::saturationRendererControl() +{ + QFETCH(int, value); + QFETCH(int, expectedValue); + + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.show(); + QTest::qWaitForWindowShown(&widget); + QSignalSpy spy(&widget, SIGNAL(saturationChanged(int))); + + widget.setSaturation(value); + QCOMPARE(widget.saturation(), expectedValue); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.value(0).value(0).toInt(), expectedValue); + + widget.setSaturation(value); + QCOMPARE(widget.saturation(), expectedValue); + QCOMPARE(spy.count(), 1); +} + +static const uchar rgb32ImageData[] = +{ + 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00 +}; + +void tst_QVideoWidget::paintRendererControl() +{ + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + object.bind(&widget); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + widget.resize(640,480); + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QPainterVideoSurface *surface = qobject_cast( + object.testService->rendererControl->surface()); + + QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32); + + QVERIFY(surface->start(format)); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); + + QCoreApplication::processEvents(QEventLoop::AllEvents); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); + + QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32); + + frame.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes()); + frame.unmap(); + + QVERIFY(surface->present(frame)); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), false); + + //wait up to 2 seconds for the frame to be presented + for (int i=0; i<200 && !surface->isReady(); i++) + QTest::qWait(10); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); +} + +QTEST_MAIN(tst_QVideoWidget) + +#include "tst_qvideowidget.moc" diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 000000000..2bd49bd97 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs +SUBDIRS += auto + +# Disabled since we don't have any source. +# SUBDIRS += benchmarks manual -- cgit v1.2.3