From f53271c1cac46ad63612e951e34ffae34328fec6 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 15 Jan 2010 14:12:40 +1000 Subject: Move QtMobility multimedia framework into Qt. --- demos/demos.pro | 2 + demos/multimedia/multimedia.pro | 4 + src/multimedia/base/base.pri | 62 + src/multimedia/base/qgraphicsvideoitem.cpp | 299 ++++ src/multimedia/base/qgraphicsvideoitem.h | 92 ++ .../base/qlocalmediaplaylistprovider.cpp | 196 +++ src/multimedia/base/qlocalmediaplaylistprovider.h | 87 ++ src/multimedia/base/qmediacontent.cpp | 219 +++ src/multimedia/base/qmediacontent.h | 90 ++ src/multimedia/base/qmediacontrol.cpp | 139 ++ src/multimedia/base/qmediacontrol.h | 82 + src/multimedia/base/qmediacontrol_p.h | 74 + src/multimedia/base/qmediaobject.cpp | 418 +++++ src/multimedia/base/qmediaobject.h | 121 ++ src/multimedia/base/qmediaobject_p.h | 94 ++ src/multimedia/base/qmediaplaylist.cpp | 719 +++++++++ src/multimedia/base/qmediaplaylist.h | 147 ++ src/multimedia/base/qmediaplaylist_p.h | 172 +++ src/multimedia/base/qmediaplaylistcontrol.cpp | 203 +++ src/multimedia/base/qmediaplaylistcontrol.h | 97 ++ src/multimedia/base/qmediaplaylistioplugin.cpp | 189 +++ src/multimedia/base/qmediaplaylistioplugin.h | 126 ++ src/multimedia/base/qmediaplaylistnavigator.cpp | 544 +++++++ src/multimedia/base/qmediaplaylistnavigator.h | 116 ++ src/multimedia/base/qmediaplaylistprovider.cpp | 307 ++++ src/multimedia/base/qmediaplaylistprovider.h | 114 ++ src/multimedia/base/qmediaplaylistprovider_p.h | 75 + src/multimedia/base/qmediapluginloader.cpp | 134 ++ src/multimedia/base/qmediapluginloader_p.h | 92 ++ src/multimedia/base/qmediaresource.cpp | 378 +++++ src/multimedia/base/qmediaresource.h | 130 ++ src/multimedia/base/qmediaservice.cpp | 139 ++ src/multimedia/base/qmediaservice.h | 90 ++ src/multimedia/base/qmediaservice_p.h | 74 + src/multimedia/base/qmediaserviceprovider.cpp | 678 +++++++++ src/multimedia/base/qmediaserviceprovider.h | 169 +++ src/multimedia/base/qmediaserviceproviderplugin.h | 125 ++ src/multimedia/base/qmediatimerange.cpp | 706 +++++++++ src/multimedia/base/qmediatimerange.h | 135 ++ src/multimedia/base/qmetadatacontrol.cpp | 185 +++ src/multimedia/base/qmetadatacontrol.h | 92 ++ src/multimedia/base/qpaintervideosurface.cpp | 1456 ++++++++++++++++++ src/multimedia/base/qpaintervideosurface_p.h | 155 ++ src/multimedia/base/qtmedianamespace.h | 189 +++ src/multimedia/base/qtmedianamespace.qdoc | 210 +++ src/multimedia/base/qvideodevicecontrol.cpp | 154 ++ src/multimedia/base/qvideodevicecontrol.h | 90 ++ src/multimedia/base/qvideooutputcontrol.cpp | 135 ++ src/multimedia/base/qvideooutputcontrol.h | 91 ++ src/multimedia/base/qvideorenderercontrol.cpp | 124 ++ src/multimedia/base/qvideorenderercontrol.h | 77 + src/multimedia/base/qvideowidget.cpp | 916 +++++++++++ src/multimedia/base/qvideowidget.h | 134 ++ src/multimedia/base/qvideowidget_p.h | 265 ++++ src/multimedia/base/qvideowidgetcontrol.cpp | 235 +++ src/multimedia/base/qvideowidgetcontrol.h | 105 ++ src/multimedia/base/qvideowindowcontrol.cpp | 274 ++++ src/multimedia/base/qvideowindowcontrol.h | 111 ++ src/multimedia/multimedia.pro | 5 +- src/multimedia/playback/playback.pri | 11 + src/multimedia/playback/qmediaplayer.cpp | 930 ++++++++++++ src/multimedia/playback/qmediaplayer.h | 199 +++ src/multimedia/playback/qmediaplayercontrol.cpp | 362 +++++ src/multimedia/playback/qmediaplayercontrol.h | 129 ++ src/multimedia/qml/qml.pri | 11 + src/multimedia/qml/qmlsound.cpp | 168 +++ src/multimedia/qml/qmlsound_p.h | 126 ++ src/plugins/mediaservices/mediaservices.pro | 5 + src/plugins/mediaservices/qt7/qcvdisplaylink.h | 90 ++ src/plugins/mediaservices/qt7/qcvdisplaylink.mm | 159 ++ src/plugins/mediaservices/qt7/qt7.pro | 52 + src/plugins/mediaservices/qt7/qt7backend.h | 68 + src/plugins/mediaservices/qt7/qt7backend.mm | 60 + src/plugins/mediaservices/qt7/qt7movierenderer.h | 112 ++ src/plugins/mediaservices/qt7/qt7movierenderer.mm | 441 ++++++ .../mediaservices/qt7/qt7movievideowidget.h | 131 ++ .../mediaservices/qt7/qt7movievideowidget.mm | 409 +++++ src/plugins/mediaservices/qt7/qt7movieviewoutput.h | 118 ++ .../mediaservices/qt7/qt7movieviewoutput.mm | 307 ++++ .../mediaservices/qt7/qt7movieviewrenderer.h | 96 ++ .../mediaservices/qt7/qt7movieviewrenderer.mm | 341 +++++ src/plugins/mediaservices/qt7/qt7playercontrol.h | 128 ++ src/plugins/mediaservices/qt7/qt7playercontrol.mm | 188 +++ src/plugins/mediaservices/qt7/qt7playermetadata.h | 84 ++ src/plugins/mediaservices/qt7/qt7playermetadata.mm | 261 ++++ src/plugins/mediaservices/qt7/qt7playerservice.h | 90 ++ src/plugins/mediaservices/qt7/qt7playerservice.mm | 151 ++ src/plugins/mediaservices/qt7/qt7playersession.h | 140 ++ src/plugins/mediaservices/qt7/qt7playersession.mm | 402 +++++ src/plugins/mediaservices/qt7/qt7serviceplugin.h | 64 + src/plugins/mediaservices/qt7/qt7serviceplugin.mm | 74 + .../mediaservices/qt7/qt7videooutputcontrol.h | 134 ++ .../mediaservices/qt7/qt7videooutputcontrol.mm | 93 ++ src/plugins/plugins.pro | 3 +- tests/auto/auto.pro | 11 + tests/auto/qmediacontent/qmediacontent.pro | 6 + tests/auto/qmediacontent/tst_qmediacontent.cpp | 160 ++ tests/auto/qmediaobject/qmediaobject.pro | 4 + tests/auto/qmediaobject/tst_qmediaobject.cpp | 549 +++++++ tests/auto/qmediaplayer/qmediaplayer.pro | 6 + tests/auto/qmediaplayer/tst_qmediaplayer.cpp | 1011 +++++++++++++ tests/auto/qmediaplaylist/qmediaplaylist.pro | 6 + tests/auto/qmediaplaylist/tmp.unsupported_format | 0 tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp | 622 ++++++++ .../qmediaplaylistnavigator.pro | 6 + .../tst_qmediaplaylistnavigator.cpp | 316 ++++ .../auto/qmediapluginloader/qmediapluginloader.pro | 6 + .../qmediapluginloader/tst_qmediapluginloader.cpp | 121 ++ tests/auto/qmediaresource/qmediaresource.pro | 6 + tests/auto/qmediaresource/tst_qmediaresource.cpp | 471 ++++++ tests/auto/qmediaservice/qmediaservice.pro | 6 + tests/auto/qmediaservice/tst_qmediaservice.cpp | 211 +++ .../qmediaserviceprovider.pro | 6 + .../tst_qmediaserviceprovider.cpp | 458 ++++++ tests/auto/qmediatimerange/qmediatimerange.pro | 6 + tests/auto/qmediatimerange/tst_qmediatimerange.cpp | 735 +++++++++ tests/auto/qvideowidget/qvideowidget.pro | 6 + tests/auto/qvideowidget/tst_qvideowidget.cpp | 1595 ++++++++++++++++++++ tests/auto/tests.xml | 11 + 119 files changed, 25111 insertions(+), 2 deletions(-) create mode 100644 demos/multimedia/multimedia.pro create mode 100644 src/multimedia/base/base.pri create mode 100644 src/multimedia/base/qgraphicsvideoitem.cpp create mode 100644 src/multimedia/base/qgraphicsvideoitem.h create mode 100644 src/multimedia/base/qlocalmediaplaylistprovider.cpp create mode 100644 src/multimedia/base/qlocalmediaplaylistprovider.h create mode 100644 src/multimedia/base/qmediacontent.cpp create mode 100644 src/multimedia/base/qmediacontent.h create mode 100644 src/multimedia/base/qmediacontrol.cpp create mode 100644 src/multimedia/base/qmediacontrol.h create mode 100644 src/multimedia/base/qmediacontrol_p.h create mode 100644 src/multimedia/base/qmediaobject.cpp create mode 100644 src/multimedia/base/qmediaobject.h create mode 100644 src/multimedia/base/qmediaobject_p.h create mode 100644 src/multimedia/base/qmediaplaylist.cpp create mode 100644 src/multimedia/base/qmediaplaylist.h create mode 100644 src/multimedia/base/qmediaplaylist_p.h create mode 100644 src/multimedia/base/qmediaplaylistcontrol.cpp create mode 100644 src/multimedia/base/qmediaplaylistcontrol.h create mode 100644 src/multimedia/base/qmediaplaylistioplugin.cpp create mode 100644 src/multimedia/base/qmediaplaylistioplugin.h create mode 100644 src/multimedia/base/qmediaplaylistnavigator.cpp create mode 100644 src/multimedia/base/qmediaplaylistnavigator.h create mode 100644 src/multimedia/base/qmediaplaylistprovider.cpp create mode 100644 src/multimedia/base/qmediaplaylistprovider.h create mode 100644 src/multimedia/base/qmediaplaylistprovider_p.h create mode 100644 src/multimedia/base/qmediapluginloader.cpp create mode 100644 src/multimedia/base/qmediapluginloader_p.h create mode 100644 src/multimedia/base/qmediaresource.cpp create mode 100644 src/multimedia/base/qmediaresource.h create mode 100644 src/multimedia/base/qmediaservice.cpp create mode 100644 src/multimedia/base/qmediaservice.h create mode 100644 src/multimedia/base/qmediaservice_p.h create mode 100644 src/multimedia/base/qmediaserviceprovider.cpp create mode 100644 src/multimedia/base/qmediaserviceprovider.h create mode 100644 src/multimedia/base/qmediaserviceproviderplugin.h create mode 100644 src/multimedia/base/qmediatimerange.cpp create mode 100644 src/multimedia/base/qmediatimerange.h create mode 100644 src/multimedia/base/qmetadatacontrol.cpp create mode 100644 src/multimedia/base/qmetadatacontrol.h create mode 100644 src/multimedia/base/qpaintervideosurface.cpp create mode 100644 src/multimedia/base/qpaintervideosurface_p.h create mode 100644 src/multimedia/base/qtmedianamespace.h create mode 100644 src/multimedia/base/qtmedianamespace.qdoc create mode 100644 src/multimedia/base/qvideodevicecontrol.cpp create mode 100644 src/multimedia/base/qvideodevicecontrol.h create mode 100644 src/multimedia/base/qvideooutputcontrol.cpp create mode 100644 src/multimedia/base/qvideooutputcontrol.h create mode 100644 src/multimedia/base/qvideorenderercontrol.cpp create mode 100644 src/multimedia/base/qvideorenderercontrol.h create mode 100644 src/multimedia/base/qvideowidget.cpp create mode 100644 src/multimedia/base/qvideowidget.h create mode 100644 src/multimedia/base/qvideowidget_p.h create mode 100644 src/multimedia/base/qvideowidgetcontrol.cpp create mode 100644 src/multimedia/base/qvideowidgetcontrol.h create mode 100644 src/multimedia/base/qvideowindowcontrol.cpp create mode 100644 src/multimedia/base/qvideowindowcontrol.h create mode 100644 src/multimedia/playback/playback.pri create mode 100644 src/multimedia/playback/qmediaplayer.cpp create mode 100644 src/multimedia/playback/qmediaplayer.h create mode 100644 src/multimedia/playback/qmediaplayercontrol.cpp create mode 100644 src/multimedia/playback/qmediaplayercontrol.h create mode 100644 src/multimedia/qml/qml.pri create mode 100644 src/multimedia/qml/qmlsound.cpp create mode 100644 src/multimedia/qml/qmlsound_p.h create mode 100644 src/plugins/mediaservices/mediaservices.pro create mode 100644 src/plugins/mediaservices/qt7/qcvdisplaylink.h create mode 100644 src/plugins/mediaservices/qt7/qcvdisplaylink.mm create mode 100644 src/plugins/mediaservices/qt7/qt7.pro create mode 100644 src/plugins/mediaservices/qt7/qt7backend.h create mode 100644 src/plugins/mediaservices/qt7/qt7backend.mm create mode 100644 src/plugins/mediaservices/qt7/qt7movierenderer.h create mode 100644 src/plugins/mediaservices/qt7/qt7movierenderer.mm create mode 100644 src/plugins/mediaservices/qt7/qt7movievideowidget.h create mode 100644 src/plugins/mediaservices/qt7/qt7movievideowidget.mm create mode 100644 src/plugins/mediaservices/qt7/qt7movieviewoutput.h create mode 100644 src/plugins/mediaservices/qt7/qt7movieviewoutput.mm create mode 100644 src/plugins/mediaservices/qt7/qt7movieviewrenderer.h create mode 100644 src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm create mode 100644 src/plugins/mediaservices/qt7/qt7playercontrol.h create mode 100644 src/plugins/mediaservices/qt7/qt7playercontrol.mm create mode 100644 src/plugins/mediaservices/qt7/qt7playermetadata.h create mode 100644 src/plugins/mediaservices/qt7/qt7playermetadata.mm create mode 100644 src/plugins/mediaservices/qt7/qt7playerservice.h create mode 100644 src/plugins/mediaservices/qt7/qt7playerservice.mm create mode 100644 src/plugins/mediaservices/qt7/qt7playersession.h create mode 100644 src/plugins/mediaservices/qt7/qt7playersession.mm create mode 100644 src/plugins/mediaservices/qt7/qt7serviceplugin.h create mode 100644 src/plugins/mediaservices/qt7/qt7serviceplugin.mm create mode 100644 src/plugins/mediaservices/qt7/qt7videooutputcontrol.h create mode 100644 src/plugins/mediaservices/qt7/qt7videooutputcontrol.mm create mode 100644 tests/auto/qmediacontent/qmediacontent.pro create mode 100644 tests/auto/qmediacontent/tst_qmediacontent.cpp create mode 100644 tests/auto/qmediaobject/qmediaobject.pro create mode 100644 tests/auto/qmediaobject/tst_qmediaobject.cpp create mode 100644 tests/auto/qmediaplayer/qmediaplayer.pro create mode 100644 tests/auto/qmediaplayer/tst_qmediaplayer.cpp create mode 100644 tests/auto/qmediaplaylist/qmediaplaylist.pro create mode 100644 tests/auto/qmediaplaylist/tmp.unsupported_format 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 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/qvideowidget/qvideowidget.pro create mode 100644 tests/auto/qvideowidget/tst_qvideowidget.cpp diff --git a/demos/demos.pro b/demos/demos.pro index 5a9b6db..86553dc 100644 --- a/demos/demos.pro +++ b/demos/demos.pro @@ -55,6 +55,7 @@ wince*:SUBDIRS += demos_sqlbrowser } contains(QT_CONFIG, phonon):!static:SUBDIRS += demos_mediaplayer contains(QT_CONFIG, webkit):contains(QT_CONFIG, svg):!symbian:SUBDIRS += demos_browser +contains(QT_CONFIG, multimedia):SUBDIRS += demos_multimedia # install sources.files = README *.pro @@ -82,6 +83,7 @@ demos_sqlbrowser.subdir = sqlbrowser demos_undo.subdir = undo demos_qtdemo.subdir = qtdemo demos_mediaplayer.subdir = qmediaplayer +demos_multimedia.subdir = multimedia demos_browser.subdir = browser diff --git a/demos/multimedia/multimedia.pro b/demos/multimedia/multimedia.pro new file mode 100644 index 0000000..042650f --- /dev/null +++ b/demos/multimedia/multimedia.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = player + + diff --git a/src/multimedia/base/base.pri b/src/multimedia/base/base.pri new file mode 100644 index 0000000..fb2784d --- /dev/null +++ b/src/multimedia/base/base.pri @@ -0,0 +1,62 @@ + +contains(QT_CONFIG, opengl):QT += opengl + +HEADERS += \ + $$PWD/qmediaresource.h \ + $$PWD/qmediacontent.h \ + $$PWD/qmediaobject.h \ + $$PWD/qmediaobject_p.h \ + $$PWD/qmediapluginloader_p.h \ + $$PWD/qmediaservice.h \ + $$PWD/qmediaservice_p.h \ + $$PWD/qmediaserviceprovider.h \ + $$PWD/qmediaserviceproviderplugin.h \ + $$PWD/qmediacontrol.h \ + $$PWD/qmediacontrol_p.h \ + $$PWD/qmetadatacontrol.h \ + $$PWD/qvideooutputcontrol.h \ + $$PWD/qvideowindowcontrol.h \ + $$PWD/qvideorenderercontrol.h \ + $$PWD/qvideodevicecontrol.h \ + $$PWD/qvideowidgetcontrol.h \ + $$PWD/qvideowidget.h \ + $$PWD/qvideowidget_p.h \ + $$PWD/qgraphicsvideoitem.h \ + $$PWD/qmediaplaylistcontrol.h \ + $$PWD/qmediaplaylist.h \ + $$PWD/qmediaplaylist_p.h \ + $$PWD/qmediaplaylistprovider.h \ + $$PWD/qmediaplaylistprovider_p.h \ + $$PWD/qmediaplaylistioplugin.h \ + $$PWD/qlocalmediaplaylistprovider.h \ + $$PWD/qmediaplaylistnavigator.h \ + $$PWD/qpaintervideosurface_p.h \ + $$PWD/qmediatimerange.h \ + $$PWD/qtmedianamespace.h + +SOURCES += \ + $$PWD/qmediaresource.cpp \ + $$PWD/qmediacontent.cpp \ + $$PWD/qmediaobject.cpp \ + $$PWD/qmediapluginloader.cpp \ + $$PWD/qmediaservice.cpp \ + $$PWD/qmediaserviceprovider.cpp \ + $$PWD/qmediacontrol.cpp \ + $$PWD/qmetadatacontrol.cpp \ + $$PWD/qvideooutputcontrol.cpp \ + $$PWD/qvideowindowcontrol.cpp \ + $$PWD/qvideorenderercontrol.cpp \ + $$PWD/qvideodevicecontrol.cpp \ + $$PWD/qvideowidgetcontrol.cpp \ + $$PWD/qvideowidget.cpp \ + $$PWD/qgraphicsvideoitem.cpp \ + $$PWD/qmediaplaylistcontrol.cpp \ + $$PWD/qmediaplaylist.cpp \ + $$PWD/qmediaplaylistprovider.cpp \ + $$PWD/qmediaplaylistioplugin.cpp \ + $$PWD/qlocalmediaplaylistprovider.cpp \ + $$PWD/qmediaplaylistnavigator.cpp \ + $$PWD/qpaintervideosurface.cpp \ + $$PWD/qmediatimerange.cpp + + diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp new file mode 100644 index 0000000..7fa2e7d --- /dev/null +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -0,0 +1,299 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include "qpaintervideosurface_p.h" +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + +class QGraphicsVideoItemPrivate +{ +public: + QGraphicsVideoItemPrivate() + : q_ptr(0) + , surface(0) + , mediaObject(0) + , service(0) + , outputControl(0) + , rendererControl(0) + { + } + + QGraphicsVideoItem *q_ptr; + + QPainterVideoSurface *surface; + QMediaObject *mediaObject; + QMediaService *service; + QVideoOutputControl *outputControl; + QVideoRendererControl *rendererControl; + QRect boundingRect; + + void clearService(); + + void _q_present(); + void _q_formatChanged(const QVideoSurfaceFormat &format); + void _q_serviceDestroyed(); + void _q_mediaObjectDestroyed(); +}; + +void QGraphicsVideoItemPrivate::clearService() +{ + if (outputControl) { + outputControl->setOutput(QVideoOutputControl::NoOutput); + outputControl = 0; + } + if (rendererControl) { + surface->stop(); + rendererControl->setSurface(0); + rendererControl = 0; + } + if (service) { + QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed())); + service = 0; + } +} + +void QGraphicsVideoItemPrivate::_q_present() +{ + q_ptr->update(boundingRect); +} + +void QGraphicsVideoItemPrivate::_q_formatChanged(const QVideoSurfaceFormat &format) +{ + q_ptr->prepareGeometryChange(); + + boundingRect = QRect(QPoint(0, 0), format.sizeHint()); + boundingRect.moveCenter(QPoint(0, 0)); +} + +void QGraphicsVideoItemPrivate::_q_serviceDestroyed() +{ + rendererControl = 0; + outputControl = 0; + service = 0; + + surface->stop(); +} + +void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed() +{ + mediaObject = 0; + + clearService(); +} + +/*! + \class QGraphicsVideoItem + + \brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject. + + \ingroup multimedia + + Attaching a QGraphicsVideoItem to a QMediaObject allows it to display + the video or image output of that media object. A QGraphicsVideoItem + is attached to a media object by passing a pointer to the QMediaObject + to the setMediaObject() function. + + \code + player = new QMediaPlayer(this); + + QGraphicsVideoItem *item = new QGraphicsVideoItem; + item->setMediaObject(player); + graphicsView->scence()->addItem(item); + graphicsView->show(); + + player->setMedia(video); + player->play(); + \endcode + + \bold {Note}: Only a single display output can be attached to a media object at one time. + + \sa QMediaObject, QMediaPlayer, QVideoWidget +*/ + +/*! + Constructs a graphics item that displays video. + + The \a parent is passed to QGraphicsItem. +*/ +QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent) + : QGraphicsItem(parent) + , d_ptr(new QGraphicsVideoItemPrivate) +{ + d_ptr->q_ptr = this; + d_ptr->surface = new QPainterVideoSurface; +} + +/*! + Destroys a video graphics item. +*/ +QGraphicsVideoItem::~QGraphicsVideoItem() +{ + if (d_ptr->outputControl) + d_ptr->outputControl->setOutput(QVideoOutputControl::NoOutput); + + if (d_ptr->rendererControl) + d_ptr->rendererControl->setSurface(0); + + delete d_ptr->surface; + delete d_ptr; +} + +/*! + \property QGraphicsVideoItem::mediaObject + \brief the media object which provides the video displayed by a graphics item. +*/ + +QMediaObject *QGraphicsVideoItem::mediaObject() const +{ + return d_func()->mediaObject; +} + +void QGraphicsVideoItem::setMediaObject(QMediaObject *object) +{ + Q_D(QGraphicsVideoItem); + + if (object == d->mediaObject) + return; + + d->clearService(); + + if (d->mediaObject) { + disconnect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed())); + d->mediaObject->unbind(this); + } + + d->mediaObject = object; + + if (d->mediaObject) { + d->mediaObject->bind(this); + + connect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed())); + + d->service = d->mediaObject->service(); + + if (d->service) { + connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); + + d->outputControl = qobject_cast( + d->service->control(QVideoOutputControl_iid)); + d->rendererControl = qobject_cast( + d->service->control(QVideoRendererControl_iid)); + + if (d->outputControl != 0 && d->rendererControl != 0) { + if (!d->surface) { + d->surface = new QPainterVideoSurface; + + connect(d->surface, SIGNAL(frameChanged()), this, SLOT(_q_present())); + connect(d->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), + this, SLOT(_q_formatChanged(QVideoSurfaceFormat))); + connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); + } + + d->rendererControl->setSurface(d->surface); + + if (isVisible()) + d->outputControl->setOutput(QVideoOutputControl::RendererOutput); + } + } + } +} + +/*! + \reimp +*/ +QRectF QGraphicsVideoItem::boundingRect() const +{ + return d_func()->boundingRect; +} + +/*! + \reimp +*/ +void QGraphicsVideoItem::paint( + QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_D(QGraphicsVideoItem); + + Q_UNUSED(option); + Q_UNUSED(widget); + + if (d->surface != 0) { + d->surface->paint(painter, d->boundingRect); + d->surface->setReady(true); + } +} + +/*! + \reimp + + \internal +*/ +QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value) +{ + Q_D(QGraphicsVideoItem); + + if (change == ItemVisibleChange && d->outputControl != 0 && d->rendererControl != 0) { + if (value.toBool()) { + d->outputControl->setOutput(QVideoOutputControl::RendererOutput); + + return d->outputControl->output() == QVideoOutputControl::RendererOutput; + } else { + d->outputControl->setOutput(QVideoOutputControl::NoOutput); + + return value; + } + } else { + return QGraphicsItem::itemChange(change, value); + } +} + +QT_END_NAMESPACE + +#include "moc_qgraphicsvideoitem.cpp" diff --git a/src/multimedia/base/qgraphicsvideoitem.h b/src/multimedia/base/qgraphicsvideoitem.h new file mode 100644 index 0000000..0cd5d46 --- /dev/null +++ b/src/multimedia/base/qgraphicsvideoitem.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSVIDEOITEM_H +#define QGRAPHICSVIDEOITEM_H + +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QVideoSurfaceFormat; + +class QGraphicsVideoItemPrivate; +class Q_MULTIMEDIA_EXPORT QGraphicsVideoItem : public QObject, public QGraphicsItem +{ + Q_OBJECT + Q_INTERFACES(QGraphicsItem) + Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject) + +public: + QGraphicsVideoItem(QGraphicsItem *parent = 0); + ~QGraphicsVideoItem(); + + QMediaObject *mediaObject() const; + void setMediaObject(QMediaObject *object); + + QRectF boundingRect() const; + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + QGraphicsVideoItemPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QGraphicsVideoItem) + Q_PRIVATE_SLOT(d_func(), void _q_present()) + Q_PRIVATE_SLOT(d_func(), void _q_formatChanged(const QVideoSurfaceFormat &)) + Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed()) + Q_PRIVATE_SLOT(d_func(), void _q_mediaObjectDestroyed()) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qlocalmediaplaylistprovider.cpp b/src/multimedia/base/qlocalmediaplaylistprovider.cpp new file mode 100644 index 0000000..40ff1fc --- /dev/null +++ b/src/multimedia/base/qlocalmediaplaylistprovider.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qmediaplaylistprovider_p.h" +#include + + +QT_BEGIN_NAMESPACE + +class QLocalMediaPlaylistProviderPrivate: public QMediaPlaylistProviderPrivate +{ +public: + QList resources; +}; + +QLocalMediaPlaylistProvider::QLocalMediaPlaylistProvider(QObject *parent) + :QMediaPlaylistProvider(*new QLocalMediaPlaylistProviderPrivate, parent) +{ +} + +QLocalMediaPlaylistProvider::~QLocalMediaPlaylistProvider() +{ +} + +bool QLocalMediaPlaylistProvider::isReadOnly() const +{ + return false; +} + +int QLocalMediaPlaylistProvider::mediaCount() const +{ + return d_func()->resources.size(); +} + +QMediaContent QLocalMediaPlaylistProvider::media(int pos) const +{ + return d_func()->resources.value(pos); +} + +bool QLocalMediaPlaylistProvider::addMedia(const QMediaContent &content) +{ + Q_D(QLocalMediaPlaylistProvider); + + int pos = d->resources.count(); + + emit mediaAboutToBeInserted(pos, pos); + d->resources.append(content); + emit mediaInserted(pos, pos); + + return true; +} + +bool QLocalMediaPlaylistProvider::addMedia(const QList &items) +{ + Q_D(QLocalMediaPlaylistProvider); + + if (items.isEmpty()) + return true; + + int pos = d->resources.count(); + int end = pos+items.count()-1; + + emit mediaAboutToBeInserted(pos, end); + d->resources.append(items); + emit mediaInserted(pos, end); + + return true; +} + + +bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QMediaContent &content) +{ + Q_D(QLocalMediaPlaylistProvider); + + emit mediaAboutToBeInserted(pos, pos); + d->resources.insert(pos, content); + emit mediaInserted(pos,pos); + + return true; +} + +bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QList &items) +{ + Q_D(QLocalMediaPlaylistProvider); + + if (items.isEmpty()) + return true; + + const int last = pos+items.count()-1; + + emit mediaAboutToBeInserted(pos, last); + for (int i=0; iresources.insert(pos+i, items.at(i)); + emit mediaInserted(pos, last); + + return true; +} + +bool QLocalMediaPlaylistProvider::removeMedia(int fromPos, int toPos) +{ + Q_D(QLocalMediaPlaylistProvider); + + Q_ASSERT(fromPos >= 0); + Q_ASSERT(fromPos <= toPos); + Q_ASSERT(toPos < mediaCount()); + + emit mediaAboutToBeRemoved(fromPos, toPos); + d->resources.erase(d->resources.begin()+fromPos, d->resources.begin()+toPos+1); + emit mediaRemoved(fromPos, toPos); + + return true; +} + +bool QLocalMediaPlaylistProvider::removeMedia(int pos) +{ + Q_D(QLocalMediaPlaylistProvider); + + emit mediaAboutToBeRemoved(pos, pos); + d->resources.removeAt(pos); + emit mediaRemoved(pos, pos); + + return true; +} + +bool QLocalMediaPlaylistProvider::clear() +{ + Q_D(QLocalMediaPlaylistProvider); + if (!d->resources.isEmpty()) { + int lastPos = mediaCount()-1; + emit mediaAboutToBeRemoved(0, lastPos); + d->resources.clear(); + emit mediaRemoved(0, lastPos); + } + + return true; +} + +void QLocalMediaPlaylistProvider::shuffle() +{ + Q_D(QLocalMediaPlaylistProvider); + if (!d->resources.isEmpty()) { + QList resources; + + while (!d->resources.isEmpty()) { + resources.append(d->resources.takeAt(qrand() % d->resources.size())); + } + + d->resources = resources; + emit mediaChanged(0, mediaCount()-1); + } + +} + +#include "moc_qlocalmediaplaylistprovider.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qlocalmediaplaylistprovider.h b/src/multimedia/base/qlocalmediaplaylistprovider.h new file mode 100644 index 0000000..db8deb1 --- /dev/null +++ b/src/multimedia/base/qlocalmediaplaylistprovider.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCALMEDIAPAYLISTPROVIDER_H +#define QLOCALMEDIAPAYLISTPROVIDER_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QLocalMediaPlaylistProviderPrivate; +class Q_MULTIMEDIA_EXPORT QLocalMediaPlaylistProvider : public QMediaPlaylistProvider +{ + Q_OBJECT + +public: + QLocalMediaPlaylistProvider(QObject *parent=0); + virtual ~QLocalMediaPlaylistProvider(); + + virtual int mediaCount() const; + virtual QMediaContent media(int pos) const; + + virtual bool isReadOnly() const; + + virtual bool addMedia(const QMediaContent &content); + virtual bool addMedia(const QList &items); + virtual bool insertMedia(int pos, const QMediaContent &content); + virtual bool insertMedia(int pos, const QList &items); + virtual bool removeMedia(int pos); + virtual bool removeMedia(int start, int end); + virtual bool clear(); + +public Q_SLOTS: + virtual void shuffle(); + +private: + Q_DECLARE_PRIVATE(QLocalMediaPlaylistProvider) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLOCALMEDIAPAYLISTSOURCE_H diff --git a/src/multimedia/base/qmediacontent.cpp b/src/multimedia/base/qmediacontent.cpp new file mode 100644 index 0000000..3e32af0 --- /dev/null +++ b/src/multimedia/base/qmediacontent.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + + +class QMediaContentPrivate : public QSharedData +{ +public: + QMediaContentPrivate() {} + QMediaContentPrivate(const QMediaResourceList &r): + resources(r) {} + + QMediaContentPrivate(const QMediaContentPrivate &other): + QSharedData(other), + resources(other.resources) + {} + + bool operator==(const QMediaContentPrivate &other) const + { + return resources == other.resources; + } + + QMediaResourceList resources; + +private: + QMediaContentPrivate& operator=(const QMediaContentPrivate &other); +}; + + +/*! + \class QMediaContent + \preliminary + \brief The QMediaContent class provides access to the resources relating to a media content. + + \ingroup multimedia + + QMediaContent is used within the multimedia framework as the logical handle + to media content. A QMediaContent object is composed of one or more + \l {QMediaResource}s where each resource provides the URL and format + information of a different encoding of the content. + + A non-null QMediaContent will always have a primary or canonical reference to + the content available through the canonicalUrl() or canonicalResource() + methods, any additional resources are optional. +*/ + + +/*! + Constructs a null QMediaContent. +*/ + +QMediaContent::QMediaContent() +{ +} + +/*! + Constructs a media content with \a url providing a reference to the content. +*/ + +QMediaContent::QMediaContent(const QUrl &url): + d(new QMediaContentPrivate) +{ + d->resources << QMediaResource(url); +} + +/*! + Constructs a media content with \a resource providing a reference to the content. +*/ + +QMediaContent::QMediaContent(const QMediaResource &resource): + d(new QMediaContentPrivate) +{ + d->resources << resource; +} + +/*! + Constructs a media content with \a resources providing a reference to the content. +*/ + +QMediaContent::QMediaContent(const QMediaResourceList &resources): + d(new QMediaContentPrivate(resources)) +{ +} + +/*! + Constructs a copy of the media content \a other. +*/ + +QMediaContent::QMediaContent(const QMediaContent &other): + d(other.d) +{ +} + +/*! + Destroys the media content object. +*/ + +QMediaContent::~QMediaContent() +{ +} + +/*! + Assigns the value of \a other to this media content. +*/ + +QMediaContent& QMediaContent::operator=(const QMediaContent &other) +{ + d = other.d; + return *this; +} + +/*! + Returns true if \a other is equivalent to this media content; false otherwise. +*/ + +bool QMediaContent::operator==(const QMediaContent &other) const +{ + return (d.constData() == 0 && other.d.constData() == 0) || + (d.constData() != 0 && other.d.constData() != 0 && + *d.constData() == *other.d.constData()); +} + +/*! + Returns true if \a other is not equivalent to this media content; false otherwise. +*/ + +bool QMediaContent::operator!=(const QMediaContent &other) const +{ + return !(*this == other); +} + +/*! + Returns true if this media content is null (uninitialized); false otherwise. +*/ + +bool QMediaContent::isNull() const +{ + return d.constData() == 0; +} + +/*! + Returns a QUrl that represents that canonical resource for this media content. +*/ + +QUrl QMediaContent::canonicalUrl() const +{ + return canonicalResource().url(); +} + +/*! + Returns a QMediaResource that represents that canonical resource for this media content. +*/ + +QMediaResource QMediaContent::canonicalResource() const +{ + return d.constData() != 0 + ? d->resources.value(0) + : QMediaResource(); +} + +/*! + Returns a list of alternative resources for this media content. The first item in this list + is always the canonical resource. +*/ + +QMediaResourceList QMediaContent::resources() const +{ + return d.constData() != 0 + ? d->resources + : QMediaResourceList(); +} + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediacontent.h b/src/multimedia/base/qmediacontent.h new file mode 100644 index 0000000..49d1155 --- /dev/null +++ b/src/multimedia/base/qmediacontent.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIACONTENT_H +#define QMEDIACONTENT_H + +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaContentPrivate; +class Q_MULTIMEDIA_EXPORT QMediaContent +{ +public: + QMediaContent(); + QMediaContent(const QUrl &contentUrl); + QMediaContent(const QMediaResource &contentResource); + QMediaContent(const QMediaResourceList &resources); + QMediaContent(const QMediaContent &other); + ~QMediaContent(); + + QMediaContent& operator=(const QMediaContent &other); + + bool operator==(const QMediaContent &other) const; + bool operator!=(const QMediaContent &other) const; + + bool isNull() const; + + QUrl canonicalUrl() const; + QMediaResource canonicalResource() const; + + QMediaResourceList resources() const; + +private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaContent)) + +QT_END_HEADER + +#endif // QMEDIACONTENT_H diff --git a/src/multimedia/base/qmediacontrol.cpp b/src/multimedia/base/qmediacontrol.cpp new file mode 100644 index 0000000..c8bbfd4 --- /dev/null +++ b/src/multimedia/base/qmediacontrol.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include "qmediacontrol_p.h" + + + +QT_BEGIN_NAMESPACE + +/*! + \class QMediaControl + \ingroup multimedia-serv + + \preliminary + \brief The QMediaControl class provides a base interface for media service controls. + + Media controls provide an interface to individual features provided by a media service. Most + services implement a principal control which exposes the core functionality of the service and + a number optional controls which expose any additional functionality. + + A pointer to a control implemented by a media service can be obtained using the + \l {QMediaService::control()}{control()} member of QMediaService. If the service doesn't + implement a control it will instead return a null pointer. + + \code + QMediaPlayerControl *control = qobject_cast( + service->control("com.nokia.Qt.QMediaPlayerControl/1.0")); + \endcode + + Alternatively if the IId of the control has been declared using Q_MEDIA_DECLARE_CONTROL + the template version of QMediaService::control() can be used to request the service without + explicitly passing the IId. + + \code + QMediaPlayerControl *control = service->control(); + \endcode + + Most application code will not interface directly with a media service's controls, instead the + QMediaObject which owns the service acts as an intermeditary between one or more controls and + the application. + + \sa QMediaService, QMediaObject +*/ + +/*! + \macro Q_MEDIA_DECLARE_CONTROL(Class, IId) + \relates QMediaControl + + The Q_MEDIA_DECLARE_CONTROL macro declares an \a IId for a \a Class that inherits from + QMediaControl. + + Declaring an IId for a QMediaControl allows an instance of that control to be requested from + QMediaService::control() without explicitly passing the IId. + + \code + QMediaPlayerControl *control = service->control(); + \endcode + + \sa QMediaService::control() +*/ + +/*! + Destroys a media control. +*/ + +QMediaControl::~QMediaControl() +{ + delete d_ptr; +} + +/*! + Constructs a media control with the given \a parent. +*/ + +QMediaControl::QMediaControl(QObject *parent) + : QObject(parent) + , d_ptr(new QMediaControlPrivate) +{ + d_ptr->q_ptr = this; +} + +/*! + \internal +*/ + +QMediaControl::QMediaControl(QMediaControlPrivate &dd, QObject *parent) + : QObject(parent) + , d_ptr(&dd) + +{ + d_ptr->q_ptr = this; +} + +#include "moc_qmediacontrol.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediacontrol.h b/src/multimedia/base/qmediacontrol.h new file mode 100644 index 0000000..8ed9fe8 --- /dev/null +++ b/src/multimedia/base/qmediacontrol.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTMEDIACONTROL_H +#define QABSTRACTMEDIACONTROL_H + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaControlPrivate; +class Q_MULTIMEDIA_EXPORT QMediaControl : public QObject +{ + Q_OBJECT + +public: + ~QMediaControl(); + +protected: + QMediaControl(QObject *parent = 0); + QMediaControl(QMediaControlPrivate &dd, QObject *parent = 0); + + QMediaControlPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QMediaControl) +}; + +template const char *qmediacontrol_iid() { return 0; } + +#define Q_MEDIA_DECLARE_CONTROL(Class, IId) \ + template <> inline const char *qmediacontrol_iid() { return IId; } + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QABSTRACTMEDIACONTROL_H diff --git a/src/multimedia/base/qmediacontrol_p.h b/src/multimedia/base/qmediacontrol_p.h new file mode 100644 index 0000000..4d00f11 --- /dev/null +++ b/src/multimedia/base/qmediacontrol_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTMEDIACONTROL_P_H +#define QABSTRACTMEDIACONTROL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaControl; + +class QMediaControlPrivate +{ +public: + virtual ~QMediaControlPrivate() {} + + QMediaControl *q_ptr; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qmediaobject.cpp b/src/multimedia/base/qmediaobject.cpp new file mode 100644 index 0000000..34b57c9 --- /dev/null +++ b/src/multimedia/base/qmediaobject.cpp @@ -0,0 +1,418 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qmediaobject_p.h" + +#include +#include + + +QT_BEGIN_NAMESPACE + +void QMediaObjectPrivate::_q_notify() +{ + Q_Q(QMediaObject); + + const QMetaObject* m = q->metaObject(); + + foreach (int pi, notifyProperties) { + QMetaProperty p = m->property(pi); + p.notifySignal().invoke( + q, QGenericArgument(QMetaType::typeName(p.userType()), p.read(q).data())); + } +} + + +/*! + \class QMediaObject + \preliminary + \brief The QMediaObject class provides a common base for multimedia objects. + + \ingroup multimedia + + QMediaObject derived classes provide access to the functionality of a + QMediaService. Each media object hosts a QMediaService and uses the + QMediaControl interfaces implemented by the service to implement its + API. Most media objects when constructed will request a new + QMediaService instance from a QMediaServiceProvider, but some like + QMediaRecorder will share a service with another object. + + QMediaObject itself provides an API for accessing a media service's \l {metaData()}{meta-data} and a means of connecting other media objects, + and peripheral classes like QVideoWidget and QMediaPlaylist. + + \sa QMediaService, QMediaControl +*/ + +/*! + Destroys a media object. +*/ + +QMediaObject::~QMediaObject() +{ + delete d_ptr; +} + +/*! + Returns the service availability error state. +*/ + +QtMedia::AvailabilityError QMediaObject::availabilityError() const +{ + return QtMedia::ServiceMissingError; +} + +/*! + Returns true if the service is available for use. +*/ + +bool QMediaObject::isAvailable() const +{ + return false; +} + +/*! + Returns the media service that provides the functionality of a multimedia object. +*/ + +QMediaService* QMediaObject::service() const +{ + return d_func()->service; +} + +int QMediaObject::notifyInterval() const +{ + return d_func()->notifyTimer->interval(); +} + +void QMediaObject::setNotifyInterval(int milliSeconds) +{ + Q_D(QMediaObject); + + if (d->notifyTimer->interval() != milliSeconds) { + d->notifyTimer->setInterval(milliSeconds); + + emit notifyIntervalChanged(milliSeconds); + } +} + +/*! + \internal +*/ +void QMediaObject::bind(QObject*) +{ +} + +/*! + \internal +*/ +void QMediaObject::unbind(QObject*) +{ +} + + +/*! + Constructs a media object which uses the functionality provided by a media \a service. + + The \a parent is passed to QObject. + + This class is meant as a base class for Multimedia objects so this + constructor is protected. +*/ + +QMediaObject::QMediaObject(QObject *parent, QMediaService *service): + QObject(parent), + d_ptr(new QMediaObjectPrivate) + +{ + Q_D(QMediaObject); + + d->q_ptr = this; + + d->notifyTimer = new QTimer(this); + d->notifyTimer->setInterval(1000); + connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify())); + + d->service = service; + + setupMetaData(); +} + +/*! + \internal +*/ + +QMediaObject::QMediaObject(QMediaObjectPrivate &dd, QObject *parent, + QMediaService *service): + QObject(parent), + d_ptr(&dd) +{ + Q_D(QMediaObject); + d->q_ptr = this; + + d->notifyTimer = new QTimer(this); + d->notifyTimer->setInterval(1000); + connect(d->notifyTimer, SIGNAL(timeout()), SLOT(_q_notify())); + + d->service = service; + + setupMetaData(); +} + +/*! + Watch the property \a name. The property's notify signal will be emitted + once every notifyInterval milliseconds. + + \sa notifyInterval +*/ + +void QMediaObject::addPropertyWatch(QByteArray const &name) +{ + Q_D(QMediaObject); + + const QMetaObject* m = metaObject(); + + int index = m->indexOfProperty(name.constData()); + + if (index != -1 && m->property(index).hasNotifySignal()) { + d->notifyProperties.insert(index); + + if (!d->notifyTimer->isActive()) + d->notifyTimer->start(); + } +} + +/*! + Remove property \a name from the list of properties whose changes are + regularly signaled. + + \sa notifyInterval +*/ + +void QMediaObject::removePropertyWatch(QByteArray const &name) +{ + Q_D(QMediaObject); + + int index = metaObject()->indexOfProperty(name.constData()); + + if (index != -1) { + d->notifyProperties.remove(index); + + if (d->notifyProperties.isEmpty()) + d->notifyTimer->stop(); + } +} + +/*! + \property QMediaObject::notifyInterval + + The interval at which notifiable properties will update. + + The interval is expressed in milliseconds, the default value is 1000. + + \sa addPropertyWatch(), removePropertyWatch() +*/ + +/*! + \fn void QMediaObject::notifyIntervalChanged(int milliseconds) + + Signal a change in the notify interval period to \a milliseconds. +*/ + +/*! + \property QMediaObject::metaDataAvailable + \brief whether access to a media object's meta-data is available. + + If this is true there is meta-data available, otherwise there is no meta-data available. +*/ + +bool QMediaObject::isMetaDataAvailable() const +{ + Q_D(const QMediaObject); + + return d->metaDataControl + ? d->metaDataControl->isMetaDataAvailable() + : false; +} + +/*! + \fn QMediaObject::metaDataAvailableChanged(bool available) + + Signals that the \a available state of a media object's meta-data has changed. +*/ + +/*! + \property QMediaObject::metaDataWritable + \brief whether a media object's meta-data is writable. + + If this is true the meta-data is writable, otherwise the meta-data is read-only. +*/ + +bool QMediaObject::isMetaDataWritable() const +{ + Q_D(const QMediaObject); + + return d->metaDataControl + ? d->metaDataControl->isWritable() + : false; +} + +/*! + \fn QMediaObject::metaDataWritableChanged(bool writable) + + Signals that the \a writable state of a media object's meta-data has changed. +*/ + +/*! + Returns the value associated with a meta-data \a key. +*/ +QVariant QMediaObject::metaData(QtMedia::MetaData key) const +{ + Q_D(const QMediaObject); + + return d->metaDataControl + ? d->metaDataControl->metaData(key) + : QVariant(); +} + +/*! + Sets a \a value for a meta-data \a key. +*/ +void QMediaObject::setMetaData(QtMedia::MetaData key, const QVariant &value) +{ + Q_D(QMediaObject); + + if (d->metaDataControl) + d->metaDataControl->setMetaData(key, value); +} + +/*! + Returns a list of keys there is meta-data available for. +*/ +QList QMediaObject::availableMetaData() const +{ + Q_D(const QMediaObject); + + return d->metaDataControl + ? d->metaDataControl->availableMetaData() + : QList(); +} + +/*! + \fn QMediaObject::metaDataChanged() + + Signals that a media object's meta-data has changed. +*/ + +/*! + Returns the value associated with a meta-data \a key. + + The naming and type of extended meta-data is not standardized, so the values and meaning + of keys may vary between backends. +*/ +QVariant QMediaObject::extendedMetaData(const QString &key) const +{ + Q_D(const QMediaObject); + + return d->metaDataControl + ? d->metaDataControl->extendedMetaData(key) + : QVariant(); +} + +/*! + Sets a \a value for a meta-data \a key. + + The naming and type of extended meta-data is not standardized, so the values and meaning + of keys may vary between backends. +*/ +void QMediaObject::setExtendedMetaData(const QString &key, const QVariant &value) +{ + Q_D(QMediaObject); + + if (d->metaDataControl) + d->metaDataControl->setExtendedMetaData(key, value); +} + +/*! + Returns a list of keys there is extended meta-data available for. +*/ +QStringList QMediaObject::availableExtendedMetaData() const +{ + Q_D(const QMediaObject); + + return d->metaDataControl + ? d->metaDataControl->availableExtendedMetaData() + : QStringList(); +} + + +void QMediaObject::setupMetaData() +{ + Q_D(QMediaObject); + + if (d->service != 0) { + d->metaDataControl = + qobject_cast(d->service->control(QMetaDataControl_iid)); + + if (d->metaDataControl) { + connect(d->metaDataControl, SIGNAL(metaDataChanged()), SIGNAL(metaDataChanged())); + connect(d->metaDataControl, + SIGNAL(metaDataAvailableChanged(bool)), + SIGNAL(metaDataAvailableChanged(bool))); + connect(d->metaDataControl, + SIGNAL(writableChanged(bool)), + SIGNAL(metaDataWritableChanged(bool))); + } + } +} + +/*! + \fn QMediaObject::availabilityChanged(bool available) + + Signal emitted when the availability state has changed to \a available +*/ + + +#include "moc_qmediaobject.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediaobject.h b/src/multimedia/base/qmediaobject.h new file mode 100644 index 0000000..a6eff1e --- /dev/null +++ b/src/multimedia/base/qmediaobject.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTMEDIAOBJECT_H +#define QABSTRACTMEDIAOBJECT_H + +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaService; + +class QMediaObjectPrivate; +class Q_MULTIMEDIA_EXPORT QMediaObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int notifyInterval READ notifyInterval WRITE setNotifyInterval NOTIFY notifyIntervalChanged) + Q_PROPERTY(bool metaDataAvailable READ isMetaDataAvailable NOTIFY metaDataAvailableChanged) + Q_PROPERTY(bool metaDataWritable READ isMetaDataWritable NOTIFY metaDataWritableChanged) + +public: + ~QMediaObject(); + + virtual bool isAvailable() const; + virtual QtMedia::AvailabilityError availabilityError() const; + + virtual QMediaService* service() const; + + int notifyInterval() const; + void setNotifyInterval(int milliSeconds); + + virtual void bind(QObject*); + virtual void unbind(QObject*); + + bool isMetaDataAvailable() const; + bool isMetaDataWritable() const; + + QVariant metaData(QtMedia::MetaData key) const; + void setMetaData(QtMedia::MetaData key, const QVariant &value); + QList availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const; + void setExtendedMetaData(const QString &key, const QVariant &value); + QStringList availableExtendedMetaData() const; + +Q_SIGNALS: + void notifyIntervalChanged(int milliSeconds); + + void metaDataAvailableChanged(bool available); + void metaDataWritableChanged(bool writable); + void metaDataChanged(); + + void availabilityChanged(bool available); + +protected: + QMediaObject(QObject *parent, QMediaService *service); + QMediaObject(QMediaObjectPrivate &dd, QObject *parent, QMediaService *service); + + void addPropertyWatch(QByteArray const &name); + void removePropertyWatch(QByteArray const &name); + + QMediaObjectPrivate *d_ptr; + +private: + void setupMetaData(); + + Q_DECLARE_PRIVATE(QMediaObject) + Q_PRIVATE_SLOT(d_func(), void _q_notify()) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QABSTRACTMEDIAOBJECT_H diff --git a/src/multimedia/base/qmediaobject_p.h b/src/multimedia/base/qmediaobject_p.h new file mode 100644 index 0000000..4bbe06a --- /dev/null +++ b/src/multimedia/base/qmediaobject_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTMEDIAOBJECT_P_H +#define QABSTRACTMEDIAOBJECT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMetaDataControl; + +#define Q_DECLARE_NON_CONST_PUBLIC(Class) \ + inline Class* q_func() { return static_cast(q_ptr); } \ + friend class Class; + + +class QMediaObjectPrivate +{ + Q_DECLARE_PUBLIC(QMediaObject) + +public: + QMediaObjectPrivate():metaDataControl(0), notifyTimer(0) {} + + void _q_notify(); + + QMediaService *service; + QMetaDataControl *metaDataControl; + QTimer* notifyTimer; + QSet notifyProperties; + + QMediaObject *q_ptr; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qmediaplaylist.cpp b/src/multimedia/base/qmediaplaylist.cpp new file mode 100644 index 0000000..8a0de80 --- /dev/null +++ b/src/multimedia/base/qmediaplaylist.cpp @@ -0,0 +1,719 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include "qmediaplaylist_p.h" +#include +#include +#include +#include +#include +#include + +#include "qmediapluginloader_p.h" + + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, playlistIOLoader, + (QMediaPlaylistIOInterface_iid, QLatin1String("/playlistformats"), Qt::CaseInsensitive)) + + +/*! + \class QMediaPlaylist + \ingroup multimedia + + \preliminary + \brief The QMediaPlaylist class provides a list of media content to play. + + QMediaPlaylist is intended to be used with other media objects, + like QMediaPlayer or QMediaImageViewer. + QMediaPlaylist allows to access the service intrinsic playlist functionality + if available, otherwise it provides the the local memory playlist implementation. + +\code + player = new QMediaPlayer; + + playlist = new QMediaPlaylist; + playlist->setMediaObject(player); + playlist->append(QUrl("http://example.com/movie1.mp4")); + playlist->append(QUrl("http://example.com/movie2.mp4")); + playlist->append(QUrl("http://example.com/movie3.mp4")); + + playlist->setCurrentIndex(1); + + player->play(); +\endcode + + Depending on playlist source implementation, + most of playlist modifcation operations can be asynchronous. + + \sa QMediaContent +*/ + + +/*! + \enum QMediaPlaylist::PlaybackMode + + The QMediaPlaylist::PlaybackMode describes the order items in playlist are played. + + \value CurrentItemOnce The current item is played only once. + + \value CurrentItemInLoop The current item is played in the loop. + + \value Linear Playback starts from the first to the last items and stops. + next item is a null item when the last one is currently playing. + + \value Loop Playback continues from the first item after the last one finished playing. + + \value Random Play items in random order. +*/ + + + +/*! + Create a new playlist object for with the given \a parent. +*/ + +QMediaPlaylist::QMediaPlaylist(QObject *parent) + : QObject(parent) + , d_ptr(new QMediaPlaylistPrivate) +{ + Q_D(QMediaPlaylist); + + d->q_ptr = this; + d->localPlaylistControl = new QLocalMediaPlaylistControl(this); + + setMediaObject(0); +} + +/*! + Destroys the playlist. + */ + +QMediaPlaylist::~QMediaPlaylist() +{ + Q_D(QMediaPlaylist); + + if (d->mediaObject) + d->mediaObject->unbind(this); + + delete d_ptr; +} + +QMediaObject *QMediaPlaylist::mediaObject() const +{ + return d_func()->mediaObject; +} + +/*! + If \a mediaObject is null or doesn't have an intrinsic playlist, + internal local memory playlist source will be created. +*/ +void QMediaPlaylist::setMediaObject(QMediaObject *mediaObject) +{ + Q_D(QMediaPlaylist); + + if (mediaObject && mediaObject == d->mediaObject) + return; + + QMediaService *service = mediaObject + ? mediaObject->service() : 0; + + QMediaPlaylistControl *newControl = 0; + + if (service) + newControl = qobject_cast(service->control(QMediaPlaylistControl_iid)); + + if (!newControl) + newControl = d->localPlaylistControl; + + if (d->control != newControl) { + int oldSize = 0; + if (d->control) { + QMediaPlaylistProvider *playlist = d->control->playlistProvider(); + oldSize = playlist->mediaCount(); + disconnect(playlist, SIGNAL(loadFailed(QMediaPlaylist::Error,QString)), + this, SLOT(_q_loadFailed(QMediaPlaylist::Error,QString))); + + disconnect(playlist, SIGNAL(mediaChanged(int,int)), this, SIGNAL(mediaChanged(int,int))); + disconnect(playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SIGNAL(mediaAboutToBeInserted(int,int))); + disconnect(playlist, SIGNAL(mediaInserted(int,int)), this, SIGNAL(mediaInserted(int,int))); + disconnect(playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SIGNAL(mediaAboutToBeRemoved(int,int))); + disconnect(playlist, SIGNAL(mediaRemoved(int,int)), this, SIGNAL(mediaRemoved(int,int))); + + disconnect(playlist, SIGNAL(loaded()), this, SIGNAL(loaded())); + + disconnect(d->control, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), + this, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode))); + disconnect(d->control, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged(int))); + disconnect(d->control, SIGNAL(currentMediaChanged(QMediaContent)), + this, SIGNAL(currentMediaChanged(QMediaContent))); + } + + d->control = newControl; + QMediaPlaylistProvider *playlist = d->control->playlistProvider(); + connect(playlist, SIGNAL(loadFailed(QMediaPlaylist::Error,QString)), + this, SLOT(_q_loadFailed(QMediaPlaylist::Error,QString))); + + connect(playlist, SIGNAL(mediaChanged(int,int)), this, SIGNAL(mediaChanged(int,int))); + connect(playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SIGNAL(mediaAboutToBeInserted(int,int))); + connect(playlist, SIGNAL(mediaInserted(int,int)), this, SIGNAL(mediaInserted(int,int))); + connect(playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SIGNAL(mediaAboutToBeRemoved(int,int))); + connect(playlist, SIGNAL(mediaRemoved(int,int)), this, SIGNAL(mediaRemoved(int,int))); + + connect(playlist, SIGNAL(loaded()), this, SIGNAL(loaded())); + + connect(d->control, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), + this, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode))); + connect(d->control, SIGNAL(currentIndexChanged(int)), + this, SIGNAL(currentIndexChanged(int))); + connect(d->control, SIGNAL(currentMediaChanged(QMediaContent)), + this, SIGNAL(currentMediaChanged(QMediaContent))); + + if (oldSize) + emit mediaRemoved(0, oldSize-1); + + if (playlist->mediaCount()) { + emit mediaAboutToBeInserted(0,playlist->mediaCount()-1); + emit mediaInserted(0,playlist->mediaCount()-1); + } + } + + if (d->mediaObject) + d->mediaObject->unbind(this); + + d->mediaObject = mediaObject; + if (d->mediaObject) + d->mediaObject->bind(this); +} + +/*! + \property QMediaPlaylist::playbackMode + + This property defines the order, items in playlist are played. + + \sa QMediaPlaylist::PlaybackMode +*/ + +QMediaPlaylist::PlaybackMode QMediaPlaylist::playbackMode() const +{ + return d_func()->control->playbackMode(); +} + +void QMediaPlaylist::setPlaybackMode(QMediaPlaylist::PlaybackMode mode) +{ + Q_D(QMediaPlaylist); + d->control->setPlaybackMode(mode); +} + +/*! + Returns position of the current media source in the playlist. +*/ +int QMediaPlaylist::currentIndex() const +{ + return d_func()->control->currentIndex(); +} + +/*! + Returns the current media content. +*/ + +QMediaContent QMediaPlaylist::currentMedia() const +{ + return d_func()->playlist()->media(currentIndex()); +} + +/*! + Returns the index of item, which were current after calling next() + \a steps times. + + Returned value depends on the size of playlist, current position + and playback mode. + + \sa QMediaPlaylist::playbackMode +*/ +int QMediaPlaylist::nextIndex(int steps) const +{ + return d_func()->control->nextIndex(steps); +} + +/*! + Returns the index of item, which were current after calling previous() + \a steps times. + + \sa QMediaPlaylist::playbackMode +*/ + +int QMediaPlaylist::previousIndex(int steps) const +{ + return d_func()->control->previousIndex(steps); +} + + +/*! + Returns the number of items in the playlist. + + \sa isEmpty() + */ +int QMediaPlaylist::mediaCount() const +{ + return d_func()->playlist()->mediaCount(); +} + +/*! + Returns true if the playlist contains no items; otherwise returns false. + \sa size() + */ +bool QMediaPlaylist::isEmpty() const +{ + return mediaCount() == 0; +} + +/*! + Returns true if the playlist can be modified; otherwise returns false. + \sa size() + */ +bool QMediaPlaylist::isReadOnly() const +{ + return d_func()->playlist()->isReadOnly(); +} + +/*! + Returns the media content at \a index in the playlist. +*/ + +QMediaContent QMediaPlaylist::media(int index) const +{ + return d_func()->playlist()->media(index); +} + +/*! + Append the media \a content to the playlist. + + Returns true if the operation is successfull, other wise return false. + */ +bool QMediaPlaylist::addMedia(const QMediaContent &content) +{ + return d_func()->control->playlistProvider()->addMedia(content); +} + +/*! + Append multiple media content \a items to the playlist. + + Returns true if the operation is successfull, other wise return false. + */ +bool QMediaPlaylist::addMedia(const QList &items) +{ + return d_func()->control->playlistProvider()->addMedia(items); +} + +/*! + Insert the media \a content to the playlist at position \a pos. + + Returns true if the operation is successful, otherwise false. +*/ + +bool QMediaPlaylist::insertMedia(int pos, const QMediaContent &content) +{ + return d_func()->playlist()->insertMedia(pos, content); +} + +/*! + Insert multiple media content \a items to the playlist at position \a pos. + + Returns true if the operation is successful, otherwise false. +*/ + +bool QMediaPlaylist::insertMedia(int pos, const QList &items) +{ + return d_func()->playlist()->insertMedia(pos, items); +} + +/*! + Remove the item from the playlist at position \a pos. + + Returns true if the operation is successfull, other wise return false. + */ +bool QMediaPlaylist::removeMedia(int pos) +{ + Q_D(QMediaPlaylist); + return d->playlist()->removeMedia(pos); +} + +/*! + Remove the items from the playlist from position \a start to \a end inclusive. + + Returns true if the operation is successfull, other wise return false. + */ +bool QMediaPlaylist::removeMedia(int start, int end) +{ + Q_D(QMediaPlaylist); + return d->playlist()->removeMedia(start, end); +} + +/*! + Remove all the items from the playlist. + + Returns true if the operation is successfull, other wise return false. + */ +bool QMediaPlaylist::clear() +{ + Q_D(QMediaPlaylist); + return d->playlist()->clear(); +} + +bool QMediaPlaylistPrivate::readItems(QMediaPlaylistReader *reader) +{ + while (!reader->atEnd()) + playlist()->addMedia(reader->readItem()); + + return true; +} + +bool QMediaPlaylistPrivate::writeItems(QMediaPlaylistWriter *writer) +{ + for (int i=0; imediaCount(); i++) { + if (!writer->writeItem(playlist()->media(i))) + return false; + } + writer->close(); + return true; +} + +/*! + Load playlist from \a location. If \a format is specified, it is used, + otherwise format is guessed from location name and data. + + New items are appended to playlist. + + QMediaPlaylist::loaded() signal is emited if playlist was loaded succesfully, + otherwise the playlist emits loadFailed(). +*/ +void QMediaPlaylist::load(const QUrl &location, const char *format) +{ + Q_D(QMediaPlaylist); + + d->error = NoError; + d->errorString.clear(); + + if (d->playlist()->load(location,format)) + return; + + if (isReadOnly()) { + d->error = AccessDeniedError; + d->errorString = tr("Could not add items to read only playlist."); + emit loadFailed(); + return; + } + + foreach (QString const& key, playlistIOLoader()->keys()) { + QMediaPlaylistIOInterface* plugin = qobject_cast(playlistIOLoader()->instance(key)); + if (plugin && plugin->canRead(location,format)) { + QMediaPlaylistReader *reader = plugin->createReader(location,QByteArray(format)); + if (reader && d->readItems(reader)) { + delete reader; + emit loaded(); + return; + } + delete reader; + } + } + + d->error = FormatNotSupportedError; + d->errorString = tr("Playlist format is not supported"); + emit loadFailed(); + + return; +} + +/*! + Load playlist from QIODevice \a device. If \a format is specified, it is used, + otherwise format is guessed from device data. + + New items are appended to playlist. + + QMediaPlaylist::loaded() signal is emited if playlist was loaded succesfully, + otherwise the playlist emits loadFailed(). +*/ +void QMediaPlaylist::load(QIODevice * device, const char *format) +{ + Q_D(QMediaPlaylist); + + d->error = NoError; + d->errorString.clear(); + + if (d->playlist()->load(device,format)) + return; + + if (isReadOnly()) { + d->error = AccessDeniedError; + d->errorString = tr("Could not add items to read only playlist."); + emit loadFailed(); + return; + } + + foreach (QString const& key, playlistIOLoader()->keys()) { + QMediaPlaylistIOInterface* plugin = qobject_cast(playlistIOLoader()->instance(key)); + if (plugin && plugin->canRead(device,format)) { + QMediaPlaylistReader *reader = plugin->createReader(device,QByteArray(format)); + if (reader && d->readItems(reader)) { + delete reader; + emit loaded(); + return; + } + delete reader; + } + } + + d->error = FormatNotSupportedError; + d->errorString = tr("Playlist format is not supported"); + emit loadFailed(); + + return; +} + +/*! + Save playlist to \a location. If \a format is specified, it is used, + otherwise format is guessed from location name. + + Returns true if playlist was saved succesfully, otherwise returns false. + */ +bool QMediaPlaylist::save(const QUrl &location, const char *format) +{ + Q_D(QMediaPlaylist); + + d->error = NoError; + d->errorString.clear(); + + if (d->playlist()->save(location,format)) + return true; + + QFile file(location.toLocalFile()); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + d->error = AccessDeniedError; + d->errorString = tr("The file could not be accessed."); + return false; + } + + return save(&file, format); +} + +/*! + Save playlist to QIODevice \a device using format \a format. + + Returns true if playlist was saved succesfully, otherwise returns false. +*/ +bool QMediaPlaylist::save(QIODevice * device, const char *format) +{ + Q_D(QMediaPlaylist); + + d->error = NoError; + d->errorString.clear(); + + if (d->playlist()->save(device,format)) + return true; + + foreach (QString const& key, playlistIOLoader()->keys()) { + QMediaPlaylistIOInterface* plugin = qobject_cast(playlistIOLoader()->instance(key)); + if (plugin && plugin->canWrite(device,format)) { + QMediaPlaylistWriter *writer = plugin->createWriter(device,QByteArray(format)); + if (writer && d->writeItems(writer)) { + delete writer; + return true; + } + delete writer; + } + } + + d->error = FormatNotSupportedError; + d->errorString = tr("Playlist format is not supported."); + + return false; +} + +/*! + Returns the last error condition. +*/ +QMediaPlaylist::Error QMediaPlaylist::error() const +{ + return d_func()->error; +} + +/*! + Returns the string describing the last error condition. +*/ +QString QMediaPlaylist::errorString() const +{ + return d_func()->errorString; +} + +/*! + Shuffle items in the playlist. +*/ +void QMediaPlaylist::shuffle() +{ + d_func()->playlist()->shuffle(); +} + + +/*! + Advance to the next media content in playlist. +*/ +void QMediaPlaylist::next() +{ + d_func()->control->next(); +} + +/*! + Return to the previous media content in playlist. +*/ +void QMediaPlaylist::previous() +{ + d_func()->control->previous(); +} + +/*! + Activate media content from playlist at position \a playlistPosition. +*/ + +void QMediaPlaylist::setCurrentIndex(int playlistPosition) +{ + d_func()->control->setCurrentIndex(playlistPosition); +} + +/*! + \fn void QMediaPlaylist::mediaInserted(int start, int end) + + This signal is emitted after media has been inserted into the playlist. + The new items are those between \a start and \a end inclusive. + */ + +/*! + \fn void QMediaPlaylist::mediaRemoved(int start, int end) + + This signal is emitted after media has been removed from the playlist. + The removed items are those between \a start and \a end inclusive. + */ + +/*! + \fn void QMediaPlaylist::mediaChanged(int start, int end) + + This signal is emitted after media has been changed in the playlist + between \a start and \a end positions inclusive. + */ + +/*! + \fn void QMediaPlaylist::currentIndexChanged(int position) + + Signal emitted when playlist position changed to \a position. +*/ + +/*! + \fn void QMediaPlaylist::playbackModeChanged(QMediaPlaylist::PlaybackMode mode) + + Signal emitted when playback mode changed to \a mode. +*/ + +/*! + \fn void QMediaPlaylist::mediaAboutToBeInserted(int start, int end) + + Signal emitted when item to be inserted at \a start and ending at \a end. +*/ + +/*! + \fn void QMediaPlaylist::mediaAboutToBeRemoved(int start, int end) + + Signal emitted when item to de deleted ar \a start and ending at \a end. +*/ + +/*! + \fn void QMediaPlaylist::currentMediaChanged(const QMediaContent &content) + + Signal emitted when current media changes to \a content. +*/ + +/*! + \property QMediaPlaylist::currentIndex + \brief Current position. +*/ + +/*! + \property QMediaPlaylist::currentMedia + \brief Current media content. +*/ + +/*! + \fn QMediaPlaylist::loaded() + + Signal emitted when playlist finished loading. +*/ + +/*! + \fn QMediaPlaylist::loadFailed() + + Signal emitted if failed to load playlist. +*/ + +/*! + \enum QMediaPlaylist::Error + + This enum describes the QMediaPlaylist error codes. + + \value NoError No errors. + \value FormatError Format error. + \value FormatNotSupportedError Format not supported. + \value NetworkError Network error. + \value AccessDeniedError Access denied error. +*/ + +QT_END_NAMESPACE + +#include "moc_qmediaplaylist.cpp" +#include "moc_qmediaplaylist_p.cpp" diff --git a/src/multimedia/base/qmediaplaylist.h b/src/multimedia/base/qmediaplaylist.h new file mode 100644 index 0000000..c16541a --- /dev/null +++ b/src/multimedia/base/qmediaplaylist.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYLIST_H +#define QMEDIAPLAYLIST_H + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaPlaylistProvider; + +class QMediaPlaylistPrivate; +class Q_MULTIMEDIA_EXPORT QMediaPlaylist : public QObject +{ + Q_OBJECT + Q_PROPERTY(QMediaPlaylist::PlaybackMode playbackMode READ playbackMode WRITE setPlaybackMode NOTIFY playbackModeChanged) + Q_PROPERTY(QMediaContent currentMedia READ currentMedia NOTIFY currentMediaChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_ENUMS(PlaybackMode Error) + +public: + enum PlaybackMode { CurrentItemOnce, CurrentItemInLoop, Linear, Loop, Random }; + enum Error { NoError, FormatError, FormatNotSupportedError, NetworkError, AccessDeniedError }; + + QMediaPlaylist(QObject *parent = 0); + virtual ~QMediaPlaylist(); + + QMediaObject *mediaObject() const; + void setMediaObject(QMediaObject *object); + + PlaybackMode playbackMode() const; + void setPlaybackMode(PlaybackMode mode); + + int currentIndex() const; + QMediaContent currentMedia() const; + + int nextIndex(int steps = 1) const; + int previousIndex(int steps = 1) const; + + QMediaContent media(int index) const; + + int mediaCount() const; + bool isEmpty() const; + bool isReadOnly() const; + + bool addMedia(const QMediaContent &content); + bool addMedia(const QList &items); + bool insertMedia(int index, const QMediaContent &content); + bool insertMedia(int index, const QList &items); + bool removeMedia(int pos); + bool removeMedia(int start, int end); + bool clear(); + + void load(const QUrl &location, const char *format = 0); + void load(QIODevice * device, const char *format = 0); + + bool save(const QUrl &location, const char *format = 0); + bool save(QIODevice * device, const char *format); + + Error error() const; + QString errorString() const; + +public Q_SLOTS: + void shuffle(); + + void next(); + void previous(); + + void setCurrentIndex(int index); + +Q_SIGNALS: + void currentIndexChanged(int index); + void playbackModeChanged(QMediaPlaylist::PlaybackMode mode); + void currentMediaChanged(const QMediaContent&); + + void mediaAboutToBeInserted(int start, int end); + void mediaInserted(int start, int end); + void mediaAboutToBeRemoved(int start, int end); + void mediaRemoved(int start, int end); + void mediaChanged(int start, int end); + + void loaded(); + void loadFailed(); + +protected: + QMediaPlaylistPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QMediaPlaylist) + Q_PRIVATE_SLOT(d_func(), void _q_loadFailed(QMediaPlaylist::Error, const QString &)) +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlaylist::PlaybackMode)) +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlaylist::Error)) + +QT_END_HEADER + +#endif // QMEDIAPLAYLIST_H diff --git a/src/multimedia/base/qmediaplaylist_p.h b/src/multimedia/base/qmediaplaylist_p.h new file mode 100644 index 0000000..da529b7 --- /dev/null +++ b/src/multimedia/base/qmediaplaylist_p.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYLIST_P_H +#define QMEDIAPLAYLIST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include "qmediaobject_p.h" + +#include + +#ifdef Q_MOC_RUN +# pragma Q_MOC_EXPAND_MACROS +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaPlaylistControl; +class QMediaPlaylistProvider; +class QMediaPlaylistReader; +class QMediaPlaylistWriter; +class QMediaPlayerControl; + +class QMediaPlaylistPrivate +{ + Q_DECLARE_PUBLIC(QMediaPlaylist) +public: + QMediaPlaylistPrivate() + :mediaObject(0), + control(0), + localPlaylistControl(0), + error(QMediaPlaylist::NoError) + { + } + + virtual ~QMediaPlaylistPrivate() {} + + void _q_loadFailed(QMediaPlaylist::Error error, const QString &errorString) + { + this->error = error; + this->errorString = errorString; + + emit q_ptr->loadFailed(); + } + + void _q_mediaObjectDeleted() + { + Q_Q(QMediaPlaylist); + mediaObject = 0; + if (control != localPlaylistControl) + control = 0; + q->setMediaObject(0); + } + + QMediaObject *mediaObject; + + QMediaPlaylistControl *control; + QMediaPlaylistProvider *playlist() const { return control->playlistProvider(); } + + QMediaPlaylistControl *localPlaylistControl; + + bool readItems(QMediaPlaylistReader *reader); + bool writeItems(QMediaPlaylistWriter *writer); + + QMediaPlaylist::Error error; + QString errorString; + + QMediaPlaylist *q_ptr; +}; + + +class QLocalMediaPlaylistControl : public QMediaPlaylistControl +{ + Q_OBJECT +public: + QLocalMediaPlaylistControl(QObject *parent) + :QMediaPlaylistControl(parent) + { + QMediaPlaylistProvider *playlist = new QLocalMediaPlaylistProvider(this); + m_navigator = new QMediaPlaylistNavigator(playlist,this); + m_navigator->setPlaybackMode(QMediaPlaylist::Linear); + + connect(m_navigator, SIGNAL(currentIndexChanged(int)), SIGNAL(currentIndexChanged(int))); + connect(m_navigator, SIGNAL(activated(QMediaContent)), SIGNAL(currentMediaChanged(QMediaContent))); + } + + virtual ~QLocalMediaPlaylistControl() {}; + + QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); } + bool setPlaylistProvider(QMediaPlaylistProvider *mediaPlaylist) + { + m_navigator->setPlaylist(mediaPlaylist); + emit playlistProviderChanged(); + 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; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYLIST_P_H diff --git a/src/multimedia/base/qmediaplaylistcontrol.cpp b/src/multimedia/base/qmediaplaylistcontrol.cpp new file mode 100644 index 0000000..2ae03ad --- /dev/null +++ b/src/multimedia/base/qmediaplaylistcontrol.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include "qmediacontrol_p.h" + + +QT_BEGIN_NAMESPACE + +/*! + \class QMediaPlaylistControl + \ingroup multimedia-serv + + \preliminary + \brief The QMediaPlaylistControl class provides access to the playlist functionality of a + QMediaService. + + If a QMediaService contains an internal playlist it will implement QMediaPlaylistControl. This + control provides access to the contents of the \l {playlistProvider()}{playlist}, as well as the + \l {currentIndex()}{position} of the current media, and a means of navigating to the + \l {next()}{next} and \l {previous()}{previous} media. + + The functionality provided by the control is exposed to application code through the + QMediaPlaylist class. + + The interface name of QMediaPlaylistControl is \c com.nokia.Qt.QMediaPlaylistControl/1.0 as + defined in QMediaPlaylistControl_iid. + + \sa QMediaService::control(), QMediaPlayer +*/ + +/*! + \macro QMediaPlaylistControl_iid + + \c com.nokia.Qt.QMediaPlaylistControl/1.0 + + Defines the interface name of the QMediaPlaylistControl class. + + \relates QMediaPlaylistControl +*/ + +/*! + Create a new playlist control object with the given \a parent. +*/ +QMediaPlaylistControl::QMediaPlaylistControl(QObject *parent): + QMediaControl(*new QMediaControlPrivate, parent) +{ +} + +/*! + Destroys the playlist control. +*/ +QMediaPlaylistControl::~QMediaPlaylistControl() +{ +} + + +/*! + \fn QMediaPlaylistControl::playlistProvider() const + + Returns the playlist used by this media player. +*/ + +/*! + \fn QMediaPlaylistControl::setPlaylistProvider(QMediaPlaylistProvider *playlist) + + Set the playlist of this media player to \a playlist. + + In many cases it is possible just to use the playlist + constructed by player, but sometimes replacing the whole + playlist allows to avoid copyting of all the items bettween playlists. + + Returns true if player can use this passed playlist; otherwise returns false. + +*/ + +/*! + \fn QMediaPlaylistControl::currentIndex() const + + Returns position of the current media source in the playlist. +*/ + +/*! + \fn QMediaPlaylistControl::setCurrentIndex(int position) + + Jump to the item at the given \a position. +*/ + +/*! + \fn QMediaPlaylistControl::nextIndex(int step) const + + Returns the index of item, which were current after calling next() + \a step times. + + Returned value depends on the size of playlist, current position + and playback mode. + + \sa QMediaPlaylist::playbackMode +*/ + +/*! + \fn QMediaPlaylistControl::previousIndex(int step) const + + Returns the index of item, which were current after calling previous() + \a step times. + + \sa QMediaPlaylist::playbackMode +*/ + +/*! + \fn QMediaPlaylistControl::next() + + Moves to the next item in playlist. +*/ + +/*! + \fn QMediaPlaylistControl::previous() + + Returns to the previous item in playlist. +*/ + +/*! + \fn QMediaPlaylistControl::playbackMode() const + + Returns the playlist navigation mode. + + \sa QMediaPlaylist::PlaybackMode +*/ + +/*! + \fn QMediaPlaylistControl::setPlaybackMode(QMediaPlaylist::PlaybackMode mode) + + Sets the playback \a mode. + + \sa QMediaPlaylist::PlaybackMode +*/ + +/*! + \fn QMediaPlaylistControl::playlistProviderChanged() + + Signal emited when the playlist provider has changed. +*/ + +/*! + \fn QMediaPlaylistControl::currentIndexChanged(int position) + + Signal emited when the playlist \a position is changed. +*/ + +/*! + \fn QMediaPlaylistControl::playbackModeChanged(QMediaPlaylist::PlaybackMode mode) + + Signal emited when the playback \a mode is changed. +*/ + +/*! + \fn QMediaPlaylistControl::currentMediaChanged(const QMediaContent& content) + + Signal emitted when current media changes to \a content. +*/ + +#include "moc_qmediaplaylistcontrol.cpp" +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediaplaylistcontrol.h b/src/multimedia/base/qmediaplaylistcontrol.h new file mode 100644 index 0000000..228ee19 --- /dev/null +++ b/src/multimedia/base/qmediaplaylistcontrol.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QMEDIAPLAYLISTCONTROL_H +#define QMEDIAPLAYLISTCONTROL_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QMediaPlaylistProvider; + +class Q_MULTIMEDIA_EXPORT QMediaPlaylistControl : public QMediaControl +{ + Q_OBJECT + +public: + virtual ~QMediaPlaylistControl(); + + virtual QMediaPlaylistProvider* playlistProvider() const = 0; + virtual bool setPlaylistProvider(QMediaPlaylistProvider *playlist) = 0; + + virtual int currentIndex() const = 0; + virtual void setCurrentIndex(int position) = 0; + virtual int nextIndex(int steps) const = 0; + virtual int previousIndex(int steps) const = 0; + + virtual void next() = 0; + virtual void previous() = 0; + + virtual QMediaPlaylist::PlaybackMode playbackMode() const = 0; + virtual void setPlaybackMode(QMediaPlaylist::PlaybackMode mode) = 0; + +Q_SIGNALS: + void playlistProviderChanged(); + void currentIndexChanged(int position); + void currentMediaChanged(const QMediaContent&); + void playbackModeChanged(QMediaPlaylist::PlaybackMode mode); + +protected: + QMediaPlaylistControl(QObject* parent = 0); +}; + +#define QMediaPlaylistControl_iid "com.nokia.Qt.QMediaPlaylistControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QMediaPlaylistControl, QMediaPlaylistControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYLISTCONTROL_H diff --git a/src/multimedia/base/qmediaplaylistioplugin.cpp b/src/multimedia/base/qmediaplaylistioplugin.cpp new file mode 100644 index 0000000..5f11e38 --- /dev/null +++ b/src/multimedia/base/qmediaplaylistioplugin.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QMediaPlaylistReader + \preliminary + \brief The QMediaPlaylistReader class provides an interface for reading a playlist file. + + \sa QMediaPlaylistIOPlugin +*/ + +/*! + Destroys a media playlist reader. +*/ +QMediaPlaylistReader::~QMediaPlaylistReader() +{ +} + +/*! + \fn QMediaPlaylistReader::atEnd() const + + Identifies if a playlist reader has reached the end of its input. + + Returns true if the reader has reached the end; and false otherwise. +*/ + +/*! + \fn QMediaPlaylistReader::readItem() + + Reads an item of media from a playlist file. + + Returns the read media, or a null QMediaContent if no more media is available. +*/ + +/*! + \fn QMediaPlaylistReader::close() + + Closes a playlist reader's input device. +*/ + +/*! + \class QMediaPlaylistWriter + \preliminary + \brief The QMediaPlaylistWriter class provides an interface for writing a playlist file. + + \sa QMediaPlaylistIOPlugin +*/ + +/*! + Destroys a media playlist writer. +*/ +QMediaPlaylistWriter::~QMediaPlaylistWriter() +{ +} + +/*! + \fn QMediaPlaylistWriter::writeItem(const QMediaContent &media) + + Writes an item of \a media to a playlist file. + + Returns true if the media was written succesfully; and false otherwise. +*/ + +/*! + \fn QMediaPlaylistWriter::close() + + Finalizes the writing of a playlist and closes the output device. +*/ + +/*! + \class QMediaPlaylistIOPlugin + \brief The QMediaPlaylistIOPlugin class provides an interface for media playlist I/O plug-ins. +*/ + +/*! + Constructs a media playlist I/O plug-in with the given \a parent. +*/ +QMediaPlaylistIOPlugin::QMediaPlaylistIOPlugin(QObject *parent) + :QObject(parent) +{ +} + +/*! + Destroys a media playlist I/O plug-in. +*/ +QMediaPlaylistIOPlugin::~QMediaPlaylistIOPlugin() +{ +} + +/*! + \fn QMediaPlaylistIOPlugin::canRead(QIODevice *device, const QByteArray &format) const + + Identifies if plug-in can read \a format data from an I/O \a device. + + Returns true if the data can be read; and false otherwise. +*/ + +/*! + \fn QMediaPlaylistIOPlugin::canRead(const QUrl& location, const QByteArray &format) const + + Identifies if a plug-in can read \a format data from a URL \a location. + + Returns true if the data can be read; and false otherwise. +*/ + +/*! + \fn QMediaPlaylistIOPlugin::canWrite(QIODevice *device, const QByteArray &format) const + + Identifies if a plug-in can write \a format data to an I/O \a device. + + Returns true if the data can be written; and false otherwise. +*/ + +/*! + \fn QMediaPlaylistIOPlugin::keys() const + + Returns a list of format keys supported by a plug-in. +*/ + +/*! + \fn QMediaPlaylistIOPlugin::createReader(QIODevice *device, const QByteArray &format) + + Returns a new QMediaPlaylistReader which reads \a format data from an I/O \a device. + + If the device is invalid or the format is unsupported this will return a null pointer. +*/ + +/*! + \fn QMediaPlaylistIOPlugin::createReader(const QUrl& location, const QByteArray &format) + + Returns a new QMediaPlaylistReader which reads \a format data from a URL \a location. + + If the location or the format is unsupported this will return a null pointer. +*/ + +/*! + \fn QMediaPlaylistIOPlugin::createWriter(QIODevice *device, const QByteArray &format) + + Returns a new QMediaPlaylistWriter which writes \a format data to an I/O \a device. + + If the device is invalid or the format is unsupported this will return a null pointer. +*/ + +QT_END_NAMESPACE + +#include "moc_qmediaplaylistioplugin.cpp" + diff --git a/src/multimedia/base/qmediaplaylistioplugin.h b/src/multimedia/base/qmediaplaylistioplugin.h new file mode 100644 index 0000000..e55298d --- /dev/null +++ b/src/multimedia/base/qmediaplaylistioplugin.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYLISTIOPLUGIN_H +#define QMEDIAPLAYLISTIOPLUGIN_H + +#include +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QString; +class QUrl; +class QByteArray; +class QIODevice; +class QStringList; + +class Q_MULTIMEDIA_EXPORT QMediaPlaylistReader +{ +public: + virtual ~QMediaPlaylistReader(); + + virtual bool atEnd() const = 0; + virtual QMediaContent readItem() = 0; + virtual void close() = 0; +}; + +class Q_MULTIMEDIA_EXPORT QMediaPlaylistWriter +{ +public: + virtual ~QMediaPlaylistWriter(); + + virtual bool writeItem(const QMediaContent &content) = 0; + virtual void close() = 0; +}; + +struct Q_MULTIMEDIA_EXPORT QMediaPlaylistIOInterface : public QFactoryInterface +{ + virtual bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const = 0; + virtual bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const = 0; + + virtual bool canWrite(QIODevice *device, const QByteArray &format) const = 0; + + virtual QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray()) = 0; + virtual QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray()) = 0; + + virtual QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format) = 0; +}; + +#define QMediaPlaylistIOInterface_iid "com.nokia.Qt.QMediaPlaylistIOInterface" +Q_DECLARE_INTERFACE(QMediaPlaylistIOInterface, QMediaPlaylistIOInterface_iid); + +class Q_MULTIMEDIA_EXPORT QMediaPlaylistIOPlugin : public QObject, public QMediaPlaylistIOInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaPlaylistIOInterface:QFactoryInterface) + +public: + explicit QMediaPlaylistIOPlugin(QObject *parent = 0); + virtual ~QMediaPlaylistIOPlugin(); + + virtual bool canRead(QIODevice *device, const QByteArray &format = QByteArray() ) const = 0; + virtual bool canRead(const QUrl& location, const QByteArray &format = QByteArray()) const = 0; + + virtual bool canWrite(QIODevice *device, const QByteArray &format) const = 0; + + virtual QStringList keys() const = 0; + + virtual QMediaPlaylistReader *createReader(QIODevice *device, const QByteArray &format = QByteArray()) = 0; + virtual QMediaPlaylistReader *createReader(const QUrl& location, const QByteArray &format = QByteArray()) = 0; + + virtual QMediaPlaylistWriter *createWriter(QIODevice *device, const QByteArray &format) = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYLISTIOPLUGIN_H diff --git a/src/multimedia/base/qmediaplaylistnavigator.cpp b/src/multimedia/base/qmediaplaylistnavigator.cpp new file mode 100644 index 0000000..3c22ea4 --- /dev/null +++ b/src/multimedia/base/qmediaplaylistnavigator.cpp @@ -0,0 +1,544 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "qmediaobject_p.h" + +#include + +QT_BEGIN_NAMESPACE + +class QMediaPlaylistNullProvider : public QMediaPlaylistProvider +{ +public: + QMediaPlaylistNullProvider() :QMediaPlaylistProvider() {} + virtual ~QMediaPlaylistNullProvider() {} + virtual int mediaCount() const {return 0;} + virtual QMediaContent media(int) const { return QMediaContent(); } +}; + +Q_GLOBAL_STATIC(QMediaPlaylistNullProvider, _q_nullMediaPlaylist) + +class QMediaPlaylistNavigatorPrivate +{ + Q_DECLARE_NON_CONST_PUBLIC(QMediaPlaylistNavigator) +public: + QMediaPlaylistNavigatorPrivate() + :playlist(0), + currentPos(-1), + lastValidPos(-1), + playbackMode(QMediaPlaylist::Linear), + randomPositionsOffset(-1) + { + } + + QMediaPlaylistProvider *playlist; + int currentPos; + int lastValidPos; //to be used with CurrentItemOnce playback mode + QMediaPlaylist::PlaybackMode playbackMode; + QMediaContent currentItem; + + mutable QList randomModePositions; + mutable int randomPositionsOffset; + + int nextItemPos(int steps = 1) const; + int previousItemPos(int steps = 1) const; + + void _q_mediaInserted(int start, int end); + void _q_mediaRemoved(int start, int end); + void _q_mediaChanged(int start, int end); + + QMediaPlaylistNavigator *q_ptr; +}; + + +int QMediaPlaylistNavigatorPrivate::nextItemPos(int steps) const +{ + if (playlist->mediaCount() == 0) + return -1; + + if (steps == 0) + return currentPos; + + switch (playbackMode) { + case QMediaPlaylist::CurrentItemOnce: + return /*currentPos == -1 ? lastValidPos :*/ -1; + case QMediaPlaylist::CurrentItemInLoop: + return currentPos; + case QMediaPlaylist::Linear: + { + int nextPos = currentPos+steps; + return nextPos < playlist->mediaCount() ? nextPos : -1; + } + case QMediaPlaylist::Loop: + return (currentPos+steps) % playlist->mediaCount(); + case QMediaPlaylist::Random: + { + //TODO: limit the history size + + if (randomPositionsOffset == -1) { + randomModePositions.clear(); + randomModePositions.append(currentPos); + randomPositionsOffset = 0; + } + + while (randomModePositions.size() < randomPositionsOffset+steps+1) + randomModePositions.append(-1); + int res = randomModePositions[randomPositionsOffset+steps]; + if (res<0 || res >= playlist->mediaCount()) { + res = qrand() % playlist->mediaCount(); + randomModePositions[randomPositionsOffset+steps] = res; + } + + return res; + } + } + + return -1; +} + +int QMediaPlaylistNavigatorPrivate::previousItemPos(int steps) const +{ + if (playlist->mediaCount() == 0) + return -1; + + if (steps == 0) + return currentPos; + + switch (playbackMode) { + case QMediaPlaylist::CurrentItemOnce: + return /*currentPos == -1 ? lastValidPos :*/ -1; + case QMediaPlaylist::CurrentItemInLoop: + return currentPos; + case QMediaPlaylist::Linear: + { + int prevPos = currentPos == -1 ? playlist->mediaCount() - steps : currentPos - steps; + return prevPos>=0 ? prevPos : -1; + } + case QMediaPlaylist::Loop: + { + int prevPos = currentPos - steps; + while (prevPos<0) + prevPos += playlist->mediaCount(); + return prevPos; + } + case QMediaPlaylist::Random: + { + //TODO: limit the history size + + if (randomPositionsOffset == -1) { + randomModePositions.clear(); + randomModePositions.append(currentPos); + randomPositionsOffset = 0; + } + + while (randomPositionsOffset-steps < 0) { + randomModePositions.prepend(-1); + randomPositionsOffset++; + } + + int res = randomModePositions[randomPositionsOffset-steps]; + if (res<0 || res >= playlist->mediaCount()) { + res = qrand() % playlist->mediaCount(); + randomModePositions[randomPositionsOffset-steps] = res; + } + + return res; + } + } + + return -1; +} + +/*! + \class QMediaPlaylistNavigator + \preliminary + \brief The QMediaPlaylistNavigator class provides navigation for a media playlist. + + \sa QMediaPlaylist, QMediaPlaylistProvider +*/ + + +/*! + Constructs a media playlist navigator for a \a playlist. + + The \a parent is passed to QObject. + */ +QMediaPlaylistNavigator::QMediaPlaylistNavigator(QMediaPlaylistProvider *playlist, QObject *parent) + : QObject(parent) + , d_ptr(new QMediaPlaylistNavigatorPrivate) +{ + d_ptr->q_ptr = this; + + setPlaylist(playlist ? playlist : _q_nullMediaPlaylist()); +} + +/*! + Destroys a media playlist navigator. + */ + +QMediaPlaylistNavigator::~QMediaPlaylistNavigator() +{ + delete d_ptr; +} + + +/*! \property QMediaPlaylistNavigator::playbackMode + Contains the playback mode. + */ +QMediaPlaylist::PlaybackMode QMediaPlaylistNavigator::playbackMode() const +{ + return d_func()->playbackMode; +} + +/*! + Sets the playback \a mode. + */ +void QMediaPlaylistNavigator::setPlaybackMode(QMediaPlaylist::PlaybackMode mode) +{ + Q_D(QMediaPlaylistNavigator); + if (d->playbackMode == mode) + return; + + if (mode == QMediaPlaylist::Random) { + d->randomPositionsOffset = 0; + d->randomModePositions.append(d->currentPos); + } else if (d->playbackMode == QMediaPlaylist::Random) { + d->randomPositionsOffset = -1; + d->randomModePositions.clear(); + } + + d->playbackMode = mode; + + emit playbackModeChanged(mode); + emit surroundingItemsChanged(); +} + +/*! + Returns the playlist being navigated. +*/ + +QMediaPlaylistProvider *QMediaPlaylistNavigator::playlist() const +{ + return d_func()->playlist; +} + +/*! + Sets the \a playlist to navigate. +*/ +void QMediaPlaylistNavigator::setPlaylist(QMediaPlaylistProvider *playlist) +{ + Q_D(QMediaPlaylistNavigator); + + if (d->playlist == playlist) + return; + + if (d->playlist) { + d->playlist->disconnect(this); + } + + if (playlist) { + d->playlist = playlist; + } else { + //assign to shared readonly null playlist + d->playlist = _q_nullMediaPlaylist(); + } + + connect(d->playlist, SIGNAL(mediaInserted(int,int)), SLOT(_q_mediaInserted(int,int))); + connect(d->playlist, SIGNAL(mediaRemoved(int,int)), SLOT(_q_mediaRemoved(int,int))); + connect(d->playlist, SIGNAL(mediaChanged(int,int)), SLOT(_q_mediaChanged(int,int))); + + d->randomPositionsOffset = -1; + d->randomModePositions.clear(); + + if (d->currentPos != -1) { + d->currentPos = -1; + emit currentIndexChanged(-1); + } + + if (!d->currentItem.isNull()) { + d->currentItem = QMediaContent(); + emit activated(d->currentItem); //stop playback + } +} + +/*! \property QMediaPlaylistNavigator::currentItem + + Contains the media at the current position in the playlist. + + \sa currentIndex() +*/ + +QMediaContent QMediaPlaylistNavigator::currentItem() const +{ + return itemAt(d_func()->currentPos); +} + +/*! \fn QMediaContent QMediaPlaylistNavigator::nextItem(int steps) const + + Returns the media that is \a steps positions ahead of the current + position in the playlist. + + \sa nextIndex() +*/ +QMediaContent QMediaPlaylistNavigator::nextItem(int steps) const +{ + return itemAt(nextIndex(steps)); +} + +/*! + Returns the media that is \a steps positions behind the current + position in the playlist. + + \sa previousIndex() + */ +QMediaContent QMediaPlaylistNavigator::previousItem(int steps) const +{ + return itemAt(previousIndex(steps)); +} + +/*! + Returns the media at a \a position in the playlist. + */ +QMediaContent QMediaPlaylistNavigator::itemAt(int position) const +{ + return d_func()->playlist->media(position); +} + +/*! \property QMediaPlaylistNavigator::currentIndex + + Contains the position of the current media. + + If no media is current, the property contains -1. + + \sa nextIndex(), previousIndex() +*/ + +int QMediaPlaylistNavigator::currentIndex() const +{ + return d_func()->currentPos; +} + +/*! + Returns a position \a steps ahead of the current position + accounting for the playbackMode(). + + If the position is beyond the end of the playlist, this value + returned is -1. + + \sa currentIndex(), previousIndex(), playbackMode() +*/ + +int QMediaPlaylistNavigator::nextIndex(int steps) const +{ + return d_func()->nextItemPos(steps); +} + +/*! + + Returns a position \a steps behind the current position accounting + for the playbackMode(). + + If the position is prior to the beginning of the playlist this will + return -1. + + \sa currentIndex(), nextIndex(), playbackMode() +*/ +int QMediaPlaylistNavigator::previousIndex(int steps) const +{ + return d_func()->previousItemPos(steps); +} + +/*! + Advances to the next item in the playlist. + + \sa previous(), jump(), playbackMode() + */ +void QMediaPlaylistNavigator::next() +{ + Q_D(QMediaPlaylistNavigator); + + int nextPos = d->nextItemPos(); + + if ( playbackMode() == QMediaPlaylist::Random ) + d->randomPositionsOffset++; + + jump(nextPos); +} + +/*! + Returns to the previous item in the playlist, + + \sa next(), jump(), playbackMode() + */ +void QMediaPlaylistNavigator::previous() +{ + Q_D(QMediaPlaylistNavigator); + + int prevPos = d->previousItemPos(); + if ( playbackMode() == QMediaPlaylist::Random ) + d->randomPositionsOffset--; + + jump(prevPos); +} + +/*! + Jumps to a new \a position in the playlist. + */ +void QMediaPlaylistNavigator::jump(int position) +{ + Q_D(QMediaPlaylistNavigator); + + if (position<-1 || position>=d->playlist->mediaCount()) { + qWarning() << "QMediaPlaylistNavigator: Jump outside playlist range"; + position = -1; + } + + if (position != -1) + d->lastValidPos = position; + + if (playbackMode() == QMediaPlaylist::Random) { + if (d->randomModePositions[d->randomPositionsOffset] != position) { + d->randomModePositions.clear(); + d->randomModePositions.append(position); + d->randomPositionsOffset = 0; + } + } + + if (position != -1) + d->currentItem = d->playlist->media(position); + else + d->currentItem = QMediaContent(); + + if (position != d->currentPos) { + d->currentPos = position; + emit currentIndexChanged(d->currentPos); + emit surroundingItemsChanged(); + } + + emit activated(d->currentItem); +} + +/*! + \internal +*/ +void QMediaPlaylistNavigatorPrivate::_q_mediaInserted(int start, int end) +{ + Q_Q(QMediaPlaylistNavigator); + + if (currentPos >= start) { + currentPos = end-start+1; + q->jump(currentPos); + } + + //TODO: check if they really changed + emit q->surroundingItemsChanged(); +} + +/*! + \internal +*/ +void QMediaPlaylistNavigatorPrivate::_q_mediaRemoved(int start, int end) +{ + Q_Q(QMediaPlaylistNavigator); + + if (currentPos > end) { + currentPos = currentPos - end-start+1; + q->jump(currentPos); + } else if (currentPos >= start) { + //current item was removed + currentPos = qMin(start, playlist->mediaCount()-1); + q->jump(currentPos); + } + + //TODO: check if they really changed + emit q->surroundingItemsChanged(); +} + +/*! + \internal +*/ +void QMediaPlaylistNavigatorPrivate::_q_mediaChanged(int start, int end) +{ + Q_Q(QMediaPlaylistNavigator); + + if (currentPos >= start && currentPos<=end) { + QMediaContent src = playlist->media(currentPos); + if (src != currentItem) { + currentItem = src; + emit q->activated(src); + } + } + + //TODO: check if they really changed + emit q->surroundingItemsChanged(); +} + +/*! + \fn QMediaPlaylistNavigator::activated(const QMediaContent &media) + + Signals that the current \a media has changed. +*/ + +/*! + \fn QMediaPlaylistNavigator::currentIndexChanged(int position) + + Signals the \a position of the current media has changed. +*/ + +/*! + \fn QMediaPlaylistNavigator::playbackModeChanged(QMediaPlaylist::PlaybackMode mode) + + Signals that the playback \a mode has changed. +*/ + +/*! + \fn QMediaPlaylistNavigator::surroundingItemsChanged() + + Signals that media immediately surrounding the current position has changed. +*/ + +#include "moc_qmediaplaylistnavigator.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediaplaylistnavigator.h b/src/multimedia/base/qmediaplaylistnavigator.h new file mode 100644 index 0000000..73789af --- /dev/null +++ b/src/multimedia/base/qmediaplaylistnavigator.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYLISTNAVIGATOR_H +#define QMEDIAPLAYLISTNAVIGATOR_H + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QMediaPlaylistNavigatorPrivate; +class Q_MULTIMEDIA_EXPORT QMediaPlaylistNavigator : public QObject +{ + Q_OBJECT + Q_PROPERTY(QMediaPlaylist::PlaybackMode playbackMode READ playbackMode WRITE setPlaybackMode NOTIFY playbackModeChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE jump NOTIFY currentIndexChanged) + Q_PROPERTY(QMediaContent currentItem READ currentItem NOTIFY currentItemChanged) + +public: + QMediaPlaylistNavigator(QMediaPlaylistProvider *playlist, QObject *parent = 0); + virtual ~QMediaPlaylistNavigator(); + + QMediaPlaylistProvider *playlist() const; + void setPlaylist(QMediaPlaylistProvider *playlist); + + QMediaPlaylist::PlaybackMode playbackMode() const; + + QMediaContent currentItem() const; + QMediaContent nextItem(int steps = 1) const; + QMediaContent previousItem(int steps = 1) const; + + QMediaContent itemAt(int position) const; + + int currentIndex() const; + int nextIndex(int steps = 1) const; + int previousIndex(int steps = 1) const; + +public Q_SLOTS: + void next(); + void previous(); + + void jump(int); + + void setPlaybackMode(QMediaPlaylist::PlaybackMode mode); + +Q_SIGNALS: + void activated(const QMediaContent &content); + void currentIndexChanged(int); + void playbackModeChanged(QMediaPlaylist::PlaybackMode mode); + + void surroundingItemsChanged(); + +protected: + QMediaPlaylistNavigatorPrivate *d_ptr; + +private: + Q_DISABLE_COPY(QMediaPlaylistNavigator) + Q_DECLARE_PRIVATE(QMediaPlaylistNavigator) + + Q_PRIVATE_SLOT(d_func(), void _q_mediaInserted(int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_mediaRemoved(int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_mediaChanged(int start, int end)) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYLISTNAVIGATOR_H diff --git a/src/multimedia/base/qmediaplaylistprovider.cpp b/src/multimedia/base/qmediaplaylistprovider.cpp new file mode 100644 index 0000000..65105dc --- /dev/null +++ b/src/multimedia/base/qmediaplaylistprovider.cpp @@ -0,0 +1,307 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include "qmediaplaylistprovider_p.h" + + +QT_BEGIN_NAMESPACE + +/*! + \class QMediaPlaylistProvider + \preliminary + \brief The QMediaPlaylistProvider class provides an abstract list of media. + + \sa QMediaPlaylist +*/ + +/*! + Constructs a playlist provider with the given \a parent. +*/ +QMediaPlaylistProvider::QMediaPlaylistProvider(QObject *parent) + :QObject(parent), d_ptr(new QMediaPlaylistProviderPrivate) +{ +} + +/*! + \internal +*/ +QMediaPlaylistProvider::QMediaPlaylistProvider(QMediaPlaylistProviderPrivate &dd, QObject *parent) + :QObject(parent), d_ptr(&dd) +{ +} + +/*! + Destroys a playlist provider. +*/ +QMediaPlaylistProvider::~QMediaPlaylistProvider() +{ + delete d_ptr; +} + +/*! + \fn QMediaPlaylistProvider::mediaCount() const; + + Returns the size of playlist. +*/ + +/*! + \fn QMediaPlaylistProvider::media(int index) const; + + Returns the media at \a index in the playlist. + + If the index is invalid this will return a null media content. +*/ + + +/*! + Loads a playlist from from a URL \a location. If no playlist \a format is specified the loader + will inspect the URL or probe the headers to guess the format. + + New items are appended to playlist. + + Returns true if the provider supports the format and loading from the locations URL protocol, + otherwise this will return false. +*/ +bool QMediaPlaylistProvider::load(const QUrl &location, const char *format) +{ + Q_UNUSED(location); + Q_UNUSED(format); + return false; +} + +/*! + Loads a playlist from from an I/O \a device. If no playlist \a format is specified the loader + will probe the headers to guess the format. + + New items are appended to playlist. + + Returns true if the provider supports the format and loading from an I/O device, otherwise this + will return false. +*/ +bool QMediaPlaylistProvider::load(QIODevice * device, const char *format) +{ + Q_UNUSED(device); + Q_UNUSED(format); + return false; +} + +/*! + Saves the contents of a playlist to a URL \a location. If no playlist \a format is specified + the writer will inspect the URL to guess the format. + + Returns true if the playlist was saved succesfully; and false otherwise. + */ +bool QMediaPlaylistProvider::save(const QUrl &location, const char *format) +{ + Q_UNUSED(location); + Q_UNUSED(format); + return false; +} + +/*! + Saves the contents of a playlist to an I/O \a device in the specified \a format. + + Returns true if the playlist was saved succesfully; and false otherwise. +*/ +bool QMediaPlaylistProvider::save(QIODevice * device, const char *format) +{ + Q_UNUSED(device); + Q_UNUSED(format); + return false; +} + +/*! + Returns true if a playlist is read-only; otherwise returns false. +*/ +bool QMediaPlaylistProvider::isReadOnly() const +{ + return true; +} + +/*! + Append \a media to a playlist. + + Returns true if the media was appended; and false otherwise. +*/ +bool QMediaPlaylistProvider::addMedia(const QMediaContent &media) +{ + Q_UNUSED(media); + return false; +} + +/*! + Append multiple media \a items to a playlist. + + Returns true if the media items were appended; and false otherwise. +*/ +bool QMediaPlaylistProvider::addMedia(const QList &items) +{ + foreach(const QMediaContent &item, items) { + if (!addMedia(item)) + return false; + } + + return true; +} + +/*! + Inserts \a media into a playlist at \a position. + + Returns true if the media was inserted; and false otherwise. +*/ +bool QMediaPlaylistProvider::insertMedia(int position, const QMediaContent &media) +{ + Q_UNUSED(position); + Q_UNUSED(media); + return false; +} + +/*! + Inserts multiple media \a items into a playlist at \a position. + + Returns true if the media \a items were inserted; and false otherwise. +*/ +bool QMediaPlaylistProvider::insertMedia(int position, const QList &items) +{ + for (int i=0; i + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QString; + + +class QMediaPlaylistProviderPrivate; +class Q_MULTIMEDIA_EXPORT QMediaPlaylistProvider : public QObject +{ + Q_OBJECT + +public: + QMediaPlaylistProvider(QObject *parent=0); + virtual ~QMediaPlaylistProvider(); + + virtual bool load(const QUrl &location, const char *format = 0); + virtual bool load(QIODevice * device, const char *format = 0); + virtual bool save(const QUrl &location, const char *format = 0); + virtual bool save(QIODevice * device, const char *format); + + virtual int mediaCount() const = 0; + virtual QMediaContent media(int index) const = 0; + + virtual bool isReadOnly() const; + + virtual bool addMedia(const QMediaContent &content); + virtual bool addMedia(const QList &contentList); + virtual bool insertMedia(int index, const QMediaContent &content); + virtual bool insertMedia(int index, const QList &content); + virtual bool removeMedia(int pos); + virtual bool removeMedia(int start, int end); + virtual bool clear(); + +public Q_SLOTS: + virtual void shuffle(); + +Q_SIGNALS: + void mediaAboutToBeInserted(int start, int end); + void mediaInserted(int start, int end); + + void mediaAboutToBeRemoved(int start, int end); + void mediaRemoved(int start, int end); + + void mediaChanged(int start, int end); + + void loaded(); + void loadFailed(QMediaPlaylist::Error, const QString& errorMessage); + +protected: + QMediaPlaylistProviderPrivate *d_ptr; + QMediaPlaylistProvider(QMediaPlaylistProviderPrivate &dd, QObject *parent); + +private: + Q_DECLARE_PRIVATE(QMediaPlaylistProvider) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYLISTPROVIDER_H diff --git a/src/multimedia/base/qmediaplaylistprovider_p.h b/src/multimedia/base/qmediaplaylistprovider_p.h new file mode 100644 index 0000000..aaf6deb --- /dev/null +++ b/src/multimedia/base/qmediaplaylistprovider_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYLISTPROVIDER_P_H +#define QMEDIAPLAYLISTPROVIDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaPlaylistProviderPrivate +{ +public: + QMediaPlaylistProviderPrivate() + {} + virtual ~QMediaPlaylistProviderPrivate() + {} +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYLISTSOURCE_P_H diff --git a/src/multimedia/base/qmediapluginloader.cpp b/src/multimedia/base/qmediapluginloader.cpp new file mode 100644 index 0000000..8130413 --- /dev/null +++ b/src/multimedia/base/qmediapluginloader.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmediapluginloader_p.h" +#include +#include +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + + +typedef QMap ObjectListMap; +Q_GLOBAL_STATIC(ObjectListMap, staticMediaPlugins); + +QMediaPluginLoader::QMediaPluginLoader(const char *iid, const QString &location, Qt::CaseSensitivity): + m_iid(iid) +{ + m_location = location + QLatin1String("/"); + load(); +} + +QStringList QMediaPluginLoader::keys() const +{ + return m_instances.keys(); +} + +QObject* QMediaPluginLoader::instance(QString const &key) +{ + return m_instances.value(key); +} + +QList QMediaPluginLoader::instances(QString const &key) +{ + return m_instances.values(key); +} + +//to be used for testing purposes only +void QMediaPluginLoader::setStaticPlugins(const QString &location, const QObjectList& objects) +{ + staticMediaPlugins()->insert(location + QLatin1String("/"), objects); +} + +void QMediaPluginLoader::load() +{ + if (!m_instances.isEmpty()) + return; + + if (staticMediaPlugins() && staticMediaPlugins()->contains(m_location)) { + qWarning() << "Load static plugins for" << m_location; + foreach(QObject *o, staticMediaPlugins()->value(m_location)) { + if (o != 0 && o->qt_metacast(m_iid) != 0) { + QFactoryInterface* p = qobject_cast(o); + if (p != 0) { + foreach (QString const &key, p->keys()) + m_instances.insertMulti(key, o); + } + } + } + } else { + QStringList paths = QCoreApplication::libraryPaths(); + + foreach (QString const &path, paths) { + QString pluginPathName(path + m_location); + QDir pluginDir(pluginPathName); + + if (!pluginDir.exists()) + continue; + + foreach (QString pluginLib, pluginDir.entryList(QDir::Files)) { + QPluginLoader loader(pluginPathName + pluginLib); + + QObject *o = loader.instance(); + if (o != 0 && o->qt_metacast(m_iid) != 0) { + QFactoryInterface* p = qobject_cast(o); + if (p != 0) { + foreach (QString const &key, p->keys()) + m_instances.insertMulti(key, o); + } + + continue; + } else { + qWarning() << "QMediaPluginLoader: Failed to load plugin: " << pluginLib << loader.errorString(); + } + delete o; + loader.unload(); + } + } + } +} + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediapluginloader_p.h b/src/multimedia/base/qmediapluginloader_p.h new file mode 100644 index 0000000..351d2f1 --- /dev/null +++ b/src/multimedia/base/qmediapluginloader_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLUGINLOADER_H +#define QMEDIAPLUGINLOADER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaServiceProviderPlugin; + +class Q_AUTOTEST_EXPORT QMediaPluginLoader +{ +public: + QMediaPluginLoader(const char *iid, + const QString &suffix = QString(), + Qt::CaseSensitivity = Qt::CaseSensitive); + + QStringList keys() const; + QObject* instance(QString const &key); + QList instances(QString const &key); + + static void setStaticPlugins(const QString &location, const QObjectList& objects); + +private: + void load(); + + QByteArray m_iid; + QString m_location; + QMap m_instances; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLUGINLOADER_H diff --git a/src/multimedia/base/qmediaresource.cpp b/src/multimedia/base/qmediaresource.cpp new file mode 100644 index 0000000..ab18ce7 --- /dev/null +++ b/src/multimedia/base/qmediaresource.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + +/*! + \class QMediaResource + \preliminary + \brief The QMediaResource class provides a description of a media resource. + \ingroup multimedia + + A media resource is composed of a \l {url()}{URL} containing the + location of the resource and a set of properties that describe the + format of the resource. The properties provide a means to assess a + resource without first attempting to load it, and in situations where + media be represented by multiple alternative representations provide a + means to select the appropriate resource. + + Media made available by a remote services can often be available in + multiple encodings or quality levels, this allows a client to select + an appropriate resource based on considerations such as codecs supported, + network bandwidth, and display constraints. QMediaResource includes + information such as the \l {mimeType()}{MIME type}, \l {audioCodec()}{audio} + and \l {videoCodec()}{video} codecs, \l {audioBitRate()}{audio} and + \l {videoBitRate()}{video} bit rates, and \l {resolution()}{resolution} + so these constraints and others can be evaluated. + + The only mandatory property of a QMediaResource is the url(). + + \sa QMediaContent +*/ + +/*! + \typedef QMediaResourceList + + Synonym for \c QList +*/ + +/*! + Constructs a null media resource. +*/ +QMediaResource::QMediaResource() +{ +} + +/*! + Constructs a media resource with the given \a mimeType from a \a url. +*/ +QMediaResource::QMediaResource(const QUrl &url, const QString &mimeType) +{ + values.insert(Url, qVariantFromValue(url)); + values.insert(MimeType, mimeType); +} + +/*! + Constructs a copy of a media resource \a other. +*/ +QMediaResource::QMediaResource(const QMediaResource &other) + : values(other.values) +{ +} + +/*! + Assigns the value of \a other to a media resource. +*/ +QMediaResource &QMediaResource::operator =(const QMediaResource &other) +{ + values = other.values; + + return *this; +} + +/*! + Destroys a media resource. +*/ +QMediaResource::~QMediaResource() +{ +} + + +/*! + Compares a media resource to \a other. + + Returns true if the resources are identical, and false otherwise. +*/ +bool QMediaResource::operator ==(const QMediaResource &other) const +{ + return values == other.values; +} + +/*! + Compares a media resource to \a other. + + Returns true if they are different, and false otherwise. +*/ +bool QMediaResource::operator !=(const QMediaResource &other) const +{ + return values != other.values; +} + +/*! + Identifies if a media resource is null. + + Returns true if the resource is null, and false otherwise. +*/ +bool QMediaResource::isNull() const +{ + return values.isEmpty(); +} + +/*! + Returns the URL of a media resource. +*/ +QUrl QMediaResource::url() const +{ + return qvariant_cast(values.value(Url)); +} + +/*! + Returns the MIME type of a media resource. + + This may be null if the MIME type is unknown. +*/ +QString QMediaResource::mimeType() const +{ + return qvariant_cast(values.value(MimeType)); +} + +/*! + Returns the language of a media resource as an ISO 639-2 code. + + This may be null if the language is unknown. +*/ +QString QMediaResource::language() const +{ + return qvariant_cast(values.value(Language)); +} + +/*! + Sets the \a language of a media resource. +*/ +void QMediaResource::setLanguage(const QString &language) +{ + if (!language.isNull()) + values.insert(Language, language); + else + values.remove(Language); +} + +/*! + Returns the audio codec of a media resource. + + This may be null if the media resource does not contain an audio stream, or the codec is + unknown. +*/ +QString QMediaResource::audioCodec() const +{ + return qvariant_cast(values.value(AudioCodec)); +} + +/*! + Sets the audio \a codec of a media resource. +*/ +void QMediaResource::setAudioCodec(const QString &codec) +{ + if (!codec.isNull()) + values.insert(AudioCodec, codec); + else + values.remove(AudioCodec); +} + +/*! + Returns the video codec of a media resource. + + This may be null if the media resource does not contain a video stream, or the codec is + unknonwn. +*/ +QString QMediaResource::videoCodec() const +{ + return qvariant_cast(values.value(VideoCodec)); +} + +/*! + Sets the video \a codec of media resource. +*/ +void QMediaResource::setVideoCodec(const QString &codec) +{ + if (!codec.isNull()) + values.insert(VideoCodec, codec); + else + values.remove(VideoCodec); +} + +/*! + Returns the size in bytes of a media resource. + + This may be zero if the size is unknown. +*/ +qint64 QMediaResource::dataSize() const +{ + return qvariant_cast(values.value(DataSize)); +} + +/*! + Sets the \a size in bytes of a media resource. +*/ +void QMediaResource::setDataSize(const qint64 size) +{ + if (size != 0) + values.insert(DataSize, size); + else + values.remove(DataSize); +} + +/*! + Returns the bit rate in bits per second of a media resource's audio stream. + + This may be zero if the bit rate is unknown, or the resource contains no audio stream. +*/ +int QMediaResource::audioBitRate() const +{ + return values.value(AudioBitRate).toInt(); +} + +/*! + Sets the bit \a rate in bits per second of a media resource's video stream. +*/ +void QMediaResource::setAudioBitRate(int rate) +{ + if (rate != 0) + values.insert(AudioBitRate, rate); + else + values.remove(AudioBitRate); +} + +/*! + Returns the audio sample rate of a media resource. + + This may be zero if the sample size is unknown, or the resource contains no audio stream. +*/ +int QMediaResource::sampleRate() const +{ + return qvariant_cast(values.value(SampleRate)); +} + +/*! + Sets the audio \a sampleRate of a media resource. +*/ +void QMediaResource::setSampleRate(int sampleRate) +{ + if (sampleRate != 0) + values.insert(SampleRate, sampleRate); + else + values.remove(SampleRate); +} + +/*! + Returns the number of audio channels in a media resource. + + This may be zero if the sample size is unknown, or the resource contains no audio stream. +*/ +int QMediaResource::channelCount() const +{ + return qvariant_cast(values.value(ChannelCount)); +} + +/*! + Sets the number of audio \a channels in a media resource. +*/ +void QMediaResource::setChannelCount(int channels) +{ + if (channels != 0) + values.insert(ChannelCount, channels); + else + values.remove(ChannelCount); +} + +/*! + Returns the bit rate in bits per second of a media resource's video stream. + + This may be zero if the bit rate is unknown, or the resource contains no video stream. +*/ +int QMediaResource::videoBitRate() const +{ + return values.value(VideoBitRate).toInt(); +} + +/*! + Sets the bit \a rate in bits per second of a media resource's video stream. +*/ +void QMediaResource::setVideoBitRate(int rate) +{ + if (rate != 0) + values.insert(VideoBitRate, rate); + else + values.remove(VideoBitRate); +} + +/*! + Returns the resolution in pixels of a media resource. + + This may be null is the resolution is unknown, or the resource contains no pixel data (i.e. the + resource is an audio stream. +*/ +QSize QMediaResource::resolution() const +{ + return qvariant_cast(values.value(Resolution)); +} + +/*! + Sets the \a resolution in pixels of a media resource. +*/ +void QMediaResource::setResolution(const QSize &resolution) +{ + if (resolution.width() != -1 || resolution.height() != -1) + values.insert(Resolution, resolution); + else + values.remove(Resolution); +} + +/*! + Sets the \a width and \a height in pixels of a media resource. +*/ +void QMediaResource::setResolution(int width, int height) +{ + if (width != -1 || height != -1) + values.insert(Resolution, QSize(width, height)); + else + values.remove(Resolution); +} + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediaresource.h b/src/multimedia/base/qmediaresource.h new file mode 100644 index 0000000..33b5a79 --- /dev/null +++ b/src/multimedia/base/qmediaresource.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIARESOURCE_H +#define QMEDIARESOURCE_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class Q_MULTIMEDIA_EXPORT QMediaResource +{ +public: + QMediaResource(); + QMediaResource(const QUrl &url, const QString &mimeType = QString()); + QMediaResource(const QMediaResource &other); + QMediaResource &operator =(const QMediaResource &other); + ~QMediaResource(); + + bool isNull() const; + + bool operator ==(const QMediaResource &other) const; + bool operator !=(const QMediaResource &other) const; + + QUrl url() const; + QString mimeType() const; + + QString language() const; + void setLanguage(const QString &language); + + QString audioCodec() const; + void setAudioCodec(const QString &codec); + + QString videoCodec() const; + void setVideoCodec(const QString &codec); + + qint64 dataSize() const; + void setDataSize(const qint64 size); + + int audioBitRate() const; + void setAudioBitRate(int rate); + + int sampleRate() const; + void setSampleRate(int frequency); + + int channelCount() const; + void setChannelCount(int channels); + + int videoBitRate() const; + void setVideoBitRate(int rate); + + QSize resolution() const; + void setResolution(const QSize &resolution); + void setResolution(int width, int height); + + +private: + enum Property + { + Url, + MimeType, + Language, + AudioCodec, + VideoCodec, + DataSize, + AudioBitRate, + VideoBitRate, + SampleRate, + ChannelCount, + Resolution, + }; + QMap values; +}; + +typedef QList QMediaResourceList; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaResource)) +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaResourceList)) + +QT_END_HEADER + + +#endif diff --git a/src/multimedia/base/qmediaservice.cpp b/src/multimedia/base/qmediaservice.cpp new file mode 100644 index 0000000..e40688e --- /dev/null +++ b/src/multimedia/base/qmediaservice.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include "qmediaservice_p.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +/*! + \class QMediaService + \brief The QMediaService class provides a common base class for media + service implementations. + \ingroup multimedia-serv + \preliminary + + Media services provide implementations of the functionality promised + by media objects, and allow multiple providers to implement a QMediaObject. + + To provide the functionality of a QMediaObject media services implement + QMediaControl interfaces. Services typically implement one core media + control which provides the core feature of a media object, and some + number of additional controls which provide either optional features of + the media object, or features of a secondary media object or peripheral + object. + + A pointer to media service's QMediaControl implementation can be + obtained by passing the control's interface name to the control() function. + + \code + QMediaPlayerControl *control = qobject_cast( + service->control("com.nokia.Qt.QMediaPlayerControl/1.0")); + \endcode + + Media objects can use services loaded dynamically from plug-ins or + implemented statically within an applications. Plug-in based services + should also implement the QMediaServiceProviderPlugin interface. Static + services should implement the QMediaServiceProvider interface. + + \sa QMediaObject, QMediaControl, QMediaServiceProvider, QMediaServiceProviderPlugin +*/ + +/*! + Construct a media service with the given \a parent. This class is meant as a + base class for Multimedia services so this constructor is protected. +*/ + +QMediaService::QMediaService(QObject *parent) + : QObject(parent) + , d_ptr(new QMediaServicePrivate) +{ + d_ptr->q_ptr = this; +} + +/*! + \internal +*/ +QMediaService::QMediaService(QMediaServicePrivate &dd, QObject *parent) + : QObject(parent) + , d_ptr(&dd) +{ + d_ptr->q_ptr = this; +} + +/*! + Destroys a media service. +*/ + +QMediaService::~QMediaService() +{ + delete d_ptr; +} + +/*! + \fn QMediaService::control(const char *interface) const + + Returns a pointer to the media control implementing \a interface. + + If the service does not implement the control a null pointer is returned instead. +*/ + +/*! + \fn QMediaService::control() const + + Returns a pointer to the media control of type T implemented by a media service. + + If the service does not implment the control a null pointer is returned instead. +*/ + +#include "moc_qmediaservice.cpp" + +QT_END_NAMESPACE + +QT_END_HEADER + diff --git a/src/multimedia/base/qmediaservice.h b/src/multimedia/base/qmediaservice.h new file mode 100644 index 0000000..c53a15f --- /dev/null +++ b/src/multimedia/base/qmediaservice.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTMEDIASERVICE_H +#define QABSTRACTMEDIASERVICE_H + +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaServicePrivate; +class Q_MULTIMEDIA_EXPORT QMediaService : public QObject +{ + Q_OBJECT + +public: + ~QMediaService(); + + virtual QMediaControl* control(const char *name) const = 0; + +#ifndef QT_NO_MEMBER_TEMPLATES + template inline T control() const { + if (QObject *object = control(qmediacontrol_iid())) { + return qobject_cast(object); + } + return 0; + } +#endif + +protected: + QMediaService(QObject* parent); + QMediaService(QMediaServicePrivate &dd, QObject *parent); + + QMediaServicePrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QMediaService) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QABSTRACTMEDIASERVICE_H + diff --git a/src/multimedia/base/qmediaservice_p.h b/src/multimedia/base/qmediaservice_p.h new file mode 100644 index 0000000..5993a7e --- /dev/null +++ b/src/multimedia/base/qmediaservice_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTMEDIASERVICE_P_H +#define QABSTRACTMEDIASERVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QAudioDeviceControl; + +class QMediaServicePrivate +{ +public: + QMediaServicePrivate(): q_ptr(0) {} + + QMediaService *q_ptr; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp new file mode 100644 index 0000000..37115e7 --- /dev/null +++ b/src/multimedia/base/qmediaserviceprovider.cpp @@ -0,0 +1,678 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include +#include "qmediapluginloader_p.h" +#include + + + +class QMediaServiceProviderHintPrivate : public QSharedData +{ +public: + QMediaServiceProviderHintPrivate(QMediaServiceProviderHint::Type type) + :type(type), features(0) + { + } + + QMediaServiceProviderHintPrivate(const QMediaServiceProviderHintPrivate &other) + :QSharedData(other), + type(other.type), + device(other.device), + mimeType(other.mimeType), + codecs(other.codecs), + features(other.features) + { + } + + ~QMediaServiceProviderHintPrivate() + { + } + + QMediaServiceProviderHint::Type type; + QByteArray device; + QString mimeType; + QStringList codecs; + QMediaServiceProviderHint::Features features; +}; + +/*! + \class QMediaServiceProviderHint + \preliminary + \brief The QMediaServiceProviderHint class describes what is required of a QMediaService. + + \ingroup multimedia-serv + + The QMediaServiceProvider class uses hints to select an appropriate media service. +*/ + +/*! + \enum QMediaServiceProviderHint::Feature + + Enumerates features a media service may provide. + + \value LowLatencyPlayback + The service is expected to play simple audio formats, + but playback should start without significant delay. + Such playback service can be used for beeps, ringtones, etc. + + \value RecordingSupport + The service provides audio or video recording functions. +*/ + +/*! + \enum QMediaServiceProviderHint::Type + + Enumerates the possible types of media service provider hint. + + \value Null En empty hint, use the default service. + \value ContentType Select media service most suitable for certain content type. + \value Device Select media service which supports certain device. + \value SupportedFeatures Select media service supporting the set of optional features. +*/ + + +/*! + Constructs an empty media service provider hint. +*/ +QMediaServiceProviderHint::QMediaServiceProviderHint() + :d(new QMediaServiceProviderHintPrivate(Null)) +{ +} + +/*! + Constructs a ContentType media service provider hint. + + This type of hint describes a service that is able to play content of a specific MIME \a type + encoded with one or more of the listed \a codecs. +*/ +QMediaServiceProviderHint::QMediaServiceProviderHint(const QString &type, const QStringList& codecs) + :d(new QMediaServiceProviderHintPrivate(ContentType)) +{ + d->mimeType = type; + d->codecs = codecs; +} + +/*! + Constructs a Device media service provider hint. + + This type of hint describes a media service that utilizes a specific \a device. +*/ +QMediaServiceProviderHint::QMediaServiceProviderHint(const QByteArray &device) + :d(new QMediaServiceProviderHintPrivate(Device)) +{ + d->device = device; +} + +/*! + Constructs a SupportedFeatures media service provider hint. + + This type of hint describes a service which supports a specific set of \a features. +*/ +QMediaServiceProviderHint::QMediaServiceProviderHint(QMediaServiceProviderHint::Features features) + :d(new QMediaServiceProviderHintPrivate(SupportedFeatures)) +{ + d->features = features; +} + +/*! + Constructs a copy of the media service provider hint \a other. +*/ +QMediaServiceProviderHint::QMediaServiceProviderHint(const QMediaServiceProviderHint &other) + :d(other.d) +{ +} + +/*! + Destroys a media service provider hint. +*/ +QMediaServiceProviderHint::~QMediaServiceProviderHint() +{ +} + +/*! + Assigns the value \a other to a media service provider hint. +*/ +QMediaServiceProviderHint& QMediaServiceProviderHint::operator=(const QMediaServiceProviderHint &other) +{ + d = other.d; + return *this; +} + +/*! + Identifies if \a other is of equal value to a media service provider hint. + + Returns true if the hints are equal, and false if they are not. +*/ +bool QMediaServiceProviderHint::operator == (const QMediaServiceProviderHint &other) const +{ + return (d == other.d) || + (d->type == other.d->type && + d->device == other.d->device && + d->mimeType == other.d->mimeType && + d->codecs == other.d->codecs && + d->features == other.d->features); +} + +/*! + Identifies if \a other is not of equal value to a media service provider hint. + + Returns true if the hints are not equal, and false if they are. +*/ +bool QMediaServiceProviderHint::operator != (const QMediaServiceProviderHint &other) const +{ + return !(*this == other); +} + +/*! + Returns true if a media service provider is null. +*/ +bool QMediaServiceProviderHint::isNull() const +{ + return d->type == Null; +} + +/*! + Returns the type of a media service provider hint. +*/ +QMediaServiceProviderHint::Type QMediaServiceProviderHint::type() const +{ + return d->type; +} + +/*! + Returns the mime type of the media a service is expected to be able play. +*/ +QString QMediaServiceProviderHint::mimeType() const +{ + return d->mimeType; +} + +/*! + Returns a list of codes a media service is expected to be able to decode. +*/ +QStringList QMediaServiceProviderHint::codecs() const +{ + return d->codecs; +} + +/*! + Returns the name of a device a media service is expected to utilize. +*/ +QByteArray QMediaServiceProviderHint::device() const +{ + return d->device; +} + +/*! + Returns a set of features a media service is expected to provide. +*/ +QMediaServiceProviderHint::Features QMediaServiceProviderHint::features() const +{ + return d->features; +} + + +Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, loader, + (QMediaServiceProviderFactoryInterface_iid, QLatin1String("/mediaservices"), Qt::CaseInsensitive)) + + +class QPluginServiceProvider : public QMediaServiceProvider +{ + QMap pluginMap; + +public: + QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) + { + QString key(type); + + QListplugins; + foreach (QObject *obj, loader()->instances(key)) { + QMediaServiceProviderPlugin *plugin = + qobject_cast(obj); + if (plugin) + plugins << plugin; + } + + if (!plugins.isEmpty()) { + QMediaServiceProviderPlugin *plugin = 0; + + switch (hint.type()) { + case QMediaServiceProviderHint::Null: + plugin = plugins[0]; + //special case for media player, if low latency was not asked, + //prefer services not offering it, since they are likely to support + //more formats + if (type == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) { + foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) { + QMediaServiceFeaturesInterface *iface = + qobject_cast(currentPlugin); + + if (!iface || !(iface->supportedFeatures(type) & + QMediaServiceProviderHint::LowLatencyPlayback)) { + plugin = currentPlugin; + break; + } + + } + } + break; + case QMediaServiceProviderHint::SupportedFeatures: + plugin = plugins[0]; + foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) { + QMediaServiceFeaturesInterface *iface = + qobject_cast(currentPlugin); + + if (iface) { + if ((iface->supportedFeatures(type) & hint.features()) == hint.features()) { + plugin = currentPlugin; + break; + } + } + } + break; + case QMediaServiceProviderHint::Device: { + foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) { + QMediaServiceSupportedDevicesInterface *iface = + qobject_cast(currentPlugin); + + if (!iface) { + // the plugin may support the device, + // but this choice still can be overridden + plugin = currentPlugin; + } else { + if (iface->devices(type).contains(hint.device())) { + plugin = currentPlugin; + break; + } + } + } + } + break; + case QMediaServiceProviderHint::ContentType: { + QtMedia::SupportEstimate estimate = QtMedia::NotSupported; + foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) { + QtMedia::SupportEstimate currentEstimate = QtMedia::MaybeSupported; + QMediaServiceSupportedFormatsInterface *iface = + qobject_cast(currentPlugin); + + if (iface) + currentEstimate = iface->hasSupport(hint.mimeType(), hint.codecs()); + + if (currentEstimate > estimate) { + estimate = currentEstimate; + plugin = currentPlugin; + + if (currentEstimate == QtMedia::PreferedService) + break; + } + } + } + break; + } + + if (plugin != 0) { + QMediaService *service = plugin->create(key); + if (service != 0) + pluginMap.insert(service, plugin); + + return service; + } + } + + qWarning() << "defaultServiceProvider::requestService(): no service found for -" << key; + return 0; + } + + void releaseService(QMediaService *service) + { + if (service != 0) { + QMediaServiceProviderPlugin *plugin = pluginMap.take(service); + + if (plugin != 0) + plugin->release(service); + } + } + + QtMedia::SupportEstimate hasSupport(const QByteArray &serviceType, + const QString &mimeType, + const QStringList& codecs, + int flags) const + { + QList instances = loader()->instances(serviceType); + + if (instances.isEmpty()) + return QtMedia::NotSupported; + + bool allServicesProvideInterface = true; + QtMedia::SupportEstimate supportEstimate = QtMedia::NotSupported; + + foreach(QObject *obj, instances) { + QMediaServiceSupportedFormatsInterface *iface = + qobject_cast(obj); + + //if low latency playback was asked, skip services known + //not to provide low latency playback + if (flags & QMediaPlayer::LowLatency) { + QMediaServiceFeaturesInterface *iface = + qobject_cast(obj); + + if (iface && !(iface->supportedFeatures(serviceType) & QMediaServiceProviderHint::LowLatencyPlayback)) + continue; + } + + if (iface) + supportEstimate = qMax(supportEstimate, iface->hasSupport(mimeType, codecs)); + else + allServicesProvideInterface = false; + } + + //don't return PreferedService + supportEstimate = qMin(supportEstimate, QtMedia::ProbablySupported); + + //Return NotSupported only if no services are available of serviceType + //or all the services returned NotSupported, otherwise return at least MaybeSupported + if (!allServicesProvideInterface) + supportEstimate = qMax(QtMedia::MaybeSupported, supportEstimate); + + return supportEstimate; + } + + QStringList supportedMimeTypes(const QByteArray &serviceType, int flags) const + { + QList instances = loader()->instances(serviceType); + + QStringList supportedTypes; + + foreach(QObject *obj, instances) { + QMediaServiceSupportedFormatsInterface *iface = + qobject_cast(obj); + + // If low latency playback was asked for, skip MIME types from services known + // not to provide low latency playback + if (flags & QMediaPlayer::LowLatency) { + QMediaServiceFeaturesInterface *iface = + qobject_cast(obj); + + if (iface && !(iface->supportedFeatures(serviceType) & QMediaServiceProviderHint::LowLatencyPlayback)) + continue; + } + + if (iface) { + supportedTypes << iface->supportedMimeTypes(); + } + } + + // Multiple services may support the same MIME type + supportedTypes.removeDuplicates(); + + return supportedTypes; + } + + QList devices(const QByteArray &serviceType) const + { + QList res; + + foreach(QObject *obj, loader()->instances(serviceType)) { + QMediaServiceSupportedDevicesInterface *iface = + qobject_cast(obj); + + if (iface) { + res.append(iface->devices(serviceType)); + } + } + + return res; + } + + QString deviceDescription(const QByteArray &serviceType, const QByteArray &device) + { + foreach(QObject *obj, loader()->instances(serviceType)) { + QMediaServiceSupportedDevicesInterface *iface = + qobject_cast(obj); + + if (iface) { + if (iface->devices(serviceType).contains(device)) + return iface->deviceDescription(serviceType, device); + } + } + + return QString(); + } +}; + +Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider); + +/*! + \class QMediaServiceProvider + \preliminary + \brief The QMediaServiceProvider class provides an abstract allocator for media services. +*/ + +/*! + \fn QMediaServiceProvider::requestService(const QByteArray &type, const QMediaServiceProviderHint &hint) + + Requests an instance of a \a type service which best matches the given \a hint. + + Returns a pointer to the requested service, or a null pointer if there is no suitable service. + + The returned service must be released with releaseService when it is finished with. +*/ + +/*! + \fn QMediaServiceProvider::releaseService(QMediaService *service) + + Releases a media \a service requested with requestService(). +*/ + +/*! + \fn QtMedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags) const + + Returns how confident a media service provider is that is can provide a \a serviceType + service that is able to play media of a specific \a mimeType that is encoded using the listed + \a codecs while adhearing to constraints identified in \a flags. +*/ +QtMedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, + const QString &mimeType, + const QStringList& codecs, + int flags) const +{ + Q_UNUSED(serviceType); + Q_UNUSED(mimeType); + Q_UNUSED(codecs); + Q_UNUSED(flags); + + return QtMedia::MaybeSupported; +} + +/*! + \fn QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const + + Returns a list of MIME types supported by the service provider for the specified \a serviceType. + + The resultant list is restricted to MIME types which can be supported given the constraints in \a flags. +*/ +QStringList QMediaServiceProvider::supportedMimeTypes(const QByteArray &serviceType, int flags) const +{ + Q_UNUSED(serviceType); + Q_UNUSED(flags); + + return QStringList(); +} + +/*! + Returns the list of devices related to \a service type. +*/ +QList QMediaServiceProvider::devices(const QByteArray &service) const +{ + Q_UNUSED(service); + return QList(); +} + +/*! + Returns the description of \a device related to \a serviceType, + suitable to be displayed to user. +*/ +QString QMediaServiceProvider::deviceDescription(const QByteArray &serviceType, const QByteArray &device) +{ + Q_UNUSED(serviceType); + Q_UNUSED(device); + return QString(); +} + +/*! + Returns a default provider of media services. +*/ +QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider() +{ + return pluginProvider(); +} + +/*! + \class QMediaServiceProviderPlugin + \preliminary + \brief The QMediaServiceProviderPlugin class interface provides an interface for QMediaService + plug-ins. + + A media service provider plug-in may implement one or more of + QMediaServiceSupportedFormatsInterface, QMediaServiceSupportedDevicesInterface, + and QMediaServiceFeaturesInterface to identify the features it supports. +*/ + +/*! + \fn QMediaServiceProviderPlugin::keys() const + + Returns a list of keys for media services a plug-in can create. +*/ + +/*! + \fn QMediaServiceProviderPlugin::create(const QString &key) + + Constructs a new instance of the QMediaService identified by \a key. + + The QMediaService returned must be destroyed with release(). +*/ + +/*! + \fn QMediaServiceProviderPlugin::release(QMediaService *service) + + Destroys a media \a service constructed with create(). +*/ + + +/*! + \class QMediaServiceSupportedFormatsInterface + \brief The QMediaServiceSupportedFormatsInterface class interface + identifies if a media service plug-in supports a media format. + + A QMediaServiceProviderPlugin may implement this interface. +*/ + +/*! + \fn QMediaServiceSupportedFormatsInterface::~QMediaServiceSupportedFormatsInterface() + + Destroys a media service supported formats interface. +*/ + +/*! + \fn QMediaServiceSupportedFormatsInterface::hasSupport(const QString &mimeType, const QStringList& codecs) const + + Returns the level of support a media service plug-in has for a \a mimeType and set of \a codecs. +*/ + +/*! + \fn QMediaServiceSupportedFormatsInterface::supportedMimeTypes() const + + Returns a list of MIME types supported by the media service plug-in. +*/ + +/*! + \class QMediaServiceSupportedDevicesInterface + \brief The QMediaServiceSupportedDevicesInterface class interface + identifies the devices supported by a media service plug-in. + + A QMediaServiceProviderPlugin may implement this interface. +*/ + +/*! + \fn QMediaServiceSupportedDevicesInterface::~QMediaServiceSupportedDevicesInterface() + + Destroys a media service supported devices interface. +*/ + +/*! + \fn QMediaServiceSupportedDevicesInterface::devices(const QByteArray &service) const + + Returns a list of devices supported by a plug-in \a service. +*/ + +/*! + \fn QMediaServiceSupportedDevicesInterface::deviceDescription(const QByteArray &service, const QByteArray &device) + + Returns a description of a \a device supported by a plug-in \a service. +*/ + +/*! + \class QMediaServiceFeaturesInterface + \brief The QMediaServiceFeaturesInterface class interface identifies + features supported by a media service plug-in. + + A QMediaServiceProviderPlugin may implement this interface. +*/ + +/*! + \fn QMediaServiceFeaturesInterface::~QMediaServiceFeaturesInterface() + + Destroys a media service features interface. +*/ +/*! + \fn QMediaServiceFeaturesInterface::supportedFeatures(const QByteArray &service) const + + Returns a set of features supported by a plug-in \a service. +*/ + +#include "moc_qmediaserviceprovider.cpp" +#include "moc_qmediaserviceproviderplugin.cpp" diff --git a/src/multimedia/base/qmediaserviceprovider.h b/src/multimedia/base/qmediaserviceprovider.h new file mode 100644 index 0000000..46f63b5 --- /dev/null +++ b/src/multimedia/base/qmediaserviceprovider.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIASERVICEPROVIDER_H +#define QMEDIASERVICEPROVIDER_H + +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QMediaService; + +class QMediaServiceProviderHintPrivate; +class Q_MULTIMEDIA_EXPORT QMediaServiceProviderHint +{ +public: + enum Type { Null, ContentType, Device, SupportedFeatures }; + + enum Feature { + LowLatencyPlayback = 0x01, + RecordingSupport = 0x02 + }; + Q_DECLARE_FLAGS(Features, Feature) + + QMediaServiceProviderHint(); + QMediaServiceProviderHint(const QString &mimeType, const QStringList& codecs); + QMediaServiceProviderHint(const QByteArray &device); + QMediaServiceProviderHint(Features features); + QMediaServiceProviderHint(const QMediaServiceProviderHint &other); + ~QMediaServiceProviderHint(); + + QMediaServiceProviderHint& operator=(const QMediaServiceProviderHint &other); + + bool operator == (const QMediaServiceProviderHint &other) const; + bool operator != (const QMediaServiceProviderHint &other) const; + + bool isNull() const; + + Type type() const; + + QString mimeType() const; + QStringList codecs() const; + + QByteArray device() const; + + Features features() const; + + //to be extended, if necessary + +private: + QSharedDataPointer d; +}; + +class Q_MULTIMEDIA_EXPORT QMediaServiceProvider : public QObject +{ + Q_OBJECT + +public: + virtual QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint = QMediaServiceProviderHint()) = 0; + virtual void releaseService(QMediaService *service) = 0; + + virtual QtMedia::SupportEstimate hasSupport(const QByteArray &serviceType, + const QString &mimeType, + const QStringList& codecs, + int flags = 0) const; + virtual QStringList supportedMimeTypes(const QByteArray &serviceType, int flags = 0) const; + + virtual QList devices(const QByteArray &serviceType) const; + virtual QString deviceDescription(const QByteArray &serviceType, const QByteArray &device); + + static QMediaServiceProvider* defaultServiceProvider(); +}; + +/*! + Service with support for media playback + Required Controls: QMediaPlayerControl + Optional Controls: QMediaPlaylistControl, QAudioDeviceControl + Video Output Controls (used by QWideoWidget and QGraphicsVideoItem): + Required: QVideoOutputControl + Optional: QVideoWindowControl, QVideoRendererControl, QVideoWidgetControl +*/ +#define Q_MEDIASERVICE_MEDIAPLAYER "com.nokia.qt.mediaplayer" + +/*! + Service with support for recording from audio sources + Required Controls: QAudioDeviceControl + Recording Controls (QMediaRecorder): + Required: QMediaRecorderControl + Recommended: QAudioEncoderControl + Optional: QMediaContainerControl +*/ +#define Q_MEDIASERVICE_AUDIOSOURCE "com.nokia.qt.audiosource" + +/*! + Service with support for camera use. + Required Controls: QCameraControl + Optional Controls: QCameraExposureControl, QCameraFocusControl, QImageProcessingControl + Still Capture Controls: QImageCaptureControl + Recording Controls (QMediaRecorder): + Required: QMediaRecorderControl + Recommended: QAudioEncoderControl, QVideoEncoderControl, QMediaContainerControl + Viewfinder Video Output Controls (used by QWideoWidget and QGraphicsVideoItem): + Required: QVideoOutputControl + Optional: QVideoWindowControl, QVideoRendererControl, QVideoWidgetControl +*/ +#define Q_MEDIASERVICE_CAMERA "com.nokia.qt.camera" + +/*! + Service with support for radio tuning. + Required Controls: QRadioTunerControl + Recording Controls (Optional, used by QMediaRecorder): + Required: QMediaRecorderControl + Recommended: QAudioEncoderControl + Optional: QMediaContainerControl +*/ +#define Q_MEDIASERVICE_RADIO "com.nokia.qt.radio" + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIASERVICEPROVIDER_H diff --git a/src/multimedia/base/qmediaserviceproviderplugin.h b/src/multimedia/base/qmediaserviceproviderplugin.h new file mode 100644 index 0000000..0381093 --- /dev/null +++ b/src/multimedia/base/qmediaserviceproviderplugin.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIASERVICEPROVIDERPLUGIN_H +#define QMEDIASERVICEPROVIDERPLUGIN_H + +#include +#include +#include + +#include + +#ifdef Q_MOC_RUN +# pragma Q_MOC_EXPAND_MACROS +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaService; + + +struct Q_MULTIMEDIA_EXPORT QMediaServiceProviderFactoryInterface : public QFactoryInterface +{ + virtual QStringList keys() const = 0; + virtual QMediaService* create(QString const& key) = 0; + virtual void release(QMediaService *service) = 0; +}; + +#define QMediaServiceProviderFactoryInterface_iid \ + "com.nokia.Qt.QMediaServiceProviderFactoryInterface/1.0" +Q_DECLARE_INTERFACE(QMediaServiceProviderFactoryInterface, QMediaServiceProviderFactoryInterface_iid) + + +struct Q_MULTIMEDIA_EXPORT QMediaServiceSupportedFormatsInterface +{ + virtual ~QMediaServiceSupportedFormatsInterface() {} + virtual QtMedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const = 0; + virtual QStringList supportedMimeTypes() const = 0; +}; + +#define QMediaServiceSupportedFormatsInterface_iid \ + "com.nokia.Qt.QMediaServiceSupportedFormatsInterface/1.0" +Q_DECLARE_INTERFACE(QMediaServiceSupportedFormatsInterface, QMediaServiceSupportedFormatsInterface_iid) + + +struct Q_MULTIMEDIA_EXPORT QMediaServiceSupportedDevicesInterface +{ + virtual ~QMediaServiceSupportedDevicesInterface() {} + virtual QList devices(const QByteArray &service) const = 0; + virtual QString deviceDescription(const QByteArray &service, const QByteArray &device) = 0; +}; + +#define QMediaServiceSupportedDevicesInterface_iid \ + "com.nokia.Qt.QMediaServiceSupportedDevicesInterface/1.0" +Q_DECLARE_INTERFACE(QMediaServiceSupportedDevicesInterface, QMediaServiceSupportedDevicesInterface_iid) + + +struct Q_MULTIMEDIA_EXPORT QMediaServiceFeaturesInterface +{ + virtual ~QMediaServiceFeaturesInterface() {} + virtual QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const = 0; +}; + +#define QMediaServiceFeaturesInterface_iid \ + "com.nokia.Qt.QMediaServiceFeaturesInterface/1.0" +Q_DECLARE_INTERFACE(QMediaServiceFeaturesInterface, QMediaServiceFeaturesInterface_iid) + +class Q_MULTIMEDIA_EXPORT QMediaServiceProviderPlugin : public QObject, public QMediaServiceProviderFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceProviderFactoryInterface:QFactoryInterface) + +public: + virtual QStringList keys() const = 0; + virtual QMediaService* create(const QString& key) = 0; + virtual void release(QMediaService *service) = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIASERVICEPROVIDERPLUGIN_H diff --git a/src/multimedia/base/qmediatimerange.cpp b/src/multimedia/base/qmediatimerange.cpp new file mode 100644 index 0000000..38a8aea --- /dev/null +++ b/src/multimedia/base/qmediatimerange.cpp @@ -0,0 +1,706 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + + +QT_BEGIN_NAMESPACE + +/*! + \class QMediaTimeInterval + \brief The QMediaTimeInterval class represents a time interval with integer precision. + \ingroup multimedia + + An interval is specified by an inclusive start() and end() time. + These must be set in the constructor, as this is an immutable class. + The specific units of time represented by the class have not been defined - + it is suitable for any times which can be represented by a signed 64 bit integer. + + The isNormal() method determines if a time interval is normal + (a normal time interval has start() <= end()). An abnormal interval can be converted + in to a normal interval by calling the normalized() method. + + The contains() method determines if a specified time lies within + the time interval. + + The translated() method returns a time interval which has been translated + forwards or backwards through time by a specified offset. + + \sa QMediaTimeRange +*/ + +/*! + \fn QMediaTimeInterval::QMediaTimeInterval() + + Constructs an empty interval. +*/ +QMediaTimeInterval::QMediaTimeInterval() + : s(0) + , e(0) +{ + +} + +/*! + \fn QMediaTimeInterval::QMediaTimeInterval(qint64 start, qint64 end) + + Constructs an interval with the specified \a start and \a end times. +*/ +QMediaTimeInterval::QMediaTimeInterval(qint64 start, qint64 end) + : s(start) + , e(end) +{ + +} + +/*! + \fn QMediaTimeInterval::QMediaTimeInterval(const QMediaTimeInterval &other) + + Constructs an interval by taking a copy of \a other. +*/ +QMediaTimeInterval::QMediaTimeInterval(const QMediaTimeInterval &other) + : s(other.s) + , e(other.e) +{ + +} + +/*! + \fn QMediaTimeInterval::start() const + + Returns the start time of the interval. + + \sa end() +*/ +qint64 QMediaTimeInterval::start() const +{ + return s; +} + +/*! + \fn QMediaTimeInterval::end() const + + Returns the end time of the interval. + + \sa start() +*/ +qint64 QMediaTimeInterval::end() const +{ + return e; +} + +/*! + \fn QMediaTimeInterval::contains(qint64 time) const + + Returns true if the time interval contains the specified \a time. + That is, start() <= time <= end(). +*/ +bool QMediaTimeInterval::contains(qint64 time) const +{ + return isNormal() ? (s <= time && time <= e) + : (e <= time && time <= s); +} + +/*! + \fn QMediaTimeInterval::isNormal() const + + Returns true if this time interval is normal. + A normal time interval has start() <= end(). + + \sa normalized() +*/ +bool QMediaTimeInterval::isNormal() const +{ + return s <= e; +} + +/*! + \fn QMediaTimeInterval::normalized() const + + Returns a normalized version of this interval. + + If the start() time of the interval is greater than the end() time, + then the returned interval has the start and end times swapped. +*/ +QMediaTimeInterval QMediaTimeInterval::normalized() const +{ + if(s > e) + return QMediaTimeInterval(e, s); + + return *this; +} + +/*! + \fn QMediaTimeInterval::translated(qint64 offset) const + + Returns a copy of this time interval, translated by a value of \a offset. + An interval can be moved forward through time with a positive offset, or backward + through time with a negative offset. +*/ +QMediaTimeInterval QMediaTimeInterval::translated(qint64 offset) const +{ + return QMediaTimeInterval(s + offset, e + offset); +} + +/*! + \fn operator==(const QMediaTimeInterval &a, const QMediaTimeInterval &b) + \relates QMediaTimeRange + + Returns true if \a a is exactly equal to \a b. +*/ +bool operator==(const QMediaTimeInterval &a, const QMediaTimeInterval &b) +{ + return a.start() == b.start() && a.end() == b.end(); +} + +/*! + \fn operator!=(const QMediaTimeInterval &a, const QMediaTimeInterval &b) + \relates QMediaTimeRange + + Returns true if \a a is not exactly equal to \a b. +*/ +bool operator!=(const QMediaTimeInterval &a, const QMediaTimeInterval &b) +{ + return a.start() != b.start() || a.end() != b.end(); +} + +class QMediaTimeRangePrivate : public QSharedData +{ +public: + + QMediaTimeRangePrivate(); + QMediaTimeRangePrivate(const QMediaTimeRangePrivate &other); + QMediaTimeRangePrivate(const QMediaTimeInterval &interval); + + QList intervals; + + void addInterval(const QMediaTimeInterval &interval); + void removeInterval(const QMediaTimeInterval &interval); +}; + +QMediaTimeRangePrivate::QMediaTimeRangePrivate() + : QSharedData() +{ + +} + +QMediaTimeRangePrivate::QMediaTimeRangePrivate(const QMediaTimeRangePrivate &other) + : QSharedData() + , intervals(other.intervals) +{ + +} + +QMediaTimeRangePrivate::QMediaTimeRangePrivate(const QMediaTimeInterval &interval) + : QSharedData() +{ + if(interval.isNormal()) + intervals << interval; +} + +void QMediaTimeRangePrivate::addInterval(const QMediaTimeInterval &interval) +{ + // Handle normalized intervals only + if(!interval.isNormal()) + return; + + // Find a place to insert the interval + int i; + for (i = 0; i < intervals.count(); i++) { + // Insert before this element + if(interval.s < intervals[i].s) { + intervals.insert(i, interval); + break; + } + } + + // Interval needs to be added to the end of the list + if (i == intervals.count()) + intervals.append(interval); + + // Do we need to correct the element before us? + if(i > 0 && intervals[i - 1].e >= interval.s - 1) + i--; + + // Merge trailing ranges + while (i < intervals.count() - 1 + && intervals[i].e >= intervals[i + 1].s - 1) { + intervals[i].e = qMax(intervals[i].e, intervals[i + 1].e); + intervals.removeAt(i + 1); + } +} + +void QMediaTimeRangePrivate::removeInterval(const QMediaTimeInterval &interval) +{ + // Handle normalized intervals only + if(!interval.isNormal()) + return; + + for (int i = 0; i < intervals.count(); i++) { + QMediaTimeInterval r = intervals[i]; + + if (r.e < interval.s) { + // Before the removal interval + continue; + } else if (interval.e < r.s) { + // After the removal interval - stop here + break; + } else if (r.s < interval.s && interval.e < r.e) { + // Split case - a single range has a chunk removed + intervals[i].e = interval.s -1; + addInterval(QMediaTimeInterval(interval.e + 1, r.e)); + break; + } else if (r.s < interval.s) { + // Trimming Tail Case + intervals[i].e = interval.s - 1; + } else if (interval.e < r.e) { + // Trimming Head Case - we can stop after this + intervals[i].s = interval.e + 1; + break; + } else { + // Complete coverage case + intervals.removeAt(i); + --i; + } + } +} + +/*! + \class QMediaTimeRange + \brief The QMediaTimeRange class represents a set of zero or more disjoint + time intervals. + \ingroup multimedia + + \reentrant + + The earliestTime(), latestTime(), intervals() and isEmpty() + methods are used to get information about the current time range. + + The addInterval(), removeInterval() and clear() methods are used to modify + the current time range. + + When adding or removing intervals from the time range, existing intervals + within the range may be expanded, trimmed, deleted, merged or split to ensure + that all intervals within the time range remain distinct and disjoint. As a + consequence, all intervals added or removed from a time range must be + \l{QMediaTimeInterval::isNormal()}{normal}. + + \sa QMediaTimeInterval +*/ + +/*! + \fn QMediaTimeRange::QMediaTimeRange() + + Constructs an empty time range. +*/ +QMediaTimeRange::QMediaTimeRange() + : d(new QMediaTimeRangePrivate) +{ + +} + +/*! + \fn QMediaTimeRange::QMediaTimeRange(qint64 start, qint64 end) + + Constructs a time range that contains an initial interval from + \a start to \a end inclusive. + + If the interval is not \l{QMediaTimeInterval::isNormal()}{normal}, + the resulting time range will be empty. + + \sa addInterval() +*/ +QMediaTimeRange::QMediaTimeRange(qint64 start, qint64 end) + : d(new QMediaTimeRangePrivate(QMediaTimeInterval(start, end))) +{ + +} + +/*! + \fn QMediaTimeRange::QMediaTimeRange(const QMediaTimeInterval &interval) + + Constructs a time range that contains an intitial interval, \a interval. + + If \a interval is not \l{QMediaTimeInterval::isNormal()}{normal}, + the resulting time range will be empty. + + \sa addInterval() +*/ +QMediaTimeRange::QMediaTimeRange(const QMediaTimeInterval &interval) + : d(new QMediaTimeRangePrivate(interval)) +{ + +} + +/*! + \fn QMediaTimeRange::QMediaTimeRange(const QMediaTimeRange &range) + + Constructs a time range by copying another time \a range. +*/ +QMediaTimeRange::QMediaTimeRange(const QMediaTimeRange &range) + : d(range.d) +{ + +} + +/*! + \fn QMediaTimeRange::~QMediaTimeRange() + + Destructor. +*/ +QMediaTimeRange::~QMediaTimeRange() +{ + +} + +/*! + \fn QMediaTimeRange::operator=(const QMediaTimeRange &other) + + Takes a copy of the \a other time range and returns itself. +*/ +QMediaTimeRange &QMediaTimeRange::operator=(const QMediaTimeRange &other) +{ + d = other.d; + return *this; +} + +/*! + \fn QMediaTimeRange::operator=(const QMediaTimeInterval &interval) + + Sets the time range to a single continuous interval, \a interval. +*/ +QMediaTimeRange &QMediaTimeRange::operator=(const QMediaTimeInterval &interval) +{ + d = new QMediaTimeRangePrivate(interval); + return *this; +} + +/*! + \fn QMediaTimeRange::earliestTime() const + + Returns the earliest time within the time range. + + For empty time ranges, this value is equal to zero. + + \sa latestTime() +*/ +qint64 QMediaTimeRange::earliestTime() const +{ + if (!d->intervals.isEmpty()) + return d->intervals[0].s; + + return 0; +} + +/*! + \fn QMediaTimeRange::latestTime() const + + Returns the latest time within the time range. + + For empty time ranges, this value is equal to zero. + + \sa earliestTime() +*/ +qint64 QMediaTimeRange::latestTime() const +{ + if (!d->intervals.isEmpty()) + return d->intervals[d->intervals.count() - 1].e; + + return 0; +} + +/*! + \fn QMediaTimeRange::addInterval(qint64 start, qint64 end) + \overload + + Adds the interval specified by \a start and \a end + to the time range. + + \sa addInterval() +*/ +void QMediaTimeRange::addInterval(qint64 start, qint64 end) +{ + d->addInterval(QMediaTimeInterval(start, end)); +} + +/*! + \fn QMediaTimeRange::addInterval(const QMediaTimeInterval &interval) + + Adds the specified \a interval to the time range. + + Adding intervals which are not \l{QMediaTimeInterval::isNormal()}{normal} + is invalid, and will be ignored. + + If the specified interval is adjacent to, or overlaps existing + intervals within the time range, these intervals will be merged. + + This operation takes \l{linear time} + + \sa removeInterval() +*/ +void QMediaTimeRange::addInterval(const QMediaTimeInterval &interval) +{ + d->addInterval(interval); +} + +/*! + \fn QMediaTimeRange::addTimeRange(const QMediaTimeRange &range) + + Adds each of the intervals in \a range to this time range. + + Equivalent to calling addInterval() for each interval in \a range. +*/ +void QMediaTimeRange::addTimeRange(const QMediaTimeRange &range) +{ + foreach(const QMediaTimeInterval &i, range.intervals()) { + d->addInterval(i); + } +} + +/*! + \fn QMediaTimeRange::removeInterval(qint64 start, qint64 end) + \overload + + Removes the interval specified by \a start and \a end + from the time range. + + \sa removeInterval() +*/ +void QMediaTimeRange::removeInterval(qint64 start, qint64 end) +{ + d->removeInterval(QMediaTimeInterval(start, end)); +} + +/*! + \fn QMediaTimeRange::removeInterval(const QMediaTimeInterval &interval) + + Removes the specified \a interval from the time range. + + Removing intervals which are not \l{QMediaTimeInterval::isNormal()}{normal} + is invalid, and will be ignored. + + Intervals within the time range will be trimmed, split or deleted + such that no intervals within the time range include any part of the + target interval. + + This operation takes \l{linear time} + + \sa addInterval() +*/ +void QMediaTimeRange::removeInterval(const QMediaTimeInterval &interval) +{ + d->removeInterval(interval); +} + +/*! + \fn QMediaTimeRange::removeTimeRange(const QMediaTimeRange &range) + + Removes each of the intervals in \a range from this time range. + + Equivalent to calling removeInterval() for each interval in \a range. +*/ +void QMediaTimeRange::removeTimeRange(const QMediaTimeRange &range) +{ + foreach(const QMediaTimeInterval &i, range.intervals()) { + d->removeInterval(i); + } +} + +/*! + \fn QMediaTimeRange::operator+=(const QMediaTimeRange &other) + + Adds each interval in \a other to the time range and returns the result. +*/ +QMediaTimeRange& QMediaTimeRange::operator+=(const QMediaTimeRange &other) +{ + addTimeRange(other); + return *this; +} + +/*! + \fn QMediaTimeRange::operator+=(const QMediaTimeInterval &interval) + + Adds the specified \a interval to the time range and returns the result. +*/ +QMediaTimeRange& QMediaTimeRange::operator+=(const QMediaTimeInterval &interval) +{ + addInterval(interval); + return *this; +} + +/*! + \fn QMediaTimeRange::operator-=(const QMediaTimeRange &other) + + Removes each interval in \a other from the time range and returns the result. +*/ +QMediaTimeRange& QMediaTimeRange::operator-=(const QMediaTimeRange &other) +{ + removeTimeRange(other); + return *this; +} + +/*! + \fn QMediaTimeRange::operator-=(const QMediaTimeInterval &interval) + + Removes the specified \a interval from the time range and returns the result. +*/ +QMediaTimeRange& QMediaTimeRange::operator-=(const QMediaTimeInterval &interval) +{ + removeInterval(interval); + return *this; +} + +/*! + \fn QMediaTimeRange::clear() + + Removes all intervals from the time range. + + \sa removeInterval() +*/ +void QMediaTimeRange::clear() +{ + d->intervals.clear(); +} + +/*! + \fn QMediaTimeRange::intervals() const + + Returns the list of intervals covered by this time range. +*/ +QList QMediaTimeRange::intervals() const +{ + return d->intervals; +} + +/*! + \fn QMediaTimeRange::isEmpty() const + + Returns true if there are no intervals within the time range. + + \sa intervals() +*/ +bool QMediaTimeRange::isEmpty() const +{ + return d->intervals.isEmpty(); +} + +/*! + \fn QMediaTimeRange::isContinuous() const + + Returns true if the time range consists of a continuous interval. + That is, there is one or fewer disjoint intervals within the time range. +*/ +bool QMediaTimeRange::isContinuous() const +{ + return (d->intervals.count() <= 1); +} + +/*! + \fn QMediaTimeRange::contains(qint64 time) const + + Returns true if the specified \a time lies within the time range. +*/ +bool QMediaTimeRange::contains(qint64 time) const +{ + for (int i = 0; i < d->intervals.count(); i++) { + if (d->intervals[i].contains(time)) + return true; + + if (time < d->intervals[i].s) + break; + } + + return false; +} + +/*! + \fn operator==(const QMediaTimeRange &a, const QMediaTimeRange &b) + \relates QMediaTimeRange + + Returns true if all intervals in \a a are present in \a b. +*/ +bool operator==(const QMediaTimeRange &a, const QMediaTimeRange &b) +{ + if (a.intervals().count() != b.intervals().count()) + return false; + + for (int i = 0; i < a.intervals().count(); i++) + { + if(a.intervals()[i] != b.intervals()[i]) + return false; + } + + return true; +} + +/*! + \fn operator!=(const QMediaTimeRange &a, const QMediaTimeRange &b) + \relates QMediaTimeRange + + Returns true if one or more intervals in \a a are not present in \a b. +*/ +bool operator!=(const QMediaTimeRange &a, const QMediaTimeRange &b) +{ + return !(a == b); +} + +/*! + \fn operator+(const QMediaTimeRange &r1, const QMediaTimeRange &r2) + + Returns a time range containing the union between \a r1 and \a r2. + */ +QMediaTimeRange operator+(const QMediaTimeRange &r1, const QMediaTimeRange &r2) +{ + return (QMediaTimeRange(r1) += r2); +} + +/*! + \fn operator-(const QMediaTimeRange &r1, const QMediaTimeRange &r2) + + Returns a time range containing \a r2 subtracted from \a r1. + */ +QMediaTimeRange operator-(const QMediaTimeRange &r1, const QMediaTimeRange &r2) +{ + return (QMediaTimeRange(r1) -= r2); +} + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmediatimerange.h b/src/multimedia/base/qmediatimerange.h new file mode 100644 index 0000000..d065368 --- /dev/null +++ b/src/multimedia/base/qmediatimerange.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIATIMERANGE_H +#define QMEDIATIMERANGE_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaTimeRangePrivate; + +class Q_MULTIMEDIA_EXPORT QMediaTimeInterval +{ +public: + QMediaTimeInterval(); + QMediaTimeInterval(qint64 start, qint64 end); + QMediaTimeInterval(const QMediaTimeInterval&); + + qint64 start() const; + qint64 end() const; + + bool contains(qint64 time) const; + + bool isNormal() const; + QMediaTimeInterval normalized() const; + QMediaTimeInterval translated(qint64 offset) const; + +private: + friend class QMediaTimeRangePrivate; + friend class QMediaTimeRange; + + qint64 s; + qint64 e; +}; + +Q_MULTIMEDIA_EXPORT bool operator==(const QMediaTimeInterval&, const QMediaTimeInterval&); +Q_MULTIMEDIA_EXPORT bool operator!=(const QMediaTimeInterval&, const QMediaTimeInterval&); + +class Q_MULTIMEDIA_EXPORT QMediaTimeRange +{ +public: + + QMediaTimeRange(); + QMediaTimeRange(qint64 start, qint64 end); + QMediaTimeRange(const QMediaTimeInterval&); + QMediaTimeRange(const QMediaTimeRange &range); + ~QMediaTimeRange(); + + QMediaTimeRange &operator=(const QMediaTimeRange&); + QMediaTimeRange &operator=(const QMediaTimeInterval&); + + qint64 earliestTime() const; + qint64 latestTime() const; + + QList intervals() const; + bool isEmpty() const; + bool isContinuous() const; + + bool contains(qint64 time) const; + + void addInterval(qint64 start, qint64 end); + void addInterval(const QMediaTimeInterval &interval); + void addTimeRange(const QMediaTimeRange&); + + void removeInterval(qint64 start, qint64 end); + void removeInterval(const QMediaTimeInterval &interval); + void removeTimeRange(const QMediaTimeRange&); + + QMediaTimeRange& operator+=(const QMediaTimeRange&); + QMediaTimeRange& operator+=(const QMediaTimeInterval&); + QMediaTimeRange& operator-=(const QMediaTimeRange&); + QMediaTimeRange& operator-=(const QMediaTimeInterval&); + + void clear(); + +private: + QSharedDataPointer d; +}; + +Q_MULTIMEDIA_EXPORT bool operator==(const QMediaTimeRange&, const QMediaTimeRange&); +Q_MULTIMEDIA_EXPORT bool operator!=(const QMediaTimeRange&, const QMediaTimeRange&); +Q_MULTIMEDIA_EXPORT QMediaTimeRange operator+(const QMediaTimeRange&, const QMediaTimeRange&); +Q_MULTIMEDIA_EXPORT QMediaTimeRange operator-(const QMediaTimeRange&, const QMediaTimeRange&); + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIATIMERANGE_H diff --git a/src/multimedia/base/qmetadatacontrol.cpp b/src/multimedia/base/qmetadatacontrol.cpp new file mode 100644 index 0000000..e45bb0c --- /dev/null +++ b/src/multimedia/base/qmetadatacontrol.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qmediacontrol_p.h" + + +QT_BEGIN_NAMESPACE + + +/*! + \class QMetaDataControl + \ingroup multimedia-serv + + \preliminary + \brief The QMetaDataControl class provides access to the meta-data of a + QMediaService's media. + + If a QMediaService can provide read or write access to the meta-data of + its current media it will implement QMetaDataControl. This control + provides functions for both retrieving and setting meta-data values. + Meta-data may be addressed by the well defined keys in the + QtMedia::MetaData enumeration using the metaData() functions, or by + string keys using the extendedMetaData() functions. + + The functionality provided by this control is exposed to application + code by the meta-data members of QMediaObject, and so meta-data access + is potentially available in any of the media object classes. Any media + service may implement QMetaDataControl. + + The interface name of QMetaDataControl is \c com.nokia.Qt.QMetaDataControl/1.0 as + defined in QMetaDataControl_iid. + + \sa QMediaService::control(), QMediaObject +*/ + +/*! + \macro QMetaDataControl_iid + + \c com.nokia.Qt.QMetaDataControl/1.0 + + Defines the interface name of the QMetaDataControl class. + + \relates QMetaDataControl +*/ + +/*! + Construct a QMetaDataControl with \a parent. This class is meant as a base class + for service specific meta data providers so this constructor is protected. +*/ + +QMetaDataControl::QMetaDataControl(QObject *parent): + QMediaControl(*new QMediaControlPrivate, parent) +{ +} + +/*! + Destroy the meta-data object. +*/ + +QMetaDataControl::~QMetaDataControl() +{ +} + +/*! + \fn bool QMetaDataControl::isMetaDataAvailable() const + + Identifies if meta-data is available from a media service. + + Returns true if the meta-data is available and false otherwise. +*/ + +/*! + \fn bool QMetaDataControl::isWritable() const + + Identifies if a media service's meta-data can be edited. + + Returns true if the meta-data is writable and false otherwise. +*/ + +/*! + \fn QVariant QMetaDataControl::metaData(QtMedia::MetaData key) const + + Returns the meta-data for the given \a key. +*/ + +/*! + \fn void QMetaDataControl::setMetaData(QtMedia::MetaData key, const QVariant &value) + + Sets the \a value of the meta-data element with the given \a key. +*/ + +/*! + \fn QMetaDataControl::availableMetaData() const + + Returns a list of keys there is meta-data available for. +*/ + +/*! + \fn QMetaDataControl::extendedMetaData(const QString &key) const + + Returns the metaData for an abitrary string \a key. + + The valid selection of keys for extended meta-data is determined by the provider and the meaning + and type may differ between providers. +*/ + +/*! + \fn QMetaDataControl::setExtendedMetaData(const QString &key, const QVariant &value) + + Change the value of the meta-data element with an abitrary string \a key to \a value. + + The valid selection of keys for extended meta-data is determined by the provider and the meaning + and type may differ between providers. +*/ + +/*! + \fn QMetaDataControl::availableExtendedMetaData() const + + Returns a list of keys there is extended meta-data available for. +*/ + + +/*! + \fn void QMetaDataControl::metaDataChanged() + + Signal the changes of meta-data. +*/ + +/*! + \fn void QMetaDataControl::metaDataAvailableChanged(bool available) + + Signal the availability of meta-data has changed, \a available will + be true if the multimedia object has meta-data. +*/ + +/*! + \fn void QMetaDataControl::writableChanged(bool writable) + + Signal a change in the writable status of meta-data, \a writable will be + true if meta-data elements can be added or adjusted. +*/ + +#include "moc_qmetadatacontrol.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qmetadatacontrol.h b/src/multimedia/base/qmetadatacontrol.h new file mode 100644 index 0000000..5609f10 --- /dev/null +++ b/src/multimedia/base/qmetadatacontrol.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMETADATACONTROL_H +#define QMETADATACONTROL_H + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class Q_MULTIMEDIA_EXPORT QMetaDataControl : public QMediaControl +{ + Q_OBJECT + +public: + ~QMetaDataControl(); + + virtual bool isWritable() const = 0; + virtual bool isMetaDataAvailable() const = 0; + + virtual QVariant metaData(QtMedia::MetaData key) const = 0; + virtual void setMetaData(QtMedia::MetaData key, const QVariant &value) = 0; + virtual QList availableMetaData() const = 0; + + virtual QVariant extendedMetaData(const QString &key) const = 0; + virtual void setExtendedMetaData(const QString &key, const QVariant &value) = 0; + virtual QStringList availableExtendedMetaData() const = 0; + +Q_SIGNALS: + void metaDataChanged(); + + void writableChanged(bool writable); + void metaDataAvailableChanged(bool available); + +protected: + QMetaDataControl(QObject *parent = 0); +}; + +#define QMetaDataControl_iid "com.nokia.Qt.QMetaDataControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QMetaDataControl, QMetaDataControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QMETADATAPROVIDER_H diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp new file mode 100644 index 0000000..feeb42f --- /dev/null +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -0,0 +1,1456 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpaintervideosurface_p.h" + +#include + +#include +#include +#include + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#include +#endif + +#include + + +QT_BEGIN_NAMESPACE + +class QVideoSurfacePainter +{ +public: + virtual ~QVideoSurfacePainter(); + + virtual QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const = 0; + + virtual bool isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const = 0; + + virtual QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) = 0; + virtual void stop() = 0; + + virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0; + + virtual QAbstractVideoSurface::Error paint( + const QRect &target, QPainter *painter, const QRect &source) = 0; + + virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0; +}; + +QVideoSurfacePainter::~QVideoSurfacePainter() +{ +} + +class QVideoSurfaceRasterPainter : public QVideoSurfacePainter +{ +public: + QVideoSurfaceRasterPainter(); + + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const; + + bool isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const; + + QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); + void stop(); + + QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); + + QAbstractVideoSurface::Error paint( + const QRect &target, QPainter *painter, const QRect &source); + + void updateColors(int brightness, int contrast, int hue, int saturation); + +private: + QList m_imagePixelFormats; + QVideoFrame m_frame; + QSize m_imageSize; + QImage::Format m_imageFormat; + QVideoSurfaceFormat::Direction m_scanLineDirection; +}; + +QVideoSurfaceRasterPainter::QVideoSurfaceRasterPainter() + : m_imageFormat(QImage::Format_Invalid) + , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom) +{ + m_imagePixelFormats + << QVideoFrame::Format_RGB32 +#ifndef QT_OPENGL_ES // The raster formats should be a subset of the GL formats. + << QVideoFrame::Format_RGB24 +#endif + << QVideoFrame::Format_ARGB32 + << QVideoFrame::Format_RGB565; +} + +QList QVideoSurfaceRasterPainter::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + return handleType == QAbstractVideoBuffer::NoHandle + ? m_imagePixelFormats + : QList(); +} + +bool QVideoSurfaceRasterPainter::isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const +{ + return format.handleType() == QAbstractVideoBuffer::NoHandle + && m_imagePixelFormats.contains(format.pixelFormat()) + && !format.frameSize().isEmpty(); +} + +QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::start(const QVideoSurfaceFormat &format) +{ + m_frame = QVideoFrame(); + m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); + m_imageSize = format.frameSize(); + m_scanLineDirection = format.scanLineDirection(); + + return format.handleType() == QAbstractVideoBuffer::NoHandle + && m_imageFormat != QImage::Format_Invalid + && !m_imageSize.isEmpty() + ? QAbstractVideoSurface::NoError + : QAbstractVideoSurface::UnsupportedFormatError; +} + +void QVideoSurfaceRasterPainter::stop() +{ + m_frame = QVideoFrame(); +} + +QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::setCurrentFrame(const QVideoFrame &frame) +{ + m_frame = frame; + + return QAbstractVideoSurface::NoError; +} + +QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::paint( + const QRect &target, QPainter *painter, const QRect &source) +{ + if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { + QImage image( + m_frame.bits(), + m_imageSize.width(), + m_imageSize.height(), + m_frame.bytesPerLine(), + m_imageFormat); + + if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) { + const QTransform oldTransform = painter->transform(); + + painter->scale(1, -1); + painter->translate(0, -target.bottom()); + painter->drawImage( + QRect(target.x(), 0, target.width(), target.height()), image, source); + painter->setTransform(oldTransform); + } else { + painter->drawImage(target, image, source); + } + + m_frame.unmap(); + } else if (m_frame.isValid()) { + return QAbstractVideoSurface::IncorrectFormatError; + } else { + painter->fillRect(target, Qt::black); + } + return QAbstractVideoSurface::NoError; +} + +void QVideoSurfaceRasterPainter::updateColors(int, int, int, int) +{ +} + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + +#ifndef Q_WS_MAC +# ifndef APIENTRYP +# ifdef APIENTRY +# define APIENTRYP APIENTRY * +# else +# define APIENTRY +# define APIENTRYP * +# endif +# endif +#else +# define APIENTRY +# define APIENTRYP * +#endif + +#ifndef GL_TEXTURE0 +# define GL_TEXTURE0 0x84C0 +# define GL_TEXTURE1 0x84C1 +# define GL_TEXTURE2 0x84C2 +#endif +#ifndef GL_PROGRAM_ERROR_STRING_ARB +# define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#endif + +#ifndef GL_UNSIGNED_SHORT_5_6_5 +# define GL_UNSIGNED_SHORT_5_6_5 33635 +#endif + +class QVideoSurfaceGLPainter : public QVideoSurfacePainter +{ +public: + QVideoSurfaceGLPainter(QGLContext *context); + ~QVideoSurfaceGLPainter(); + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const; + + bool isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const; + + QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); + + void updateColors(int brightness, int contrast, int hue, int saturation); + +protected: + void initRgbTextureInfo(GLenum internalFormat, GLuint format, GLenum type, const QSize &size); + void initYuv420PTextureInfo(const QSize &size); + void initYv12TextureInfo(const QSize &size); + +#ifndef QT_OPENGL_ES + typedef void (APIENTRY *_glActiveTexture) (GLenum); + _glActiveTexture glActiveTexture; +#endif + + QList m_imagePixelFormats; + QList m_glPixelFormats; + QMatrix4x4 m_colorMatrix; + QVideoFrame m_frame; + + QGLContext *m_context; + QAbstractVideoBuffer::HandleType m_handleType; + QVideoSurfaceFormat::Direction m_scanLineDirection; + GLenum m_textureFormat; + GLuint m_textureInternalFormat; + GLenum m_textureType; + int m_textureCount; + GLuint m_textureIds[3]; + int m_textureWidths[3]; + int m_textureHeights[3]; + int m_textureOffsets[3]; + bool m_yuv; +}; + +QVideoSurfaceGLPainter::QVideoSurfaceGLPainter(QGLContext *context) + : m_context(context) + , m_handleType(QAbstractVideoBuffer::NoHandle) + , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom) + , m_textureFormat(0) + , m_textureInternalFormat(0) + , m_textureType(0) + , m_textureCount(0) + , m_yuv(false) +{ +#ifndef QT_OPENGL_ES + glActiveTexture = (_glActiveTexture)m_context->getProcAddress(QLatin1String("glActiveTexture")); +#endif +} + +QVideoSurfaceGLPainter::~QVideoSurfaceGLPainter() +{ +} + +QList QVideoSurfaceGLPainter::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + switch (handleType) { + case QAbstractVideoBuffer::NoHandle: + return m_imagePixelFormats; + case QAbstractVideoBuffer::GLTextureHandle: + return m_glPixelFormats; + default: + return QList(); + } +} + +bool QVideoSurfaceGLPainter::isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const +{ + if (format.frameSize().isEmpty()) { + return false; + } else { + switch (format.handleType()) { + case QAbstractVideoBuffer::NoHandle: + return m_imagePixelFormats.contains(format.pixelFormat()); + case QAbstractVideoBuffer::GLTextureHandle: + return m_glPixelFormats.contains(format.pixelFormat()); + default: + return false; + } + } +} + +QAbstractVideoSurface::Error QVideoSurfaceGLPainter::setCurrentFrame(const QVideoFrame &frame) +{ + m_frame = frame; + + if (m_handleType == QAbstractVideoBuffer::GLTextureHandle) { + m_textureIds[0] = frame.handle().toInt(); + } else if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { + m_context->makeCurrent(); + + for (int i = 0; i < m_textureCount; ++i) { + glBindTexture(GL_TEXTURE_2D, m_textureIds[i]); + glTexImage2D( + GL_TEXTURE_2D, + 0, + m_textureInternalFormat, + m_textureWidths[i], + m_textureHeights[i], + 0, + m_textureFormat, + m_textureType, + m_frame.bits() + m_textureOffsets[i]); + 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); + } + m_frame.unmap(); + } else if (m_frame.isValid()) { + return QAbstractVideoSurface::IncorrectFormatError; + } + + return QAbstractVideoSurface::NoError; +} + +void QVideoSurfaceGLPainter::updateColors(int brightness, int contrast, int hue, int saturation) +{ + const qreal b = brightness / 200.0; + const qreal c = contrast / 100.0 + 1.0; + const qreal h = hue / 200.0; + const qreal s = saturation / 100.0 + 1.0; + + const qreal cosH = qCos(M_PI * h); + const qreal sinH = qSin(M_PI * h); + + const qreal h11 = -0.4728 * cosH + 0.7954 * sinH + 1.4728; + const qreal h21 = -0.9253 * cosH - 0.0118 * sinH + 0.9523; + const qreal h31 = 0.4525 * cosH + 0.8072 * sinH - 0.4524; + + const qreal h12 = 1.4728 * cosH - 1.3728 * sinH - 1.4728; + const qreal h22 = 1.9253 * cosH + 0.5891 * sinH - 0.9253; + const qreal h32 = -0.4525 * cosH - 1.9619 * sinH + 0.4525; + + const qreal h13 = 1.4728 * cosH - 0.2181 * sinH - 1.4728; + const qreal h23 = 0.9253 * cosH + 1.1665 * sinH - 0.9253; + const qreal h33 = 0.5475 * cosH - 1.3846 * sinH + 0.4525; + + const qreal sr = (1.0 - s) * 0.3086; + const qreal sg = (1.0 - s) * 0.6094; + const qreal sb = (1.0 - s) * 0.0820; + + const qreal sr_s = sr + s; + const qreal sg_s = sg + s; + const qreal sb_s = sr + s; + + const float m4 = (s + sr + sg + sb) * (0.5 - 0.5 * c + b); + + m_colorMatrix(0, 0) = c * (sr_s * h11 + sg * h21 + sb * h31); + m_colorMatrix(0, 1) = c * (sr_s * h12 + sg * h22 + sb * h32); + m_colorMatrix(0, 2) = c * (sr_s * h13 + sg * h23 + sb * h33); + m_colorMatrix(0, 3) = m4; + + m_colorMatrix(1, 0) = c * (sr * h11 + sg_s * h21 + sb * h31); + m_colorMatrix(1, 1) = c * (sr * h12 + sg_s * h22 + sb * h32); + m_colorMatrix(1, 2) = c * (sr * h13 + sg_s * h23 + sb * h33); + m_colorMatrix(1, 3) = m4; + + m_colorMatrix(2, 0) = c * (sr * h11 + sg * h21 + sb_s * h31); + m_colorMatrix(2, 1) = c * (sr * h12 + sg * h22 + sb_s * h32); + m_colorMatrix(2, 2) = c * (sr * h13 + sg * h23 + sb_s * h33); + m_colorMatrix(2, 3) = m4; + + m_colorMatrix(3, 0) = 0.0; + m_colorMatrix(3, 1) = 0.0; + m_colorMatrix(3, 2) = 0.0; + m_colorMatrix(3, 3) = 1.0; + + if (m_yuv) { + m_colorMatrix = m_colorMatrix * QMatrix4x4( + 1.0, 0.000, 1.140, -0.5700, + 1.0, -0.394, -0.581, 0.4875, + 1.0, 2.028, 0.000, -1.0140, + 0.0, 0.000, 0.000, 1.0000); + } +} + +void QVideoSurfaceGLPainter::initRgbTextureInfo( + GLenum internalFormat, GLuint format, GLenum type, const QSize &size) +{ + m_yuv = false; + m_textureInternalFormat = internalFormat; + m_textureFormat = format; + m_textureType = type; + m_textureCount = 1; + m_textureWidths[0] = size.width(); + m_textureHeights[0] = size.height(); + m_textureOffsets[0] = 0; +} + +void QVideoSurfaceGLPainter::initYuv420PTextureInfo(const QSize &size) +{ + m_yuv = true; + m_textureInternalFormat = GL_LUMINANCE; + m_textureFormat = GL_LUMINANCE; + m_textureType = GL_UNSIGNED_BYTE; + m_textureCount = 3; + m_textureWidths[0] = size.width(); + m_textureHeights[0] = size.height(); + m_textureOffsets[0] = 0; + m_textureWidths[1] = size.width() / 2; + m_textureHeights[1] = size.height() / 2; + m_textureOffsets[1] = size.width() * size.height(); + m_textureWidths[2] = size.width() / 2; + m_textureHeights[2] = size.height() / 2; + m_textureOffsets[2] = size.width() * size.height() * 5 / 4; +} + +void QVideoSurfaceGLPainter::initYv12TextureInfo(const QSize &size) +{ + m_yuv = true; + m_textureInternalFormat = GL_LUMINANCE; + m_textureFormat = GL_LUMINANCE; + m_textureType = GL_UNSIGNED_BYTE; + m_textureCount = 3; + m_textureWidths[0] = size.width(); + m_textureHeights[0] = size.height(); + m_textureOffsets[0] = 0; + m_textureWidths[1] = size.width() / 2; + m_textureHeights[1] = size.height() / 2; + m_textureOffsets[1] = size.width() * size.height() * 5 / 4; + m_textureWidths[2] = size.width() / 2; + m_textureHeights[2] = size.height() / 2; + m_textureOffsets[2] = size.width() * size.height(); +} + +#ifndef QT_OPENGL_ES + +# ifndef GL_FRAGMENT_PROGRAM_ARB +# define GL_FRAGMENT_PROGRAM_ARB 0x8804 +# define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +# endif + +// Paints an RGB32 frame +static const char *qt_arbfp_xrgbShaderProgram = + "!!ARBfp1.0\n" + "PARAM matrix[4] = { program.local[0..2]," + "{ 0.0, 0.0, 0.0, 1.0 } };\n" + "TEMP xrgb;\n" + "TEX xrgb.xyz, fragment.texcoord[0], texture[0], 2D;\n" + "MOV xrgb.w, matrix[3].w;\n" + "DP4 result.color.x, xrgb.zyxw, matrix[0];\n" + "DP4 result.color.y, xrgb.zyxw, matrix[1];\n" + "DP4 result.color.z, xrgb.zyxw, matrix[2];\n" + "END"; + +// Paints an ARGB frame. +static const char *qt_arbfp_argbShaderProgram = + "!!ARBfp1.0\n" + "PARAM matrix[4] = { program.local[0..2]," + "{ 0.0, 0.0, 0.0, 1.0 } };\n" + "TEMP argb;\n" + "TEX argb, fragment.texcoord[0], texture[0], 2D;\n" + "MOV argb.w, matrix[3].w;\n" + "DP4 result.color.x, argb.zyxw, matrix[0];\n" + "DP4 result.color.y, argb.zyxw, matrix[1];\n" + "DP4 result.color.z, argb.zyxw, matrix[2];\n" + "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n" + "END"; + +// Paints an RGB(A) frame. +static const char *qt_arbfp_rgbShaderProgram = + "!!ARBfp1.0\n" + "PARAM matrix[4] = { program.local[0..2]," + "{ 0.0, 0.0, 0.0, 1.0 } };\n" + "TEMP rgb;\n" + "TEX rgb, fragment.texcoord[0], texture[0], 2D;\n" + "MOV rgb.w, matrix[3].w;\n" + "DP4 result.color.x, rgb, matrix[0];\n" + "DP4 result.color.y, rgb, matrix[1];\n" + "DP4 result.color.z, rgb, matrix[2];\n" + "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n" + "END"; + +// Paints a YUV420P or YV12 frame. +static const char *qt_arbfp_yuvPlanarShaderProgram = + "!!ARBfp1.0\n" + "PARAM matrix[4] = { program.local[0..2]," + "{ 0.0, 0.0, 0.0, 1.0 } };\n" + "TEMP yuv;\n" + "TEX yuv.x, fragment.texcoord[0], texture[0], 2D;\n" + "TEX yuv.y, fragment.texcoord[0], texture[1], 2D;\n" + "TEX yuv.z, fragment.texcoord[0], texture[2], 2D;\n" + "MOV yuv.w, matrix[3].w;\n" + "DP4 result.color.x, yuv, matrix[0];\n" + "DP4 result.color.y, yuv, matrix[1];\n" + "DP4 result.color.z, yuv, matrix[2];\n" + "END"; + + +class QVideoSurfaceArbFpPainter : public QVideoSurfaceGLPainter +{ +public: + QVideoSurfaceArbFpPainter(QGLContext *context); + + QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); + void stop(); + + QAbstractVideoSurface::Error paint(const QRect &target, QPainter *painter, const QRect &source); + +private: + typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *); + typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint); + typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *); + typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *); + typedef void (APIENTRY *_glProgramLocalParameter4fARB) ( + GLenum, GLuint, GLfloat, GLfloat, GLfloat, GLfloat); + typedef void (APIENTRY *_glActiveTexture) (GLenum); + + _glProgramStringARB glProgramStringARB; + _glBindProgramARB glBindProgramARB; + _glDeleteProgramsARB glDeleteProgramsARB; + _glGenProgramsARB glGenProgramsARB; + _glProgramLocalParameter4fARB glProgramLocalParameter4fARB; + + GLuint m_programId; + QSize m_frameSize; +}; + +QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context) + : QVideoSurfaceGLPainter(context) + , m_programId(0) +{ + glProgramStringARB = (_glProgramStringARB) m_context->getProcAddress( + QLatin1String("glProgramStringARB")); + glBindProgramARB = (_glBindProgramARB) m_context->getProcAddress( + QLatin1String("glBindProgramARB")); + glDeleteProgramsARB = (_glDeleteProgramsARB) m_context->getProcAddress( + QLatin1String("glDeleteProgramsARB")); + glGenProgramsARB = (_glGenProgramsARB) m_context->getProcAddress( + QLatin1String("glGenProgramsARB")); + glProgramLocalParameter4fARB = (_glProgramLocalParameter4fARB) m_context->getProcAddress( + QLatin1String("glProgramLocalParameter4fARB")); + + m_imagePixelFormats + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32 + << QVideoFrame::Format_RGB24 + << QVideoFrame::Format_RGB565 + << QVideoFrame::Format_YV12 + << QVideoFrame::Format_YUV420P; + m_glPixelFormats + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32; +} + +QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfaceFormat &format) +{ + Q_ASSERT(m_textureCount == 0); + + QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError; + + m_context->makeCurrent(); + + const char *program = 0; + + if (format.handleType() == QAbstractVideoBuffer::NoHandle) { + switch (format.pixelFormat()) { + case QVideoFrame::Format_RGB32: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_xrgbShaderProgram; + break; + case QVideoFrame::Format_ARGB32: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_argbShaderProgram; + break; + case QVideoFrame::Format_RGB24: + initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_argbShaderProgram; + break; + case QVideoFrame::Format_RGB565: + initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize()); + program = qt_arbfp_rgbShaderProgram; + break; + case QVideoFrame::Format_YV12: + initYv12TextureInfo(format.frameSize()); + program = qt_arbfp_yuvPlanarShaderProgram; + break; + case QVideoFrame::Format_YUV420P: + initYuv420PTextureInfo(format.frameSize()); + program = qt_arbfp_yuvPlanarShaderProgram; + break; + default: + break; + } + } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) { + switch (format.pixelFormat()) { + case QVideoFrame::Format_RGB32: + case QVideoFrame::Format_ARGB32: + m_yuv = false; + m_textureCount = 1; + program = qt_arbfp_rgbShaderProgram; + break; + default: + break; + } + } + + if (!program) { + error = QAbstractVideoSurface::UnsupportedFormatError; + } else { + glGenProgramsARB(1, &m_programId); + + GLenum glError = glGetError(); + if (glError != GL_NO_ERROR) { + qWarning("QPainterVideoSurface: ARBfb Shader allocation error %x", int(glError)); + m_textureCount = 0; + m_programId = 0; + + error = QAbstractVideoSurface::ResourceError; + } else { + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId); + glProgramStringARB( + GL_FRAGMENT_PROGRAM_ARB, + GL_PROGRAM_FORMAT_ASCII_ARB, + qstrlen(program), + reinterpret_cast(program)); + + if ((glError = glGetError()) != GL_NO_ERROR) { + const GLubyte* errorString = glGetString(GL_PROGRAM_ERROR_STRING_ARB); + + qWarning("QPainterVideoSurface: ARBfp Shader compile error %x, %s", + int(glError), + reinterpret_cast(errorString)); + glDeleteProgramsARB(1, &m_programId); + + m_textureCount = 0; + m_programId = 0; + + error = QAbstractVideoSurface::ResourceError; + } else { + m_handleType = format.handleType(); + m_scanLineDirection = format.scanLineDirection(); + m_frameSize = format.frameSize(); + + if (m_handleType == QAbstractVideoBuffer::NoHandle) + glGenTextures(m_textureCount, m_textureIds); + } + } + } + + return error; +} + +void QVideoSurfaceArbFpPainter::stop() +{ + m_context->makeCurrent(); + + if (m_handleType != QAbstractVideoBuffer::GLTextureHandle) + glDeleteTextures(m_textureCount, m_textureIds); + glDeleteProgramsARB(1, &m_programId); + + m_textureCount = 0; + m_programId = 0; + m_handleType = QAbstractVideoBuffer::NoHandle; +} + +QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint( + const QRect &target, QPainter *painter, const QRect &source) +{ + if (m_frame.isValid()) { + painter->beginNativePainting(); + + const float txLeft = float(source.left()) / float(m_frameSize.width()); + const float txRight = float(source.right()) / float(m_frameSize.width()); + const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom + ? float(source.top()) / float(m_frameSize.height()) + : float(source.bottom()) / float(m_frameSize.height()); + const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom + ? float(source.bottom()) / float(m_frameSize.height()) + : float(source.top()) / float(m_frameSize.height()); + + + const float tx_array[] = + { + txLeft , txBottom, + txRight, txBottom, + txLeft , txTop, + txRight, txTop + }; + const float v_array[] = + { + target.left() , target.bottom() + 1, + target.right() + 1, target.bottom() + 1, + target.left() , target.top(), + target.right() + 1, target.top() + }; + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_programId); + + glProgramLocalParameter4fARB( + GL_FRAGMENT_PROGRAM_ARB, + 0, + m_colorMatrix(0, 0), + m_colorMatrix(0, 1), + m_colorMatrix(0, 2), + m_colorMatrix(0, 3)); + glProgramLocalParameter4fARB( + GL_FRAGMENT_PROGRAM_ARB, + 1, + m_colorMatrix(1, 0), + m_colorMatrix(1, 1), + m_colorMatrix(1, 2), + m_colorMatrix(1, 3)); + glProgramLocalParameter4fARB( + GL_FRAGMENT_PROGRAM_ARB, + 2, + m_colorMatrix(2, 0), + m_colorMatrix(2, 1), + m_colorMatrix(2, 2), + m_colorMatrix(2, 3)); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_textureIds[0]); + + if (m_textureCount == 3) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_textureIds[1]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, m_textureIds[2]); + glActiveTexture(GL_TEXTURE0); + } + + glVertexPointer(2, GL_FLOAT, 0, v_array); + glTexCoordPointer(2, GL_FLOAT, 0, tx_array); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_FRAGMENT_PROGRAM_ARB); + + painter->endNativePainting(); + } + return QAbstractVideoSurface::NoError; +} + +#endif + +static const char *qt_glsl_vertexShaderProgram = + "attribute highp vec4 vertexCoordArray;\n" + "attribute highp vec2 textureCoordArray;\n" + "uniform highp mat4 positionMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " gl_Position = positionMatrix * vertexCoordArray;\n" + " textureCoord = textureCoordArray;\n" + "}\n"; + +// Paints an RGB32 frame +static const char *qt_glsl_xrgbShaderProgram = + "uniform sampler2D texRgb;\n" + "uniform mediump mat4 colorMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n" + " gl_FragColor = colorMatrix * color;\n" + "}\n"; + +// Paints an ARGB frame. +static const char *qt_glsl_argbShaderProgram = + "uniform sampler2D texRgb;\n" + "uniform mediump mat4 colorMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).bgr, 1.0);\n" + " color = colorMatrix * color;\n" + " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n" + "}\n"; + +// Paints an RGB(A) frame. +static const char *qt_glsl_rgbShaderProgram = + "uniform sampler2D texRgb;\n" + "uniform mediump mat4 colorMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).rgb, 1.0);\n" + " color = colorMatrix * color;\n" + " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).a);\n" + "}\n"; + +// Paints a YUV420P or YV12 frame. +static const char *qt_glsl_yuvPlanarShaderProgram = + "uniform sampler2D texY;\n" + "uniform sampler2D texU;\n" + "uniform sampler2D texV;\n" + "uniform mediump mat4 colorMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " highp vec4 color = vec4(\n" + " texture2D(texY, textureCoord.st).r,\n" + " texture2D(texU, textureCoord.st).r,\n" + " texture2D(texV, textureCoord.st).r,\n" + " 1.0);\n" + " gl_FragColor = colorMatrix * color;\n" + "}\n"; + + +class QVideoSurfaceGlslPainter : public QVideoSurfaceGLPainter +{ +public: + QVideoSurfaceGlslPainter(QGLContext *context); + + QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); + void stop(); + + QAbstractVideoSurface::Error paint(const QRect &target, QPainter *painter, const QRect &source); + +private: + QGLShaderProgram m_program; + QSize m_frameSize; +}; + +QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context) + : QVideoSurfaceGLPainter(context) + , m_program(context) +{ + m_imagePixelFormats + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32 +#ifndef QT_OPENGL_ES + << QVideoFrame::Format_RGB24 +#endif + << QVideoFrame::Format_RGB565 + << QVideoFrame::Format_YV12 + << QVideoFrame::Format_YUV420P; + m_glPixelFormats + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32; +} + +QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurfaceFormat &format) +{ + Q_ASSERT(m_textureCount == 0); + + QAbstractVideoSurface::Error error = QAbstractVideoSurface::NoError; + + m_context->makeCurrent(); + + const char *fragmentProgram = 0; + + if (format.handleType() == QAbstractVideoBuffer::NoHandle) { + switch (format.pixelFormat()) { + case QVideoFrame::Format_RGB32: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_xrgbShaderProgram; + break; + case QVideoFrame::Format_ARGB32: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_argbShaderProgram; + break; +#ifndef QT_OPENGL_ES + case QVideoFrame::Format_RGB24: + initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_rgbShaderProgram; + break; +#endif + case QVideoFrame::Format_RGB565: + initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize()); + fragmentProgram = qt_glsl_rgbShaderProgram; + break; + case QVideoFrame::Format_YV12: + initYv12TextureInfo(format.frameSize()); + fragmentProgram = qt_glsl_yuvPlanarShaderProgram; + break; + case QVideoFrame::Format_YUV420P: + initYuv420PTextureInfo(format.frameSize()); + fragmentProgram = qt_glsl_yuvPlanarShaderProgram; + break; + default: + break; + } + } else if (format.handleType() == QAbstractVideoBuffer::GLTextureHandle) { + switch (format.pixelFormat()) { + case QVideoFrame::Format_RGB32: + case QVideoFrame::Format_ARGB32: + m_yuv = false; + m_textureCount = 1; + fragmentProgram = qt_glsl_rgbShaderProgram; + break; + default: + break; + } + } + + if (!fragmentProgram) { + error = QAbstractVideoSurface::UnsupportedFormatError; + } else if (!m_program.addShaderFromSourceCode(QGLShader::Vertex, qt_glsl_vertexShaderProgram)) { + qWarning("QPainterVideoSurface: Vertex shader compile error %s", + qPrintable(m_program.log())); + error = QAbstractVideoSurface::ResourceError; + } else if (!m_program.addShaderFromSourceCode(QGLShader::Fragment, fragmentProgram)) { + qWarning("QPainterVideoSurface: Shader compile error %s", qPrintable(m_program.log())); + error = QAbstractVideoSurface::ResourceError; + m_program.removeAllShaders(); + } else if(!m_program.link()) { + qWarning("QPainterVideoSurface: Shader link error %s", qPrintable(m_program.log())); + m_program.removeAllShaders(); + error = QAbstractVideoSurface::ResourceError; + } else { + m_handleType = format.handleType(); + m_scanLineDirection = format.scanLineDirection(); + m_frameSize = format.frameSize(); + + if (m_handleType == QAbstractVideoBuffer::NoHandle) + glGenTextures(m_textureCount, m_textureIds); + } + + return error; +} + +void QVideoSurfaceGlslPainter::stop() +{ + m_context->makeCurrent(); + + if (m_handleType != QAbstractVideoBuffer::GLTextureHandle) + glDeleteTextures(m_textureCount, m_textureIds); + m_program.removeAllShaders(); + + m_textureCount = 0; + m_handleType = QAbstractVideoBuffer::NoHandle; +} + +QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( + const QRect &target, QPainter *painter, const QRect &source) +{ + if (m_frame.isValid()) { + painter->beginNativePainting(); + + const int width = QGLContext::currentContext()->device()->width(); + const int height = QGLContext::currentContext()->device()->height(); + + const QTransform transform = painter->deviceTransform(); + + const GLfloat wfactor = 2.0 / width; + const GLfloat hfactor = -2.0 / height; + + const GLfloat positionMatrix[4][4] = + { + { + /*(0,0)*/ wfactor * transform.m11() - transform.m13(), + /*(0,1)*/ hfactor * transform.m12() + transform.m13(), + /*(0,2)*/ 0.0, + /*(0,3)*/ transform.m13() + }, { + /*(1,0)*/ wfactor * transform.m21() - transform.m23(), + /*(1,1)*/ hfactor * transform.m22() + transform.m23(), + /*(1,2)*/ 0.0, + /*(1,3)*/ transform.m23() + }, { + /*(2,0)*/ 0.0, + /*(2,1)*/ 0.0, + /*(2,2)*/ -1.0, + /*(2,3)*/ 0.0 + }, { + /*(3,0)*/ wfactor * transform.dx() - transform.m33(), + /*(3,1)*/ hfactor * transform.dy() + transform.m33(), + /*(3,2)*/ 0.0, + /*(3,3)*/ transform.m33() + } + }; + + const GLfloat vertexCoordArray[] = + { + target.left() , target.bottom() + 1, + target.right() + 1, target.bottom() + 1, + target.left() , target.top(), + target.right() + 1, target.top() + }; + + const GLfloat txLeft = float(source.left()) / float(m_frameSize.width()); + const GLfloat txRight = float(source.right()) / float(m_frameSize.width()); + const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom + ? float(source.top()) / float(m_frameSize.height()) + : float(source.bottom()) / float(m_frameSize.height()); + const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom + ? float(source.bottom()) / float(m_frameSize.height()) + : float(source.top()) / float(m_frameSize.height()); + + const GLfloat textureCoordArray[] = + { + txLeft , txBottom, + txRight, txBottom, + txLeft , txTop, + txRight, txTop + }; + + m_program.bind(); + + m_program.enableAttributeArray("vertexCoordArray"); + m_program.enableAttributeArray("textureCoordArray"); + m_program.setAttributeArray("vertexCoordArray", vertexCoordArray, 2); + m_program.setAttributeArray("textureCoordArray", textureCoordArray, 2); + m_program.setUniformValue("positionMatrix", positionMatrix); + + if (m_textureCount == 3) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_textureIds[0]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, m_textureIds[1]); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, m_textureIds[2]); + glActiveTexture(GL_TEXTURE0); + + m_program.setUniformValue("texY", 0); + m_program.setUniformValue("texU", 1); + m_program.setUniformValue("texV", 2); + } else { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_textureIds[0]); + + m_program.setUniformValue("texRgb", 0); + } + m_program.setUniformValue("colorMatrix", m_colorMatrix); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + m_program.release(); + + painter->endNativePainting(); + } + return QAbstractVideoSurface::NoError; +} + +#endif + +/*! + \class QPainterVideoSurface + \internal +*/ + +/*! +*/ +QPainterVideoSurface::QPainterVideoSurface(QObject *parent) + : QAbstractVideoSurface(parent) + , m_painter(0) +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + , m_glContext(0) + , m_shaderTypes(NoShaders) + , m_shaderType(NoShaders) +#endif + , m_brightness(0) + , m_contrast(0) + , m_hue(0) + , m_saturation(0) + , m_pixelFormat(QVideoFrame::Format_Invalid) + , m_colorsDirty(true) + , m_ready(false) +{ +} + +/*! +*/ +QPainterVideoSurface::~QPainterVideoSurface() +{ + if (isActive()) + m_painter->stop(); + + delete m_painter; +} + +/*! +*/ +QList QPainterVideoSurface::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + if (!m_painter) + const_cast(this)->createPainter(); + + return m_painter->supportedPixelFormats(handleType); +} + +/*! +*/ +bool QPainterVideoSurface::isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const +{ + if (!m_painter) + const_cast(this)->createPainter(); + + return m_painter->isFormatSupported(format, similar); +} + +/*! +*/ +bool QPainterVideoSurface::start(const QVideoSurfaceFormat &format) +{ + if (isActive()) + m_painter->stop(); + + if (!m_painter) + createPainter(); + + if (format.frameSize().isEmpty()) { + setError(UnsupportedFormatError); + } else { + QAbstractVideoSurface::Error error = m_painter->start(format); + + if (error != QAbstractVideoSurface::NoError) { + setError(error); + } else { + m_pixelFormat = format.pixelFormat(); + m_frameSize = format.frameSize(); + m_sourceRect = format.viewport(); + m_colorsDirty = true; + m_ready = true; + + return QAbstractVideoSurface::start(format); + } + } + + QAbstractVideoSurface::stop(); + + return false; +} + +/*! +*/ +void QPainterVideoSurface::stop() +{ + if (isActive()) { + m_painter->stop(); + m_ready = false; + + QAbstractVideoSurface::stop(); + } +} + +/*! +*/ +bool QPainterVideoSurface::present(const QVideoFrame &frame) +{ + if (!m_ready) { + if (!isActive()) + setError(StoppedError); + } else if (frame.isValid() + && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) { + setError(IncorrectFormatError); + + stop(); + } else { + QAbstractVideoSurface::Error error = m_painter->setCurrentFrame(frame); + + if (error != QAbstractVideoSurface::NoError) { + setError(error); + + stop(); + } else { + m_ready = false; + + emit frameChanged(); + + return true; + } + } + return false; +} + +/*! +*/ +int QPainterVideoSurface::brightness() const +{ + return m_brightness; +} + +/*! +*/ +void QPainterVideoSurface::setBrightness(int brightness) +{ + m_brightness = brightness; + + m_colorsDirty = true; +} + +/*! +*/ +int QPainterVideoSurface::contrast() const +{ + return m_contrast; +} + +/*! +*/ +void QPainterVideoSurface::setContrast(int contrast) +{ + m_contrast = contrast; + + m_colorsDirty = true; +} + +/*! +*/ +int QPainterVideoSurface::hue() const +{ + return m_hue; +} + +/*! +*/ +void QPainterVideoSurface::setHue(int hue) +{ + m_hue = hue; + + m_colorsDirty = true; +} + +/*! +*/ +int QPainterVideoSurface::saturation() const +{ + return m_saturation; +} + +/*! +*/ +void QPainterVideoSurface::setSaturation(int saturation) +{ + m_saturation = saturation; + + m_colorsDirty = true; +} + +/*! +*/ +bool QPainterVideoSurface::isReady() const +{ + return m_ready; +} + +/*! +*/ +void QPainterVideoSurface::setReady(bool ready) +{ + m_ready = ready; +} + +/*! +*/ +void QPainterVideoSurface::paint(QPainter *painter, const QRect &rect) +{ + if (!isActive()) { + painter->fillRect(rect, QBrush(Qt::black)); + } else { + if (m_colorsDirty) { + m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation); + m_colorsDirty = false; + } + + QAbstractVideoSurface::Error error = m_painter->paint(rect, painter, m_sourceRect); + + if (error != QAbstractVideoSurface::NoError) { + setError(error); + + stop(); + } + } +} + +/*! + \fn QPainterVideoSurface::frameChanged() +*/ + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + +/*! +*/ +const QGLContext *QPainterVideoSurface::glContext() const +{ + return m_glContext; +} + +/*! +*/ +void QPainterVideoSurface::setGLContext(QGLContext *context) +{ + if (m_glContext == context) + return; + + m_glContext = context; + + m_shaderTypes = NoShaders; + + if (m_glContext) { + m_glContext->makeCurrent(); + + const QByteArray extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); +#ifndef QT_OPENGL_ES + + if (extensions.contains("ARB_fragment_program")) + m_shaderTypes |= FragmentProgramShader; +#endif + + if (QGLShaderProgram::hasOpenGLShaderPrograms(m_glContext) + && extensions.contains("ARB_shader_objects")) + m_shaderTypes |= GlslShader; + } + + ShaderType type = (m_shaderType & m_shaderTypes) + ? m_shaderType + : NoShaders; + + if (type != m_shaderType || type != NoShaders) { + m_shaderType = type; + + if (isActive()) { + m_painter->stop(); + delete m_painter; + m_painter = 0; + m_ready = false; + + setError(ResourceError); + QAbstractVideoSurface::stop(); + } + emit supportedFormatsChanged(); + } +} + +/*! + \enum QPainterVideoSurface::ShaderType + + \value NoShaders + \value FragmentProgramShader + \value HlslShader +*/ + +/*! + \typedef QPainterVideoSurface::ShaderTypes +*/ + +/*! +*/ +QPainterVideoSurface::ShaderTypes QPainterVideoSurface::supportedShaderTypes() const +{ + return m_shaderTypes; +} + +/*! +*/ +QPainterVideoSurface::ShaderType QPainterVideoSurface::shaderType() const +{ + return m_shaderType; +} + +/*! +*/ +void QPainterVideoSurface::setShaderType(ShaderType type) +{ + if (!(type & m_shaderTypes)) + type = NoShaders; + + if (type != m_shaderType) { + m_shaderType = type; + + if (isActive()) { + m_painter->stop(); + delete m_painter; + m_painter = 0; + m_ready = false; + + setError(ResourceError); + QAbstractVideoSurface::stop(); + } else { + delete m_painter; + m_painter = 0; + } + emit supportedFormatsChanged(); + } +} + +#endif + +void QPainterVideoSurface::createPainter() +{ + Q_ASSERT(!m_painter); + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + switch (m_shaderType) { +#ifndef QT_OPENGL_ES + case FragmentProgramShader: + Q_ASSERT(m_glContext); + m_glContext->makeCurrent(); + m_painter = new QVideoSurfaceArbFpPainter(m_glContext); + break; +#endif + case GlslShader: + Q_ASSERT(m_glContext); + m_glContext->makeCurrent(); + m_painter = new QVideoSurfaceGlslPainter(m_glContext); + break; + default: + m_painter = new QVideoSurfaceRasterPainter; + break; + } +#else + m_painter = new QVideoSurfaceRasterPainter; +#endif +} + +QT_END_NAMESPACE + +#include "moc_qpaintervideosurface_p.cpp" + + diff --git a/src/multimedia/base/qpaintervideosurface_p.h b/src/multimedia/base/qpaintervideosurface_p.h new file mode 100644 index 0000000..2a146d0 --- /dev/null +++ b/src/multimedia/base/qpaintervideosurface_p.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPAINTERVIDEOSURFACE_P_H +#define QPAINTERVIDEOSURFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QVideoSurfacePainter; +class Q_AUTOTEST_EXPORT QPainterVideoSurface : public QAbstractVideoSurface +{ + Q_OBJECT +public: + explicit QPainterVideoSurface(QObject *parent = 0); + ~QPainterVideoSurface(); + + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + + bool isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar = 0) const; + + bool start(const QVideoSurfaceFormat &format); + void stop(); + + bool present(const QVideoFrame &frame); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + bool isReady() const; + void setReady(bool ready); + + void paint(QPainter *painter, const QRect &rect); + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + const QGLContext *glContext() const; + void setGLContext(QGLContext *context); + + enum ShaderType + { + NoShaders = 0x00, + FragmentProgramShader = 0x01, + GlslShader = 0x02 + }; + + Q_DECLARE_FLAGS(ShaderTypes, ShaderType) + + ShaderTypes supportedShaderTypes() const; + + ShaderType shaderType() const; + void setShaderType(ShaderType type); +#endif + +Q_SIGNALS: + void frameChanged(); + +private: + void createPainter(); + + QVideoSurfacePainter *m_painter; +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + QGLContext *m_glContext; + ShaderTypes m_shaderTypes; + ShaderType m_shaderType; +#endif + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; + + QVideoFrame::PixelFormat m_pixelFormat; + QSize m_frameSize; + QRect m_sourceRect; + bool m_colorsDirty; + bool m_ready; +}; + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +Q_DECLARE_OPERATORS_FOR_FLAGS(QPainterVideoSurface::ShaderTypes) +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qtmedianamespace.h b/src/multimedia/base/qtmedianamespace.h new file mode 100644 index 0000000..c3b4896 --- /dev/null +++ b/src/multimedia/base/qtmedianamespace.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTMEDIANAMESPACE_H +#define QTMEDIANAMESPACE_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +namespace QtMedia +{ + enum MetaData + { + // Common + Title, + SubTitle, + Author, + Comment, + Description, + Category, + Genre, + Year, + Date, + UserRating, + Keywords, + Language, + Publisher, + Copyright, + ParentalRating, + RatingOrganisation, + + // Media + Size, + MediaType, + Duration, + + // Audio + AudioBitRate, + AudioCodec, + AverageLevel, + ChannelCount, + PeakValue, + SampleRate, + + // Music + AlbumTitle, + AlbumArtist, + ContributingArtist, + Composer, + Conductor, + Lyrics, + Mood, + TrackNumber, + TrackCount, + + CoverArtUrlSmall, + CoverArtUrlLarge, + + // Image/Video + Resolution, + PixelAspectRatio, + + // Video + VideoFrameRate, + VideoBitRate, + VideoCodec, + + PosterUrl, + + // Movie + ChapterNumber, + Director, + LeadPerformer, + Writer, + + // Photos + CameraManufacturer, + CameraModel, + Event, + Subject, + Orientation, + ExposureTime, + FNumber, + ExposureProgram, + ISOSpeedRatings, + ExposureBiasValue, + DateTimeOriginal, + DateTimeDigitized, + SubjectDistance, + MeteringMode, + LightSource, + Flash, + FocalLength, + ExposureMode, + WhiteBalance, + DigitalZoomRatio, + FocalLengthIn35mmFilm, + SceneCaptureType, + GainControl, + Contrast, + Saturation, + Sharpness, + DeviceSettingDescription + }; + + enum SupportEstimate + { + NotSupported, + MaybeSupported, + ProbablySupported, + PreferedService + }; + + enum EncodingQuality + { + VeryLowQuality, + LowQuality, + NormalQuality, + HighQuality, + VeryHighQuality + }; + + enum EncodingMode + { + ConstantQualityEncoding, + ConstantBitRateEncoding, + AverageBitRateEncoding, + TwoPassEncoding + }; + + enum AvailabilityError + { + NoError, + ServiceMissingError, + BusyError, + ResourceError + }; + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qtmedianamespace.qdoc b/src/multimedia/base/qtmedianamespace.qdoc new file mode 100644 index 0000000..0fb39f5 --- /dev/null +++ b/src/multimedia/base/qtmedianamespace.qdoc @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \namespace QtMedia + \ingroup multimedia + + \brief The QtMedia namespace contains miscellaneous identifiers used throughout the Qt Media + library. +*/ + +/*! + \enum QtMedia::MetaData + + This enum provides identifiers for meta-data attributes. + + Common attributes + \value Title The title of the media. QString. + \value SubTitle The sub-title of the media. QString. + \value Author The authors of the media. QStringList. + \value Comment A user comment about the media. QString. + \value Description A description of the media. QString + \value Category The category of the media. QStringList. + \value Genre The genre of the media. QStringList. + \value Year The year of release of the media. int. + \value Date The date of the media. QDate. + \value UserRating A user rating of the media. int [0..100]. + \value Keywords A list of keywords describing the media. QStringList. + \value Language The language of media, as an ISO 639-2 code. + + \value Publisher The publisher of the media. QString. + \value Copyright The media's copyright notice. QString. + \value ParentalRating The parental rating of the media. QString. + \value RatingOrganisation The organisation responsible for the parental rating of the media. + QString. + + Media attributes + \value Size The size in bytes of the media. qint64 + \value MediaType The type of the media (audio, video, etc). QString. + \value Duration The duration in millseconds of the media. qint64. + + Audio attributes + \value AudioBitRate The bit rate of the media's audio stream in bits per second. int. + \value AudioCodec The codec of the media's audio stream. QString. + \value AverageLevel The average volume level of the media. int. + \value ChannelCount The number of channels in the media's audio stream. int. + \value PeakValue The peak volume of the media's audio stream. int + \value SampleRate The sample rate of the media's audio stream in hertz. int + + Music attributes + \value AlbumTitle The title of the album the media belongs to. QString. + \value AlbumArtist The principal artist of the album the media belongs to. QString. + \value ContributingArtist The artists contributing to the media. QStringList. + \value Composer The composer of the media. QStringList. + \value Conductor The conductor of the media. QString. + \value Lyrics The lyrics to the media. QString. + \value Mood The mood of the media. QString. + \value TrackNumber The track number of the media. int. + \value TrackCount The number of tracks on the album containing the media. int. + + \value CoverArtUrlSmall The URL of a small cover art image. QUrl. + \value CoverArtUrlLarge The URL of a large cover art image. QUrl. + + Image and video attributes + \value Resolution The dimensions of an image or video. QSize. + \value PixelAspectRatio The pixel aspect ratio of an image or video. QSize. + + Video attributes + \value VideoFrameRate The frame rate of the media's video stream. qreal. + \value VideoBitRate The bit rate of the media's video stream in bits per second. int. + \value VideoCodec The codec of the media's video stream. QString. + + \value PosterUrl The URL of a poster image. QUrl. + + Movie attributes + \value ChapterNumber The chapter number of the media. int. + \value Director The director of the media. QString. + \value LeadPerformer The lead performer in the media. QStringList. + \value Writer The writer of the media. QStringList. + + Photo attributes. + \value CameraManufacturer The manufacturer of the camera used to capture the media. QString. + \value CameraModel The model of the camera used to capture the media. QString. + \value Event The event during which the media was captured. QString. + \value Subject The subject of the media. QString. + \value Orientation Orientation of image. + \value ExposureTime Exposure time, given in seconds. + \value FNumber The F Number. + \value ExposureProgram + The class of the program used by the camera to set exposure when the picture is taken. + \value ISOSpeedRatings + Indicates the ISO Speed and ISO Latitude of the camera or input device as specified in ISO 12232. + \value ExposureBiasValue + The exposure bias. + The unit is the APEX (Additive System of Photographic Exposure) setting. + \value DateTimeOriginal The date and time when the original image data was generated. + \value DateTimeDigitized The date and time when the image was stored as digital data. + \value SubjectDistance The distance to the subject, given in meters. + \value MeteringMode The metering mode. + \value LightSource + The kind of light source. + \value Flash + Status of flash when the image was shot. + \value FocalLength + The actual focal length of the lens, in mm. + \value ExposureMode + Indicates the exposure mode set when the image was shot. + \value WhiteBalance + Indicates the white balance mode set when the image was shot. + \value DigitalZoomRatio + Indicates the digital zoom ratio when the image was shot. + \value FocalLengthIn35mmFilm + Indicates the equivalent focal length assuming a 35mm film camera, in mm. + \value SceneCaptureType + Indicates the type of scene that was shot. + It can also be used to record the mode in which the image was shot. + \value GainControl + Indicates the degree of overall image gain adjustment. + \value Contrast + Indicates the direction of contrast processing applied by the camera when the image was shot. + \value Saturation + Indicates the direction of saturation processing applied by the camera when the image was shot. + \value Sharpness + Indicates the direction of sharpness processing applied by the camera when the image was shot. + \value DeviceSettingDescription + Exif tag, indicates information on the picture-taking conditions of a particular camera model. QString +*/ + +/*! + \enum QtMedia::SupportEstimate + + Enumerates the levels of support a media service provider may have for a feature. + + \value NotSupported The feature is not supported. + \value MaybeSupported The feature may be supported. + \value ProbablySupported The feature is probably supported. + \value PreferedService The service is the preferred provider of a service. +*/ + +/*! + \enum QtMedia::EncodingQuality + + Enumerates quality encoding levels. + + \value VeryLowQuality + \value LowQuality + \value NormalQuality + \value HighQuality + \value VeryHighQuality +*/ + +/*! + \enum QtMedia::EncodingMode + + Enumerates encoding modes. + + \value ConstantQualityEncoding + \value ConstantBitRateEncoding + \value AverageBitRateEncoding + \value TwoPassEncoding +*/ + +/*! + \enum QtMedia::AvailabilityError + + Enumerates Service status errors. + + \value NoError + \value ServiceMissingError + \value ResourceError + \value BusyError +*/ diff --git a/src/multimedia/base/qvideodevicecontrol.cpp b/src/multimedia/base/qvideodevicecontrol.cpp new file mode 100644 index 0000000..21db500 --- /dev/null +++ b/src/multimedia/base/qvideodevicecontrol.cpp @@ -0,0 +1,154 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +/*! + \class QVideoDeviceControl + \preliminary + \brief The QVideoDeviceControl class provides an video device selector media control. + \ingroup multimedia-serv + + The QVideoDeviceControl class provides descriptions of the video devices + available on a system and allows one to be selected as the endpoint of + a media service. + + The interface name of QVideoDeviceControl is \c com.nokia.Qt.VideoDeviceControl as + defined in QVideoDeviceControl_iid. +*/ + +/*! + \macro QVideoDeviceControl_iid + + \c com.nokia.Qt.VideoDeviceControl + + Defines the interface name of the QVideoDeviceControl class. + + \relates QVideoDeviceControl +*/ + +/*! + Constructs a video device control with the given \a parent. +*/ +QVideoDeviceControl::QVideoDeviceControl(QObject *parent) + :QMediaControl(parent) +{ +} + +/*! + Destroys a video device control. +*/ +QVideoDeviceControl::~QVideoDeviceControl() +{ +} + +/*! + \fn QVideoDeviceControl::deviceCount() const + + Returns the number of available video devices; +*/ + +/*! + \fn QVideoDeviceControl::deviceName(int index) const + + Returns the name of the video device at \a index. +*/ + +/*! + \fn QVideoDeviceControl::deviceDescription(int index) const + + Returns a description of the video device at \a index. +*/ + +/*! + \fn QVideoDeviceControl::deviceIcon(int index) const + + Returns an icon for the video device at \a index. +*/ + +/*! + \fn QVideoDeviceControl::defaultDevice() const + + Returns the index of the default video device. +*/ + +/*! + \fn QVideoDeviceControl::selectedDevice() const + + Returns the index of the selected video device. +*/ + +/*! + \fn QVideoDeviceControl::setSelectedDevice(int index) + + Sets the selected video device \a index. +*/ + +/*! + \fn QVideoDeviceControl::devicesChanged() + + Signals that the list of available video devices has changed. +*/ + +/*! + \fn QVideoDeviceControl::selectedDeviceChanged(int index) + + Signals that the selected video device \a index has changed. +*/ + +/*! + \fn QVideoDeviceControl::selectedDeviceChanged(const QString &name) + + Signals that the selected video device \a name has changed. +*/ + +QT_END_NAMESPACE + +QT_END_HEADER + +#include "moc_qvideodevicecontrol.cpp" + + diff --git a/src/multimedia/base/qvideodevicecontrol.h b/src/multimedia/base/qvideodevicecontrol.h new file mode 100644 index 0000000..ce99fd1 --- /dev/null +++ b/src/multimedia/base/qvideodevicecontrol.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEODEVICECONTROL_H +#define QVIDEODEVICECONTROL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class Q_MULTIMEDIA_EXPORT QVideoDeviceControl : public QMediaControl +{ + Q_OBJECT + +public: + virtual ~QVideoDeviceControl(); + + virtual int deviceCount() const = 0; + + virtual QString deviceName(int index) const = 0; + virtual QString deviceDescription(int index) const = 0; + virtual QIcon deviceIcon(int index) const = 0; + + virtual int defaultDevice() const = 0; + virtual int selectedDevice() const = 0; + +public Q_SLOTS: + virtual void setSelectedDevice(int index) = 0; + +Q_SIGNALS: + void selectedDeviceChanged(int index); + void selectedDeviceChanged(const QString &deviceName); + void devicesChanged(); + +protected: + QVideoDeviceControl(QObject *parent = 0); +}; + +#define QVideoDeviceControl_iid "com.nokia.Qt.QVideoDeviceControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QVideoDeviceControl, QVideoDeviceControl_iid) + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QVIDEODEVICECONTROL_H diff --git a/src/multimedia/base/qvideooutputcontrol.cpp b/src/multimedia/base/qvideooutputcontrol.cpp new file mode 100644 index 0000000..a904385 --- /dev/null +++ b/src/multimedia/base/qvideooutputcontrol.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + + +QT_BEGIN_NAMESPACE + +/*! + \class QVideoOutputControl + \preliminary + + \brief The QVideoOutputControl class provides a means of selecting the + active video output control. + + \ingroup multimedia-serv + + There are multiple controls which a QMediaService may use to output + video ony one of which may be active at one time, QVideoOutputControl + is the means by which this active control is selected. + + The possible output controls are QVideoRendererControl, + QVideoWindowControl, and QVideoWidgetControl. + + The interface name of QVideoOutputControl is \c com.nokia.Qt.QVideoOutputControl/1.0 as + defined in QVideoOutputControl_iid. + + \sa QMediaService::control(), QVideoWidget, QVideoRendererControl, + QVideoWindowControl, QVideoWidgetControl +*/ + +/*! + \macro QVideoOutputControl_iid + + \c com.nokia.Qt.QVideoOutputControl/1.0 + + Defines the interface name of the QVideoOutputControl class. + + \relates QVideoOutputControl +*/ + +/*! + \enum QVideoOutputControl::Output + + Identifies the possible render targets of a video output. + + \value NoOutput Video is not rendered. + \value WindowOutput Video is rendered to the target of a QVideoWindowControl. + \value RendererOutput Video is rendered to the target of a QVideoRendererControl. + \value WidgetOutput Video is rendered to a QWidget provided by QVideoWidgetControl. + \value UserOutput Start value for user defined video targets. + \value MaxUserOutput End value for user defined video targets. +*/ + +/*! + Constructs a new video output control with the given \a parent. +*/ +QVideoOutputControl::QVideoOutputControl(QObject *parent) + : QMediaControl(parent) +{ +} + +/*! + Destroys a video output control. +*/ +QVideoOutputControl::~QVideoOutputControl() +{ +} + +/*! + \fn QList QVideoOutputControl::availableOutputs() const + + Returns a list of available video output targets. +*/ + +/*! + \fn QVideoOutputControl::output() const + + Returns the current video output target. +*/ + +/*! + \fn QVideoOutputControl::setOutput(Output output) + + Sets the current video \a output target. +*/ + +/*! + \fn QVideoOutputControl::availableOutputsChanged(const QList &outputs) + + Signals that available set of video \a outputs has changed. +*/ + +#include "moc_qvideooutputcontrol.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qvideooutputcontrol.h b/src/multimedia/base/qvideooutputcontrol.h new file mode 100644 index 0000000..805da58 --- /dev/null +++ b/src/multimedia/base/qvideooutputcontrol.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEOOUTPUTCONTROL_H +#define QVIDEOOUTPUTCONTROL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class Q_MULTIMEDIA_EXPORT QVideoOutputControl : public QMediaControl +{ + Q_OBJECT + +public: + enum Output + { + NoOutput, + WindowOutput, + RendererOutput, + WidgetOutput, + UserOutput = 100, + MaxUserOutput = 1000 + }; + + ~QVideoOutputControl(); + + virtual QList availableOutputs() const = 0; + + virtual Output output() const = 0; + virtual void setOutput(Output output) = 0; + +Q_SIGNALS: + void availableOutputsChanged(const QList &outputs); + +protected: + QVideoOutputControl(QObject *parent = 0); +}; + +#define QVideoOutputControl_iid "com.nokia.Qt.QVideoOutputControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QVideoOutputControl, QVideoOutputControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qvideorenderercontrol.cpp b/src/multimedia/base/qvideorenderercontrol.cpp new file mode 100644 index 0000000..4e7b3da --- /dev/null +++ b/src/multimedia/base/qvideorenderercontrol.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qmediacontrol_p.h" + + +QT_BEGIN_NAMESPACE + +/*! + \class QVideoRendererControl + \preliminary + + \brief The QVideoRendererControl class provides a control for rendering + to a video surface. + + \ingroup multimedia-serv + + Using the surface() property of QVideoRendererControl a QAbstractVideoSurface + may be set as the video render target of a QMediaService. + + \code + QVideoRendererControl *rendererControl = mediaService->control(); + rendererControl->setSurface(myVideoSurface); + \endcode + + QVideoRendererControl is one of number of possible video output controls, + in order to receive video it must be made the active video output + control by setting the output property of QVideoOutputControl to + \l {QVideoOutputControl::RendererOutput}{RendererOutput}. Consequently any + QMediaService that implements QVideoRendererControl must also implement + QVideoOutputControl. + + \code + QVideoOutputControl *outputControl = mediaService->control(); + outputControl->setOutput(QVideoOutputControl::RendererOutput); + \endcode + + The interface name of QVideoRendererControl is \c com.nokia.Qt.QVideoRendererControl/1.0 as + defined in QVideoRendererControl_iid. + + \sa QMediaService::control(), QVideoOutputControl, QVideoWidget +*/ + +/*! + \macro QVideoRendererControl_iid + + \c com.nokia.Qt.QVideoRendererControl/1.0 + + Defines the interface name of the QVideoRendererControl class. + + \relates QVideoRendererControl +*/ + +/*! + Constructs a new video renderer media end point with the given \a parent. +*/ +QVideoRendererControl::QVideoRendererControl(QObject *parent) + : QMediaControl(parent) +{ +} + +/*! + Destroys a video renderer media end point. +*/ +QVideoRendererControl::~QVideoRendererControl() +{ +} + +/*! + \fn QVideoRendererControl::surface() const + + Returns the surface a video producer renders to. +*/ + +/*! + \fn QVideoRendererControl::setSurface(QAbstractVideoSurface *surface) + + Sets the \a surface a video producer renders to. +*/ + +#include "moc_qvideorenderercontrol.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qvideorenderercontrol.h b/src/multimedia/base/qvideorenderercontrol.h new file mode 100644 index 0000000..f5ba83e --- /dev/null +++ b/src/multimedia/base/qvideorenderercontrol.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEORENDERERCONTROL_H +#define QVIDEORENDERERCONTROL_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QAbstractVideoSurface; + +class Q_MULTIMEDIA_EXPORT QVideoRendererControl : public QMediaControl +{ + Q_OBJECT + +public: + ~QVideoRendererControl(); + + virtual QAbstractVideoSurface *surface() const = 0; + virtual void setSurface(QAbstractVideoSurface *surface) = 0; + +protected: + QVideoRendererControl(QObject *parent = 0); +}; + +#define QVideoRendererControl_iid "com.nokia.Qt.QVideoRendererControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QVideoRendererControl, QVideoRendererControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QVIDEORENDERERCONTROL_H diff --git a/src/multimedia/base/qvideowidget.cpp b/src/multimedia/base/qvideowidget.cpp new file mode 100644 index 0000000..31cfd8d --- /dev/null +++ b/src/multimedia/base/qvideowidget.cpp @@ -0,0 +1,916 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvideowidget_p.h" + +#include +#include +#include +#include +#include + +#include "qpaintervideosurface_p.h" +#include +#include +#include + +#include +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +QVideoWidgetControlBackend::QVideoWidgetControlBackend( + QVideoWidgetControl *control, QWidget *widget) + : m_widgetControl(control) +{ + connect(control, SIGNAL(brightnessChanged(int)), widget, SLOT(_q_brightnessChanged(int))); + connect(control, SIGNAL(contrastChanged(int)), widget, SLOT(_q_contrastChanged(int))); + connect(control, SIGNAL(hueChanged(int)), widget, SLOT(_q_hueChanged(int))); + connect(control, SIGNAL(saturationChanged(int)), widget, SLOT(_q_saturationChanged(int))); + connect(control, SIGNAL(fullScreenChanged(bool)), widget, SLOT(_q_fullScreenChanged(bool))); + + QBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(control->videoWidget()); + + widget->setLayout(layout); +} + +void QVideoWidgetControlBackend::setBrightness(int brightness) +{ + m_widgetControl->setBrightness(brightness); +} + +void QVideoWidgetControlBackend::setContrast(int contrast) +{ + m_widgetControl->setContrast(contrast); +} + +void QVideoWidgetControlBackend::setHue(int hue) +{ + m_widgetControl->setHue(hue); +} + +void QVideoWidgetControlBackend::setSaturation(int saturation) +{ + m_widgetControl->setSaturation(saturation); +} + +void QVideoWidgetControlBackend::setFullScreen(bool fullScreen) +{ + m_widgetControl->setFullScreen(fullScreen); +} + + +QVideoWidget::AspectRatioMode QVideoWidgetControlBackend::aspectRatioMode() const +{ + return m_widgetControl->aspectRatioMode(); +} + +void QVideoWidgetControlBackend::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + m_widgetControl->setAspectRatioMode(mode); +} + +QRendererVideoWidgetBackend::QRendererVideoWidgetBackend( + QVideoRendererControl *control, QWidget *widget) + : m_rendererControl(control) + , m_widget(widget) + , m_surface(new QPainterVideoSurface) + , m_aspectRatioMode(QVideoWidget::KeepAspectRatio) + , m_updatePaintDevice(true) +{ + connect(this, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int))); + connect(this, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int))); + connect(this, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int))); + connect(this, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int))); + connect(m_surface, SIGNAL(frameChanged()), m_widget, SLOT(update())); + connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), + m_widget, SLOT(_q_dimensionsChanged())); + + m_rendererControl->setSurface(m_surface); +} + +QRendererVideoWidgetBackend::~QRendererVideoWidgetBackend() +{ + delete m_surface; +} + +void QRendererVideoWidgetBackend::clearSurface() +{ + m_rendererControl->setSurface(0); +} + +void QRendererVideoWidgetBackend::setBrightness(int brightness) +{ + m_surface->setBrightness(brightness); + + emit brightnessChanged(brightness); +} + +void QRendererVideoWidgetBackend::setContrast(int contrast) +{ + m_surface->setContrast(contrast); + + emit contrastChanged(contrast); +} + +void QRendererVideoWidgetBackend::setHue(int hue) +{ + m_surface->setHue(hue); + + emit hueChanged(hue); +} + +void QRendererVideoWidgetBackend::setSaturation(int saturation) +{ + m_surface->setSaturation(saturation); + + emit saturationChanged(saturation); +} + +QVideoWidget::AspectRatioMode QRendererVideoWidgetBackend::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QRendererVideoWidgetBackend::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; + + m_widget->updateGeometry(); +} + +void QRendererVideoWidgetBackend::setFullScreen(bool) +{ +} + +QSize QRendererVideoWidgetBackend::sizeHint() const +{ + return m_surface->surfaceFormat().sizeHint(); +} + +void QRendererVideoWidgetBackend::showEvent() +{ +} + +void QRendererVideoWidgetBackend::hideEvent(QHideEvent *) +{ +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + m_updatePaintDevice = true; + m_surface->setGLContext(0); +#endif +} + +void QRendererVideoWidgetBackend::resizeEvent(QResizeEvent *) +{ +} + +void QRendererVideoWidgetBackend::moveEvent(QMoveEvent *) +{ +} + +void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event) +{ + QPainter painter(m_widget); + + if (m_surface->isActive()) { + m_surface->paint(&painter, displayRect()); + + m_surface->setReady(true); + } else { + painter.fillRect(event->rect(), m_widget->palette().background()); + + #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + if (m_updatePaintDevice && (painter.paintEngine()->type() == QPaintEngine::OpenGL + || painter.paintEngine()->type() == QPaintEngine::OpenGL2)) { + m_updatePaintDevice = false; + + m_surface->setGLContext(const_cast(QGLContext::currentContext())); + if (m_surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { + m_surface->setShaderType(QPainterVideoSurface::GlslShader); + } else { + m_surface->setShaderType(QPainterVideoSurface::FragmentProgramShader); + } + } +#endif + } +} + +QRect QRendererVideoWidgetBackend::displayRect() const +{ + QRect displayRect = m_widget->rect(); + + if (m_aspectRatioMode != QVideoWidget::IgnoreAspectRatio) { + QVideoSurfaceFormat format = m_surface->surfaceFormat(); + + QSize aspectRatio = format.pixelAspectRatio(); + + QSize size = format.viewport().size(); + size.rwidth() *= aspectRatio.width(); + size.rheight() *= aspectRatio.height(); + size.scale(displayRect.size(), Qt::KeepAspectRatio); + + QPoint center = displayRect.center(); + + displayRect = QRect(QPoint(0, 0), size); + displayRect.moveCenter(center); + } + + return displayRect; +} + +QWindowVideoWidgetBackend::QWindowVideoWidgetBackend(QVideoWindowControl *control, QWidget *widget) + : m_windowControl(control) + , m_widget(widget) + , m_aspectRatioMode(QVideoWidget::KeepAspectRatio) +{ + connect(control, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int))); + connect(control, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int))); + connect(control, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int))); + connect(control, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int))); + connect(control, SIGNAL(fullScreenChanged(bool)), m_widget, SLOT(_q_fullScreenChanged(bool))); + connect(control, SIGNAL(nativeSizeChanged()), m_widget, SLOT(_q_dimensionsChanged())); +} + +QWindowVideoWidgetBackend::~QWindowVideoWidgetBackend() +{ +} + +void QWindowVideoWidgetBackend::setBrightness(int brightness) +{ + m_windowControl->setBrightness(brightness); +} + +void QWindowVideoWidgetBackend::setContrast(int contrast) +{ + m_windowControl->setContrast(contrast); +} + +void QWindowVideoWidgetBackend::setHue(int hue) +{ + m_windowControl->setHue(hue); +} + +void QWindowVideoWidgetBackend::setSaturation(int saturation) +{ + m_windowControl->setSaturation(saturation); +} + +void QWindowVideoWidgetBackend::setFullScreen(bool fullScreen) +{ + m_windowControl->setFullScreen(fullScreen); +} + +QVideoWidget::AspectRatioMode QWindowVideoWidgetBackend::aspectRatioMode() const +{ + return m_windowControl->aspectRatioMode(); +} + +void QWindowVideoWidgetBackend::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + m_windowControl->setAspectRatioMode(mode); +} + +QSize QWindowVideoWidgetBackend::sizeHint() const +{ + return m_windowControl->nativeSize(); +} + +void QWindowVideoWidgetBackend::showEvent() +{ + m_windowControl->setWinId(m_widget->winId()); + + m_windowControl->setDisplayRect(m_widget->rect()); +} + +void QWindowVideoWidgetBackend::hideEvent(QHideEvent *) +{ +} + +void QWindowVideoWidgetBackend::moveEvent(QMoveEvent *) +{ + m_windowControl->setDisplayRect(m_widget->rect()); +} + +void QWindowVideoWidgetBackend::resizeEvent(QResizeEvent *) +{ + m_windowControl->setDisplayRect(m_widget->rect()); +} + +void QWindowVideoWidgetBackend::paintEvent(QPaintEvent *event) +{ + m_windowControl->repaint(); + + event->accept(); +} + +void QVideoWidgetPrivate::setCurrentControl(QVideoWidgetControlInterface *control) +{ + if (currentControl != control) { + currentControl = control; + + currentControl->setBrightness(brightness); + currentControl->setContrast(contrast); + currentControl->setHue(hue); + currentControl->setSaturation(saturation); + currentControl->setAspectRatioMode(aspectRatioMode); + } +} + +void QVideoWidgetPrivate::show() +{ + if (outputControl) { + if (widgetBackend != 0) { + setCurrentControl(widgetBackend); + outputControl->setOutput(QVideoOutputControl::WidgetOutput); + } else if (windowBackend != 0 && (q_func()->window() == 0 + || !q_func()->window()->testAttribute(Qt::WA_DontShowOnScreen))) { + windowBackend->showEvent(); + currentBackend = windowBackend; + setCurrentControl(windowBackend); + outputControl->setOutput(QVideoOutputControl::WindowOutput); + } else if (rendererBackend != 0) { + rendererBackend->showEvent(); + currentBackend = rendererBackend; + setCurrentControl(rendererBackend); + outputControl->setOutput(QVideoOutputControl::RendererOutput); + } else { + outputControl->setOutput(QVideoOutputControl::NoOutput); + } + } +} + +void QVideoWidgetPrivate::clearService() +{ + if (service) { + QObject::disconnect(service, SIGNAL(destroyed()), q_func(), SLOT(_q_serviceDestroyed())); + + if (outputControl) + outputControl->setOutput(QVideoOutputControl::NoOutput); + + if (widgetBackend) { + QLayout *layout = q_func()->layout(); + + for (QLayoutItem *item = layout->takeAt(0); item; item = layout->takeAt(0)) { + item->widget()->setParent(0); + delete item; + } + delete layout; + + delete widgetBackend; + widgetBackend = 0; + } + + delete windowBackend; + windowBackend = 0; + + if (rendererBackend) { + rendererBackend->clearSurface(); + + delete rendererBackend; + rendererBackend = 0; + } + + currentBackend = 0; + currentControl = 0; + outputControl = 0; + service = 0; + } +} + +void QVideoWidgetPrivate::_q_serviceDestroyed() +{ + if (widgetBackend) { + delete q_func()->layout(); + + delete widgetBackend; + widgetBackend = 0; + } + + delete windowBackend; + windowBackend = 0; + + delete rendererBackend; + rendererBackend = 0; + + currentControl = 0; + currentBackend = 0; + outputControl = 0; + service = 0; +} + +void QVideoWidgetPrivate::_q_mediaObjectDestroyed() +{ + mediaObject = 0; + clearService(); +} + +void QVideoWidgetPrivate::_q_brightnessChanged(int b) +{ + if (b != brightness) + emit q_func()->brightnessChanged(brightness = b); +} + +void QVideoWidgetPrivate::_q_contrastChanged(int c) +{ + if (c != contrast) + emit q_func()->contrastChanged(contrast = c); +} + +void QVideoWidgetPrivate::_q_hueChanged(int h) +{ + if (h != hue) + emit q_func()->hueChanged(hue = h); +} + +void QVideoWidgetPrivate::_q_saturationChanged(int s) +{ + if (s != saturation) + emit q_func()->saturationChanged(saturation = s); +} + + +void QVideoWidgetPrivate::_q_fullScreenChanged(bool fullScreen) +{ + if (!fullScreen && q_func()->isFullScreen()) + q_func()->showNormal(); +} + +void QVideoWidgetPrivate::_q_dimensionsChanged() +{ + q_func()->updateGeometry(); +} + +/*! + \class QVideoWidget + \preliminary + + \brief The QVideoWidget class provides a widget which presents video + produced by a media object. + \ingroup multimedia + + Attaching a QVideoWidget to a QMediaObject allows it to display the + video or image output of that media object. A QVideoWidget is attached + to media object by passing a pointer to the QMediaObject in its + constructor, and detached by destroying the QVideoWidget. + + \code + player = new QMediaPlayer; + + widget = new QVideoWidget(player); + widget->show(); + + player->setMedia(QUrl("http://example.com/movie.mp4")); + player->play(); + \endcode + + \bold {Note}: Only a single display output can be attached to a media + object at one time. + + \sa QMediaObject, QMediaPlayer, QGraphicsVideoItem +*/ + +/*! + \enum QVideoWidget::AspectRatioMode + + Specfies how video is scaled with respect to its aspect ratio. + + \value IgnoreAspectRatio The video is scaled to fill the widget ignoring its aspect ratio. + \value KeepAspectRatio The video is scaled to the largest rectangle that will fit within the + widget's dimensions while still retaining its original aspect ratio. +*/ + +/*! + Constructs a new video widget. + + The \a parent is passed to QWidget. +*/ +QVideoWidget::QVideoWidget(QWidget *parent) + : QWidget(parent, 0) + , d_ptr(new QVideoWidgetPrivate) +{ + d_ptr->q_ptr = this; + + QPalette palette = QWidget::palette(); + palette.setColor(QPalette::Background, Qt::black); + setPalette(palette); +} + +/*! + Destroys a video widget. +*/ +QVideoWidget::~QVideoWidget() +{ + setMediaObject(0); + delete d_ptr; +} + +/*! + \property QVideoWidget::mediaObject + \brief the media object which provides the video displayed by a widget. +*/ + +QMediaObject *QVideoWidget::mediaObject() const +{ + return d_func()->mediaObject; +} + +void QVideoWidget::setMediaObject(QMediaObject *object) +{ + Q_D(QVideoWidget); + + if (object == d->mediaObject) + return; + + if (d->mediaObject) { + disconnect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed())); + d->mediaObject->unbind(this); + } + + d->clearService(); + + d->mediaObject = object; + + if (d->mediaObject) { + d->service = d->mediaObject->service(); + + connect(d->mediaObject, SIGNAL(destroyed()), this, SLOT(_q_mediaObjectDestroyed())); + d->mediaObject->bind(this); + } + + if (d->service) { + connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed())); + + d->outputControl = qobject_cast( + d->service->control(QVideoOutputControl_iid)); + + QVideoWidgetControl *widgetControl = qobject_cast( + d->service->control(QVideoWidgetControl_iid)); + + if (widgetControl != 0) { + d->widgetBackend = new QVideoWidgetControlBackend(widgetControl, this); + } else { + QVideoWindowControl *windowControl = qobject_cast( + d->service->control(QVideoWindowControl_iid)); + + if (windowControl != 0) + d->windowBackend = new QWindowVideoWidgetBackend(windowControl, this); + + QVideoRendererControl *rendererControl = qobject_cast( + d->service->control(QVideoRendererControl_iid)); + + if (rendererControl != 0) + d->rendererBackend = new QRendererVideoWidgetBackend(rendererControl, this); + } + + if (isVisible()) + d->show(); + } +} + +/*! + \property QVideoWidget::aspectRatioMode + \brief how video is scaled with respect to its aspect ratio. +*/ + +QVideoWidget::AspectRatioMode QVideoWidget::aspectRatioMode() const +{ + return d_func()->aspectRatioMode; +} + +void QVideoWidget::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + Q_D(QVideoWidget); + + if (d->currentControl) { + d->currentControl->setAspectRatioMode(mode); + d->aspectRatioMode = d->currentControl->aspectRatioMode(); + } else { + d->aspectRatioMode = mode; + } +} + +/*! + \property QVideoWidget::fullScreen + \brief whether video display is confined to a window or is fullScreen. +*/ + +void QVideoWidget::setFullScreen(bool fullScreen) +{ + Q_D(QVideoWidget); + + if (fullScreen) { + Qt::WindowFlags flags = windowFlags(); + + d->nonFullScreenFlags = flags & (Qt::Window | Qt::SubWindow); + flags |= Qt::Window; + flags &= ~Qt::SubWindow; + setWindowFlags(flags); + + showFullScreen(); + } else { + showNormal(); + } +} + +/*! + \fn QVideoWidget::fullScreenChanged(bool fullScreen) + + Signals that the \a fullScreen mode of a video widget has changed. + + \sa fullScreen +*/ + +/*! + \property QVideoWidget::brightness + \brief an adjustment to the brightness of displayed video. + + Valid brightness values range between -100 and 100, the default is 0. +*/ + +int QVideoWidget::brightness() const +{ + return d_func()->brightness; +} + +void QVideoWidget::setBrightness(int brightness) +{ + Q_D(QVideoWidget); + + int boundedBrightness = qBound(-100, brightness, 100); + + if (d->currentControl) + d->currentControl->setBrightness(boundedBrightness); + else if (d->brightness != boundedBrightness) + emit brightnessChanged(d->brightness = boundedBrightness); +} + +/*! + \fn QVideoWidget::brightnessChanged(int brightness) + + Signals that a video widgets's \a brightness adjustment has changed. + + \sa brightness +*/ + +/*! + \property QVideoWidget::contrast + \brief an adjustment to the contrast of displayed video. + + Valid contrast values range between -100 and 100, the default is 0. + +*/ + +int QVideoWidget::contrast() const +{ + return d_func()->contrast; +} + +void QVideoWidget::setContrast(int contrast) +{ + Q_D(QVideoWidget); + + int boundedContrast = qBound(-100, contrast, 100); + + if (d->currentControl) + d->currentControl->setContrast(boundedContrast); + else if (d->contrast != boundedContrast) + emit contrastChanged(d->contrast = boundedContrast); +} + +/*! + \fn QVideoWidget::contrastChanged(int contrast) + + Signals that a video widgets's \a contrast adjustment has changed. + + \sa contrast +*/ + +/*! + \property QVideoWidget::hue + \brief an adjustment to the hue of displayed video. + + Valid hue values range between -100 and 100, the default is 0. +*/ + +int QVideoWidget::hue() const +{ + return d_func()->hue; +} + +void QVideoWidget::setHue(int hue) +{ + Q_D(QVideoWidget); + + int boundedHue = qBound(-100, hue, 100); + + if (d->currentControl) + d->currentControl->setHue(boundedHue); + else if (d->hue != boundedHue) + emit hueChanged(d->hue = boundedHue); +} + +/*! + \fn QVideoWidget::hueChanged(int hue) + + Signals that a video widgets's \a hue has changed. + + \sa hue +*/ + +/*! + \property QVideoWidget::saturation + \brief an adjustment to the saturation of displayed video. + + Valid saturation values range between -100 and 100, the default is 0. +*/ + +int QVideoWidget::saturation() const +{ + return d_func()->saturation; +} + +void QVideoWidget::setSaturation(int saturation) +{ + Q_D(QVideoWidget); + + int boundedSaturation = qBound(-100, saturation, 100); + + if (d->currentControl) + d->currentControl->setSaturation(boundedSaturation); + else if (d->saturation != boundedSaturation) + emit saturationChanged(d->saturation = boundedSaturation); + +} + +/*! + \fn QVideoWidget::saturationChanged(int saturation) + + Signals that a video widgets's \a saturation has changed. + + \sa saturation +*/ + +/*! + Returns the size hint for the current back end, + if there is one, or else the size hint from QWidget. + */ +QSize QVideoWidget::sizeHint() const +{ + Q_D(const QVideoWidget); + + if (d->currentBackend) + return d->currentBackend->sizeHint(); + else + return QWidget::sizeHint(); + + +} + +/*! + \reimp + \internal + */ +bool QVideoWidget::event(QEvent *event) +{ + Q_D(QVideoWidget); + + if (event->type() == QEvent::WindowStateChange) { + Qt::WindowFlags flags = windowFlags(); + + if (windowState() & Qt::WindowFullScreen) { + if (d->currentControl) + d->currentControl->setFullScreen(true); + + if (!d->wasFullScreen) + emit fullScreenChanged(d->wasFullScreen = true); + } else { + if (d->currentControl) + d->currentControl->setFullScreen(false); + + if (d->wasFullScreen) { + flags &= ~(Qt::Window | Qt::SubWindow); //clear the flags... + flags |= d->nonFullScreenFlags; //then we reset the flags (window and subwindow) + setWindowFlags(flags); + + emit fullScreenChanged(d->wasFullScreen = false); + } + } + } + return QWidget::event(event); +} + +/*! + Handles the show \a event. + */ +void QVideoWidget::showEvent(QShowEvent *event) +{ + Q_D(QVideoWidget); + + QWidget::showEvent(event); + + d->show(); + +} + +/*! + + Handles the hide \a event. +*/ +void QVideoWidget::hideEvent(QHideEvent *event) +{ + Q_D(QVideoWidget); + + if (d->currentBackend) + d->currentBackend->hideEvent(event); + + if (d->outputControl) + d->outputControl->setOutput(QVideoOutputControl::NoOutput); + + QWidget::hideEvent(event); +} + +/*! + Handles the resize \a event. + */ +void QVideoWidget::resizeEvent(QResizeEvent *event) +{ + Q_D(QVideoWidget); + + QWidget::resizeEvent(event); + + if (d->currentBackend) + d->currentBackend->resizeEvent(event); +} + +/*! + Handles the move \a event. + */ +void QVideoWidget::moveEvent(QMoveEvent *event) +{ + Q_D(QVideoWidget); + + if (d->currentBackend) + d->currentBackend->moveEvent(event); +} + +/*! + Handles the paint \a event. + */ +void QVideoWidget::paintEvent(QPaintEvent *event) +{ + Q_D(QVideoWidget); + + if (d->currentBackend) + d->currentBackend->paintEvent(event); +} + +#include "moc_qvideowidget.cpp" +#include "moc_qvideowidget_p.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qvideowidget.h b/src/multimedia/base/qvideowidget.h new file mode 100644 index 0000000..4e6cf2e --- /dev/null +++ b/src/multimedia/base/qvideowidget.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEOWIDGET_H +#define QVIDEOWIDGET_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QMediaObject; + +class QVideoWidgetPrivate; +class Q_MULTIMEDIA_EXPORT QVideoWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject) + Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged) + Q_PROPERTY(AspectRatioMode aspectRatioMode READ aspectRatioMode WRITE setAspectRatioMode NOTIFY aspectRatioModeChanged) + Q_PROPERTY(int brightness READ brightness WRITE setBrightness NOTIFY brightnessChanged) + Q_PROPERTY(int contrast READ contrast WRITE setContrast NOTIFY contrastChanged) + Q_PROPERTY(int hue READ hue WRITE setHue NOTIFY hueChanged) + Q_PROPERTY(int saturation READ saturation WRITE setSaturation NOTIFY saturationChanged) + Q_ENUMS(AspectRatio) + +public: + enum AspectRatioMode { IgnoreAspectRatio, KeepAspectRatio }; + + QVideoWidget(QWidget *parent = 0); + ~QVideoWidget(); + + QMediaObject *mediaObject() const; + void setMediaObject(QMediaObject *object); + +#ifdef Q_QDOC + bool isFullScreen() const; +#endif + + AspectRatioMode aspectRatioMode() const; + + int brightness() const; + int contrast() const; + int hue() const; + int saturation() const; + + QSize sizeHint() const; + +public Q_SLOTS: + void setFullScreen(bool fullScreen); + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + void setBrightness(int brightness); + void setContrast(int contrast); + void setHue(int hue); + void setSaturation(int saturation); + +Q_SIGNALS: + void fullScreenChanged(bool fullScreen); + void brightnessChanged(int brightness); + void contrastChanged(int contrast); + void hueChanged(int hue); + void saturationChanged(int saturation); + +protected: + bool event(QEvent *event); + void showEvent(QShowEvent *event); + void hideEvent(QHideEvent *event); + void resizeEvent(QResizeEvent *event); + void moveEvent(QMoveEvent *event); + void paintEvent(QPaintEvent *event); + +protected: + QVideoWidgetPrivate *d_ptr; + +private: + Q_DECLARE_PRIVATE(QVideoWidget) + Q_PRIVATE_SLOT(d_func(), void _q_serviceDestroyed()) + Q_PRIVATE_SLOT(d_func(), void _q_mediaObjectDestroyed()) + Q_PRIVATE_SLOT(d_func(), void _q_brightnessChanged(int)) + Q_PRIVATE_SLOT(d_func(), void _q_contrastChanged(int)) + Q_PRIVATE_SLOT(d_func(), void _q_hueChanged(int)) + Q_PRIVATE_SLOT(d_func(), void _q_saturationChanged(int)) + Q_PRIVATE_SLOT(d_func(), void _q_fullScreenChanged(bool)) + Q_PRIVATE_SLOT(d_func(), void _q_dimensionsChanged()); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qvideowidget_p.h b/src/multimedia/base/qvideowidget_p.h new file mode 100644 index 0000000..4227afd --- /dev/null +++ b/src/multimedia/base/qvideowidget_p.h @@ -0,0 +1,265 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEOWIDGET_P_H +#define QVIDEOWIDGET_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#ifndef QT_NO_OPENGL +#include +#endif + +#include "qpaintervideosurface_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QVideoWidgetControlInterface +{ +public: + virtual ~QVideoWidgetControlInterface() {} + + virtual void setBrightness(int brightness) = 0; + virtual void setContrast(int contrast) = 0; + virtual void setHue(int hue) = 0; + virtual void setSaturation(int saturation) = 0; + + virtual void setFullScreen(bool fullScreen) = 0; + + virtual QVideoWidget::AspectRatioMode aspectRatioMode() const = 0; + virtual void setAspectRatioMode(QVideoWidget::AspectRatioMode mode) = 0; +}; + +class QVideoWidgetBackend : public QObject, public QVideoWidgetControlInterface +{ + Q_OBJECT + +public: + virtual QSize sizeHint() const = 0; + + virtual void showEvent() = 0; + virtual void hideEvent(QHideEvent *event) = 0; + virtual void resizeEvent(QResizeEvent *event) = 0; + virtual void moveEvent(QMoveEvent *event) = 0; + virtual void paintEvent(QPaintEvent *event) = 0; +}; + +class QVideoWidgetControl; + +class QVideoWidgetControlBackend : public QObject, public QVideoWidgetControlInterface +{ + Q_OBJECT +public: + QVideoWidgetControlBackend(QVideoWidgetControl *control, QWidget *widget); + + void setBrightness(int brightness); + void setContrast(int contrast); + void setHue(int hue); + void setSaturation(int saturation); + + void setFullScreen(bool fullScreen); + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + +private: + QVideoWidgetControl *m_widgetControl; +}; + + +class QVideoRendererControl; + +class QRendererVideoWidgetBackend : public QVideoWidgetBackend +{ + Q_OBJECT +public: + QRendererVideoWidgetBackend(QVideoRendererControl *control, QWidget *widget); + ~QRendererVideoWidgetBackend(); + + void clearSurface(); + + void setBrightness(int brightness); + void setContrast(int contrast); + void setHue(int hue); + void setSaturation(int saturation); + + void setFullScreen(bool fullScreen); + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + QSize sizeHint() const; + + void showEvent(); + void hideEvent(QHideEvent *event); + void resizeEvent(QResizeEvent *event); + void moveEvent(QMoveEvent *event); + void paintEvent(QPaintEvent *event); + +Q_SIGNALS: + void fullScreenChanged(bool fullScreen); + void brightnessChanged(int brightness); + void contrastChanged(int contrast); + void hueChanged(int hue); + void saturationChanged(int saturation); + +private: + QRect displayRect() const; + + QVideoRendererControl *m_rendererControl; + QWidget *m_widget; + QPainterVideoSurface *m_surface; + QVideoWidget::AspectRatioMode m_aspectRatioMode; + QSize m_aspectRatio; + bool m_updatePaintDevice; +}; + +class QVideoWindowControl; + +class QWindowVideoWidgetBackend : public QVideoWidgetBackend +{ + Q_OBJECT +public: + QWindowVideoWidgetBackend(QVideoWindowControl *control, QWidget *widget); + ~QWindowVideoWidgetBackend(); + + void setBrightness(int brightness); + void setContrast(int contrast); + void setHue(int hue); + void setSaturation(int saturation); + + void setFullScreen(bool fullScreen); + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + QSize sizeHint() const; + + void showEvent(); + void hideEvent(QHideEvent *event); + void resizeEvent(QResizeEvent *event); + void moveEvent(QMoveEvent *event); + void paintEvent(QPaintEvent *event); + +private: + QVideoWindowControl *m_windowControl; + QWidget *m_widget; + QVideoWidget::AspectRatioMode m_aspectRatioMode; + QSize m_pixelAspectRatio; +}; + +class QMediaService; +class QVideoOutputControl; + +class QVideoWidgetPrivate +{ + Q_DECLARE_PUBLIC(QVideoWidget) +public: + QVideoWidgetPrivate() + : q_ptr(0) + , mediaObject(0) + , service(0) + , outputControl(0) + , widgetBackend(0) + , windowBackend(0) + , rendererBackend(0) + , currentControl(0) + , currentBackend(0) + , brightness(0) + , contrast(0) + , hue(0) + , saturation(0) + , aspectRatioMode(QVideoWidget::KeepAspectRatio) + , nonFullScreenFlags(0) + , wasFullScreen(false) + { + } + + QVideoWidget *q_ptr; + QMediaObject *mediaObject; + QMediaService *service; + QVideoOutputControl *outputControl; + QVideoWidgetControlBackend *widgetBackend; + QWindowVideoWidgetBackend *windowBackend; + QRendererVideoWidgetBackend *rendererBackend; + QVideoWidgetControlInterface *currentControl; + QVideoWidgetBackend *currentBackend; + int brightness; + int contrast; + int hue; + int saturation; + QVideoWidget::AspectRatioMode aspectRatioMode; + Qt::WindowFlags nonFullScreenFlags; + bool wasFullScreen; + + void setCurrentControl(QVideoWidgetControlInterface *control); + void show(); + void clearService(); + + void _q_serviceDestroyed(); + void _q_mediaObjectDestroyed(); + void _q_brightnessChanged(int brightness); + void _q_contrastChanged(int contrast); + void _q_hueChanged(int hue); + void _q_saturationChanged(int saturation); + void _q_fullScreenChanged(bool fullScreen); + void _q_dimensionsChanged(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qvideowidgetcontrol.cpp b/src/multimedia/base/qvideowidgetcontrol.cpp new file mode 100644 index 0000000..bd7ce4e --- /dev/null +++ b/src/multimedia/base/qvideowidgetcontrol.cpp @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "qmediacontrol_p.h" + + +QT_BEGIN_NAMESPACE + +/*! + \class QVideoWidgetControl + \preliminary + + \brief The QVideoWidgetControl class provides a media control which + implements a video widget. + + \ingroup multimedia-serv + + The videoWidget() property of QVideoWidgetControl provides a pointer to + a video widget implemented by the control's media service. This widget + is owned by the media service and so care should be taken not to delete it. + + \code + QVideoWidgetControl *widgetControl = mediaService->control(); + + layout->addWidget(widgetControl->widget()); + \endcode + + QVideoWidgetControl is one of number of possible video output controls, + in order to receive video it must be made the active video output + control by setting the output property of QVideoOutputControl to \l {QVideoOutputControl::WidgetOutput}{WidgetOutput}. Consequently any + QMediaService that implements QVideoWidgetControl must also implement + QVideoOutputControl. + + The interface name of QVideoWidgetControl is \c com.nokia.Qt.QVideoWidgetControl/1.0 as + defined in QVideoWidgetControl_iid. + + \sa QMediaService::control(), QVideoOutputControl, QVideoWidget +*/ + +/*! + \macro QVideoWidgetControl_iid + + \c com.nokia.Qt.QVideoWidgetControl/1.0 + + Defines the interface name of the QVideoWidgetControl class. + + \relates QVideoWidgetControl +*/ + +/*! + Constructs a new video widget control with the given \a parent. +*/ +QVideoWidgetControl::QVideoWidgetControl(QObject *parent) + :QMediaControl(parent) +{ +} + +/*! + Destroys a video widget control. +*/ +QVideoWidgetControl::~QVideoWidgetControl() +{ +} + +/*! + \fn QVideoWidgetControl::isFullScreen() const + + Returns true if the video is shown using the complete screen. +*/ + +/*! + \fn QVideoWidgetControl::setFullScreen(bool fullScreen) + + Sets whether a video widget is in \a fullScreen mode. +*/ + +/*! + \fn QVideoWidgetControl::fullScreenChanged(bool fullScreen) + + Signals that the \a fullScreen state of a video widget has changed. +*/ + +/*! + \fn QVideoWidgetControl::aspectRatioMode() const + + Returns how video is scaled to fit the widget with respect to its aspect ratio. +*/ + +/*! + \fn QVideoWidgetControl::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) + + Sets the aspect ratio \a mode which determines how video is scaled to the fit the widget with + respect to its aspect ratio. +*/ + +/*! + \fn QVideoWidgetControl::brightness() const + + Returns the brightness adjustment applied to a video. + + Valid brightness values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWidgetControl::setBrightness(int brightness) + + Sets a \a brightness adjustment for a video. + + Valid brightness values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWidgetControl::brightnessChanged(int brightness) + + Signals that a video widget's \a brightness adjustment has changed. +*/ + +/*! + \fn QVideoWidgetControl::contrast() const + + Returns the contrast adjustment applied to a video. + + Valid contrast values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWidgetControl::setContrast(int contrast) + + Sets the contrast adjustment for a video widget to \a contrast. + + Valid contrast values range between -100 and 100, the default is 0. +*/ + + +/*! + \fn QVideoWidgetControl::contrastChanged(int contrast) + + Signals that a video widget's \a contrast adjustment has changed. +*/ + +/*! + \fn QVideoWidgetControl::hue() const + + Returns the hue adjustment applied to a video widget. + + Value hue values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWidgetControl::setHue(int hue) + + Sets a \a hue adjustment for a video widget. + + Valid hue values range between -100 and 100, the default is 0. +*/ + + +/*! + \fn QVideoWidgetControl::hueChanged(int hue) + + Signals that a video widget's \a hue adjustment has changed. +*/ + +/*! + \fn QVideoWidgetControl::saturation() const + + Returns the saturation adjustment applied to a video widget. + + Value saturation values range between -100 and 100, the default is 0. +*/ + + +/*! + \fn QVideoWidgetControl::setSaturation(int saturation) + + Sets a \a saturation adjustment for a video widget. + + Valid saturation values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWidgetControl::saturationChanged(int saturation) + + Signals that a video widget's \a saturation adjustment has changed. +*/ + +/*! + \fn QVideoWidgetControl::videoWidget() + + Returns the QWidget. +*/ + +#include "moc_qvideowidgetcontrol.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qvideowidgetcontrol.h b/src/multimedia/base/qvideowidgetcontrol.h new file mode 100644 index 0000000..6981e89 --- /dev/null +++ b/src/multimedia/base/qvideowidgetcontrol.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEOWIDGETCONTROL_H +#define QVIDEOWIDGETCONTROL_H + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QVideoWidgetControlPrivate; + +class Q_MULTIMEDIA_EXPORT QVideoWidgetControl : public QMediaControl +{ + Q_OBJECT + +public: + virtual ~QVideoWidgetControl(); + + virtual QWidget *videoWidget() = 0; + + virtual QVideoWidget::AspectRatioMode aspectRatioMode() const = 0; + virtual void setAspectRatioMode(QVideoWidget::AspectRatioMode mode) = 0; + + virtual bool isFullScreen() const = 0; + virtual void setFullScreen(bool fullScreen) = 0; + + virtual int brightness() const = 0; + virtual void setBrightness(int brightness) = 0; + + virtual int contrast() const = 0; + virtual void setContrast(int contrast) = 0; + + virtual int hue() const = 0; + virtual void setHue(int hue) = 0; + + virtual int saturation() const = 0; + virtual void setSaturation(int saturation) = 0; + +Q_SIGNALS: + void fullScreenChanged(bool fullScreen); + void brightnessChanged(int brightness); + void contrastChanged(int contrast); + void hueChanged(int hue); + void saturationChanged(int saturation); + +protected: + QVideoWidgetControl(QObject *parent = 0); +}; + +#define QVideoWidgetControl_iid "com.nokia.Qt.QVideoWidgetControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QVideoWidgetControl, QVideoWidgetControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/base/qvideowindowcontrol.cpp b/src/multimedia/base/qvideowindowcontrol.cpp new file mode 100644 index 0000000..a23cb4b --- /dev/null +++ b/src/multimedia/base/qvideowindowcontrol.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + + +QT_BEGIN_NAMESPACE + +/*! + \class QVideoWindowControl + \preliminary + \ingroup multimedia-serv + \brief The QVideoWindowControl class provides a media control for rendering video to a window. + + + The winId() property QVideoWindowControl allows a platform specific + window ID to be set as the video render target of a QMediaService. The + displayRect() property is used to set the region of the window the + video should be rendered to, and the aspectRatioMode() property + indicates how the video should be scaled to fit the displayRect(). + + \code + QVideoWindowControl *windowControl = mediaService->control(); + windowControl->setWinId(widget->winId()); + windowControl->setDisplayRect(widget->rect()); + windowControl->setAspectRatioMode(QVideoWidget::KeepAspectRatio); + \endcode + + QVideoWindowControl is one of number of possible video output controls, + in order to receive video it must be made the active video output + control by setting the output property of QVideoOutputControl to \l {QVideoOutputControl::WindowOutput}{WindowOutput}. + Consequently any QMediaService that implements QVideoWindowControl must + also implement QVideoOutputControl. + + \code + QVideoOutputControl *outputControl = mediaService->control(); + outputControl->setOutput(QVideoOutputControl::WindowOutput); + \endcode + + The interface name of QVideoWindowControl is \c com.nokia.Qt.QVideoWindowControl/1.0 as + defined in QVideoWindowControl_iid. + + \sa QMediaService::control(), QVideoOutputControl, QVideoWidget +*/ + +/*! + \macro QVideoWindowControl_iid + + \c com.nokia.Qt.QVideoWindowControl/1.0 + + Defines the interface name of the QVideoWindowControl class. + + \relates QVideoWindowControl +*/ + +/*! + Constructs a new video window control with the given \a parent. +*/ +QVideoWindowControl::QVideoWindowControl(QObject *parent) + : QMediaControl(parent) +{ +} + +/*! + Destroys a video window control. +*/ +QVideoWindowControl::~QVideoWindowControl() +{ +} + +/*! + \fn QVideoWindowControl::winId() const + + Returns the ID of the window a video overlay end point renders to. +*/ + +/*! + \fn QVideoWindowControl::setWinId(WId id) + + Sets the \a id of the window a video overlay end point renders to. +*/ + +/*! + \fn QVideoWindowControl::displayRect() const + Returns the sub-rect of a window where video is displayed. +*/ + +/*! + \fn QVideoWindowControl::setDisplayRect(const QRect &rect) + Sets the sub-\a rect of a window where video is displayed. +*/ + +/*! + \fn QVideoWindowControl::isFullScreen() const + + Identifies if a video overlay is a fullScreen overlay. + + Returns true if the video overlay is fullScreen, and false otherwise. +*/ + +/*! + \fn QVideoWindowControl::setFullScreen(bool fullScreen) + + Sets whether a video overlay is a \a fullScreen overlay. +*/ + +/*! + \fn QVideoWindowControl::fullScreenChanged(bool fullScreen) + + Signals that the \a fullScreen state of a video overlay has changed. +*/ + +/*! + \fn QVideoWindowControl::repaint() + + Repaints the last frame. +*/ + +/*! + \fn QVideoWindowControl::nativeSize() const + + Returns a suggested size for the video display based on the resolution and aspect ratio of the + video. +*/ + +/*! + \fn QVideoWindowControl::nativeSizeChanged() + + Signals that the native dimensions of the video have changed. +*/ + + +/*! + \fn QVideoWindowControl::aspectRatioMode() const + + Returns how video is scaled to fit the display region with respect to its aspect ratio. +*/ + +/*! + \fn QVideoWindowControl::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) + + Sets the aspect ratio \a mode which determines how video is scaled to the fit the display region + with respect to its aspect ratio. +*/ + +/*! + \fn QVideoWindowControl::brightness() const + + Returns the brightness adjustment applied to a video overlay. + + Valid brightness values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::setBrightness(int brightness) + + Sets a \a brightness adjustment for a video overlay. + + Valid brightness values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::brightnessChanged(int brightness) + + Signals that a video overlay's \a brightness adjustment has changed. +*/ + +/*! + \fn QVideoWindowControl::contrast() const + + Returns the contrast adjustment applied to a video overlay. + + Valid contrast values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::setContrast(int contrast) + + Sets the \a contrast adjustment for a video overlay. + + Valid contrast values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::contrastChanged(int contrast) + + Signals that a video overlay's \a contrast adjustment has changed. +*/ + +/*! + \fn QVideoWindowControl::hue() const + + Returns the hue adjustment applied to a video overlay. + + Value hue values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::setHue(int hue) + + Sets a \a hue adjustment for a video overlay. + + Valid hue values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::hueChanged(int hue) + + Signals that a video overlay's \a hue adjustment has changed. +*/ + +/*! + \fn QVideoWindowControl::saturation() const + + Returns the saturation adjustment applied to a video overlay. + + Value saturation values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::setSaturation(int saturation) + Sets a \a saturation adjustment for a video overlay. + + Valid saturation values range between -100 and 100, the default is 0. +*/ + +/*! + \fn QVideoWindowControl::saturationChanged(int saturation) + + Signals that a video overlay's \a saturation adjustment has changed. +*/ + +#include "moc_qvideowindowcontrol.cpp" + +QT_END_NAMESPACE + diff --git a/src/multimedia/base/qvideowindowcontrol.h b/src/multimedia/base/qvideowindowcontrol.h new file mode 100644 index 0000000..9ee96ab --- /dev/null +++ b/src/multimedia/base/qvideowindowcontrol.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVIDEOWINDOWCONTROL_H +#define QVIDEOWINDOWCONTROL_H + +#include + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class Q_MULTIMEDIA_EXPORT QVideoWindowControl : public QMediaControl +{ + Q_OBJECT + +public: + ~QVideoWindowControl(); + + virtual WId winId() const = 0; + virtual void setWinId(WId id) = 0; + + virtual QRect displayRect() const = 0; + virtual void setDisplayRect(const QRect &rect) = 0; + + virtual bool isFullScreen() const = 0; + virtual void setFullScreen(bool fullScreen) = 0; + + virtual void repaint() = 0; + + virtual QSize nativeSize() const = 0; + + virtual QVideoWidget::AspectRatioMode aspectRatioMode() const = 0; + virtual void setAspectRatioMode(QVideoWidget::AspectRatioMode mode) = 0; + + virtual int brightness() const = 0; + virtual void setBrightness(int brightness) = 0; + + virtual int contrast() const = 0; + virtual void setContrast(int contrast) = 0; + + virtual int hue() const = 0; + virtual void setHue(int hue) = 0; + + virtual int saturation() const = 0; + virtual void setSaturation(int saturation) = 0; + +Q_SIGNALS: + void fullScreenChanged(bool fullScreen); + void brightnessChanged(int brightness); + void contrastChanged(int contrast); + void hueChanged(int hue); + void saturationChanged(int saturation); + void nativeSizeChanged(); + +protected: + QVideoWindowControl(QObject *parent = 0); +}; + +#define QVideoWindowControl_iid "com.nokia.Qt.QVideoWindowControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QVideoWindowControl, QVideoWindowControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/multimedia.pro b/src/multimedia/multimedia.pro index c729103..106d3ab 100644 --- a/src/multimedia/multimedia.pro +++ b/src/multimedia/multimedia.pro @@ -10,5 +10,8 @@ include(../qbase.pri) include(audio/audio.pri) include(video/video.pri) +include(base/base.pri) +include(playback/playback.pri) +include(qml/qml.pri) -symbian: TARGET.UID3 = 0x2001E627 \ No newline at end of file +symbian: TARGET.UID3 = 0x2001E627 diff --git a/src/multimedia/playback/playback.pri b/src/multimedia/playback/playback.pri new file mode 100644 index 0000000..09a81c9 --- /dev/null +++ b/src/multimedia/playback/playback.pri @@ -0,0 +1,11 @@ + +HEADERS += \ + $$PWD/qmediaplayer.h \ + $$PWD/qmediaplayercontrol.h + +SOURCES += \ + $$PWD/qmediaplayer.cpp \ + $$PWD/qmediaplayercontrol.cpp + + + diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp new file mode 100644 index 0000000..878af0a --- /dev/null +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -0,0 +1,930 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +/*! + \class QMediaPlayer + \brief The QMediaPlayer class allows the playing of a media source. + \ingroup multimedia + + \preliminary + + The QMediaPlayer class is a high level media playback class. It can be used + to playback such content as songs, movies and internet radio. The content + to playback is specified as a QMediaContent, which can be thought of as a + main or canonical URL with addition information attached. When provided + with a QMediaContent playback may be able to commence. + + \code + player = new QMediaPlayer; + connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64))); + player->setMedia(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3")); + player->setVolume(50); + player->play(); + \endcode + + QVideoWidget can be used with QMediaPlayer for video rendering and QMediaPlaylist + for accessing playlist functionality. + + \code + player = new QMediaPlayer; + + playlist = new QMediaPlaylist; + playlist->setMediaObject(player); + playlist->append(QUrl("http://example.com/movie1.mp4")); + playlist->append(QUrl("http://example.com/movie2.mp4")); + + widget = new QVideoWidget; + widget->setMediaObject(player); + widget->show(); + + player->play(); + \endcode + + \sa QMediaObject, QMediaService, QVideoWidget, QMediaPlaylist +*/ + +namespace +{ +class MediaPlayerRegisterMetaTypes +{ +public: + MediaPlayerRegisterMetaTypes() + { + qRegisterMetaType("QMediaPlayer::State"); + qRegisterMetaType("QMediaPlayer::MediaStatus"); + qRegisterMetaType("QMediaPlayer::Error"); + } +} _registerPlayerMetaTypes; +} + +class QMediaPlayerPrivate : public QMediaObjectPrivate +{ + Q_DECLARE_NON_CONST_PUBLIC(QMediaPlayer) + +public: + QMediaPlayerPrivate() + : provider(0) + , control(0) + , playlistControl(0) + , state(QMediaPlayer::StoppedState) + , error(QMediaPlayer::NoError) + , filterStates(false) + , playlist(0) + {} + + QMediaServiceProvider *provider; + QMediaPlayerControl* control; + QMediaPlaylistControl* playlistControl; + QMediaPlayer::State state; + QMediaPlayer::Error error; + QString errorString; + bool filterStates; + + QMediaPlaylist *playlist; + QPointer videoWidget; + QPointer videoItem; + + void _q_stateChanged(QMediaPlayer::State state); + void _q_mediaStatusChanged(QMediaPlayer::MediaStatus status); + void _q_error(int error, const QString &errorString); + void _q_updateMedia(const QMediaContent&); + void _q_playlistDestroyed(); +}; + +void QMediaPlayerPrivate::_q_stateChanged(QMediaPlayer::State ps) +{ + Q_Q(QMediaPlayer); + + if (filterStates) + return; + + if (playlist + && !playlistControl //service should do this itself + && ps != state && ps == QMediaPlayer::StoppedState + && control->mediaStatus() == QMediaPlayer::EndOfMedia) { + playlist->next(); + ps = control->state(); + } + + if (ps != state) { + state = ps; + + if (ps == QMediaPlayer::PlayingState) + q->addPropertyWatch("position"); + else + q->removePropertyWatch("position"); + + emit q->stateChanged(ps); + } +} + +void QMediaPlayerPrivate::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status) +{ + Q_Q(QMediaPlayer); + + switch (status) { + case QMediaPlayer::StalledMedia: + case QMediaPlayer::BufferingMedia: + q->addPropertyWatch("bufferStatus"); + emit q->mediaStatusChanged(status); + break; + default: + q->removePropertyWatch("bufferStatus"); + emit q->mediaStatusChanged(status); + break; + } + +} + +void QMediaPlayerPrivate::_q_error(int error, const QString &errorString) +{ + Q_Q(QMediaPlayer); + + this->error = QMediaPlayer::Error(error); + this->errorString = errorString; + + emit q->error(this->error); +} + +void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media) +{ + const QMediaPlayer::State currentState = state; + + filterStates = true; + control->setMedia(media, 0); + + if (!media.isNull()) { + switch (currentState) { + case QMediaPlayer::PlayingState: + control->play(); + break; + case QMediaPlayer::PausedState: + control->pause(); + break; + default: + break; + } + } + filterStates = false; + + state = control->state(); + + if (state != currentState) + emit q_func()->stateChanged(state); +} + +void QMediaPlayerPrivate::_q_playlistDestroyed() +{ + playlist = 0; + + control->setMedia(QMediaContent(), 0); +} + +static QMediaService *playerService(QMediaPlayer::Flags flags, QMediaServiceProvider *provider) +{ + if (flags && QMediaPlayer::LowLatency) + return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER, + QMediaServiceProviderHint(QMediaServiceProviderHint::LowLatencyPlayback)); + else + return provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER); +} + + +/*! + Construct a QMediaPlayer that uses the playback service from \a provider, + parented to \a parent and with \a flags. + + If a playback service is not specified the system default will be used. +*/ + +QMediaPlayer::QMediaPlayer(QObject *parent, QMediaPlayer::Flags flags, QMediaServiceProvider *provider): + QMediaObject(*new QMediaPlayerPrivate, + parent, + playerService(flags,provider)) +{ + Q_D(QMediaPlayer); + + d->provider = provider; + + if (d->service == 0) { + d->error = ServiceMissingError; + } else { + d->control = qobject_cast(d->service->control(QMediaPlayerControl_iid)); + d->playlistControl = qobject_cast(d->service->control(QMediaPlaylistControl_iid)); + if (d->control != 0) { + connect(d->control, SIGNAL(mediaChanged(QMediaContent)), SIGNAL(mediaChanged(QMediaContent))); + connect(d->control, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(_q_stateChanged(QMediaPlayer::State))); + connect(d->control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(d->control, SIGNAL(error(int,QString)), SLOT(_q_error(int,QString))); + + connect(d->control, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64))); + connect(d->control, SIGNAL(positionChanged(qint64)), SIGNAL(positionChanged(qint64))); + connect(d->control, SIGNAL(videoAvailableChanged(bool)), SIGNAL(videoAvailableChanged(bool))); + connect(d->control, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged(int))); + connect(d->control, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool))); + connect(d->control, SIGNAL(seekableChanged(bool)), SIGNAL(seekableChanged(bool))); + connect(d->control, SIGNAL(playbackRateChanged(qreal)), SIGNAL(playbackRateChanged(qreal))); + + if (d->control->state() == PlayingState) + addPropertyWatch("position"); + + if (d->control->mediaStatus() == StalledMedia || d->control->mediaStatus() == BufferingMedia) + addPropertyWatch("bufferStatus"); + } + } +} + + +/*! + Destroys the player object. +*/ + +QMediaPlayer::~QMediaPlayer() +{ + Q_D(QMediaPlayer); + + d->provider->releaseService(d->service); +} + +QMediaContent QMediaPlayer::media() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->media(); + + return QMediaContent(); +} + +/*! + Returns the stream source of media data. + + This is only valid if a stream was passed to setMedia(). + + \sa setMedia() +*/ + +const QIODevice *QMediaPlayer::mediaStream() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->mediaStream(); + + return 0; +} + +QMediaPlayer::State QMediaPlayer::state() const +{ + return d_func()->state; +} + +QMediaPlayer::MediaStatus QMediaPlayer::mediaStatus() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->mediaStatus(); + + return QMediaPlayer::UnknownMediaStatus; +} + +qint64 QMediaPlayer::duration() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->duration(); + + return -1; +} + +qint64 QMediaPlayer::position() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->position(); + + return 0; +} + +int QMediaPlayer::volume() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->volume(); + + return 0; +} + +bool QMediaPlayer::isMuted() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->isMuted(); + + return false; +} + +int QMediaPlayer::bufferStatus() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->bufferStatus(); + + return 0; +} + +bool QMediaPlayer::isVideoAvailable() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->isVideoAvailable(); + + return false; +} + +bool QMediaPlayer::isSeekable() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->isSeekable(); + + return false; +} + +qreal QMediaPlayer::playbackRate() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->playbackRate(); + + return 0.0; +} + +/*! + Returns the current error state. +*/ + +QMediaPlayer::Error QMediaPlayer::error() const +{ + return d_func()->error; +} + +QString QMediaPlayer::errorString() const +{ + return d_func()->errorString; +} + +//public Q_SLOTS: +/*! + Start or resume playing the current source. +*/ + +void QMediaPlayer::play() +{ + Q_D(QMediaPlayer); + + if (d->control == 0) { + QMetaObject::invokeMethod(this, "_q_error", Qt::QueuedConnection); + Q_ARG(int, QMediaPlayer::ServiceMissingError), + Q_ARG(QString, tr("The QMediaPlayer object does not have a valid service")); + return; + } + + //if playlist control is available, the service should advance itself + if (d->playlist && !d->playlistControl && d->playlist->currentIndex() == -1 && !d->playlist->isEmpty()) + d->playlist->setCurrentIndex(0); + + // Reset error conditions + d->error = NoError; + d->errorString = QString(); + + d->control->play(); +} + +/*! + Pause playing the current source. +*/ + +void QMediaPlayer::pause() +{ + Q_D(QMediaPlayer); + + if (d->control != 0) + d->control->pause(); +} + +/*! + Stop playing, and reset the play position to the beginning. +*/ + +void QMediaPlayer::stop() +{ + Q_D(QMediaPlayer); + + if (d->control != 0) + d->control->stop(); +} + +void QMediaPlayer::setPosition(qint64 position) +{ + Q_D(QMediaPlayer); + + if (d->control == 0 || !isSeekable()) + return; + + d->control->setPosition(qBound(qint64(0), duration(), position)); +} + +void QMediaPlayer::setVolume(int v) +{ + Q_D(QMediaPlayer); + + if (d->control == 0) + return; + + int clamped = qBound(0, v, 100); + if (clamped == volume()) + return; + + d->control->setVolume(clamped); +} + +void QMediaPlayer::setMuted(bool muted) +{ + Q_D(QMediaPlayer); + + if (d->control == 0 || muted == isMuted()) + return; + + d->control->setMuted(muted); +} + +void QMediaPlayer::setPlaybackRate(qreal rate) +{ + Q_D(QMediaPlayer); + + if (d->control != 0) + d->control->setPlaybackRate(rate); +} + +/*! + Sets the current \a media source. + + If a \a stream is supplied; media data will be read from it instead of resolving the media + source. In this case the media source may still be used to resolve additional information + about the media such as mime type. + + Setting the media to a null QMediaContent will cause the player to discard all + information relating to the current media source and to cease all I/O operations related + to that media. +*/ + +void QMediaPlayer::setMedia(const QMediaContent &media, QIODevice *stream) +{ + Q_D(QMediaPlayer); + + if (d->control != 0) + d_func()->control->setMedia(media, stream); +} + +/*! + \internal +*/ + +void QMediaPlayer::bind(QObject *obj) +{ + Q_D(QMediaPlayer); + + if (d->control != 0) { + QMediaPlaylist *playlist = qobject_cast(obj); + + if (playlist) { + if (d->playlist) + d->playlist->setMediaObject(0); + + d->playlist = playlist; + connect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)), + this, SLOT(_q_updateMedia(QMediaContent))); + connect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed())); + + setMedia(playlist->currentMedia()); + + return; + } + + QVideoWidget *videoWidget = qobject_cast(obj); + QGraphicsVideoItem *videoItem = qobject_cast(obj); + + if (videoWidget || videoItem) { + //detach the current video output + if (d->videoWidget) { + d->videoWidget->setMediaObject(0); + d->videoWidget = 0; + } + + if (d->videoItem) { + d->videoItem->setMediaObject(0); + d->videoItem = 0; + } + } + + if (videoWidget) + d->videoWidget = videoWidget; + + if (videoItem) + d->videoItem = videoItem; + } +} + +/*! + \internal +*/ + +void QMediaPlayer::unbind(QObject *obj) +{ + Q_D(QMediaPlayer); + + if (obj == d->videoWidget) { + d->videoWidget = 0; + } else if (obj == d->videoItem) { + d->videoItem = 0; + } else if (obj == d->playlist) { + disconnect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)), + this, SLOT(_q_updateMedia(QMediaContent))); + disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed())); + d->playlist = 0; + setMedia(QMediaContent()); + } +} + +/*! + Returns the level of support a media player has for a \a mimeType and a set of \a codecs. + + The \a flags argument allows additional requirements such as performance indicators to be + specified. +*/ +QtMedia::SupportEstimate QMediaPlayer::hasSupport(const QString &mimeType, + const QStringList& codecs, + Flags flags) +{ + return QMediaServiceProvider::defaultServiceProvider()->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), + mimeType, + codecs, + flags); +} + +/*! + Returns a list of MIME types supported by the media player. + + The \a flags argument causes the resultant list to be restricted to MIME types which can be supported + given additional requirements, such as performance indicators. +*/ +QStringList QMediaPlayer::supportedMimeTypes(Flags flags) +{ + return QMediaServiceProvider::defaultServiceProvider()->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), + flags); +} + + +// Enums +/*! + \enum QMediaPlayer::State + + Defines the current state of a media player. + + \value PlayingState The media player is currently playing content. + \value PausedState The media player has paused playback, playback of the current track will + resume from the position the player was paused at. + \value StoppedState The media player is not playing content, playback will begin from the start + of the current track. +*/ + +/*! + \enum QMediaPlayer::MediaStatus + + Defines the status of a media player's current media. + + \value UnknownMediaStatus The status of the media cannot be determined. + \value NoMedia The is no current media. The player is in the StoppedState. + \value LoadingMedia The current media is being loaded. The player may be in any state. + \value LoadedMedia The current media has been loaded. The player is in the StoppedState. + \value StalledMedia Playback of the current media has stalled due to insufficient buffering or + some other temporary interruption. The player is in the PlayingState or PausedState. + \value BufferingMedia The player is buffering data but has enough data buffered for playback to + continue for the immediate future. The player is in the PlayingState or PausedState. + \value BufferedMedia The player has fully buffered the current media. The player is in the + PlayingState or PausedState. + \value EndOfMedia Playback has reached the end of the current media. The player is in the + StoppedState. + \value InvalidMedia The current media cannot be played. The player is in the StoppedState. +*/ + +/*! + \enum QMediaPlayer::Error + + Defines a media player error condition. + + \value NoError No error has occurred. + \value ResourceError A media resource couldn't be resolved. + \value FormatError The format of a media resource isn't (fully) supported. Playback may still + be possible, but without an audio or video component. + \value NetworkError A network error occurred. + \value AccessDeniedError There are not the appropriate permissions to play a media resource. + \value ServiceMissingError A valid playback service was not found, playback cannot proceed. +*/ + +// Signals +/*! + \fn QMediaPlayer::error(QMediaPlayer::Error error) + + Signals that an \a error condition has occurred. + + \sa errorString() +*/ + +/*! + \fn void QMediaPlayer::stateChanged(State state) + + Signal the \a state of the Player object has changed. +*/ + +/*! + \fn QMediaPlayer::mediaStatusChanged(QMediaPlayer::MediaStatus status) + + Signals that the \a status of the current media has changed. + + \sa mediaStatus() +*/ + +/*! + \fn void QMediaPlayer::mediaChanged(const QMediaContent &media); + + Signals that the current playing content will be obtained from \a media. + + \sa media() +*/ + +/*! + \fn void QMediaPlayer::playbackRateChanged(qreal rate); + + Signals the playbackRate has changed to \a rate. +*/ + +/*! + \fn void QMediaPlayer::seekableChanged(bool seekable); + + Signals the \a seekable status of the player object has changed. +*/ + +// Properties +/*! + \property QMediaPlayer::state + \brief the media player's playback state. + + By default this property is QMediaPlayer::Stopped + + \sa mediaStatus(), play(), pause(), stop() +*/ + +/*! + \property QMediaPlayer::error + \brief a string describing the last error condition. + + \sa error() +*/ + +/*! + \property QMediaPlayer::media + \brief the active media source being used by the player object. + + The player object will use the QMediaContent for selection of the content to + be played. + + By default this property has a null QMediaContent. + + Setting this property to a null QMediaContent will cause the player to discard all + information relating to the current media source and to cease all I/O operations related + to that media. + + \sa QMediaContent +*/ + +/*! + \property QMediaPlayer::mediaStatus + \brief the status of the current media stream. + + The stream status describes how the playback of the current stream is + progressing. + + By default this property is QMediaPlayer::NoMedia + + \sa state +*/ + +/*! + \property QMediaPlayer::duration + \brief the duration of the current media. + + The value is the total playback time in milliseconds of the current media. + The value may change across the life time of the QMediaPlayer object and + may not be available when initial playback begins, connect to the + durationChanged() signal to receive status notifications. +*/ + +/*! + \property QMediaPlayer::position + \brief the playback position of the current media. + + The value is the current playback position, expressed in milliseconds since + the beginning of the media. Periodically changes in the position will be + indicated with the signal positionChanged(), the interval between updates + can be set with QMediaObject's method setNotifyInterval(). +*/ + +/*! + \property QMediaPlayer::volume + \brief the current playback volume. + + The playback volume is a linear in effect and the value can range from 0 - + 100, values outside this range will be clamped. +*/ + +/*! + \property QMediaPlayer::muted + \brief the muted state of the current media. + + The value will be true if the playback volume is muted; otherwise false. +*/ + +/*! + \property QMediaPlayer::bufferStatus + \brief the percentage of the temporary buffer filled before playback begins. + + When the player object is buffering; this property holds the percentage of + the temporary buffer that is filled. The buffer will need to reach 100% + filled before playback can resume, at which time the MediaStatus will be + BufferedMedia. + + \sa mediaStatus() +*/ + +/*! + \property QMediaPlayer::videoAvailable + \brief the video availability status for the current media. + + If available, the QVideoWidget class can be used to view the video. As the + life time of QMediaPlayer can be longer than the playback of one + QMediaContent, this property may change over time, the + videoAvailableChanged signal can be used to monitor it's status. + + \sa QVideoWidget, QMediaContent +*/ + +/*! + \property QMediaPlayer::seekable + \brief the seek-able status of the current media + + If seeking is supported this property will be true; false otherwise. The + status of this property may change across the life time of the QMediaPlayer + object, use the seekableChanged signal to monitor changes. +*/ + +/*! + \property QMediaPlayer::playbackRate + \brief the playback rate of the current media. + + This value is a multiplier applied to the media's standard play rate. By + default this value is 1.0, indicating that the media is playing at the + standard pace. Values higher than 1.0 will increase the rate of play. + Values less than zero can be set and indicate the media will rewind at the + multiplier of the standard pace. + + Not all playback services support change of the playback rate. It is + framework defined as to the status and quality of audio and video + while fast forwarding or rewinding. +*/ + +/*! + \fn void QMediaPlayer::durationChanged(qint64 duration) + + Signal the duration of the content has changed to \a duration, expressed in milliseconds. +*/ + +/*! + \fn void QMediaPlayer::positionChanged(qint64 position) + + Signal the position of the content has changed to \a position, expressed in + milliseconds. +*/ + +/*! + \fn void QMediaPlayer::volumeChanged(int volume) + + Signal the playback volume has changed to \a volume. +*/ + +/*! + \fn void QMediaPlayer::mutedChanged(bool muted) + + Signal the mute state has changed to \a muted. +*/ + +/*! + \fn void QMediaPlayer::videoAvailableChanged(bool videoAvailable) + + Signal the availability of visual content has changed to \a videoAvailable. +*/ + +/*! + \fn void QMediaPlayer::bufferStatusChanged(int percentFilled) + + Signal the amount of the local buffer filled as a percentage by \a percentFilled. +*/ + +/*! + \enum QMediaPlayer::Flag + + \value LowLatency + The player is expected to be used with simple audio formats, + but playback should start without significant delay. + Such playback service can be used for beeps, ringtones, etc. +*/ + +#include "moc_qmediaplayer.cpp" + +QT_END_NAMESPACE + +QT_END_NAMESPACE + diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h new file mode 100644 index 0000000..4de2b5e --- /dev/null +++ b/src/multimedia/playback/qmediaplayer.h @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYER_H +#define QMEDIAPLAYER_H + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QMediaPlaylist; + +class QMediaPlayerPrivate; +class Q_MULTIMEDIA_EXPORT QMediaPlayer : public QMediaObject +{ + Q_OBJECT + Q_PROPERTY(QMediaContent media READ media WRITE setMedia NOTIFY mediaChanged) + Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged) + Q_PROPERTY(qint64 position READ position WRITE setPosition NOTIFY positionChanged) + Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) + Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) + Q_PROPERTY(int bufferStatus READ bufferStatus NOTIFY bufferStatusChanged) + Q_PROPERTY(bool videoAvailable READ isVideoAvailable NOTIFY videoAvailableChanged) + Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged) + Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged) + Q_PROPERTY(State state READ state NOTIFY stateChanged) + Q_PROPERTY(MediaStatus mediaStatus READ mediaStatus NOTIFY mediaStatusChanged) + Q_PROPERTY(QString error READ errorString) + Q_ENUMS(State) + Q_ENUMS(MediaStatus) + +public: + enum State + { + StoppedState, + PlayingState, + PausedState + }; + + enum MediaStatus + { + UnknownMediaStatus, + NoMedia, + LoadingMedia, + LoadedMedia, + StalledMedia, + BufferingMedia, + BufferedMedia, + EndOfMedia, + InvalidMedia + }; + + enum Flag + { + LowLatency = 0x01 + }; + Q_DECLARE_FLAGS(Flags, Flag) + + enum Error + { + NoError, + ResourceError, + FormatError, + NetworkError, + AccessDeniedError, + ServiceMissingError + }; + + QMediaPlayer(QObject *parent = 0, Flags flags = 0, QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider()); + ~QMediaPlayer(); + + static QtMedia::SupportEstimate hasSupport(const QString &mimeType, + const QStringList& codecs = QStringList(), + Flags flags = 0); + static QStringList supportedMimeTypes(Flags flags = 0); + + QMediaContent media() const; + const QIODevice *mediaStream() const; + + State state() const; + MediaStatus mediaStatus() const; + + qint64 duration() const; + qint64 position() const; + + int volume() const; + bool isMuted() const; + bool isVideoAvailable() const; + + int bufferStatus() const; + + bool isSeekable() const; + qreal playbackRate() const; + + Error error() const; + QString errorString() const; + +public Q_SLOTS: + void play(); + void pause(); + void stop(); + + void setPosition(qint64 position); + void setVolume(int volume); + void setMuted(bool muted); + + void setPlaybackRate(qreal rate); + + void setMedia(const QMediaContent &media, QIODevice *stream = 0); + +Q_SIGNALS: + void mediaChanged(const QMediaContent &media); + + void stateChanged(QMediaPlayer::State newState); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + + void durationChanged(qint64 duration); + void positionChanged(qint64 position); + + void volumeChanged(int volume); + void mutedChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + + void bufferStatusChanged(int percentFilled); + + void seekableChanged(bool seekable); + void playbackRateChanged(qreal rate); + + void error(QMediaPlayer::Error error); + +public: + virtual void bind(QObject*); + virtual void unbind(QObject*); + +private: + Q_DISABLE_COPY(QMediaPlayer) + Q_DECLARE_PRIVATE(QMediaPlayer) + Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QMediaPlayer::State)) + Q_PRIVATE_SLOT(d_func(), void _q_mediaStatusChanged(QMediaPlayer::MediaStatus)) + Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &)) + Q_PRIVATE_SLOT(d_func(), void _q_updateMedia(const QMediaContent&)) + Q_PRIVATE_SLOT(d_func(), void _q_playlistDestroyed()) +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlayer::State)) +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlayer::MediaStatus)) +Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlayer::Error)) + +QT_END_HEADER + +#endif // QMEDIAPLAYER_H diff --git a/src/multimedia/playback/qmediaplayercontrol.cpp b/src/multimedia/playback/qmediaplayercontrol.cpp new file mode 100644 index 0000000..90e3a8c --- /dev/null +++ b/src/multimedia/playback/qmediaplayercontrol.cpp @@ -0,0 +1,362 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + + +QT_BEGIN_NAMESPACE + + +/*! + \class QMediaPlayerControl + \ingroup multimedia-serv + + \preliminary + \brief The QMediaPlayerControl class provides access to the media playing + functionality of a QMediaService. + + If a QMediaService can play media is will implement QMediaPlayerControl. + This control provides a means to set the \l {setMedia()}{media} to play, + \l {play()}{start}, \l {pause()} {pause} and \l {stop()}{stop} playback, + \l {setPosition()}{seek}, and control the \l {setVolume()}{volume}. + It also provides feedback on the \l {duration()}{duration} of the media, + the current \l {position()}{position}, and \l {bufferStatus()}{buffering} + progress. + + The functionality provided by this control is exposed to application + code through the QMediaPlayer class. + + The interface name of QMediaPlayerControl is \c com.nokia.Qt.QMediaPlayerControl/1.0 as + defined in QMediaPlayerControl_iid. + + \sa QMediaService::control(), QMediaPlayer +*/ + +/*! + \macro QMediaPlayerControl_iid + + \c com.nokia.Qt.QMediaPlayerControl/1.0 + + Defines the interface name of the QMediaPlayerControl class. + + \relates QMediaPlayerControl +*/ + +/*! + Destroys a media player control. +*/ +QMediaPlayerControl::~QMediaPlayerControl() +{ +} + +/*! + Constructs a new media player control with the given \a parent. +*/ +QMediaPlayerControl::QMediaPlayerControl(QObject *parent): + QMediaControl(*new QMediaControlPrivate, parent) +{ +} + +/*! + \fn QMediaPlayerControl::state() const + + Returns the state of a player control. +*/ + +/*! + \fn QMediaPlayerControl::stateChanged(QMediaPlayer::State state) + + Signals that the \a state of a player control has changed. + + \sa state() +*/ + +/*! + \fn QMediaPlayerControl::mediaStatus() const + + Returns the status of the current media. +*/ + +/*! + \fn QMediaPlayerControl::mediaStatusChanged(QMediaPlayer::MediaStatus status) + + Signals that the \a status of the current media has changed. + + \sa mediaStatus() +*/ + + +/*! + \fn QMediaPlayerControl::duration() const + + Returns the duration of the current media in milliseconds. +*/ + +/*! + \fn QMediaPlayerControl::durationChanged(qint64 duration) + + Signals that the \a duration of the current media has changed. + + \sa duration() +*/ + +/*! + \fn QMediaPlayerControl::position() const + + Returns the current playback position in milliseconds. +*/ + +/*! + \fn QMediaPlayerControl::setPosition(qint64 position) + + Sets the playback \a position of the current media. This will initiate a seek and it may take + some time for playback to reach the position set. +*/ + +/*! + \fn QMediaPlayerControl::positionChanged(qint64 position) + + Signals the playback \a position has changed. + + This is only emitted in when there has been a discontinous change in the playback postion, such + as a seek or the position being reset. + + \sa position() +*/ + +/*! + \fn QMediaPlayerControl::volume() const + + Returns the audio volume of a player control. +*/ + +/*! + \fn QMediaPlayerControl::setVolume(int volume) + + Sets the audio \a volume of a player control. +*/ + +/*! + \fn QMediaPlayerControl::volumeChanged(int volume) + + Signals the audio \a volume of a player control has changed. + + \sa volume() +*/ + +/*! + \fn QMediaPlayerControl::isMuted() const + + Returns the mute state of a player control. +*/ + +/*! + \fn QMediaPlayerControl::setMuted(bool mute) + + Sets the \a mute state of a player control. +*/ + +/*! + \fn QMediaPlayerControl::mutedChanged(bool mute) + + Signals a change in the \a mute status of a player control. + + \sa isMuted() +*/ + +/*! + \fn QMediaPlayerControl::bufferStatus() const + + Returns the buffering progress of the current media. Progress is measured in the percentage + of the buffer filled. +*/ + +/*! + \fn QMediaPlayerControl::bufferStatusChanged(int progress) + + Signals that buffering \a progress has changed. + + \sa bufferStatus() +*/ + +/*! + \fn QMediaPlayerControl::isVideoAvailable() const + + Identifies if there is video output available for the current media. + + Returns true if video output is available and false otherwise. +*/ + +/*! + \fn QMediaPlayerControl::videoAvailableChanged(bool video) + + Signals that there has been a change in the availability of \a video output. + + \sa isVideoAvailable() +*/ + +/*! + \fn QMediaPlayerControl::isSeekable() const + + Identifies if the current media is seekable. + + Returns true if it possible to seek within the current media, and false otherwise. +*/ + +/*! + \fn QMediaPlayerControl::seekableChanged(bool seekable) + + Signals that the \a seekable state of a player control has changed. + + \sa isSeekable() +*/ + +/*! + \fn QMediaPlayerControl::availablePlaybackRanges() const + + Returns a range of times in milliseconds that can be played back. + + Usually for local files this is a continuous interval equal to [0..duration()] + or an empty time range if seeking is not supported, but for network sources + it refers to the buffered parts of the media. +*/ + +/*! + \fn QMediaPlayerControl::availablePlaybackRangesChanged(const QMediaTimeRange &ranges) + + Signals that the available media playback \a ranges have changed. + + \sa QMediaPlayerControl::availablePlaybackRanges() +*/ + +/*! + \fn qreal QMediaPlayerControl::playbackRate() const + + Returns the rate of playback. +*/ + +/*! + \fn QMediaPlayerControl::setPlaybackRate(qreal rate) + + Sets the \a rate of playback. +*/ + +/*! + \fn QMediaPlayerControl::media() const + + Returns the current media source. +*/ + +/*! + \fn QMediaPlayerControl::mediaStream() const + + Returns the current media stream. This is only a valid if a stream was passed to setMedia(). + + \sa setMedia() +*/ + +/*! + \fn QMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream) + + Sets the current \a media source. If a \a stream is supplied; data will be read from that + instead of attempting to resolve the media source. The media source may still be used to + supply media information such as mime type. + + Setting the media to a null QMediaContent will cause the control to discard all + information relating to the current media source and to cease all I/O operations related + to that media. +*/ + +/*! + \fn QMediaPlayerControl::mediaChanged(const QMediaContent& content) + + Signals that the current media \a content has changed. +*/ + +/*! + \fn QMediaPlayerControl::play() + + Starts playback of the current media. + + If successful the player control will immediately enter the \l {QMediaPlayer::PlayingState} + {playing} state. + + \sa state() +*/ + +/*! + \fn QMediaPlayerControl::pause() + + Pauses playback of the current media. + + If sucessful the player control will immediately enter the \l {QMediaPlayer::PausedState} + {paused} state. + + \sa state(), play(), stop() +*/ + +/*! + \fn QMediaPlayerControl::stop() + + Stops playback of the current media. + + If succesful the player control will immediately enter the \l {QMediaPlayer::StoppedState} + {stopped} state. +*/ + +/*! + \fn QMediaPlayerControl::error(int error, const QString &errorString) + + Signals that an \a error has occurred. The \a errorString provides a more detailed explanation. +*/ + +/*! + \fn QMediaPlayerControl::playbackRateChanged(qreal rate) + + Signal emitted when playback rate changes to \a rate. +*/ + +QT_END_NAMESPACE + +#include "moc_qmediaplayercontrol.cpp" + diff --git a/src/multimedia/playback/qmediaplayercontrol.h b/src/multimedia/playback/qmediaplayercontrol.h new file mode 100644 index 0000000..ac3fc45 --- /dev/null +++ b/src/multimedia/playback/qmediaplayercontrol.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMEDIAPLAYERCONTROL_H +#define QMEDIAPLAYERCONTROL_H + +#include + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + + +class QMediaPlaylist; + +class Q_MULTIMEDIA_EXPORT QMediaPlayerControl : public QMediaControl +{ + Q_OBJECT + +public: + ~QMediaPlayerControl(); + + virtual QMediaPlayer::State state() const = 0; + + virtual QMediaPlayer::MediaStatus mediaStatus() const = 0; + + virtual qint64 duration() const = 0; + + virtual qint64 position() const = 0; + virtual void setPosition(qint64 position) = 0; + + virtual int volume() const = 0; + virtual void setVolume(int volume) = 0; + + virtual bool isMuted() const = 0; + virtual void setMuted(bool muted) = 0; + + virtual int bufferStatus() const = 0; + + virtual bool isVideoAvailable() const = 0; + + virtual bool isSeekable() const = 0; + + virtual QMediaTimeRange availablePlaybackRanges() const = 0; + + virtual qreal playbackRate() const = 0; + virtual void setPlaybackRate(qreal rate) = 0; + + virtual QMediaContent media() const = 0; + virtual const QIODevice *mediaStream() const = 0; + virtual void setMedia(const QMediaContent &media, QIODevice *stream) = 0; + + virtual void play() = 0; + virtual void pause() = 0; + virtual void stop() = 0; + +Q_SIGNALS: + void mediaChanged(const QMediaContent& content); + void durationChanged(qint64 duration); + void positionChanged(qint64 position); + void stateChanged(QMediaPlayer::State newState); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + void bufferStatusChanged(int percentFilled); + void seekableChanged(bool); + void availablePlaybackRangesChanged(const QMediaTimeRange&); + void playbackRateChanged(qreal rate); + void error(int error, const QString &errorString); + +protected: + QMediaPlayerControl(QObject* parent = 0); +}; + +#define QMediaPlayerControl_iid "com.nokia.Qt.QMediaPlayerControl/1.0" +Q_MEDIA_DECLARE_CONTROL(QMediaPlayerControl, QMediaPlayerControl_iid) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMEDIAPLAYERCONTROL_H + diff --git a/src/multimedia/qml/qml.pri b/src/multimedia/qml/qml.pri new file mode 100644 index 0000000..adfcc23 --- /dev/null +++ b/src/multimedia/qml/qml.pri @@ -0,0 +1,11 @@ + +contains(QT_CONFIG, declarative) { + QT += declarative + + HEADERS += \ + $$PWD/qmlsound_p.h + + SOURCES += \ + $$PWD/qmlsound.cpp +} + diff --git a/src/multimedia/qml/qmlsound.cpp b/src/multimedia/qml/qmlsound.cpp new file mode 100644 index 0000000..6b01418 --- /dev/null +++ b/src/multimedia/qml/qmlsound.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlsound_p.h" + +#include + + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt,4,6,Sound,QmlSound) + +QmlSound::QmlSound(QObject *parent) : + QObject(parent), + m_loopCount(1), + m_volume(100), + m_muted(false), + m_runningCount(0), + m_player(0) +{ +} + +QmlSound::~QmlSound() +{ + delete m_player; +} + +QUrl QmlSound::source() const +{ + return m_player != 0 ? m_player->media().canonicalUrl() : QUrl(); +} + +void QmlSound::setSource(const QUrl &url) +{ + if (m_player != 0 && m_player->media().canonicalUrl() == url) + return; + + if (m_player == 0) { + m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency); + m_player->setVolume(m_volume); + m_player->setMuted(m_muted); + + connect(m_player, SIGNAL(volumeChanged()), SIGNAL(volumeChanged())); + connect(m_player, SIGNAL(mutedChanged()), SIGNAL(mutedChanged())); + connect(m_player, SIGNAL(durationChanged()), SIGNAL(durationChanged())); + connect(m_player, SIGNAL(stateChanged()), SLOT(repeat())); + } + + m_player->setMedia(url); + if (url.isEmpty()) + return; + + emit sourceChanged(); +} + +int QmlSound::loopCount() const +{ + return m_loopCount; +} + +void QmlSound::setLoopCount(int loopCount) +{ + if (m_loopCount == loopCount) + return; + + m_loopCount = loopCount; + emit loopCountChanged(); +} + +int QmlSound::volume() const +{ + return m_player != 0 ? m_player->volume() : m_volume; +} + +void QmlSound::setVolume(int volume) +{ + if (m_volume == volume) + return; + + m_volume = volume; + if (m_player != 0) + m_player->setVolume(volume); + else + emit volumeChanged(); +} + +bool QmlSound::isMuted() const +{ + return m_player != 0 ? m_player->isMuted() : m_muted; +} + +void QmlSound::setMuted(bool muted) +{ + if (m_muted == muted) + return; + + m_muted = muted; + if (m_player != 0) + m_player->setMuted(muted); + else + emit mutedChanged(); +} + +int QmlSound::duration() const +{ + return m_player != 0 ? m_player->duration() : 0; +} + +void QmlSound::play() +{ + m_runningCount = 0; + if (m_player != 0) + m_player->play(); +} + +void QmlSound::stop() +{ + if (m_player != 0) + m_player->stop(); +} + +void QmlSound::repeat() +{ + if (m_player->state() == QMediaPlayer::StoppedState) { + if (++m_runningCount < m_loopCount) + m_player->play(); + } +} + +QT_END_NAMESPACE diff --git a/src/multimedia/qml/qmlsound_p.h b/src/multimedia/qml/qmlsound_p.h new file mode 100644 index 0000000..3c17413 --- /dev/null +++ b/src/multimedia/qml/qmlsound_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLSOUND_H +#define QMLSOUND_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Multimedia) + +class QMediaPlayer; + +class QmlSound : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount NOTIFY loopCountChanged) + Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) + Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) + Q_PROPERTY(int duration READ duration NOTIFY durationChanged) + +public: + explicit QmlSound(QObject *parent = 0); + ~QmlSound(); + + QUrl source() const; + void setSource(const QUrl &url); + + int loopCount() const; + void setLoopCount(int loopCount); + + int volume() const; + void setVolume(int volume); + + bool isMuted() const; + void setMuted(bool muted); + + int duration() const; + +signals: + void sourceChanged(); + void loopCountChanged(); + void volumeChanged(); + void mutedChanged(); + void durationChanged(); + +public slots: + void play(); + void stop(); + +private slots: + void repeat(); + +private: + Q_DISABLE_COPY(QmlSound) + + int m_loopCount; + int m_volume; + bool m_muted; + int m_runningCount; + QMediaPlayer *m_player; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +QML_DECLARE_TYPE(QmlSound) + +#endif // QMLSOUND_H diff --git a/src/plugins/mediaservices/mediaservices.pro b/src/plugins/mediaservices/mediaservices.pro new file mode 100644 index 0000000..765477d --- /dev/null +++ b/src/plugins/mediaservices/mediaservices.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS += qt7 + + diff --git a/src/plugins/mediaservices/qt7/qcvdisplaylink.h b/src/plugins/mediaservices/qt7/qcvdisplaylink.h new file mode 100644 index 0000000..5cd8f73 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qcvdisplaylink.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCVDISPLAYLINK_H +#define QCVDISPLAYLINK_H + +#include +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QCvDisplayLink : public QObject +{ +Q_OBJECT +public: + QCvDisplayLink(QObject *parent = 0); + virtual ~QCvDisplayLink(); + + bool isValid(); + bool isActive() const; + +public slots: + void start(); + void stop(); + +signals: + void tick(const CVTimeStamp &ts); + +public: + void displayLinkEvent(const CVTimeStamp *); + +protected: + virtual bool event(QEvent *); + +private: + CVDisplayLinkRef m_displayLink; + QMutex m_displayLinkMutex; + bool m_pendingDisplayLinkEvent; + bool m_isActive; + CVTimeStamp m_frameTimeStamp; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/plugins/mediaservices/qt7/qcvdisplaylink.mm b/src/plugins/mediaservices/qt7/qcvdisplaylink.mm new file mode 100644 index 0000000..98ae71d --- /dev/null +++ b/src/plugins/mediaservices/qt7/qcvdisplaylink.mm @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcvdisplaylink.h" + +#include +#include + + +QT_USE_NAMESPACE + +static CVReturn CVDisplayLinkCallback(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + Q_UNUSED(displayLink); + Q_UNUSED(inNow); + Q_UNUSED(flagsIn); + Q_UNUSED(flagsOut); + + QCvDisplayLink *link = (QCvDisplayLink *)displayLinkContext; + + link->displayLinkEvent(inOutputTime); + return kCVReturnSuccess; +} + + +QCvDisplayLink::QCvDisplayLink(QObject *parent) + :QObject(parent), + m_pendingDisplayLinkEvent(false), + m_isActive(false) +{ + // create display link for the main display + CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink); + if (m_displayLink) { + // set the current display of a display link. + CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay); + + // set the renderer output callback function + CVDisplayLinkSetOutputCallback(m_displayLink, &CVDisplayLinkCallback, this); + } +} + +QCvDisplayLink::~QCvDisplayLink() +{ + if (m_displayLink) { + CVDisplayLinkStop(m_displayLink); + CVDisplayLinkRelease(m_displayLink); + m_displayLink = NULL; + } +} + +bool QCvDisplayLink::isValid() +{ + return m_displayLink != 0; +} + +bool QCvDisplayLink::isActive() const +{ + return m_isActive; +} + +void QCvDisplayLink::start() +{ + if (m_displayLink && !m_isActive) { + CVDisplayLinkStart(m_displayLink); + m_isActive = true; + } +} + +void QCvDisplayLink::stop() +{ + if (m_displayLink && m_isActive) { + CVDisplayLinkStop(m_displayLink); + m_isActive = false; + } +} + +void QCvDisplayLink::displayLinkEvent(const CVTimeStamp *ts) +{ + // This function is called from a + // thread != gui thread. So we post the event. + // But we need to make sure that we don't post faster + // than the event loop can eat: + m_displayLinkMutex.lock(); + bool pending = m_pendingDisplayLinkEvent; + m_pendingDisplayLinkEvent = true; + m_frameTimeStamp = *ts; + m_displayLinkMutex.unlock(); + + if (!pending) + qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority); +} + +bool QCvDisplayLink::event(QEvent *event) +{ + switch (event->type()){ + case QEvent::User: { + m_displayLinkMutex.lock(); + m_pendingDisplayLinkEvent = false; + CVTimeStamp ts = m_frameTimeStamp; + m_displayLinkMutex.unlock(); + + emit tick(ts); + + return false; + } + break; + default: + break; + } + return QObject::event(event); +} + +QT_END_NAMESPACE + +#include "moc_qcvdisplaylink.cpp" + diff --git a/src/plugins/mediaservices/qt7/qt7.pro b/src/plugins/mediaservices/qt7/qt7.pro new file mode 100644 index 0000000..938bc97 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7.pro @@ -0,0 +1,52 @@ +TARGET = qt7 +include(../../qpluginbase.pri) + +QT += opengl multimedia + +LIBS += -framework AppKit -framework AudioUnit \ + -framework AudioToolbox -framework CoreAudio \ + -framework QuartzCore -framework QTKit + +# The Quicktime framework is only awailable for 32-bit builds, so we +# need to check for this before linking against it. +# QMAKE_MAC_XARCH is not awailable on Tiger, but at the same time, +# we never build for 64-bit architechtures on Tiger either: +contains(QMAKE_MAC_XARCH, no) { + LIBS += -framework QuickTime +} else { + LIBS += -Xarch_i386 -framework QuickTime -Xarch_ppc -framework QuickTime +} + +HEADERS += \ + qt7backend.h \ + qt7playercontrol.h \ + qt7videooutputcontrol.h \ + qt7movieviewoutput.h \ + qt7movievideowidget.h \ + qt7movieviewrenderer.h \ + qt7playersession.h \ + qt7playerservice.h \ + qt7serviceplugin.h \ + qt7movierenderer.h \ + qt7playermetadata.h \ + qcvdisplaylink.h + +OBJECTIVE_SOURCES += \ + qt7backend.mm \ + qt7playersession.mm \ + qt7serviceplugin.mm \ + qt7movieviewoutput.mm \ + qt7movievideowidget.mm \ + qt7movieviewrenderer.mm \ + qt7playermetadata.mm \ + qt7movierenderer.mm \ + qt7playercontrol.mm \ + qt7videooutputcontrol.mm \ + qt7playerservice.mm \ + qcvdisplaylink.mm + + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/mediaservices +target.path = $$[QT_INSTALL_PLUGINS]/plugins/mediaservices +INSTALLS += target + diff --git a/src/plugins/mediaservices/qt7/qt7backend.h b/src/plugins/mediaservices/qt7/qt7backend.h new file mode 100644 index 0000000..5668965 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7backend.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7BACKEND_H +#define QT7BACKEND_H + +#include + +#ifndef Q_WS_MAC64 +#define QUICKTIME_C_API_AVAILABLE +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class AutoReleasePool +{ +private: + void *pool; +public: + AutoReleasePool(); + ~AutoReleasePool(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7backend.mm b/src/plugins/mediaservices/qt7/qt7backend.mm new file mode 100644 index 0000000..478589b --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7backend.mm @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt7backend.h" + +#import +#include + + +QT_BEGIN_NAMESPACE + +AutoReleasePool::AutoReleasePool() +{ + pool = (void*)[[NSAutoreleasePool alloc] init]; +} + +AutoReleasePool::~AutoReleasePool() +{ + [(NSAutoreleasePool*)pool release]; +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.h b/src/plugins/mediaservices/qt7/qt7movierenderer.h new file mode 100644 index 0000000..4543152 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movierenderer.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7MOVIERENDERER_H +#define QT7MOVIERENDERER_H + +#include "qt7backend.h" + +#include +#include + +#include +#include + +#include +#include "qt7videooutputcontrol.h" + +#include +#include + + +QT_BEGIN_HEADER + +class QGLContext; + +QT_BEGIN_NAMESPACE + +class QCvDisplayLink; +class QT7PlayerSession; +class QT7PlayerService; + +class QT7MovieRenderer : public QT7VideoRendererControl +{ +Q_OBJECT +public: + QT7MovieRenderer(QObject *parent = 0); + virtual ~QT7MovieRenderer(); + + void setEnabled(bool); + void setMovie(void *movie); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + QSize nativeSize() const; + +private slots: + void updateVideoFrame(const CVTimeStamp &ts); + +private: + void setupVideoOutput(); + bool createPixelBufferVisualContext(); + bool createGLVisualContext(); + + void *m_movie; + + QMutex m_mutex; + + QCvDisplayLink *m_displayLink; +#ifdef QUICKTIME_C_API_AVAILABLE + QTVisualContextRef m_visualContext; + bool m_usingGLContext; + const QGLContext *m_currentGLContext; + QSize m_pixelBufferContextGeometry; +#endif + QAbstractVideoSurface *m_surface; + QSize m_nativeSize; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.mm b/src/plugins/mediaservices/qt7/qt7movierenderer.mm new file mode 100644 index 0000000..8cb0f46 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movierenderer.mm @@ -0,0 +1,441 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import + +#include "qt7backend.h" + +#include "qt7playercontrol.h" +#include "qt7movierenderer.h" +#include "qt7playersession.h" +#include "qcvdisplaylink.h" +#include +#include + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class CVGLTextureVideoBuffer : public QAbstractVideoBuffer +{ +public: + CVGLTextureVideoBuffer(CVOpenGLTextureRef buffer) + : QAbstractVideoBuffer(NoHandle) + , m_buffer(buffer) + , m_mode(NotMapped) + { + CVOpenGLTextureRetain(m_buffer); + } + + virtual ~CVGLTextureVideoBuffer() + { + CVOpenGLTextureRelease(m_buffer); + } + + QVariant handle() const + { + GLuint id = CVOpenGLTextureGetName(m_buffer); + return QVariant(int(id)); + } + + HandleType handleType() const + { + return GLTextureHandle; + } + + MapMode mapMode() const { return m_mode; } + + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + { + if (numBytes) + *numBytes = 0; + + if (bytesPerLine) + *bytesPerLine = 0; + + m_mode = mode; + return 0; + } + + void unmap() { m_mode = NotMapped; } + +private: + CVOpenGLTextureRef m_buffer; + MapMode m_mode; +}; + + +class CVPixelBufferVideoBuffer : public QAbstractVideoBuffer +{ +public: + CVPixelBufferVideoBuffer(CVPixelBufferRef buffer) + : QAbstractVideoBuffer(NoHandle) + , m_buffer(buffer) + , m_mode(NotMapped) + { + CVPixelBufferRetain(m_buffer); + } + + virtual ~CVPixelBufferVideoBuffer() + { + CVPixelBufferRelease(m_buffer); + } + + MapMode mapMode() const { return m_mode; } + + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + { + if (mode != NotMapped && m_mode == NotMapped) { + CVPixelBufferLockBaseAddress(m_buffer, 0); + + if (numBytes) + *numBytes = CVPixelBufferGetDataSize(m_buffer); + + if (bytesPerLine) + *bytesPerLine = CVPixelBufferGetBytesPerRow(m_buffer); + + m_mode = mode; + + return (uchar*)CVPixelBufferGetBaseAddress(m_buffer); + } else { + return 0; + } + } + + void unmap() + { + if (m_mode != NotMapped) { + m_mode = NotMapped; + CVPixelBufferUnlockBaseAddress(m_buffer, 0); + } + } + +private: + CVPixelBufferRef m_buffer; + MapMode m_mode; +}; + + + +QT7MovieRenderer::QT7MovieRenderer(QObject *parent) + :QT7VideoRendererControl(parent), + m_movie(0), +#ifdef QUICKTIME_C_API_AVAILABLE + m_visualContext(0), + m_usingGLContext(false), + m_currentGLContext(0), +#endif + m_surface(0) +{ + qDebug() << "QT7MovieRenderer"; + + m_displayLink = new QCvDisplayLink(this); + connect(m_displayLink, SIGNAL(tick(CVTimeStamp)), SLOT(updateVideoFrame(CVTimeStamp))); +} + + +bool QT7MovieRenderer::createGLVisualContext() +{ +#ifdef QUICKTIME_C_API_AVAILABLE + AutoReleasePool pool; + CGLContextObj cglContext = CGLGetCurrentContext(); + NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat]; + CGLPixelFormatObj cglPixelFormat = static_cast([nsglPixelFormat CGLPixelFormatObj]); + + OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, cglContext, + cglPixelFormat, NULL, &m_visualContext); + if (err != noErr) + qWarning() << "Could not create visual context (OpenGL)"; + + return (err == noErr); +#endif // QUICKTIME_C_API_AVAILABLE + + return false; +} + +#ifdef QUICKTIME_C_API_AVAILABLE +static bool DictionarySetValue(CFMutableDictionaryRef dict, CFStringRef key, SInt32 value) +{ + CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + + if (number) { + CFDictionarySetValue( dict, key, number ); + CFRelease( number ); + return true; + } + return false; +} +#endif // QUICKTIME_C_API_AVAILABLE + +bool QT7MovieRenderer::createPixelBufferVisualContext() +{ +#ifdef QUICKTIME_C_API_AVAILABLE + if (m_visualContext) { + QTVisualContextRelease(m_visualContext); + m_visualContext = 0; + } + + m_pixelBufferContextGeometry = m_nativeSize; + + CFMutableDictionaryRef pixelBufferOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + //DictionarySetValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, k32ARGBPixelFormat ); + DictionarySetValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat ); + DictionarySetValue(pixelBufferOptions, kCVPixelBufferWidthKey, m_nativeSize.width() ); + DictionarySetValue(pixelBufferOptions, kCVPixelBufferHeightKey, m_nativeSize.height() ); + DictionarySetValue(pixelBufferOptions, kCVPixelBufferBytesPerRowAlignmentKey, 16); + //CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue); + + CFMutableDictionaryRef visualContextOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(visualContextOptions, kQTVisualContextPixelBufferAttributesKey, pixelBufferOptions); + CFDictionarySetValue(visualContextOptions, kQTVisualContextWorkingColorSpaceKey, CGColorSpaceCreateDeviceRGB()); + + OSStatus err = QTPixelBufferContextCreate(kCFAllocatorDefault, + visualContextOptions, + &m_visualContext); + CFRelease(pixelBufferOptions); + CFRelease(visualContextOptions); + + if (err != noErr) { + qWarning() << "Could not create visual context (PixelBuffer)"; + return false; + } + + return true; +#endif // QUICKTIME_C_API_AVAILABLE + + return false; +} + + +QT7MovieRenderer::~QT7MovieRenderer() +{ + m_displayLink->stop(); +} + +void QT7MovieRenderer::setupVideoOutput() +{ + AutoReleasePool pool; + + qDebug() << "QT7MovieRenderer::setupVideoOutput" << m_movie; + + if (m_movie == 0 || m_surface == 0) { + m_displayLink->stop(); + return; + } + + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue]; + m_nativeSize = QSize(size.width, size.height); + +#ifdef QUICKTIME_C_API_AVAILABLE + bool usedGLContext = m_usingGLContext; + + if (!m_nativeSize.isEmpty()) { + + bool glSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty(); + + //Try rendering using opengl textures first: + if (glSupported) { + QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle); + + if (m_surface->isActive()) + m_surface->stop(); + + qDebug() << "Starting the surface with format" << format; + if (!m_surface->start(format)) { + qDebug() << "failed to start video surface" << m_surface->error(); + glSupported = false; + } else { + m_usingGLContext = true; + } + + } + + if (!glSupported) { + m_usingGLContext = false; + QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32); + + if (m_surface->isActive() && m_surface->surfaceFormat() != format) { + qDebug() << "Surface format was changed, stop the surface."; + m_surface->stop(); + } + + if (!m_surface->isActive()) { + qDebug() << "Starting the surface with format" << format; + if (!m_surface->start(format)) + qDebug() << "failed to start video surface" << m_surface->error(); + } + } + } + + + if (m_visualContext) { + //check if the visual context still can be reused + if (usedGLContext != m_usingGLContext || + (m_usingGLContext && (m_currentGLContext != QGLContext::currentContext())) || + (!m_usingGLContext && (m_pixelBufferContextGeometry != m_nativeSize))) { + QTVisualContextRelease(m_visualContext); + m_visualContext = 0; + } + } + + if (!m_visualContext) { + if (m_usingGLContext) { + qDebug() << "Building OpenGL visual context"; + m_currentGLContext = QGLContext::currentContext(); + if (!createGLVisualContext()) { + qWarning() << "QT7MovieRenderer: failed to create visual context"; + return; + } + } else { + qDebug() << "Building Pixel Buffer visual context"; + if (!createPixelBufferVisualContext()) { + qWarning() << "QT7MovieRenderer: failed to create visual context"; + return; + } + } + } + + // targets a Movie to render into a visual context + SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext); + + +#endif + + m_displayLink->start(); +} + +void QT7MovieRenderer::setEnabled(bool) +{ +} + +void QT7MovieRenderer::setMovie(void *movie) +{ + qDebug() << "QT7MovieRenderer::setMovie" << movie; + + if (m_movie == movie) + return; + + QMutexLocker locker(&m_mutex); + +#ifdef QUICKTIME_C_API_AVAILABLE + //ensure the old movie doesn't hold the visual context, otherwise it can't be reused + if (m_movie && m_visualContext) + SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], 0); +#endif + + m_movie = movie; + setupVideoOutput(); +} + +QAbstractVideoSurface *QT7MovieRenderer::surface() const +{ + return m_surface; +} + +void QT7MovieRenderer::setSurface(QAbstractVideoSurface *surface) +{ + qDebug() << "Set video surface" << surface; + + if (surface == m_surface) + return; + + QMutexLocker locker(&m_mutex); + + if (m_surface && m_surface->isActive()) + m_surface->stop(); + + m_surface = surface; + setupVideoOutput(); +} + + +QSize QT7MovieRenderer::nativeSize() const +{ + return m_nativeSize; +} + +void QT7MovieRenderer::updateVideoFrame(const CVTimeStamp &ts) +{ +#ifdef QUICKTIME_C_API_AVAILABLE + + QMutexLocker locker(&m_mutex); + + if (m_surface && m_surface->isActive() && + m_visualContext && QTVisualContextIsNewImageAvailable(m_visualContext, &ts)) { + + CVImageBufferRef imageBuffer = NULL; + + OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, &imageBuffer); + + if (status == noErr && imageBuffer) { + //qDebug() << "render video frame"; + QAbstractVideoBuffer *buffer = 0; + + if (m_usingGLContext) { + buffer = new CVGLTextureVideoBuffer((CVOpenGLTextureRef)imageBuffer); + CVOpenGLTextureRelease((CVOpenGLTextureRef)imageBuffer); + //qDebug() << "render GL video frame" << buffer->handle(); + } else { + buffer = new CVPixelBufferVideoBuffer((CVPixelBufferRef)imageBuffer); + CVPixelBufferRelease((CVPixelBufferRef)imageBuffer); + } + + QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_RGB32); + m_surface->present(frame); + QTVisualContextTask(m_visualContext); + } + } +#else + Q_UNUSED(ts); +#endif +} + +#include "moc_qt7movierenderer.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.h b/src/plugins/mediaservices/qt7/qt7movievideowidget.h new file mode 100644 index 0000000..266dad4 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7MOVIEVIDEOWIDGET_H +#define QT7MOVIEVIDEOWIDGET_H + +#include +#include + +#include +#include + +#include +#include "qt7videooutputcontrol.h" + +#include +#include + + +QT_BEGIN_HEADER + +class GLVideoWidget; + +QT_BEGIN_NAMESPACE + +class QCvDisplayLink; +class QT7PlayerSession; +class QT7PlayerService; + +class QT7MovieVideoWidget : public QT7VideoWidgetControl +{ +Q_OBJECT +public: + QT7MovieVideoWidget(QObject *parent = 0); + virtual ~QT7MovieVideoWidget(); + + void setEnabled(bool); + void setMovie(void *movie); + + QWidget *videoWidget(); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + QSize nativeSize() const; + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + +private slots: + void updateVideoFrame(const CVTimeStamp &ts); + +private: + void setupVideoOutput(); + bool createVisualContext(); + + void updateColors(); + + void *m_movie; + GLVideoWidget *m_videoWidget; + + QCvDisplayLink *m_displayLink; + +#ifdef QUICKTIME_C_API_AVAILABLE + QTVisualContextRef m_visualContext; +#endif + + bool m_fullscreen; + QSize m_nativeSize; + QVideoWidget::AspectRatioMode m_aspectRatioMode; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.mm b/src/plugins/mediaservices/qt7/qt7movievideowidget.mm new file mode 100644 index 0000000..e1e0162 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.mm @@ -0,0 +1,409 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import + +#include "qt7backend.h" + +#include "qt7playercontrol.h" +#include "qt7movievideowidget.h" +#include "qt7playersession.h" +#include "qcvdisplaylink.h" +#include +#include + +#include + +#import + +#include "math.h" + +QT_BEGIN_NAMESPACE + +class GLVideoWidget : public QGLWidget +{ +public: + + GLVideoWidget(QWidget *parent, const QGLFormat &format) + : QGLWidget(format, parent), + m_texRef(0), + m_nativeSize(640,480), + m_aspectRatioMode(QVideoWidget::KeepAspectRatio) + { + setAutoFillBackground(false); + } + + void initializeGL() + { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + } + + void resizeGL(int w, int h) + { + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glViewport(0, 0, GLsizei(w), GLsizei(h)); + gluOrtho2D(0, GLsizei(w), 0, GLsizei(h)); + updateGL(); + } + + void paintGL() + { + glClear(GL_COLOR_BUFFER_BIT); + if (!m_texRef) + return; + + glPushMatrix(); + glDisable(GL_CULL_FACE); + GLenum target = CVOpenGLTextureGetTarget(m_texRef); + glEnable(target); + + glBindTexture(target, CVOpenGLTextureGetName(m_texRef)); + glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GLfloat lowerLeft[2], lowerRight[2], upperRight[2], upperLeft[2]; + CVOpenGLTextureGetCleanTexCoords(m_texRef, lowerLeft, lowerRight, upperRight, upperLeft); + + glBegin(GL_QUADS); + QRect rect = displayRect(); + glTexCoord2f(lowerLeft[0], lowerLeft[1]); + glVertex2i(rect.topLeft().x(), rect.topLeft().y()); + glTexCoord2f(lowerRight[0], lowerRight[1]); + glVertex2i(rect.topRight().x() + 1, rect.topRight().y()); + glTexCoord2f(upperRight[0], upperRight[1]); + glVertex2i(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1); + glTexCoord2f(upperLeft[0], upperLeft[1]); + glVertex2i(rect.bottomLeft().x(), rect.bottomLeft().y() + 1); + glEnd(); + glPopMatrix(); + } + + void setCVTexture(CVOpenGLTextureRef texRef) + { + if (m_texRef) + CVOpenGLTextureRelease(m_texRef); + + m_texRef = texRef; + + if (m_texRef) + CVOpenGLTextureRetain(m_texRef); + + if (isVisible()) { + makeCurrent(); + paintGL(); + swapBuffers(); + } + } + + QSize sizeHint() const + { + return m_nativeSize; + } + + void setNativeSize(const QSize &size) + { + m_nativeSize = size; + } + + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode) + { + if (m_aspectRatioMode != mode) { + m_aspectRatioMode = mode; + update(); + } + } + +private: + QRect displayRect() const + { + QRect displayRect = rect(); + + if (m_aspectRatioMode == QVideoWidget::KeepAspectRatio) { + QSize size = m_nativeSize; + size.scale(displayRect.size(), Qt::KeepAspectRatio); + + displayRect = QRect(QPoint(0, 0), size); + displayRect.moveCenter(rect().center()); + } + return displayRect; + } + + CVOpenGLTextureRef m_texRef; + QSize m_nativeSize; + QVideoWidget::AspectRatioMode m_aspectRatioMode; +}; + +QT7MovieVideoWidget::QT7MovieVideoWidget(QObject *parent) + :QT7VideoWidgetControl(parent), + m_movie(0), + m_videoWidget(0), + m_fullscreen(false), + m_aspectRatioMode(QVideoWidget::KeepAspectRatio), + m_brightness(0), + m_contrast(0), + m_hue(0), + m_saturation(0) +{ + qDebug() << "QT7MovieVideoWidget"; + + QGLFormat format = QGLFormat::defaultFormat(); + format.setSwapInterval(1); // Vertical sync (avoid tearing) + m_videoWidget = new GLVideoWidget(0, format); + + m_displayLink = new QCvDisplayLink(this); + + connect(m_displayLink, SIGNAL(tick(CVTimeStamp)), SLOT(updateVideoFrame(CVTimeStamp))); + + if (!createVisualContext()) { + qWarning() << "QT7MovieVideoWidget: failed to create visual context"; + } +} + + +bool QT7MovieVideoWidget::createVisualContext() +{ +#ifdef QUICKTIME_C_API_AVAILABLE + m_videoWidget->makeCurrent(); + + AutoReleasePool pool; + CGLContextObj cglContext = CGLGetCurrentContext(); + NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat]; + CGLPixelFormatObj cglPixelFormat = static_cast([nsglPixelFormat CGLPixelFormatObj]); + + CFTypeRef keys[] = { kQTVisualContextWorkingColorSpaceKey }; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CFDictionaryRef textureContextAttributes = CFDictionaryCreate(kCFAllocatorDefault, + (const void **)keys, + (const void **)&colorSpace, 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + OSStatus err = QTOpenGLTextureContextCreate(kCFAllocatorDefault, + cglContext, + cglPixelFormat, + textureContextAttributes, + &m_visualContext); + if (err != noErr) + qWarning() << "Could not create visual context (OpenGL)"; + + + return (err == noErr); +#endif // QUICKTIME_C_API_AVAILABLE + + return false; +} + +QT7MovieVideoWidget::~QT7MovieVideoWidget() +{ + m_displayLink->stop(); + [(QTMovie*)m_movie release]; + delete m_videoWidget; +} + +QWidget *QT7MovieVideoWidget::videoWidget() +{ + return m_videoWidget; +} + +void QT7MovieVideoWidget::setupVideoOutput() +{ + AutoReleasePool pool; + + qDebug() << "QT7MovieVideoWidget::setupVideoOutput" << m_movie; + + if (m_movie == 0) { + m_displayLink->stop(); + return; + } + + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue]; + m_nativeSize = QSize(size.width, size.height); + m_videoWidget->setNativeSize(m_nativeSize); + +#ifdef QUICKTIME_C_API_AVAILABLE + // targets a Movie to render into a visual context + SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext); +#endif + + m_displayLink->start(); +} + +void QT7MovieVideoWidget::setEnabled(bool) +{ +} + +void QT7MovieVideoWidget::setMovie(void *movie) +{ + if (m_movie == movie) + return; + + if (m_movie) { +#ifdef QUICKTIME_C_API_AVAILABLE + SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], nil); +#endif + [(QTMovie*)m_movie release]; + } + + m_movie = movie; + [(QTMovie*)m_movie retain]; + + setupVideoOutput(); +} + +bool QT7MovieVideoWidget::isFullScreen() const +{ + return m_fullscreen; +} + +void QT7MovieVideoWidget::setFullScreen(bool fullScreen) +{ + m_fullscreen = fullScreen; +} + +QSize QT7MovieVideoWidget::nativeSize() const +{ + return m_nativeSize; +} + +QVideoWidget::AspectRatioMode QT7MovieVideoWidget::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QT7MovieVideoWidget::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; + m_videoWidget->setAspectRatioMode(mode); +} + +int QT7MovieVideoWidget::brightness() const +{ + return m_brightness; +} + +void QT7MovieVideoWidget::setBrightness(int brightness) +{ + m_brightness = brightness; + updateColors(); +} + +int QT7MovieVideoWidget::contrast() const +{ + return m_contrast; +} + +void QT7MovieVideoWidget::setContrast(int contrast) +{ + m_contrast = contrast; + updateColors(); +} + +int QT7MovieVideoWidget::hue() const +{ + return m_hue; +} + +void QT7MovieVideoWidget::setHue(int hue) +{ + m_hue = hue; + updateColors(); +} + +int QT7MovieVideoWidget::saturation() const +{ + return m_saturation; +} + +void QT7MovieVideoWidget::setSaturation(int saturation) +{ + m_saturation = saturation; + updateColors(); +} + +void QT7MovieVideoWidget::updateColors() +{ +#ifdef QUICKTIME_C_API_AVAILABLE + if (m_movie) { + QTMovie *movie = (QTMovie*)m_movie; + + Float32 value; + value = m_brightness/100.0; + SetMovieVisualBrightness([movie quickTimeMovie], value, 0); + value = pow(2, m_contrast/50.0); + SetMovieVisualContrast([movie quickTimeMovie], value, 0); + value = m_hue/100.0; + SetMovieVisualHue([movie quickTimeMovie], value, 0); + value = 1.0+m_saturation/100.0; + SetMovieVisualSaturation([movie quickTimeMovie], value, 0); + } +#endif +} + +void QT7MovieVideoWidget::updateVideoFrame(const CVTimeStamp &ts) +{ +#ifdef QUICKTIME_C_API_AVAILABLE + AutoReleasePool pool; + // check for new frame + if (m_visualContext && QTVisualContextIsNewImageAvailable(m_visualContext, &ts)) { + CVOpenGLTextureRef currentFrame = NULL; + + // get a "frame" (image buffer) from the Visual Context, indexed by the provided time + OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, ¤tFrame); + + // the above call may produce a null frame so check for this first + // if we have a frame, then draw it + if (status == noErr && currentFrame) { + //qDebug() << "render video frame"; + m_videoWidget->setCVTexture(currentFrame); + CVOpenGLTextureRelease(currentFrame); + } + QTVisualContextTask(m_visualContext); + } +#else + Q_UNUSED(ts); +#endif +} + +#include "moc_qt7movievideowidget.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.h b/src/plugins/mediaservices/qt7/qt7movieviewoutput.h new file mode 100644 index 0000000..7f3ff91 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7MOVIEVIEWOUTPUT_H +#define QT7MOVIEVIEWOUTPUT_H + +#include + +#include +#include + +#include +#include "qt7videooutputcontrol.h" + + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QT7PlayerSession; +class QT7PlayerService; + +class QT7MovieViewOutput : public QT7VideoWindowControl +{ +public: + QT7MovieViewOutput(QObject *parent = 0); + ~QT7MovieViewOutput(); + + void setEnabled(bool); + void setMovie(void *movie); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + void repaint(); + + QSize nativeSize() const; + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + +private: + void setupVideoOutput(); + + void *m_movie; + void *m_movieView; + + WId m_winId; + QRect m_displayRect; + bool m_fullscreen; + QSize m_nativeSize; + QVideoWidget::AspectRatioMode m_aspectRatioMode; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm new file mode 100644 index 0000000..8182797 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm @@ -0,0 +1,307 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import + +#include "qt7backend.h" + +#include "qt7playercontrol.h" +#include "qt7movieviewoutput.h" +#include "qt7playersession.h" +#include + + +QT_BEGIN_NAMESPACE + +#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];} + +@interface TransparentQTMovieView : QTMovieView +{ +@private + QRect *m_drawRect; + qreal m_brightness, m_contrast, m_saturation, m_hue; +} + +- (TransparentQTMovieView *) init; +- (void) setDrawRect:(QRect &)rect; +- (void) setContrast:(qreal) contrast; +@end + +@implementation TransparentQTMovieView + +- (TransparentQTMovieView *) init +{ + self = [super initWithFrame:NSZeroRect]; + if (self) { + [self setControllerVisible:NO]; + [self setContrast:1.0]; + [self setDelegate:self]; + } + return self; +} + +- (void) dealloc +{ + [super dealloc]; +} + +- (void) setContrast:(qreal) contrast +{ + m_hue = 0.0; + m_brightness = 0.0; + m_contrast = contrast; + m_saturation = 1.0; +} + + +- (void) setDrawRect:(QRect &)rect +{ + *m_drawRect = rect; + + NSRect nsrect; + nsrect.origin.x = m_drawRect->x(); + nsrect.origin.y = m_drawRect->y(); + nsrect.size.width = m_drawRect->width(); + nsrect.size.height = m_drawRect->height(); + [self setFrame:nsrect]; +} + +- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img +{ + // This method is called from QTMovieView just + // before the image will be drawn. + Q_UNUSED(view); + + if ( !qFuzzyCompare(m_brightness, 0.0) || + !qFuzzyCompare(m_contrast, 1.0) || + !qFuzzyCompare(m_saturation, 1.0)){ + CIFilter *colorFilter = [CIFilter filterWithName:@"CIColorControls"]; + [colorFilter setValue:[NSNumber numberWithFloat:m_brightness] forKey:@"inputBrightness"]; + [colorFilter setValue:[NSNumber numberWithFloat:(m_contrast < 1) ? m_contrast : 1 + ((m_contrast-1)*3)] forKey:@"inputContrast"]; + [colorFilter setValue:[NSNumber numberWithFloat:m_saturation] forKey:@"inputSaturation"]; + [colorFilter setValue:img forKey:@"inputImage"]; + img = [colorFilter valueForKey:@"outputImage"]; + } + + /*if (m_hue){ + CIFilter *colorFilter = [CIFilter filterWithName:@"CIHueAdjust"]; + [colorFilter setValue:[NSNumber numberWithFloat:(m_hue * 3.14)] forKey:@"inputAngle"]; + [colorFilter setValue:img forKey:@"inputImage"]; + img = [colorFilter valueForKey:@"outputImage"]; + }*/ + + return img; +} + + +VIDEO_TRANSPARENT(mouseDown); +VIDEO_TRANSPARENT(mouseDragged); +VIDEO_TRANSPARENT(mouseUp); +VIDEO_TRANSPARENT(mouseMoved); +VIDEO_TRANSPARENT(mouseEntered); +VIDEO_TRANSPARENT(mouseExited); +VIDEO_TRANSPARENT(rightMouseDown); +VIDEO_TRANSPARENT(rightMouseDragged); +VIDEO_TRANSPARENT(rightMouseUp); +VIDEO_TRANSPARENT(otherMouseDown); +VIDEO_TRANSPARENT(otherMouseDragged); +VIDEO_TRANSPARENT(otherMouseUp); +VIDEO_TRANSPARENT(keyDown); +VIDEO_TRANSPARENT(keyUp); +VIDEO_TRANSPARENT(scrollWheel) + +@end + + +QT7MovieViewOutput::QT7MovieViewOutput(QObject *parent) + :QT7VideoWindowControl(parent), + m_movie(0), + m_movieView(0), + m_winId(0), + m_fullscreen(false), + m_aspectRatioMode(QVideoWidget::KeepAspectRatio), + m_brightness(0), + m_contrast(0), + m_hue(0), + m_saturation(0) +{ +} + +QT7MovieViewOutput::~QT7MovieViewOutput() +{ +} + +void QT7MovieViewOutput::setupVideoOutput() +{ + AutoReleasePool pool; + + //qDebug() << "QT7MovieViewOutput::setupVideoOutput" << m_movie << m_winId; + if (m_movie == 0 || m_winId <= 0) + return; + + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue]; + m_nativeSize = QSize(size.width, size.height); + + if (!m_movieView) + m_movieView = [[TransparentQTMovieView alloc] init]; + + [(QTMovieView*)m_movieView setControllerVisible:NO]; + [(QTMovieView*)m_movieView setMovie:(QTMovie*)m_movie]; + + [(NSView *)m_winId addSubview:(QTMovieView*)m_movieView]; + + setDisplayRect(m_displayRect); +} + +void QT7MovieViewOutput::setEnabled(bool) +{ +} + +void QT7MovieViewOutput::setMovie(void *movie) +{ + m_movie = movie; + setupVideoOutput(); +} + +WId QT7MovieViewOutput::winId() const +{ + return m_winId; +} + +void QT7MovieViewOutput::setWinId(WId id) +{ + m_winId = id; + setupVideoOutput(); +} + +QRect QT7MovieViewOutput::displayRect() const +{ + return m_displayRect; +} + +void QT7MovieViewOutput::setDisplayRect(const QRect &rect) +{ + m_displayRect = rect; + + if (m_movieView) { + AutoReleasePool pool; + [(QTMovieView*)m_movieView setPreservesAspectRatio:(m_aspectRatioMode == QVideoWidget::KeepAspectRatio ? YES : NO)]; + [(QTMovieView*)m_movieView setFrame:NSMakeRect(m_displayRect.x(), + m_displayRect.y(), + m_displayRect.width(), + m_displayRect.height())]; + } + +} + +bool QT7MovieViewOutput::isFullScreen() const +{ + return m_fullscreen; +} + +void QT7MovieViewOutput::setFullScreen(bool fullScreen) +{ + m_fullscreen = fullScreen; + setDisplayRect(m_displayRect); +} + +void QT7MovieViewOutput::repaint() +{ +} + +QSize QT7MovieViewOutput::nativeSize() const +{ + return m_nativeSize; +} + +QVideoWidget::AspectRatioMode QT7MovieViewOutput::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QT7MovieViewOutput::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; + setDisplayRect(m_displayRect); +} + +int QT7MovieViewOutput::brightness() const +{ + return m_brightness; +} + +void QT7MovieViewOutput::setBrightness(int brightness) +{ + m_brightness = brightness; +} + +int QT7MovieViewOutput::contrast() const +{ + return m_contrast; +} + +void QT7MovieViewOutput::setContrast(int contrast) +{ + m_contrast = contrast; + [(TransparentQTMovieView*)m_movieView setContrast:(contrast/100.0+1.0)]; +} + +int QT7MovieViewOutput::hue() const +{ + return m_hue; +} + +void QT7MovieViewOutput::setHue(int hue) +{ + m_hue = hue; +} + +int QT7MovieViewOutput::saturation() const +{ + return m_saturation; +} + +void QT7MovieViewOutput::setSaturation(int saturation) +{ + m_saturation = saturation; +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h new file mode 100644 index 0000000..6f381f8 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7MOVIEVIEWRENDERER_H +#define QT7MOVIEVIEWRENDERER_H + +#include +#include + +#include +#include + +#include +#include "qt7videooutputcontrol.h" +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QVideoFrame; +class QT7PlayerSession; +class QT7PlayerService; + +class QT7MovieViewRenderer : public QT7VideoRendererControl +{ +public: + QT7MovieViewRenderer(QObject *parent = 0); + ~QT7MovieViewRenderer(); + + void setEnabled(bool); + void setMovie(void *movie); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + void renderFrame(const QVideoFrame &); + +protected: + bool event(QEvent *event); + +private: + void setupVideoOutput(); + + void *m_movie; + void *m_movieView; + QSize m_nativeSize; + QAbstractVideoSurface *m_surface; + QVideoFrame m_currentFrame; + QMutex m_mutex; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm new file mode 100644 index 0000000..e08d0f3 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import + +#include "qt7backend.h" + +#include "qt7playercontrol.h" +#include "qt7movieviewrenderer.h" +#include "qt7playersession.h" +#include +#include +#include + +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +class NSBitmapVideoBuffer : public QAbstractVideoBuffer +{ +public: + NSBitmapVideoBuffer(NSBitmapImageRep *buffer) + : QAbstractVideoBuffer(NoHandle) + , m_buffer(buffer) + , m_mode(NotMapped) + { + [m_buffer retain]; + } + + virtual ~NSBitmapVideoBuffer() + { + [m_buffer release]; + } + + MapMode mapMode() const { return m_mode; } + + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + { + if (mode != NotMapped && m_mode == NotMapped) { + if (numBytes) + *numBytes = [m_buffer bytesPerPlane]; + + if (bytesPerLine) + *bytesPerLine = [m_buffer bytesPerRow]; + + m_mode = mode; + + return [m_buffer bitmapData]; + } else { + return 0; + } + } + + void unmap() { m_mode = NotMapped; } + +private: + NSBitmapImageRep *m_buffer; + MapMode m_mode; +}; + + +#define VIDEO_TRANSPARENT(m) -(void)m:(NSEvent *)e{[[self superview] m:e];} + +@interface HiddenQTMovieView : QTMovieView +{ +@private + QWidget *m_window; + QT7MovieViewRenderer *m_renderer; +} + +- (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer; +- (void) setRenderer:(QT7MovieViewRenderer *)renderer; +- (void) setDrawRect:(const QRect &)rect; +@end + +@implementation HiddenQTMovieView + +- (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer +{ + self = [super initWithFrame:NSZeroRect]; + if (self) { + [self setControllerVisible:NO]; + [self setDelegate:self]; + + self->m_renderer = renderer; + + self->m_window = new QWidget; + self->m_window->setWindowOpacity(0.0); + self->m_window->show(); + self->m_window->hide(); + + [(NSView *)(self->m_window->winId()) addSubview:self]; + [self setDrawRect:QRect(0,0,1,1)]; + } + return self; +} + +- (void) dealloc +{ + [super dealloc]; +} + +- (void) setRenderer:(QT7MovieViewRenderer *)renderer +{ + m_renderer = renderer; +} + +- (void) setDrawRect:(const QRect &)rect +{ + NSRect nsrect; + nsrect.origin.x = rect.x(); + nsrect.origin.y = rect.y(); + nsrect.size.width = rect.width(); + nsrect.size.height = rect.height(); + [self setFrame:nsrect]; +} + +- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img +{ + // This method is called from QTMovieView just + // before the image will be drawn. + Q_UNUSED(view); + if (m_renderer) { + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img]; + CGRect bounds = [img extent]; + int w = bounds.size.width; + int h = bounds.size.height; + + // Swap red and blue (same as QImage::rgbSwapped, but without copy) + uchar *data = [bitmap bitmapData]; + //qDebug() << data << w << h; + int bytesPerLine = [bitmap bytesPerRow]; + for (int i=0; i> 16) & 0xff) | (*p & 0xff00ff00); + p++; + } + } + + QVideoFrame frame( new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 ); + + //static int i=0; + //i++; + //QImage img([bitmap bitmapData], w, h, QImage::Format_RGB32); + //img.save(QString("img%1.jpg").arg(i)); + + [bitmap release]; + + if (m_renderer) + m_renderer->renderFrame(frame); + } + + return img; +} + +// Override this method so that the movie doesn't stop if +// the window becomes invisible +- (void)viewWillMoveToWindow:(NSWindow *)newWindow +{ + Q_UNUSED(newWindow); +} + + +VIDEO_TRANSPARENT(mouseDown); +VIDEO_TRANSPARENT(mouseDragged); +VIDEO_TRANSPARENT(mouseUp); +VIDEO_TRANSPARENT(mouseMoved); +VIDEO_TRANSPARENT(mouseEntered); +VIDEO_TRANSPARENT(mouseExited); +VIDEO_TRANSPARENT(rightMouseDown); +VIDEO_TRANSPARENT(rightMouseDragged); +VIDEO_TRANSPARENT(rightMouseUp); +VIDEO_TRANSPARENT(otherMouseDown); +VIDEO_TRANSPARENT(otherMouseDragged); +VIDEO_TRANSPARENT(otherMouseUp); +VIDEO_TRANSPARENT(keyDown); +VIDEO_TRANSPARENT(keyUp); +VIDEO_TRANSPARENT(scrollWheel) + +@end + + +QT7MovieViewRenderer::QT7MovieViewRenderer(QObject *parent) + :QT7VideoRendererControl(parent), + m_movie(0), + m_movieView(0), + m_surface(0) +{ +} + +QT7MovieViewRenderer::~QT7MovieViewRenderer() +{ + [(HiddenQTMovieView*)m_movieView setRenderer:0]; + + QMutexLocker locker(&m_mutex); + m_currentFrame = QVideoFrame(); + [(HiddenQTMovieView*)m_movieView release]; +} + +void QT7MovieViewRenderer::setupVideoOutput() +{ + AutoReleasePool pool; + + qDebug() << "QT7MovieViewRenderer::setupVideoOutput" << m_movie << m_surface; + + HiddenQTMovieView *movieView = (HiddenQTMovieView*)m_movieView; + + if (movieView && !m_movie) { + [movieView setMovie:nil]; + } + + if (m_movie) { + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; + + m_nativeSize = QSize(size.width, size.height); + + if (!movieView) { + movieView = [[HiddenQTMovieView alloc] initWithRenderer:this]; + m_movieView = movieView; + [movieView setControllerVisible:NO]; + } + + [movieView setMovie:(QTMovie*)m_movie]; + //[movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)]; + } + + if (m_surface && !m_nativeSize.isEmpty()) { + QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32); + + if (m_surface->isActive() && m_surface->surfaceFormat() != format) { + qDebug() << "Surface format was changed, stop the surface."; + m_surface->stop(); + } + + if (!m_surface->isActive()) { + qDebug() << "Starting the surface with format" << format; + if (!m_surface->start(format)) + qDebug() << "failed to start video surface" << m_surface->error(); + } + } +} + +void QT7MovieViewRenderer::setEnabled(bool) +{ +} + +void QT7MovieViewRenderer::setMovie(void *movie) +{ + if (movie == m_movie) + return; + + QMutexLocker locker(&m_mutex); + m_movie = movie; + setupVideoOutput(); +} + +QAbstractVideoSurface *QT7MovieViewRenderer::surface() const +{ + return m_surface; +} + +void QT7MovieViewRenderer::setSurface(QAbstractVideoSurface *surface) +{ + if (surface == m_surface) + return; + + QMutexLocker locker(&m_mutex); + + if (m_surface && m_surface->isActive()) + m_surface->stop(); + + m_surface = surface; + setupVideoOutput(); +} + +void QT7MovieViewRenderer::renderFrame(const QVideoFrame &frame) +{ + { + QMutexLocker locker(&m_mutex); + m_currentFrame = frame; + } + + qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority); +} + +bool QT7MovieViewRenderer::event(QEvent *event) +{ + if (event->type() == QEvent::User) { + QMutexLocker locker(&m_mutex); + if (m_surface->isActive()) + m_surface->present(m_currentFrame); + } + + return QT7VideoRendererControl::event(event); +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7playercontrol.h b/src/plugins/mediaservices/qt7/qt7playercontrol.h new file mode 100644 index 0000000..da86949 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playercontrol.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERCONTROL_H +#define QT7PLAYERCONTROL_H + +#include +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7PlayerSession; +class QT7PlayerService; +class QMediaPlaylist; +class QMediaPlaylistNavigator; + +class QT7PlayerControl : public QMediaPlayerControl +{ +Q_OBJECT +public: + QT7PlayerControl(QObject *parent = 0); + ~QT7PlayerControl(); + + void setSession(QT7PlayerSession *session); + + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent &content, QIODevice *stream); + + qint64 position() const; + qint64 duration() const; + + int bufferStatus() const; + + int volume() const; + bool isMuted() const; + + bool isVideoAvailable() const; + + bool isSeekable() const; + + QMediaTimeRange availablePlaybackRanges() const; + + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + +public Q_SLOTS: + void setPosition(qint64 pos); + + void play(); + void pause(); + void stop(); + + void setVolume(int volume); + void setMuted(bool muted); + +Q_SIGNALS: + void mediaChanged(const QMediaContent& content); + void durationChanged(qint64 duration); + void positionChanged(qint64 position); + void stateChanged(QMediaPlayer::State newState); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + void bufferStatusChanged(int percentFilled); + void seekableChanged(bool); + void seekRangeChanged(const QPair&); + void playbackRateChanged(qreal rate); + void error(int error, const QString &errorString); + +private: + QT7PlayerSession *m_session; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7playercontrol.mm b/src/plugins/mediaservices/qt7/qt7playercontrol.mm new file mode 100644 index 0000000..b74f434 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playercontrol.mm @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt7playercontrol.h" +#include "qt7playersession.h" + +#include + +#include +#include + + +QT_BEGIN_NAMESPACE + +QT7PlayerControl::QT7PlayerControl(QObject *parent) + : QMediaPlayerControl(parent) +{ +} + +QT7PlayerControl::~QT7PlayerControl() +{ +} + +void QT7PlayerControl::setSession(QT7PlayerSession *session) +{ + m_session = session; + + connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64))); + connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); + connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)), + this, SIGNAL(stateChanged(QMediaPlayer::State))); + connect(m_session, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int))); + connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); + connect(m_session, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(videoAvailableChanged(bool))); + connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); +} + +qint64 QT7PlayerControl::position() const +{ + return m_session->position(); +} + +qint64 QT7PlayerControl::duration() const +{ + return m_session->duration(); +} + +QMediaPlayer::State QT7PlayerControl::state() const +{ + return m_session->state(); +} + +QMediaPlayer::MediaStatus QT7PlayerControl::mediaStatus() const +{ + return m_session->mediaStatus(); +} + +int QT7PlayerControl::bufferStatus() const +{ + return m_session->bufferStatus(); +} + +int QT7PlayerControl::volume() const +{ + return m_session->volume(); +} + +bool QT7PlayerControl::isMuted() const +{ + return m_session->isMuted(); +} + +bool QT7PlayerControl::isSeekable() const +{ + return m_session->isSeekable(); +} + +QMediaTimeRange QT7PlayerControl::availablePlaybackRanges() const +{ + return isSeekable() ? QMediaTimeRange(0, duration()) : QMediaTimeRange(); +} + +qreal QT7PlayerControl::playbackRate() const +{ + return m_session->playbackRate(); +} + +void QT7PlayerControl::setPlaybackRate(qreal rate) +{ + m_session->setPlaybackRate(rate); +} + +void QT7PlayerControl::setPosition(qint64 pos) +{ + m_session->setPosition(pos); +} + +void QT7PlayerControl::play() +{ + m_session->play(); +} + +void QT7PlayerControl::pause() +{ + m_session->pause(); +} + +void QT7PlayerControl::stop() +{ + m_session->stop(); +} + +void QT7PlayerControl::setVolume(int volume) +{ + m_session->setVolume(volume); +} + +void QT7PlayerControl::setMuted(bool muted) +{ + m_session->setMuted(muted); +} + +QMediaContent QT7PlayerControl::media() const +{ + return m_session->media(); +} + +const QIODevice *QT7PlayerControl::mediaStream() const +{ + return m_session->mediaStream(); +} + +void QT7PlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) +{ + m_session->setMedia(content, stream); + + emit mediaChanged(content); +} + + +bool QT7PlayerControl::isVideoAvailable() const +{ + return m_session->isVideoAvailable(); +} + +#include "moc_qt7playercontrol.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7playermetadata.h b/src/plugins/mediaservices/qt7/qt7playermetadata.h new file mode 100644 index 0000000..9aa9887 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playermetadata.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERMETADATACONTROL_H +#define QT7PLAYERMETADATACONTROL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7PlayerSession; + +class QT7PlayerMetaDataControl : public QMetaDataControl +{ + Q_OBJECT +public: + QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent); + virtual ~QT7PlayerMetaDataControl(); + + bool isMetaDataAvailable() const; + bool isWritable() const; + + QVariant metaData(QtMedia::MetaData key) const; + void setMetaData(QtMedia::MetaData key, const QVariant &value); + QList availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const ; + void setExtendedMetaData(const QString &key, const QVariant &value); + QStringList availableExtendedMetaData() const; + +private slots: + void updateTags(); + +private: + QT7PlayerSession *m_session; + QMap m_tags; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7playermetadata.mm b/src/plugins/mediaservices/qt7/qt7playermetadata.mm new file mode 100644 index 0000000..96b7a68 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playermetadata.mm @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt7backend.h" +#include "qt7playermetadata.h" +#include "qt7playersession.h" +#include + +#import + +#ifdef QUICKTIME_C_API_AVAILABLE + #include + #undef check // avoid name clash; +#endif + +QT_BEGIN_NAMESPACE + +QT7PlayerMetaDataControl::QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent) + :QMetaDataControl(parent), m_session(session) +{ +} + +QT7PlayerMetaDataControl::~QT7PlayerMetaDataControl() +{ +} + +bool QT7PlayerMetaDataControl::isMetaDataAvailable() const +{ + return !m_tags.isEmpty(); +} + +bool QT7PlayerMetaDataControl::isWritable() const +{ + return false; +} + +QVariant QT7PlayerMetaDataControl::metaData(QtMedia::MetaData key) const +{ + return m_tags.value(key); +} + +void QT7PlayerMetaDataControl::setMetaData(QtMedia::MetaData key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QList QT7PlayerMetaDataControl::availableMetaData() const +{ + return m_tags.keys(); +} + +QVariant QT7PlayerMetaDataControl::extendedMetaData(const QString &key) const +{ + Q_UNUSED(key); + return QVariant(); +} + +void QT7PlayerMetaDataControl::setExtendedMetaData(const QString &key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QStringList QT7PlayerMetaDataControl::availableExtendedMetaData() const +{ + return QStringList(); +} + +#ifdef QUICKTIME_C_API_AVAILABLE + +static QString stripCopyRightSymbol(const QString &key) +{ + return key.right(key.length()-1); +} + +static QString convertQuickTimeKeyToUserKey(const QString &key) +{ + if (key == QLatin1String("com.apple.quicktime.displayname")) + return QLatin1String("nam"); + else if (key == QLatin1String("com.apple.quicktime.album")) + return QLatin1String("alb"); + else if (key == QLatin1String("com.apple.quicktime.artist")) + return QLatin1String("ART"); + else + return QLatin1String("???"); +} + +static OSStatus readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass, + QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size) +{ + QTPropertyValueType type; + ByteCount propSize; + UInt32 propFlags; + OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags); + + + *value = malloc(propSize); + + err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size); + + if (type == 'code' || type == 'itsk' || type == 'itlk') { + // convert from native endian to big endian + OSTypePtr pType = (OSTypePtr)*value; + *pType = EndianU32_NtoB(*pType); + } + + return err; +} + +static UInt32 getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item) +{ + QTPropertyValuePtr value = 0; + ByteCount ignore = 0; + OSStatus err = readMetaValue( + metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore); + + UInt32 type = *((UInt32 *) value); + if (value) + free(value); + return type; +} + +static QString cFStringToQString(CFStringRef str) +{ + if(!str) + return QString(); + CFIndex length = CFStringGetLength(str); + const UniChar *chars = CFStringGetCharactersPtr(str); + if (chars) + return QString(reinterpret_cast(chars), length); + + QVarLengthArray buffer(length); + CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); + return QString(reinterpret_cast(buffer.constData()), length); +} + + +static QString getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id) +{ + QTPropertyValuePtr value = 0; + ByteCount size = 0; + OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size); + + QString string; + UInt32 dataType = getMetaType(metaDataRef, item); + switch (dataType){ + case kQTMetaDataTypeUTF8: + case kQTMetaDataTypeMacEncodedText: + string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false)); + break; + case kQTMetaDataTypeUTF16BE: + string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false)); + break; + default: + break; + } + + if (value) + free(value); + return string; +} + + +static void readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap &result) +{ + QTMetaDataItem item = kQTMetaDataItemUninitialized; + OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item); + while (err == noErr){ + QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key); + if (format == kQTMetaDataStorageFormatQuickTime) + key = convertQuickTimeKeyToUserKey(key); + else + key = stripCopyRightSymbol(key); + + if (!result.contains(key)){ + QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value); + result.insert(key, val); + } + err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item); + } +} +#endif + + +void QT7PlayerMetaDataControl::updateTags() +{ + bool wasEmpty = m_tags.isEmpty(); + m_tags.clear(); + + QTMovie *movie = (QTMovie*)m_session->movie(); + + if (movie) { + QMultiMap metaMap; + +#ifdef QUICKTIME_C_API_AVAILABLE + QTMetaDataRef metaDataRef; + OSStatus err = QTCopyMovieMetaData([movie quickTimeMovie], &metaDataRef); + + readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap); + readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap); + readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap); +#else + NSString *name = [movie attributeForKey:@"QTMovieDisplayNameAttribute"]; + metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String])); +#endif // QUICKTIME_C_API_AVAILABLE + + m_tags.insert(QtMedia::AlbumArtist, metaMap.value(QLatin1String("ART"))); + m_tags.insert(QtMedia::AlbumTitle, metaMap.value(QLatin1String("alb"))); + m_tags.insert(QtMedia::Title, metaMap.value(QLatin1String("nam"))); + m_tags.insert(QtMedia::Date, metaMap.value(QLatin1String("day"))); + m_tags.insert(QtMedia::Genre, metaMap.value(QLatin1String("gnre"))); + m_tags.insert(QtMedia::TrackNumber, metaMap.value(QLatin1String("trk"))); + m_tags.insert(QtMedia::Description, metaMap.value(QLatin1String("des"))); + } + + if (!wasEmpty || !m_tags.isEmpty()) + emit metaDataChanged(); +} + +QT_END_NAMESPACE + +#include "moc_qt7playermetadata.cpp" diff --git a/src/plugins/mediaservices/qt7/qt7playerservice.h b/src/plugins/mediaservices/qt7/qt7playerservice.h new file mode 100644 index 0000000..d4b30b8 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playerservice.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERSERVICE_H +#define QT7PLAYERSERVICE_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaMetaData; +class QMediaPlayerControl; +class QMediaPlaylist; +class QMediaPlaylistNavigator; +class QT7PlayerControl; +class QT7PlayerMetaDataControl; +class QT7VideoOutputControl; +class QT7VideoWindowControl; +class QT7VideoWidgetControl; +class QT7VideoRendererControl; +class QT7VideoOutput; +class QT7PlayerSession; + +class QT7PlayerService : public QMediaService +{ +Q_OBJECT +public: + QT7PlayerService(QObject *parent = 0); + ~QT7PlayerService(); + + QMediaControl *control(const char *name) const; + +private slots: + void updateVideoOutput(); + +private: + QT7PlayerSession *m_session; + QT7PlayerControl *m_control; + QT7VideoOutputControl *m_videoOutputControl; + QT7VideoWindowControl *m_videoWidnowControl; + QT7VideoWidgetControl *m_videoWidgetControl; + QT7VideoRendererControl *m_videoRendererControl; + QT7PlayerMetaDataControl *m_playerMetaDataControl; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7playerservice.mm b/src/plugins/mediaservices/qt7/qt7playerservice.mm new file mode 100644 index 0000000..df15fa8 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playerservice.mm @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "qt7backend.h" +#include "qt7playerservice.h" +#include "qt7playercontrol.h" +#include "qt7playersession.h" +#include "qt7videooutputcontrol.h" +#include "qt7movieviewoutput.h" +#include "qt7movieviewrenderer.h" +#include "qt7movierenderer.h" +#include "qt7movievideowidget.h" +#include "qt7playermetadata.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QT7PlayerService::QT7PlayerService(QObject *parent): + QMediaService(parent) +{ + m_session = new QT7PlayerSession; + + m_control = new QT7PlayerControl(this); + m_control->setSession(m_session); + + m_playerMetaDataControl = new QT7PlayerMetaDataControl(m_session, this); + connect(m_control, SIGNAL(mediaChanged(QMediaContent)), m_playerMetaDataControl, SLOT(updateTags())); + + m_videoOutputControl = new QT7VideoOutputControl(this); + + m_videoWidnowControl = 0; + m_videoWidgetControl = 0; + m_videoRendererControl = 0; + +#if defined(QT_MAC_USE_COCOA) + m_videoWidnowControl = new QT7MovieViewOutput(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::WindowOutput); + qDebug() << "Using cocoa"; +#endif + +#ifdef QUICKTIME_C_API_AVAILABLE + m_videoRendererControl = new QT7MovieRenderer(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::RendererOutput); + + m_videoWidgetControl = new QT7MovieVideoWidget(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::WidgetOutput); + qDebug() << "QuickTime C API is available"; +#else + m_videoRendererControl = new QT7MovieViewRenderer(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::RendererOutput); + qDebug() << "QuickTime C API is not available"; +#endif + + + connect(m_videoOutputControl, SIGNAL(videoOutputChanged(QVideoOutputControl::Output)), + this, SLOT(updateVideoOutput())); +} + +QT7PlayerService::~QT7PlayerService() +{ +} + +QMediaControl *QT7PlayerService::control(const char *name) const +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return m_control; + + if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return m_videoOutputControl; + + if (qstrcmp(name, QVideoWindowControl_iid) == 0) + return m_videoWidnowControl; + + if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return m_videoRendererControl; + + if (qstrcmp(name, QVideoWidgetControl_iid) == 0) + return m_videoWidgetControl; + + if (qstrcmp(name, QMetaDataControl_iid) == 0) + return m_playerMetaDataControl; + + return 0; +} + +void QT7PlayerService::updateVideoOutput() +{ + qDebug() << "QT7PlayerService::updateVideoOutput" << m_videoOutputControl->output(); + + switch (m_videoOutputControl->output()) { + case QVideoOutputControl::WindowOutput: + m_session->setVideoOutput(m_videoWidnowControl); + break; + case QVideoOutputControl::RendererOutput: + m_session->setVideoOutput(m_videoRendererControl); + break; + case QVideoOutputControl::WidgetOutput: + m_session->setVideoOutput(m_videoWidgetControl); + break; + default: + m_session->setVideoOutput(0); + } +} + +QT_END_NAMESPACE + +#include "moc_qt7playerservice.cpp" diff --git a/src/plugins/mediaservices/qt7/qt7playersession.h b/src/plugins/mediaservices/qt7/qt7playersession.h new file mode 100644 index 0000000..55505ee --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playersession.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERSESSION_H +#define QT7PLAYERSESSION_H + +#include +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7PlayerControl; +class QMediaPlaylist; +class QMediaPlaylistNavigator; +class QT7VideoOutput; +class QT7PlayerSession; +class QT7PlayerService; + +class QT7PlayerSession : public QObject +{ +Q_OBJECT +public: + QT7PlayerSession(QObject *parent = 0); + ~QT7PlayerSession(); + + void *movie() const; + + void setControl(QT7PlayerControl *control); + void setVideoOutput(QT7VideoOutput *output); + + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent &content, QIODevice *stream); + + qint64 position() const; + qint64 duration() const; + + int bufferStatus() const; + + int volume() const; + bool isMuted() const; + + bool isVideoAvailable() const; + + bool isSeekable() const; + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + void setPosition(qint64 pos); + + void play(); + void pause(); + void stop(); + + void setVolume(int volume); + void setMuted(bool muted); + + void processEOS(); + +signals: + void positionChanged(qint64 position); + void durationChanged(qint64 duration); + void stateChanged(QMediaPlayer::State newState); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + void error(int error, const QString &errorString); + +private: + void *m_QTMovie; + void *m_movieObserver; + + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_mediaStatus; + QIODevice *m_mediaStream; + QMediaContent m_resources; + + QT7VideoOutput *m_videoOutput; + + mutable qint64 m_currentTime; + + bool m_muted; + int m_volume; + qreal m_rate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7playersession.mm b/src/plugins/mediaservices/qt7/qt7playersession.mm new file mode 100644 index 0000000..3131a90 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7playersession.mm @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import +#import + +#include "qt7backend.h" + +#include "qt7playersession.h" +#include "qt7playercontrol.h" +#include "qt7videooutputcontrol.h" + +#include + +#include + +#include +#include + + +QT_BEGIN_NAMESPACE + +@interface QTMovieObserver : NSObject +{ +@private + QT7PlayerSession *m_session; + QTMovie *m_movie; +} + +- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session; +- (void) setMovie:(QTMovie *)movie; +- (void) processEOS:(NSNotification *)notification; +@end + +@implementation QTMovieObserver + +- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session +{ + if (!(self = [super init])) + return nil; + + self->m_session = session; + return self; +} + +- (void) setMovie:(QTMovie *)movie +{ + if (m_movie == movie) + return; + + if (m_movie) { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [m_movie release]; + } + + m_movie = movie; + + if (movie) { + [[NSNotificationCenter defaultCenter] addObserver: self selector: + @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie]; + + [movie retain]; + } +} + +- (void) processEOS:(NSNotification *)notification +{ + Q_UNUSED(notification); + m_session->processEOS(); +} + +@end + +static CFStringRef qString2CFStringRef(const QString &string) +{ + return CFStringCreateWithCharacters(0, reinterpret_cast(string.unicode()), + string.length()); +} + +QT7PlayerSession::QT7PlayerSession(QObject *parent) + : QObject(parent) + , m_QTMovie(0) + , m_state(QMediaPlayer::StoppedState) + , m_mediaStatus(QMediaPlayer::NoMedia) + , m_mediaStream(0) + , m_videoOutput(0) + , m_muted(false) + , m_volume(100) + , m_rate(1.0) +{ + m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this]; +} + +QT7PlayerSession::~QT7PlayerSession() +{ + [(QTMovieObserver*)m_movieObserver setMovie:nil]; + [(QTMovieObserver*)m_movieObserver release]; +} + +void *QT7PlayerSession::movie() const +{ + return m_QTMovie; +} + +void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output) +{ + if (m_videoOutput == output) + return; + + qDebug() << "set output" << output; + + if (m_videoOutput) { + m_videoOutput->setEnabled(false); + m_videoOutput->setMovie(0); + } + + m_videoOutput = output; + + if (m_videoOutput) { + m_videoOutput->setEnabled(m_QTMovie != 0); + m_videoOutput->setMovie(m_QTMovie); + } +} + + +qint64 QT7PlayerSession::position() const +{ + if (!m_QTMovie || m_state == QMediaPlayer::PausedState) + return m_currentTime; + + AutoReleasePool pool; + + QTTime qtTime = [(QTMovie*)m_QTMovie currentTime]; + quint64 t = static_cast(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); + m_currentTime = t; + + return m_currentTime; +} + +qint64 QT7PlayerSession::duration() const +{ + if (!m_QTMovie) + return 0; + + AutoReleasePool pool; + + QTTime qtTime = [(QTMovie*)m_QTMovie duration]; + + return static_cast(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); +} + +QMediaPlayer::State QT7PlayerSession::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus QT7PlayerSession::mediaStatus() const +{ + return m_mediaStatus; +} + +int QT7PlayerSession::bufferStatus() const +{ + return 100; +} + +int QT7PlayerSession::volume() const +{ + return m_volume; +} + +bool QT7PlayerSession::isMuted() const +{ + return m_muted; +} + +bool QT7PlayerSession::isSeekable() const +{ + return true; +} + +qreal QT7PlayerSession::playbackRate() const +{ + return m_rate; +} + +void QT7PlayerSession::setPlaybackRate(qreal rate) +{ + if (qFuzzyCompare(m_rate, rate)) + return; + + m_rate = rate; + + if (m_QTMovie && m_state == QMediaPlayer::PlayingState) { + float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; + [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; + } +} + +void QT7PlayerSession::setPosition(qint64 pos) +{ + if ( !isSeekable() || pos == position()) + return; + + AutoReleasePool pool; + + pos = qMin(pos, duration()); + + QTTime newQTTime = [(QTMovie*)m_QTMovie currentTime]; + newQTTime.timeValue = (pos / 1000.0f) * newQTTime.timeScale; + [(QTMovie*)m_QTMovie setCurrentTime:newQTTime]; +} + +void QT7PlayerSession::play() +{ + m_state = QMediaPlayer::PlayingState; + + float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; + [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; + + emit stateChanged(m_state); +} + +void QT7PlayerSession::pause() +{ + m_state = QMediaPlayer::PausedState; + + [(QTMovie*)m_QTMovie setRate:0]; + + emit stateChanged(m_state); +} + +void QT7PlayerSession::stop() +{ + m_state = QMediaPlayer::StoppedState; + + [(QTMovie*)m_QTMovie setRate:0]; + setPosition(0); + + if (m_state == QMediaPlayer::StoppedState) + emit stateChanged(m_state); +} + +void QT7PlayerSession::setVolume(int volume) +{ + if (m_QTMovie) { + m_volume = volume; + [(QTMovie*)m_QTMovie setVolume:(volume/100.0f)]; + } +} + +void QT7PlayerSession::setMuted(bool muted) +{ + if (m_muted != muted) { + m_muted = muted; + + if (m_QTMovie) + [(QTMovie*)m_QTMovie setMuted:m_muted]; + + emit mutedChanged(muted); + } +} + +QMediaContent QT7PlayerSession::media() const +{ + return m_resources; +} + +const QIODevice *QT7PlayerSession::mediaStream() const +{ + return m_mediaStream; +} + +void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) +{ + AutoReleasePool pool; + + if (m_QTMovie) { + [(QTMovieObserver*)m_movieObserver setMovie:nil]; + + if (m_videoOutput) { + m_videoOutput->setEnabled(false); + m_videoOutput->setMovie(0); + } + + [(QTMovie*)m_QTMovie release]; + m_QTMovie = 0; + } + + m_resources = content; + m_mediaStream = stream; + + QUrl url; + + if (!content.isNull()) + url = content.canonicalUrl(); + else + return; + + NSError *err = 0; + QTDataReference *dataRef = 0; + + if ( url.scheme() == "file" ) { + NSString *nsFileName = (NSString *)qString2CFStringRef( url.toLocalFile() ); + dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFileName]; + } else { + NSString *urlString = (NSString *)qString2CFStringRef( url.toString() ); + NSURL *url = [NSURL URLWithString: urlString]; + dataRef = [QTDataReference dataReferenceWithReferenceToURL:url]; + } + + NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys: + dataRef, QTMovieDataReferenceAttribute, + [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute, + [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute, + [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute, + [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute, + nil]; + + m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain]; + + if (err) { + [(QTMovie*)m_QTMovie release]; + m_QTMovie = 0; + QString description = QString::fromUtf8([[err localizedDescription] UTF8String]); + + qDebug() << "QT7PlayerSession::setMedia error" << description; + emit error(QMediaPlayer::FormatError, description ); + } else { + [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie]; + + if (m_videoOutput) { + m_videoOutput->setEnabled(true); + m_videoOutput->setMovie(m_QTMovie); + } + + emit durationChanged(duration()); + emit videoAvailableChanged(isVideoAvailable()); + + [(QTMovie*)m_QTMovie setMuted:m_muted]; + setVolume(m_volume); + } +} + +bool QT7PlayerSession::isVideoAvailable() const +{ + if (!m_QTMovie) + return false; + + AutoReleasePool pool; + return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES; +} + +void QT7PlayerSession::processEOS() +{ + m_mediaStatus = QMediaPlayer::EndOfMedia; + emit stateChanged(m_state = QMediaPlayer::StoppedState); + emit mediaStatusChanged(m_mediaStatus); +} + +#include "moc_qt7playersession.cpp" + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/qt7/qt7serviceplugin.h b/src/plugins/mediaservices/qt7/qt7serviceplugin.h new file mode 100644 index 0000000..c5afda1 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7serviceplugin.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QT7SERVICEPLUGIN_H +#define QT7SERVICEPLUGIN_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7ServicePlugin : public QMediaServiceProviderPlugin +{ +public: + QStringList keys() const; + QMediaService* create(QString const& key); + void release(QMediaService *service); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERSERVICEPLUGIN_H diff --git a/src/plugins/mediaservices/qt7/qt7serviceplugin.mm b/src/plugins/mediaservices/qt7/qt7serviceplugin.mm new file mode 100644 index 0000000..49ae8e0 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7serviceplugin.mm @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qt7serviceplugin.h" +#include "qt7playerservice.h" + +#include + +QT_BEGIN_NAMESPACE + +QStringList QT7ServicePlugin::keys() const +{ + return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); +} + +QMediaService* QT7ServicePlugin::create(QString const& key) +{ + qDebug() << "QT7ServicePlugin::create" << key; + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) + return new QT7PlayerService; + + qDebug() << "unsupported key:" << key; + return 0; +} + +void QT7ServicePlugin::release(QMediaService *service) +{ + delete service; +} + +Q_EXPORT_PLUGIN2(qt7_serviceplugin, QT7ServicePlugin); + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h new file mode 100644 index 0000000..2faf6bb --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7VIDEOOUTPUTCONTROL_H +#define QT7VIDEOOUTPUTCONTROL_H + +#include + +#include +#include +#include +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaPlaylist; +class QMediaPlaylistNavigator; +class QT7PlayerSession; +class QT7PlayerService; + + +class QT7VideoOutput { +public: + virtual ~QT7VideoOutput() {} + virtual void setEnabled(bool enabled) = 0; + virtual void setMovie(void *movie) = 0; +}; + +class QT7VideoWindowControl : public QVideoWindowControl, public QT7VideoOutput +{ +public: + virtual ~QT7VideoWindowControl() {} + +protected: + QT7VideoWindowControl(QObject *parent) + :QVideoWindowControl(parent) + {} +}; + +class QT7VideoRendererControl : public QVideoRendererControl, public QT7VideoOutput +{ +public: + virtual ~QT7VideoRendererControl() {} + +protected: + QT7VideoRendererControl(QObject *parent) + :QVideoRendererControl(parent) + {} +}; + +class QT7VideoWidgetControl : public QVideoWidgetControl, public QT7VideoOutput +{ +public: + virtual ~QT7VideoWidgetControl() {} + +protected: + QT7VideoWidgetControl(QObject *parent) + :QVideoWidgetControl(parent) + {} +}; + +class QT7VideoOutputControl : public QVideoOutputControl +{ +Q_OBJECT +public: + QT7VideoOutputControl(QObject *parent = 0); + ~QT7VideoOutputControl(); + + void setSession(QT7PlayerSession *session); + + QList availableOutputs() const; + void enableOutput(Output); + + Output output() const; + void setOutput(Output output); + +signals: + void videoOutputChanged(QVideoOutputControl::Output); + +private: + QT7PlayerSession *m_session; + Output m_output; + QList m_outputs; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/qt7videooutputcontrol.mm b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.mm new file mode 100644 index 0000000..a468431 --- /dev/null +++ b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.mm @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt7playercontrol.h" +#include "qt7videooutputcontrol.h" +#include "qt7playersession.h" +#include + +QT_BEGIN_NAMESPACE + +QT7VideoOutputControl::QT7VideoOutputControl(QObject *parent) + :QVideoOutputControl(parent), + m_session(0), + m_output(QVideoOutputControl::NoOutput) +{ +} + +QT7VideoOutputControl::~QT7VideoOutputControl() +{ +} + +void QT7VideoOutputControl::setSession(QT7PlayerSession *session) +{ + m_session = session; +} + +QList QT7VideoOutputControl::availableOutputs() const +{ + return m_outputs; +} + +void QT7VideoOutputControl::enableOutput(QVideoOutputControl::Output output) +{ + if (!m_outputs.contains(output)) + m_outputs.append(output); +} + +QVideoOutputControl::Output QT7VideoOutputControl::output() const +{ + return m_output; +} + +void QT7VideoOutputControl::setOutput(Output output) +{ + if (m_output != output) { + m_output = output; + emit videoOutputChanged(m_output); + } + +} + +QT_END_NAMESPACE + +#include "moc_qt7videooutputcontrol.cpp" + diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 004b816..5eca0f4 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -11,4 +11,5 @@ embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers !win32:!embedded:!mac:!symbian:SUBDIRS *= inputmethods symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon -contains(QT_CONFIG, multimedia): SUBDIRS *= audio +contains(QT_CONFIG, multimedia): SUBDIRS *= audio mediaservices + diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 4215e97..50ab902 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -294,6 +294,17 @@ SUBDIRS += \ qaudioformat \ qaudiooutput \ qaudioinput \ + qmediacontent \ + qmediaobject \ + qmediaplayer \ + qmediaplaylist \ + qmediaplaylistnavigator \ + qmediapluginloader \ + qmediaresource \ + qmediaservice \ + qmediaserviceprovider \ + qmediatimerange \ + qvideowidget \ qspinbox \ qsplitter \ qsql \ diff --git a/tests/auto/qmediacontent/qmediacontent.pro b/tests/auto/qmediacontent/qmediacontent.pro new file mode 100644 index 0000000..f7884f6 --- /dev/null +++ b/tests/auto/qmediacontent/qmediacontent.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES += tst_qmediacontent.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediacontent/tst_qmediacontent.cpp b/tests/auto/qmediacontent/tst_qmediacontent.cpp new file mode 100644 index 0000000..4857672 --- /dev/null +++ b/tests/auto/qmediacontent/tst_qmediacontent.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + + +class tst_QMediaContent : public QObject +{ + Q_OBJECT + +private slots: + void testNull(); + void testUrlCtor(); + 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::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/qmediaobject/qmediaobject.pro b/tests/auto/qmediaobject/qmediaobject.pro new file mode 100644 index 0000000..e59bfdc --- /dev/null +++ b/tests/auto/qmediaobject/qmediaobject.pro @@ -0,0 +1,4 @@ +load(qttest_p4) + +SOURCES += tst_qmediaobject.cpp +QT = core multimedia diff --git a/tests/auto/qmediaobject/tst_qmediaobject.cpp b/tests/auto/qmediaobject/tst_qmediaobject.cpp new file mode 100644 index 0000000..0370fff --- /dev/null +++ b/tests/auto/qmediaobject/tst_qmediaobject.cpp @@ -0,0 +1,549 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +#include +#include +#include + + +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 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: + void setupNotifyTests(); +}; + +class QtTestMetaDataProvider : public QMetaDataControl +{ + Q_OBJECT +public: + QtTestMetaDataProvider(QObject *parent = 0) + : QMetaDataControl(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(QtMedia::MetaData key) const { return m_data.value(key); } + void setMetaData(QtMedia::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 QMetaDataControl::metaDataChanged; + + void populateMetaData() + { + m_available = true; + } + + bool m_available; + bool m_writable; + QMap m_data; + QMap m_extendedData; +}; + +class QtTestMetaDataService : public QMediaService +{ + Q_OBJECT +public: + QtTestMetaDataService(QObject *parent = 0):QMediaService(parent), hasMetaData(true) + { + } + + QMediaControl *control(const char *iid) const + { + if (hasMetaData && qstrcmp(iid, QMetaDataControl_iid) == 0) + return const_cast(&metaData); + else + return 0; + } + + QtTestMetaDataProvider metaData; + 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; +}; + +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.isMetaDataWritable(), false); + + object.setMetaData(QtMedia::Title, title); + object.setExtendedMetaData(titleKey, title); + + QCOMPARE(object.metaData(QtMedia::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::isWritable() +{ + QtTestMetaDataService service; + service.metaData.setWritable(false); + + QtTestMediaObject object(&service); + + QSignalSpy spy(&object, SIGNAL(metaDataWritableChanged(bool))); + + QCOMPARE(object.isMetaDataWritable(), false); + + service.metaData.setWritable(true); + + QCOMPARE(object.isMetaDataWritable(), true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).at(0).toBool(), true); + + service.metaData.setWritable(false); + + QCOMPARE(object.isMetaDataWritable(), 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(QtMedia::AlbumArtist, artist); + service.metaData.m_data.insert(QtMedia::Title, title); + service.metaData.m_data.insert(QtMedia::Genre, genre); + + QCOMPARE(object.metaData(QtMedia::AlbumArtist).toString(), artist); + QCOMPARE(object.metaData(QtMedia::Title).toString(), title); + + QList metaDataKeys = object.availableMetaData(); + QCOMPARE(metaDataKeys.size(), 3); + QVERIFY(metaDataKeys.contains(QtMedia::AlbumArtist)); + QVERIFY(metaDataKeys.contains(QtMedia::Title)); + QVERIFY(metaDataKeys.contains(QtMedia::Genre)); +} + +void tst_QMediaObject::setMetaData_data() +{ + QTest::addColumn("title"); + + QTest::newRow("") + << QString::fromLatin1("In the Kingdom of the Blind the One eyed are Kings"); +} + +void tst_QMediaObject::setMetaData() +{ + QFETCH(QString, title); + + QtTestMetaDataService service; + service.metaData.populateMetaData(); + + QtTestMediaObject object(&service); + + object.setMetaData(QtMedia::Title, title); + QCOMPARE(object.metaData(QtMedia::Title).toString(), title); + QCOMPARE(service.metaData.m_data.value(QtMedia::Title).toString(), title); +} + +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::setExtendedMetaData() +{ + QtTestMetaDataService service; + service.metaData.populateMetaData(); + + QtTestMediaObject object(&service); + + QString title(QLatin1String("In the Kingdom of the Blind the One eyed are Kings")); + + object.setExtendedMetaData(QLatin1String("Title"), title); + QCOMPARE(object.extendedMetaData(QLatin1String("Title")).toString(), title); + QCOMPARE(service.metaData.m_extendedData.value(QLatin1String("Title")).toString(), title); +} + +QTEST_MAIN(tst_QMediaObject) + +#include "tst_qmediaobject.moc" diff --git a/tests/auto/qmediaplayer/qmediaplayer.pro b/tests/auto/qmediaplayer/qmediaplayer.pro new file mode 100644 index 0000000..21008f9 --- /dev/null +++ b/tests/auto/qmediaplayer/qmediaplayer.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES += tst_qmediaplayer.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp new file mode 100644 index 0000000..a3cba3f --- /dev/null +++ b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp @@ -0,0 +1,1011 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + + + +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 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 _videoAvailable; + bool _isSeekable; + QPair _seekRange; + qreal _playbackRate; + QMediaContent _media; + QIODevice *_stream; + bool _isValid; + QString _errorString; +}; + + +class MockPlayerService : public QMediaService +{ + Q_OBJECT + +public: + MockPlayerService():QMediaService(0) + { + mockControl = new MockPlayerControl; + } + + ~MockPlayerService() + { + delete mockControl; + } + + QMediaControl* control(const char *iid) const + { + if (qstrcmp(iid, QMediaPlayerControl_iid) == 0) + return mockControl; + + return 0; + } + + 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 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(); + } + + MockPlayerControl *mockControl; +}; + +class MockProvider : public QMediaServiceProvider +{ +public: + MockProvider(MockPlayerService *service):mockService(service) {} + QMediaService *requestService(const QByteArray &, const QMediaServiceProviderHint &) + { + return mockService; + } + + void releaseService(QMediaService *service) { delete service; } + + MockPlayerService *mockService; +}; + +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 testVideoAvailable(); + void testBufferStatus(); + void testSeekable(); + void testPlaybackRate(); + void testError(); + void testErrorString(); + void testService(); + void testPlay(); + void testPause(); + void testStop(); + void testMediaStatus(); + void testPlaylist(); + +private: + MockProvider *mockProvider; + MockPlayerService *mockService; + QMediaPlayer *player; +}; + +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); + + { + 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; + playlist.setMediaObject(&player); + + 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::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); + +#ifdef QTM_NAMESPACE + //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace + QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); +#endif + QCOMPARE(qvariant_cast(statusSpy.last().value(0)), + QMediaPlayer::LoadingMedia); + + mockService->setMediaStatus(QMediaPlayer::LoadedMedia); + QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadedMedia); + QCOMPARE(statusSpy.count(), 2); + +#ifdef QTM_NAMESPACE + //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace + QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); +#endif + 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); + +#ifdef QTM_NAMESPACE + //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace + QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); +#endif + 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); + +#ifdef QTM_NAMESPACE + //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace + QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); +#endif + 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); + +#ifdef QTM_NAMESPACE + //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace + QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); +#endif + 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); + +#ifdef QTM_NAMESPACE + //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace + QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); +#endif + 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; + playlist->setMediaObject(player); + + 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; + playlist->setMediaObject(player); + QCOMPARE(playlist->mediaObject(), qobject_cast(player)); + + 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(); + playlist2->setMediaObject(player); + QCOMPARE(playlist2->mediaObject(), qobject_cast(player)); + QVERIFY(playlist->mediaObject() == 0); + QCOMPARE(player->media(), playlist2->currentMedia()); + QCOMPARE(player->state(), QMediaPlayer::StoppedState); + + playlist2->setCurrentIndex(1); + QCOMPARE(player->media(), playlist2->currentMedia()); +} + +QTEST_MAIN(tst_QMediaPlayer) + +#include "tst_qmediaplayer.moc" diff --git a/tests/auto/qmediaplaylist/qmediaplaylist.pro b/tests/auto/qmediaplaylist/qmediaplaylist.pro new file mode 100644 index 0000000..b114bda --- /dev/null +++ b/tests/auto/qmediaplaylist/qmediaplaylist.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediaplaylist.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediaplaylist/tmp.unsupported_format b/tests/auto/qmediaplaylist/tmp.unsupported_format new file mode 100644 index 0000000..e69de29 diff --git a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp new file mode 100644 index 0000000..88a2f31 --- /dev/null +++ b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp @@ -0,0 +1,622 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + + +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* control(const char *iid) const + { + if (qstrcmp(iid, QMediaPlaylistControl_iid) == 0) + return mockControl; + return 0; + } + + 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 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"))); +} + +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); + + QTest::ignoreMessage(QtWarningMsg, "Load static plugins for \"/playlistformats/\" "); + 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)); + + res = playlist.save(QUrl(QLatin1String("tmp.m3u")), "m3u"); + QVERIFY(res); + + playlist2.clear(); + QVERIFY(playlist2.isEmpty()); + playlist2.load(QUrl(QLatin1String("tmp.m3u")), "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)); +} + +void tst_QMediaPlaylist::playbackMode_data() +{ + QTest::addColumn("playbackMode"); + QTest::addColumn("expectedPrevious"); + QTest::addColumn("pos"); + QTest::addColumn("expectedNext"); + + QTest::newRow("Linear, 0") << QMediaPlaylist::Linear << -1 << 0 << 1; + QTest::newRow("Linear, 1") << QMediaPlaylist::Linear << 0 << 1 << 2; + QTest::newRow("Linear, 2") << QMediaPlaylist::Linear << 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::Linear); + 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()); + + playlist.setMediaObject(&mediaObject); + QCOMPARE(playlist.mediaObject(), qobject_cast(&mediaObject)); + QCOMPARE(playlist.mediaCount(), 3); + QVERIFY(playlist.isReadOnly()); + + playlist.setMediaObject(0); + QVERIFY(playlist.mediaObject() == 0); + QCOMPARE(playlist.mediaCount(), 0); + QVERIFY(!playlist.isReadOnly()); + + playlist.setMediaObject(&mediaObject); + 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 0000000..ea9bc0f --- /dev/null +++ b/tests/auto/qmediaplaylistnavigator/qmediaplaylistnavigator.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediaplaylistnavigator.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp new file mode 100644 index 0000000..a5eb3fe --- /dev/null +++ b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + + +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::Linear); + 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 0000000..66950e9 --- /dev/null +++ b/tests/auto/qmediapluginloader/qmediapluginloader.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediapluginloader.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp new file mode 100644 index 0000000..1ed23a0 --- /dev/null +++ b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include + + + +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/qmediaresource/qmediaresource.pro b/tests/auto/qmediaresource/qmediaresource.pro new file mode 100644 index 0000000..2741608 --- /dev/null +++ b/tests/auto/qmediaresource/qmediaresource.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediaresource.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediaresource/tst_qmediaresource.cpp b/tests/auto/qmediaresource/tst_qmediaresource.cpp new file mode 100644 index 0000000..55ddcab --- /dev/null +++ b/tests/auto/qmediaresource/tst_qmediaresource.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + + +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.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("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")) + << 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")) + << 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")) + << 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")) + << QString::fromLatin1("image/png") + << QString() + << QString() + << QString() + << qint64(2360) + << 0 + << 0 + << 0 + << 0 + << QSize(128, 128); +} + +void tst_QMediaResource::construct() +{ + QFETCH(QUrl, url); + 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.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")); + + 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 0000000..f877665 --- /dev/null +++ b/tests/auto/qmediaservice/qmediaservice.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediaservice.cpp + +QT = core gui multimedia + diff --git a/tests/auto/qmediaservice/tst_qmediaservice.cpp b/tests/auto/qmediaservice/tst_qmediaservice.cpp new file mode 100644 index 0000000..3c3684a --- /dev/null +++ b/tests/auto/qmediaservice/tst_qmediaservice.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +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 +}; + +struct QtTestDevice +{ + QtTestDevice() {} + QtTestDevice(const QString &name, const QString &description, const QIcon &icon) + : name(name), description(description), icon(icon) + { + } + + QString name; + QString description; + QIcon icon; +}; + +class QtTestVideoDeviceControl : public QVideoDeviceControl +{ +public: + QtTestVideoDeviceControl(QObject *parent = 0) + : QVideoDeviceControl(parent) + , m_selectedDevice(-1) + , m_defaultDevice(-1) + { + } + + int deviceCount() const { return devices.count(); } + + QString deviceName(int index) const { return devices.value(index).name; } + QString deviceDescription(int index) const { return devices.value(index).description; } + QIcon deviceIcon(int index) const { return devices.value(index).icon; } + + int defaultDevice() const { return m_defaultDevice; } + void setDefaultDevice(int index) { m_defaultDevice = index; } + + int selectedDevice() const { return m_selectedDevice; } + void setSelectedDevice(int index) + { + emit selectedDeviceChanged(m_selectedDevice = index); + emit selectedDeviceChanged(devices.value(index).name); + } + + QList devices; + +private: + int m_selectedDevice; + int m_defaultDevice; +}; + +class QtTestMediaService : public QMediaService +{ + Q_OBJECT +public: + QtTestMediaService() + : QMediaService(0) + , hasDeviceControls(false) + { + } + + QMediaControl* control(const char *name) const + { + if (strcmp(name, QtTestMediaControlA_iid) == 0) + return const_cast(&controlA); + else if (strcmp(name, QtTestMediaControlB_iid) == 0) + return const_cast(&controlB); + else if (strcmp(name, QtTestMediaControlC_iid) == 0) + return const_cast(&controlC); + else if (hasDeviceControls && strcmp(name, QVideoDeviceControl_iid) == 0) + return const_cast(&videoDeviceControl); + else + return 0; + } + + using QMediaService::control; + + QtTestMediaControlA controlA; + QtTestMediaControlB controlB; + QtTestMediaControlC controlC; + QtTestVideoDeviceControl videoDeviceControl; + bool hasDeviceControls; +}; + +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; + + QCOMPARE(service.control(), &service.controlA); + QCOMPARE(service.control(), &service.controlB); + QVERIFY(!service.control()); // Faulty implementation returns A. + QVERIFY(!service.control()); // No control of that type. +} + +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 0000000..9aaa9e5 --- /dev/null +++ b/tests/auto/qmediaserviceprovider/qmediaserviceprovider.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediaserviceprovider.cpp + +QT = core gui multimedia + diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp new file mode 100644 index 0000000..a2c1be5 --- /dev/null +++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp @@ -0,0 +1,458 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +class MockMediaService : public QMediaService +{ + Q_OBJECT +public: + MockMediaService(const QString& name, QObject *parent = 0) : QMediaService(parent) + { setObjectName(name); } + ~MockMediaService() {} + + QMediaControl* control(const char *) const {return 0;} +}; + +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) << + QLatin1String(Q_MEDIASERVICE_CAMERA); + } + + QMediaService* create(QString const& key) + { + if (keys().contains(key)) + return new MockMediaService("MockServicePlugin1"); + else + return 0; + } + + void release(QMediaService *service) + { + delete service; + } + + QtMedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + { + if (codecs.contains(QLatin1String("mpeg4"))) + return QtMedia::NotSupported; + + if (mimeType == "audio/ogg") { + return QtMedia::ProbablySupported; + } + + return QtMedia::MaybeSupported; + } + + QStringList supportedMimeTypes() const + { + return QStringList("audio/ogg"); + } + + QList devices(const QByteArray &service) const + { + QList res; + if (service == QByteArray(Q_MEDIASERVICE_CAMERA)) + res << "camera1" << "camera2"; + 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); + } + + QMediaService* create(QString const& key) + { + if (keys().contains(key)) + return new MockMediaService("MockServicePlugin2"); + else + return 0; + } + + void release(QMediaService *service) + { + delete service; + } + + QtMedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + { + Q_UNUSED(codecs); + + if (mimeType == "audio/wav") + return QtMedia::PreferedService; + + return QtMedia::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_CAMERA) << + 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_CAMERA)) + res << "camera3" << "camera4"; + else 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 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 testDevices(); + void testProviderHints(); + +private: + QObjectList plugins; +}; + +void tst_QMediaServiceProvider::initTestCase() +{ + plugins << new MockServicePlugin1; + plugins << new MockServicePlugin2; + plugins << new MockServicePlugin3; + + 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; + + QTest::ignoreMessage(QtWarningMsg, "Load static plugins for \"/mediaservice/\" "); + // 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()), + QtMedia::MaybeSupported); + + QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); + + if (provider == 0) + QSKIP("No default provider", SkipSingle); + + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()), + QtMedia::MaybeSupported); + + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/ogg", QStringList()), + QtMedia::ProbablySupported); + + //while the service returns PreferredService, provider should return ProbablySupported + QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/wav", QStringList()), + QtMedia::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"), + QtMedia::MaybeSupported); + + QCOMPARE(provider->hasSupport(QByteArray("non existing service"), "video/ogv", QStringList()), + QtMedia::NotSupported); + + QCOMPARE(QMediaPlayer::hasSupport("video/ogv"), QtMedia::MaybeSupported); + QCOMPARE(QMediaPlayer::hasSupport("audio/ogg"), QtMedia::ProbablySupported); + QCOMPARE(QMediaPlayer::hasSupport("audio/wav"), QtMedia::ProbablySupported); + + //ensure the correct media player plugin is choosen for mime type + QMediaPlayer simplePlayer(0, QMediaPlayer::LowLatency); + QCOMPARE(simplePlayer.service()->objectName(), QLatin1String("MockServicePlugin2")); + + QMediaPlayer mediaPlayer; + QVERIFY(mediaPlayer.service()->objectName() != QLatin1String("MockServicePlugin2")); +} + +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::testDevices() +{ + MockMediaServiceProvider mockProvider; + QVERIFY(mockProvider.devices(QByteArray(Q_MEDIASERVICE_CAMERA)).isEmpty()); + QVERIFY(mockProvider.deviceDescription(QByteArray(Q_MEDIASERVICE_CAMERA), + QByteArray()).isEmpty()); + + QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); + + QList cameraDevices = provider->devices(QByteArray(Q_MEDIASERVICE_CAMERA)); + QCOMPARE(cameraDevices.count(), 4); + QVERIFY(cameraDevices.contains(QByteArray("camera1"))); + QVERIFY(cameraDevices.contains(QByteArray("camera2"))); + QVERIFY(cameraDevices.contains(QByteArray("camera3"))); + QVERIFY(cameraDevices.contains(QByteArray("camera4"))); + + /* + //ensure the right plugin is choosen for a device + QCamera camera1(QByteArray("camera1")); + QCOMPARE( camera1.service()->objectName(), QLatin1String("MockServicePlugin1") ); + QCamera camera2(QByteArray("camera2")); + QCOMPARE( camera2.service()->objectName(), QLatin1String("MockServicePlugin1") ); + QCamera camera3(QByteArray("camera3")); + QCOMPARE( camera3.service()->objectName(), QLatin1String("MockServicePlugin3") ); + QCamera camera4(QByteArray("camera4")); + QCOMPARE( camera4.service()->objectName(), QLatin1String("MockServicePlugin3") ); + + QList audioSourceDevices = provider->devices(QByteArray(Q_MEDIASERVICE_AUDIOSOURCE)); + QCOMPARE(audioSourceDevices.count(), 2); + QVERIFY(audioSourceDevices.contains(QByteArray("audiosource1"))); + QVERIFY(audioSourceDevices.contains(QByteArray("audiosource2"))); + + QVERIFY(provider->devices(QByteArray("non existing service")).isEmpty()); + */ +} + + + + +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 0000000..b1b436e --- /dev/null +++ b/tests/auto/qmediatimerange/qmediatimerange.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qmediatimerange.cpp + +QT = core multimedia + diff --git a/tests/auto/qmediatimerange/tst_qmediatimerange.cpp b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp new file mode 100644 index 0000000..a8c58db --- /dev/null +++ b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp @@ -0,0 +1,735 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include + +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/qvideowidget/qvideowidget.pro b/tests/auto/qvideowidget/qvideowidget.pro new file mode 100644 index 0000000..ca0fc24 --- /dev/null +++ b/tests/auto/qvideowidget/qvideowidget.pro @@ -0,0 +1,6 @@ +load(qttest_p4) + +SOURCES = tst_qvideowidget.cpp + +QT = core gui multimedia + diff --git a/tests/auto/qvideowidget/tst_qvideowidget.cpp b/tests/auto/qvideowidget/tst_qvideowidget.cpp new file mode 100644 index 0000000..37676cf --- /dev/null +++ b/tests/auto/qvideowidget/tst_qvideowidget.cpp @@ -0,0 +1,1595 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +class tst_QVideoWidget : public QObject +{ + Q_OBJECT +private slots: + void nullObject(); + void nullService(); + void nullOutputControl(); + 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(QVideoWidget::AspectRatioMode) +Q_DECLARE_METATYPE(const uchar *) + +class QtTestOutputControl : public QVideoOutputControl +{ +public: + QtTestOutputControl() : m_output(NoOutput) {} + + QList availableOutputs() const { return m_outputs; } + void setAvailableOutputs(const QList outputs) { m_outputs = outputs; } + + Output output() const { return m_output; } + virtual void setOutput(Output output) { m_output = output; } + +private: + Output m_output; + QList m_outputs; +}; + +class QtTestWindowControl : public QVideoWindowControl +{ +public: + QtTestWindowControl() + : m_winId(0) + , m_repaintCount(0) + , m_brightness(0) + , m_contrast(0) + , m_saturation(0) + , m_aspectRatioMode(QVideoWidget::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(); } + + QVideoWidget::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; } + void setAspectRatioMode(QVideoWidget::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; + QVideoWidget::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(QVideoWidget::KeepAspectRatio) + , m_fullScreen(false) + { + } + + bool isFullScreen() const { return m_fullScreen; } + void setFullScreen(bool fullScreen) { emit fullScreenChanged(m_fullScreen = fullScreen); } + + QVideoWidget::AspectRatioMode aspectRatioMode() const { return m_aspectRatioMode; } + void setAspectRatioMode(QVideoWidget::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; + QVideoWidget::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( + QtTestOutputControl *output, + QtTestWindowControl *window, + QtTestWidgetControl *widget, + QtTestRendererControl *renderer) + : QMediaService(0) + , outputControl(output) + , windowControl(window) + , widgetControl(widget) + , rendererControl(renderer) + { + } + + ~QtTestVideoService() + { + delete outputControl; + delete windowControl; + delete widgetControl; + delete rendererControl; + } + + QMediaControl *control(const char *name) const + { + if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return outputControl; + else if (qstrcmp(name, QVideoWindowControl_iid) == 0) + return windowControl; + else if (qstrcmp(name, QVideoWidgetControl_iid) == 0) + return widgetControl; + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return rendererControl; + else + return 0; + } + + QtTestOutputControl *outputControl; + QtTestWindowControl *windowControl; + QtTestWidgetControl *widgetControl; + QtTestRendererControl *rendererControl; +}; + +class QtTestVideoObject : public QMediaObject +{ + Q_OBJECT +public: + QtTestVideoObject( + QtTestWindowControl *window, + QtTestWidgetControl *widget, + QtTestRendererControl *renderer): + QMediaObject(0, new QtTestVideoService(new QtTestOutputControl, window, widget, renderer)) + { + testService = qobject_cast(service()); + QList outputs; + + if (window) + outputs.append(QVideoOutputControl::WindowOutput); + if (widget) + outputs.append(QVideoOutputControl::WidgetOutput); + if (renderer) + outputs.append(QVideoOutputControl::RendererOutput); + + testService->outputControl->setAvailableOutputs(outputs); + } + + 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(QVideoWidget::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::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; + widget.setMediaObject(&object); + + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QVERIFY(widget.sizeHint().isEmpty()); + + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.isFullScreen(), true); + + widget.setAspectRatioMode(QVideoWidget::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::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::nullOutputControl() +{ + QtTestVideoObject object(new QtTestVideoService(0, 0, 0, 0)); + + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QVERIFY(widget.sizeHint().isEmpty()); + + widget.setFullScreen(true); + QTest::qWaitForWindowShown(&widget); + 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::noOutputs() +{ + QtTestVideoObject object(0, 0, 0); + + QVideoWidget widget; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + 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(service->outputControl->output(), QVideoOutputControl::NoOutput); + + 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->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(widgetObject.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(rendererObject.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + widget.setMediaObject(&windowObject); + QCOMPARE(widget.mediaObject(), static_cast(&windowObject)); + QCOMPARE(windowObject.testService->outputControl->output(), QVideoOutputControl::WindowOutput); + QVERIFY(windowObject.testService->windowControl->winId() != 0); + + + widget.setMediaObject(&widgetObject); + QCOMPARE(widget.mediaObject(), static_cast(&widgetObject)); + QCOMPARE(widgetObject.testService->outputControl->output(), QVideoOutputControl::WidgetOutput); + + QCoreApplication::processEvents(QEventLoop::AllEvents); + QCOMPARE(widgetObject.testService->widgetControl->videoWidget()->isVisible(), true); + + QCOMPARE(windowObject.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + widget.setMediaObject(&rendererObject); + QCOMPARE(widget.mediaObject(), static_cast(&rendererObject)); + QCOMPARE(rendererObject.testService->outputControl->output(), QVideoOutputControl::RendererOutput); + QVERIFY(rendererObject.testService->rendererControl->surface() != 0); + + QCOMPARE(widgetObject.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + widget.setMediaObject(0); + QCOMPARE(widget.mediaObject(), nullObject); + + QCOMPARE(rendererObject.testService->outputControl->output(), QVideoOutputControl::NoOutput); +} + +void tst_QVideoWidget::showWindowControl() +{ + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setNativeSize(QSize(240, 180)); + + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::WindowOutput); + 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(); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); +} + +void tst_QVideoWidget::showWidgetControl() +{ + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::WidgetOutput); + QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), true); + + widget.resize(640, 480); + + widget.move(10, 10); + + widget.hide(); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), false); +} + +void tst_QVideoWidget::showRendererControl() +{ + QtTestVideoObject object(0, 0, new QtTestRendererControl); + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + widget.show(); + QTest::qWaitForWindowShown(&widget); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); + QVERIFY(object.testService->rendererControl->surface() != 0); + + widget.resize(640, 480); + + widget.move(10, 10); + + widget.hide(); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); +} + +void tst_QVideoWidget::aspectRatioWindowControl() +{ + QtTestVideoObject object(new QtTestWindowControl, 0, 0); + object.testService->windowControl->setAspectRatioMode(QVideoWidget::IgnoreAspectRatio); + + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + // Test the aspect ratio defaults to keeping the aspect ratio. + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + + // Test the control has been informed of the aspect ratio change, post show. + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + QCOMPARE(object.testService->windowControl->aspectRatioMode(), QVideoWidget::KeepAspectRatio); + + // Test an aspect ratio change is enforced immediately while visible. + widget.setAspectRatioMode(QVideoWidget::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::IgnoreAspectRatio); + QCOMPARE(object.testService->windowControl->aspectRatioMode(), QVideoWidget::IgnoreAspectRatio); + + // Test an aspect ratio set while not visible is respected. + widget.hide(); + widget.setAspectRatioMode(QVideoWidget::KeepAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + widget.show(); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + QCOMPARE(object.testService->windowControl->aspectRatioMode(), QVideoWidget::KeepAspectRatio); +} + +void tst_QVideoWidget::aspectRatioWidgetControl() +{ + QtTestVideoObject object(0, new QtTestWidgetControl, 0); + object.testService->widgetControl->setAspectRatioMode(QVideoWidget::IgnoreAspectRatio); + + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + // Test the aspect ratio defaults to keeping the aspect ratio. + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + + // Test the control has been informed of the aspect ratio change, post show. + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + QCOMPARE(object.testService->widgetControl->aspectRatioMode(), QVideoWidget::KeepAspectRatio); + + // Test an aspect ratio change is enforced immediately while visible. + widget.setAspectRatioMode(QVideoWidget::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::IgnoreAspectRatio); + QCOMPARE(object.testService->widgetControl->aspectRatioMode(), QVideoWidget::IgnoreAspectRatio); + + // Test an aspect ratio set while not visible is respected. + widget.hide(); + widget.setAspectRatioMode(QVideoWidget::KeepAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + widget.show(); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + QCOMPARE(object.testService->widgetControl->aspectRatioMode(), QVideoWidget::KeepAspectRatio); +} + +void tst_QVideoWidget::aspectRatioRendererControl() +{ + QtTestVideoObject object(0, 0, new QtTestRendererControl); + + QVideoWidget widget; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + + // Test the aspect ratio defaults to keeping the aspect ratio. + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + + // Test the control has been informed of the aspect ratio change, post show. + widget.show(); + QTest::qWaitForWindowShown(&widget); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + + // Test an aspect ratio change is enforced immediately while visible. + widget.setAspectRatioMode(QVideoWidget::IgnoreAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::IgnoreAspectRatio); + + // Test an aspect ratio set while not visible is respected. + widget.hide(); + widget.setAspectRatioMode(QVideoWidget::KeepAspectRatio); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::KeepAspectRatio); + widget.show(); + QCOMPARE(widget.aspectRatioMode(), QVideoWidget::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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + 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; + widget.setMediaObject(&object); + widget.setWindowFlags(Qt::X11BypassWindowManagerHint); + 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); + + QCoreApplication::processEvents(QEventLoop::AllEvents); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); +} + +QTEST_MAIN(tst_QVideoWidget) + +#include "tst_qvideowidget.moc" diff --git a/tests/auto/tests.xml b/tests/auto/tests.xml index f197de0..96c3094 100644 --- a/tests/auto/tests.xml +++ b/tests/auto/tests.xml @@ -276,6 +276,17 @@ + + + + + + + + + + + -- cgit v0.12 From 70f1fc423cbd6676f4b872fd87579cf41f5240e5 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 18 Jan 2010 12:35:39 +1000 Subject: Multimedia; Add player demo. --- demos/multimedia/player/main.cpp | 54 +++++ demos/multimedia/player/player.cpp | 325 +++++++++++++++++++++++++++++ demos/multimedia/player/player.h | 109 ++++++++++ demos/multimedia/player/player.pro | 22 ++ demos/multimedia/player/playercontrols.cpp | 205 ++++++++++++++++++ demos/multimedia/player/playercontrols.h | 107 ++++++++++ demos/multimedia/player/playlistmodel.cpp | 160 ++++++++++++++ demos/multimedia/player/playlistmodel.h | 95 +++++++++ demos/multimedia/player/videowidget.cpp | 72 +++++++ demos/multimedia/player/videowidget.h | 66 ++++++ 10 files changed, 1215 insertions(+) create mode 100644 demos/multimedia/player/main.cpp create mode 100644 demos/multimedia/player/player.cpp create mode 100644 demos/multimedia/player/player.h create mode 100644 demos/multimedia/player/player.pro create mode 100644 demos/multimedia/player/playercontrols.cpp create mode 100644 demos/multimedia/player/playercontrols.h create mode 100644 demos/multimedia/player/playlistmodel.cpp create mode 100644 demos/multimedia/player/playlistmodel.h create mode 100644 demos/multimedia/player/videowidget.cpp create mode 100644 demos/multimedia/player/videowidget.h diff --git a/demos/multimedia/player/main.cpp b/demos/multimedia/player/main.cpp new file mode 100644 index 0000000..87c5b87 --- /dev/null +++ b/demos/multimedia/player/main.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "player.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + Player player; + player.show(); + + return app.exec(); +}; diff --git a/demos/multimedia/player/player.cpp b/demos/multimedia/player/player.cpp new file mode 100644 index 0000000..38d96d6 --- /dev/null +++ b/demos/multimedia/player/player.cpp @@ -0,0 +1,325 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "player.h" + +#include "playercontrols.h" +#include "playlistmodel.h" +#include "videowidget.h" + +#include +#include + +#include + +Player::Player(QWidget *parent) + : QWidget(parent) + , videoWidget(0) + , coverLabel(0) + , slider(0) + , colorDialog(0) +{ + player = new QMediaPlayer(this); + playlist = new QMediaPlaylist(this); + playlist->setMediaObject(player); + + connect(player, SIGNAL(durationChanged(qint64)), SLOT(durationChanged(qint64))); + connect(player, SIGNAL(positionChanged(qint64)), SLOT(positionChanged(qint64))); + connect(player, SIGNAL(metaDataChanged()), SLOT(metaDataChanged())); + connect(playlist, SIGNAL(currentIndexChanged(int)), SLOT(playlistPositionChanged(int))); + connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + this, SLOT(statusChanged(QMediaPlayer::MediaStatus))); + connect(player, SIGNAL(bufferStatusChanged(int)), this, SLOT(bufferingProgress(int))); + + videoWidget = new VideoWidget; + videoWidget->setMediaObject(player); + + playlistModel = new PlaylistModel(this); + playlistModel->setPlaylist(playlist); + + playlistView = new QListView; + playlistView->setModel(playlistModel); + playlistView->setCurrentIndex(playlistModel->index(playlist->currentIndex(), 0)); + + connect(playlistView, SIGNAL(activated(QModelIndex)), this, SLOT(jump(QModelIndex))); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(0, player->duration() / 1000); + + connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(seek(int))); + + QPushButton *openButton = new QPushButton(tr("Open")); + + connect(openButton, SIGNAL(clicked()), this, SLOT(open())); + + PlayerControls *controls = new PlayerControls; + controls->setState(player->state()); + controls->setVolume(player->volume()); + controls->setMuted(controls->isMuted()); + + connect(controls, SIGNAL(play()), player, SLOT(play())); + connect(controls, SIGNAL(pause()), player, SLOT(pause())); + connect(controls, SIGNAL(stop()), player, SLOT(stop())); + connect(controls, SIGNAL(next()), playlist, SLOT(next())); + connect(controls, SIGNAL(previous()), playlist, SLOT(previous())); + connect(controls, SIGNAL(changeVolume(int)), player, SLOT(setVolume(int))); + connect(controls, SIGNAL(changeMuting(bool)), player, SLOT(setMuted(bool))); + connect(controls, SIGNAL(changeRate(qreal)), player, SLOT(setPlaybackRate(qreal))); + + connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), + controls, SLOT(setState(QMediaPlayer::State))); + connect(player, SIGNAL(volumeChanged(int)), controls, SLOT(setVolume(int))); + connect(player, SIGNAL(mutedChanged(bool)), controls, SLOT(setMuted(bool))); + + QPushButton *fullScreenButton = new QPushButton(tr("FullScreen")); + fullScreenButton->setCheckable(true); + + if (videoWidget != 0) { + connect(fullScreenButton, SIGNAL(clicked(bool)), videoWidget, SLOT(setFullScreen(bool))); + connect(videoWidget, SIGNAL(fullScreenChanged(bool)), + fullScreenButton, SLOT(setChecked(bool))); + } else { + fullScreenButton->setEnabled(false); + } + + QPushButton *colorButton = new QPushButton(tr("Color Options...")); + if (videoWidget) + connect(colorButton, SIGNAL(clicked()), this, SLOT(showColorDialog())); + else + colorButton->setEnabled(false); + + QBoxLayout *displayLayout = new QHBoxLayout; + if (videoWidget) + displayLayout->addWidget(videoWidget, 2); + else + displayLayout->addWidget(coverLabel, 2); + displayLayout->addWidget(playlistView); + + QBoxLayout *controlLayout = new QHBoxLayout; + controlLayout->setMargin(0); + controlLayout->addWidget(openButton); + controlLayout->addStretch(1); + controlLayout->addWidget(controls); + controlLayout->addStretch(1); + controlLayout->addWidget(fullScreenButton); + controlLayout->addWidget(colorButton); + + QBoxLayout *layout = new QVBoxLayout; + layout->addLayout(displayLayout); + layout->addWidget(slider); + layout->addLayout(controlLayout); + + setLayout(layout); + + metaDataChanged(); + + QStringList fileNames = qApp->arguments(); + fileNames.removeAt(0); + foreach (QString const &fileName, fileNames) { + if (QFileInfo(fileName).exists()) + playlist->addMedia(QUrl::fromLocalFile(fileName)); + } +} + +Player::~Player() +{ + delete playlist; + delete player; +} + +void Player::open() +{ + QStringList fileNames = QFileDialog::getOpenFileNames(); + foreach (QString const &fileName, fileNames) + playlist->addMedia(QUrl::fromLocalFile(fileName)); +} + +void Player::durationChanged(qint64 duration) +{ + slider->setMaximum(duration / 1000); +} + +void Player::positionChanged(qint64 progress) +{ + slider->setValue(progress / 1000); +} + +void Player::metaDataChanged() +{ + //qDebug() << "update metadata" << player->metaData(QtMedia::Title).toString(); + if (player->isMetaDataAvailable()) { + setTrackInfo(QString("%1 - %2") + .arg(player->metaData(QtMedia::AlbumArtist).toString()) + .arg(player->metaData(QtMedia::Title).toString())); + + if (coverLabel) { + QUrl url = player->metaData(QtMedia::CoverArtUrlLarge).value(); + + coverLabel->setPixmap(!url.isEmpty() + ? QPixmap(url.toString()) + : QPixmap()); + } + } +} + +void Player::jump(const QModelIndex &index) +{ + if (index.isValid()) { + playlist->setCurrentIndex(index.row()); + player->play(); + } +} + +void Player::playlistPositionChanged(int currentItem) +{ + playlistView->setCurrentIndex(playlistModel->index(currentItem, 0)); +} + +void Player::seek(int seconds) +{ + player->setPosition(seconds * 1000); +} + +void Player::statusChanged(QMediaPlayer::MediaStatus status) +{ + switch (status) { + case QMediaPlayer::UnknownMediaStatus: + case QMediaPlayer::NoMedia: + case QMediaPlayer::LoadedMedia: + case QMediaPlayer::BufferingMedia: + case QMediaPlayer::BufferedMedia: +#ifndef QT_NO_CURSOR + unsetCursor(); +#endif + setStatusInfo(QString()); + break; + case QMediaPlayer::LoadingMedia: +#ifndef QT_NO_CURSOR + setCursor(QCursor(Qt::BusyCursor)); +#endif + setStatusInfo(tr("Loading...")); + break; + case QMediaPlayer::StalledMedia: +#ifndef QT_NO_CURSOR + setCursor(QCursor(Qt::BusyCursor)); +#endif + break; + case QMediaPlayer::EndOfMedia: +#ifndef QT_NO_CURSOR + unsetCursor(); +#endif + setStatusInfo(QString()); + QApplication::alert(this); + break; + case QMediaPlayer::InvalidMedia: +#ifndef QT_NO_CURSOR + unsetCursor(); +#endif + setStatusInfo(player->errorString()); + break; + } +} + +void Player::bufferingProgress(int progress) +{ + setStatusInfo(tr("Buffering %4%%").arg(progress)); +} + +void Player::setTrackInfo(const QString &info) +{ + trackInfo = info; + + if (!statusInfo.isEmpty()) + setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo)); + else + setWindowTitle(trackInfo); + +} + +void Player::setStatusInfo(const QString &info) +{ + statusInfo = info; + + if (!statusInfo.isEmpty()) + setWindowTitle(QString("%1 | %2").arg(trackInfo).arg(statusInfo)); + else + setWindowTitle(trackInfo); +} + +void Player::showColorDialog() +{ + if (!colorDialog) { + QSlider *brightnessSlider = new QSlider(Qt::Horizontal); + brightnessSlider->setRange(-100, 100); + brightnessSlider->setValue(videoWidget->brightness()); + connect(brightnessSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setBrightness(int))); + connect(videoWidget, SIGNAL(brightnessChanged(int)), brightnessSlider, SLOT(setValue(int))); + + QSlider *contrastSlider = new QSlider(Qt::Horizontal); + contrastSlider->setRange(-100, 100); + contrastSlider->setValue(videoWidget->contrast()); + connect(contrastSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setContrast(int))); + connect(videoWidget, SIGNAL(contrastChanged(int)), contrastSlider, SLOT(setValue(int))); + + QSlider *hueSlider = new QSlider(Qt::Horizontal); + hueSlider->setRange(-100, 100); + hueSlider->setValue(videoWidget->hue()); + connect(hueSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setHue(int))); + connect(videoWidget, SIGNAL(hueChanged(int)), hueSlider, SLOT(setValue(int))); + + QSlider *saturationSlider = new QSlider(Qt::Horizontal); + saturationSlider->setRange(-100, 100); + saturationSlider->setValue(videoWidget->saturation()); + connect(saturationSlider, SIGNAL(sliderMoved(int)), videoWidget, SLOT(setSaturation(int))); + connect(videoWidget, SIGNAL(saturationChanged(int)), saturationSlider, SLOT(setValue(int))); + + QFormLayout *layout = new QFormLayout; + layout->addRow(tr("Brightness"), brightnessSlider); + layout->addRow(tr("Contrast"), contrastSlider); + layout->addRow(tr("Hue"), hueSlider); + layout->addRow(tr("Saturation"), saturationSlider); + + colorDialog = new QDialog(this); + colorDialog->setWindowTitle(tr("Color Options")); + colorDialog->setLayout(layout); + } + colorDialog->show(); +} diff --git a/demos/multimedia/player/player.h b/demos/multimedia/player/player.h new file mode 100644 index 0000000..0ad609b --- /dev/null +++ b/demos/multimedia/player/player.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLAYER_H +#define PLAYER_H + +#include + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QAbstractItemView; +class QLabel; +class QModelIndex; +class QSlider; +class QMediaPlayer; +class QVideoWidget; +class PlaylistModel; + +class Player : public QWidget +{ + Q_OBJECT +public: + Player(QWidget *parent = 0); + ~Player(); + +Q_SIGNALS: + void fullScreenChanged(bool fullScreen); + +private slots: + void open(); + void durationChanged(qint64 duration); + void positionChanged(qint64 progress); + void metaDataChanged(); + + void seek(int seconds); + void jump(const QModelIndex &index); + void playlistPositionChanged(int); + + void statusChanged(QMediaPlayer::MediaStatus status); + void bufferingProgress(int progress); + + void showColorDialog(); + +private: + void setTrackInfo(const QString &info); + void setStatusInfo(const QString &info); + + QMediaPlayer *player; + QMediaPlaylist *playlist; + QVideoWidget *videoWidget; + QLabel *coverLabel; + QSlider *slider; + PlaylistModel *playlistModel; + QAbstractItemView *playlistView; + QDialog *colorDialog; + QString trackInfo; + QString statusInfo; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/demos/multimedia/player/player.pro b/demos/multimedia/player/player.pro new file mode 100644 index 0000000..dc731e4 --- /dev/null +++ b/demos/multimedia/player/player.pro @@ -0,0 +1,22 @@ +TEMPLATE = app +TARGET = player + +QT += gui multimedia + + +HEADERS = \ + player.h \ + playercontrols.h \ + playlistmodel.h \ + videowidget.h + +SOURCES = \ + main.cpp \ + player.cpp \ + playercontrols.cpp \ + playlistmodel.cpp \ + videowidget.cpp + +target.path = $$[QT_INSTALL_DEMOS]/multimedia/player +INSTALLS += target + diff --git a/demos/multimedia/player/playercontrols.cpp b/demos/multimedia/player/playercontrols.cpp new file mode 100644 index 0000000..3798a71 --- /dev/null +++ b/demos/multimedia/player/playercontrols.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "playercontrols.h" + +#include +#include +#include +#include +#include + +PlayerControls::PlayerControls(QWidget *parent) + : QWidget(parent) + , playerState(QMediaPlayer::StoppedState) + , playerMuted(false) + , playButton(0) + , stopButton(0) + , nextButton(0) + , previousButton(0) + , muteButton(0) + , volumeSlider(0) + , rateBox(0) +{ + playButton = new QToolButton; + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + + connect(playButton, SIGNAL(clicked()), this, SLOT(playClicked())); + + stopButton = new QToolButton; + stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop)); + stopButton->setEnabled(false); + + connect(stopButton, SIGNAL(clicked()), this, SIGNAL(stop())); + + nextButton = new QToolButton; + nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward)); + + connect(nextButton, SIGNAL(clicked()), this, SIGNAL(next())); + + previousButton = new QToolButton; + previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward)); + + connect(previousButton, SIGNAL(clicked()), this, SIGNAL(previous())); + + muteButton = new QToolButton; + muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume)); + + connect(muteButton, SIGNAL(clicked()), this, SLOT(muteClicked())); + + volumeSlider = new QSlider(Qt::Horizontal); + volumeSlider->setRange(0, 100); + + connect(volumeSlider, SIGNAL(sliderMoved(int)), this, SIGNAL(changeVolume(int))); + + rateBox = new QComboBox; + rateBox->addItem("0.5x", QVariant(0.5)); + rateBox->addItem("1.0x", QVariant(1.0)); + rateBox->addItem("2.0x", QVariant(2.0)); + rateBox->setCurrentIndex(1); + + connect(rateBox, SIGNAL(activated(int)), SLOT(updateRate())); + + QBoxLayout *layout = new QHBoxLayout; + layout->setMargin(0); + layout->addWidget(stopButton); + layout->addWidget(previousButton); + layout->addWidget(playButton); + layout->addWidget(nextButton); + layout->addWidget(muteButton); + layout->addWidget(volumeSlider); + layout->addWidget(rateBox); + setLayout(layout); +} + +QMediaPlayer::State PlayerControls::state() const +{ + return playerState; +} + +void PlayerControls::setState(QMediaPlayer::State state) +{ + if (state != playerState) { + playerState = state; + + switch (state) { + case QMediaPlayer::StoppedState: + stopButton->setEnabled(false); + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + break; + case QMediaPlayer::PlayingState: + stopButton->setEnabled(true); + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); + break; + case QMediaPlayer::PausedState: + stopButton->setEnabled(true); + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + break; + } + } +} + +int PlayerControls::volume() const +{ + return volumeSlider->value(); +} + +void PlayerControls::setVolume(int volume) +{ + volumeSlider->setValue(volume); +} + +bool PlayerControls::isMuted() const +{ + return playerMuted; +} + +void PlayerControls::setMuted(bool muted) +{ + if (muted != playerMuted) { + playerMuted = muted; + + muteButton->setIcon(style()->standardIcon(muted + ? QStyle::SP_MediaVolumeMuted + : QStyle::SP_MediaVolume)); + } +} + +void PlayerControls::playClicked() +{ + switch (playerState) { + case QMediaPlayer::StoppedState: + case QMediaPlayer::PausedState: + emit play(); + break; + case QMediaPlayer::PlayingState: + emit pause(); + break; + } +} + +void PlayerControls::muteClicked() +{ + emit changeMuting(!playerMuted); +} + +qreal PlayerControls::playbackRate() const +{ + return rateBox->itemData(rateBox->currentIndex()).toDouble(); +} + +void PlayerControls::setPlaybackRate(float rate) +{ + for (int i=0; icount(); i++) { + if (qFuzzyCompare(rate, float(rateBox->itemData(i).toDouble()))) { + rateBox->setCurrentIndex(i); + return; + } + } + + rateBox->addItem( QString("%1x").arg(rate), QVariant(rate)); + rateBox->setCurrentIndex(rateBox->count()-1); +} + +void PlayerControls::updateRate() +{ + emit changeRate(playbackRate()); +} diff --git a/demos/multimedia/player/playercontrols.h b/demos/multimedia/player/playercontrols.h new file mode 100644 index 0000000..99894ff --- /dev/null +++ b/demos/multimedia/player/playercontrols.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLAYERCONTROLS_H +#define PLAYERCONTROLS_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QAbstractButton; +class QAbstractSlider; +class QComboBox; + +class PlayerControls : public QWidget +{ + Q_OBJECT +public: + PlayerControls(QWidget *parent = 0); + + QMediaPlayer::State state() const; + + int volume() const; + bool isMuted() const; + qreal playbackRate() const; + +public slots: + void setState(QMediaPlayer::State state); + void setVolume(int volume); + void setMuted(bool muted); + void setPlaybackRate(float rate); + +signals: + void play(); + void pause(); + void stop(); + void next(); + void previous(); + void changeVolume(int volume); + void changeMuting(bool muting); + void changeRate(qreal rate); + +private slots: + void playClicked(); + void muteClicked(); + void updateRate(); + +private: + QMediaPlayer::State playerState; + bool playerMuted; + QAbstractButton *playButton; + QAbstractButton *stopButton; + QAbstractButton *nextButton; + QAbstractButton *previousButton; + QAbstractButton *muteButton; + QAbstractSlider *volumeSlider; + QComboBox *rateBox; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/demos/multimedia/player/playlistmodel.cpp b/demos/multimedia/player/playlistmodel.cpp new file mode 100644 index 0000000..b60f914 --- /dev/null +++ b/demos/multimedia/player/playlistmodel.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "playlistmodel.h" + +#include +#include + +#include + +PlaylistModel::PlaylistModel(QObject *parent) + : QAbstractItemModel(parent) + , m_playlist(0) +{ +} + +int PlaylistModel::rowCount(const QModelIndex &parent) const +{ + return m_playlist && !parent.isValid() ? m_playlist->mediaCount() : 0; +} + +int PlaylistModel::columnCount(const QModelIndex &parent) const +{ + return !parent.isValid() ? ColumnCount : 0; +} + +QModelIndex PlaylistModel::index(int row, int column, const QModelIndex &parent) const +{ + return m_playlist && !parent.isValid() + && row >= 0 && row < m_playlist->mediaCount() + && column >= 0 && column < ColumnCount + ? createIndex(row, column) + : QModelIndex(); +} + +QModelIndex PlaylistModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + + return QModelIndex(); +} + +QVariant PlaylistModel::data(const QModelIndex &index, int role) const +{ + if (index.isValid() && role == Qt::DisplayRole) { + QVariant value = m_data[index]; + if (!value.isValid() && index.column() == Title) { + QUrl location = m_playlist->media(index.row()).canonicalUrl(); + return QFileInfo(location.path()).fileName(); + } + + return value; + } + return QVariant(); +} + +QMediaPlaylist *PlaylistModel::playlist() const +{ + return m_playlist; +} + +void PlaylistModel::setPlaylist(QMediaPlaylist *playlist) +{ + if (m_playlist) { + disconnect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SLOT(beginInsertItems(int,int))); + disconnect(m_playlist, SIGNAL(mediaInserted(int,int)), this, SLOT(endInsertItems())); + disconnect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SLOT(beginRemoveItems(int,int))); + disconnect(m_playlist, SIGNAL(mediaRemoved(int,int)), this, SLOT(endRemoveItems())); + disconnect(m_playlist, SIGNAL(mediaChanged(int,int)), this, SLOT(changeItems(int,int))); + } + + m_playlist = playlist; + + if (m_playlist) { + connect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)), this, SLOT(beginInsertItems(int,int))); + connect(m_playlist, SIGNAL(mediaInserted(int,int)), this, SLOT(endInsertItems())); + connect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)), this, SLOT(beginRemoveItems(int,int))); + connect(m_playlist, SIGNAL(mediaRemoved(int,int)), this, SLOT(endRemoveItems())); + connect(m_playlist, SIGNAL(mediaChanged(int,int)), this, SLOT(changeItems(int,int))); + } + + + reset(); +} + +bool PlaylistModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(role); + m_data[index] = value; + emit dataChanged(index, index); + return true; +} + +void PlaylistModel::beginInsertItems(int start, int end) +{ + m_data.clear(); + beginInsertRows(QModelIndex(), start, end); +} + +void PlaylistModel::endInsertItems() +{ + endInsertRows(); +} + +void PlaylistModel::beginRemoveItems(int start, int end) +{ + m_data.clear(); + beginRemoveRows(QModelIndex(), start, end); +} + +void PlaylistModel::endRemoveItems() +{ + endInsertRows(); +} + +void PlaylistModel::changeItems(int start, int end) +{ + m_data.clear(); + emit dataChanged(index(start,0), index(end,ColumnCount)); +} + + diff --git a/demos/multimedia/player/playlistmodel.h b/demos/multimedia/player/playlistmodel.h new file mode 100644 index 0000000..0180282 --- /dev/null +++ b/demos/multimedia/player/playlistmodel.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PLAYLISTMODEL_H +#define PLAYLISTMODEL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaPlaylist; + +class PlaylistModel : public QAbstractItemModel +{ + Q_OBJECT +public: + enum Column + { + Title = 0, + ColumnCount + }; + + PlaylistModel(QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + QMediaPlaylist *playlist() const; + void setPlaylist(QMediaPlaylist *playlist); + + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole); + +private slots: + void beginInsertItems(int start, int end); + void endInsertItems(); + void beginRemoveItems(int start, int end); + void endRemoveItems(); + void changeItems(int start, int end); + +private: + QMediaPlaylist *m_playlist; + QMap m_data; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/demos/multimedia/player/videowidget.cpp b/demos/multimedia/player/videowidget.cpp new file mode 100644 index 0000000..3bf36c3 --- /dev/null +++ b/demos/multimedia/player/videowidget.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "videowidget.h" + +#include + +VideoWidget::VideoWidget(QWidget *parent) + : QVideoWidget(parent) +{ + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); +} + +void VideoWidget::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape && isFullScreen()) { + showNormal(); + + event->accept(); + } else if (event->key() == Qt::Key_Enter && event->modifiers() & Qt::Key_Alt) { + setFullScreen(!isFullScreen()); + + event->accept(); + } else { + QVideoWidget::keyPressEvent(event); + } +} + +void VideoWidget::mouseDoubleClickEvent(QMouseEvent *event) +{ + setFullScreen(!isFullScreen()); + + event->accept(); +} diff --git a/demos/multimedia/player/videowidget.h b/demos/multimedia/player/videowidget.h new file mode 100644 index 0000000..543e1e0 --- /dev/null +++ b/demos/multimedia/player/videowidget.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef VIDEOWIDGET_H +#define VIDEOWIDGET_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class VideoWidget : public QVideoWidget +{ + Q_OBJECT +public: + VideoWidget(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif -- cgit v0.12 From 29ae7af90a5bb86f9add481e8236b6ac91f22ad3 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 18 Jan 2010 12:36:30 +1000 Subject: Multimedia; fixes for linux --- src/multimedia/base/qmediaserviceprovider.cpp | 2 +- src/multimedia/base/qpaintervideosurface_p.h | 3 +++ src/plugins/mediaservices/mediaservices.pro | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp index 37115e7..f7c4e1f 100644 --- a/src/multimedia/base/qmediaserviceprovider.cpp +++ b/src/multimedia/base/qmediaserviceprovider.cpp @@ -43,7 +43,7 @@ #include #include -#include +#include #include #include "qmediapluginloader_p.h" #include diff --git a/src/multimedia/base/qpaintervideosurface_p.h b/src/multimedia/base/qpaintervideosurface_p.h index 2a146d0..a7d3e3a 100644 --- a/src/multimedia/base/qpaintervideosurface_p.h +++ b/src/multimedia/base/qpaintervideosurface_p.h @@ -65,6 +65,9 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +class QGLContext; + + class QVideoSurfacePainter; class Q_AUTOTEST_EXPORT QPainterVideoSurface : public QAbstractVideoSurface { diff --git a/src/plugins/mediaservices/mediaservices.pro b/src/plugins/mediaservices/mediaservices.pro index 765477d..03859bd 100644 --- a/src/plugins/mediaservices/mediaservices.pro +++ b/src/plugins/mediaservices/mediaservices.pro @@ -1,5 +1,5 @@ TEMPLATE = subdirs -SUBDIRS += qt7 +mac:SUBDIRS += qt7 -- cgit v0.12 From 07144fabe351f3a6021a2d213cfdba7ee55602a0 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Tue, 19 Jan 2010 12:16:42 +1000 Subject: Multimedia; Add GStreamer backend --- src/plugins/mediaservices/gstreamer/gstreamer.pro | 57 ++ .../gstreamer/mediaplayer/mediaplayer.pri | 19 + .../mediaplayer/qgstreamermetadataprovider.cpp | 204 ++++++ .../mediaplayer/qgstreamermetadataprovider.h | 83 +++ .../mediaplayer/qgstreamerplayercontrol.cpp | 334 ++++++++++ .../mediaplayer/qgstreamerplayercontrol.h | 128 ++++ .../mediaplayer/qgstreamerplayerservice.cpp | 137 +++++ .../mediaplayer/qgstreamerplayerservice.h | 101 +++ .../mediaplayer/qgstreamerplayersession.cpp | 683 +++++++++++++++++++++ .../mediaplayer/qgstreamerplayersession.h | 168 +++++ .../mediaplayer/qgstreamerstreamscontrol.cpp | 89 +++ .../mediaplayer/qgstreamerstreamscontrol.h | 71 +++ .../qgstreameraudioinputendpointselector.cpp | 172 ++++++ .../qgstreameraudioinputendpointselector.h | 83 +++ .../gstreamer/qgstreamerbushelper.cpp | 203 ++++++ .../mediaservices/gstreamer/qgstreamerbushelper.h | 87 +++ .../mediaservices/gstreamer/qgstreamermessage.cpp | 93 +++ .../mediaservices/gstreamer/qgstreamermessage.h | 76 +++ .../gstreamer/qgstreamerserviceplugin.cpp | 186 ++++++ .../gstreamer/qgstreamerserviceplugin.h | 76 +++ .../qgstreamervideoinputdevicecontrol.cpp | 157 +++++ .../gstreamer/qgstreamervideoinputdevicecontrol.h | 85 +++ .../gstreamer/qgstreamervideooutputcontrol.cpp | 72 +++ .../gstreamer/qgstreamervideooutputcontrol.h | 86 +++ .../gstreamer/qgstreamervideooverlay.cpp | 210 +++++++ .../gstreamer/qgstreamervideooverlay.h | 114 ++++ .../gstreamer/qgstreamervideorenderer.cpp | 82 +++ .../gstreamer/qgstreamervideorenderer.h | 78 +++ .../gstreamer/qgstreamervideorendererinterface.cpp | 46 ++ .../gstreamer/qgstreamervideorendererinterface.h | 69 +++ .../gstreamer/qgstreamervideowidget.cpp | 322 ++++++++++ .../gstreamer/qgstreamervideowidget.h | 109 ++++ .../mediaservices/gstreamer/qgstvideobuffer.cpp | 85 +++ .../mediaservices/gstreamer/qgstvideobuffer.h | 75 +++ .../gstreamer/qvideosurfacegstsink.cpp | 553 +++++++++++++++++ .../mediaservices/gstreamer/qvideosurfacegstsink.h | 141 +++++ .../mediaservices/gstreamer/qx11videosurface.cpp | 471 ++++++++++++++ .../mediaservices/gstreamer/qx11videosurface.h | 117 ++++ src/plugins/mediaservices/mediaservices.pro | 11 + 39 files changed, 5933 insertions(+) create mode 100644 src/plugins/mediaservices/gstreamer/gstreamer.pro create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp create mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamermessage.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h create mode 100644 src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstvideobuffer.h create mode 100644 src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h create mode 100644 src/plugins/mediaservices/gstreamer/qx11videosurface.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qx11videosurface.h diff --git a/src/plugins/mediaservices/gstreamer/gstreamer.pro b/src/plugins/mediaservices/gstreamer/gstreamer.pro new file mode 100644 index 0000000..e4e8d5a --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/gstreamer.pro @@ -0,0 +1,57 @@ +TARGET = gstengine +include(../../qpluginbase.pri) + +QT += multimedia + +unix:contains(QT_CONFIG, alsa) { + DEFINES += HAVE_ALSA + LIBS += -lasound +} + +LIBS += -lXv + +CONFIG += link_pkgconfig + +PKGCONFIG += \ + gstreamer-0.10 \ + gstreamer-base-0.10 \ + gstreamer-interfaces-0.10 \ + gstreamer-audio-0.10 \ + gstreamer-video-0.10 + +# Input +HEADERS += \ + qgstreamermessage.h \ + qgstreamerbushelper.h \ + qgstreamervideooutputcontrol.h \ + qgstreamervideorendererinterface.h \ + qgstreamervideowidget.h \ + qgstreamerserviceplugin.h \ +# qgstreameraudioinputendpointselector.h \ + qgstreamervideoinputdevicecontrol.h \ + qgstreamervideooverlay.h \ + qgstreamervideorenderer.h \ + qgstvideobuffer.h \ + qvideosurfacegstsink.h \ + qx11videosurface.h + +SOURCES += \ + qgstreamermessage.cpp \ + qgstreamerbushelper.cpp \ + qgstreamervideooutputcontrol.cpp \ + qgstreamervideorendererinterface.cpp \ + qgstreamervideowidget.cpp \ + qgstreamerserviceplugin.cpp \ +# qgstreameraudioinputendpointselector.cpp \ + qgstreamervideoinputdevicecontrol.cpp \ + qgstreamervideooverlay.cpp \ + qgstreamervideorenderer.cpp \ + qgstvideobuffer.cpp \ + qvideosurfacegstsink.cpp \ + qx11videosurface.cpp + +include(mediaplayer/mediaplayer.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/mediaservices +target.path = $$[QT_INSTALL_PLUGINS]/plugins/mediaservices +INSTALLS += target diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri new file mode 100644 index 0000000..dda641c --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri @@ -0,0 +1,19 @@ +INCLUDEPATH += $$PWD + +DEFINES += QMEDIA_GSTREAMER_PLAYER + +HEADERS += \ + $$PWD/qgstreamerplayercontrol.h \ + $$PWD/qgstreamerplayerservice.h \ + $$PWD/qgstreamerplayersession.h \ +# $$PWD/qgstreamerstreamscontrol.h \ + $$PWD/qgstreamermetadataprovider.h + +SOURCES += \ + $$PWD/qgstreamerplayercontrol.cpp \ + $$PWD/qgstreamerplayerservice.cpp \ + $$PWD/qgstreamerplayersession.cpp \ +# $$PWD/qgstreamerstreamscontrol.cpp \ + $$PWD/qgstreamermetadataprovider.cpp + + diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp new file mode 100644 index 0000000..c22e83c --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamermetadataprovider.h" +#include "qgstreamerplayersession.h" +#include + +#include + +struct QGstreamerMetaDataKeyLookup +{ + QtMedia::MetaData key; + const char *token; +}; + +static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = +{ + { QtMedia::Title, GST_TAG_TITLE }, + //{ QtMedia::SubTitle, 0 }, + //{ QtMedia::Author, 0 }, + { QtMedia::Comment, GST_TAG_COMMENT }, + { QtMedia::Description, GST_TAG_DESCRIPTION }, + //{ QtMedia::Category, 0 }, + { QtMedia::Genre, GST_TAG_GENRE }, + { QtMedia::Year, "year" }, + //{ QtMedia::UserRating, 0 }, + + { QtMedia::Language, GST_TAG_LANGUAGE_CODE }, + + { QtMedia::Publisher, GST_TAG_ORGANIZATION }, + { QtMedia::Copyright, GST_TAG_COPYRIGHT }, + //{ QtMedia::ParentalRating, 0 }, + //{ QtMedia::RatingOrganisation, 0 }, + + // Media + //{ QtMedia::Size, 0 }, + //{ QtMedia::MediaType, 0 }, + { QtMedia::Duration, GST_TAG_DURATION }, + + // Audio + { QtMedia::AudioBitRate, GST_TAG_BITRATE }, + { QtMedia::AudioCodec, GST_TAG_AUDIO_CODEC }, + //{ QtMedia::ChannelCount, 0 }, + //{ QtMedia::Frequency, 0 }, + + // Music + { QtMedia::AlbumTitle, GST_TAG_ALBUM }, + { QtMedia::AlbumArtist, GST_TAG_ARTIST}, + { QtMedia::ContributingArtist, GST_TAG_PERFORMER }, +#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) + { QtMedia::Composer, GST_TAG_COMPOSER }, +#endif + //{ QtMedia::Conductor, 0 }, + //{ QtMedia::Lyrics, 0 }, + //{ QtMedia::Mood, 0 }, + { QtMedia::TrackNumber, GST_TAG_TRACK_NUMBER }, + + //{ QtMedia::CoverArtUrlSmall, 0 }, + //{ QtMedia::CoverArtUrlLarge, 0 }, + + // Image/Video + //{ QtMedia::Resolution, 0 }, + //{ QtMedia::PixelAspectRatio, 0 }, + + // Video + //{ QtMedia::VideoFrameRate, 0 }, + //{ QtMedia::VideoBitRate, 0 }, + { QtMedia::VideoCodec, GST_TAG_VIDEO_CODEC }, + + //{ QtMedia::PosterUrl, 0 }, + + // Movie + //{ QtMedia::ChapterNumber, 0 }, + //{ QtMedia::Director, 0 }, + { QtMedia::LeadPerformer, GST_TAG_PERFORMER }, + //{ QtMedia::Writer, 0 }, + + // Photos + //{ QtMedia::CameraManufacturer, 0 }, + //{ QtMedia::CameraModel, 0 }, + //{ QtMedia::Event, 0 }, + //{ QtMedia::Subject, 0 } +}; + +QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent) + :QMetaDataControl(parent), m_session(session) +{ + connect(m_session, SIGNAL(tagsChanged()), SLOT(updateTags())); +} + +QGstreamerMetaDataProvider::~QGstreamerMetaDataProvider() +{ +} + +bool QGstreamerMetaDataProvider::isMetaDataAvailable() const +{ + return !m_session->tags().isEmpty(); +} + +bool QGstreamerMetaDataProvider::isWritable() const +{ + return false; +} + +QVariant QGstreamerMetaDataProvider::metaData(QtMedia::MetaData key) const +{ + static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); + + for (int i = 0; i < count; ++i) { + if (qt_gstreamerMetaDataKeys[i].key == key) { + return m_session->tags().value(QByteArray(qt_gstreamerMetaDataKeys[i].token)); + } + } + return QVariant(); +} + +void QGstreamerMetaDataProvider::setMetaData(QtMedia::MetaData key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QList QGstreamerMetaDataProvider::availableMetaData() const +{ + static QMap keysMap; + if (keysMap.isEmpty()) { + const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); + for (int i = 0; i < count; ++i) { + keysMap[QByteArray(qt_gstreamerMetaDataKeys[i].token)] = qt_gstreamerMetaDataKeys[i].key; + } + } + + QList res; + foreach (const QByteArray &key, m_session->tags().keys()) { + QtMedia::MetaData tag = keysMap.value(key, QtMedia::MetaData(-1)); + if (tag != -1) + res.append(tag); + } + + return res; +} + +QVariant QGstreamerMetaDataProvider::extendedMetaData(const QString &key) const +{ + return m_session->tags().value(key.toLatin1()); +} + +void QGstreamerMetaDataProvider::setExtendedMetaData(const QString &key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QStringList QGstreamerMetaDataProvider::availableExtendedMetaData() const +{ + QStringList res; + foreach (const QByteArray &key, m_session->tags().keys()) + res.append(QString(key)); + + return res; +} + +void QGstreamerMetaDataProvider::updateTags() +{ + emit metaDataChanged(); +} diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h new file mode 100644 index 0000000..7e9af23 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERMETADATAPROVIDER_H +#define QGSTREAMERMETADATAPROVIDER_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerPlayerSession; + +class QGstreamerMetaDataProvider : public QMetaDataControl +{ + Q_OBJECT +public: + QGstreamerMetaDataProvider( QGstreamerPlayerSession *session, QObject *parent ); + virtual ~QGstreamerMetaDataProvider(); + + bool isMetaDataAvailable() const; + bool isWritable() const; + + QVariant metaData(QtMedia::MetaData key) const; + void setMetaData(QtMedia::MetaData key, const QVariant &value); + QList availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const ; + void setExtendedMetaData(const QString &key, const QVariant &value); + QStringList availableExtendedMetaData() const; + +private slots: + void updateTags(); + +private: + QGstreamerPlayerSession *m_session; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERMETADATAPROVIDER_H diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp new file mode 100644 index 0000000..730279a --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -0,0 +1,334 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamerplayercontrol.h" +#include "qgstreamerplayersession.h" + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent) + : QMediaPlayerControl(parent) + , m_session(session) + , m_stream(0) + , m_fifoNotifier(0) + , m_fifoCanWrite(false) + , m_bufferSize(0) + , m_bufferOffset(0) +{ + m_fifoFd[0] = -1; + m_fifoFd[1] = -1; + + connect(m_session, SIGNAL(positionChanged(qint64)), + this, SIGNAL(positionChanged(qint64))); + connect(m_session, SIGNAL(durationChanged(qint64)), + this, SIGNAL(durationChanged(qint64))); + connect(m_session, SIGNAL(mutedStateChanged(bool)), + this, SIGNAL(mutedChanged(bool))); + connect(m_session, SIGNAL(volumeChanged(int)), + this, SIGNAL(volumeChanged(int))); + connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)), + this, SIGNAL(stateChanged(QMediaPlayer::State))); + connect(m_session, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_session,SIGNAL(bufferingProgressChanged(int)), + this, SIGNAL(bufferStatusChanged(int))); + connect(m_session, SIGNAL(videoAvailableChanged(bool)), + this, SIGNAL(videoAvailableChanged(bool))); + connect(m_session, SIGNAL(seekableChanged(bool)), + this, SIGNAL(seekableChanged(bool))); +} + +QGstreamerPlayerControl::~QGstreamerPlayerControl() +{ + if (m_fifoFd[0] >= 0) { + ::close(m_fifoFd[0]); + ::close(m_fifoFd[1]); + m_fifoFd[0] = -1; + m_fifoFd[1] = -1; + } +} + +qint64 QGstreamerPlayerControl::position() const +{ + return m_session->position(); +} + +qint64 QGstreamerPlayerControl::duration() const +{ + return m_session->duration(); +} + +QMediaPlayer::State QGstreamerPlayerControl::state() const +{ + return m_session->state(); +} + +QMediaPlayer::MediaStatus QGstreamerPlayerControl::mediaStatus() const +{ + return m_session->mediaStatus(); +} + +int QGstreamerPlayerControl::bufferStatus() const +{ + return 100; +} + +int QGstreamerPlayerControl::volume() const +{ + return m_session->volume(); +} + +bool QGstreamerPlayerControl::isMuted() const +{ + return m_session->isMuted(); +} + +bool QGstreamerPlayerControl::isSeekable() const +{ + return m_session->isSeekable(); +} + +QMediaTimeRange QGstreamerPlayerControl::availablePlaybackRanges() const +{ + QMediaTimeRange ranges; + + if (m_session->isSeekable()) + ranges.addInterval(0, m_session->duration()); + + return ranges; +} + +qreal QGstreamerPlayerControl::playbackRate() const +{ + return m_session->playbackRate(); +} + +void QGstreamerPlayerControl::setPlaybackRate(qreal rate) +{ + m_session->setPlaybackRate(rate); +} + +void QGstreamerPlayerControl::setPosition(qint64 pos) +{ + m_session->seek(pos); +} + +void QGstreamerPlayerControl::play() +{ + m_session->play(); + + if (m_fifoFd[1] >= 0) { + m_fifoCanWrite = true; + + writeFifo(); + } +} + +void QGstreamerPlayerControl::pause() +{ + m_session->pause(); +} + +void QGstreamerPlayerControl::stop() +{ + m_session->stop(); +} + +void QGstreamerPlayerControl::setVolume(int volume) +{ + m_session->setVolume(volume); +} + +void QGstreamerPlayerControl::setMuted(bool muted) +{ + m_session->setMuted(muted); +} + +QMediaContent QGstreamerPlayerControl::media() const +{ + return m_currentResource; +} + +const QIODevice *QGstreamerPlayerControl::mediaStream() const +{ + return m_stream; +} + +void QGstreamerPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) +{ + m_session->stop(); + + if (m_stream) { + closeFifo(); + + disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(writeFifo())); + m_stream = 0; + } + + m_currentResource = content; + m_stream = stream; + + QUrl url; + + if (m_stream) { + if (m_stream->isReadable() && openFifo()) { + url = QUrl(QString(QLatin1String("fd://%1")).arg(m_fifoFd[0])); + } + } else if (!content.isNull()) { + url = content.canonicalUrl(); + } + + m_session->load(url); + + emit mediaChanged(m_currentResource); +} + +void QGstreamerPlayerControl::setVideoOutput(QObject *output) +{ + m_session->setVideoRenderer(output); +} + +bool QGstreamerPlayerControl::isVideoAvailable() const +{ + return m_session->isVideoAvailable(); +} + +void QGstreamerPlayerControl::writeFifo() +{ + if (m_fifoCanWrite) { + qint64 bytesToRead = qMin( + m_stream->bytesAvailable(), PIPE_BUF - m_bufferSize); + + if (bytesToRead > 0) { + int bytesRead = m_stream->read(&m_buffer[m_bufferOffset + m_bufferSize], bytesToRead); + + if (bytesRead > 0) + m_bufferSize += bytesRead; + } + + if (m_bufferSize > 0) { + int bytesWritten = ::write(m_fifoFd[1], &m_buffer[m_bufferOffset], size_t(m_bufferSize)); + + if (bytesWritten > 0) { + m_bufferOffset += bytesWritten; + m_bufferSize -= bytesWritten; + + if (m_bufferSize == 0) + m_bufferOffset = 0; + } else if (errno == EAGAIN) { + m_fifoCanWrite = false; + } else { + closeFifo(); + } + } + } + + m_fifoNotifier->setEnabled(m_stream->bytesAvailable() > 0); +} + +void QGstreamerPlayerControl::fifoReadyWrite(int socket) +{ + if (socket == m_fifoFd[1]) { + m_fifoCanWrite = true; + + writeFifo(); + } +} + +bool QGstreamerPlayerControl::openFifo() +{ + Q_ASSERT(m_fifoFd[0] < 0); + Q_ASSERT(m_fifoFd[1] < 0); + + if (::pipe(m_fifoFd) == 0) { + int flags = ::fcntl(m_fifoFd[1], F_GETFD); + + if (::fcntl(m_fifoFd[1], F_SETFD, flags | O_NONBLOCK) >= 0) { + m_fifoNotifier = new QSocketNotifier(m_fifoFd[1], QSocketNotifier::Write); + + connect(m_fifoNotifier, SIGNAL(activated(int)), this, SLOT(fifoReadyWrite(int))); + + return true; + } else { + qWarning("Failed to make pipe non blocking %d", errno); + + ::close(m_fifoFd[0]); + ::close(m_fifoFd[1]); + + m_fifoFd[0] = -1; + m_fifoFd[1] = -1; + + return false; + } + } else { + qWarning("Failed to create pipe %d", errno); + + return false; + } +} + +void QGstreamerPlayerControl::closeFifo() +{ + if (m_fifoFd[0] >= 0) { + delete m_fifoNotifier; + m_fifoNotifier = 0; + + ::close(m_fifoFd[0]); + ::close(m_fifoFd[1]); + m_fifoFd[0] = -1; + m_fifoFd[1] = -1; + + m_fifoCanWrite = false; + + m_bufferSize = 0; + m_bufferOffset = 0; + } +} diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h new file mode 100644 index 0000000..ec0253b --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERPLAYERCONTROL_H +#define QGSTREAMERPLAYERCONTROL_H + +#include + +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaPlaylist; +class QGstreamerPlayerSession; +class QGstreamerPlayerService; +class QMediaPlaylistNavigator; +class QSocketNotifier; + +class QGstreamerPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT + +public: + QGstreamerPlayerControl(QGstreamerPlayerSession *session, QObject *parent = 0); + ~QGstreamerPlayerControl(); + + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + + qint64 position() const; + qint64 duration() const; + + int bufferStatus() const; + + int volume() const; + bool isMuted() const; + + bool isVideoAvailable() const; + void setVideoOutput(QObject *output); + + bool isSeekable() const; + QMediaTimeRange availablePlaybackRanges() const; + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent&, QIODevice *); + +public Q_SLOTS: + void setPosition(qint64 pos); + + void play(); + void pause(); + void stop(); + + void setVolume(int volume); + void setMuted(bool muted); + +private Q_SLOTS: + void writeFifo(); + void fifoReadyWrite(int socket); + +private: + bool openFifo(); + void closeFifo(); + + QGstreamerPlayerSession *m_session; + QMediaContent m_currentResource; + QIODevice *m_stream; + QSocketNotifier *m_fifoNotifier; + int m_fifoFd[2]; + bool m_fifoCanWrite; + int m_bufferSize; + int m_bufferOffset; + char m_buffer[PIPE_BUF]; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp new file mode 100644 index 0000000..0c83147 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "qgstreamerplayerservice.h" +#include "qgstreamerplayercontrol.h" +#include "qgstreamerplayersession.h" +#include "qgstreamermetadataprovider.h" +#include "qgstreamervideooutputcontrol.h" + +#include "qgstreamervideooverlay.h" +#include "qgstreamervideorenderer.h" + +#include "qgstreamervideowidget.h" +//#include "qgstreamerstreamscontrol.h" + +#include +#include + + +QT_BEGIN_NAMESPACE + + +QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): + QMediaService(parent) +{ + m_session = new QGstreamerPlayerSession(this); + m_control = new QGstreamerPlayerControl(m_session, this); + m_metaData = new QGstreamerMetaDataProvider(m_session, this); + m_videoOutput = new QGstreamerVideoOutputControl(this); +// m_streamsControl = new QGstreamerStreamsControl(m_session,this); + + connect(m_videoOutput, SIGNAL(outputChanged(QVideoOutputControl::Output)), + this, SLOT(videoOutputChanged(QVideoOutputControl::Output))); + m_videoRenderer = new QGstreamerVideoRenderer(this); + m_videoWindow = new QGstreamerVideoOverlay(this); + m_videoWidget = new QGstreamerVideoWidgetControl(this); + + m_videoOutput->setAvailableOutputs(QList() + << QVideoOutputControl::RendererOutput + << QVideoOutputControl::WindowOutput + << QVideoOutputControl::WidgetOutput); +} + +QGstreamerPlayerService::~QGstreamerPlayerService() +{ +} + +QMediaControl *QGstreamerPlayerService::control(const char *name) const +{ + if (qstrcmp(name,QMediaPlayerControl_iid) == 0) + return m_control; + + if (qstrcmp(name,QMetaDataControl_iid) == 0) + return m_metaData; + +// if (qstrcmp(name,QMediaStreamsControl_iid) == 0) +// return m_streamsControl; + + if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return m_videoOutput; + + if (qstrcmp(name, QVideoWidgetControl_iid) == 0) + return m_videoWidget; + + if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return m_videoRenderer; + + if (qstrcmp(name, QVideoWindowControl_iid) == 0) + return m_videoWindow; + + return 0; +} + +void QGstreamerPlayerService::videoOutputChanged(QVideoOutputControl::Output output) +{ + switch (output) { + case QVideoOutputControl::NoOutput: + m_control->setVideoOutput(0); + break; + case QVideoOutputControl::RendererOutput: + m_control->setVideoOutput(m_videoRenderer); + break; + case QVideoOutputControl::WindowOutput: + m_control->setVideoOutput(m_videoWindow); + break; + case QVideoOutputControl::WidgetOutput: + m_control->setVideoOutput(m_videoWidget); + break; + default: + qWarning("Invalid video output selection"); + break; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h new file mode 100644 index 0000000..b27c2ae --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERPLAYERSERVICE_H +#define QGSTREAMERPLAYERSERVICE_H + +#include +#include + +#include + +#include "qgstreamervideooutputcontrol.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaMetaData; +class QMediaPlayerControl; +class QMediaPlaylist; +class QMediaPlaylistNavigator; +class QGstreamerMetaData; +class QGstreamerPlayerControl; +class QGstreamerPlayerSession; +class QGstreamerMetaDataProvider; +class QGstreamerStreamsControl; +class QGstreamerVideoRenderer; +class QGstreamerVideoOverlay; +class QGstreamerVideoWidgetControl; + + +class QGstreamerPlayerService : public QMediaService +{ + Q_OBJECT +public: + QGstreamerPlayerService(QObject *parent = 0); + ~QGstreamerPlayerService(); + + //void setVideoOutput(QObject *output); + + QMediaControl *control(const char *name) const; + +private slots: + void videoOutputChanged(QVideoOutputControl::Output output); + +private: + QGstreamerPlayerControl *m_control; + QGstreamerPlayerSession *m_session; + QGstreamerMetaDataProvider *m_metaData; + QGstreamerVideoOutputControl *m_videoOutput; + QGstreamerStreamsControl *m_streamsControl; + + QGstreamerVideoRenderer *m_videoRenderer; + QGstreamerVideoOverlay *m_videoWindow; + QGstreamerVideoWidgetControl *m_videoWidget; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp new file mode 100644 index 0000000..baece67 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -0,0 +1,683 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamerplayersession.h" +#include "qgstreamerbushelper.h" + +#include "qgstreamervideorendererinterface.h" + +#include + +#include +#include + +//#define USE_PLAYBIN2 + +QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) + :QObject(parent), + m_state(QMediaPlayer::StoppedState), + m_mediaStatus(QMediaPlayer::UnknownMediaStatus), + m_busHelper(0), + m_playbin(0), + m_nullVideoOutput(0), + m_bus(0), + m_renderer(0), + m_volume(100), + m_playbackRate(1.0), + m_muted(false), + m_videoAvailable(false), + m_seekable(false), + m_lastPosition(0), + m_duration(-1) +{ + static bool initialized = false; + if (!initialized) { + initialized = true; + gst_init(NULL, NULL); + } + +#ifdef USE_PLAYBIN2 + m_playbin = gst_element_factory_make("playbin2", NULL); +#else + m_playbin = gst_element_factory_make("playbin", NULL); +#endif + + if (m_playbin != 0) { + // Sort out messages + m_bus = gst_element_get_bus(m_playbin); + m_busHelper = new QGstreamerBusHelper(m_bus, this); + connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage))); + m_busHelper->installSyncEventFilter(this); + + m_nullVideoOutput = gst_element_factory_make("fakesink", NULL); + g_object_set(G_OBJECT(m_playbin), "video-sink", m_nullVideoOutput, NULL); + + // Initial volume + double volume = 1.0; + g_object_get(G_OBJECT(m_playbin), "volume", &volume, NULL); + m_volume = int(volume*100); + } +} + +QGstreamerPlayerSession::~QGstreamerPlayerSession() +{ + if (m_playbin) { + stop(); + + delete m_busHelper; + gst_object_unref(GST_OBJECT(m_bus)); + gst_object_unref(GST_OBJECT(m_playbin)); + } +} + +void QGstreamerPlayerSession::load(const QUrl &url) +{ + m_url = url; + if (m_playbin) { + m_tags.clear(); + emit tagsChanged(); + + g_object_set(G_OBJECT(m_playbin), "uri", m_url.toString().toLocal8Bit().constData(), NULL); + +// if (!m_streamTypes.isEmpty()) { +// m_streamProperties.clear(); +// m_streamTypes.clear(); +// +// emit streamsChanged(); +// } + } +} + +qint64 QGstreamerPlayerSession::duration() const +{ + return m_duration; +} + +qint64 QGstreamerPlayerSession::position() const +{ + GstFormat format = GST_FORMAT_TIME; + gint64 position = 0; + + if ( m_playbin && gst_element_query_position(m_playbin, &format, &position)) + return position / 1000000; + else + return 0; +} + +qreal QGstreamerPlayerSession::playbackRate() const +{ + return m_playbackRate; +} + +void QGstreamerPlayerSession::setPlaybackRate(qreal rate) +{ + if (!qFuzzyCompare(m_playbackRate, rate)) { + m_playbackRate = rate; + if (m_playbin) { + gst_element_seek(m_playbin, rate, GST_FORMAT_TIME, + GstSeekFlags(GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT), + GST_SEEK_TYPE_NONE,0, + GST_SEEK_TYPE_NONE,0 ); + } + } +} + + +//int QGstreamerPlayerSession::activeStream(QMediaStreamsControl::StreamType streamType) const +//{ +// int streamNumber = -1; +// if (m_playbin) { +// switch (streamType) { +// case QMediaStreamsControl::AudioStream: +// g_object_set(G_OBJECT(m_playbin), "current-audio", streamNumber, NULL); +// break; +// case QMediaStreamsControl::VideoStream: +// g_object_set(G_OBJECT(m_playbin), "current-video", streamNumber, NULL); +// break; +// case QMediaStreamsControl::SubPictureStream: +// g_object_set(G_OBJECT(m_playbin), "current-text", streamNumber, NULL); +// break; +// default: +// break; +// } +// } +// +//#ifdef USE_PLAYBIN2 +// streamNumber += m_playbin2StreamOffset.value(streamType,0); +//#endif +// +// return streamNumber; +//} + +//void QGstreamerPlayerSession::setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber) +//{ +//#ifdef USE_PLAYBIN2 +// streamNumber -= m_playbin2StreamOffset.value(streamType,0); +//#endif +// +// if (m_playbin) { +// switch (streamType) { +// case QMediaStreamsControl::AudioStream: +// g_object_get(G_OBJECT(m_playbin), "current-audio", &streamNumber, NULL); +// break; +// case QMediaStreamsControl::VideoStream: +// g_object_get(G_OBJECT(m_playbin), "current-video", &streamNumber, NULL); +// break; +// case QMediaStreamsControl::SubPictureStream: +// g_object_get(G_OBJECT(m_playbin), "current-text", &streamNumber, NULL); +// break; +// default: +// break; +// } +// } +//} + + +bool QGstreamerPlayerSession::isBuffering() const +{ + return false; +} + +int QGstreamerPlayerSession::bufferingProgress() const +{ + return 0; +} + +int QGstreamerPlayerSession::volume() const +{ + return m_volume; +} + +bool QGstreamerPlayerSession::isMuted() const +{ + return m_muted; +} + +void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) +{ + m_renderer = qobject_cast(videoOutput); + if (m_renderer) + g_object_set(G_OBJECT(m_playbin), "video-sink", m_renderer->videoSink(), NULL); + else + g_object_set(G_OBJECT(m_playbin), "video-sink", m_nullVideoOutput, NULL); +} + +bool QGstreamerPlayerSession::isVideoAvailable() const +{ + return m_videoAvailable; +} + +bool QGstreamerPlayerSession::isSeekable() const +{ + return m_seekable; +} + +void QGstreamerPlayerSession::play() +{ + if (m_playbin) { + if (gst_element_set_state(m_playbin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + qWarning() << "GStreamer; Unable to play -" << m_url.toString(); + m_state = QMediaPlayer::StoppedState; + m_mediaStatus = QMediaPlayer::InvalidMedia; + + emit stateChanged(m_state); + emit mediaStatusChanged(m_mediaStatus); + } + } +} + +void QGstreamerPlayerSession::pause() +{ + if (m_playbin) + gst_element_set_state(m_playbin, GST_STATE_PAUSED); +} + +void QGstreamerPlayerSession::stop() +{ + if (m_playbin) { + gst_element_set_state(m_playbin, GST_STATE_NULL); + + //we have to do it here, since gstreamer will not emit bus messages any more + if (m_state != QMediaPlayer::StoppedState) + emit stateChanged(m_state = QMediaPlayer::StoppedState); + } +} + +void QGstreamerPlayerSession::seek(qint64 ms) +{ + if (m_playbin && m_state != QMediaPlayer::StoppedState) { + gint64 position = (gint64)ms * 1000000; + gst_element_seek_simple(m_playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position); + } +} + +void QGstreamerPlayerSession::setVolume(int volume) +{ + m_volume = volume; + emit volumeChanged(m_volume); + + if (!m_muted && m_playbin) + g_object_set(G_OBJECT(m_playbin), "volume", m_volume/100.0, NULL); + +} + +void QGstreamerPlayerSession::setMuted(bool muted) +{ + m_muted = muted; + + g_object_set(G_OBJECT(m_playbin), "volume", (m_muted ? 0 : m_volume/100.0), NULL); + + emit mutedStateChanged(m_muted); +} + +static void addTagToMap(const GstTagList *list, + const gchar *tag, + gpointer user_data) +{ + QMap *map = reinterpret_cast* >(user_data); + + GValue val; + val.g_type = 0; + gst_tag_list_copy_value(&val,list,tag); + + switch( G_VALUE_TYPE(&val) ) { + case G_TYPE_STRING: + { + const gchar *str_value = g_value_get_string(&val); + map->insert(QByteArray(tag), QString::fromUtf8(str_value)); + break; + } + case G_TYPE_INT: + map->insert(QByteArray(tag), g_value_get_int(&val)); + break; + case G_TYPE_UINT: + map->insert(QByteArray(tag), g_value_get_uint(&val)); + break; + case G_TYPE_LONG: + map->insert(QByteArray(tag), qint64(g_value_get_long(&val))); + break; + case G_TYPE_BOOLEAN: + map->insert(QByteArray(tag), g_value_get_boolean(&val)); + break; + case G_TYPE_CHAR: + map->insert(QByteArray(tag), g_value_get_char(&val)); + break; + case G_TYPE_DOUBLE: + map->insert(QByteArray(tag), g_value_get_double(&val)); + break; + default: + // GST_TYPE_DATE is a function, not a constant, so pull it out of the switch + if (G_VALUE_TYPE(&val) == GST_TYPE_DATE) { + const GDate *date = gst_value_get_date(&val); + if (g_date_valid(date)) { + int year = g_date_get_year(date); + int month = g_date_get_month(date); + int day = g_date_get_day(date); + map->insert(QByteArray(tag), QDate(year,month,day)); + if (!map->contains("year")) + map->insert("year", year); + } + } else if (G_VALUE_TYPE(&val) == GST_TYPE_FRACTION) { + int nom = gst_value_get_fraction_numerator(&val); + int denom = gst_value_get_fraction_denominator(&val); + + if (denom > 0) { + map->insert(QByteArray(tag), double(nom)/denom); + } + } + break; + } + + g_value_unset(&val); +} + +void QGstreamerPlayerSession::setSeekable(bool seekable) +{ + if (seekable != m_seekable) { + m_seekable = seekable; + emit seekableChanged(m_seekable); + } +} + +void QGstreamerPlayerSession::setMediaStatus(QMediaPlayer::MediaStatus status) +{ + if (m_mediaStatus != status) { + m_mediaStatus = status; + emit mediaStatusChanged(status); + } +} + +bool QGstreamerPlayerSession::processSyncMessage(const QGstreamerMessage &message) +{ + GstMessage* gm = message.rawMessage(); + + if (gm && + GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT && + gst_structure_has_name(gm->structure, "prepare-xwindow-id")) + { + if (m_renderer) + m_renderer->precessNewStream(); + return true; + } + + return false; +} + +void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message) +{ + GstMessage* gm = message.rawMessage(); + + if (gm == 0) { + // Null message, query current position + quint32 newPos = position(); + + if (newPos/1000 != m_lastPosition) { + m_lastPosition = newPos/1000; + emit positionChanged(newPos); + } + + } else { + //tag message comes from elements inside playbin, not from playbin itself + if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_TAG) { + //qDebug() << "tag message"; + GstTagList *tag_list; + gst_message_parse_tag(gm, &tag_list); + gst_tag_list_foreach(tag_list, addTagToMap, &m_tags); + + //qDebug() << m_tags; + + emit tagsChanged(); + } + + if (GST_MESSAGE_SRC(gm) == GST_OBJECT_CAST(m_playbin)) { + switch (GST_MESSAGE_TYPE(gm)) { + case GST_MESSAGE_DURATION: + break; + + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldState; + GstState newState; + GstState pending; + + gst_message_parse_state_changed(gm, &oldState, &newState, &pending); + + /*QStringList states; + states << "GST_STATE_VOID_PENDING" << "GST_STATE_NULL" << "GST_STATE_READY" << "GST_STATE_PAUSED" << "GST_STATE_PLAYING"; + + qDebug() << QString("state changed: old: %1 new: %2 pending: %3") \ + .arg(states[oldState]) \ + .arg(states[newState]) \ + .arg(states[pending]);*/ + + switch (newState) { + case GST_STATE_VOID_PENDING: + case GST_STATE_NULL: + setMediaStatus(QMediaPlayer::UnknownMediaStatus); + setSeekable(false); + if (m_state != QMediaPlayer::StoppedState) + emit stateChanged(m_state = QMediaPlayer::StoppedState); + break; + case GST_STATE_READY: + setMediaStatus(QMediaPlayer::LoadedMedia); + setSeekable(false); + if (m_state != QMediaPlayer::StoppedState) + emit stateChanged(m_state = QMediaPlayer::StoppedState); + break; + case GST_STATE_PAUSED: + //don't emit state changes for intermediate states + if (m_state != QMediaPlayer::PausedState && pending == GST_STATE_VOID_PENDING) + emit stateChanged(m_state = QMediaPlayer::PausedState); + + setMediaStatus(QMediaPlayer::LoadedMedia); + + //check for seekable + if (oldState == GST_STATE_READY) { + /* + //gst_element_seek_simple doesn't work reliably here, have to find a better solution + + GstFormat format = GST_FORMAT_TIME; + gint64 position = 0; + bool seekable = false; + if (gst_element_query_position(m_playbin, &format, &position)) { + seekable = gst_element_seek_simple(m_playbin, format, GST_SEEK_FLAG_NONE, position); + } + + setSeekable(seekable); + */ + + setSeekable(true); + + if (!qFuzzyCompare(m_playbackRate, qreal(1.0))) + setPlaybackRate(m_playbackRate); + + if (m_renderer) + m_renderer->precessNewStream(); + + } + + + break; + case GST_STATE_PLAYING: + if (oldState == GST_STATE_PAUSED) + getStreamsInfo(); + + if (m_state != QMediaPlayer::PlayingState) + emit stateChanged(m_state = QMediaPlayer::PlayingState); + break; + } + } + break; + + case GST_MESSAGE_EOS: + if (m_state != QMediaPlayer::StoppedState) + emit stateChanged(m_state = QMediaPlayer::StoppedState); + + setMediaStatus(QMediaPlayer::EndOfMedia); + + emit playbackFinished(); + break; + + case GST_MESSAGE_TAG: + case GST_MESSAGE_STREAM_STATUS: + case GST_MESSAGE_UNKNOWN: + case GST_MESSAGE_ERROR: + case GST_MESSAGE_WARNING: + case GST_MESSAGE_INFO: + break; + case GST_MESSAGE_BUFFERING: + setMediaStatus(QMediaPlayer::BufferingMedia); + break; + case GST_MESSAGE_STATE_DIRTY: + case GST_MESSAGE_STEP_DONE: + case GST_MESSAGE_CLOCK_PROVIDE: + case GST_MESSAGE_CLOCK_LOST: + case GST_MESSAGE_NEW_CLOCK: + case GST_MESSAGE_STRUCTURE_CHANGE: + case GST_MESSAGE_APPLICATION: + case GST_MESSAGE_ELEMENT: + case GST_MESSAGE_SEGMENT_START: + case GST_MESSAGE_SEGMENT_DONE: + case GST_MESSAGE_LATENCY: +#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 13) + case GST_MESSAGE_ASYNC_START: + case GST_MESSAGE_ASYNC_DONE: +#if GST_VERSION_MICRO >= 23 + case GST_MESSAGE_REQUEST_STATE: +#endif +#endif + case GST_MESSAGE_ANY: + break; + } + } + } +} + +void QGstreamerPlayerSession::getStreamsInfo() +{ + GstFormat format = GST_FORMAT_TIME; + gint64 duration = 0; + + if (gst_element_query_duration(m_playbin, &format, &duration)) { + int newDuration = duration / 1000000; + if (m_duration != newDuration) { + m_duration = newDuration; + emit durationChanged(m_duration); + } + } + + //check if video is available: + bool haveVideo = false; +// m_streamProperties.clear(); +// m_streamTypes.clear(); + +#ifdef USE_PLAYBIN2 + gint audioStreamsCount = 0; + gint videoStreamsCount = 0; + gint textStreamsCount = 0; + + g_object_get(G_OBJECT(m_playbin), "n-audio", &audioStreamsCount, NULL); + g_object_get(G_OBJECT(m_playbin), "n-video", &videoStreamsCount, NULL); + g_object_get(G_OBJECT(m_playbin), "n-text", &textStreamsCount, NULL); + + m_playbin2StreamOffset[QMediaStreamsControl::AudioStream] = 0; + m_playbin2StreamOffset[QMediaStreamsControl::VideoStream] = audioStreamsCount; + m_playbin2StreamOffset[QMediaStreamsControl::SubPictureStream] = audioStreamsCount+videoStreamsCount; + + for (int i=0; i streamProperties; + + int streamIndex = i - m_playbin2StreamOffset[streamType]; + + GstTagList *tags = 0; + switch (streamType) { + case QMediaStreamsControl::AudioStream: + g_signal_emit_by_name(G_OBJECT(m_playbin), "get-audio-tags", streamIndex, &tags); + break; + case QMediaStreamsControl::VideoStream: + g_signal_emit_by_name(G_OBJECT(m_playbin), "get-video-tags", streamIndex, &tags); + break; + case QMediaStreamsControl::SubPictureStream: + g_signal_emit_by_name(G_OBJECT(m_playbin), "get-text-tags", streamIndex, &tags); + break; + default: + break; + } + + if (tags && gst_is_tag_list(tags)) { + gchar *languageCode = 0; + if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode)) + streamProperties[QtMedia::Language] = QString::fromUtf8(languageCode); + + //qDebug() << "language for setream" << i << QString::fromUtf8(languageCode); + g_free (languageCode); + } + + m_streamProperties.append(streamProperties); + } + +#else + enum { + GST_STREAM_TYPE_UNKNOWN, + GST_STREAM_TYPE_AUDIO, + GST_STREAM_TYPE_VIDEO, + GST_STREAM_TYPE_TEXT, + GST_STREAM_TYPE_SUBPICTURE, + GST_STREAM_TYPE_ELEMENT + }; + + GList* streamInfo; + g_object_get(G_OBJECT(m_playbin), "stream-info", &streamInfo, NULL); + + for (; streamInfo != 0; streamInfo = g_list_next(streamInfo)) { + gint type; + gchar *languageCode = 0; + + GObject* obj = G_OBJECT(streamInfo->data); + + g_object_get(obj, "type", &type, NULL); + g_object_get(obj, "language-code", &languageCode, NULL); + + if (type == GST_STREAM_TYPE_VIDEO) + haveVideo = true; + +// QMediaStreamsControl::StreamType streamType = QMediaStreamsControl::UnknownStream; +// +// switch (type) { +// case GST_STREAM_TYPE_VIDEO: +// streamType = QMediaStreamsControl::VideoStream; +// break; +// case GST_STREAM_TYPE_AUDIO: +// streamType = QMediaStreamsControl::AudioStream; +// break; +// case GST_STREAM_TYPE_SUBPICTURE: +// streamType = QMediaStreamsControl::SubPictureStream; +// break; +// default: +// streamType = QMediaStreamsControl::UnknownStream; +// break; +// } +// +// QMap streamProperties; +// streamProperties[QtMedia::Language] = QString::fromUtf8(languageCode); +// +// m_streamProperties.append(streamProperties); +// m_streamTypes.append(streamType); + } +#endif + + if (haveVideo != m_videoAvailable) { + m_videoAvailable = haveVideo; + emit videoAvailableChanged(m_videoAvailable); + } + + emit streamsChanged(); +} diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h new file mode 100644 index 0000000..a0f5f1a --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERPLAYERSESSION_H +#define QGSTREAMERPLAYERSESSION_H + +#include +#include +#include "qgstreamerplayercontrol.h" +#include "qgstreamerbushelper.h" +#include +//#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerBusHelper; +class QGstreamerMessage; +class QGstreamerVideoRendererInterface; + +class QGstreamerPlayerSession : public QObject, public QGstreamerSyncEventFilter +{ +Q_OBJECT + +public: + QGstreamerPlayerSession(QObject *parent); + virtual ~QGstreamerPlayerSession(); + + QUrl url() const; + + QMediaPlayer::State state() const { return m_state; } + QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; } + + qint64 duration() const; + qint64 position() const; + + bool isBuffering() const; + + int bufferingProgress() const; + + int volume() const; + bool isMuted() const; + + void setVideoRenderer(QObject *renderer); + bool isVideoAvailable() const; + + bool isSeekable() const; + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + QMap tags() const { return m_tags; } + QMap streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; } +// int streamCount() const { return m_streamProperties.count(); } +// QMediaStreamsControl::StreamType streamType(int streamNumber) { return m_streamTypes.value(streamNumber, QMediaStreamsControl::UnknownStream); } +// +// int activeStream(QMediaStreamsControl::StreamType streamType) const; +// void setActiveStream(QMediaStreamsControl::StreamType streamType, int streamNumber); + + bool processSyncMessage(const QGstreamerMessage &message); + +public slots: + void load(const QUrl &url); + + void play(); + void pause(); + void stop(); + + void seek(qint64 pos); + + void setVolume(int volume); + void setMuted(bool muted); + +signals: + void durationChanged(qint64 duration); + void positionChanged(qint64 position); + void stateChanged(QMediaPlayer::State state); + void mediaStatusChanged(QMediaPlayer::MediaStatus mediaStatus); + void volumeChanged(int volume); + void mutedStateChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + void bufferingChanged(bool buffering); + void bufferingProgressChanged(int percentFilled); + void playbackFinished(); + void tagsChanged(); + void streamsChanged(); + void seekableChanged(bool); + +private slots: + void busMessage(const QGstreamerMessage &message); + void getStreamsInfo(); + void setSeekable(bool); + +private: + void setMediaStatus(QMediaPlayer::MediaStatus); + + QUrl m_url; + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_mediaStatus; + QGstreamerBusHelper* m_busHelper; + GstElement* m_playbin; + GstElement* m_nullVideoOutput; + GstBus* m_bus; + QGstreamerVideoRendererInterface *m_renderer; + + QMap m_tags; + QList< QMap > m_streamProperties; +// QList m_streamTypes; +// QMap m_playbin2StreamOffset; + + + int m_volume; + qreal m_playbackRate; + bool m_muted; + bool m_videoAvailable; + bool m_seekable; + + qint64 m_lastPosition; + qint64 m_duration; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERPLAYERSESSION_H diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp new file mode 100644 index 0000000..22c0b95 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamerstreamscontrol.h" +#include "qgstreamerplayersession.h" + +QGstreamerStreamsControl::QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent) + :QMediaStreamsControl(parent), m_session(session) +{ + connect(m_session, SIGNAL(streamsChanged()), SIGNAL(streamsChanged())); +} + +QGstreamerStreamsControl::~QGstreamerStreamsControl() +{ +} + +int QGstreamerStreamsControl::streamCount() +{ + return m_session->streamCount(); +} + +QMediaStreamsControl::StreamType QGstreamerStreamsControl::streamType(int streamNumber) +{ + return m_session->streamType(streamNumber); +} + +QVariant QGstreamerStreamsControl::metaData(int streamNumber, QtMedia::MetaData key) +{ + return m_session->streamProperties(streamNumber).value(key); +} + +bool QGstreamerStreamsControl::isActive(int streamNumber) +{ + return streamNumber != -1 && streamNumber == m_session->activeStream(streamType(streamNumber)); +} + +void QGstreamerStreamsControl::setActive(int streamNumber, bool state) +{ + QMediaStreamsControl::StreamType type = m_session->streamType(streamNumber); + if (type == QMediaStreamsControl::UnknownStream) + return; + + if (state) + m_session->setActiveStream(type, streamNumber); + else { + //only one active stream of certain type is supported + if (m_session->activeStream(type) == streamNumber) + m_session->setActiveStream(type, -1); + } +} + diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h new file mode 100644 index 0000000..c115bce --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERSTREAMSCONTROL_H +#define QGSTREAMERSTREAMSCONTROL_H + +#include + +QTM_USE_NAMESPACE + +class QGstreamerPlayerSession; + +class QGstreamerStreamsControl : public QMediaStreamsControl +{ + Q_OBJECT +public: + QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent); + virtual ~QGstreamerStreamsControl(); + + virtual int streamCount(); + virtual StreamType streamType(int streamNumber); + + virtual QVariant metaData(int streamNumber, QtMedia::MetaData key); + + virtual bool isActive(int streamNumber); + virtual void setActive(int streamNumber, bool state); + +private: + QGstreamerPlayerSession *m_session; +}; + +#endif // QGSTREAMERSTREAMSCONTROL_H + diff --git a/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp b/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp new file mode 100644 index 0000000..ce6ab30 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreameraudioinputendpointselector.h" + +#include +#include +#include + +#include + +#ifdef HAVE_ALSA +#include +#endif + +QGstreamerAudioInputEndpointSelector::QGstreamerAudioInputEndpointSelector(QObject *parent) + :QAudioEndpointSelector(parent) +{ + update(); +} + +QGstreamerAudioInputEndpointSelector::~QGstreamerAudioInputEndpointSelector() +{ +} + +QList QGstreamerAudioInputEndpointSelector::availableEndpoints() const +{ + return m_names; +} + +QString QGstreamerAudioInputEndpointSelector::endpointDescription(const QString& name) const +{ + QString desc; + + for (int i = 0; i < m_names.size(); i++) { + if (m_names.at(i).compare(name) == 0) { + desc = m_descriptions.at(i); + break; + } + } + return desc; +} + +QString QGstreamerAudioInputEndpointSelector::defaultEndpoint() const +{ + if (m_names.size() > 0) + return m_names.at(0); + + return QString(); +} + +QString QGstreamerAudioInputEndpointSelector::activeEndpoint() const +{ + return m_audioInput; +} + +void QGstreamerAudioInputEndpointSelector::setActiveEndpoint(const QString& name) +{ + if (m_audioInput.compare(name) != 0) { + m_audioInput = name; + emit activeEndpointChanged(name); + } +} + +void QGstreamerAudioInputEndpointSelector::update() +{ + m_names.clear(); + m_descriptions.clear(); + updateAlsaDevices(); + updateOssDevices(); + updatePulseDevices(); + if (m_names.size() > 0) + m_audioInput = m_names.at(0); +} + +void QGstreamerAudioInputEndpointSelector::updateAlsaDevices() +{ +#ifdef HAVE_ALSA + void **hints, **n; + if (snd_device_name_hint(-1, "pcm", &hints) < 0) { + qWarning()<<"no alsa devices available"; + return; + } + n = hints; + + while (*n != NULL) { + char *name = snd_device_name_get_hint(*n, "NAME"); + char *descr = snd_device_name_get_hint(*n, "DESC"); + char *io = snd_device_name_get_hint(*n, "IOID"); + + if ((name != NULL) && (descr != NULL)) { + if ( io == NULL || qstrcmp(io,"Input") == 0 ) { + m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name)); + m_descriptions.append(QString::fromUtf8(descr)); + } + } + + if (name != NULL) + free(name); + if (descr != NULL) + free(descr); + if (io != NULL) + free(io); + n++; + } + snd_device_name_free_hint(hints); +#endif +} + +void QGstreamerAudioInputEndpointSelector::updateOssDevices() +{ + QDir devDir("/dev"); + devDir.setFilter(QDir::System); +#ifndef QT_QWS_N810 + QFileInfoList entries = devDir.entryInfoList(QStringList() << "dsp*"); + foreach(const QFileInfo& entryInfo, entries) { + m_names.append(QLatin1String("oss:")+entryInfo.filePath()); + m_descriptions.append(QString("OSS device %1").arg(entryInfo.fileName())); + } +#else + m_names.append("dsppcm"); + m_descriptions.append("PCM audio input"); +#endif +} + +void QGstreamerAudioInputEndpointSelector::updatePulseDevices() +{ + GstElementFactory *factory = gst_element_factory_find("pulsesrc"); + if (factory) { + m_names.append("pulseaudio:"); + m_descriptions.append("PulseAudio device."); + gst_object_unref(GST_OBJECT(factory)); + } +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h b/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h new file mode 100644 index 0000000..9b15939 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H +#define QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerAudioInputEndpointSelector : public QAudioEndpointSelector +{ +Q_OBJECT +public: + QGstreamerAudioInputEndpointSelector(QObject *parent); + ~QGstreamerAudioInputEndpointSelector(); + + QList availableEndpoints() const; + QString endpointDescription(const QString& name) const; + QString defaultEndpoint() const; + QString activeEndpoint() const; + +public Q_SLOTS: + void setActiveEndpoint(const QString& name); + +private: + void update(); + void updateAlsaDevices(); + void updateOssDevices(); + void updatePulseDevices(); + + QString m_audioInput; + QList m_names; + QList m_descriptions; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp new file mode 100644 index 0000000..0f09c6b --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "qgstreamerbushelper.h" + + +#ifndef QT_NO_GLIB +class QGstreamerBusHelperPrivate : public QObject +{ + Q_OBJECT + +public: + void addWatch(GstBus* bus, QGstreamerBusHelper* helper) + { + setParent(helper); + m_tag = gst_bus_add_watch_full(bus, 0, busCallback, this, NULL); + m_helper = helper; + filter = 0; + } + + void removeWatch(QGstreamerBusHelper* helper) + { + Q_UNUSED(helper); + g_source_remove(m_tag); + } + + static QGstreamerBusHelperPrivate* instance() + { + return new QGstreamerBusHelperPrivate; + } + +private: + void processMessage(GstBus* bus, GstMessage* message) + { + Q_UNUSED(bus); + emit m_helper->message(message); + } + + static gboolean busCallback(GstBus *bus, GstMessage *message, gpointer data) + { + reinterpret_cast(data)->processMessage(bus, message); + return TRUE; + } + + guint m_tag; + QGstreamerBusHelper* m_helper; + +public: + GstBus* bus; + QGstreamerSyncEventFilter *filter; + QMutex filterMutex; +}; + +#else + +class QGstreamerBusHelperPrivate : public QObject +{ + Q_OBJECT + typedef QMap HelperMap; + +public: + void addWatch(GstBus* bus, QGstreamerBusHelper* helper) + { + m_helperMap.insert(helper, bus); + + if (m_helperMap.size() == 1) + m_intervalTimer->start(); + } + + void removeWatch(QGstreamerBusHelper* helper) + { + m_helperMap.remove(helper); + + if (m_helperMap.size() == 0) + m_intervalTimer->stop(); + } + + static QGstreamerBusHelperPrivate* instance() + { + static QGstreamerBusHelperPrivate self; + + return &self; + } + +private slots: + void interval() + { + for (HelperMap::iterator it = m_helperMap.begin(); it != m_helperMap.end(); ++it) { + GstMessage* message; + + while ((message = gst_bus_poll(it.value(), GST_MESSAGE_ANY, 0)) != 0) { + emit it.key()->message(message); + gst_message_unref(message); + } + + emit it.key()->message(QGstreamerMessage()); + } + } + +private: + QGstreamerBusHelperPrivate() + { + m_intervalTimer = new QTimer(this); + m_intervalTimer->setInterval(250); + + connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval())); + } + + HelperMap m_helperMap; + QTimer* m_intervalTimer; + +public: + GstBus* bus; + QGstreamerSyncEventFilter *filter; + QMutex filterMutex; +}; +#endif + + +static GstBusSyncReply syncGstBusFilter(GstBus* bus, GstMessage* message, QGstreamerBusHelperPrivate *d) +{ + Q_UNUSED(bus); + QMutexLocker lock(&d->filterMutex); + + bool res = false; + + if (d->filter) + res = d->filter->processSyncMessage(QGstreamerMessage(message)); + + return res ? GST_BUS_DROP : GST_BUS_PASS; +} + + +/*! + \class gstreamer::QGstreamerBusHelper + \internal +*/ + +QGstreamerBusHelper::QGstreamerBusHelper(GstBus* bus, QObject* parent): + QObject(parent), + d(QGstreamerBusHelperPrivate::instance()) +{ + d->bus = bus; + d->addWatch(bus, this); + + gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d); +} + +QGstreamerBusHelper::~QGstreamerBusHelper() +{ + d->removeWatch(this); + gst_bus_set_sync_handler(d->bus,0,0); +} + +void QGstreamerBusHelper::installSyncEventFilter(QGstreamerSyncEventFilter *filter) +{ + QMutexLocker lock(&d->filterMutex); + d->filter = filter; +} + +#include "qgstreamerbushelper.moc" diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h new file mode 100644 index 0000000..471ca50 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERBUSHELPER_H +#define QGSTREAMERBUSHELPER_H + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerSyncEventFilter { +public: + //returns true if message was processed and should be dropped, false otherwise + virtual bool processSyncMessage(const QGstreamerMessage &message) = 0; +}; + +class QGstreamerBusHelperPrivate; + +class QGstreamerBusHelper : public QObject +{ + Q_OBJECT + friend class QGstreamerBusHelperPrivate; + +public: + QGstreamerBusHelper(GstBus* bus, QObject* parent = 0); + ~QGstreamerBusHelper(); + + void installSyncEventFilter(QGstreamerSyncEventFilter *filter); + +signals: + void message(QGstreamerMessage const& message); + + +private: + QGstreamerBusHelperPrivate* d; +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp b/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp new file mode 100644 index 0000000..19cdfb1 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qgstreamermessage.h" + + +static int wuchi = qRegisterMetaType(); + + +/*! + \class gstreamer::QGstreamerMessage + \internal +*/ + +QGstreamerMessage::QGstreamerMessage(): + m_message(0) +{ +} + +QGstreamerMessage::QGstreamerMessage(GstMessage* message): + m_message(message) +{ + gst_message_ref(m_message); +} + +QGstreamerMessage::QGstreamerMessage(QGstreamerMessage const& m): + m_message(m.m_message) +{ + gst_message_ref(m_message); +} + + +QGstreamerMessage::~QGstreamerMessage() +{ + if (m_message != 0) + gst_message_unref(m_message); +} + +GstMessage* QGstreamerMessage::rawMessage() const +{ + return m_message; +} + +QGstreamerMessage& QGstreamerMessage::operator=(QGstreamerMessage const& rhs) +{ + if (m_message != 0) + gst_message_unref(m_message); + + if ((m_message = rhs.m_message) != 0) + gst_message_ref(m_message); + + return *this; +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreamermessage.h b/src/plugins/mediaservices/gstreamer/qgstreamermessage.h new file mode 100644 index 0000000..70f35f3 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamermessage.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERMESSAGE_H +#define QGSTREAMERMESSAGE_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerMessage +{ +public: + QGstreamerMessage(); + QGstreamerMessage(GstMessage* message); + QGstreamerMessage(QGstreamerMessage const& m); + ~QGstreamerMessage(); + + GstMessage* rawMessage() const; + + QGstreamerMessage& operator=(QGstreamerMessage const& rhs); + +private: + GstMessage* m_message; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGstreamerMessage); + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp new file mode 100644 index 0000000..e892e45 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "qgstreamerserviceplugin.h" + +#ifdef QMEDIA_GSTREAMER_PLAYER +#include "qgstreamerplayerservice.h" +#endif +#ifdef QMEDIA_GSTREAMER_CAPTURE +#include "qgstreamercaptureservice.h" +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + + +QStringList QGstreamerServicePlugin::keys() const +{ + return QStringList() +#ifdef QMEDIA_GSTREAMER_PLAYER + << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) +#endif +#ifdef QMEDIA_GSTREAMER_CAPTURE + << QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE) + << QLatin1String(Q_MEDIASERVICE_CAMERA) +#endif + ; +} + +QMediaService* QGstreamerServicePlugin::create(const QString &key) +{ +#ifdef QMEDIA_GSTREAMER_PLAYER + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) + return new QGstreamerPlayerService; +#endif +#ifdef QMEDIA_GSTREAMER_CAPTURE + if (key == QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE)) + return new QGstreamerCaptureService(key); + + if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) + return new QGstreamerCaptureService(key); +#endif + + qDebug() << "unsupported key:" << key; + return 0; +} + +void QGstreamerServicePlugin::release(QMediaService *service) +{ + delete service; +} + +QList QGstreamerServicePlugin::devices(const QByteArray &service) const +{ + if (service == Q_MEDIASERVICE_CAMERA) { + if (m_cameraDevices.isEmpty()) + updateDevices(); + + return m_cameraDevices; + } + + return QList(); +} + +QString QGstreamerServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) +{ + if (service == Q_MEDIASERVICE_CAMERA) { + if (m_cameraDevices.isEmpty()) + updateDevices(); + + for (int i=0; i= 0; ++input.index) { + if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) { + isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0; + break; + } + } + + if (isCamera) { + // find out its driver "name" + QString name; + struct v4l2_capability vcap; + memset(&vcap, 0, sizeof(struct v4l2_capability)); + + if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) + name = entryInfo.fileName(); + else + name = QString((const char*)vcap.card); + qDebug() << "found camera: " << name; + + m_cameraDevices.append(entryInfo.filePath().toLocal8Bit()); + m_cameraDescriptions.append(name); + } + ::close(fd); + } +} + +Q_EXPORT_PLUGIN2(gstengine, QGstreamerServicePlugin); + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h new file mode 100644 index 0000000..33148ac --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QGSTREAMERSERVICEPLUGIN_H +#define QGSTREAMERSERVICEPLUGIN_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerServicePlugin : public QMediaServiceProviderPlugin, public QMediaServiceSupportedDevicesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedDevicesInterface) +public: + QStringList keys() const; + QMediaService* create(QString const& key); + void release(QMediaService *service); + + QList devices(const QByteArray &service) const; + QString deviceDescription(const QByteArray &service, const QByteArray &device); + +private: + void updateDevices() const; + + mutable QList m_cameraDevices; + mutable QStringList m_cameraDescriptions; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERSERVICEPLUGIN_H diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp new file mode 100644 index 0000000..5059409 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideoinputdevicecontrol.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QGstreamerVideoInputDeviceControl::QGstreamerVideoInputDeviceControl(QObject *parent) + :QVideoDeviceControl(parent), m_selectedDevice(0) +{ + update(); +} + +QGstreamerVideoInputDeviceControl::~QGstreamerVideoInputDeviceControl() +{ +} + +int QGstreamerVideoInputDeviceControl::deviceCount() const +{ + return m_names.size(); +} + +QString QGstreamerVideoInputDeviceControl::deviceName(int index) const +{ + return m_names[index]; +} + +QString QGstreamerVideoInputDeviceControl::deviceDescription(int index) const +{ + return m_descriptions[index]; +} + +QIcon QGstreamerVideoInputDeviceControl::deviceIcon(int index) const +{ + Q_UNUSED(index); + return QIcon(); +} + +int QGstreamerVideoInputDeviceControl::defaultDevice() const +{ + return 0; +} + +int QGstreamerVideoInputDeviceControl::selectedDevice() const +{ + return m_selectedDevice; +} + + +void QGstreamerVideoInputDeviceControl::setSelectedDevice(int index) +{ + if (index != m_selectedDevice) { + m_selectedDevice = index; + emit selectedDeviceChanged(index); + emit selectedDeviceChanged(deviceName(index)); + } +} + + +void QGstreamerVideoInputDeviceControl::update() +{ + m_names.clear(); + m_descriptions.clear(); + + QDir devDir("/dev"); + devDir.setFilter(QDir::System); + + QFileInfoList entries = devDir.entryInfoList(QStringList() << "video*"); + + foreach( const QFileInfo &entryInfo, entries ) { + qDebug() << "Try" << entryInfo.filePath(); + + int fd = ::open(entryInfo.filePath().toLatin1().constData(), O_RDWR ); + if (fd == -1) + continue; + + bool isCamera = false; + + v4l2_input input; + memset(&input, 0, sizeof(input)); + for (; ::ioctl(fd, VIDIOC_ENUMINPUT, &input) >= 0; ++input.index) { + if(input.type == V4L2_INPUT_TYPE_CAMERA || input.type == 0) { + isCamera = ::ioctl(fd, VIDIOC_S_INPUT, input.index) != 0; + break; + } + } + + if (isCamera) { + // find out its driver "name" + QString name; + struct v4l2_capability vcap; + memset(&vcap, 0, sizeof(struct v4l2_capability)); + + if (ioctl(fd, VIDIOC_QUERYCAP, &vcap) != 0) + name = entryInfo.fileName(); + else + name = QString((const char*)vcap.card); + qDebug() << "found camera: " << name; + + m_names.append(entryInfo.filePath()); + m_descriptions.append(name); + } + ::close(fd); + } +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h new file mode 100644 index 0000000..5cdc05f --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEOINPUTDEVICECONTROL_H +#define QGSTREAMERVIDEOINPUTDEVICECONTROL_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QGstreamerVideoInputDeviceControl : public QVideoDeviceControl +{ +Q_OBJECT +public: + QGstreamerVideoInputDeviceControl(QObject *parent); + ~QGstreamerVideoInputDeviceControl(); + + int deviceCount() const; + + QString deviceName(int index) const; + QString deviceDescription(int index) const; + QIcon deviceIcon(int index) const; + + int defaultDevice() const; + int selectedDevice() const; + +public Q_SLOTS: + void setSelectedDevice(int index); + +private: + void update(); + + int m_selectedDevice; + QStringList m_names; + QStringList m_descriptions; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERAUDIOINPUTDEVICECONTROL_H diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp new file mode 100644 index 0000000..10d446f --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideooutputcontrol.h" + +QGstreamerVideoOutputControl::QGstreamerVideoOutputControl(QObject *parent) + : QVideoOutputControl(parent) + , m_output(NoOutput) +{ +} + +QList QGstreamerVideoOutputControl::availableOutputs() const +{ + return m_outputs; +} + +void QGstreamerVideoOutputControl::setAvailableOutputs(const QList &outputs) +{ + emit availableOutputsChanged(m_outputs = outputs); +} + +QVideoOutputControl::Output QGstreamerVideoOutputControl::output() const +{ + return m_output; +} + +void QGstreamerVideoOutputControl::setOutput(Output output) +{ + if (!m_outputs.contains(output)) + output = NoOutput; + + if (m_output != output) + emit outputChanged(m_output = output); +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h new file mode 100644 index 0000000..0d618f2 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEOOUTPUTCONTROL_H +#define QGSTREAMERVIDEOOUTPUTCONTROL_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerVideoRendererInterface +{ +public: + virtual ~QGstreamerVideoRendererInterface(); + virtual GstElement *videoSink() = 0; + virtual void precessNewStream() {} +}; + +class QGstreamerVideoOutputControl : public QVideoOutputControl +{ + Q_OBJECT +public: + QGstreamerVideoOutputControl(QObject *parent = 0); + + QList availableOutputs() const; + void setAvailableOutputs(const QList &outputs); + + Output output() const; + void setOutput(Output output); + +Q_SIGNALS: + void outputChanged(QVideoOutputControl::Output output); + +private: + QList m_outputs; + Output m_output; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp new file mode 100644 index 0000000..8dbe3db --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideooverlay.h" +#include "qvideosurfacegstsink.h" + +#include + +#include "qx11videosurface.h" + +QGstreamerVideoOverlay::QGstreamerVideoOverlay(QObject *parent) + : QVideoWindowControl(parent) + , m_surface(new QX11VideoSurface) + , m_videoSink(reinterpret_cast(QVideoSurfaceGstSink::createSink(m_surface))) + , m_aspectRatioMode(QVideoWidget::KeepAspectRatio) + , m_fullScreen(false) +{ + if (m_videoSink) { + gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership + gst_object_sink(GST_OBJECT(m_videoSink)); + } + + connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), + this, SLOT(surfaceFormatChanged())); +} + +QGstreamerVideoOverlay::~QGstreamerVideoOverlay() +{ + if (m_videoSink) + gst_object_unref(GST_OBJECT(m_videoSink)); + + delete m_surface; +} + +WId QGstreamerVideoOverlay::winId() const +{ + return m_surface->winId(); +} + +void QGstreamerVideoOverlay::setWinId(WId id) +{ + m_surface->setWinId(id); +} + +QRect QGstreamerVideoOverlay::displayRect() const +{ + return m_displayRect; +} + +void QGstreamerVideoOverlay::setDisplayRect(const QRect &rect) +{ + m_displayRect = rect; + + setScaledDisplayRect(); +} + +QVideoWidget::AspectRatioMode QGstreamerVideoOverlay::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QGstreamerVideoOverlay::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; + + setScaledDisplayRect(); +} + +void QGstreamerVideoOverlay::repaint() +{ +} + +int QGstreamerVideoOverlay::brightness() const +{ + return m_surface->brightness(); +} + +void QGstreamerVideoOverlay::setBrightness(int brightness) +{ + m_surface->setBrightness(brightness); + + emit brightnessChanged(m_surface->brightness()); +} + +int QGstreamerVideoOverlay::contrast() const +{ + return m_surface->contrast(); +} + +void QGstreamerVideoOverlay::setContrast(int contrast) +{ + m_surface->setContrast(contrast); + + emit contrastChanged(m_surface->contrast()); +} + +int QGstreamerVideoOverlay::hue() const +{ + return m_surface->hue(); +} + +void QGstreamerVideoOverlay::setHue(int hue) +{ + m_surface->setHue(hue); + + emit hueChanged(m_surface->hue()); +} + +int QGstreamerVideoOverlay::saturation() const +{ + return m_surface->saturation(); +} + +void QGstreamerVideoOverlay::setSaturation(int saturation) +{ + m_surface->setSaturation(saturation); + + emit saturationChanged(m_surface->saturation()); +} + +bool QGstreamerVideoOverlay::isFullScreen() const +{ + return m_fullScreen; +} + +void QGstreamerVideoOverlay::setFullScreen(bool fullScreen) +{ + emit fullScreenChanged(m_fullScreen = fullScreen); +} + +QSize QGstreamerVideoOverlay::nativeSize() const +{ + return m_surface->surfaceFormat().sizeHint(); +} + +QAbstractVideoSurface *QGstreamerVideoOverlay::surface() const +{ + return m_surface; +} + +GstElement *QGstreamerVideoOverlay::videoSink() +{ + return m_videoSink; +} + +void QGstreamerVideoOverlay::surfaceFormatChanged() +{ + setScaledDisplayRect(); + + emit nativeSizeChanged(); +} + +void QGstreamerVideoOverlay::setScaledDisplayRect() +{ + switch (m_aspectRatioMode) { + case QVideoWidget::KeepAspectRatio: + { + QSize size = m_surface->surfaceFormat().viewport().size(); + + size.scale(m_displayRect.size(), Qt::KeepAspectRatio); + + QRect rect(QPoint(0, 0), size); + rect.moveCenter(m_displayRect.center()); + + m_surface->setDisplayRect(rect); + } + break; + case QVideoWidget::IgnoreAspectRatio: + m_surface->setDisplayRect(m_displayRect); + break; + }; +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h new file mode 100644 index 0000000..518d8ce --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEOOVERLAY_H +#define QGSTREAMERVIDEOOVERLAY_H + +#include + +#include "qgstreamervideorendererinterface.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QAbstractVideoSurface; +class QX11VideoSurface; + +class QGstreamerVideoOverlay : public QVideoWindowControl, public QGstreamerVideoRendererInterface +{ + Q_OBJECT + Q_INTERFACES(QGstreamerVideoRendererInterface) +public: + QGstreamerVideoOverlay(QObject *parent = 0); + ~QGstreamerVideoOverlay(); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + QSize nativeSize() const; + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + void repaint(); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + QAbstractVideoSurface *surface() const; + + GstElement *videoSink(); + +private slots: + void surfaceFormatChanged(); + +private: + void setScaledDisplayRect(); + + QX11VideoSurface *m_surface; + GstElement *m_videoSink; + QVideoWidget::AspectRatioMode m_aspectRatioMode; + QRect m_displayRect; + bool m_fullScreen; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp new file mode 100644 index 0000000..7e10fbf --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideorenderer.h" +#include "qvideosurfacegstsink.h" + +#include +#include + +#include + +QGstreamerVideoRenderer::QGstreamerVideoRenderer(QObject *parent) + :QVideoRendererControl(parent),m_videoSink(0) +{ +} + +QGstreamerVideoRenderer::~QGstreamerVideoRenderer() +{ + if (m_videoSink) + gst_object_unref(GST_OBJECT(m_videoSink)); +} + +GstElement *QGstreamerVideoRenderer::videoSink() +{ + if (!m_videoSink) { + m_videoSink = reinterpret_cast(QVideoSurfaceGstSink::createSink(m_surface)); + gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership + gst_object_sink(GST_OBJECT(m_videoSink)); + } + + return m_videoSink; +} + + +QAbstractVideoSurface *QGstreamerVideoRenderer::surface() const +{ + return m_surface; +} + +void QGstreamerVideoRenderer::setSurface(QAbstractVideoSurface *surface) +{ + m_surface = surface; +} + diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h new file mode 100644 index 0000000..f476730 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEORENDERER_H +#define QGSTREAMERVIDEORENDERER_H + +#include +#include "qvideosurfacegstsink.h" + +#include "qgstreamervideorendererinterface.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerVideoRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface +{ + Q_OBJECT + Q_INTERFACES(QGstreamerVideoRendererInterface) +public: + QGstreamerVideoRenderer(QObject *parent = 0); + virtual ~QGstreamerVideoRenderer(); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + GstElement *videoSink(); + void precessNewStream() {} + +private: + GstElement *m_videoSink; + QAbstractVideoSurface *m_surface; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERVIDEORENDRER_H diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp new file mode 100644 index 0000000..57df692 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideorendererinterface.h" + +QGstreamerVideoRendererInterface::~QGstreamerVideoRendererInterface() +{ +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h new file mode 100644 index 0000000..2700965 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEOOUTPUTCONTROL_H +#define QGSTREAMERVIDEOOUTPUTCONTROL_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerVideoRendererInterface +{ +public: + virtual ~QGstreamerVideoRendererInterface(); + virtual GstElement *videoSink() = 0; + virtual void precessNewStream() {} +}; + +QT_END_NAMESPACE + +#define QGstreamerVideoRendererInterface_iid "com.nokia.Qt.QGstreamerVideoRendererInterface/1.0" +Q_DECLARE_INTERFACE(QGstreamerVideoRendererInterface, QGstreamerVideoRendererInterface_iid) + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp new file mode 100644 index 0000000..7b2ec14 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp @@ -0,0 +1,322 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamervideowidget.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +class QGstreamerVideoWidget : public QWidget +{ +public: + QGstreamerVideoWidget(QWidget *parent = 0) + :QWidget(parent) + { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QPalette palette; + palette.setColor(QPalette::Background, Qt::black); + setPalette(palette); + } + + virtual ~QGstreamerVideoWidget() {} + + QSize sizeHint() const + { + return m_nativeSize; + } + + void setNativeSize( const QSize &size) + { + if (size != m_nativeSize) { + m_nativeSize = size; + if (size.isEmpty()) + setMinimumSize(0,0); + else + setMinimumSize(160,120); + + updateGeometry(); + } + } + +protected: + void paintEvent(QPaintEvent *) + { + QPainter painter(this); + painter.fillRect(rect(), palette().background()); + } + + QSize m_nativeSize; +}; + +QGstreamerVideoWidgetControl::QGstreamerVideoWidgetControl(QObject *parent) + : QVideoWidgetControl(parent) + , m_videoSink(0) + , m_widget(new QGstreamerVideoWidget) + , m_fullScreen(false) +{ + m_widget->installEventFilter(this); + m_windowId = m_widget->winId(); + + m_videoSink = gst_element_factory_make ("xvimagesink", NULL); + if (m_videoSink) { + // Check if the xv sink is usable + if (gst_element_set_state(m_videoSink, GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS) { + gst_object_unref(GST_OBJECT(m_videoSink)); + m_videoSink = 0; + } else { + gst_element_set_state(m_videoSink, GST_STATE_NULL); + + g_object_set(G_OBJECT(m_videoSink), "force-aspect-ratio", 1, (const char*)NULL); + } + } + + if (!m_videoSink) + m_videoSink = gst_element_factory_make ("ximagesink", NULL); + + gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership + gst_object_sink (GST_OBJECT (m_videoSink)); +} + +QGstreamerVideoWidgetControl::~QGstreamerVideoWidgetControl() +{ + if (m_videoSink) + gst_object_unref(GST_OBJECT(m_videoSink)); + + delete m_widget; +} + +GstElement *QGstreamerVideoWidgetControl::videoSink() +{ + return m_videoSink; +} + +bool QGstreamerVideoWidgetControl::eventFilter(QObject *object, QEvent *e) +{ + if (object == m_widget) { + if (e->type() == QEvent::ParentChange || e->type() == QEvent::Show) { + WId newWId = m_widget->winId(); + if (newWId != m_windowId) { + m_windowId = newWId; + // Even if we have created a winId at this point, other X applications + // need to be aware of it. + QApplication::syncX(); + setOverlay(); + } + } + + if (e->type() == QEvent::Show) { + // Setting these values ensures smooth resizing since it + // will prevent the system from clearing the background + m_widget->setAttribute(Qt::WA_NoSystemBackground, true); + m_widget->setAttribute(Qt::WA_PaintOnScreen, true); + } else if (e->type() == QEvent::Resize) { + // This is a workaround for missing background repaints + // when reducing window size + windowExposed(); + } + } + + return false; +} + +void QGstreamerVideoWidgetControl::precessNewStream() +{ + setOverlay(); + QMetaObject::invokeMethod(this, "updateNativeVideoSize", Qt::QueuedConnection); +} + +void QGstreamerVideoWidgetControl::setOverlay() +{ + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { + gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); + } +} + +void QGstreamerVideoWidgetControl::updateNativeVideoSize() +{ + if (m_videoSink) { + //find video native size to update video widget size hint + GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); + GstCaps *caps = gst_pad_get_negotiated_caps(pad); + + if (caps) { + GstStructure *str; + gint width, height; + + if ((str = gst_caps_get_structure (caps, 0))) { + if (gst_structure_get_int (str, "width", &width) && gst_structure_get_int (str, "height", &height)) { + gint aspectNum = 0; + gint aspectDenum = 0; + if (gst_structure_get_fraction(str, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { + if (aspectDenum > 0) + width = width*aspectNum/aspectDenum; + } + m_widget->setNativeSize(QSize(width, height)); + } + } + gst_caps_unref(caps); + } + } else { + m_widget->setNativeSize(QSize()); + } +} + + +void QGstreamerVideoWidgetControl::windowExposed() +{ + if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) + gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); +} + +QWidget *QGstreamerVideoWidgetControl::videoWidget() +{ + return m_widget; +} + +QVideoWidget::AspectRatioMode QGstreamerVideoWidgetControl::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QGstreamerVideoWidgetControl::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + if (m_videoSink) { + g_object_set(G_OBJECT(m_videoSink), + "force-aspect-ratio", + (mode == QVideoWidget::KeepAspectRatio), + (const char*)NULL); + } + + m_aspectRatioMode = mode; +} + +bool QGstreamerVideoWidgetControl::isFullScreen() const +{ + return m_fullScreen; +} + +void QGstreamerVideoWidgetControl::setFullScreen(bool fullScreen) +{ + emit fullScreenChanged(m_fullScreen = fullScreen); +} + +int QGstreamerVideoWidgetControl::brightness() const +{ + int brightness = 0; + + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) + g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL); + + return brightness / 10; +} + +void QGstreamerVideoWidgetControl::setBrightness(int brightness) +{ + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "brightness")) { + g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL); + + emit brightnessChanged(brightness); + } +} + +int QGstreamerVideoWidgetControl::contrast() const +{ + int contrast = 0; + + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) + g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL); + + return contrast / 10; +} + +void QGstreamerVideoWidgetControl::setContrast(int contrast) +{ + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "contrast")) { + g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL); + + emit contrastChanged(contrast); + } +} + +int QGstreamerVideoWidgetControl::hue() const +{ + int hue = 0; + + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) + g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL); + + return hue / 10; +} + +void QGstreamerVideoWidgetControl::setHue(int hue) +{ + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "hue")) { + g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL); + + emit hueChanged(hue); + } +} + +int QGstreamerVideoWidgetControl::saturation() const +{ + int saturation = 0; + + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) + g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL); + + return saturation / 10; +} + +void QGstreamerVideoWidgetControl::setSaturation(int saturation) +{ + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "saturation")) { + g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL); + + emit saturationChanged(saturation); + } +} diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h new file mode 100644 index 0000000..9edd1dd --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERVIDEOWIDGET_H +#define QGSTREAMERVIDEOWIDGET_H + +#include + +#include "qgstreamervideorendererinterface.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstreamerVideoWidget; + +class QGstreamerVideoWidgetControl + : public QVideoWidgetControl + , public QGstreamerVideoRendererInterface +{ + Q_OBJECT + Q_INTERFACES(QGstreamerVideoRendererInterface) +public: + QGstreamerVideoWidgetControl(QObject *parent = 0); + virtual ~QGstreamerVideoWidgetControl(); + + GstElement *videoSink(); + void precessNewStream(); + + QWidget *videoWidget(); + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + void setOverlay(); + + bool eventFilter(QObject *object, QEvent *event); + +public slots: + void updateNativeVideoSize(); + +private: + void windowExposed(); + + GstElement *m_videoSink; + QGstreamerVideoWidget *m_widget; + WId m_windowId; + QVideoWidget::AspectRatioMode m_aspectRatioMode; + bool m_fullScreen; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGSTREAMERVIDEOWIDGET_H diff --git a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp new file mode 100644 index 0000000..80943b5 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstvideobuffer.h" + + +QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine) + : QAbstractVideoBuffer(NoHandle) + , m_buffer(buffer) + , m_bytesPerLine(bytesPerLine) + , m_mode(NotMapped) +{ + gst_buffer_ref(m_buffer); +} + +QGstVideoBuffer::~QGstVideoBuffer() +{ + gst_buffer_unref(m_buffer); +} + + +QAbstractVideoBuffer::MapMode QGstVideoBuffer::mapMode() const +{ + return m_mode; +} + +uchar *QGstVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) +{ + if (mode != NotMapped && m_mode == NotMapped) { + if (numBytes) + *numBytes = m_buffer->size; + + if (bytesPerLine) + *bytesPerLine = m_bytesPerLine; + + m_mode = mode; + + return m_buffer->data; + } else { + return 0; + } +} +void QGstVideoBuffer::unmap() +{ + m_mode = NotMapped; +} + diff --git a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h new file mode 100644 index 0000000..487832c --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTVIDEOBUFFER_H +#define QGSTVIDEOBUFFER_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QGstVideoBuffer : public QAbstractVideoBuffer +{ +public: + QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine); + ~QGstVideoBuffer(); + + MapMode mapMode() const; + + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); + void unmap(); + +private: + GstBuffer *m_buffer; + int m_bytesPerLine; + MapMode m_mode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp new file mode 100644 index 0000000..7c5805c --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -0,0 +1,553 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvideosurfacegstsink.h" + +#include "qgstvideobuffer.h" + +#include +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QVideoSurfaceFormat) + +QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface) + : m_surface(surface) + , m_renderReturn(GST_FLOW_ERROR) + , m_bytesPerLine(0) +{ + m_supportedPixelFormats = m_surface->supportedPixelFormats(); + + connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged())); +} + +QList QVideoSurfaceGstDelegate::supportedPixelFormats() const +{ + QMutexLocker locker(const_cast(&m_mutex)); + + return m_supportedPixelFormats; +} + +bool QVideoSurfaceGstDelegate::start(const QVideoSurfaceFormat &format, int bytesPerLine) +{ + QMutexLocker locker(&m_mutex); + + m_format = format; + m_bytesPerLine = bytesPerLine; + + if (QThread::currentThread() == thread()) { + m_started = !m_surface.isNull() ? m_surface->start(m_format) : false; + } else { + QMetaObject::invokeMethod(this, "queuedStart", Qt::QueuedConnection); + + m_setupCondition.wait(&m_mutex); + } + + return m_started; +} + +void QVideoSurfaceGstDelegate::stop() +{ + QMutexLocker locker(&m_mutex); + + if (QThread::currentThread() == thread()) { + if (!m_surface.isNull()) + m_surface->stop(); + } else { + QMetaObject::invokeMethod(this, "queuedStop", Qt::QueuedConnection); + + m_setupCondition.wait(&m_mutex); + } + + m_started = false; +} + +GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) +{ + QMutexLocker locker(&m_mutex); + + m_frame = QVideoFrame( + new QGstVideoBuffer(buffer, m_bytesPerLine), + m_format.frameSize(), + m_format.pixelFormat()); + + qint64 startTime = GST_BUFFER_TIMESTAMP(buffer); + + if (startTime >= 0) { + m_frame.setStartTime(startTime/G_GINT64_CONSTANT (1000000)); + + qint64 duration = GST_BUFFER_DURATION(buffer); + + if (duration >= 0) + m_frame.setEndTime((startTime + duration)/G_GINT64_CONSTANT (1000000)); + } + + QMetaObject::invokeMethod(this, "queuedRender", Qt::QueuedConnection); + + if (!m_renderCondition.wait(&m_mutex, 300)) { + m_frame = QVideoFrame(); + + return GST_FLOW_OK; + } else { + return m_renderReturn; + } +} + + +void QVideoSurfaceGstDelegate::queuedStart() +{ + QMutexLocker locker(&m_mutex); + + m_started = m_surface->start(m_format); + + m_setupCondition.wakeAll(); +} + +void QVideoSurfaceGstDelegate::queuedStop() +{ + QMutexLocker locker(&m_mutex); + + m_surface->stop(); + + m_setupCondition.wakeAll(); +} + +void QVideoSurfaceGstDelegate::queuedRender() +{ + QMutexLocker locker(&m_mutex); + + if (m_surface.isNull()) { + m_renderReturn = GST_FLOW_ERROR; + } else if (m_surface->present(m_frame)) { + m_renderReturn = GST_FLOW_OK; + } else { + switch (m_surface->error()) { + case QAbstractVideoSurface::NoError: + m_renderReturn = GST_FLOW_OK; + break; + case QAbstractVideoSurface::StoppedError: + m_renderReturn = GST_FLOW_NOT_NEGOTIATED; + break; + default: + m_renderReturn = GST_FLOW_ERROR; + break; + } + } + + m_renderCondition.wakeAll(); +} + +void QVideoSurfaceGstDelegate::supportedFormatsChanged() +{ + QMutexLocker locker(&m_mutex); + + m_supportedPixelFormats = m_surface->supportedPixelFormats(); +} + +struct YuvFormat +{ + QVideoFrame::PixelFormat pixelFormat; + guint32 fourcc; + int bitsPerPixel; +}; + +static const YuvFormat qt_yuvColorLookup[] = +{ + { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 }, + { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 }, + { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 8 }, + { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','V'), 8 }, + { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 8 }, + { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 }, + { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 } +}; + +static int indexOfYuvColor(QVideoFrame::PixelFormat format) +{ + const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat); + + for (int i = 0; i < count; ++i) + if (qt_yuvColorLookup[i].pixelFormat == format) + return i; + return -1; +} + +static int indexOfYuvColor(guint32 fourcc) +{ + const int count = sizeof(YuvFormat) / sizeof(YuvFormat); + + for (int i = 0; i < count; ++i) + if (qt_yuvColorLookup[i].fourcc == fourcc) + return i; + return -1; +} + +struct RgbFormat +{ + QVideoFrame::PixelFormat pixelFormat; + int bitsPerPixel; + int depth; + int endianness; + int red; + int green; + int blue; + int alpha; +}; + +static const RgbFormat qt_rgbColorLookup[] = +{ + { QVideoFrame::Format_RGB32 , 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, + { QVideoFrame::Format_RGB32 , 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, + { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, + { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 } +}; + +static int indexOfRgbColor( + int bits, int depth, int endianness, int red, int green, int blue, int alpha) +{ + const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat); + + for (int i = 0; i < count; ++i) { + if (qt_rgbColorLookup[i].bitsPerPixel == bits + && qt_rgbColorLookup[i].depth == depth + && qt_rgbColorLookup[i].endianness == endianness + && qt_rgbColorLookup[i].red == red + && qt_rgbColorLookup[i].green == green + && qt_rgbColorLookup[i].blue == blue + && qt_rgbColorLookup[i].alpha == alpha) { + return i; + } + } + return -1; +} + +static GstVideoSinkClass *sink_parent_class; + +#define VO_SINK(s) QVideoSurfaceGstSink *sink(reinterpret_cast(s)) + +QVideoSurfaceGstSink *QVideoSurfaceGstSink::createSink(QAbstractVideoSurface *surface) +{ + QVideoSurfaceGstSink *sink = reinterpret_cast( + g_object_new(QVideoSurfaceGstSink::get_type(), 0)); + + sink->delegate = new QVideoSurfaceGstDelegate(surface); + + return sink; +} + +GType QVideoSurfaceGstSink::get_type() +{ + static GType type = 0; + + if (type == 0) { + static const GTypeInfo info = + { + sizeof(QVideoSurfaceGstSinkClass), // class_size + base_init, // base_init + NULL, // base_finalize + class_init, // class_init + NULL, // class_finalize + NULL, // class_data + sizeof(QVideoSurfaceGstSink), // instance_size + 0, // n_preallocs + instance_init, // instance_init + 0 // value_table + }; + + type = g_type_register_static( + GST_TYPE_VIDEO_SINK, "QVideoSurfaceGstSink", &info, GTypeFlags(0)); + } + + return type; +} + +void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) +{ + Q_UNUSED(class_data); + + sink_parent_class = reinterpret_cast(g_type_class_peek_parent(g_class)); + + GstBaseSinkClass *base_sink_class = reinterpret_cast(g_class); + base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; + base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; + // base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc; // Not implemented. + base_sink_class->start = QVideoSurfaceGstSink::start; + base_sink_class->stop = QVideoSurfaceGstSink::stop; + // base_sink_class->unlock = QVideoSurfaceGstSink::unlock; // Not implemented. + // base_sink_class->event = QVideoSurfaceGstSink::event; // Not implemented. + base_sink_class->preroll = QVideoSurfaceGstSink::preroll; + base_sink_class->render = QVideoSurfaceGstSink::render; + + GstElementClass *element_class = reinterpret_cast(g_class); + element_class->change_state = QVideoSurfaceGstSink::change_state; + + GObjectClass *object_class = reinterpret_cast(g_class); + object_class->finalize = QVideoSurfaceGstSink::finalize; +} + +void QVideoSurfaceGstSink::base_init(gpointer g_class) +{ + static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE( + "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS( + "video/x-raw-rgb, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ]; " + "video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ]")); + + gst_element_class_add_pad_template( + GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template)); +} + +void QVideoSurfaceGstSink::instance_init(GTypeInstance *instance, gpointer g_class) +{ + VO_SINK(instance); + + Q_UNUSED(g_class); + + sink->delegate = 0; +} + +void QVideoSurfaceGstSink::finalize(GObject *object) +{ + Q_UNUSED(object); +} + +GstStateChangeReturn QVideoSurfaceGstSink::change_state( + GstElement *element, GstStateChange transition) +{ + Q_UNUSED(element); + + return GST_ELEMENT_CLASS(sink_parent_class)->change_state( + element, transition); +} + +GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) +{ + VO_SINK(base); + + GstCaps *caps = gst_caps_new_empty(); + + foreach (QVideoFrame::PixelFormat format, sink->delegate->supportedPixelFormats()) { + int index = indexOfYuvColor(format); + + if (index != -1) { + gst_caps_append_structure(caps, gst_structure_new( + "video/x-raw-yuv", + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, + "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, + "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, + "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc, + NULL)); + continue; + } + + const int count = sizeof(qt_rgbColorLookup) / sizeof(RgbFormat); + + for (int i = 0; i < count; ++i) { + if (qt_rgbColorLookup[i].pixelFormat == format) { + GstStructure *structure = gst_structure_new( + "video/x-raw-rgb", + "framerate" , GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, + "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, + "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, + "bpp" , G_TYPE_INT, qt_rgbColorLookup[i].bitsPerPixel, + "depth" , G_TYPE_INT, qt_rgbColorLookup[i].depth, + "endianness", G_TYPE_INT, qt_rgbColorLookup[i].endianness, + "red_mask" , G_TYPE_INT, qt_rgbColorLookup[i].red, + "green_mask", G_TYPE_INT, qt_rgbColorLookup[i].green, + "blue_mask" , G_TYPE_INT, qt_rgbColorLookup[i].blue, + NULL); + + if (qt_rgbColorLookup[i].alpha != 0) { + gst_structure_set( + structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, NULL); + } + gst_caps_append_structure(caps, structure); + } + } + } + + return caps; +} + +gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) +{ + VO_SINK(base); + + if (!caps) { + sink->delegate->stop(); + + return TRUE; + } else { + const GstStructure *structure = gst_caps_get_structure(caps, 0); + + //qDebug() << gst_caps_to_string(caps); + + QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid; + int bitsPerPixel = 0; + + QSize size; + gst_structure_get_int(structure, "width", &size.rwidth()); + gst_structure_get_int(structure, "height", &size.rheight()); + + if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) { + guint32 fourcc = 0; + gst_structure_get_fourcc(structure, "format", &fourcc); + + int index = indexOfYuvColor(fourcc); + if (index != -1) { + pixelFormat = qt_yuvColorLookup[index].pixelFormat; + bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel; + } + } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) { + int depth = 0; + int endianness = 0; + int red = 0; + int green = 0; + int blue = 0; + int alpha = 0; + + gst_structure_get_int(structure, "bpp", &bitsPerPixel); + gst_structure_get_int(structure, "depth", &depth); + gst_structure_get_int(structure, "endianness", &endianness); + gst_structure_get_int(structure, "red_mask", &red); + gst_structure_get_int(structure, "green_mask", &green); + gst_structure_get_int(structure, "blue_mask", &blue); + gst_structure_get_int(structure, "alpha_mask", &alpha); + + int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha); + + if (index != -1) + pixelFormat = qt_rgbColorLookup[index].pixelFormat; + } + + if (pixelFormat != QVideoFrame::Format_Invalid) { + QVideoSurfaceFormat format(size, pixelFormat); + + QPair rate; + gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second); + + if (rate.second) + format.setFrameRate(qreal(rate.first)/rate.second); + + gint aspectNum = 0; + gint aspectDenum = 0; + if (gst_structure_get_fraction( + structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { + if (aspectDenum > 0) + format.setPixelAspectRatio(aspectNum, aspectDenum); + } + + int bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3; + + if (sink->delegate->start(format, bytesPerLine)) + return TRUE; + } + + } + + return FALSE; +} + +GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( + GstBaseSink *base, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer) +{ + // Should implement this when the buffer pool situation is sorted. + Q_UNUSED(base); + Q_UNUSED(offset); + Q_UNUSED(size); + Q_UNUSED(caps); + Q_UNUSED(buffer); + + return GST_FLOW_NOT_SUPPORTED; +} + +gboolean QVideoSurfaceGstSink::start(GstBaseSink *base) +{ + Q_UNUSED(base); + + return TRUE; +} + +gboolean QVideoSurfaceGstSink::stop(GstBaseSink *base) +{ + Q_UNUSED(base); + + return TRUE; +} + +gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base) +{ + Q_UNUSED(base); + + return TRUE; +} + +gboolean QVideoSurfaceGstSink::event(GstBaseSink *base, GstEvent *event) +{ + Q_UNUSED(base); + Q_UNUSED(event); + + return TRUE; +} + +GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer) +{ + VO_SINK(base); + + return sink->delegate->render(buffer); +} + +GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer) +{ + VO_SINK(base); + return sink->delegate->render(buffer); +} + diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h new file mode 100644 index 0000000..99d7007 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VIDEOSURFACEGSTSINK_H +#define VIDEOSURFACEGSTSINK_H + +#include + +#include +#include +#include +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QAbstractVideoSurface; + +class QVideoSurfaceGstDelegate : public QObject +{ + Q_OBJECT +public: + QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface); + + QList supportedPixelFormats() const; + + bool start(const QVideoSurfaceFormat &format, int bytesPerLine); + void stop(); + + GstFlowReturn render(GstBuffer *buffer); + +private slots: + void queuedStart(); + void queuedStop(); + void queuedRender(); + + void supportedFormatsChanged(); + +private: + QPointer m_surface; + QList m_supportedPixelFormats; + QMutex m_mutex; + QWaitCondition m_setupCondition; + QWaitCondition m_renderCondition; + QVideoSurfaceFormat m_format; + QVideoFrame m_frame; + GstFlowReturn m_renderReturn; + int m_bytesPerLine; + bool m_started; +}; + +class QVideoSurfaceGstSink +{ +public: + GstVideoSink parent; + + static QVideoSurfaceGstSink *createSink(QAbstractVideoSurface *surface); + +private: + static GType get_type(); + static void class_init(gpointer g_class, gpointer class_data); + static void base_init(gpointer g_class); + static void instance_init(GTypeInstance *instance, gpointer g_class); + + static void finalize(GObject *object); + + static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition); + + static GstCaps *get_caps(GstBaseSink *sink); + static gboolean set_caps(GstBaseSink *sink, GstCaps *caps); + + static GstFlowReturn buffer_alloc( + GstBaseSink *sink, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer); + + static gboolean start(GstBaseSink *sink); + static gboolean stop(GstBaseSink *sink); + + static gboolean unlock(GstBaseSink *sink); + + static gboolean event(GstBaseSink *sink, GstEvent *event); + static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer); + static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); + +private: + QVideoSurfaceGstDelegate *delegate; +}; + + +class QVideoSurfaceGstSinkClass +{ +public: + GstVideoSinkClass parent_class; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp new file mode 100644 index 0000000..56c1405 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "qx11videosurface.h" + +struct XvFormatRgb +{ + QVideoFrame::PixelFormat pixelFormat; + int bits_per_pixel; + int format; + int num_planes; + + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + +}; + +bool operator ==(const XvImageFormatValues &format, const XvFormatRgb &rgb) +{ + return format.type == XvRGB + && format.bits_per_pixel == rgb.bits_per_pixel + && format.format == rgb.format + && format.num_planes == rgb.num_planes + && format.depth == rgb.depth + && format.red_mask == rgb.red_mask + && format.blue_mask == rgb.blue_mask; +} + +static const XvFormatRgb qt_xvRgbLookup[] = +{ + { QVideoFrame::Format_ARGB32, 32, XvPacked, 1, 32, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_RGB32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_RGB24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_RGB565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F }, + { QVideoFrame::Format_BGRA32, 32, XvPacked, 1, 32, 0xFF000000, 0x00FF0000, 0x0000FF00 }, + { QVideoFrame::Format_BGR32 , 32, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_BGR24 , 24, XvPacked, 1, 24, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { QVideoFrame::Format_BGR565, 16, XvPacked, 1, 16, 0x0000F800, 0x000007E0, 0x0000001F } +}; + +struct XvFormatYuv +{ + QVideoFrame::PixelFormat pixelFormat; + int bits_per_pixel; + int format; + int num_planes; + + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; +}; + +bool operator ==(const XvImageFormatValues &format, const XvFormatYuv &yuv) +{ + return format.type == XvYUV + && format.bits_per_pixel == yuv.bits_per_pixel + && format.format == yuv.format + && format.num_planes == yuv.num_planes + && format.y_sample_bits == yuv.y_sample_bits + && format.u_sample_bits == yuv.u_sample_bits + && format.v_sample_bits == yuv.v_sample_bits + && format.horz_y_period == yuv.horz_y_period + && format.horz_u_period == yuv.horz_u_period + && format.horz_v_period == yuv.horz_v_period + && format.horz_y_period == yuv.vert_y_period + && format.vert_u_period == yuv.vert_u_period + && format.vert_v_period == yuv.vert_v_period + && qstrncmp(format.component_order, yuv.component_order, 32) == 0; +} + +static const XvFormatYuv qt_xvYuvLookup[] = +{ + { QVideoFrame::Format_YUV444 , 24, XvPacked, 1, 8, 8, 8, 1, 1, 1, 1, 1, 1, "YUV" }, + { QVideoFrame::Format_YUV420P, 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" }, + { QVideoFrame::Format_YV12 , 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" }, + { QVideoFrame::Format_UYVY , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY" }, + { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV" }, + { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" }, + { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" }, + { QVideoFrame::Format_Y8 , 8 , XvPlanar, 1, 8, 0, 0, 1, 0, 0, 1, 0, 0, "Y" } +}; + +QX11VideoSurface::QX11VideoSurface(QObject *parent) + : QAbstractVideoSurface(parent) + , m_winId(0) + , m_portId(0) + , m_gc(0) + , m_image(0) +{ +} + +QX11VideoSurface::~QX11VideoSurface() +{ + if (m_gc) + XFreeGC(QX11Info::display(), m_gc); + + if (m_portId != 0) + XvUngrabPort(QX11Info::display(), m_portId, 0); +} + +WId QX11VideoSurface::winId() const +{ + return m_winId; +} + +void QX11VideoSurface::setWinId(WId id) +{ + if (id == m_winId) + return; + + if (m_image) + XFree(m_image); + + if (m_gc) { + XFreeGC(QX11Info::display(), m_gc); + m_gc = 0; + } + + if (m_portId != 0) + XvUngrabPort(QX11Info::display(), m_portId, 0); + + m_supportedPixelFormats.clear(); + m_formatIds.clear(); + + m_winId = id; + + if (m_winId && findPort()) { + querySupportedFormats(); + + m_gc = XCreateGC(QX11Info::display(), m_winId, 0, 0); + + if (m_image) { + m_image = 0; + + if (!start(surfaceFormat())) + QAbstractVideoSurface::stop(); + } + } else if (m_image) { + m_image = 0; + + QAbstractVideoSurface::stop(); + } + + emit supportedFormatsChanged(); +} + +QRect QX11VideoSurface::displayRect() const +{ + return m_displayRect; +} + +void QX11VideoSurface::setDisplayRect(const QRect &rect) +{ + m_displayRect = rect; +} + +int QX11VideoSurface::brightness() const +{ + return getAttribute("XV_BRIGHTNESS", m_brightnessRange.first, m_brightnessRange.second); +} + +void QX11VideoSurface::setBrightness(int brightness) +{ + setAttribute("XV_BRIGHTNESS", brightness, m_brightnessRange.first, m_brightnessRange.second); +} + +int QX11VideoSurface::contrast() const +{ + return getAttribute("XV_CONTRAST", m_contrastRange.first, m_contrastRange.second); +} + +void QX11VideoSurface::setContrast(int contrast) +{ + setAttribute("XV_CONTRAST", contrast, m_contrastRange.first, m_contrastRange.second); +} + +int QX11VideoSurface::hue() const +{ + return getAttribute("XV_HUE", m_hueRange.first, m_hueRange.second); +} + +void QX11VideoSurface::setHue(int hue) +{ + setAttribute("XV_HUE", hue, m_hueRange.first, m_hueRange.second); +} + +int QX11VideoSurface::saturation() const +{ + return getAttribute("XV_SATURATION", m_saturationRange.first, m_saturationRange.second); +} + +void QX11VideoSurface::setSaturation(int saturation) +{ + setAttribute("XV_SATURATION", saturation, m_saturationRange.first, m_saturationRange.second); +} + +int QX11VideoSurface::getAttribute(const char *attribute, int minimum, int maximum) const +{ + if (m_portId != 0) { + Display *display = QX11Info::display(); + + Atom atom = XInternAtom(display, attribute, True); + + int value = 0; + + XvGetPortAttribute(display, m_portId, atom, &value); + + return redistribute(value, minimum, maximum, -100, 100); + } else { + return 0; + } +} + +void QX11VideoSurface::setAttribute(const char *attribute, int value, int minimum, int maximum) +{ + if (m_portId != 0) { + Display *display = QX11Info::display(); + + Atom atom = XInternAtom(display, attribute, True); + + XvSetPortAttribute( + display, m_portId, atom, redistribute(value, -100, 100, minimum, maximum)); + } +} + +int QX11VideoSurface::redistribute( + int value, int fromLower, int fromUpper, int toLower, int toUpper) +{ + return fromUpper != fromLower + ? ((value - fromLower) * (toUpper - toLower) / (fromUpper - fromLower)) + toLower + : 0; +} + +QList QX11VideoSurface::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const +{ + return handleType == QAbstractVideoBuffer::NoHandle + ? m_supportedPixelFormats + : QList(); +} + +bool QX11VideoSurface::start(const QVideoSurfaceFormat &format) +{ + if (m_image) + XFree(m_image); + + int xvFormatId = 0; + for (int i = 0; i < m_supportedPixelFormats.count(); ++i) { + if (m_supportedPixelFormats.at(i) == format.pixelFormat()) { + xvFormatId = m_formatIds.at(i); + break; + } + } + + if (xvFormatId == 0) { + setError(UnsupportedFormatError); + } else { + XvImage *image = XvCreateImage( + QX11Info::display(), + m_portId, + xvFormatId, + 0, + format.frameWidth(), + format.frameHeight()); + + if (!image) { + setError(ResourceError); + } else { + m_viewport = format.viewport(); + m_image = image; + + return QAbstractVideoSurface::start(format); + } + } + + if (m_image) { + m_image = 0; + + QAbstractVideoSurface::stop(); + } + + return false; +} + +void QX11VideoSurface::stop() +{ + if (m_image) { + XFree(m_image); + m_image = 0; + + QAbstractVideoSurface::stop(); + } +} + +bool QX11VideoSurface::present(const QVideoFrame &frame) +{ + if (!m_image) { + setError(StoppedError); + return false; + } else if (m_image->width != frame.width() || m_image->height != frame.height()) { + setError(IncorrectFormatError); + return false; + } else { + QVideoFrame frameCopy(frame); + + if (!frameCopy.map(QAbstractVideoBuffer::ReadOnly)) { + setError(IncorrectFormatError); + return false; + } else { + bool presented = false; + + if (m_image->data_size > frame.mappedBytes()) { + qWarning("Insufficient frame buffer size"); + setError(IncorrectFormatError); + } else if (m_image->num_planes > 0 && m_image->pitches[0] != frame.bytesPerLine()) { + qWarning("Incompatible frame pitches"); + setError(IncorrectFormatError); + } else { + m_image->data = reinterpret_cast(frameCopy.bits()); + + XvPutImage( + QX11Info::display(), + m_portId, + m_winId, + m_gc, + m_image, + m_viewport.x(), + m_viewport.y(), + m_viewport.width(), + m_viewport.height(), + m_displayRect.x(), + m_displayRect.y(), + m_displayRect.width(), + m_displayRect.height()); + + m_image->data = 0; + + presented = true; + } + + frameCopy.unmap(); + + return presented; + } + } +} + +bool QX11VideoSurface::findPort() +{ + unsigned int count = 0; + XvAdaptorInfo *adaptors = 0; + bool portFound = false; + + if (XvQueryAdaptors(QX11Info::display(), m_winId, &count, &adaptors) == Success) { + for (unsigned int i = 0; i < count && !portFound; ++i) { + if (adaptors[i].type & XvImageMask) { + m_portId = adaptors[i].base_id; + + for (unsigned int j = 0; j < adaptors[i].num_ports && !portFound; ++j, ++m_portId) + portFound = XvGrabPort(QX11Info::display(), m_portId, 0) == Success; + } + } + XvFreeAdaptorInfo(adaptors); + } + + return portFound; +} + +void QX11VideoSurface::querySupportedFormats() +{ + int count = 0; + if (XvImageFormatValues *imageFormats = XvListImageFormats( + QX11Info::display(), m_portId, &count)) { + const int rgbCount = sizeof(qt_xvRgbLookup) / sizeof(XvFormatRgb); + const int yuvCount = sizeof(qt_xvYuvLookup) / sizeof(XvFormatYuv); + + for (int i = 0; i < count; ++i) { + switch (imageFormats[i].type) { + case XvRGB: + for (int j = 0; j < rgbCount; ++j) { + if (imageFormats[i] == qt_xvRgbLookup[j]) { + m_supportedPixelFormats.append(qt_xvRgbLookup[j].pixelFormat); + m_formatIds.append(imageFormats[i].id); + break; + } + } + break; + case XvYUV: + for (int j = 0; j < yuvCount; ++j) { + if (imageFormats[i] == qt_xvYuvLookup[j]) { + m_supportedPixelFormats.append(qt_xvYuvLookup[j].pixelFormat); + m_formatIds.append(imageFormats[i].id); + break; + } + } + break; + } + } + XFree(imageFormats); + } + + m_brightnessRange = qMakePair(0, 0); + m_contrastRange = qMakePair(0, 0); + m_hueRange = qMakePair(0, 0); + m_saturationRange = qMakePair(0, 0); + + if (XvAttribute *attributes = XvQueryPortAttributes(QX11Info::display(), m_portId, &count)) { + for (int i = 0; i < count; ++i) { + if (qstrcmp(attributes[i].name, "XV_BRIGHTNESS") == 0) + m_brightnessRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + else if (qstrcmp(attributes[i].name, "XV_CONTRAST") == 0) + m_contrastRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + else if (qstrcmp(attributes[i].name, "XV_HUE") == 0) + m_hueRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + else if (qstrcmp(attributes[i].name, "XV_SATURATION") == 0) + m_saturationRange = qMakePair(attributes[i].min_value, attributes[i].max_value); + } + + XFree(attributes); + } +} diff --git a/src/plugins/mediaservices/gstreamer/qx11videosurface.h b/src/plugins/mediaservices/gstreamer/qx11videosurface.h new file mode 100644 index 0000000..e69517a --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qx11videosurface.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QX11VIDEOSURFACE_H +#define QX11VIDEOSURFACE_H + +#include +#include + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QX11VideoSurface : public QAbstractVideoSurface +{ + Q_OBJECT +public: + QX11VideoSurface(QObject *parent = 0); + ~QX11VideoSurface(); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + + bool start(const QVideoSurfaceFormat &format); + void stop(); + + bool present(const QVideoFrame &frame); + +private: + WId m_winId; + XvPortID m_portId; + GC m_gc; + XvImage *m_image; + QList m_supportedPixelFormats; + QVector m_formatIds; + QRect m_viewport; + QRect m_displayRect; + QPair m_brightnessRange; + QPair m_contrastRange; + QPair m_hueRange; + QPair m_saturationRange; + + bool findPort(); + void querySupportedFormats(); + + int getAttribute(const char *attribute, int minimum, int maximum) const; + void setAttribute(const char *attribute, int value, int minimum, int maximum); + + static int redistribute(int value, int fromLower, int fromUpper, int toLower, int toUpper); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/mediaservices.pro b/src/plugins/mediaservices/mediaservices.pro index 03859bd..879d914 100644 --- a/src/plugins/mediaservices/mediaservices.pro +++ b/src/plugins/mediaservices/mediaservices.pro @@ -2,4 +2,15 @@ TEMPLATE = subdirs mac:SUBDIRS += qt7 +unix:!mac:!symbian { + TMP_GST_LIBS = \ + gstreamer-0.10 >= 0.10.19 \ + gstreamer-base-0.10 >= 0.10.19 \ + gstreamer-interfaces-0.10 >= 0.10.19 \ + gstreamer-audio-0.10 >= 0.10.19 \ + gstreamer-video-0.10 >= 0.10.19 + system(pkg-config --exists \'$${TMP_GST_LIBS}\' --print-errors): { + SUBDIRS += gstreamer + } +} -- cgit v0.12 From 65bca1935008012d096872647dc02c124abcab75 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Tue, 19 Jan 2010 13:54:25 +1000 Subject: Multimedia; reorganize qt7 mediaservice provider. --- .../mediaservices/qt7/mediaplayer/mediaplayer.pri | 18 + .../qt7/mediaplayer/qt7playercontrol.h | 128 +++++++ .../qt7/mediaplayer/qt7playercontrol.mm | 188 ++++++++++ .../qt7/mediaplayer/qt7playermetadata.h | 84 +++++ .../qt7/mediaplayer/qt7playermetadata.mm | 261 +++++++++++++ .../qt7/mediaplayer/qt7playerservice.h | 90 +++++ .../qt7/mediaplayer/qt7playerservice.mm | 151 ++++++++ .../qt7/mediaplayer/qt7playersession.h | 140 +++++++ .../qt7/mediaplayer/qt7playersession.mm | 402 +++++++++++++++++++++ src/plugins/mediaservices/qt7/qt7.pro | 9 +- src/plugins/mediaservices/qt7/qt7playercontrol.h | 128 ------- src/plugins/mediaservices/qt7/qt7playercontrol.mm | 188 ---------- src/plugins/mediaservices/qt7/qt7playermetadata.h | 84 ----- src/plugins/mediaservices/qt7/qt7playermetadata.mm | 261 ------------- src/plugins/mediaservices/qt7/qt7playerservice.h | 90 ----- src/plugins/mediaservices/qt7/qt7playerservice.mm | 151 -------- src/plugins/mediaservices/qt7/qt7playersession.h | 140 ------- src/plugins/mediaservices/qt7/qt7playersession.mm | 402 --------------------- src/plugins/mediaservices/qt7/qt7serviceplugin.mm | 10 +- 19 files changed, 1470 insertions(+), 1455 deletions(-) create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.h create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.mm create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h create mode 100644 src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm delete mode 100644 src/plugins/mediaservices/qt7/qt7playercontrol.h delete mode 100644 src/plugins/mediaservices/qt7/qt7playercontrol.mm delete mode 100644 src/plugins/mediaservices/qt7/qt7playermetadata.h delete mode 100644 src/plugins/mediaservices/qt7/qt7playermetadata.mm delete mode 100644 src/plugins/mediaservices/qt7/qt7playerservice.h delete mode 100644 src/plugins/mediaservices/qt7/qt7playerservice.mm delete mode 100644 src/plugins/mediaservices/qt7/qt7playersession.h delete mode 100644 src/plugins/mediaservices/qt7/qt7playersession.mm diff --git a/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri new file mode 100644 index 0000000..f00d418 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri @@ -0,0 +1,18 @@ +INCLUDEPATH += $$PWD + +DEFINES += Q_MEDIASERVICE_MEDIAPLAYER_AVAILABLE + +HEADERS += \ + $$PWD/qt7playercontrol.h \ + $$PWD/qt7playermetadata.h \ + $$PWD/qt7playerservice.h \ + $$PWD/qt7playersession.h + +OBJECTIVE_SOURCES += \ + $$PWD/qt7playercontrol.mm \ + $$PWD/qt7playermetadata.mm \ + $$PWD/qt7playerservice.mm \ + $$PWD/qt7playersession.mm + + + diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h new file mode 100644 index 0000000..da86949 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERCONTROL_H +#define QT7PLAYERCONTROL_H + +#include +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7PlayerSession; +class QT7PlayerService; +class QMediaPlaylist; +class QMediaPlaylistNavigator; + +class QT7PlayerControl : public QMediaPlayerControl +{ +Q_OBJECT +public: + QT7PlayerControl(QObject *parent = 0); + ~QT7PlayerControl(); + + void setSession(QT7PlayerSession *session); + + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent &content, QIODevice *stream); + + qint64 position() const; + qint64 duration() const; + + int bufferStatus() const; + + int volume() const; + bool isMuted() const; + + bool isVideoAvailable() const; + + bool isSeekable() const; + + QMediaTimeRange availablePlaybackRanges() const; + + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + +public Q_SLOTS: + void setPosition(qint64 pos); + + void play(); + void pause(); + void stop(); + + void setVolume(int volume); + void setMuted(bool muted); + +Q_SIGNALS: + void mediaChanged(const QMediaContent& content); + void durationChanged(qint64 duration); + void positionChanged(qint64 position); + void stateChanged(QMediaPlayer::State newState); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + void bufferStatusChanged(int percentFilled); + void seekableChanged(bool); + void seekRangeChanged(const QPair&); + void playbackRateChanged(qreal rate); + void error(int error, const QString &errorString); + +private: + QT7PlayerSession *m_session; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm new file mode 100644 index 0000000..b74f434 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt7playercontrol.h" +#include "qt7playersession.h" + +#include + +#include +#include + + +QT_BEGIN_NAMESPACE + +QT7PlayerControl::QT7PlayerControl(QObject *parent) + : QMediaPlayerControl(parent) +{ +} + +QT7PlayerControl::~QT7PlayerControl() +{ +} + +void QT7PlayerControl::setSession(QT7PlayerSession *session) +{ + m_session = session; + + connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64))); + connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); + connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)), + this, SIGNAL(stateChanged(QMediaPlayer::State))); + connect(m_session, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int))); + connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); + connect(m_session, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(videoAvailableChanged(bool))); + connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); +} + +qint64 QT7PlayerControl::position() const +{ + return m_session->position(); +} + +qint64 QT7PlayerControl::duration() const +{ + return m_session->duration(); +} + +QMediaPlayer::State QT7PlayerControl::state() const +{ + return m_session->state(); +} + +QMediaPlayer::MediaStatus QT7PlayerControl::mediaStatus() const +{ + return m_session->mediaStatus(); +} + +int QT7PlayerControl::bufferStatus() const +{ + return m_session->bufferStatus(); +} + +int QT7PlayerControl::volume() const +{ + return m_session->volume(); +} + +bool QT7PlayerControl::isMuted() const +{ + return m_session->isMuted(); +} + +bool QT7PlayerControl::isSeekable() const +{ + return m_session->isSeekable(); +} + +QMediaTimeRange QT7PlayerControl::availablePlaybackRanges() const +{ + return isSeekable() ? QMediaTimeRange(0, duration()) : QMediaTimeRange(); +} + +qreal QT7PlayerControl::playbackRate() const +{ + return m_session->playbackRate(); +} + +void QT7PlayerControl::setPlaybackRate(qreal rate) +{ + m_session->setPlaybackRate(rate); +} + +void QT7PlayerControl::setPosition(qint64 pos) +{ + m_session->setPosition(pos); +} + +void QT7PlayerControl::play() +{ + m_session->play(); +} + +void QT7PlayerControl::pause() +{ + m_session->pause(); +} + +void QT7PlayerControl::stop() +{ + m_session->stop(); +} + +void QT7PlayerControl::setVolume(int volume) +{ + m_session->setVolume(volume); +} + +void QT7PlayerControl::setMuted(bool muted) +{ + m_session->setMuted(muted); +} + +QMediaContent QT7PlayerControl::media() const +{ + return m_session->media(); +} + +const QIODevice *QT7PlayerControl::mediaStream() const +{ + return m_session->mediaStream(); +} + +void QT7PlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) +{ + m_session->setMedia(content, stream); + + emit mediaChanged(content); +} + + +bool QT7PlayerControl::isVideoAvailable() const +{ + return m_session->isVideoAvailable(); +} + +#include "moc_qt7playercontrol.cpp" + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h new file mode 100644 index 0000000..9aa9887 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERMETADATACONTROL_H +#define QT7PLAYERMETADATACONTROL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7PlayerSession; + +class QT7PlayerMetaDataControl : public QMetaDataControl +{ + Q_OBJECT +public: + QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent); + virtual ~QT7PlayerMetaDataControl(); + + bool isMetaDataAvailable() const; + bool isWritable() const; + + QVariant metaData(QtMedia::MetaData key) const; + void setMetaData(QtMedia::MetaData key, const QVariant &value); + QList availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const ; + void setExtendedMetaData(const QString &key, const QVariant &value); + QStringList availableExtendedMetaData() const; + +private slots: + void updateTags(); + +private: + QT7PlayerSession *m_session; + QMap m_tags; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm new file mode 100644 index 0000000..96b7a68 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm @@ -0,0 +1,261 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qt7backend.h" +#include "qt7playermetadata.h" +#include "qt7playersession.h" +#include + +#import + +#ifdef QUICKTIME_C_API_AVAILABLE + #include + #undef check // avoid name clash; +#endif + +QT_BEGIN_NAMESPACE + +QT7PlayerMetaDataControl::QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent) + :QMetaDataControl(parent), m_session(session) +{ +} + +QT7PlayerMetaDataControl::~QT7PlayerMetaDataControl() +{ +} + +bool QT7PlayerMetaDataControl::isMetaDataAvailable() const +{ + return !m_tags.isEmpty(); +} + +bool QT7PlayerMetaDataControl::isWritable() const +{ + return false; +} + +QVariant QT7PlayerMetaDataControl::metaData(QtMedia::MetaData key) const +{ + return m_tags.value(key); +} + +void QT7PlayerMetaDataControl::setMetaData(QtMedia::MetaData key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QList QT7PlayerMetaDataControl::availableMetaData() const +{ + return m_tags.keys(); +} + +QVariant QT7PlayerMetaDataControl::extendedMetaData(const QString &key) const +{ + Q_UNUSED(key); + return QVariant(); +} + +void QT7PlayerMetaDataControl::setExtendedMetaData(const QString &key, QVariant const &value) +{ + Q_UNUSED(key); + Q_UNUSED(value); +} + +QStringList QT7PlayerMetaDataControl::availableExtendedMetaData() const +{ + return QStringList(); +} + +#ifdef QUICKTIME_C_API_AVAILABLE + +static QString stripCopyRightSymbol(const QString &key) +{ + return key.right(key.length()-1); +} + +static QString convertQuickTimeKeyToUserKey(const QString &key) +{ + if (key == QLatin1String("com.apple.quicktime.displayname")) + return QLatin1String("nam"); + else if (key == QLatin1String("com.apple.quicktime.album")) + return QLatin1String("alb"); + else if (key == QLatin1String("com.apple.quicktime.artist")) + return QLatin1String("ART"); + else + return QLatin1String("???"); +} + +static OSStatus readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass, + QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size) +{ + QTPropertyValueType type; + ByteCount propSize; + UInt32 propFlags; + OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags); + + + *value = malloc(propSize); + + err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size); + + if (type == 'code' || type == 'itsk' || type == 'itlk') { + // convert from native endian to big endian + OSTypePtr pType = (OSTypePtr)*value; + *pType = EndianU32_NtoB(*pType); + } + + return err; +} + +static UInt32 getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item) +{ + QTPropertyValuePtr value = 0; + ByteCount ignore = 0; + OSStatus err = readMetaValue( + metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore); + + UInt32 type = *((UInt32 *) value); + if (value) + free(value); + return type; +} + +static QString cFStringToQString(CFStringRef str) +{ + if(!str) + return QString(); + CFIndex length = CFStringGetLength(str); + const UniChar *chars = CFStringGetCharactersPtr(str); + if (chars) + return QString(reinterpret_cast(chars), length); + + QVarLengthArray buffer(length); + CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); + return QString(reinterpret_cast(buffer.constData()), length); +} + + +static QString getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id) +{ + QTPropertyValuePtr value = 0; + ByteCount size = 0; + OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size); + + QString string; + UInt32 dataType = getMetaType(metaDataRef, item); + switch (dataType){ + case kQTMetaDataTypeUTF8: + case kQTMetaDataTypeMacEncodedText: + string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false)); + break; + case kQTMetaDataTypeUTF16BE: + string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false)); + break; + default: + break; + } + + if (value) + free(value); + return string; +} + + +static void readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap &result) +{ + QTMetaDataItem item = kQTMetaDataItemUninitialized; + OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item); + while (err == noErr){ + QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key); + if (format == kQTMetaDataStorageFormatQuickTime) + key = convertQuickTimeKeyToUserKey(key); + else + key = stripCopyRightSymbol(key); + + if (!result.contains(key)){ + QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value); + result.insert(key, val); + } + err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item); + } +} +#endif + + +void QT7PlayerMetaDataControl::updateTags() +{ + bool wasEmpty = m_tags.isEmpty(); + m_tags.clear(); + + QTMovie *movie = (QTMovie*)m_session->movie(); + + if (movie) { + QMultiMap metaMap; + +#ifdef QUICKTIME_C_API_AVAILABLE + QTMetaDataRef metaDataRef; + OSStatus err = QTCopyMovieMetaData([movie quickTimeMovie], &metaDataRef); + + readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap); + readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap); + readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap); +#else + NSString *name = [movie attributeForKey:@"QTMovieDisplayNameAttribute"]; + metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String])); +#endif // QUICKTIME_C_API_AVAILABLE + + m_tags.insert(QtMedia::AlbumArtist, metaMap.value(QLatin1String("ART"))); + m_tags.insert(QtMedia::AlbumTitle, metaMap.value(QLatin1String("alb"))); + m_tags.insert(QtMedia::Title, metaMap.value(QLatin1String("nam"))); + m_tags.insert(QtMedia::Date, metaMap.value(QLatin1String("day"))); + m_tags.insert(QtMedia::Genre, metaMap.value(QLatin1String("gnre"))); + m_tags.insert(QtMedia::TrackNumber, metaMap.value(QLatin1String("trk"))); + m_tags.insert(QtMedia::Description, metaMap.value(QLatin1String("des"))); + } + + if (!wasEmpty || !m_tags.isEmpty()) + emit metaDataChanged(); +} + +QT_END_NAMESPACE + +#include "moc_qt7playermetadata.cpp" diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.h new file mode 100644 index 0000000..d4b30b8 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERSERVICE_H +#define QT7PLAYERSERVICE_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaMetaData; +class QMediaPlayerControl; +class QMediaPlaylist; +class QMediaPlaylistNavigator; +class QT7PlayerControl; +class QT7PlayerMetaDataControl; +class QT7VideoOutputControl; +class QT7VideoWindowControl; +class QT7VideoWidgetControl; +class QT7VideoRendererControl; +class QT7VideoOutput; +class QT7PlayerSession; + +class QT7PlayerService : public QMediaService +{ +Q_OBJECT +public: + QT7PlayerService(QObject *parent = 0); + ~QT7PlayerService(); + + QMediaControl *control(const char *name) const; + +private slots: + void updateVideoOutput(); + +private: + QT7PlayerSession *m_session; + QT7PlayerControl *m_control; + QT7VideoOutputControl *m_videoOutputControl; + QT7VideoWindowControl *m_videoWidnowControl; + QT7VideoWidgetControl *m_videoWidgetControl; + QT7VideoRendererControl *m_videoRendererControl; + QT7PlayerMetaDataControl *m_playerMetaDataControl; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.mm new file mode 100644 index 0000000..df15fa8 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playerservice.mm @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "qt7backend.h" +#include "qt7playerservice.h" +#include "qt7playercontrol.h" +#include "qt7playersession.h" +#include "qt7videooutputcontrol.h" +#include "qt7movieviewoutput.h" +#include "qt7movieviewrenderer.h" +#include "qt7movierenderer.h" +#include "qt7movievideowidget.h" +#include "qt7playermetadata.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QT7PlayerService::QT7PlayerService(QObject *parent): + QMediaService(parent) +{ + m_session = new QT7PlayerSession; + + m_control = new QT7PlayerControl(this); + m_control->setSession(m_session); + + m_playerMetaDataControl = new QT7PlayerMetaDataControl(m_session, this); + connect(m_control, SIGNAL(mediaChanged(QMediaContent)), m_playerMetaDataControl, SLOT(updateTags())); + + m_videoOutputControl = new QT7VideoOutputControl(this); + + m_videoWidnowControl = 0; + m_videoWidgetControl = 0; + m_videoRendererControl = 0; + +#if defined(QT_MAC_USE_COCOA) + m_videoWidnowControl = new QT7MovieViewOutput(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::WindowOutput); + qDebug() << "Using cocoa"; +#endif + +#ifdef QUICKTIME_C_API_AVAILABLE + m_videoRendererControl = new QT7MovieRenderer(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::RendererOutput); + + m_videoWidgetControl = new QT7MovieVideoWidget(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::WidgetOutput); + qDebug() << "QuickTime C API is available"; +#else + m_videoRendererControl = new QT7MovieViewRenderer(this); + m_videoOutputControl->enableOutput(QVideoOutputControl::RendererOutput); + qDebug() << "QuickTime C API is not available"; +#endif + + + connect(m_videoOutputControl, SIGNAL(videoOutputChanged(QVideoOutputControl::Output)), + this, SLOT(updateVideoOutput())); +} + +QT7PlayerService::~QT7PlayerService() +{ +} + +QMediaControl *QT7PlayerService::control(const char *name) const +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return m_control; + + if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return m_videoOutputControl; + + if (qstrcmp(name, QVideoWindowControl_iid) == 0) + return m_videoWidnowControl; + + if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return m_videoRendererControl; + + if (qstrcmp(name, QVideoWidgetControl_iid) == 0) + return m_videoWidgetControl; + + if (qstrcmp(name, QMetaDataControl_iid) == 0) + return m_playerMetaDataControl; + + return 0; +} + +void QT7PlayerService::updateVideoOutput() +{ + qDebug() << "QT7PlayerService::updateVideoOutput" << m_videoOutputControl->output(); + + switch (m_videoOutputControl->output()) { + case QVideoOutputControl::WindowOutput: + m_session->setVideoOutput(m_videoWidnowControl); + break; + case QVideoOutputControl::RendererOutput: + m_session->setVideoOutput(m_videoRendererControl); + break; + case QVideoOutputControl::WidgetOutput: + m_session->setVideoOutput(m_videoWidgetControl); + break; + default: + m_session->setVideoOutput(0); + } +} + +QT_END_NAMESPACE + +#include "moc_qt7playerservice.cpp" diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h new file mode 100644 index 0000000..55505ee --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT7PLAYERSESSION_H +#define QT7PLAYERSESSION_H + +#include +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QT7PlayerControl; +class QMediaPlaylist; +class QMediaPlaylistNavigator; +class QT7VideoOutput; +class QT7PlayerSession; +class QT7PlayerService; + +class QT7PlayerSession : public QObject +{ +Q_OBJECT +public: + QT7PlayerSession(QObject *parent = 0); + ~QT7PlayerSession(); + + void *movie() const; + + void setControl(QT7PlayerControl *control); + void setVideoOutput(QT7VideoOutput *output); + + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent &content, QIODevice *stream); + + qint64 position() const; + qint64 duration() const; + + int bufferStatus() const; + + int volume() const; + bool isMuted() const; + + bool isVideoAvailable() const; + + bool isSeekable() const; + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + void setPosition(qint64 pos); + + void play(); + void pause(); + void stop(); + + void setVolume(int volume); + void setMuted(bool muted); + + void processEOS(); + +signals: + void positionChanged(qint64 position); + void durationChanged(qint64 duration); + void stateChanged(QMediaPlayer::State newState); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void videoAvailableChanged(bool videoAvailable); + void error(int error, const QString &errorString); + +private: + void *m_QTMovie; + void *m_movieObserver; + + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_mediaStatus; + QIODevice *m_mediaStream; + QMediaContent m_resources; + + QT7VideoOutput *m_videoOutput; + + mutable qint64 m_currentTime; + + bool m_muted; + int m_volume; + qreal m_rate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm new file mode 100644 index 0000000..3131a90 --- /dev/null +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import +#import + +#include "qt7backend.h" + +#include "qt7playersession.h" +#include "qt7playercontrol.h" +#include "qt7videooutputcontrol.h" + +#include + +#include + +#include +#include + + +QT_BEGIN_NAMESPACE + +@interface QTMovieObserver : NSObject +{ +@private + QT7PlayerSession *m_session; + QTMovie *m_movie; +} + +- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session; +- (void) setMovie:(QTMovie *)movie; +- (void) processEOS:(NSNotification *)notification; +@end + +@implementation QTMovieObserver + +- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session +{ + if (!(self = [super init])) + return nil; + + self->m_session = session; + return self; +} + +- (void) setMovie:(QTMovie *)movie +{ + if (m_movie == movie) + return; + + if (m_movie) { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [m_movie release]; + } + + m_movie = movie; + + if (movie) { + [[NSNotificationCenter defaultCenter] addObserver: self selector: + @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie]; + + [movie retain]; + } +} + +- (void) processEOS:(NSNotification *)notification +{ + Q_UNUSED(notification); + m_session->processEOS(); +} + +@end + +static CFStringRef qString2CFStringRef(const QString &string) +{ + return CFStringCreateWithCharacters(0, reinterpret_cast(string.unicode()), + string.length()); +} + +QT7PlayerSession::QT7PlayerSession(QObject *parent) + : QObject(parent) + , m_QTMovie(0) + , m_state(QMediaPlayer::StoppedState) + , m_mediaStatus(QMediaPlayer::NoMedia) + , m_mediaStream(0) + , m_videoOutput(0) + , m_muted(false) + , m_volume(100) + , m_rate(1.0) +{ + m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this]; +} + +QT7PlayerSession::~QT7PlayerSession() +{ + [(QTMovieObserver*)m_movieObserver setMovie:nil]; + [(QTMovieObserver*)m_movieObserver release]; +} + +void *QT7PlayerSession::movie() const +{ + return m_QTMovie; +} + +void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output) +{ + if (m_videoOutput == output) + return; + + qDebug() << "set output" << output; + + if (m_videoOutput) { + m_videoOutput->setEnabled(false); + m_videoOutput->setMovie(0); + } + + m_videoOutput = output; + + if (m_videoOutput) { + m_videoOutput->setEnabled(m_QTMovie != 0); + m_videoOutput->setMovie(m_QTMovie); + } +} + + +qint64 QT7PlayerSession::position() const +{ + if (!m_QTMovie || m_state == QMediaPlayer::PausedState) + return m_currentTime; + + AutoReleasePool pool; + + QTTime qtTime = [(QTMovie*)m_QTMovie currentTime]; + quint64 t = static_cast(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); + m_currentTime = t; + + return m_currentTime; +} + +qint64 QT7PlayerSession::duration() const +{ + if (!m_QTMovie) + return 0; + + AutoReleasePool pool; + + QTTime qtTime = [(QTMovie*)m_QTMovie duration]; + + return static_cast(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); +} + +QMediaPlayer::State QT7PlayerSession::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus QT7PlayerSession::mediaStatus() const +{ + return m_mediaStatus; +} + +int QT7PlayerSession::bufferStatus() const +{ + return 100; +} + +int QT7PlayerSession::volume() const +{ + return m_volume; +} + +bool QT7PlayerSession::isMuted() const +{ + return m_muted; +} + +bool QT7PlayerSession::isSeekable() const +{ + return true; +} + +qreal QT7PlayerSession::playbackRate() const +{ + return m_rate; +} + +void QT7PlayerSession::setPlaybackRate(qreal rate) +{ + if (qFuzzyCompare(m_rate, rate)) + return; + + m_rate = rate; + + if (m_QTMovie && m_state == QMediaPlayer::PlayingState) { + float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; + [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; + } +} + +void QT7PlayerSession::setPosition(qint64 pos) +{ + if ( !isSeekable() || pos == position()) + return; + + AutoReleasePool pool; + + pos = qMin(pos, duration()); + + QTTime newQTTime = [(QTMovie*)m_QTMovie currentTime]; + newQTTime.timeValue = (pos / 1000.0f) * newQTTime.timeScale; + [(QTMovie*)m_QTMovie setCurrentTime:newQTTime]; +} + +void QT7PlayerSession::play() +{ + m_state = QMediaPlayer::PlayingState; + + float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; + [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; + + emit stateChanged(m_state); +} + +void QT7PlayerSession::pause() +{ + m_state = QMediaPlayer::PausedState; + + [(QTMovie*)m_QTMovie setRate:0]; + + emit stateChanged(m_state); +} + +void QT7PlayerSession::stop() +{ + m_state = QMediaPlayer::StoppedState; + + [(QTMovie*)m_QTMovie setRate:0]; + setPosition(0); + + if (m_state == QMediaPlayer::StoppedState) + emit stateChanged(m_state); +} + +void QT7PlayerSession::setVolume(int volume) +{ + if (m_QTMovie) { + m_volume = volume; + [(QTMovie*)m_QTMovie setVolume:(volume/100.0f)]; + } +} + +void QT7PlayerSession::setMuted(bool muted) +{ + if (m_muted != muted) { + m_muted = muted; + + if (m_QTMovie) + [(QTMovie*)m_QTMovie setMuted:m_muted]; + + emit mutedChanged(muted); + } +} + +QMediaContent QT7PlayerSession::media() const +{ + return m_resources; +} + +const QIODevice *QT7PlayerSession::mediaStream() const +{ + return m_mediaStream; +} + +void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) +{ + AutoReleasePool pool; + + if (m_QTMovie) { + [(QTMovieObserver*)m_movieObserver setMovie:nil]; + + if (m_videoOutput) { + m_videoOutput->setEnabled(false); + m_videoOutput->setMovie(0); + } + + [(QTMovie*)m_QTMovie release]; + m_QTMovie = 0; + } + + m_resources = content; + m_mediaStream = stream; + + QUrl url; + + if (!content.isNull()) + url = content.canonicalUrl(); + else + return; + + NSError *err = 0; + QTDataReference *dataRef = 0; + + if ( url.scheme() == "file" ) { + NSString *nsFileName = (NSString *)qString2CFStringRef( url.toLocalFile() ); + dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFileName]; + } else { + NSString *urlString = (NSString *)qString2CFStringRef( url.toString() ); + NSURL *url = [NSURL URLWithString: urlString]; + dataRef = [QTDataReference dataReferenceWithReferenceToURL:url]; + } + + NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys: + dataRef, QTMovieDataReferenceAttribute, + [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute, + [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute, + [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute, + [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute, + nil]; + + m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain]; + + if (err) { + [(QTMovie*)m_QTMovie release]; + m_QTMovie = 0; + QString description = QString::fromUtf8([[err localizedDescription] UTF8String]); + + qDebug() << "QT7PlayerSession::setMedia error" << description; + emit error(QMediaPlayer::FormatError, description ); + } else { + [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie]; + + if (m_videoOutput) { + m_videoOutput->setEnabled(true); + m_videoOutput->setMovie(m_QTMovie); + } + + emit durationChanged(duration()); + emit videoAvailableChanged(isVideoAvailable()); + + [(QTMovie*)m_QTMovie setMuted:m_muted]; + setVolume(m_volume); + } +} + +bool QT7PlayerSession::isVideoAvailable() const +{ + if (!m_QTMovie) + return false; + + AutoReleasePool pool; + return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES; +} + +void QT7PlayerSession::processEOS() +{ + m_mediaStatus = QMediaPlayer::EndOfMedia; + emit stateChanged(m_state = QMediaPlayer::StoppedState); + emit mediaStatusChanged(m_mediaStatus); +} + +#include "moc_qt7playersession.cpp" + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/qt7/qt7.pro b/src/plugins/mediaservices/qt7/qt7.pro index 938bc97..13d14d7 100644 --- a/src/plugins/mediaservices/qt7/qt7.pro +++ b/src/plugins/mediaservices/qt7/qt7.pro @@ -19,32 +19,25 @@ contains(QMAKE_MAC_XARCH, no) { HEADERS += \ qt7backend.h \ - qt7playercontrol.h \ qt7videooutputcontrol.h \ qt7movieviewoutput.h \ qt7movievideowidget.h \ qt7movieviewrenderer.h \ - qt7playersession.h \ - qt7playerservice.h \ qt7serviceplugin.h \ qt7movierenderer.h \ - qt7playermetadata.h \ qcvdisplaylink.h OBJECTIVE_SOURCES += \ qt7backend.mm \ - qt7playersession.mm \ qt7serviceplugin.mm \ qt7movieviewoutput.mm \ qt7movievideowidget.mm \ qt7movieviewrenderer.mm \ - qt7playermetadata.mm \ qt7movierenderer.mm \ - qt7playercontrol.mm \ qt7videooutputcontrol.mm \ - qt7playerservice.mm \ qcvdisplaylink.mm +include(mediaplayer/mediaplayer.pri) QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/mediaservices target.path = $$[QT_INSTALL_PLUGINS]/plugins/mediaservices diff --git a/src/plugins/mediaservices/qt7/qt7playercontrol.h b/src/plugins/mediaservices/qt7/qt7playercontrol.h deleted file mode 100644 index da86949..0000000 --- a/src/plugins/mediaservices/qt7/qt7playercontrol.h +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT7PLAYERCONTROL_H -#define QT7PLAYERCONTROL_H - -#include -#include - -#include -#include - - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QT7PlayerSession; -class QT7PlayerService; -class QMediaPlaylist; -class QMediaPlaylistNavigator; - -class QT7PlayerControl : public QMediaPlayerControl -{ -Q_OBJECT -public: - QT7PlayerControl(QObject *parent = 0); - ~QT7PlayerControl(); - - void setSession(QT7PlayerSession *session); - - QMediaPlayer::State state() const; - QMediaPlayer::MediaStatus mediaStatus() const; - - QMediaContent media() const; - const QIODevice *mediaStream() const; - void setMedia(const QMediaContent &content, QIODevice *stream); - - qint64 position() const; - qint64 duration() const; - - int bufferStatus() const; - - int volume() const; - bool isMuted() const; - - bool isVideoAvailable() const; - - bool isSeekable() const; - - QMediaTimeRange availablePlaybackRanges() const; - - - qreal playbackRate() const; - void setPlaybackRate(qreal rate); - -public Q_SLOTS: - void setPosition(qint64 pos); - - void play(); - void pause(); - void stop(); - - void setVolume(int volume); - void setMuted(bool muted); - -Q_SIGNALS: - void mediaChanged(const QMediaContent& content); - void durationChanged(qint64 duration); - void positionChanged(qint64 position); - void stateChanged(QMediaPlayer::State newState); - void mediaStatusChanged(QMediaPlayer::MediaStatus status); - void volumeChanged(int volume); - void mutedChanged(bool muted); - void videoAvailableChanged(bool videoAvailable); - void bufferStatusChanged(int percentFilled); - void seekableChanged(bool); - void seekRangeChanged(const QPair&); - void playbackRateChanged(qreal rate); - void error(int error, const QString &errorString); - -private: - QT7PlayerSession *m_session; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/plugins/mediaservices/qt7/qt7playercontrol.mm b/src/plugins/mediaservices/qt7/qt7playercontrol.mm deleted file mode 100644 index b74f434..0000000 --- a/src/plugins/mediaservices/qt7/qt7playercontrol.mm +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qt7playercontrol.h" -#include "qt7playersession.h" - -#include - -#include -#include - - -QT_BEGIN_NAMESPACE - -QT7PlayerControl::QT7PlayerControl(QObject *parent) - : QMediaPlayerControl(parent) -{ -} - -QT7PlayerControl::~QT7PlayerControl() -{ -} - -void QT7PlayerControl::setSession(QT7PlayerSession *session) -{ - m_session = session; - - connect(m_session, SIGNAL(positionChanged(qint64)), this, SIGNAL(positionChanged(qint64))); - connect(m_session, SIGNAL(durationChanged(qint64)), this, SIGNAL(durationChanged(qint64))); - connect(m_session, SIGNAL(stateChanged(QMediaPlayer::State)), - this, SIGNAL(stateChanged(QMediaPlayer::State))); - connect(m_session, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), - this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); - connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int))); - connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); - connect(m_session, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(videoAvailableChanged(bool))); - connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); -} - -qint64 QT7PlayerControl::position() const -{ - return m_session->position(); -} - -qint64 QT7PlayerControl::duration() const -{ - return m_session->duration(); -} - -QMediaPlayer::State QT7PlayerControl::state() const -{ - return m_session->state(); -} - -QMediaPlayer::MediaStatus QT7PlayerControl::mediaStatus() const -{ - return m_session->mediaStatus(); -} - -int QT7PlayerControl::bufferStatus() const -{ - return m_session->bufferStatus(); -} - -int QT7PlayerControl::volume() const -{ - return m_session->volume(); -} - -bool QT7PlayerControl::isMuted() const -{ - return m_session->isMuted(); -} - -bool QT7PlayerControl::isSeekable() const -{ - return m_session->isSeekable(); -} - -QMediaTimeRange QT7PlayerControl::availablePlaybackRanges() const -{ - return isSeekable() ? QMediaTimeRange(0, duration()) : QMediaTimeRange(); -} - -qreal QT7PlayerControl::playbackRate() const -{ - return m_session->playbackRate(); -} - -void QT7PlayerControl::setPlaybackRate(qreal rate) -{ - m_session->setPlaybackRate(rate); -} - -void QT7PlayerControl::setPosition(qint64 pos) -{ - m_session->setPosition(pos); -} - -void QT7PlayerControl::play() -{ - m_session->play(); -} - -void QT7PlayerControl::pause() -{ - m_session->pause(); -} - -void QT7PlayerControl::stop() -{ - m_session->stop(); -} - -void QT7PlayerControl::setVolume(int volume) -{ - m_session->setVolume(volume); -} - -void QT7PlayerControl::setMuted(bool muted) -{ - m_session->setMuted(muted); -} - -QMediaContent QT7PlayerControl::media() const -{ - return m_session->media(); -} - -const QIODevice *QT7PlayerControl::mediaStream() const -{ - return m_session->mediaStream(); -} - -void QT7PlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) -{ - m_session->setMedia(content, stream); - - emit mediaChanged(content); -} - - -bool QT7PlayerControl::isVideoAvailable() const -{ - return m_session->isVideoAvailable(); -} - -#include "moc_qt7playercontrol.cpp" - -QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7playermetadata.h b/src/plugins/mediaservices/qt7/qt7playermetadata.h deleted file mode 100644 index 9aa9887..0000000 --- a/src/plugins/mediaservices/qt7/qt7playermetadata.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT7PLAYERMETADATACONTROL_H -#define QT7PLAYERMETADATACONTROL_H - -#include - - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QT7PlayerSession; - -class QT7PlayerMetaDataControl : public QMetaDataControl -{ - Q_OBJECT -public: - QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent); - virtual ~QT7PlayerMetaDataControl(); - - bool isMetaDataAvailable() const; - bool isWritable() const; - - QVariant metaData(QtMedia::MetaData key) const; - void setMetaData(QtMedia::MetaData key, const QVariant &value); - QList availableMetaData() const; - - QVariant extendedMetaData(const QString &key) const ; - void setExtendedMetaData(const QString &key, const QVariant &value); - QStringList availableExtendedMetaData() const; - -private slots: - void updateTags(); - -private: - QT7PlayerSession *m_session; - QMap m_tags; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/plugins/mediaservices/qt7/qt7playermetadata.mm b/src/plugins/mediaservices/qt7/qt7playermetadata.mm deleted file mode 100644 index 96b7a68..0000000 --- a/src/plugins/mediaservices/qt7/qt7playermetadata.mm +++ /dev/null @@ -1,261 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qt7backend.h" -#include "qt7playermetadata.h" -#include "qt7playersession.h" -#include - -#import - -#ifdef QUICKTIME_C_API_AVAILABLE - #include - #undef check // avoid name clash; -#endif - -QT_BEGIN_NAMESPACE - -QT7PlayerMetaDataControl::QT7PlayerMetaDataControl(QT7PlayerSession *session, QObject *parent) - :QMetaDataControl(parent), m_session(session) -{ -} - -QT7PlayerMetaDataControl::~QT7PlayerMetaDataControl() -{ -} - -bool QT7PlayerMetaDataControl::isMetaDataAvailable() const -{ - return !m_tags.isEmpty(); -} - -bool QT7PlayerMetaDataControl::isWritable() const -{ - return false; -} - -QVariant QT7PlayerMetaDataControl::metaData(QtMedia::MetaData key) const -{ - return m_tags.value(key); -} - -void QT7PlayerMetaDataControl::setMetaData(QtMedia::MetaData key, QVariant const &value) -{ - Q_UNUSED(key); - Q_UNUSED(value); -} - -QList QT7PlayerMetaDataControl::availableMetaData() const -{ - return m_tags.keys(); -} - -QVariant QT7PlayerMetaDataControl::extendedMetaData(const QString &key) const -{ - Q_UNUSED(key); - return QVariant(); -} - -void QT7PlayerMetaDataControl::setExtendedMetaData(const QString &key, QVariant const &value) -{ - Q_UNUSED(key); - Q_UNUSED(value); -} - -QStringList QT7PlayerMetaDataControl::availableExtendedMetaData() const -{ - return QStringList(); -} - -#ifdef QUICKTIME_C_API_AVAILABLE - -static QString stripCopyRightSymbol(const QString &key) -{ - return key.right(key.length()-1); -} - -static QString convertQuickTimeKeyToUserKey(const QString &key) -{ - if (key == QLatin1String("com.apple.quicktime.displayname")) - return QLatin1String("nam"); - else if (key == QLatin1String("com.apple.quicktime.album")) - return QLatin1String("alb"); - else if (key == QLatin1String("com.apple.quicktime.artist")) - return QLatin1String("ART"); - else - return QLatin1String("???"); -} - -static OSStatus readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass, - QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size) -{ - QTPropertyValueType type; - ByteCount propSize; - UInt32 propFlags; - OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags); - - - *value = malloc(propSize); - - err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size); - - if (type == 'code' || type == 'itsk' || type == 'itlk') { - // convert from native endian to big endian - OSTypePtr pType = (OSTypePtr)*value; - *pType = EndianU32_NtoB(*pType); - } - - return err; -} - -static UInt32 getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item) -{ - QTPropertyValuePtr value = 0; - ByteCount ignore = 0; - OSStatus err = readMetaValue( - metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore); - - UInt32 type = *((UInt32 *) value); - if (value) - free(value); - return type; -} - -static QString cFStringToQString(CFStringRef str) -{ - if(!str) - return QString(); - CFIndex length = CFStringGetLength(str); - const UniChar *chars = CFStringGetCharactersPtr(str); - if (chars) - return QString(reinterpret_cast(chars), length); - - QVarLengthArray buffer(length); - CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); - return QString(reinterpret_cast(buffer.constData()), length); -} - - -static QString getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id) -{ - QTPropertyValuePtr value = 0; - ByteCount size = 0; - OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size); - - QString string; - UInt32 dataType = getMetaType(metaDataRef, item); - switch (dataType){ - case kQTMetaDataTypeUTF8: - case kQTMetaDataTypeMacEncodedText: - string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false)); - break; - case kQTMetaDataTypeUTF16BE: - string = cFStringToQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false)); - break; - default: - break; - } - - if (value) - free(value); - return string; -} - - -static void readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap &result) -{ - QTMetaDataItem item = kQTMetaDataItemUninitialized; - OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item); - while (err == noErr){ - QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key); - if (format == kQTMetaDataStorageFormatQuickTime) - key = convertQuickTimeKeyToUserKey(key); - else - key = stripCopyRightSymbol(key); - - if (!result.contains(key)){ - QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value); - result.insert(key, val); - } - err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item); - } -} -#endif - - -void QT7PlayerMetaDataControl::updateTags() -{ - bool wasEmpty = m_tags.isEmpty(); - m_tags.clear(); - - QTMovie *movie = (QTMovie*)m_session->movie(); - - if (movie) { - QMultiMap metaMap; - -#ifdef QUICKTIME_C_API_AVAILABLE - QTMetaDataRef metaDataRef; - OSStatus err = QTCopyMovieMetaData([movie quickTimeMovie], &metaDataRef); - - readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap); - readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap); - readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap); -#else - NSString *name = [movie attributeForKey:@"QTMovieDisplayNameAttribute"]; - metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String])); -#endif // QUICKTIME_C_API_AVAILABLE - - m_tags.insert(QtMedia::AlbumArtist, metaMap.value(QLatin1String("ART"))); - m_tags.insert(QtMedia::AlbumTitle, metaMap.value(QLatin1String("alb"))); - m_tags.insert(QtMedia::Title, metaMap.value(QLatin1String("nam"))); - m_tags.insert(QtMedia::Date, metaMap.value(QLatin1String("day"))); - m_tags.insert(QtMedia::Genre, metaMap.value(QLatin1String("gnre"))); - m_tags.insert(QtMedia::TrackNumber, metaMap.value(QLatin1String("trk"))); - m_tags.insert(QtMedia::Description, metaMap.value(QLatin1String("des"))); - } - - if (!wasEmpty || !m_tags.isEmpty()) - emit metaDataChanged(); -} - -QT_END_NAMESPACE - -#include "moc_qt7playermetadata.cpp" diff --git a/src/plugins/mediaservices/qt7/qt7playerservice.h b/src/plugins/mediaservices/qt7/qt7playerservice.h deleted file mode 100644 index d4b30b8..0000000 --- a/src/plugins/mediaservices/qt7/qt7playerservice.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT7PLAYERSERVICE_H -#define QT7PLAYERSERVICE_H - -#include -#include - - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QMediaMetaData; -class QMediaPlayerControl; -class QMediaPlaylist; -class QMediaPlaylistNavigator; -class QT7PlayerControl; -class QT7PlayerMetaDataControl; -class QT7VideoOutputControl; -class QT7VideoWindowControl; -class QT7VideoWidgetControl; -class QT7VideoRendererControl; -class QT7VideoOutput; -class QT7PlayerSession; - -class QT7PlayerService : public QMediaService -{ -Q_OBJECT -public: - QT7PlayerService(QObject *parent = 0); - ~QT7PlayerService(); - - QMediaControl *control(const char *name) const; - -private slots: - void updateVideoOutput(); - -private: - QT7PlayerSession *m_session; - QT7PlayerControl *m_control; - QT7VideoOutputControl *m_videoOutputControl; - QT7VideoWindowControl *m_videoWidnowControl; - QT7VideoWidgetControl *m_videoWidgetControl; - QT7VideoRendererControl *m_videoRendererControl; - QT7PlayerMetaDataControl *m_playerMetaDataControl; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/mediaservices/qt7/qt7playerservice.mm b/src/plugins/mediaservices/qt7/qt7playerservice.mm deleted file mode 100644 index df15fa8..0000000 --- a/src/plugins/mediaservices/qt7/qt7playerservice.mm +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include - -#include "qt7backend.h" -#include "qt7playerservice.h" -#include "qt7playercontrol.h" -#include "qt7playersession.h" -#include "qt7videooutputcontrol.h" -#include "qt7movieviewoutput.h" -#include "qt7movieviewrenderer.h" -#include "qt7movierenderer.h" -#include "qt7movievideowidget.h" -#include "qt7playermetadata.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -QT7PlayerService::QT7PlayerService(QObject *parent): - QMediaService(parent) -{ - m_session = new QT7PlayerSession; - - m_control = new QT7PlayerControl(this); - m_control->setSession(m_session); - - m_playerMetaDataControl = new QT7PlayerMetaDataControl(m_session, this); - connect(m_control, SIGNAL(mediaChanged(QMediaContent)), m_playerMetaDataControl, SLOT(updateTags())); - - m_videoOutputControl = new QT7VideoOutputControl(this); - - m_videoWidnowControl = 0; - m_videoWidgetControl = 0; - m_videoRendererControl = 0; - -#if defined(QT_MAC_USE_COCOA) - m_videoWidnowControl = new QT7MovieViewOutput(this); - m_videoOutputControl->enableOutput(QVideoOutputControl::WindowOutput); - qDebug() << "Using cocoa"; -#endif - -#ifdef QUICKTIME_C_API_AVAILABLE - m_videoRendererControl = new QT7MovieRenderer(this); - m_videoOutputControl->enableOutput(QVideoOutputControl::RendererOutput); - - m_videoWidgetControl = new QT7MovieVideoWidget(this); - m_videoOutputControl->enableOutput(QVideoOutputControl::WidgetOutput); - qDebug() << "QuickTime C API is available"; -#else - m_videoRendererControl = new QT7MovieViewRenderer(this); - m_videoOutputControl->enableOutput(QVideoOutputControl::RendererOutput); - qDebug() << "QuickTime C API is not available"; -#endif - - - connect(m_videoOutputControl, SIGNAL(videoOutputChanged(QVideoOutputControl::Output)), - this, SLOT(updateVideoOutput())); -} - -QT7PlayerService::~QT7PlayerService() -{ -} - -QMediaControl *QT7PlayerService::control(const char *name) const -{ - if (qstrcmp(name, QMediaPlayerControl_iid) == 0) - return m_control; - - if (qstrcmp(name, QVideoOutputControl_iid) == 0) - return m_videoOutputControl; - - if (qstrcmp(name, QVideoWindowControl_iid) == 0) - return m_videoWidnowControl; - - if (qstrcmp(name, QVideoRendererControl_iid) == 0) - return m_videoRendererControl; - - if (qstrcmp(name, QVideoWidgetControl_iid) == 0) - return m_videoWidgetControl; - - if (qstrcmp(name, QMetaDataControl_iid) == 0) - return m_playerMetaDataControl; - - return 0; -} - -void QT7PlayerService::updateVideoOutput() -{ - qDebug() << "QT7PlayerService::updateVideoOutput" << m_videoOutputControl->output(); - - switch (m_videoOutputControl->output()) { - case QVideoOutputControl::WindowOutput: - m_session->setVideoOutput(m_videoWidnowControl); - break; - case QVideoOutputControl::RendererOutput: - m_session->setVideoOutput(m_videoRendererControl); - break; - case QVideoOutputControl::WidgetOutput: - m_session->setVideoOutput(m_videoWidgetControl); - break; - default: - m_session->setVideoOutput(0); - } -} - -QT_END_NAMESPACE - -#include "moc_qt7playerservice.cpp" diff --git a/src/plugins/mediaservices/qt7/qt7playersession.h b/src/plugins/mediaservices/qt7/qt7playersession.h deleted file mode 100644 index 55505ee..0000000 --- a/src/plugins/mediaservices/qt7/qt7playersession.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT7PLAYERSESSION_H -#define QT7PLAYERSESSION_H - -#include -#include - -#include -#include - - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QT7PlayerControl; -class QMediaPlaylist; -class QMediaPlaylistNavigator; -class QT7VideoOutput; -class QT7PlayerSession; -class QT7PlayerService; - -class QT7PlayerSession : public QObject -{ -Q_OBJECT -public: - QT7PlayerSession(QObject *parent = 0); - ~QT7PlayerSession(); - - void *movie() const; - - void setControl(QT7PlayerControl *control); - void setVideoOutput(QT7VideoOutput *output); - - QMediaPlayer::State state() const; - QMediaPlayer::MediaStatus mediaStatus() const; - - QMediaContent media() const; - const QIODevice *mediaStream() const; - void setMedia(const QMediaContent &content, QIODevice *stream); - - qint64 position() const; - qint64 duration() const; - - int bufferStatus() const; - - int volume() const; - bool isMuted() const; - - bool isVideoAvailable() const; - - bool isSeekable() const; - - qreal playbackRate() const; - void setPlaybackRate(qreal rate); - - void setPosition(qint64 pos); - - void play(); - void pause(); - void stop(); - - void setVolume(int volume); - void setMuted(bool muted); - - void processEOS(); - -signals: - void positionChanged(qint64 position); - void durationChanged(qint64 duration); - void stateChanged(QMediaPlayer::State newState); - void mediaStatusChanged(QMediaPlayer::MediaStatus status); - void volumeChanged(int volume); - void mutedChanged(bool muted); - void videoAvailableChanged(bool videoAvailable); - void error(int error, const QString &errorString); - -private: - void *m_QTMovie; - void *m_movieObserver; - - QMediaPlayer::State m_state; - QMediaPlayer::MediaStatus m_mediaStatus; - QIODevice *m_mediaStream; - QMediaContent m_resources; - - QT7VideoOutput *m_videoOutput; - - mutable qint64 m_currentTime; - - bool m_muted; - int m_volume; - qreal m_rate; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/plugins/mediaservices/qt7/qt7playersession.mm b/src/plugins/mediaservices/qt7/qt7playersession.mm deleted file mode 100644 index 3131a90..0000000 --- a/src/plugins/mediaservices/qt7/qt7playersession.mm +++ /dev/null @@ -1,402 +0,0 @@ -/**************************************************************************** -** -** 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 plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#import -#import - -#include "qt7backend.h" - -#include "qt7playersession.h" -#include "qt7playercontrol.h" -#include "qt7videooutputcontrol.h" - -#include - -#include - -#include -#include - - -QT_BEGIN_NAMESPACE - -@interface QTMovieObserver : NSObject -{ -@private - QT7PlayerSession *m_session; - QTMovie *m_movie; -} - -- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session; -- (void) setMovie:(QTMovie *)movie; -- (void) processEOS:(NSNotification *)notification; -@end - -@implementation QTMovieObserver - -- (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session -{ - if (!(self = [super init])) - return nil; - - self->m_session = session; - return self; -} - -- (void) setMovie:(QTMovie *)movie -{ - if (m_movie == movie) - return; - - if (m_movie) { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [m_movie release]; - } - - m_movie = movie; - - if (movie) { - [[NSNotificationCenter defaultCenter] addObserver: self selector: - @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie]; - - [movie retain]; - } -} - -- (void) processEOS:(NSNotification *)notification -{ - Q_UNUSED(notification); - m_session->processEOS(); -} - -@end - -static CFStringRef qString2CFStringRef(const QString &string) -{ - return CFStringCreateWithCharacters(0, reinterpret_cast(string.unicode()), - string.length()); -} - -QT7PlayerSession::QT7PlayerSession(QObject *parent) - : QObject(parent) - , m_QTMovie(0) - , m_state(QMediaPlayer::StoppedState) - , m_mediaStatus(QMediaPlayer::NoMedia) - , m_mediaStream(0) - , m_videoOutput(0) - , m_muted(false) - , m_volume(100) - , m_rate(1.0) -{ - m_movieObserver = [[QTMovieObserver alloc] initWithPlayerSession:this]; -} - -QT7PlayerSession::~QT7PlayerSession() -{ - [(QTMovieObserver*)m_movieObserver setMovie:nil]; - [(QTMovieObserver*)m_movieObserver release]; -} - -void *QT7PlayerSession::movie() const -{ - return m_QTMovie; -} - -void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output) -{ - if (m_videoOutput == output) - return; - - qDebug() << "set output" << output; - - if (m_videoOutput) { - m_videoOutput->setEnabled(false); - m_videoOutput->setMovie(0); - } - - m_videoOutput = output; - - if (m_videoOutput) { - m_videoOutput->setEnabled(m_QTMovie != 0); - m_videoOutput->setMovie(m_QTMovie); - } -} - - -qint64 QT7PlayerSession::position() const -{ - if (!m_QTMovie || m_state == QMediaPlayer::PausedState) - return m_currentTime; - - AutoReleasePool pool; - - QTTime qtTime = [(QTMovie*)m_QTMovie currentTime]; - quint64 t = static_cast(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); - m_currentTime = t; - - return m_currentTime; -} - -qint64 QT7PlayerSession::duration() const -{ - if (!m_QTMovie) - return 0; - - AutoReleasePool pool; - - QTTime qtTime = [(QTMovie*)m_QTMovie duration]; - - return static_cast(float(qtTime.timeValue) / float(qtTime.timeScale) * 1000.0f); -} - -QMediaPlayer::State QT7PlayerSession::state() const -{ - return m_state; -} - -QMediaPlayer::MediaStatus QT7PlayerSession::mediaStatus() const -{ - return m_mediaStatus; -} - -int QT7PlayerSession::bufferStatus() const -{ - return 100; -} - -int QT7PlayerSession::volume() const -{ - return m_volume; -} - -bool QT7PlayerSession::isMuted() const -{ - return m_muted; -} - -bool QT7PlayerSession::isSeekable() const -{ - return true; -} - -qreal QT7PlayerSession::playbackRate() const -{ - return m_rate; -} - -void QT7PlayerSession::setPlaybackRate(qreal rate) -{ - if (qFuzzyCompare(m_rate, rate)) - return; - - m_rate = rate; - - if (m_QTMovie && m_state == QMediaPlayer::PlayingState) { - float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; - [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; - } -} - -void QT7PlayerSession::setPosition(qint64 pos) -{ - if ( !isSeekable() || pos == position()) - return; - - AutoReleasePool pool; - - pos = qMin(pos, duration()); - - QTTime newQTTime = [(QTMovie*)m_QTMovie currentTime]; - newQTTime.timeValue = (pos / 1000.0f) * newQTTime.timeScale; - [(QTMovie*)m_QTMovie setCurrentTime:newQTTime]; -} - -void QT7PlayerSession::play() -{ - m_state = QMediaPlayer::PlayingState; - - float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; - [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; - - emit stateChanged(m_state); -} - -void QT7PlayerSession::pause() -{ - m_state = QMediaPlayer::PausedState; - - [(QTMovie*)m_QTMovie setRate:0]; - - emit stateChanged(m_state); -} - -void QT7PlayerSession::stop() -{ - m_state = QMediaPlayer::StoppedState; - - [(QTMovie*)m_QTMovie setRate:0]; - setPosition(0); - - if (m_state == QMediaPlayer::StoppedState) - emit stateChanged(m_state); -} - -void QT7PlayerSession::setVolume(int volume) -{ - if (m_QTMovie) { - m_volume = volume; - [(QTMovie*)m_QTMovie setVolume:(volume/100.0f)]; - } -} - -void QT7PlayerSession::setMuted(bool muted) -{ - if (m_muted != muted) { - m_muted = muted; - - if (m_QTMovie) - [(QTMovie*)m_QTMovie setMuted:m_muted]; - - emit mutedChanged(muted); - } -} - -QMediaContent QT7PlayerSession::media() const -{ - return m_resources; -} - -const QIODevice *QT7PlayerSession::mediaStream() const -{ - return m_mediaStream; -} - -void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) -{ - AutoReleasePool pool; - - if (m_QTMovie) { - [(QTMovieObserver*)m_movieObserver setMovie:nil]; - - if (m_videoOutput) { - m_videoOutput->setEnabled(false); - m_videoOutput->setMovie(0); - } - - [(QTMovie*)m_QTMovie release]; - m_QTMovie = 0; - } - - m_resources = content; - m_mediaStream = stream; - - QUrl url; - - if (!content.isNull()) - url = content.canonicalUrl(); - else - return; - - NSError *err = 0; - QTDataReference *dataRef = 0; - - if ( url.scheme() == "file" ) { - NSString *nsFileName = (NSString *)qString2CFStringRef( url.toLocalFile() ); - dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFileName]; - } else { - NSString *urlString = (NSString *)qString2CFStringRef( url.toString() ); - NSURL *url = [NSURL URLWithString: urlString]; - dataRef = [QTDataReference dataReferenceWithReferenceToURL:url]; - } - - NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys: - dataRef, QTMovieDataReferenceAttribute, - [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute, - [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute, - [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute, - [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute, - nil]; - - m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain]; - - if (err) { - [(QTMovie*)m_QTMovie release]; - m_QTMovie = 0; - QString description = QString::fromUtf8([[err localizedDescription] UTF8String]); - - qDebug() << "QT7PlayerSession::setMedia error" << description; - emit error(QMediaPlayer::FormatError, description ); - } else { - [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie]; - - if (m_videoOutput) { - m_videoOutput->setEnabled(true); - m_videoOutput->setMovie(m_QTMovie); - } - - emit durationChanged(duration()); - emit videoAvailableChanged(isVideoAvailable()); - - [(QTMovie*)m_QTMovie setMuted:m_muted]; - setVolume(m_volume); - } -} - -bool QT7PlayerSession::isVideoAvailable() const -{ - if (!m_QTMovie) - return false; - - AutoReleasePool pool; - return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasVideoAttribute"] boolValue] == YES; -} - -void QT7PlayerSession::processEOS() -{ - m_mediaStatus = QMediaPlayer::EndOfMedia; - emit stateChanged(m_state = QMediaPlayer::StoppedState); - emit mediaStatusChanged(m_mediaStatus); -} - -#include "moc_qt7playersession.cpp" - -QT_END_NAMESPACE - diff --git a/src/plugins/mediaservices/qt7/qt7serviceplugin.mm b/src/plugins/mediaservices/qt7/qt7serviceplugin.mm index 49ae8e0..3e2a2a6 100644 --- a/src/plugins/mediaservices/qt7/qt7serviceplugin.mm +++ b/src/plugins/mediaservices/qt7/qt7serviceplugin.mm @@ -51,16 +51,20 @@ QT_BEGIN_NAMESPACE QStringList QT7ServicePlugin::keys() const { - return QStringList() << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); + return QStringList() +#ifdef Q_MEDIASERVICE_MEDIAPLAYER_AVAILABLE + << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); +#endif } QMediaService* QT7ServicePlugin::create(QString const& key) { - qDebug() << "QT7ServicePlugin::create" << key; +#ifdef Q_MEDIASERVICE_MEDIAPLAYER_AVAILABLE if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) return new QT7PlayerService; +#endif - qDebug() << "unsupported key:" << key; + qWarning() << "Attempt to create unknown service with key" << key; return 0; } -- cgit v0.12 From 7574328b1bdfb5d7d34aa2428cb5dc623f19f4aa Mon Sep 17 00:00:00 2001 From: Nicholas Young Date: Tue, 19 Jan 2010 15:47:26 +1000 Subject: Added QtMultimedia audio/video to Webkit. Affects HTML5 Audio/Video --- src/3rdparty/webkit/WebCore/WebCore.pro | 28 +- .../WebCore/platform/graphics/MediaPlayer.cpp | 2 +- .../platform/graphics/qt/MediaPlayerPrivateQt.cpp | 583 +++++++++++++++++++++ .../platform/graphics/qt/MediaPlayerPrivateQt.h | 110 ++++ 4 files changed, 705 insertions(+), 18 deletions(-) create mode 100644 src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp create mode 100644 src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 3eba696..614a32a 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -155,8 +155,8 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) { # HTML5 media support !contains(DEFINES, ENABLE_VIDEO=.) { - contains(QT_CONFIG, phonon):DEFINES += ENABLE_VIDEO=1 - else:DEFINES += ENABLE_VIDEO=0 + contains(QT_CONFIG, multimedia): DEFINES += ENABLE_VIDEO=1 + else: DEFINES += ENABLE_VIDEO=0 } # HTML5 datalist support @@ -2721,23 +2721,17 @@ contains(DEFINES, ENABLE_VIDEO=1) { rendering/RenderMedia.cpp \ bindings/js/JSAudioConstructor.cpp - HEADERS += \ - platform/graphics/qt/MediaPlayerPrivatePhonon.h + INCLUDEPATH += \ + $$PWD/../../../multimedia/base - SOURCES += \ - platform/graphics/qt/MediaPlayerPrivatePhonon.cpp - - # Add phonon manually to prevent it from coming first in - # the include paths, as Phonon's path.h conflicts with - # WebCore's Path.h on case-insensitive filesystems. - qtAddLibrary(phonon) - INCLUDEPATH -= $$QMAKE_INCDIR_QT/phonon - INCLUDEPATH += $$QMAKE_INCDIR_QT/phonon - mac { - INCLUDEPATH -= $$QMAKE_LIBDIR_QT/phonon.framework/Headers - INCLUDEPATH += $$QMAKE_LIBDIR_QT/phonon.framework/Headers - } + HEADERS += \ + platform/graphics/qt/MediaPlayerPrivateQt.h + + SOURCES += \ + platform/graphics/qt/MediaPlayerPrivateQt.cpp + QT += multimedia + contains(QT_CONFIG, opengl): QT += opengl } contains(DEFINES, ENABLE_XPATH=1) { diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp index 3b32b65..07232fd 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp @@ -46,7 +46,7 @@ #elif PLATFORM(GTK) #include "MediaPlayerPrivateGStreamer.h" #elif PLATFORM(QT) -#include "MediaPlayerPrivatePhonon.h" +#include "MediaPlayerPrivateQt.h" #elif PLATFORM(CHROMIUM) #include "MediaPlayerPrivateChromium.h" #endif diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp new file mode 100644 index 0000000..967e125 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -0,0 +1,583 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Apple Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "MediaPlayerPrivateQt.h" + +#include + +// WebCore Includes +#include "CString.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "NotImplemented.h" +#include "TimeRanges.h" +#include "Widget.h" + +// WebKit Includes +#include + +// Qt Includes +#include +#include +#include +#include +#include +#include + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) +#include +#endif + +// Qt Multimedia Includes +#include +#include +#include +#include + + +//#define QT_WEBKIT_MEDIA_INSTRUMENTATION + +using namespace WTF; + +namespace WebCore { + +#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION +class MediaPlayerPrivateInstrumentation +{ +public: + MediaPlayerPrivateInstrumentation() + : update(false) + , frameCount(0) + , paintTimeTotal(0) + , framesPerSecond(0) + , averagePaintTime(0) + , preTime(QTime()) + , lastUpdate(QTime::currentTime()) {} + + void prePaint() { preTime = QTime::currentTime(); } + + void postPaint() + { + QTime time = QTime::currentTime(); + + // Measure seconds different + int paintTime = (time.second() - preTime.second() - 1) * 1000; + paintTime = qMax(0, paintTime); + + // Measure milliseconds different + if(time.msec() < preTime.msec()) + paintTime += time.msec() + (1000 - preTime.msec()); + else + paintTime += time.msec() - preTime.msec(); + + // Add to the total paint time for this second + paintTimeTotal += paintTime; + + // Check for update time + if(time.second() != lastUpdate.second()) { + // Calculate Values + framesPerSecond = frameCount; + averagePaintTime = static_cast(paintTimeTotal) / static_cast(frameCount); + + // Next Update + update = true; + frameCount = 1; + paintTimeTotal = 0; + lastUpdate = time; + } else { + frameCount++; + } + } + + bool updateAvailable() { return update; } + + int fps() { update = false; return framesPerSecond; } + qreal paintTime() { update = false; return averagePaintTime; } + +private: + bool update; + + int frameCount; + qint64 paintTimeTotal; + + int framesPerSecond; + qreal averagePaintTime; + + QTime preTime; + QTime lastUpdate; +}; +#endif // QT_WEBKIT_MEDIA_INSTRUMENTATION + +class MediaPlayerPrivateDefault : public MediaPlayerPrivate { +public: + IntSize naturalSize() const; + void setSize(const IntSize&) {} + void paint(GraphicsContext*, const IntRect&); + bool supportsFullscreen() const { return true; } + +private slots: + void repaint(); + +private: + friend class MediaPlayerPrivate; + MediaPlayerPrivateDefault(MediaPlayer*); + ~MediaPlayerPrivateDefault(); + + QPainterVideoSurface* m_videoSurface; + QVideoOutputControl* m_outputControl; + QVideoRendererControl* m_rendererControl; + + bool m_isActive; + +#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION + MediaPlayerPrivateInstrumentation* m_instruments; +#endif +}; + +MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +{ + return new MediaPlayerPrivateDefault(player); +} + +void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +{ + registrar(create, getSupportedTypes, supportsType); +} + +void MediaPlayerPrivate::getSupportedTypes(HashSet &supported) +{ + QStringList types = QMediaPlayer::supportedMimeTypes(); + + for (int i = 0; i < types.size(); i++) { + supported.add(types.at(i)); + } +} + +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, const String& codec) +{ + if(QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMedia::ProbablySupported) { + return MediaPlayer::IsSupported; + } + + return MediaPlayer::MayBeSupported; +} + +MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) + : m_player(player) + , m_mediaPlayer(new QMediaPlayer) + , m_networkState(MediaPlayer::Empty) + , m_readyState(MediaPlayer::HaveNothing) + , m_isVisible(false) + , m_endTime(std::numeric_limits::max()) +{ + // Signal Handlers + connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), + this, SLOT(stateChanged(QMediaPlayer::State))); + connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)), + this, SLOT(handleError(QMediaPlayer::Error))); + connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)), + this, SLOT(durationChanged(qint64))); + connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)), + this, SLOT(positionChanged(qint64))); + + // Grab the player control + if (m_mediaPlayer) { + QMediaService *service = m_mediaPlayer->service(); + if (service) { + m_mediaPlayerControl = qobject_cast( + service->control(QMediaPlayerControl_iid)); + } + } +} + +MediaPlayerPrivate::~MediaPlayerPrivate() +{ + delete m_mediaPlayer; + m_mediaPlayer = 0; +} + +bool MediaPlayerPrivate::hasVideo() const +{ + return m_mediaPlayer->isVideoAvailable(); +} + +bool MediaPlayerPrivate::hasAudio() const +{ + return true; +} + +void MediaPlayerPrivate::load(const String& url) +{ + // We are now loading + if (m_networkState != MediaPlayer::Loading) { + m_networkState = MediaPlayer::Loading; + m_player->networkStateChanged(); + } + + // And we don't have any data yet + if (m_readyState != MediaPlayer::HaveNothing) { + m_readyState = MediaPlayer::HaveNothing; + m_player->readyStateChanged(); + } + + m_mediaPlayer->setMedia(QUrl(url)); +} + +void MediaPlayerPrivate::cancelLoad() +{ + m_mediaPlayer->setMedia(QMediaContent()); + updateStates(); +} + +void MediaPlayerPrivate::play() +{ + if(m_mediaPlayer->state() != QMediaPlayer::PlayingState) { + m_mediaPlayer->play(); + } +} + +void MediaPlayerPrivate::pause() +{ + if(m_mediaPlayer->state() == QMediaPlayer::PlayingState) { + m_mediaPlayer->pause(); + } +} + +bool MediaPlayerPrivate::paused() const +{ + return m_mediaPlayer->state() != QMediaPlayer::PlayingState; +} + +void MediaPlayerPrivate::seek(float position) +{ + if (!m_mediaPlayer->isSeekable()) + return; + + if (m_mediaPlayerControl != 0 && + !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000)) + return; + + if (position > duration()) + position = duration(); + + m_mediaPlayer->setPosition(position * 1000.0f); +} + +bool MediaPlayerPrivate::seeking() const +{ + return false; +} + +void MediaPlayerPrivate::setEndTime(float time) +{ + // Set the end time in milliseconds + m_endTime = static_cast(time * 1000.0f); + + // Duration may return a smaller value as of now + m_player->durationChanged(); +} + +float MediaPlayerPrivate::duration() const +{ + if (m_readyState < MediaPlayer::HaveMetadata) + return 0.0f; + + float duration = qMin(m_mediaPlayer->duration(), m_endTime) / 1000.0f; + + // We are streaming + if (duration <= 0.0f) + duration = std::numeric_limits::infinity(); + + return duration; +} + +float MediaPlayerPrivate::currentTime() const +{ + float currentTime = m_mediaPlayer->position() / 1000.0f; + return currentTime; +} + +PassRefPtr MediaPlayerPrivate::buffered() const +{ + RefPtr buffered = TimeRanges::create(); + + if(m_mediaPlayerControl == 0) + return buffered; + + QMediaTimeRange playbackRanges = m_mediaPlayerControl->availablePlaybackRanges(); + + foreach(const QMediaTimeInterval interval, playbackRanges.intervals()) { + float rangeMin = static_cast(interval.start()) / 1000.0f; + float rangeMax = static_cast(interval.end()) / 1000.0f; + buffered->add(rangeMin, rangeMax); + } + + return buffered.release(); +} + +float MediaPlayerPrivate::maxTimeSeekable() const +{ + if(m_mediaPlayerControl == 0) + return 0; + + return static_cast(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f; +} + +unsigned MediaPlayerPrivate::bytesLoaded() const +{ + unsigned percentage = m_mediaPlayer->bufferStatus(); + + if(percentage == 100) { + if(m_networkState != MediaPlayer::Idle) { + m_networkState = MediaPlayer::Idle; + m_player->networkStateChanged(); + } + if(m_readyState != MediaPlayer::HaveEnoughData) { + m_readyState = MediaPlayer::HaveEnoughData; + m_player->readyStateChanged(); + } + } + + QLatin1String blKey("bytes-loaded"); + if(m_mediaPlayer->availableExtendedMetaData().contains(blKey)) + return m_mediaPlayer->extendedMetaData(blKey).toInt(); + + return percentage; +} + +unsigned MediaPlayerPrivate::totalBytes() const +{ + if(m_mediaPlayer->availableMetaData().contains(QtMedia::Size)) + return m_mediaPlayer->metaData(QtMedia::Size).toInt(); + + return 100; +} + +bool MediaPlayerPrivate::totalBytesKnown() const +{ + return m_mediaPlayer->availableMetaData().contains(QtMedia::Size); +} + +void MediaPlayerPrivate::setRate(float rate) +{ + m_mediaPlayer->setPlaybackRate(rate); +} + +void MediaPlayerPrivate::setVolume(float volume) +{ + m_mediaPlayer->setVolume(static_cast(volume * 100.0)); +} + +void MediaPlayerPrivate::setMuted(bool muted) +{ + m_mediaPlayer->setMuted(muted); +} + +int MediaPlayerPrivate::dataRate() const +{ + return 0; +} + +MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const +{ + return m_networkState; +} + +MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const +{ + return m_readyState; +} + +void MediaPlayerPrivate::setVisible(bool visible) +{ + m_isVisible = visible; +} + +void MediaPlayerPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus) +{ + updateStates(); +} + +void MediaPlayerPrivate::handleError(QMediaPlayer::Error) +{ + updateStates(); +} + +void MediaPlayerPrivate::durationChanged(qint64) +{ + m_player->durationChanged(); +} + +void MediaPlayerPrivate::updateStates() +{ + // Store the old states so that we can detect a change and raise change events + MediaPlayer::NetworkState oldNetworkState = m_networkState; + MediaPlayer::ReadyState oldReadyState = m_readyState; + + QMediaPlayer::MediaStatus currentStatus = m_mediaPlayer->mediaStatus(); + QMediaPlayer::Error currentError = m_mediaPlayer->error(); + + if(currentError != QMediaPlayer::NoError) { + m_readyState = MediaPlayer::HaveNothing; + if(currentError == QMediaPlayer::FormatError) { + m_networkState = MediaPlayer::FormatError; + } else { + // ResourceError, NetworkError, AccessDeniedError, ServiceMissingError + m_networkState = MediaPlayer::NetworkError; + } + } else if(currentStatus == QMediaPlayer::UnknownMediaStatus || + currentStatus == QMediaPlayer::NoMedia) { + m_networkState = MediaPlayer::Idle; + m_readyState = MediaPlayer::HaveNothing; + } else if(currentStatus == QMediaPlayer::LoadingMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveNothing; + } else if(currentStatus == QMediaPlayer::LoadedMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveMetadata; + } else if(currentStatus == QMediaPlayer::BufferingMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveFutureData; + } else if(currentStatus == QMediaPlayer::StalledMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveCurrentData; + } else if(currentStatus == QMediaPlayer::BufferedMedia || + currentStatus == QMediaPlayer::EndOfMedia) { + m_networkState = MediaPlayer::Idle; + m_readyState = MediaPlayer::HaveEnoughData; + } else if(currentStatus == QMediaPlayer::InvalidMedia) { + m_networkState = MediaPlayer::FormatError; + m_readyState = MediaPlayer::HaveMetadata; + } + + // Log the state changes and raise the state change events + if (m_networkState != oldNetworkState) { + m_player->networkStateChanged(); + } + + if (m_readyState != oldReadyState) { + m_player->readyStateChanged(); + } +} + +MediaPlayerPrivateDefault::MediaPlayerPrivateDefault(MediaPlayer *player) + : MediaPlayerPrivate(player) + , m_videoSurface(new QPainterVideoSurface(m_mediaPlayer)) +{ +#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION + m_instruments = new MediaPlayerPrivateInstrumentation; +#endif + + if (m_mediaPlayer) { + QMediaService *service = m_mediaPlayer->service(); + if (service) { + m_outputControl = qobject_cast( + service->control(QVideoOutputControl_iid)); + m_rendererControl = qobject_cast( + service->control(QVideoRendererControl_iid)); + + if (m_outputControl != 0 && m_rendererControl != 0) { + connect(m_videoSurface, SIGNAL(frameChanged()), this, SLOT(repaint())); + + m_rendererControl->setSurface(m_videoSurface); + m_outputControl->setOutput(QVideoOutputControl::RendererOutput); + } + } + } +} + +MediaPlayerPrivateDefault::~MediaPlayerPrivateDefault() +{ +#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION + delete m_instruments; + m_instruments = 0; +#endif +} + +IntSize MediaPlayerPrivateDefault::naturalSize() const +{ + if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata) + return IntSize(); + + QSize videoSize = m_videoSurface->surfaceFormat().sizeHint(); + return IntSize(videoSize.width(), videoSize.height()); +} + +void MediaPlayerPrivateDefault::paint(GraphicsContext* context, const IntRect& rect) +{ + if (context->paintingDisabled()) + return; + + if (!m_isVisible) + return; + +#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION + m_instruments->prePaint(); +#endif + + // Grab the painter + QPainter* painter = context->platformContext(); + + if(!m_isActive) { + // Attempt GL Setup +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) + if ((painter->paintEngine()->type() == QPaintEngine::OpenGL || + painter->paintEngine()->type() == QPaintEngine::OpenGL2)) { + // Set GL Context + m_videoSurface->setGLContext(const_cast(QGLContext::currentContext())); + + // Check Shader Types + if (m_videoSurface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { + m_videoSurface->setShaderType(QPainterVideoSurface::GlslShader); + } else { + m_videoSurface->setShaderType(QPainterVideoSurface::FragmentProgramShader); + } + } +#endif + + // Setup Completed + m_isActive = true; + } + + // Paint the frame + m_videoSurface->paint(painter, QRect(rect.x(), rect.y(), + rect.width(), rect.height())); + m_videoSurface->setReady(true); + + #ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION + m_instruments->postPaint(); + + if(m_instruments->updateAvailable()) { + qDebug("FPS: %d, Average Paint Time: %f", m_instruments->fps(), m_instruments->paintTime()); + } + #endif +} + +void MediaPlayerPrivateDefault::repaint() +{ + m_player->repaint(); +} + +} // namespace WebCore + +#include "moc_MediaPlayerPrivateQt.cpp" diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h new file mode 100644 index 0000000..f2d4040 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Apple Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MediaPlayerPrivateQt_h +#define MediaPlayerPrivateQt_h + +#include "MediaPlayerPrivate.h" +#include +#include +#include + +namespace WebCore { + + class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface { + + Q_OBJECT + + public: + static MediaPlayerPrivateInterface* create(MediaPlayer* player); + virtual ~MediaPlayerPrivate(); + + static void registerMediaEngine(MediaEngineRegistrar); + static void getSupportedTypes(HashSet&); + static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); + static bool isAvailable() { return true; } + + bool hasVideo() const; + bool hasAudio() const; + + void load(const String &url); + void cancelLoad(); + + void play(); + void pause(); + + bool paused() const; + bool seeking() const; + + float duration() const; + float currentTime() const; + void seek(float); + void setEndTime(float); + + void setRate(float); + void setVolume(float); + void setMuted(bool); + + // State Information + MediaPlayer::NetworkState networkState() const; + MediaPlayer::ReadyState readyState() const; + + // Network Information + PassRefPtr buffered() const; + float maxTimeSeekable() const; + unsigned bytesLoaded() const; + unsigned totalBytes() const; + bool totalBytesKnown() const; + int dataRate() const; + + virtual void setVisible(bool); + + virtual IntSize naturalSize() const = 0; + virtual void setSize(const IntSize&) = 0; + virtual void paint(GraphicsContext*, const IntRect&) = 0; + virtual bool supportsFullscreen() const = 0; + + protected slots: + virtual void mediaStatusChanged(QMediaPlayer::MediaStatus); + virtual void handleError(QMediaPlayer::Error); + virtual void stateChanged(QMediaPlayer::State) {} + virtual void positionChanged(qint64) {} + virtual void durationChanged(qint64); + virtual void repaint() {} + + protected: + MediaPlayerPrivate(MediaPlayer*); + + MediaPlayer* m_player; + QMediaPlayer* m_mediaPlayer; + QMediaPlayerControl* m_mediaPlayerControl; + + mutable MediaPlayer::NetworkState m_networkState; + mutable MediaPlayer::ReadyState m_readyState; + + bool m_isVisible; + qint64 m_endTime; + + private: + void updateStates(); + }; +} + +#endif // MediaPlayerPrivateQt_h -- cgit v0.12 From e3b0ec7288b2ad3c477e6717d0ce605a06c0361e Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Thu, 28 Jan 2010 17:20:21 +1000 Subject: Fixup license headers. --- src/multimedia/qml/qmlsound.cpp | 2 +- src/multimedia/qml/qmlsound_p.h | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamermessage.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h | 2 +- .../mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h | 2 +- .../mediaservices/gstreamer/qgstreamervideorendererinterface.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h | 2 +- src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp | 2 +- src/plugins/mediaservices/gstreamer/qgstvideobuffer.h | 2 +- src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp | 2 +- src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h | 2 +- src/plugins/mediaservices/gstreamer/qx11videosurface.cpp | 2 +- src/plugins/mediaservices/gstreamer/qx11videosurface.h | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/multimedia/qml/qmlsound.cpp b/src/multimedia/qml/qmlsound.cpp index 6b01418..b0693b7 100644 --- a/src/multimedia/qml/qmlsound.cpp +++ b/src/multimedia/qml/qmlsound.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/multimedia/qml/qmlsound_p.h b/src/multimedia/qml/qmlsound_p.h index 3c17413..0a149c0 100644 --- a/src/multimedia/qml/qmlsound_p.h +++ b/src/multimedia/qml/qmlsound_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index c22e83c..e38f80f 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h index 7e9af23..cdf82d9 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index 730279a..7dd8375 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h index ec0253b..7fb2349 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp index 0c83147..d5d7bd0 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h index b27c2ae..f60c72e 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayerservice.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp index baece67..93d97cf 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h index a0f5f1a..f855727 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp index 0f09c6b..4649c21 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h index 471ca50..8600015 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamerbushelper.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp b/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp index 19cdfb1..13a2454 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamermessage.h b/src/plugins/mediaservices/gstreamer/qgstreamermessage.h index 70f35f3..4680903 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamermessage.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamermessage.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp index e892e45..9e5f425 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h index 33148ac..d6d6899 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp index 5059409..ac9a1e3 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h index 5cdc05f..6762bab 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp index 10d446f..decf524 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h index 0d618f2..7685239 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooutputcontrol.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp index 8dbe3db..6c6c802 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h index 518d8ce..9566949 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideooverlay.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp index 7e10fbf..25a53cf 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h index f476730..ba3f806 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorenderer.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp index 57df692..0a1c20d 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h index 2700965..39deee8 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideorendererinterface.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp index 7b2ec14..1d8d43d 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h index 9edd1dd..7b966b7 100644 --- a/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h +++ b/src/plugins/mediaservices/gstreamer/qgstreamervideowidget.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp index 80943b5..384bdff 100644 --- a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h index 487832c..36b7c08 100644 --- a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h +++ b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index 7c5805c..41e3f77 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h index 99d7007..f02f9a5 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp index 56c1405..30b7e55 100644 --- a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp +++ b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/mediaservices/gstreamer/qx11videosurface.h b/src/plugins/mediaservices/gstreamer/qx11videosurface.h index e69517a..1be963e 100644 --- a/src/plugins/mediaservices/gstreamer/qx11videosurface.h +++ b/src/plugins/mediaservices/gstreamer/qx11videosurface.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Qt Mobility Components. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage -- cgit v0.12 From 1e7dc2be019a5cb278d5ca72702dfbac846bf3e7 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Thu, 28 Jan 2010 17:22:01 +1000 Subject: Normalise #defines for service support. --- src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri | 2 +- src/plugins/mediaservices/qt7/qt7serviceplugin.mm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri index f00d418..577209e 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri +++ b/src/plugins/mediaservices/qt7/mediaplayer/mediaplayer.pri @@ -1,6 +1,6 @@ INCLUDEPATH += $$PWD -DEFINES += Q_MEDIASERVICE_MEDIAPLAYER_AVAILABLE +DEFINES += QMEDIA_QT7_PLAYER HEADERS += \ $$PWD/qt7playercontrol.h \ diff --git a/src/plugins/mediaservices/qt7/qt7serviceplugin.mm b/src/plugins/mediaservices/qt7/qt7serviceplugin.mm index 3e2a2a6..c59a453 100644 --- a/src/plugins/mediaservices/qt7/qt7serviceplugin.mm +++ b/src/plugins/mediaservices/qt7/qt7serviceplugin.mm @@ -52,14 +52,14 @@ QT_BEGIN_NAMESPACE QStringList QT7ServicePlugin::keys() const { return QStringList() -#ifdef Q_MEDIASERVICE_MEDIAPLAYER_AVAILABLE +#ifdef QMEDIA_QT7_PLAYER << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); #endif } QMediaService* QT7ServicePlugin::create(QString const& key) { -#ifdef Q_MEDIASERVICE_MEDIAPLAYER_AVAILABLE +#ifdef QMEDIA_QT7_PLAYER if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) return new QT7PlayerService; #endif -- cgit v0.12 From b220901d125b6c440426577b10d5c7463bf49964 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Thu, 28 Jan 2010 17:28:36 +1000 Subject: Add an audioAvailable property to QMediaPlayer. from: Andrew den Exter committed 00373999 to qtmobility/qtm-multimedia --- src/multimedia/playback/qmediaplayer.cpp | 26 ++++++++++++++++++++++ src/multimedia/playback/qmediaplayer.h | 3 +++ src/multimedia/playback/qmediaplayercontrol.cpp | 16 +++++++++++++ src/multimedia/playback/qmediaplayercontrol.h | 2 ++ .../mediaplayer/qgstreamerplayercontrol.cpp | 7 ++++++ .../mediaplayer/qgstreamerplayercontrol.h | 1 + .../mediaplayer/qgstreamerplayersession.cpp | 16 +++++++++++++ .../mediaplayer/qgstreamerplayersession.h | 3 +++ .../qt7/mediaplayer/qt7playercontrol.h | 2 +- .../qt7/mediaplayer/qt7playercontrol.mm | 5 +++++ .../qt7/mediaplayer/qt7playersession.h | 2 ++ .../qt7/mediaplayer/qt7playersession.mm | 10 +++++++++ 12 files changed, 92 insertions(+), 1 deletion(-) diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 878af0a..0853597 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -282,6 +282,7 @@ QMediaPlayer::QMediaPlayer(QObject *parent, QMediaPlayer::Flags flags, QMediaSer connect(d->control, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64))); connect(d->control, SIGNAL(positionChanged(qint64)), SIGNAL(positionChanged(qint64))); + connect(d->control, SIGNAL(audioAvailableChanged(bool)), SIGNAL(audioAvailableChanged(bool))); connect(d->control, SIGNAL(videoAvailableChanged(bool)), SIGNAL(videoAvailableChanged(bool))); connect(d->control, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged(int))); connect(d->control, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool))); @@ -402,6 +403,16 @@ int QMediaPlayer::bufferStatus() const return 0; } +bool QMediaPlayer::isAudioAvailable() const +{ + Q_D(const QMediaPlayer); + + if (d->control != 0) + return d->control->isAudioAvailable(); + + return false; +} + bool QMediaPlayer::isVideoAvailable() const { Q_D(const QMediaPlayer); @@ -841,6 +852,15 @@ QStringList QMediaPlayer::supportedMimeTypes(Flags flags) */ /*! + \property QMediaPlayer::audioAvailable + \brief the audio availabilty status for the current media. + + As the life time of QMediaPlayer can be longer than the playback of one + QMediaContent, this property may change over time, the + audioAvailableChanged signal can be used to monitor it's status. +*/ + +/*! \property QMediaPlayer::videoAvailable \brief the video availability status for the current media. @@ -902,6 +922,12 @@ QStringList QMediaPlayer::supportedMimeTypes(Flags flags) */ /*! + \fn void QMediaPlayer::audioAvailableChanged(bool available) + + Signals the availability of audio content has changed to \a available. +*/ + +/*! \fn void QMediaPlayer::videoAvailableChanged(bool videoAvailable) Signal the availability of visual content has changed to \a videoAvailable. diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index 4de2b5e..dc9d4f0 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -66,6 +66,7 @@ class Q_MULTIMEDIA_EXPORT QMediaPlayer : public QMediaObject Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) Q_PROPERTY(int bufferStatus READ bufferStatus NOTIFY bufferStatusChanged) + Q_PROPERTY(bool audioAvailable READ isAudioAvailable NOTIFY audioAvailableChanged) Q_PROPERTY(bool videoAvailable READ isVideoAvailable NOTIFY videoAvailableChanged) Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged) Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged) @@ -131,6 +132,7 @@ public: int volume() const; bool isMuted() const; + bool isAudioAvailable() const; bool isVideoAvailable() const; int bufferStatus() const; @@ -165,6 +167,7 @@ Q_SIGNALS: void volumeChanged(int volume); void mutedChanged(bool muted); + void audioAvailableChanged(bool audioAvailable); void videoAvailableChanged(bool videoAvailable); void bufferStatusChanged(int percentFilled); diff --git a/src/multimedia/playback/qmediaplayercontrol.cpp b/src/multimedia/playback/qmediaplayercontrol.cpp index 90e3a8c..95ffade 100644 --- a/src/multimedia/playback/qmediaplayercontrol.cpp +++ b/src/multimedia/playback/qmediaplayercontrol.cpp @@ -220,6 +220,22 @@ QMediaPlayerControl::QMediaPlayerControl(QObject *parent): */ /*! + \fn QMediaPlayerControl::isAudioAvailable() const + + Identifies if there is audio output available for the current media. + + Returns true if audio output is available and false otherwise. +*/ + +/*! + \fn QMediaPlayerControl::audioAvailableChanged(bool audio) + + Signals that there has been a change in the availability of \a audio output. + + \sa isAudioAvailable() +*/ + +/*! \fn QMediaPlayerControl::isVideoAvailable() const Identifies if there is video output available for the current media. diff --git a/src/multimedia/playback/qmediaplayercontrol.h b/src/multimedia/playback/qmediaplayercontrol.h index ac3fc45..a7e418b 100644 --- a/src/multimedia/playback/qmediaplayercontrol.h +++ b/src/multimedia/playback/qmediaplayercontrol.h @@ -82,6 +82,7 @@ public: virtual int bufferStatus() const = 0; + virtual bool isAudioAvailable() const = 0; virtual bool isVideoAvailable() const = 0; virtual bool isSeekable() const = 0; @@ -107,6 +108,7 @@ Q_SIGNALS: void mediaStatusChanged(QMediaPlayer::MediaStatus status); void volumeChanged(int volume); void mutedChanged(bool muted); + void audioAvailableChanged(bool audioAvailable); void videoAvailableChanged(bool videoAvailable); void bufferStatusChanged(int percentFilled); void seekableChanged(bool); diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index 7dd8375..f008e81 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -80,6 +80,8 @@ QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *sessio this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); connect(m_session,SIGNAL(bufferingProgressChanged(int)), this, SIGNAL(bufferStatusChanged(int))); + connect(m_session, SIGNAL(audioAvailableChanged(bool)), + this, SIGNAL(audioAvailableChanged(bool))); connect(m_session, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(videoAvailableChanged(bool))); connect(m_session, SIGNAL(seekableChanged(bool)), @@ -236,6 +238,11 @@ void QGstreamerPlayerControl::setVideoOutput(QObject *output) m_session->setVideoRenderer(output); } +bool QGstreamerPlayerControl::isAudioAvailable() const +{ + return m_session->isAudioAvailable(); +} + bool QGstreamerPlayerControl::isVideoAvailable() const { return m_session->isVideoAvailable(); diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h index 7fb2349..ae0f8b6 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.h @@ -79,6 +79,7 @@ public: int volume() const; bool isMuted() const; + bool isAudioAvailable() const; bool isVideoAvailable() const; void setVideoOutput(QObject *output); diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 93d97cf..93151e1 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -63,6 +63,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) m_volume(100), m_playbackRate(1.0), m_muted(false), + m_audioAvailable(false), m_videoAvailable(false), m_seekable(false), m_lastPosition(0), @@ -231,6 +232,11 @@ bool QGstreamerPlayerSession::isMuted() const return m_muted; } +bool QGstreamerPlayerSession::isAudioAvailable() const +{ + return m_audioAvailable; +} + void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) { m_renderer = qobject_cast(videoOutput); @@ -565,6 +571,7 @@ void QGstreamerPlayerSession::getStreamsInfo() } //check if video is available: + bool haveAudio = false; bool haveVideo = false; // m_streamProperties.clear(); // m_streamTypes.clear(); @@ -578,6 +585,9 @@ void QGstreamerPlayerSession::getStreamsInfo() g_object_get(G_OBJECT(m_playbin), "n-video", &videoStreamsCount, NULL); g_object_get(G_OBJECT(m_playbin), "n-text", &textStreamsCount, NULL); + haveAudio = audioStreamsCount > 0; + haveVideo = videoStreamsCount > 0; + m_playbin2StreamOffset[QMediaStreamsControl::AudioStream] = 0; m_playbin2StreamOffset[QMediaStreamsControl::VideoStream] = audioStreamsCount; m_playbin2StreamOffset[QMediaStreamsControl::SubPictureStream] = audioStreamsCount+videoStreamsCount; @@ -648,6 +658,8 @@ void QGstreamerPlayerSession::getStreamsInfo() if (type == GST_STREAM_TYPE_VIDEO) haveVideo = true; + else if (type == GST_STREAM_TYPE_AUDIO) + hasAudio = true; // QMediaStreamsControl::StreamType streamType = QMediaStreamsControl::UnknownStream; // @@ -674,6 +686,10 @@ void QGstreamerPlayerSession::getStreamsInfo() } #endif + if (haveAudio != m_audioAvailable) { + m_audioAvailable = haveAudio; + emit audioAvailableChanged(m_audioAvailable); + } if (haveVideo != m_videoAvailable) { m_videoAvailable = haveVideo; emit videoAvailableChanged(m_videoAvailable); diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h index f855727..0da5f8f 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -84,6 +84,7 @@ public: bool isMuted() const; void setVideoRenderer(QObject *renderer); + bool isAudioAvailable() const; bool isVideoAvailable() const; bool isSeekable() const; @@ -120,6 +121,7 @@ signals: void mediaStatusChanged(QMediaPlayer::MediaStatus mediaStatus); void volumeChanged(int volume); void mutedStateChanged(bool muted); + void audioAvailalbeChanged(bool audioAvailable); void videoAvailableChanged(bool videoAvailable); void bufferingChanged(bool buffering); void bufferingProgressChanged(int percentFilled); @@ -154,6 +156,7 @@ private: int m_volume; qreal m_playbackRate; bool m_muted; + bool m_audioAvailable; bool m_videoAvailable; bool m_seekable; diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h index da86949..907d13d 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.h @@ -82,13 +82,13 @@ public: int volume() const; bool isMuted() const; + bool isAudioAvailable() const; bool isVideoAvailable() const; bool isSeekable() const; QMediaTimeRange availablePlaybackRanges() const; - qreal playbackRate() const; void setPlaybackRate(qreal rate); diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm index b74f434..0f4ac41 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playercontrol.mm @@ -71,6 +71,7 @@ void QT7PlayerControl::setSession(QT7PlayerSession *session) this, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))); connect(m_session, SIGNAL(volumeChanged(int)), this, SIGNAL(volumeChanged(int))); connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); + connect(m_session, SIGNAL(audioAvailableChanged(bool)), this, SIGNAL(audioAvailableChanged(bool))); connect(m_session, SIGNAL(videoAvailableChanged(bool)), this, SIGNAL(videoAvailableChanged(bool))); connect(m_session, SIGNAL(error(int,QString)), this, SIGNAL(error(int,QString))); } @@ -177,6 +178,10 @@ void QT7PlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) emit mediaChanged(content); } +bool QT7PlayerControl::isAudioAvailable() const +{ + return m_session->isAudioAvailable(); +} bool QT7PlayerControl::isVideoAvailable() const { diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h index 55505ee..2a6bab7 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h @@ -87,6 +87,7 @@ public: int volume() const; bool isMuted() const; + bool isAudioAvailable() const; bool isVideoAvailable() const; bool isSeekable() const; @@ -112,6 +113,7 @@ signals: void mediaStatusChanged(QMediaPlayer::MediaStatus status); void volumeChanged(int volume); void mutedChanged(bool muted); + void audioAvailableChanged(bool audioAvailable); void videoAvailableChanged(bool videoAvailable); void error(int error, const QString &errorString); diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm index 3131a90..d9bb646 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -373,6 +373,7 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) } emit durationChanged(duration()); + emit audioAvailableChanged(isAudioAvailable()); emit videoAvailableChanged(isVideoAvailable()); [(QTMovie*)m_QTMovie setMuted:m_muted]; @@ -380,6 +381,15 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) } } +bool QT7PlayerSession::isAudioAvailable() const +{ + if (!m_QTMovie) + return false; + + AutoReleasePool pool; + return [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieHasAudioAttribute"] boolValue] == YES; +} + bool QT7PlayerSession::isVideoAvailable() const { if (!m_QTMovie) -- cgit v0.12 From b4402915aab8a13ec6a085dd2e3a1e13a59ade98 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Thu, 28 Jan 2010 17:31:52 +1000 Subject: Add size, offset and fillMode properties to QGraphicsVideoItem. From: Andrew den Exter committed 9fb251df to qtmobility/qtm-multimedia --- src/multimedia/base/qgraphicsvideoitem.cpp | 169 +++++++++++++++++++++++---- src/multimedia/base/qgraphicsvideoitem.h | 32 ++++- src/multimedia/base/qpaintervideosurface.cpp | 16 +-- src/multimedia/base/qpaintervideosurface_p.h | 2 +- 4 files changed, 185 insertions(+), 34 deletions(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp index 7fa2e7d..1a5ccd7 100644 --- a/src/multimedia/base/qgraphicsvideoitem.cpp +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -43,15 +43,15 @@ #include #include -#include "qpaintervideosurface_p.h" +#include #include #include - #include QT_BEGIN_NAMESPACE + class QGraphicsVideoItemPrivate { public: @@ -62,6 +62,8 @@ public: , service(0) , outputControl(0) , rendererControl(0) + , aspectRatioMode(Qt::KeepAspectRatio) + , updatePaintDevice(true) { } @@ -72,9 +74,14 @@ public: QMediaService *service; QVideoOutputControl *outputControl; QVideoRendererControl *rendererControl; - QRect boundingRect; + Qt::AspectRatioMode aspectRatioMode; + bool updatePaintDevice; + QRectF rect; + QRectF boundingRect; + QSizeF nativeSize; void clearService(); + void updateBoundingRect(); void _q_present(); void _q_formatChanged(const QVideoSurfaceFormat &format); @@ -99,17 +106,40 @@ void QGraphicsVideoItemPrivate::clearService() } } +void QGraphicsVideoItemPrivate::updateBoundingRect() +{ + q_ptr->prepareGeometryChange(); + + if (nativeSize.isEmpty()) { + boundingRect = QRectF(); + } else { + if (aspectRatioMode == Qt::IgnoreAspectRatio) { + boundingRect = rect; + } else { + QSizeF size = nativeSize; + size.scale(rect.size(), aspectRatioMode); + + boundingRect = QRectF(QPointF(), size); + boundingRect.moveCenter(rect.center()); + } + } +} + void QGraphicsVideoItemPrivate::_q_present() { - q_ptr->update(boundingRect); + if (q_ptr->isObscured()) { + q_ptr->update(boundingRect); + surface->setReady(true); + } else { + q_ptr->update(boundingRect); + } } void QGraphicsVideoItemPrivate::_q_formatChanged(const QVideoSurfaceFormat &format) { - q_ptr->prepareGeometryChange(); + nativeSize = format.sizeHint(); - boundingRect = QRect(QPoint(0, 0), format.sizeHint()); - boundingRect.moveCenter(QPoint(0, 0)); + updateBoundingRect(); } void QGraphicsVideoItemPrivate::_q_serviceDestroyed() @@ -152,22 +182,39 @@ void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed() player->play(); \endcode - \bold {Note}: Only a single display output can be attached to a media object at one time. + \bold {Note}: Only a single display output can be attached to a media + object at one time. \sa QMediaObject, QMediaPlayer, QVideoWidget */ /*! + \enum QGraphicsVideoItem::FillMode + + Enumerates the methods of scaling a video to fit a graphics item. + + \value Stretch The video is stretched to fit the item's size. + \value PreserveAspectFit The video is uniformly scaled to fix the item's + size without cropping. + \value PreserveAspectCrop The video is uniformly scaled to fill the item's + size, cropping if necessary. +*/ + +/*! Constructs a graphics item that displays video. The \a parent is passed to QGraphicsItem. */ QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent) - : QGraphicsItem(parent) + : QGraphicsObject(parent) , d_ptr(new QGraphicsVideoItemPrivate) { d_ptr->q_ptr = this; d_ptr->surface = new QPainterVideoSurface; + + connect(d_ptr->surface, SIGNAL(frameChanged()), this, SLOT(_q_present())); + connect(d_ptr->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), + this, SLOT(_q_formatChanged(QVideoSurfaceFormat))); } /*! @@ -187,7 +234,8 @@ QGraphicsVideoItem::~QGraphicsVideoItem() /*! \property QGraphicsVideoItem::mediaObject - \brief the media object which provides the video displayed by a graphics item. + \brief the media object which provides the video displayed by a graphics + item. */ QMediaObject *QGraphicsVideoItem::mediaObject() const @@ -227,15 +275,6 @@ void QGraphicsVideoItem::setMediaObject(QMediaObject *object) d->service->control(QVideoRendererControl_iid)); if (d->outputControl != 0 && d->rendererControl != 0) { - if (!d->surface) { - d->surface = new QPainterVideoSurface; - - connect(d->surface, SIGNAL(frameChanged()), this, SLOT(_q_present())); - connect(d->surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), - this, SLOT(_q_formatChanged(QVideoSurfaceFormat))); - connect(d->service, SIGNAL(destroyed()), this, SLOT(_q_serviceDestroyed())); - } - d->rendererControl->setSurface(d->surface); if (isVisible()) @@ -246,6 +285,82 @@ void QGraphicsVideoItem::setMediaObject(QMediaObject *object) } /*! + \property QGraphicsVideoItem::aspectRatioMode + \brief how a video is scaled to fit the graphics item's size. +*/ + +Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const +{ + return d_func()->aspectRatioMode; +} + +void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode) +{ + Q_D(QGraphicsVideoItem); + + d->aspectRatioMode = mode; + d->updateBoundingRect(); +} + +/*! + \property QGraphicsVideoItem::offset + \brief the video item's offset. + + QGraphicsVideoItem will draw video using the offset for its top left + corner. +*/ + +QPointF QGraphicsVideoItem::offset() const +{ + return d_func()->rect.topLeft(); +} + +void QGraphicsVideoItem::setOffset(const QPointF &offset) +{ + Q_D(QGraphicsVideoItem); + + d->rect.moveTo(offset); + d->updateBoundingRect(); +} + +/*! + \property QGraphicsVideoItem::size + \brief the video item's size. + + QGraphicsVideoItem will draw video scaled to fit size according to its + fillMode. +*/ + +QSizeF QGraphicsVideoItem::size() const +{ + return d_func()->rect.size(); +} + +void QGraphicsVideoItem::setSize(const QSizeF &size) +{ + Q_D(QGraphicsVideoItem); + + d->rect.setSize(size); + d->updateBoundingRect(); +} + +/*! + \property QGraphicsVideoItem::nativeSize + \brief the native size of the video. +*/ + +QSizeF QGraphicsVideoItem::nativeSize() const +{ + return d_func()->nativeSize; +} + +/*! + \fn QGraphicsVideoItem::nativeSizeChanged(const QSizeF &size) + + Signals that the native \a size of the video has changed. +*/ + +/*! \reimp */ QRectF QGraphicsVideoItem::boundingRect() const @@ -264,10 +379,24 @@ void QGraphicsVideoItem::paint( Q_UNUSED(option); Q_UNUSED(widget); - if (d->surface != 0) { + if (d->surface && d->surface->isActive()) { d->surface->paint(painter, d->boundingRect); d->surface->setReady(true); +#ifndef QGRAPHICSVIDEOITEM_SHADERS // Flickers + } +#else + } else if (d->updatePaintDevice && (painter->paintEngine()->type() == QPaintEngine::OpenGL + || painter->paintEngine()->type() == QPaintEngine::OpenGL2)) { + d->updatePaintDevice = false; + + d->surface->setGLContext(const_cast(QGLContext::currentContext())); + if (d->surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { + d->surface->setShaderType(QPainterVideoSurface::GlslShader); + } else { + d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader); + } } +#endif } /*! diff --git a/src/multimedia/base/qgraphicsvideoitem.h b/src/multimedia/base/qgraphicsvideoitem.h index 0cd5d46..ac215ea 100644 --- a/src/multimedia/base/qgraphicsvideoitem.h +++ b/src/multimedia/base/qgraphicsvideoitem.h @@ -46,32 +46,54 @@ #include + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -QT_MODULE(Multimedia) - class QVideoSurfaceFormat; class QGraphicsVideoItemPrivate; -class Q_MULTIMEDIA_EXPORT QGraphicsVideoItem : public QObject, public QGraphicsItem +class Q_MULTIMEDIA_EXPORT QGraphicsVideoItem : public QGraphicsObject { Q_OBJECT - Q_INTERFACES(QGraphicsItem) Q_PROPERTY(QMediaObject* mediaObject READ mediaObject WRITE setMediaObject) - + Q_PROPERTY(Qt::AspectRatioMode aspectRatioMode READ aspectRatioMode WRITE setAspectRatioMode) + Q_PROPERTY(QPointF offset READ offset WRITE setOffset) + Q_PROPERTY(QSizeF size READ size WRITE setSize) + Q_PROPERTY(QSizeF nativeSize READ nativeSize NOTIFY nativeSizeChanged) public: + enum FillMode + { + Stretch, + PreserveAspectFit, + PreserveAspectCrop + }; + QGraphicsVideoItem(QGraphicsItem *parent = 0); ~QGraphicsVideoItem(); QMediaObject *mediaObject() const; void setMediaObject(QMediaObject *object); + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode mode); + + QPointF offset() const; + void setOffset(const QPointF &offset); + + QSizeF size() const; + void setSize(const QSizeF &size); + + QSizeF nativeSize() const; + QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); +Q_SIGNALS: + void nativeSizeChanged(const QSizeF &size) const; + protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index feeb42f..9953ae8 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -73,7 +73,7 @@ public: virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0; virtual QAbstractVideoSurface::Error paint( - const QRect &target, QPainter *painter, const QRect &source) = 0; + const QRectF &target, QPainter *painter, const QRect &source) = 0; virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0; }; @@ -99,7 +99,7 @@ public: QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); QAbstractVideoSurface::Error paint( - const QRect &target, QPainter *painter, const QRect &source); + const QRectF &target, QPainter *painter, const QRect &source); void updateColors(int brightness, int contrast, int hue, int saturation); @@ -167,7 +167,7 @@ QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::setCurrentFrame(const Q } QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::paint( - const QRect &target, QPainter *painter, const QRect &source) + const QRectF &target, QPainter *painter, const QRect &source) { if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { QImage image( @@ -540,7 +540,7 @@ public: QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); void stop(); - QAbstractVideoSurface::Error paint(const QRect &target, QPainter *painter, const QRect &source); + QAbstractVideoSurface::Error paint(const QRectF &target, QPainter *painter, const QRect &source); private: typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *); @@ -700,7 +700,7 @@ void QVideoSurfaceArbFpPainter::stop() } QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint( - const QRect &target, QPainter *painter, const QRect &source) + const QRectF &target, QPainter *painter, const QRect &source) { if (m_frame.isValid()) { painter->beginNativePainting(); @@ -857,7 +857,7 @@ public: QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); void stop(); - QAbstractVideoSurface::Error paint(const QRect &target, QPainter *painter, const QRect &source); + QAbstractVideoSurface::Error paint(const QRectF &target, QPainter *painter, const QRect &source); private: QGLShaderProgram m_program; @@ -975,7 +975,7 @@ void QVideoSurfaceGlslPainter::stop() } QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( - const QRect &target, QPainter *painter, const QRect &source) + const QRectF &target, QPainter *painter, const QRect &source) { if (m_frame.isValid()) { painter->beginNativePainting(); @@ -1289,7 +1289,7 @@ void QPainterVideoSurface::setReady(bool ready) /*! */ -void QPainterVideoSurface::paint(QPainter *painter, const QRect &rect) +void QPainterVideoSurface::paint(QPainter *painter, const QRectF &rect) { if (!isActive()) { painter->fillRect(rect, QBrush(Qt::black)); diff --git a/src/multimedia/base/qpaintervideosurface_p.h b/src/multimedia/base/qpaintervideosurface_p.h index a7d3e3a..67b514f 100644 --- a/src/multimedia/base/qpaintervideosurface_p.h +++ b/src/multimedia/base/qpaintervideosurface_p.h @@ -102,7 +102,7 @@ public: bool isReady() const; void setReady(bool ready); - void paint(QPainter *painter, const QRect &rect); + void paint(QPainter *painter, const QRectF &rect); #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) const QGLContext *glContext() const; -- cgit v0.12 From 11e4882fdde6efba2b3fef6805801a290ad15fb0 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Thu, 28 Jan 2010 17:34:20 +1000 Subject: Add Audio and Video QML elements. --- src/multimedia/qml/qmetadatacontrolmetaobject.cpp | 234 +++++++++++++ src/multimedia/qml/qmetadatacontrolmetaobject_p.h | 85 +++++ src/multimedia/qml/qml.pri | 12 +- src/multimedia/qml/qmlaudio.cpp | 292 +++++++++++++++++ src/multimedia/qml/qmlaudio_p.h | 162 +++++++++ src/multimedia/qml/qmlgraphicsvideo.cpp | 378 +++++++++++++++++++++ src/multimedia/qml/qmlgraphicsvideo_p.h | 197 +++++++++++ src/multimedia/qml/qmlmediabase.cpp | 379 ++++++++++++++++++++++ 8 files changed, 1737 insertions(+), 2 deletions(-) create mode 100644 src/multimedia/qml/qmetadatacontrolmetaobject.cpp create mode 100644 src/multimedia/qml/qmetadatacontrolmetaobject_p.h create mode 100644 src/multimedia/qml/qmlaudio.cpp create mode 100644 src/multimedia/qml/qmlaudio_p.h create mode 100644 src/multimedia/qml/qmlgraphicsvideo.cpp create mode 100644 src/multimedia/qml/qmlgraphicsvideo_p.h create mode 100644 src/multimedia/qml/qmlmediabase.cpp diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp new file mode 100644 index 0000000..c2b5e78 --- /dev/null +++ b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include /qmetadatacontrol.h> + + +QT_BEGIN_NAMESPACE + +namespace +{ + struct MetaDataKey + { + QtMedia::MetaData key; + const char *name; + }; + + const MetaDataKey qt_metaDataKeys[] = + { + { QtMedia::Title, "title" }, + { QtMedia::SubTitle, "subTitle" }, + { QtMedia::Author, "author" }, + { QtMedia::Comment, "comment" }, + { QtMedia::Description, "description" }, + { QtMedia::Category, "category" }, + { QtMedia::Genre, "genre" }, + { QtMedia::Year, "year" }, + { QtMedia::Date, "date" }, + { QtMedia::UserRating, "userRating" }, + { QtMedia::Keywords, "keywords" }, + { QtMedia::Language, "language" }, + { QtMedia::Publisher, "publisher" }, + { QtMedia::Copyright, "copyright" }, + { QtMedia::ParentalRating, "parentalRating" }, + { QtMedia::RatingOrganisation, "ratingOrganisation" }, + + // Media + { QtMedia::Size, "size" }, + { QtMedia::MediaType, "mediaType" }, + { QtMedia::Duration, "duration" }, + + // Audio + { QtMedia::AudioBitRate, "audioBitRate" }, + { QtMedia::AudioCodec, "audioCodec" }, + { QtMedia::AverageLevel, "averageLevel" }, + { QtMedia::ChannelCount, "channelCount" }, + { QtMedia::PeakValue, "peakValue" }, + { QtMedia::SampleRate, "frequency" }, + + // Music + { QtMedia::AlbumTitle, "albumTitle" }, + { QtMedia::AlbumArtist, "albumArtist" }, + { QtMedia::ContributingArtist, "contributingArtist" }, + { QtMedia::Composer, "composer" }, + { QtMedia::Conductor, "conductor" }, + { QtMedia::Lyrics, "lyrics" }, + { QtMedia::Mood, "mood" }, + { QtMedia::TrackNumber, "trackNumber" }, + { QtMedia::TrackCount, "trackCount" }, + + { QtMedia::CoverArtUrlSmall, "coverArtUrlSmall" }, + { QtMedia::CoverArtUrlLarge, "coverArtUrlLarge" }, + + // Image/Video + { QtMedia::Resolution, "resolution" }, + { QtMedia::PixelAspectRatio, "pixelAspectRatio" }, + + // Video + { QtMedia::VideoFrameRate, "videoFrameRate" }, + { QtMedia::VideoBitRate, "videoBitRate" }, + { QtMedia::VideoCodec, "videoCodec" }, + + { QtMedia::PosterUrl, "posterUrl" }, + + // Movie + { QtMedia::ChapterNumber, "chapterNumber" }, + { QtMedia::Director, "director" }, + { QtMedia::LeadPerformer, "leadPerformer" }, + { QtMedia::Writer, "writer" }, + + // Photos + { QtMedia::CameraManufacturer, "cameraManufacturer" }, + { QtMedia::CameraModel, "cameraModel" }, + { QtMedia::Event, "event" }, + { QtMedia::Subject, "subject" }, + { QtMedia::Orientation, "orientation" }, + { QtMedia::ExposureTime, "exposureTime" }, + { QtMedia::FNumber, "fNumber" }, + { QtMedia::ExposureProgram, "exposureProgram" }, + { QtMedia::ISOSpeedRatings, "isoSpeedRatings" }, + { QtMedia::ExposureBiasValue, "exposureBiasValue" }, + { QtMedia::DateTimeOriginal, "dateTimeOriginal" }, + { QtMedia::DateTimeDigitized, "dateTimeDigitized" }, + { QtMedia::SubjectDistance, "subjectDistance" }, + { QtMedia::MeteringMode, "meteringMode" }, + { QtMedia::LightSource, "lightSource" }, + { QtMedia::Flash, "flash" }, + { QtMedia::FocalLength, "focalLength" }, + { QtMedia::ExposureMode, "exposureMode" }, + { QtMedia::WhiteBalance, "whiteBalance" }, + { QtMedia::DigitalZoomRatio, "digitalZoomRatio" }, + { QtMedia::FocalLengthIn35mmFilm, "focalLengthIn35mmFilm" }, + { QtMedia::SceneCaptureType, "sceneCaptureType" }, + { QtMedia::GainControl, "gainControl" }, + { QtMedia::Contrast, "contrast" }, + { QtMedia::Saturation, "saturation" }, + { QtMedia::Sharpness, "sharpness" }, + { QtMedia::DeviceSettingDescription, "deviceSettingDescription" } + }; +} + +QMetaDataControlMetaObject::QMetaDataControlMetaObject(QMetaDataControl *control, QObject *object) + : m_control(control) + , m_object(object) + , m_mem(0) + , m_propertyOffset(0) + , m_signalOffset(0) +{ + m_builder.setSuperClass(m_object->metaObject()); + m_builder.setClassName(m_object->metaObject()->className()); + m_builder.setFlags(QMetaObjectBuilder::DynamicMetaObject); + + QObjectPrivate *op = QObjectPrivate::get(m_object); + if (op->metaObject) + m_builder.setSuperClass(op->metaObject); + + m_mem = m_builder.toMetaObject(); + *static_cast(this) = *m_mem; + + op->metaObject = this; + m_propertyOffset = propertyOffset(); + m_signalOffset = methodOffset(); +} + +QMetaDataControlMetaObject::~QMetaDataControlMetaObject() +{ + qFree(m_mem); + + QObjectPrivate *op = QObjectPrivate::get(m_object); + op->metaObject = 0; +} + +int QMetaDataControlMetaObject::metaCall(QMetaObject::Call c, int id, void **a) +{ + if (c == QMetaObject::ReadProperty && id >= m_propertyOffset) { + int propId = id - m_propertyOffset; + + *reinterpret_cast(a[0]) = m_control->metaData(m_keys.at(propId)); + + return -1; + } else if (c == QMetaObject::WriteProperty && id >= m_propertyOffset) { + int propId = id - m_propertyOffset; + + m_control->setMetaData(m_keys.at(propId), *reinterpret_cast(a[0])); + + activate(m_object, m_signalOffset + propId, 0); + + return -1; + } else { + return m_object->qt_metacall(c, id, a); + } +} + +int QMetaDataControlMetaObject::createProperty(const char *name, const char *) +{ + const int count = sizeof(qt_metaDataKeys) / sizeof(MetaDataKey); + + for (int i = 0; i < count; ++i) { + if (qstrcmp(name, qt_metaDataKeys[i].name) == 0) { + int id = m_keys.count(); + m_keys.append(qt_metaDataKeys[i].key); + + m_builder.addSignal("__" + QByteArray::number(id) + "()"); + + QMetaPropertyBuilder build = m_builder.addProperty(name, "QVariant", id); + build.setDynamic(true); + + qFree(m_mem); + m_mem = m_builder.toMetaObject(); + *static_cast(this) = *m_mem; + + return m_propertyOffset + id; + } + } + + return -1; +} + +void QMetaDataControlMetaObject::metaDataChanged() +{ + for (int i = 0; i < m_keys.count(); ++i) + activate(m_object, m_signalOffset + i, 0); +} + +QT_END_NAMESPACE diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject_p.h b/src/multimedia/qml/qmetadatacontrolmetaobject_p.h new file mode 100644 index 0000000..b7f88fe --- /dev/null +++ b/src/multimedia/qml/qmetadatacontrolmetaobject_p.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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMETADATACONTROLMETAOBJECT_P_H +#define QMETADATACONTROLMETAOJBECT_P_H + +#include + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMetaDataControl; + +class QMetaDataControlMetaObject : public QAbstractDynamicMetaObject +{ +public: + QMetaDataControlMetaObject(QMetaDataControl *control, QObject *object); + ~QMetaDataControlMetaObject(); + + int metaCall(QMetaObject::Call call, int _id, void **arguments); + int createProperty(const char *, const char *); + + void metaDataChanged(); + +private: + QMetaDataControl *m_control; + QObject *m_object; + QMetaObject *m_mem; + + int m_propertyOffset; + int m_signalOffset; + + QVector m_keys; + QMetaObjectBuilder m_builder; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/multimedia/qml/qml.pri b/src/multimedia/qml/qml.pri index adfcc23..6b44e0c 100644 --- a/src/multimedia/qml/qml.pri +++ b/src/multimedia/qml/qml.pri @@ -3,9 +3,17 @@ contains(QT_CONFIG, declarative) { QT += declarative HEADERS += \ - $$PWD/qmlsound_p.h + $$PWD/qmlsound_p.h \ + $$PWD/qmetadatacontrolmetaobject_p.h \ + $$PWD/qmlaudio_p.h \ + $$PWD/qmlgraphicsvideo_p.h \ + $$PWD/qmlmediabase_p.h SOURCES += \ - $$PWD/qmlsound.cpp + $$PWD/qmlsound.cpp \ + $$PWD/qmetadatacontrolmetaobject.cpp \ + $$PWD/qmlaudio.cpp \ + $$PWD/qmlgraphicsvideo.cpp \ + $$PWD/qmlmediabase.cpp } diff --git a/src/multimedia/qml/qmlaudio.cpp b/src/multimedia/qml/qmlaudio.cpp new file mode 100644 index 0000000..713e36a --- /dev/null +++ b/src/multimedia/qml/qmlaudio.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlaudio_p.h" + +#include + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt,4,6,Audio,QmlAudio); + +/*! + \qmlclass Audio QmlAudio + \brief The Audio element allows you to add audio to a scene. +*/ + +/*! + \internal + \class QmlAudio + \brief The QmlAudio class provides a audio item that you can add to a QmlView. +*/ + +void QmlAudio::_q_error(QMediaPlayer::Error errorCode, const QString &errorString) +{ + m_error = errorCode; + m_errorString = errorString; + + emit error(Error(errorCode), errorString); + emit errorChanged(); +} + + +QmlAudio::QmlAudio(QObject *parent) + : QObject(parent) +{ + setObject(this); +} + +QmlAudio::~QmlAudio() +{ + shutdown(); +} + +/*! + \qmlmethod Audio::play() + + Starts playback of the audio. +*/ + +void QmlAudio::play() +{ + m_playerControl->play(); +} + +/*! + \qmlmethod Audio::pause() + + Pauses playback of the audio. +*/ + +void QmlAudio::pause() +{ + m_playerControl->pause(); +} + +/*! + \qmlmethod Audio::stop() + + Stops playback of the audio. +*/ + +void QmlAudio::stop() +{ + m_playerControl->stop(); +} + +/*! + \qmlproperty url Audio::source + + This property holds the source URL of the audio. +*/ + +/*! + \qmlproperty bool Audio::playing + + This property holds whether the audio is playing. +*/ + +/*! + \qmlproperty bool Audio::paused + + This property holds whether the audio is paused. +*/ + +/*! + \qmlsignal Audio::onStarted() + + This handler is called when playback is started. +*/ + +/*! + \qmlsignal Audio::onResumed() + + This handler is called when playback is resumed from the paused state. +*/ + +/*! + \qmlsignal Audio::onPaused() + + This handler is called when playback is paused. +*/ + +/*! + \qmlsignal Audio::onStopped() + + This handler is called when playback is stopped. +*/ + +/*! + \qmlproperty enum Audio::status + + This property holds the status of audio loading. It can be one of: + + \list + \o NoMedia - no audio has been set. + \o Loading - the audio is currently being loaded. + \o Loaded - the audio has been loaded. + \o Buffering - the audio is buffering data. + \o Stalled - playback has been interrupted while the audio is buffering data. + \o Buffered - the audio has buffered data. + \o EndOfMedia - the audio has played to the end. + \o InvalidMedia - the audio cannot be played. + \o UnknownStatus - the status of the audio is unknown. + \endlist +*/ + +QmlAudio::Status QmlAudio::status() const +{ + return Status(m_status); +} + +/*! + \qmlsignal Audio::onLoaded() + + This handler is called when the video source has been loaded. +*/ + +/*! + \qmlsignal Audio::onBuffering() + + This handler is called when the video stream starts buffering. +*/ + +/*! + \qmlsignal Audio::onStalled() + + This handler is called when playback has stalled while the video stream buffers. +*/ + +/*! + \qmlsignal Audio::onBuffered() + + This handler is called when the video stream has finished buffering. +*/ + +/*! + \qmlsignal Audio::onEndOfMedia + + This handler is called when playback stops because end of the video has been reached. +*/ +/*! + \qmlproperty int Audio::duration + + This property holds the duration of the audio in milliseconds. + + If the audio doesn't have a fixed duration (a live stream for example) this will be 0. +*/ + +/*! + \qmlproperty int Audio::position + + This property holds the current playback position in milliseconds. +*/ + +/*! + \qmlproperty qreal Audio::volume + + This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume). +*/ + +/*! + \qmlproperty bool Audio::muted + + This property holds whether the audio output is muted. +*/ + +/*! + \qmlproperty qreal Audio::bufferProgress + + This property holds how much of the data buffer is currently filled, from 0.0 (empty) to 1.0 + (full). +*/ + +/*! + \qmlproperty bool Audio::seekable + + This property holds whether position of the audio can be changed. +*/ + +/*! + \qmlproperty qreal playbackRate + + This property holds the rate at which audio is played at as a multiple of the normal rate. +*/ + +/*! + \qmlproperty enum Audio::error + + This property holds the error state of the audio. It can be one of: + + \list + \o NoError - there is no current error. + \o ResourceError - the audio cannot be played due to a problem allocating resources. + \o FormatError - the audio format is not supported. + \o NetworkError - the audio cannot be played due to network issues. + \o AccessDenied - the audio cannot be played due to insufficient permissions. + \o ServiceMissing - the audio cannot be played because the media service could not be + instantiated. + \endlist +*/ + +QmlAudio::Error QmlAudio::error() const +{ + return Error(m_error); +} + +/*! + \qmlproperty string Audio::errorString + + This property holds a string describing the current error condition in more detail. +*/ + +/*! + \qmlproperty Audio::onError(error, errorString) + + This property is called when an \l {Error}{error} has occurred. The errorString parameter + may contain more detailed information about the error. +*/ + +QT_END_NAMESPACE + +#include "moc_qmlaudio_p.cpp" + + diff --git a/src/multimedia/qml/qmlaudio_p.h b/src/multimedia/qml/qmlaudio_p.h new file mode 100644 index 0000000..c6ab53d --- /dev/null +++ b/src/multimedia/qml/qmlaudio_p.h @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLAUDIO_P_H +#define QMLAUDIO_P_H + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QTimerEvent; + +class QmlAudio : public QObject, public QmlMediaBase, public QmlParserStatus +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged) + Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(int duration READ duration NOTIFY durationChanged) + Q_PROPERTY(int position READ position WRITE setPosition NOTIFY positionChanged) + Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged) + Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) + Q_PROPERTY(int bufferProgress READ bufferProgress NOTIFY bufferProgressChanged) + Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged) + Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged) + Q_PROPERTY(Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_ENUMS(Status) + Q_ENUMS(Error) + Q_INTERFACES(QmlParserStatus) +public: + enum Status + { + UnknownStatus = QMediaPlayer::UnknownMediaStatus, + NoMedia = QMediaPlayer::NoMedia, + Loading = QMediaPlayer::LoadingMedia, + Loaded = QMediaPlayer::LoadedMedia, + Stalled = QMediaPlayer::StalledMedia, + Buffering = QMediaPlayer::BufferingMedia, + Buffered = QMediaPlayer::BufferedMedia, + EndOfMedia = QMediaPlayer::EndOfMedia, + InvalidMedia = QMediaPlayer::InvalidMedia + }; + + enum Error + { + NoError = QMediaPlayer::NoError, + ResourceError = QMediaPlayer::ResourceError, + FormatError = QMediaPlayer::FormatError, + NetworkError = QMediaPlayer::NetworkError, + AccessDenied = QMediaPlayer::AccessDeniedError, + ServiceMissing = QMediaPlayer::ServiceMissingError + }; + + QmlAudio(QObject *parent = 0); + ~QmlAudio(); + + Status status() const; + Error error() const; + +public Q_SLOTS: + void play(); + void pause(); + void stop(); + +Q_SIGNALS: + void sourceChanged(); + + void playingChanged(); + void pausedChanged(); + + void started(); + void resumed(); + void paused(); + void stopped(); + + void statusChanged(); + + void loaded(); + void buffering(); + void stalled(); + void buffered(); + void endOfMedia(); + + void durationChanged(); + void positionChanged(); + + void volumeChanged(); + void mutedChanged(); + + void bufferProgressChanged(); + + void seekableChanged(); + void playbackRateChanged(); + + void errorChanged(); + void error(QmlAudio::Error error, const QString &errorString); + +private Q_SLOTS: + void _q_error(QMediaPlayer::Error, const QString &); + +private: + Q_DISABLE_COPY(QmlAudio) + Q_PRIVATE_SLOT(mediaBase(), void _q_stateChanged(QMediaPlayer::State)) + Q_PRIVATE_SLOT(mediaBase(), void _q_mediaStatusChanged(QMediaPlayer::MediaStatus)) + Q_PRIVATE_SLOT(mediaBase(), void _q_metaDataChanged()) + + inline QmlMediaBase *mediaBase() { return this; } +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QmlAudio)) + +QT_END_HEADER + +#endif diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp new file mode 100644 index 0000000..c96f7e9 --- /dev/null +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlgraphicsvideo_p.h" + +#include +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +QML_DEFINE_TYPE(Qt,4,6,Video,QmlGraphicsVideo); + + +void QmlGraphicsVideo::_q_nativeSizeChanged(const QSizeF &size) +{ + setImplicitWidth(size.width()); + setImplicitHeight(size.height()); +} + +void QmlGraphicsVideo::_q_error(QMediaPlayer::Error errorCode, const QString &errorString) +{ + m_error = errorCode; + m_errorString = errorString; + + emit error(Error(errorCode), errorString); + emit errorChanged(); +} + + +/*! + \qmlclass Video QmlGraphicsVideo + \brief The Video element allows you to add videos to a scene. + \inherits Item +*/ + +/*! + \internal + \class QmlGraphicsVideo + \brief The QmlGraphicsVideo class provides a video item that you can add to a QmlView. +*/ + +QmlGraphicsVideo::QmlGraphicsVideo(QmlGraphicsItem *parent) + : QmlGraphicsItem(parent) + , m_graphicsItem(0) + , m_fillMode(QmlGraphicsVideo::PreserveAspectFit) + +{ + m_graphicsItem = new QGraphicsVideoItem(this); + connect(m_graphicsItem, SIGNAL(nativeSizeChanged(QSizeF)), + this, SLOT(_q_nativeSizeChanged(QSizeF))); + + setObject(this); + + if (m_mediaService) { + connect(m_playerControl, SIGNAL(audioAvailableChanged(bool)), + this, SIGNAL(hasAudioChanged())); + connect(m_playerControl, SIGNAL(videoAvailableChanged(bool)), + this, SIGNAL(hasVideoChanged())); + + m_graphicsItem->setMediaObject(m_mediaObject); + } +} + +QmlGraphicsVideo::~QmlGraphicsVideo() +{ + shutdown(); + + delete m_graphicsItem; +} + +/*! + \qmlproperty url Video::source + + This property holds the source URL of the video. +*/ + +/*! + \qmlproperty bool Video::playing + + This property holds whether the video is playing. +*/ + +/*! + \qmlproperty bool Video::paused + + This property holds whether the video is paused. +*/ + +/*! + \qmlsignal Video::onStarted() + + This handler is called when playback is started. +*/ + +/*! + \qmlsignal Video::onResumed() + + This handler is called when playback is resumed from the paused state. +*/ + +/*! + \qmlsignal Video::onPaused() + + This handler is called when playback is paused. +*/ + +/*! + \qmlsignal Video::onStopped() + + This handler is called when playback is stopped. +*/ + +/*! + \qmlproperty enum Video::status + + This property holds the status of video loading. It can be one of: + + \list + \o NoMedia - no video has been set. + \o Loading - the video is currently being loaded. + \o Loaded - the video has been loaded. + \o Buffering - the video is buffering data. + \o Stalled - playback has been interrupted while the video is buffering data. + \o Buffered - the video has buffered data. + \o EndOfMedia - the video has played to the end. + \o InvalidMedia - the video cannot be played. + \o UnknownStatus - the status of the video is unknown. + \endlist +*/ + +QmlGraphicsVideo::Status QmlGraphicsVideo::status() const +{ + return Status(m_status); +} + +/*! + \qmlsignal Video::onLoaded() + + This handler is called when the video source has been loaded. +*/ + +/*! + \qmlsignal Video::onBuffering() + + This handler is called when the video stream starts buffering. +*/ + +/*! + \qmlsignal Video::onStalled() + + This handler is called when playback has stalled while the video stream buffers. +*/ + +/*! + \qmlsignal Video::onBuffered() + + This handler is called when the video stream has finished buffering. +*/ + +/*! + \qmlsignal Video::onEndOfMedia + + This handler is called when playback stops because end of the video has been reached. +*/ + +/*! + \qmlproperty int Video::duration + + This property holds the duration of the video in milliseconds. + + If the video doesn't have a fixed duration (a live stream for example) this will be 0. +*/ + +/*! + \qmlproperty int Video::position + + This property holds the current playback position in milliseconds. +*/ + +/*! + \qmlproperty qreal Video::volume + + This property holds the volume of the audio output, from 0.0 (silent) to 1.0 (maximum volume). +*/ + +/*! + \qmlproperty bool Video::muted + + This property holds whether the audio output is muted. +*/ + +/*! + \qmlproperty bool Audio::hasAudio + + This property holds whether the source contains audio. +*/ + +bool QmlGraphicsVideo::hasAudio() const +{ + return m_playerControl->isAudioAvailable(); +} + +/*! + \qmlproperty bool Video::hasVideo + + This property holds whether the source contains video. +*/ + +bool QmlGraphicsVideo::hasVideo() const +{ + return m_playerControl->isVideoAvailable(); +} + +/*! + \qmlproperty qreal Video::bufferProgress + + This property holds how much of the data buffer is currently filled, from 0.0 (empty) to 1.0 + (full). +*/ + +/*! + \qmlproperty bool Video::seekable + + This property holds whether position of the video can be changed. +*/ + +/*! + \qmlproperty qreal playbackRate + + This property holds the rate at which video is played at as a multiple of the normal rate. +*/ + +/*! + \qmlproperty enum Video::error + + This property holds the error state of the video. It can be one of: + + \list + \o NoError - there is no current error. + \o ResourceError - the video cannot be played due to a problem allocating resources. + \o FormatError - the video format is not supported. + \o NetworkError - the video cannot be played due to network issues. + \o AccessDenied - the video cannot be played due to insufficient permissions. + \o ServiceMissing - the video cannot be played because the media service could not be + instantiated. + \endlist +*/ + + +QmlGraphicsVideo::Error QmlGraphicsVideo::error() const +{ + return Error(m_error); +} + +/*! + \qmlproperty string Video::errorString + + This property holds a string describing the current error condition in more detail. +*/ + +/*! + \qmlproperty Video::onError(error, errorString) + + This property is called when an \l {Error}{error} has occurred. The errorString parameter + may contain more detailed information about the error. +*/ + +/*! + \qmlproperty enum Video::FillMode + + Set this property to define how the video is scaled to fit the target area. + + \list + \o Stretch - the video is scaled to fit. + \o PreserveAspectFit - the video is scaled uniformly to fit without cropping + \o PreserveAspectCrop - the video is scaled uniformly to fill, cropping if necessary + \endlist +*/ + +QmlGraphicsVideo::FillMode QmlGraphicsVideo::fillMode() const +{ + return FillMode(m_graphicsItem->aspectRatioMode()); +} + +void QmlGraphicsVideo::setFillMode(FillMode mode) +{ + m_graphicsItem->setAspectRatioMode(Qt::AspectRatioMode(mode)); +} + +/*! + \qmlmethod Video::play() + + Starts playback of the video. +*/ + +void QmlGraphicsVideo::play() +{ + m_playerControl->play(); +} + +/*! + \qmlmethod Video::pause() + + Pauses playback of the video. +*/ + +void QmlGraphicsVideo::pause() +{ + m_playerControl->pause(); +} + +/*! + \qmlmethod Video::stop() + + Stops playback of the video. +*/ + +void QmlGraphicsVideo::stop() +{ + m_playerControl->stop(); +} + +void QmlGraphicsVideo::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) +{ +} + +void QmlGraphicsVideo::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + m_graphicsItem->setSize(newGeometry.size()); + + QmlGraphicsItem::geometryChanged(newGeometry, oldGeometry); +} + +QT_END_NAMESPACE + +#include "moc_qmlgraphicsvideo_p.cpp" diff --git a/src/multimedia/qml/qmlgraphicsvideo_p.h b/src/multimedia/qml/qmlgraphicsvideo_p.h new file mode 100644 index 0000000..d89de8c --- /dev/null +++ b/src/multimedia/qml/qmlgraphicsvideo_p.h @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLGRAPHICSVIDEO_H +#define QMLGRAPHICSVIDEO_H + +#include + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QTimerEvent; +class QVideoSurfaceFormat; + + +class QmlGraphicsVideo : public QmlGraphicsItem, public QmlMediaBase +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(bool playing READ isPlaying WRITE setPlaying NOTIFY playingChanged) + Q_PROPERTY(bool paused READ isPaused WRITE setPaused NOTIFY pausedChanged) + Q_PROPERTY(Status status READ status NOTIFY statusChanged) + Q_PROPERTY(int duration READ duration NOTIFY durationChanged) + Q_PROPERTY(int position READ position WRITE setPosition NOTIFY positionChanged) + Q_PROPERTY(qreal volume READ volume WRITE setVolume NOTIFY volumeChanged) + Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) + Q_PROPERTY(bool hasAudio READ hasAudio NOTIFY hasAudioChanged) + Q_PROPERTY(bool hasVideo READ hasVideo NOTIFY hasVideoChanged) + Q_PROPERTY(int bufferProgress READ bufferProgress NOTIFY bufferProgressChanged) + Q_PROPERTY(bool seekable READ isSeekable NOTIFY seekableChanged) + Q_PROPERTY(qreal playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged) + Q_PROPERTY(Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(FillMode fillMode READ fillMode WRITE setFillMode) + Q_ENUMS(FillMode) + Q_ENUMS(Status) + Q_ENUMS(Error) +public: + enum FillMode + { + Stretch = Qt::IgnoreAspectRatio, + PreserveAspectFit = Qt::KeepAspectRatio, + PreserveAspectCrop = Qt::KeepAspectRatioByExpanding + }; + + enum Status + { + UnknownStatus = QMediaPlayer::UnknownMediaStatus, + NoMedia = QMediaPlayer::NoMedia, + Loading = QMediaPlayer::LoadingMedia, + Loaded = QMediaPlayer::LoadedMedia, + Stalled = QMediaPlayer::StalledMedia, + Buffering = QMediaPlayer::BufferingMedia, + Buffered = QMediaPlayer::BufferedMedia, + EndOfMedia = QMediaPlayer::EndOfMedia, + InvalidMedia = QMediaPlayer::InvalidMedia + }; + + enum Error + { + NoError = QMediaPlayer::NoError, + ResourceError = QMediaPlayer::ResourceError, + FormatError = QMediaPlayer::FormatError, + NetworkError = QMediaPlayer::NetworkError, + AccessDenied = QMediaPlayer::AccessDeniedError, + ServiceMissing = QMediaPlayer::ServiceMissingError + }; + + QmlGraphicsVideo(QmlGraphicsItem *parent = 0); + ~QmlGraphicsVideo(); + + bool hasAudio() const; + bool hasVideo() const; + + FillMode fillMode() const; + void setFillMode(FillMode mode); + + Status status() const; + Error error() const; + + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + +public Q_SLOTS: + void play(); + void pause(); + void stop(); + +Q_SIGNALS: + void sourceChanged(); + + void playingChanged(); + void pausedChanged(); + + void started(); + void resumed(); + void paused(); + void stopped(); + + void statusChanged(); + + void loaded(); + void buffering(); + void stalled(); + void buffered(); + void endOfMedia(); + + void durationChanged(); + void positionChanged(); + + void volumeChanged(); + void mutedChanged(); + void hasAudioChanged(); + void hasVideoChanged(); + + void bufferProgressChanged(); + + void seekableChanged(); + void playbackRateChanged(); + + void errorChanged(); + void error(QmlGraphicsVideo::Error error, const QString &errorString); + +protected: + void geometryChanged(const QRectF &geometry, const QRectF &); + +private Q_SLOTS: + void _q_nativeSizeChanged(const QSizeF &size); + void _q_error(QMediaPlayer::Error, const QString &); + +private: + Q_DISABLE_COPY(QmlGraphicsVideo) + + QGraphicsVideoItem *m_graphicsItem; + + FillMode m_fillMode; + QRectF m_scaledRect; + bool m_updatePaintDevice; + + Q_PRIVATE_SLOT(mediaBase(), void _q_stateChanged(QMediaPlayer::State)) + Q_PRIVATE_SLOT(mediaBase(), void _q_mediaStatusChanged(QMediaPlayer::MediaStatus)) + Q_PRIVATE_SLOT(mediaBase(), void _q_metaDataChanged()) + + inline QmlMediaBase *mediaBase() { return this; } +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QmlGraphicsVideo)) + +QT_END_HEADER + +#endif diff --git a/src/multimedia/qml/qmlmediabase.cpp b/src/multimedia/qml/qmlmediabase.cpp new file mode 100644 index 0000000..0f0f1e4 --- /dev/null +++ b/src/multimedia/qml/qmlmediabase.cpp @@ -0,0 +1,379 @@ +/**************************************************************************** +** +** 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 QtMultimedia module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "QtMultimedia/private/qmlmediabase_p.h" + +#include +#include + +#include +#include +#include +#include +#include + + + +QT_BEGIN_NAMESPACE + + +class QmlMediaBaseObject : public QMediaObject +{ +public: + QmlMediaBaseObject(QMediaService *service) + : QMediaObject(0, service) + { + } +}; + +class QmlMediaBasePlayerControl : public QMediaPlayerControl +{ +public: + QmlMediaBasePlayerControl(QObject *parent) + : QMediaPlayerControl(parent) + { + } + + QMediaPlayer::State state() const { return QMediaPlayer::StoppedState; } + QMediaPlayer::MediaStatus mediaStatus() const { return QMediaPlayer::NoMedia; } + + qint64 duration() const { return 0; } + qint64 position() const { return 0; } + void setPosition(qint64) {} + int volume() const { return 100; } + void setVolume(int) {} + bool isMuted() const { return false; } + void setMuted(bool) {} + int bufferStatus() const { return 0; } + bool isAudioAvailable() const { return false; } + bool isVideoAvailable() const { return false; } + bool isSeekable() const { return false; } + QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); } + qreal playbackRate() const { return 1; } + void setPlaybackRate(qreal) {} + QMediaContent media() const { return QMediaContent(); } + const QIODevice *mediaStream() const { return 0; } + void setMedia(const QMediaContent &, QIODevice *) {} + + void play() {} + void pause() {} + void stop() {} +}; + +class QmlMediaBaseAnimation : public QObject +{ +public: + QmlMediaBaseAnimation(QmlMediaBase *media) + : m_media(media) + { + } + + void start() { if (!m_timer.isActive()) m_timer.start(500, this); } + void stop() { m_timer.stop(); } + +protected: + void timerEvent(QTimerEvent *event) + { + if (event->timerId() == m_timer.timerId()) { + event->accept(); + + if (m_media->m_state == QMediaPlayer::PlayingState) + emit m_media->positionChanged(); + if (m_media->m_status == QMediaPlayer::BufferingMedia || QMediaPlayer::StalledMedia) + emit m_media->bufferProgressChanged(); + } else { + QObject::timerEvent(event); + } + } + +private: + QmlMediaBase *m_media; + QBasicTimer m_timer; +}; + +void QmlMediaBase::_q_stateChanged(QMediaPlayer::State state) +{ + if (state != m_state) { + QMediaPlayer::State oldState = state; + + m_state = state; + + switch (state) { + case QMediaPlayer::PlayingState: + if (oldState == QMediaPlayer::StoppedState) + emit started(); + else if (oldState == QMediaPlayer::PausedState) + emit resumed(); + break; + case QMediaPlayer::PausedState: + emit paused(); + case QMediaPlayer::StoppedState: + emit stopped(); + break; + default: + break; + } + + emit playingChanged(); + emit pausedChanged(); + + if (m_state == QMediaPlayer::PlayingState + || m_status == QMediaPlayer::BufferingMedia + || m_status == QMediaPlayer::StalledMedia) { + m_animation->start(); + } else { + m_animation->stop(); + } + } +} + +void QmlMediaBase::_q_mediaStatusChanged(QMediaPlayer::MediaStatus status) +{ + if (status != m_status) { + m_status = status; + + switch (status) { + case QMediaPlayer::LoadedMedia: + emit loaded(); + break; + case QMediaPlayer::BufferingMedia: + emit buffering(); + break; + case QMediaPlayer::BufferedMedia: + emit buffered(); + break; + case QMediaPlayer::StalledMedia: + emit stalled(); + break; + case QMediaPlayer::EndOfMedia: + emit endOfMedia(); + break; + default: + break; + } + + emit statusChanged(); + + if (m_state == QMediaPlayer::PlayingState + || m_status == QMediaPlayer::BufferingMedia + || m_status == QMediaPlayer::StalledMedia) { + m_animation->start(); + } else { + m_animation->stop(); + } + } +} + +void QmlMediaBase::_q_metaDataChanged() +{ + m_metaObject->metaDataChanged(); +} + +QmlMediaBase::QmlMediaBase() + : m_mediaService(0) + , m_playerControl(0) + , m_mediaObject(0) + , m_mediaProvider(0) + , m_metaDataControl(0) + , m_metaObject(0) + , m_animation(0) + , m_state(QMediaPlayer::StoppedState) + , m_status(QMediaPlayer::NoMedia) + , m_error(QMediaPlayer::NoError) +{ +} + +QmlMediaBase::~QmlMediaBase() +{ +} + +void QmlMediaBase::shutdown() +{ + delete m_metaObject; + delete m_mediaObject; + + if (m_mediaProvider) + m_mediaProvider->releaseService(m_mediaService); + + delete m_animation; + +} + +void QmlMediaBase::setObject(QObject *object) +{ + if ((m_mediaProvider = QMediaServiceProvider::defaultServiceProvider())) { + if ((m_mediaService = m_mediaProvider->requestService(Q_MEDIASERVICE_MEDIAPLAYER))) { + m_playerControl = qobject_cast( + m_mediaService->control(QMediaPlayerControl_iid)); + m_metaDataControl = qobject_cast( + m_mediaService->control(QMetaDataControl_iid)); + m_mediaObject = new QmlMediaBaseObject(m_mediaService); + } + } + + if (m_playerControl) { + QObject::connect(m_playerControl, SIGNAL(stateChanged(QMediaPlayer::State)), + object, SLOT(_q_stateChanged(QMediaPlayer::State))); + QObject::connect(m_playerControl, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + object, SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus))); + QObject::connect(m_playerControl, SIGNAL(mediaChanged(QMediaContent)), + object, SIGNAL(sourceChanged())); + QObject::connect(m_playerControl, SIGNAL(durationChanged(qint64)), + object, SIGNAL(durationChanged())); + QObject::connect(m_playerControl, SIGNAL(positionChanged(qint64)), + object, SIGNAL(positionChanged())); + QObject::connect(m_playerControl, SIGNAL(volumeChanged(int)), + object, SIGNAL(volumeChanged())); + QObject::connect(m_playerControl, SIGNAL(mutedChanged(bool)), + object, SIGNAL(mutedChanged())); + + m_animation = new QmlMediaBaseAnimation(this); + } else { + m_playerControl = new QmlMediaBasePlayerControl(object); + } + + if (m_metaDataControl) { + m_metaObject = new QMetaDataControlMetaObject(m_metaDataControl, object); + + QObject::connect(m_metaDataControl, SIGNAL(metaDataChanged()), + object, SLOT(_q_metaDataChanged())); + } +} + +QUrl QmlMediaBase::source() const +{ + return m_playerControl->media().canonicalUrl(); +} + +void QmlMediaBase::setSource(const QUrl &url) +{ + m_playerControl->setMedia(QMediaContent(url), 0); +} + +bool QmlMediaBase::isPlaying() const +{ + return m_state != QMediaPlayer::StoppedState; +} + +void QmlMediaBase::setPlaying(bool playing) +{ + if (playing && m_state == QMediaPlayer::StoppedState) + m_playerControl->play(); + else if (!playing) + m_playerControl->stop(); +} + +bool QmlMediaBase::isPaused() const +{ + return m_state == QMediaPlayer::PausedState; +} + +void QmlMediaBase::setPaused(bool paused) +{ + if (paused && m_state == QMediaPlayer::PlayingState) + m_playerControl->pause(); + if (!paused && m_state == QMediaPlayer::PausedState) + m_playerControl->play(); +} + +int QmlMediaBase::duration() const +{ + return m_playerControl->duration(); +} + +int QmlMediaBase::position() const +{ + return m_playerControl->position(); + +} + +void QmlMediaBase::setPosition(int position) +{ + m_playerControl->setPosition(position); +} + +qreal QmlMediaBase::volume() const +{ + return qreal(m_playerControl->volume()) / 100; +} + +void QmlMediaBase::setVolume(qreal volume) +{ + m_playerControl->setVolume(volume * 100); +} + +bool QmlMediaBase::isMuted() const +{ + return m_playerControl->isMuted(); +} + +void QmlMediaBase::setMuted(bool muted) +{ + m_playerControl->setMuted(muted); +} + +qreal QmlMediaBase::bufferProgress() const +{ + return qreal(m_playerControl->bufferStatus()) / 100; +} + +bool QmlMediaBase::isSeekable() const +{ + return m_playerControl->isSeekable(); +} + +qreal QmlMediaBase::playbackRate() const +{ + return m_playerControl->playbackRate(); +} + +void QmlMediaBase::setPlaybackRate(qreal rate) +{ + m_playerControl->setPlaybackRate(rate); +} + +QString QmlMediaBase::errorString() const +{ + return m_errorString; +} + +QT_END_NAMESPACE + -- cgit v0.12 From 7123ef04484f283ffa30ece8cb73f541bd81e830 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Thu, 28 Jan 2010 17:35:17 +1000 Subject: Multimedia; Add directshow backend --- .../mediaservices/directshow/directshow.pro | 14 + .../mediaservices/directshow/dsserviceplugin.cpp | 189 +++ .../mediaservices/directshow/dsserviceplugin.h | 77 ++ .../mediaplayer/directshowaudioendpointcontrol.cpp | 147 +++ .../mediaplayer/directshowaudioendpointcontrol.h | 90 ++ .../directshow/mediaplayer/directshoweventloop.cpp | 160 +++ .../directshow/mediaplayer/directshoweventloop.h | 83 ++ .../directshow/mediaplayer/directshowglobal.h | 78 ++ .../directshow/mediaplayer/directshowioreader.cpp | 501 ++++++++ .../directshow/mediaplayer/directshowioreader.h | 126 ++ .../directshow/mediaplayer/directshowiosource.cpp | 603 ++++++++++ .../directshow/mediaplayer/directshowiosource.h | 145 +++ .../directshow/mediaplayer/directshowmediatype.cpp | 158 +++ .../directshow/mediaplayer/directshowmediatype.h | 85 ++ .../mediaplayer/directshowmediatypelist.cpp | 229 ++++ .../mediaplayer/directshowmediatypelist.h | 78 ++ .../mediaplayer/directshowmetadatacontrol.cpp | 351 ++++++ .../mediaplayer/directshowmetadatacontrol.h | 98 ++ .../directshow/mediaplayer/directshowpinenum.cpp | 140 +++ .../directshow/mediaplayer/directshowpinenum.h | 81 ++ .../mediaplayer/directshowplayercontrol.cpp | 369 ++++++ .../mediaplayer/directshowplayercontrol.h | 147 +++ .../mediaplayer/directshowplayerservice.cpp | 1235 ++++++++++++++++++++ .../mediaplayer/directshowplayerservice.h | 208 ++++ .../mediaplayer/directshowsamplescheduler.cpp | 394 +++++++ .../mediaplayer/directshowsamplescheduler.h | 126 ++ .../mediaplayer/directshowvideooutputcontrol.cpp | 87 ++ .../mediaplayer/directshowvideooutputcontrol.h | 75 ++ .../mediaplayer/directshowvideorenderercontrol.cpp | 93 ++ .../mediaplayer/directshowvideorenderercontrol.h | 82 ++ .../directshow/mediaplayer/mediaplayer.pri | 43 + .../mediaplayer/mediasamplevideobuffer.cpp | 91 ++ .../mediaplayer/mediasamplevideobuffer.h | 77 ++ .../directshow/mediaplayer/videosurfacefilter.cpp | 600 ++++++++++ .../directshow/mediaplayer/videosurfacefilter.h | 182 +++ .../mediaplayer/vmr9videowindowcontrol.cpp | 308 +++++ .../mediaplayer/vmr9videowindowcontrol.h | 112 ++ src/plugins/mediaservices/mediaservices.pro | 2 + 38 files changed, 7664 insertions(+) create mode 100644 src/plugins/mediaservices/directshow/directshow.pro create mode 100644 src/plugins/mediaservices/directshow/dsserviceplugin.cpp create mode 100644 src/plugins/mediaservices/directshow/dsserviceplugin.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowglobal.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.h create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp create mode 100644 src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.h diff --git a/src/plugins/mediaservices/directshow/directshow.pro b/src/plugins/mediaservices/directshow/directshow.pro new file mode 100644 index 0000000..a3080d3 --- /dev/null +++ b/src/plugins/mediaservices/directshow/directshow.pro @@ -0,0 +1,14 @@ +TARGET = dsengine +include(../../qpluginbase.pri) + +QT += multimedia + +HEADERS += dsserviceplugin.h +SOURCES += dsserviceplugin.cpp + +include(mediaplayer/mediaplayer.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/mediaservices +target.path = $$[QT_INSTALL_PLUGINS]/plugins/mediaservices +INSTALLS += target + diff --git a/src/plugins/mediaservices/directshow/dsserviceplugin.cpp b/src/plugins/mediaservices/directshow/dsserviceplugin.cpp new file mode 100644 index 0000000..fc5d11f --- /dev/null +++ b/src/plugins/mediaservices/directshow/dsserviceplugin.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "dsserviceplugin.h" + +#ifdef QMEDIA_DIRECTSHOW_CAMERA +#include "dscameraservice.h" +#endif + +#ifdef QMEDIA_DIRECTSHOW_PLAYER +#include "directshowplayerservice.h" +#endif + +#include + + +#ifdef QMEDIA_DIRECTSHOW_CAMERA +#ifdef QMEDIA_DIRECTSHOW_CAMERA +#ifndef _STRSAFE_H_INCLUDED_ +#include +#endif +#include +#include +#include +#pragma comment(lib, "strmiids.lib") +#pragma comment(lib, "ole32.lib") +#include +#endif + + +QT_BEGIN_NAMESPACE + +QStringList DSServicePlugin::keys() const +{ + return QStringList() +#ifdef QMEDIA_DIRECTSHOW_CAMERA + << QLatin1String(Q_MEDIASERVICE_CAMERA) +#endif +#ifdef QMEDIA_DIRECTSHOW_PLAYER + << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) +#endif + ; +} + +QMediaService* DSServicePlugin::create(QString const& key) +{ +#ifdef QMEDIA_DIRECTSHOW_CAMERA + if (key == QLatin1String(Q_MEDIASERVICE_CAMERA)) + return new DSCameraService; +#endif +#ifdef QMEDIA_DIRECTSHOW_PLAYER + if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER)) + return new DirectShowPlayerService; +#endif + + qDebug() << "unsupported key:" << key; + return 0; +} + +void DSServicePlugin::release(QMediaService *service) +{ + delete service; +} + +QList DSServicePlugin::devices(const QByteArray &service) const +{ +#ifdef QMEDIA_DIRECTSHOW_CAMERA + if (service == Q_MEDIASERVICE_CAMERA) { + if (m_cameraDevices.isEmpty()) + updateDevices(); + + return m_cameraDevices; + } +#endif + + return QList(); +} + +QString DSServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device) +{ +#ifdef QMEDIA_DIRECTSHOW_CAMERA + if (service == Q_MEDIASERVICE_CAMERA) { + if (m_cameraDevices.isEmpty()) + updateDevices(); + + for (int i=0; i(&pDevEnum)); + if(SUCCEEDED(hr)) { + // Create the enumerator for the video capture category + hr = pDevEnum->CreateClassEnumerator( + CLSID_VideoInputDeviceCategory, &pEnum, 0); + pEnum->Reset(); + // go through and find all video capture devices + IMoniker* pMoniker = NULL; + while(pEnum->Next(1, &pMoniker, NULL) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag, + (void**)(&pPropBag)); + if(FAILED(hr)) { + pMoniker->Release(); + continue; // skip this one + } + // Find the description + WCHAR str[120]; + VARIANT varName; + varName.vt = VT_BSTR; + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if(SUCCEEDED(hr)) { + StringCchCopyW(str,sizeof(str)/sizeof(str[0]),varName.bstrVal); + QString temp(QString::fromUtf16((unsigned short*)str)); + m_cameraDevices.append(QString("ds:%1").arg(temp).toLocal8Bit().constData()); + hr = pPropBag->Read(L"Description", &varName, 0); + StringCchCopyW(str,sizeof(str)/sizeof(str[0]),varName.bstrVal); + QString temp2(QString::fromUtf16((unsigned short*)str)); + m_cameraDescriptions.append(temp2); + } + pPropBag->Release(); + pMoniker->Release(); + } + } + CoUninitialize(); +} +#endif + +QT_END_NAMESPACE + +Q_EXPORT_PLUGIN2(dsengine, DSServicePlugin); + diff --git a/src/plugins/mediaservices/directshow/dsserviceplugin.h b/src/plugins/mediaservices/directshow/dsserviceplugin.h new file mode 100644 index 0000000..3c6f1b8 --- /dev/null +++ b/src/plugins/mediaservices/directshow/dsserviceplugin.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DSSERVICEPLUGIN_H +#define DSSERVICEPLUGIN_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class DSServicePlugin : public QMediaServiceProviderPlugin, public QMediaServiceSupportedDevicesInterface +{ + Q_OBJECT + Q_INTERFACES(QMediaServiceSupportedDevicesInterface) +public: + QStringList keys() const; + QMediaService* create(QString const& key); + void release(QMediaService *service); + + QList devices(const QByteArray &service) const; + QString deviceDescription(const QByteArray &service, const QByteArray &device); + +private: +#ifdef QMEDIA_DIRECTSHOW_CAMERA + void updateDevices() const; + + mutable QList m_cameraDevices; + mutable QStringList m_cameraDescriptions; +#endif +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // DSSERVICEPLUGIN_H diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp new file mode 100644 index 0000000..2826ba5 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowaudioendpointcontrol.h" + +#include "directshowglobal.h" +#include "directshowplayerservice.h" + + +QT_BEGIN_NAMESPACE + +DirectShowAudioEndpointControl::DirectShowAudioEndpointControl( + DirectShowPlayerService *service, QObject *parent) + : QAudioEndpointSelector(parent) + , m_service(service) + , m_bindContext(0) + , m_deviceEnumerator(0) +{ + if (CreateBindCtx(0, &m_bindContext) == S_OK) { + m_deviceEnumerator = com_new(CLSID_SystemDeviceEnum); + + updateEndpoints(); + + setActiveEndpoint(m_defaultEndpoint); + } +} + +DirectShowAudioEndpointControl::~DirectShowAudioEndpointControl() +{ + foreach (IMoniker *moniker, m_devices) + moniker->Release(); + + if (m_bindContext) + m_bindContext->Release(); + + if (m_deviceEnumerator) + m_deviceEnumerator->Release(); +} + +QList DirectShowAudioEndpointControl::availableEndpoints() const +{ + return m_devices.keys(); +} + +QString DirectShowAudioEndpointControl::endpointDescription(const QString &name) const +{ + return name.section(QLatin1Char('\\'), -1); +} + +QString DirectShowAudioEndpointControl::defaultEndpoint() const +{ + return m_defaultEndpoint; +} + +QString DirectShowAudioEndpointControl::activeEndpoint() const +{ + return m_activeEndpoint; +} + +void DirectShowAudioEndpointControl::setActiveEndpoint(const QString &name) +{ + if (m_activeEndpoint == name) + return; + + if (IMoniker *moniker = m_devices.value(name, 0)) { + IBaseFilter *filter = 0; + + if (moniker->BindToObject( + m_bindContext, + 0, + __uuidof(IBaseFilter), + reinterpret_cast(&filter)) == S_OK) { + m_service->setAudioOutput(filter); + + filter->Release(); + } + } +} + +void DirectShowAudioEndpointControl::updateEndpoints() +{ + IMalloc *oleMalloc = 0; + if (m_deviceEnumerator && CoGetMalloc(1, &oleMalloc) == S_OK) { + IEnumMoniker *monikers = 0; + + if (m_deviceEnumerator->CreateClassEnumerator( + CLSID_AudioRendererCategory, &monikers, 0) == S_OK) { + for (IMoniker *moniker = 0; monikers->Next(1, &moniker, 0) == S_OK; moniker->Release()) { + OLECHAR *string = 0; + if (moniker->GetDisplayName(m_bindContext, 0, &string) == S_OK) { + QString deviceId = QString::fromWCharArray(string); + oleMalloc->Free(string); + + moniker->AddRef(); + m_devices.insert(QString::fromWCharArray(string), moniker); + + if (m_defaultEndpoint.isEmpty() + || deviceId.endsWith(QLatin1String("Default DirectSound Device"))) { + m_defaultEndpoint = deviceId; + } + } + } + monikers->Release(); + } + oleMalloc->Release(); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h new file mode 100644 index 0000000..9ab188c --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWAUDIOENDPOINTCONTROL_H +#define DIRECTSHOWAUDIOENDPOINTCONTROL_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowPlayerService; + + +class DirectShowAudioEndpointControl : public QAudioEndpointSelector +{ + Q_OBJECT +public: + DirectShowAudioEndpointControl(DirectShowPlayerService *service, QObject *parent = 0); + ~DirectShowAudioEndpointControl(); + + QList availableEndpoints() const; + + QString endpointDescription(const QString &name) const; + + QString defaultEndpoint() const; + QString activeEndpoint() const; + + void setActiveEndpoint(const QString& name); + +private: + void updateEndpoints(); + + DirectShowPlayerService *m_service; + IBindCtx *m_bindContext; + ICreateDevEnum *m_deviceEnumerator; + + QMap m_devices; + QString m_defaultEndpoint; + QString m_activeEndpoint; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp new file mode 100644 index 0000000..4f9a19d --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include +#include + + +QT_BEGIN_NAMESPACE + + +class DirectShowPostedEvent +{ +public: + DirectShowPostedEvent(QObject *receiver, QEvent *event) + : receiver(receiver) + , event(event) + , next(0) + { + } + + ~DirectShowPostedEvent() + { + delete event; + } + + QObject *receiver; + QEvent *event; + DirectShowPostedEvent *next; +}; + +DirectShowEventLoop::DirectShowEventLoop(QObject *parent) + : QWinEventNotifier(parent) + , m_postsHead(0) + , m_postsTail(0) + , m_eventHandle(::CreateEvent(0, 0, 0, 0)) + , m_waitHandle(::CreateEvent(0, 0, 0, 0)) +{ + setHandle(m_eventHandle); + setEnabled(true); +} + +DirectShowEventLoop::~DirectShowEventLoop() +{ + setEnabled(false); + + ::CloseHandle(m_eventHandle); + ::CloseHandle(m_waitHandle); + + for (DirectShowPostedEvent *post = m_postsHead; post; post = m_postsHead) { + m_postsHead = m_postsHead->next; + + delete post; + } +} + +void DirectShowEventLoop::wait(QMutex *mutex) +{ + ::ResetEvent(m_waitHandle); + + mutex->unlock(); + + HANDLE handles[] = { m_eventHandle, m_waitHandle }; + while (::WaitForMultipleObjects(2, handles, false, INFINITE) == WAIT_OBJECT_0) + processEvents(); + + mutex->lock(); +} + +void DirectShowEventLoop::wake() +{ + ::SetEvent(m_waitHandle); +} + +void DirectShowEventLoop::postEvent(QObject *receiver, QEvent *event) +{ + QMutexLocker locker(&m_mutex); + + DirectShowPostedEvent *post = new DirectShowPostedEvent(receiver, event); + + if (m_postsTail) + m_postsTail->next = post; + else + m_postsHead = post; + + m_postsTail = post; + + ::SetEvent(m_eventHandle); +} + +bool DirectShowEventLoop::event(QEvent *event) +{ + if (event->type() == QEvent::WinEventAct) { + processEvents(); + + return true; + } else { + return QWinEventNotifier::event(event); + } +} + +void DirectShowEventLoop::processEvents() +{ + QMutexLocker locker(&m_mutex); + + while(m_postsHead) { + ::ResetEvent(m_eventHandle); + + DirectShowPostedEvent *post = m_postsHead; + m_postsHead = m_postsHead->next; + + locker.unlock(); + QCoreApplication::sendEvent(post->receiver, post->event); + delete post; + locker.relock(); + } + + m_postsTail = 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h new file mode 100644 index 0000000..eb68af3 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWEVENTLOOP_H +#define DIRECTSHOWEVENTLOOP_H + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowPostedEvent; + +class DirectShowEventLoop : public QWinEventNotifier +{ + Q_OBJECT +public: + DirectShowEventLoop(QObject *parent = 0); + ~DirectShowEventLoop(); + + void wait(QMutex *mutex); + void wake(); + + void postEvent(QObject *object, QEvent *event); + + bool event(QEvent *event); + +private: + void processEvents(); + + DirectShowPostedEvent *m_postsHead; + DirectShowPostedEvent *m_postsTail; + HANDLE m_eventHandle; + HANDLE m_waitHandle; + QMutex m_mutex; +}; + +QT_END_NAMESPAC + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowglobal.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowglobal.h new file mode 100644 index 0000000..1c9fe54 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowglobal.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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWGLOBAL_H +#define DIRECTSHOWGLOBAL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template T *com_cast(IUnknown *unknown) +{ + T *iface = 0; + return unknown && unknown->QueryInterface( + __uuidof(T), reinterpret_cast(&iface)) == S_OK + ? iface + : 0; +} + +template T *com_new(const IID &clsid) +{ + T *object = 0; + return CoCreateInstance( + clsid, + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(T), + reinterpret_cast(&object)) == S_OK + ? object + : 0; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp new file mode 100644 index 0000000..dcb9a40 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp @@ -0,0 +1,501 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowioreader.h" + +#include "directshoweventloop.h" +#include "directshowglobal.h" +#include "directshowiosource.h" + +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +class DirectShowSampleRequest +{ +public: + DirectShowSampleRequest( + IMediaSample *sample, DWORD_PTR userData, LONGLONG position, LONG length, BYTE *buffer) + : next(0) + , sample(sample) + , userData(userData) + , position(position) + , length(length) + , buffer(buffer) + , result(S_FALSE) + { + } + + DirectShowSampleRequest *remove() { DirectShowSampleRequest *n = next; delete this; return n; } + + DirectShowSampleRequest *next; + IMediaSample *sample; + DWORD_PTR userData; + LONGLONG position; + LONG length; + BYTE *buffer; + HRESULT result; +}; + +DirectShowIOReader::DirectShowIOReader( + QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop) + : m_source(source) + , m_device(device) + , m_loop(loop) + , m_pendingHead(0) + , m_pendingTail(0) + , m_readyHead(0) + , m_readyTail(0) + , m_synchronousPosition(0) + , m_synchronousLength(0) + , m_synchronousBytesRead(0) + , m_synchronousBuffer(0) + , m_synchronousResult(S_OK) + , m_totalLength(0) + , m_availableLength(0) + , m_flushing(false) +{ + moveToThread(device->thread()); + + connect(device, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + +DirectShowIOReader::~DirectShowIOReader() +{ + flushRequests(); +} + +HRESULT DirectShowIOReader::QueryInterface(REFIID riid, void **ppvObject) +{ + return m_source->QueryInterface(riid, ppvObject); +} + +ULONG DirectShowIOReader::AddRef() +{ + return m_source->AddRef(); +} + +ULONG DirectShowIOReader::Release() +{ + return m_source->Release(); +} + +// IAsyncReader +HRESULT DirectShowIOReader::RequestAllocator( + IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual) +{ + if (!ppActual || !pProps) { + return E_POINTER; + } else { + ALLOCATOR_PROPERTIES actualProperties; + + if (pProps->cbAlign == 0) + pProps->cbAlign = 1; + + if (pPreferred && pPreferred->SetProperties(pProps, &actualProperties) == S_OK) { + pPreferred->AddRef(); + + *ppActual = pPreferred; + + m_source->setAllocator(*ppActual); + + return S_OK; + } else { + *ppActual = com_new(CLSID_MemoryAllocator); + + if (*ppActual) { + if ((*ppActual)->SetProperties(pProps, &actualProperties) != S_OK) { + (*ppActual)->Release(); + } else { + m_source->setAllocator(*ppActual); + + return S_OK; + } + } + } + ppActual = 0; + + return E_FAIL; + } +} + +HRESULT DirectShowIOReader::Request(IMediaSample *pSample, DWORD_PTR dwUser) +{ + QMutexLocker locker(&m_mutex); + + if (!pSample) { + return E_POINTER; + } else if (m_flushing) { + return VFW_E_WRONG_STATE; + } else { + REFERENCE_TIME startTime = 0; + REFERENCE_TIME endTime = 0; + BYTE *buffer; + + if (pSample->GetTime(&startTime, &endTime) != S_OK + || pSample->GetPointer(&buffer) != S_OK) { + return VFW_E_SAMPLE_TIME_NOT_SET; + } else { + LONGLONG position = startTime / 10000000; + LONG length = ((endTime - startTime) / 10000000) + 1; + + DirectShowSampleRequest *request = new DirectShowSampleRequest( + pSample, dwUser, position, length, buffer); + + if (m_pendingTail) { + m_pendingTail->next = request; + } else { + m_pendingHead = request; + + m_loop->postEvent(this, new QEvent(QEvent::User)); + } + m_pendingTail = request; + + return S_OK; + } + } +} + +HRESULT DirectShowIOReader::WaitForNext( + DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser) +{ + if (!ppSample || !pdwUser) + return E_POINTER; + + QMutexLocker locker(&m_mutex); + + do { + if (m_readyHead) { + DirectShowSampleRequest *request = m_readyHead; + + *ppSample = request->sample; + *pdwUser = request->userData; + + HRESULT hr = request->result; + + m_readyHead = request->next; + + if (!m_readyHead) + m_readyTail = 0; + + delete request; + + return hr; + } else if (m_flushing) { + *ppSample = 0; + *pdwUser = 0; + + return VFW_E_WRONG_STATE; + } + } while (m_wait.wait(&m_mutex, dwTimeout)); + + *ppSample = 0; + *pdwUser = 0; + + return VFW_E_TIMEOUT; +} + +HRESULT DirectShowIOReader::SyncReadAligned(IMediaSample *pSample) +{ + if (!pSample) { + return E_POINTER; + } else { + REFERENCE_TIME startTime = 0; + REFERENCE_TIME endTime = 0; + BYTE *buffer; + + if (pSample->GetTime(&startTime, &endTime) != S_OK + || pSample->GetPointer(&buffer) != S_OK) { + return VFW_E_SAMPLE_TIME_NOT_SET; + } else { + LONGLONG position = startTime / 10000000; + LONG length = ((endTime - startTime) / 10000000) + 1; + + QMutexLocker locker(&m_mutex); + + if (thread() == QThread::currentThread()) { + qint64 bytesRead = 0; + + HRESULT hr = blockingRead(position, length, buffer, &bytesRead); + + if (SUCCEEDED(hr)) + pSample->SetActualDataLength(bytesRead); + + return hr; + } else { + m_synchronousPosition = position; + m_synchronousLength = length; + m_synchronousBuffer = buffer; + + m_loop->postEvent(this, new QEvent(QEvent::User)); + + m_wait.wait(&m_mutex); + + m_synchronousBuffer = 0; + + if (SUCCEEDED(m_synchronousResult)) + pSample->SetActualDataLength(m_synchronousBytesRead); + + return m_synchronousResult; + } + } + } +} + +HRESULT DirectShowIOReader::SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer) +{ + if (!pBuffer) { + return E_POINTER; + } else { + if (thread() == QThread::currentThread()) { + qint64 bytesRead; + + return blockingRead(llPosition, lLength, pBuffer, &bytesRead); + } else { + QMutexLocker locker(&m_mutex); + + m_synchronousPosition = llPosition; + m_synchronousLength = lLength; + m_synchronousBuffer = pBuffer; + + m_loop->postEvent(this, new QEvent(QEvent::User)); + + m_wait.wait(&m_mutex); + + m_synchronousBuffer = 0; + + return m_synchronousResult; + } + } +} + +HRESULT DirectShowIOReader::Length(LONGLONG *pTotal, LONGLONG *pAvailable) +{ + if (!pTotal || !pAvailable) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + *pTotal = m_totalLength; + *pAvailable = m_availableLength; + + return S_OK; + } +} + + +HRESULT DirectShowIOReader::BeginFlush() +{ + QMutexLocker locker(&m_mutex); + + if (m_flushing) + return S_FALSE; + + m_flushing = true; + + flushRequests(); + + m_wait.wakeAll(); + + return S_OK; +} + +HRESULT DirectShowIOReader::EndFlush() +{ + QMutexLocker locker(&m_mutex); + + if (!m_flushing) + return S_FALSE; + + m_flushing = false; + + return S_OK; +} + +void DirectShowIOReader::customEvent(QEvent *event) +{ + if (event->type() == QEvent::User) { + readyRead(); + } else { + QObject::customEvent(event); + } +} + +void DirectShowIOReader::readyRead() +{ + QMutexLocker locker(&m_mutex); + + m_availableLength = m_device->bytesAvailable() + m_device->pos(); + m_totalLength = m_device->size(); + + if (m_synchronousBuffer) { + if (nonBlockingRead( + m_synchronousPosition, + m_synchronousLength, + m_synchronousBuffer, + &m_synchronousBytesRead, + &m_synchronousResult)) { + m_wait.wakeAll(); + } + } else { + qint64 bytesRead = 0; + + while (m_pendingHead && nonBlockingRead( + m_pendingHead->position, + m_pendingHead->length, + m_pendingHead->buffer, + &bytesRead, + &m_pendingHead->result)) { + m_pendingHead->sample->SetActualDataLength(bytesRead); + + if (m_readyTail) + m_readyTail->next = m_pendingHead; + m_readyTail = m_pendingHead; + + m_pendingHead = m_pendingHead->next; + + m_readyTail->next = 0; + + if (!m_pendingHead) + m_pendingTail = 0; + + if (!m_readyHead) + m_readyHead = m_readyTail; + + m_wait.wakeAll(); + } + } +} + +HRESULT DirectShowIOReader::blockingRead( + LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead) +{ + *bytesRead = 0; + + if (qint64(position) > m_device->size()) + return S_FALSE; + + const qint64 maxSize = qMin(m_device->size(), position + length); + + while (m_device->bytesAvailable() + m_device->pos() < maxSize) { + if (!m_device->waitForReadyRead(-1)) + return S_FALSE; + } + + if (m_device->pos() != position && !m_device->seek(position)) + return S_FALSE; + + const qint64 maxBytes = qMin(length, m_device->bytesAvailable()); + + *bytesRead = m_device->read(reinterpret_cast(buffer), maxBytes); + + if (*bytesRead != length) { + qMemSet(buffer + *bytesRead, 0, length - *bytesRead); + + return S_FALSE; + } else { + return S_OK; + } +} + +bool DirectShowIOReader::nonBlockingRead( + LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result) +{ + const qint64 maxSize = qMin(m_device->size(), position + length); + + if (position > m_device->size()) { + *bytesRead = 0; + *result = S_FALSE; + + return true; + } else if (m_device->bytesAvailable() + m_device->pos() >= maxSize) { + if (m_device->pos() != position && !m_device->seek(position)) { + *bytesRead = 0; + *result = S_FALSE; + + return true; + } else { + const qint64 maxBytes = qMin(length, m_device->bytesAvailable()); + + *bytesRead = m_device->read(reinterpret_cast(buffer), maxBytes); + + if (*bytesRead != length) { + qMemSet(buffer + *bytesRead, 0, length - *bytesRead); + + *result = S_FALSE; + } else { + *result = S_OK; + } + + return true; + } + } else { + return false; + } +} + +void DirectShowIOReader::flushRequests() +{ + while (m_pendingHead) { + m_pendingHead->result = VFW_E_WRONG_STATE; + + if (m_readyTail) + m_readyTail->next = m_pendingHead; + + m_readyTail = m_pendingHead; + + m_pendingHead = m_pendingHead->next; + + m_readyTail->next = 0; + + if (!m_pendingHead) + m_pendingTail = 0; + + if (!m_readyHead) + m_readyHead = m_readyTail; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.h new file mode 100644 index 0000000..8cbc2f1 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWIOREADER_H +#define DIRECTSHOWIOREADER_H + +#include +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QIODevice; + +class DirectShowEventLoop; +class DirectShowIOSource; +class DirectShowSampleRequest; + +class DirectShowIOReader : public QObject, public IAsyncReader +{ + Q_OBJECT +public: + DirectShowIOReader(QIODevice *device, DirectShowIOSource *source, DirectShowEventLoop *loop); + ~DirectShowIOReader(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IAsyncReader + HRESULT STDMETHODCALLTYPE RequestAllocator( + IMemAllocator *pPreferred, ALLOCATOR_PROPERTIES *pProps, IMemAllocator **ppActual); + + HRESULT STDMETHODCALLTYPE Request(IMediaSample *pSample, DWORD_PTR dwUser); + + HRESULT STDMETHODCALLTYPE WaitForNext( + DWORD dwTimeout, IMediaSample **ppSample, DWORD_PTR *pdwUser); + + HRESULT STDMETHODCALLTYPE SyncReadAligned(IMediaSample *pSample); + + HRESULT STDMETHODCALLTYPE SyncRead(LONGLONG llPosition, LONG lLength, BYTE *pBuffer); + + HRESULT STDMETHODCALLTYPE Length(LONGLONG *pTotal, LONGLONG *pAvailable); + + HRESULT STDMETHODCALLTYPE BeginFlush(); + HRESULT STDMETHODCALLTYPE EndFlush(); + +protected: + void customEvent(QEvent *event); + +private Q_SLOTS: + void readyRead(); + +private: + HRESULT blockingRead(LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead); + bool nonBlockingRead( + LONGLONG position, LONG length, BYTE *buffer, qint64 *bytesRead, HRESULT *result); + void flushRequests(); + + DirectShowIOSource *m_source; + QIODevice *m_device; + DirectShowEventLoop *m_loop; + DirectShowSampleRequest *m_pendingHead; + DirectShowSampleRequest *m_pendingTail; + DirectShowSampleRequest *m_readyHead; + DirectShowSampleRequest *m_readyTail; + LONGLONG m_synchronousPosition; + LONG m_synchronousLength; + qint64 m_synchronousBytesRead; + BYTE *m_synchronousBuffer; + HRESULT m_synchronousResult; + LONGLONG m_totalLength; + LONGLONG m_availableLength; + bool m_flushing; + QMutex m_mutex; + QWaitCondition m_wait; +}; + +QT_END_NAMESPACE + +QT_END_HEADER +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp new file mode 100644 index 0000000..bf83dcf --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp @@ -0,0 +1,603 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowiosource.h" + +#include "directshowglobal.h" +#include "directshowmediatype.h" +#include "directshowpinenum.h" + + +QT_BEGIN_NAMESPACE + +static const GUID directshow_subtypes[] = +{ + MEDIASUBTYPE_Avi, + MEDIASUBTYPE_WAVE, + MEDIASUBTYPE_NULL +}; + +DirectShowIOSource::DirectShowIOSource(QIODevice *device, DirectShowEventLoop *loop) + : m_ref(1) + , m_state(State_Stopped) + , m_graph(0) + , m_clock(0) + , m_allocator(0) + , m_peerPin(0) + , m_pinId(QLatin1String("Data")) + , m_reader(device, this, loop) +{ + QVector mediaTypes; + + AM_MEDIA_TYPE type = + { + MEDIATYPE_Stream, // majortype + MEDIASUBTYPE_NULL, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 1, // lSampleSize + GUID_NULL, // formattype + 0, // pUnk + 0, // cbFormat + 0, // pbFormat + }; + + static const int count = sizeof(directshow_subtypes) / sizeof(GUID); + + for (int i = 0; i < count; ++i) { + type.subtype = directshow_subtypes[i]; + mediaTypes.append(type); + } + + setMediaTypes(mediaTypes); +} + +DirectShowIOSource::~DirectShowIOSource() +{ + Q_ASSERT(m_ref == 0); +} + +void DirectShowIOSource::setAllocator(IMemAllocator *allocator) +{ + if (m_allocator) + m_allocator->Release(); + + m_allocator = allocator; + + if (m_allocator) + m_allocator->AddRef(); +} + +// IUnknown +HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject) +{ + if (!ppvObject) { + return E_POINTER; + } else if (riid == IID_IUnknown + || riid == IID_IPersist + || riid == IID_IMediaFilter + || riid == IID_IBaseFilter) { + *ppvObject = static_cast(this); + } else if (riid == IID_IAMFilterMiscFlags) { + *ppvObject = static_cast(this); + } else if (riid == IID_IPin) { + *ppvObject = static_cast(this); + } else if (riid == IID_IAsyncReader) { + *ppvObject = static_cast(&m_reader); + } else { + *ppvObject = 0; + + return E_NOINTERFACE; + } + + AddRef(); + + return S_OK; +} + +ULONG DirectShowIOSource::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG DirectShowIOSource::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + if (ref == 0) { + delete this; + } + + return ref; +} + +// IPersist +HRESULT DirectShowIOSource::GetClassID(CLSID *pClassID) +{ + *pClassID = CLSID_NULL; + + return S_OK; +} + +// IMediaFilter +HRESULT DirectShowIOSource::Run(REFERENCE_TIME tStart) +{ + QMutexLocker locker(&m_mutex); + + m_state = State_Running; + + return S_OK; +} + +HRESULT DirectShowIOSource::Pause() +{ + QMutexLocker locker(&m_mutex); + + m_state = State_Paused; + + return S_OK; +} + +HRESULT DirectShowIOSource::Stop() +{ + QMutexLocker locker(&m_mutex); + + m_state = State_Stopped; + + return S_OK; +} + +HRESULT DirectShowIOSource::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState) +{ + Q_UNUSED(dwMilliSecsTimeout); + + if (!pState) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + *pState = m_state; + + return S_OK; + } +} + +HRESULT DirectShowIOSource::SetSyncSource(IReferenceClock *pClock) +{ + QMutexLocker locker(&m_mutex); + + if (m_clock) + m_clock->Release(); + + m_clock = pClock; + + if (m_clock) + m_clock->AddRef(); + + return S_OK; +} + +HRESULT DirectShowIOSource::GetSyncSource(IReferenceClock **ppClock) +{ + if (!ppClock) { + return E_POINTER; + } else { + if (!m_clock) { + *ppClock = 0; + + return S_FALSE; + } else { + m_clock->AddRef(); + + *ppClock = m_clock; + + return S_OK; + } + } +} + +// IBaseFilter +HRESULT DirectShowIOSource::EnumPins(IEnumPins **ppEnum) +{ + if (!ppEnum) { + return E_POINTER; + } else { + *ppEnum = new DirectShowPinEnum(QList() << this); + + return S_OK; + } +} + +HRESULT DirectShowIOSource::FindPin(LPCWSTR Id, IPin **ppPin) +{ + if (!ppPin || !Id) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + if (QString::fromWCharArray(Id) == m_pinId) { + AddRef(); + + *ppPin = this; + + return S_OK; + } else { + *ppPin = 0; + + return VFW_E_NOT_FOUND; + } + } +} + +HRESULT DirectShowIOSource::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) +{ + QMutexLocker locker(&m_mutex); + + m_graph = pGraph; + m_filterName = QString::fromWCharArray(pName); + + return S_OK; +} + +HRESULT DirectShowIOSource::QueryFilterInfo(FILTER_INFO *pInfo) +{ + if (!pInfo) { + return E_POINTER; + } else { + QString name = m_filterName; + + if (name.length() >= MAX_FILTER_NAME) + name.truncate(MAX_FILTER_NAME - 1); + + int length = name.toWCharArray(pInfo->achName); + pInfo->achName[length] = '\0'; + + if (m_graph) + m_graph->AddRef(); + + pInfo->pGraph = m_graph; + + return S_OK; + } +} + +HRESULT DirectShowIOSource::QueryVendorInfo(LPWSTR *pVendorInfo) +{ + Q_UNUSED(pVendorInfo); + + return E_NOTIMPL; +} + +// IAMFilterMiscFlags +ULONG DirectShowIOSource::GetMiscFlags() +{ + return AM_FILTER_MISC_FLAGS_IS_SOURCE; +} + +// IPin +HRESULT DirectShowIOSource::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + QMutexLocker locker(&m_mutex); + if (!pReceivePin) { + return E_POINTER; + } else if (m_state != State_Stopped) { + return VFW_E_NOT_STOPPED; + } else if (m_peerPin) { + return VFW_E_ALREADY_CONNECTED; + } else { + HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; + + m_peerPin = pReceivePin; + m_peerPin->AddRef(); + + if (!pmt) { + IEnumMediaTypes *mediaTypes = 0; + if (pReceivePin->EnumMediaTypes(&mediaTypes) == S_OK) { + for (AM_MEDIA_TYPE *type = 0; + mediaTypes->Next(1, &type, 0) == S_OK; + DirectShowMediaType::deleteType(type)) { + switch (tryConnect(pReceivePin, type)) { + case S_OK: + DirectShowMediaType::freeData(type); + mediaTypes->Release(); + return S_OK; + case VFW_E_NO_TRANSPORT: + hr = VFW_E_NO_TRANSPORT; + break; + default: + break; + } + } + mediaTypes->Release(); + } + AM_MEDIA_TYPE type = + { + MEDIATYPE_Stream, // majortype + MEDIASUBTYPE_NULL, // subtype + TRUE, // bFixedSizeSamples + FALSE, // bTemporalCompression + 1, // lSampleSize + GUID_NULL, // formattype + 0, // pUnk + 0, // cbFormat + 0, // pbFormat + }; + + static const int count = sizeof(directshow_subtypes) / sizeof(GUID); + + for (int i = 0; i < count; ++i) { + type.subtype = directshow_subtypes[i]; + + switch (tryConnect(pReceivePin, &type)) { + case S_OK: + return S_OK; + case VFW_E_NO_TRANSPORT: + hr = VFW_E_NO_TRANSPORT; + break; + default: + break; + } + } + } else if (pmt->majortype == MEDIATYPE_Stream && (hr = tryConnect(pReceivePin, pmt))) { + return S_OK; + } + + m_peerPin->Release(); + m_peerPin = 0; + + m_mediaType.clear(); + + return hr; + } +} + +HRESULT DirectShowIOSource::tryConnect(IPin *pin, const AM_MEDIA_TYPE *type) +{ + m_mediaType = *type; + + HRESULT hr = pin->ReceiveConnection(this, type); + + if (!SUCCEEDED(hr)) { + if (m_allocator) { + m_allocator->Release(); + m_allocator = 0; + } + } else if (!m_allocator) { + hr = VFW_E_NO_TRANSPORT; + + if (IMemInputPin *memPin = com_cast(pin)) { + if ((m_allocator = com_new(CLSID_MemoryAllocator))) { + ALLOCATOR_PROPERTIES properties; + if (memPin->GetAllocatorRequirements(&properties) == S_OK + || m_allocator->GetProperties(&properties) == S_OK) { + if (properties.cbAlign == 0) + properties.cbAlign = 1; + + ALLOCATOR_PROPERTIES actualProperties; + if (SUCCEEDED(hr = m_allocator->SetProperties(&properties, &actualProperties))) + hr = memPin->NotifyAllocator(m_allocator, TRUE); + } + if (!SUCCEEDED(hr)) { + m_allocator->Release(); + m_allocator = 0; + } + } + memPin->Release(); + } + if (!SUCCEEDED(hr)) + pin->Disconnect(); + } + return hr; +} + +HRESULT DirectShowIOSource::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) +{ + Q_UNUSED(pConnector); + Q_UNUSED(pmt); + // Output pin. + return E_NOTIMPL; +} + +HRESULT DirectShowIOSource::Disconnect() +{ + if (!m_peerPin) { + return S_FALSE; + } else if (m_state != State_Stopped) { + return VFW_E_NOT_STOPPED; + } else { + HRESULT hr = m_peerPin->Disconnect(); + + if (!SUCCEEDED(hr)) + return hr; + + if (m_allocator) { + m_allocator->Release(); + m_allocator = 0; + } + + m_peerPin->Release(); + m_peerPin = 0; + + m_mediaType.clear(); + + return S_OK; + } +} + +HRESULT DirectShowIOSource::ConnectedTo(IPin **ppPin) +{ + if (!ppPin) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) { + *ppPin = 0; + + return VFW_E_NOT_CONNECTED; + } else { + m_peerPin->AddRef(); + + *ppPin = m_peerPin; + + return S_OK; + } + } +} + +HRESULT DirectShowIOSource::ConnectionMediaType(AM_MEDIA_TYPE *pmt) +{ + if (!pmt) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) { + pmt = 0; + + return VFW_E_NOT_CONNECTED; + } else { + DirectShowMediaType::copy(pmt, m_mediaType); + + return S_OK; + } + } +} + +HRESULT DirectShowIOSource::QueryPinInfo(PIN_INFO *pInfo) +{ + if (!pInfo) { + return E_POINTER; + } else { + AddRef(); + + pInfo->pFilter = this; + pInfo->dir = PINDIR_OUTPUT; + + const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2); + + qMemCopy(pInfo->achName, m_pinId.utf16(), bytes); + + return S_OK; + } +} + +HRESULT DirectShowIOSource::QueryId(LPWSTR *Id) +{ + if (!Id) { + return E_POINTER; + } else { + const int bytes = (m_pinId.length() + 1) * 2; + + *Id = static_cast(::CoTaskMemAlloc(bytes)); + + qMemCopy(*Id, m_pinId.utf16(), bytes); + + return S_OK; + } +} + +HRESULT DirectShowIOSource::QueryAccept(const AM_MEDIA_TYPE *pmt) +{ + if (!pmt) { + return E_POINTER; + } else if (pmt->majortype == MEDIATYPE_Stream) { + return S_OK; + } else { + return S_FALSE; + } +} + +HRESULT DirectShowIOSource::EnumMediaTypes(IEnumMediaTypes **ppEnum) +{ + if (!ppEnum) { + return E_POINTER; + } else { + *ppEnum = createMediaTypeEnum(); + + return S_OK; + } +} + +HRESULT DirectShowIOSource::QueryInternalConnections(IPin **apPin, ULONG *nPin) +{ + Q_UNUSED(apPin); + Q_UNUSED(nPin); + + return E_NOTIMPL; +} + +HRESULT DirectShowIOSource::EndOfStream() +{ + return S_OK; +} + +HRESULT DirectShowIOSource::BeginFlush() +{ + return m_reader.BeginFlush(); +} + +HRESULT DirectShowIOSource::EndFlush() +{ + return m_reader.EndFlush(); +} + +HRESULT DirectShowIOSource::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + Q_UNUSED(tStart); + Q_UNUSED(tStop); + Q_UNUSED(dRate); + + return S_OK; +} + +HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir) +{ + if (!pPinDir) { + return E_POINTER; + } else { + *pPinDir = PINDIR_OUTPUT; + + return S_OK; + } +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h new file mode 100644 index 0000000..a8ed56a --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWIOSOURCE_H +#define DIRECTSHOWIOSOURCE_H + +#include "directshowioreader.h" +#include "directshowmediatype.h" +#include "directshowmediatypelist.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QIODevice; + +class DirectShowIOSource + : public DirectShowMediaTypeList + , public IBaseFilter + , public IAMFilterMiscFlags + , public IPin +{ +public: + DirectShowIOSource(QIODevice *device, DirectShowEventLoop *loop); + ~DirectShowIOSource(); + + void setAllocator(IMemAllocator *allocator); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IPersist + HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); + + // IMediaFilter + HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart); + HRESULT STDMETHODCALLTYPE Pause(); + HRESULT STDMETHODCALLTYPE Stop(); + + HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState); + + HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock); + HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock); + + // IBaseFilter + HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum); + HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin); + + HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName); + + HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo); + HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo); + + // IAMFilterMiscFlags + ULONG STDMETHODCALLTYPE GetMiscFlags(); + + // IPin + HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE Disconnect(); + HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin); + + HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); + + HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); + HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); + + HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); + + HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); + + HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); + + HRESULT STDMETHODCALLTYPE EndOfStream(); + + HRESULT STDMETHODCALLTYPE BeginFlush(); + HRESULT STDMETHODCALLTYPE EndFlush(); + + HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + + HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); + +private: + HRESULT tryConnect(IPin *pin, const AM_MEDIA_TYPE *type); + + volatile LONG m_ref; + FILTER_STATE m_state; + IFilterGraph *m_graph; + IReferenceClock *m_clock; + IMemAllocator *m_allocator; + IPin *m_peerPin; + DirectShowMediaType m_mediaType; + QString m_filterName; + const QString m_pinId; + QMutex m_mutex; + DirectShowIOReader m_reader; + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp new file mode 100644 index 0000000..8edf93e --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowmediatype.h" + + +QT_BEGIN_NAMESPACE + +namespace +{ + struct TypeLookup + { + QVideoFrame::PixelFormat pixelFormat; + GUID mediaType; + }; + + static const TypeLookup qt_typeLookup[] = + { + { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, + { QVideoFrame::Format_RGB32, MEDIASUBTYPE_RGB32 }, + { QVideoFrame::Format_YV12, MEDIASUBTYPE_YV12 } + }; +} + +void DirectShowMediaType::copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source) +{ + *target = source; + + if (source.cbFormat > 0) { + target->pbFormat = reinterpret_cast(CoTaskMemAlloc(source.cbFormat)); + memcpy(target->pbFormat, source.pbFormat, source.cbFormat); + } + if (target->pUnk) + target->pUnk->AddRef(); +} + +void DirectShowMediaType::deleteType(AM_MEDIA_TYPE *type) +{ + freeData(type); + + CoTaskMemFree(type); +} + +void DirectShowMediaType::freeData(AM_MEDIA_TYPE *type) +{ + if (type->cbFormat > 0) + CoTaskMemFree(type->pbFormat); + + if (type->pUnk) + type->pUnk->Release(); +} + + +GUID DirectShowMediaType::convertPixelFormat(QVideoFrame::PixelFormat format) +{ + const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup); + + for (int i = 0; i < count; ++i) + if (qt_typeLookup[i].pixelFormat == format) + return qt_typeLookup[i].mediaType; + return MEDIASUBTYPE_None; +} + +QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &type) +{ + const int count = sizeof(qt_typeLookup) / sizeof(TypeLookup); + + for (int i = 0; i < count; ++i) { + if (IsEqualGUID(qt_typeLookup[i].mediaType, type.subtype) && type.cbFormat > 0) { + if (IsEqualGUID(type.formattype, FORMAT_VideoInfo)) { + VIDEOINFOHEADER *header = reinterpret_cast(type.pbFormat); + + QVideoSurfaceFormat format( + QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)), + qt_typeLookup[i].pixelFormat); + + if (header->AvgTimePerFrame > 0) + format.setFrameRate(10000 /header->AvgTimePerFrame); + + format.setScanLineDirection(header->bmiHeader.biHeight < 0 + ? QVideoSurfaceFormat::TopToBottom + : QVideoSurfaceFormat::BottomToTop); + + return format; + } else if (IsEqualGUID(type.formattype, FORMAT_VideoInfo2)) { + VIDEOINFOHEADER2 *header = reinterpret_cast(type.pbFormat); + + QVideoSurfaceFormat format( + QSize(header->bmiHeader.biWidth, qAbs(header->bmiHeader.biHeight)), + qt_typeLookup[i].pixelFormat); + + if (header->AvgTimePerFrame > 0) + format.setFrameRate(10000 / header->AvgTimePerFrame); + + format.setScanLineDirection(header->bmiHeader.biHeight < 0 + ? QVideoSurfaceFormat::TopToBottom + : QVideoSurfaceFormat::BottomToTop); + + return format; + } + } + } + return QVideoSurfaceFormat(); +} + +int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format) +{ + switch (format.pixelFormat()) { + case QVideoFrame::Format_RGB24: + return format.frameWidth() * 4 + 3 - format.frameWidth() % 4; + case QVideoFrame::Format_RGB32: + return format.frameWidth() * 4; + case QVideoFrame::Format_YV12: + return format.frameWidth() + 3 - format.frameWidth() % 4; + default: + return 0; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h new file mode 100644 index 0000000..3ba907e --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWMEDIATYPE_H +#define DIRECTSHOWMEDIATYPE_H + +#include + +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class DirectShowMediaType : public AM_MEDIA_TYPE +{ +public: + DirectShowMediaType() { memset(this, 0, sizeof(DirectShowMediaType)); } + DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); } + DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); } + DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) { + free(this); copy(this, type); return *this; } + DirectShowMediaType &operator =(const DirectShowMediaType &other) { + free(this); copy(this, other); return *this; } + ~DirectShowMediaType() { freeData(this); } + + void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); } + + static void copy(AM_MEDIA_TYPE *target, const AM_MEDIA_TYPE &source); + static void freeData(AM_MEDIA_TYPE *type); + static void deleteType(AM_MEDIA_TYPE *type); + + static GUID convertPixelFormat(QVideoFrame::PixelFormat format); + static QVideoSurfaceFormat formatFromType(const AM_MEDIA_TYPE &type); + + static int bytesPerLine(const QVideoSurfaceFormat &format); +}; + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.cpp new file mode 100644 index 0000000..f67794a --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowmediatypelist.h" + +#include "directshowmediatype.h" +#include "videosurfacefilter.h" + + +QT_BEGIN_NAMESPACE + +class DirectShowMediaTypeEnum : public IEnumMediaTypes +{ +public: + DirectShowMediaTypeEnum(DirectShowMediaTypeList *list, int token, int index = 0); + ~DirectShowMediaTypeEnum(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IEnumMediaTypes + HRESULT STDMETHODCALLTYPE Next( + ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched); + HRESULT STDMETHODCALLTYPE Skip(ULONG cMediaTypes); + HRESULT STDMETHODCALLTYPE Reset(); + + HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **ppEnum); + +private: + LONG m_ref; + DirectShowMediaTypeList *m_list; + int m_mediaTypeToken; + int m_index; +}; + + +DirectShowMediaTypeEnum::DirectShowMediaTypeEnum( + DirectShowMediaTypeList *list, int token, int index) + : m_ref(1) + , m_list(list) + , m_mediaTypeToken(token) + , m_index(index) +{ + m_list->AddRef(); +} + +DirectShowMediaTypeEnum::~DirectShowMediaTypeEnum() +{ + m_list->Release(); +} + +HRESULT DirectShowMediaTypeEnum::QueryInterface(REFIID riid, void **ppvObject) +{ + if (!ppvObject) { + return E_POINTER; + } else if (riid == IID_IUnknown + || riid == IID_IEnumMediaTypes) { + *ppvObject = static_cast(this); + } else { + *ppvObject = 0; + + return E_NOINTERFACE; + } + + AddRef(); + + return S_OK; +} + +ULONG DirectShowMediaTypeEnum::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG DirectShowMediaTypeEnum::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + if (ref == 0) { + delete this; + } + + return ref; +} + +HRESULT DirectShowMediaTypeEnum::Next( + ULONG cMediaTypes, AM_MEDIA_TYPE **ppMediaTypes, ULONG *pcFetched) +{ + return m_list->nextMediaType(m_mediaTypeToken, &m_index, cMediaTypes, ppMediaTypes, pcFetched); +} + +HRESULT DirectShowMediaTypeEnum::Skip(ULONG cMediaTypes) +{ + return m_list->skipMediaType(m_mediaTypeToken, &m_index, cMediaTypes); +} + +HRESULT DirectShowMediaTypeEnum::Reset() +{ + m_mediaTypeToken = m_list->currentMediaTypeToken(); + m_index = 0; + + return S_OK; +} + +HRESULT DirectShowMediaTypeEnum::Clone(IEnumMediaTypes **ppEnum) +{ + return m_list->cloneMediaType(m_mediaTypeToken, m_index, ppEnum); +} + + +DirectShowMediaTypeList::DirectShowMediaTypeList() + : m_mediaTypeToken(0) +{ +} + +IEnumMediaTypes *DirectShowMediaTypeList::createMediaTypeEnum() +{ + return new DirectShowMediaTypeEnum(this, m_mediaTypeToken, 0); +} + + +void DirectShowMediaTypeList::setMediaTypes(const QVector &types) +{ + ++m_mediaTypeToken; + + m_mediaTypes = types; +} + + +int DirectShowMediaTypeList::currentMediaTypeToken() +{ + return m_mediaTypeToken; +} + +HRESULT DirectShowMediaTypeList::nextMediaType( + int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount) +{ + if (!types || (count != 1 && !fetchedCount)) { + return E_POINTER; + } else if (m_mediaTypeToken != token) { + return VFW_E_ENUM_OUT_OF_SYNC; + } else { + int boundedCount = qBound(0, count, m_mediaTypes.count() - *index); + + for (int i = 0; i < boundedCount; ++i, ++(*index)) { + types[i] = reinterpret_cast(CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))); + + if (types[i]) { + DirectShowMediaType::copy(types[i], m_mediaTypes.at(*index)); + } else { + for (--i; i >= 0; --i) + CoTaskMemFree(types[i]); + + if (fetchedCount) + *fetchedCount = 0; + + return E_OUTOFMEMORY; + } + } + if (fetchedCount) + *fetchedCount = boundedCount; + + return boundedCount == count ? S_OK : S_FALSE; + } +} + +HRESULT DirectShowMediaTypeList::skipMediaType(int token, int *index, ULONG count) +{ + if (m_mediaTypeToken != token) { + return VFW_E_ENUM_OUT_OF_SYNC; + } else { + *index = qMin(*index + count, m_mediaTypes.size()); + + return *index < m_mediaTypes.size() ? S_OK : S_FALSE; + } +} + +HRESULT DirectShowMediaTypeList::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration) +{ + if (m_mediaTypeToken != token) { + return VFW_E_ENUM_OUT_OF_SYNC; + } else { + *enumeration = new DirectShowMediaTypeEnum(this, token, index); + + return S_OK; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.h new file mode 100644 index 0000000..b49f24c --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatypelist.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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWMEDIATYPELIST_H +#define DIRECTSHOWMEDIATYPELIST_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowMediaTypeList : public IUnknown +{ +public: + DirectShowMediaTypeList(); + + IEnumMediaTypes *createMediaTypeEnum(); + + void setMediaTypes(const QVector &types); + + virtual int currentMediaTypeToken(); + virtual HRESULT nextMediaType( + int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount); + virtual HRESULT skipMediaType(int token, int *index, ULONG count); + virtual HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration); + +private: + int m_mediaTypeToken; + QVector m_mediaTypes; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp new file mode 100644 index 0000000..7335e3d --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp @@ -0,0 +1,351 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "directshowmetadatacontrol.h" + +#include "directshowplayerservice.h" + +#include + + +QT_BEGIN_NAMESPACE + +namespace +{ + struct QWMMetaDataKeyLookup + { + QtMedia::MetaData key; + const wchar_t *token; + }; +} + +static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = +{ + { QtMedia::Title, L"Title" }, + { QtMedia::SubTitle, L"WM/SubTitle" }, + { QtMedia::Author, L"Author" }, + { QtMedia::Comment, L"Comment" }, + { QtMedia::Description, L"Description" }, + { QtMedia::Category, L"WM/Category" }, + { QtMedia::Genre, L"WM/Genre" }, + //{ QtMedia::Date, 0 }, + { QtMedia::Year, L"WM/Year" }, + { QtMedia::UserRating, L"UserRating" }, + //{ QtMedia::MetaDatawords, 0 }, + { QtMedia::Language, L"Language" }, + { QtMedia::Publisher, L"WM/Publisher" }, + { QtMedia::Copyright, L"Copyright" }, + { QtMedia::ParentalRating, L"ParentalRating" }, + { QtMedia::RatingOrganisation, L"RatingOrganisation" }, + + // Media + { QtMedia::Size, L"FileSize" }, + { QtMedia::MediaType, L"MediaType" }, + { QtMedia::Duration, L"Duration" }, + + // Audio + { QtMedia::AudioBitRate, L"AudioBitRate" }, + { QtMedia::AudioCodec, L"AudioCodec" }, + { QtMedia::ChannelCount, L"ChannelCount" }, + { QtMedia::SampleRate, L"Frequency" }, + + // Music + { QtMedia::AlbumTitle, L"WM/AlbumTitle" }, + { QtMedia::AlbumArtist, L"WM/AlbumArtist" }, + { QtMedia::ContributingArtist, L"Author" }, + { QtMedia::Composer, L"WM/Composer" }, + { QtMedia::Conductor, L"WM/Conductor" }, + { QtMedia::Lyrics, L"WM/Lyrics" }, + { QtMedia::Mood, L"WM/Mood" }, + { QtMedia::TrackNumber, L"WM/TrackNumber" }, + //{ QtMedia::TrackCount, 0 }, + //{ QtMedia::CoverArtUriSmall, 0 }, + //{ QtMedia::CoverArtUriLarge, 0 }, + + // Image/Video + //{ QtMedia::Resolution, 0 }, + //{ QtMedia::PixelAspectRatio, 0 }, + + // Video + //{ QtMedia::FrameRate, 0 }, + { QtMedia::VideoBitRate, L"VideoBitRate" }, + { QtMedia::VideoCodec, L"VideoCodec" }, + + //{ QtMedia::PosterUri, 0 }, + + // Movie + { QtMedia::ChapterNumber, L"ChapterNumber" }, + { QtMedia::Director, L"WM/Director" }, + { QtMedia::LeadPerformer, L"LeadPerformer" }, + { QtMedia::Writer, L"WM/Writer" }, + + // Photos + { QtMedia::CameraManufacturer, L"CameraManufacturer" }, + { QtMedia::CameraModel, L"CameraModel" }, + { QtMedia::Event, L"Event" }, + { QtMedia::Subject, L"Subject" } +}; + +static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key) +{ + WORD streamNumber = 0; + WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD; + WORD size = 0; + + if (header->GetAttributeByName(&streamNumber, key, &type, 0, &size) == S_OK) { + switch (type) { + case WMT_TYPE_DWORD: + if (size == sizeof(DWORD)) { + DWORD word; + if (header->GetAttributeByName( + &streamNumber, + key, + &type, + reinterpret_cast(&word), + &size) == S_OK) { + return int(word); + } + } + break; + case WMT_TYPE_STRING: + { + QString string; + string.resize(size / 2 - 1); + + if (header->GetAttributeByName( + &streamNumber, + key, + &type, + reinterpret_cast(const_cast(string.utf16())), + &size) == S_OK) { + return string; + } + } + break; + case WMT_TYPE_BINARY: + { + QByteArray bytes; + bytes.resize(size); + if (header->GetAttributeByName( + &streamNumber, + key, + &type, + reinterpret_cast(bytes.data()), + &size) == S_OK) { + return bytes; + } + } + break; + case WMT_TYPE_BOOL: + if (size == sizeof(DWORD)) { + DWORD word; + if (header->GetAttributeByName( + &streamNumber, + key, + &type, + reinterpret_cast(&word), + &size) == S_OK) { + return bool(word); + } + } + break; + case WMT_TYPE_QWORD: + if (size == sizeof(QWORD)) { + QWORD word; + if (header->GetAttributeByName( + &streamNumber, + key, + &type, + reinterpret_cast(&word), + &size) == S_OK) { + return qint64(word); + } + } + break; + case WMT_TYPE_WORD: + if (size == sizeof(WORD)){ + WORD word; + if (header->GetAttributeByName( + &streamNumber, + key, + &type, + reinterpret_cast(&word), + &size) == S_OK) { + return short(word); + } + } + break; + case WMT_TYPE_GUID: + if (size == 16) { + } + break; + default: + break; + } + } + return QVariant(); +} + +DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent) + : QMetaDataControl(parent) + , m_content(0) + , m_headerInfo(0) +{ +} + +DirectShowMetaDataControl::~DirectShowMetaDataControl() +{ +} + +bool DirectShowMetaDataControl::isWritable() const +{ + return false; +} + +bool DirectShowMetaDataControl::isMetaDataAvailable() const +{ + return m_content || m_headerInfo; +} + +QVariant DirectShowMetaDataControl::metaData(QtMedia::MetaData key) const +{ + QVariant value; + + if (m_headerInfo) { + static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup); + for (int i = 0; i < count; ++i) { + if (qt_wmMetaDataKeys[i].key == key) { + value = getValue(m_headerInfo, qt_wmMetaDataKeys[i].token); + break; + } + } + } else if (m_content) { + BSTR string = 0; + + switch (key) { + case QtMedia::Author: + m_content->get_AuthorName(&string); + break; + case QtMedia::Title: + m_content->get_Title(&string); + break; + case QtMedia::ParentalRating: + m_content->get_Rating(&string); + break; + case QtMedia::Description: + m_content->get_Description(&string); + break; + case QtMedia::Copyright: + m_content->get_Copyright(&string); + break; + default: + break; + } + + if (string) { + value = QString::fromUtf16(string, ::SysStringLen(string)); + + ::SysFreeString(string); + } + } + return value; +} + +void DirectShowMetaDataControl::setMetaData(QtMedia::MetaData, const QVariant &) +{ +} + +QList DirectShowMetaDataControl::availableMetaData() const +{ + return QList(); +} + +QVariant DirectShowMetaDataControl::extendedMetaData(const QString &) const +{ + return QVariant(); +} + +void DirectShowMetaDataControl::setExtendedMetaData(const QString &, const QVariant &) +{ +} + +QStringList DirectShowMetaDataControl::availableExtendedMetaData() const +{ + return QStringList(); +} + +void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source) +{ + if (m_content) + m_content->Release(); + + if (m_headerInfo) + m_headerInfo->Release(); + + if (!graph || graph->QueryInterface( + IID_IAMMediaContent, reinterpret_cast(&m_content)) != S_OK) { + m_content = 0; + } + + m_headerInfo = com_cast(source); + + // DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later + // time. + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged))); +} + +void DirectShowMetaDataControl::customEvent(QEvent *event) +{ + if (event->type() == QEvent::Type(MetaDataChanged)) { + event->accept(); + + emit metaDataChanged(); + emit metaDataAvailableChanged(m_content || m_headerInfo); + } else { + QMetaDataControl::customEvent(event); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h new file mode 100644 index 0000000..9bb5fcc --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWMETADATACONTROL_H +#define DIRECTSHOWMETADATACONTROL_H + +#include + +#include +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowPlayerService; + + +class DirectShowMetaDataControl : public QMetaDataControl +{ + Q_OBJECT +public: + DirectShowMetaDataControl(QObject *parent = 0); + ~DirectShowMetaDataControl(); + + bool isWritable() const; + bool isMetaDataAvailable() const; + + QVariant metaData(QtMedia::MetaData key) const; + void setMetaData(QtMedia::MetaData key, const QVariant &value); + QList availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const; + void setExtendedMetaData(const QString &key, const QVariant &value); + QStringList availableExtendedMetaData() const; + + void updateGraph(IFilterGraph2 *graph, IBaseFilter *source); + +protected: + void customEvent(QEvent *event); + +private: + enum Event + { + MetaDataChanged = QEvent::User + }; + + IAMMediaContent *m_content; + IWMHeaderInfo *m_headerInfo; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.cpp new file mode 100644 index 0000000..19f65da --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowpinenum.h" + +#include + + +QT_BEGIN_NAMESPACE + +DirectShowPinEnum::DirectShowPinEnum(const QList &pins) + : m_ref(1) + , m_pins(pins) + , m_index(0) +{ + foreach (IPin *pin, m_pins) + pin->AddRef(); +} + +DirectShowPinEnum::~DirectShowPinEnum() +{ + foreach (IPin *pin, m_pins) + pin->Release(); +} + +HRESULT DirectShowPinEnum::QueryInterface(REFIID riid, void **ppvObject) +{ + if (riid == IID_IUnknown + || riid == IID_IEnumPins) { + AddRef(); + + *ppvObject = static_cast(this); + + return S_OK; + } else { + *ppvObject = 0; + + return E_NOINTERFACE; + } +} + +ULONG DirectShowPinEnum::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG DirectShowPinEnum::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + if (ref == 0) { + delete this; + } + + return ref; +} + +HRESULT DirectShowPinEnum::Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched) +{ + if (ppPins && (pcFetched || cPins == 1)) { + ULONG count = qBound(0, cPins, m_pins.count() - m_index); + + for (ULONG i = 0; i < count; ++i, ++m_index) { + ppPins[i] = m_pins.at(m_index); + ppPins[i]->AddRef(); + } + + if (pcFetched) + *pcFetched = count; + + return count == cPins ? S_OK : S_FALSE; + } else { + return E_POINTER; + } +} + +HRESULT DirectShowPinEnum::Skip(ULONG cPins) +{ + m_index = qMin(int(m_index + cPins), m_pins.count()); + + return m_index < m_pins.count() ? S_OK : S_FALSE; +} + +HRESULT DirectShowPinEnum::Reset() +{ + m_index = 0; + + return S_OK; +} + +HRESULT DirectShowPinEnum::Clone(IEnumPins **ppEnum) +{ + if (ppEnum) { + *ppEnum = new DirectShowPinEnum(m_pins); + + return S_OK; + } else { + return E_POINTER; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.h new file mode 100644 index 0000000..40d99ea --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowpinenum.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWPINENUM_H +#define DIRECTSHOWPINENUM_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowPinEnum : public IEnumPins +{ +public: + DirectShowPinEnum(const QList &pins); + ~DirectShowPinEnum(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IEnumPins + HRESULT STDMETHODCALLTYPE Next(ULONG cPins, IPin **ppPins, ULONG *pcFetched); + HRESULT STDMETHODCALLTYPE Skip(ULONG cPins); + HRESULT STDMETHODCALLTYPE Reset(); + HRESULT STDMETHODCALLTYPE Clone(IEnumPins **ppEnum); + +private: + LONG m_ref; + QList m_pins; + int m_index; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp new file mode 100644 index 0000000..a4308d7 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp @@ -0,0 +1,369 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowplayercontrol.h" + +#include "directshowplayerservice.h" + +#include +#include + + +QT_BEGIN_NAMESPACE + +static int volumeToDecibels(int volume) +{ + if (volume == 0) { + return -10000; + } else if (volume == 100) { + return 0; +#ifdef QT_USE_MATH_H_FLOATS + } else if (sizeof(qreal) == sizeof(float)) { + return qRound(::log10f(float(volume) / 100) * 5000); +#endif + } else { + return qRound(::log10(qreal(volume) / 100) * 5000); + } +} + +static int decibelsToVolume(int dB) +{ + if (dB == -10000) { + return 0; + } else if (dB == 0) { + return 100; + } else { + return qRound(100 * qPow(10, qreal(dB) / 5000)); + } +} + +DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent) + : QMediaPlayerControl(parent) + , m_service(service) + , m_audio(0) + , m_updateProperties(0) + , m_state(QMediaPlayer::StoppedState) + , m_status(QMediaPlayer::UnknownMediaStatus) + , m_streamTypes(0) + , m_muteVolume(-1) + , m_duration(0) + , m_playbackRate(0) + , m_seekable(false) +{ +} + +DirectShowPlayerControl::~DirectShowPlayerControl() +{ + if (m_audio) + m_audio->Release(); +} + +QMediaPlayer::State DirectShowPlayerControl::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus DirectShowPlayerControl::mediaStatus() const +{ + return m_status; +} + +qint64 DirectShowPlayerControl::duration() const +{ + return m_duration; +} + +qint64 DirectShowPlayerControl::position() const +{ + return m_service->position(); +} + +void DirectShowPlayerControl::setPosition(qint64 position) +{ + m_service->seek(position); +} + +int DirectShowPlayerControl::volume() const +{ + if (m_muteVolume >= 0) { + return m_muteVolume; + } else if (m_audio) { + long dB = 0; + + m_audio->get_Volume(&dB); + + return decibelsToVolume(dB); + } else { + return 0; + } +} + +void DirectShowPlayerControl::setVolume(int volume) +{ + int boundedVolume = qBound(0, volume, 100); + + if (m_muteVolume >= 0) { + m_muteVolume = boundedVolume; + + emit volumeChanged(m_muteVolume); + } else if (m_audio) { + m_audio->put_Volume(volumeToDecibels(volume)); + + emit volumeChanged(boundedVolume); + } +} + +bool DirectShowPlayerControl::isMuted() const +{ + return m_muteVolume >= 0; +} + +void DirectShowPlayerControl::setMuted(bool muted) +{ + if (muted && m_muteVolume < 0) { + if (m_audio) { + long dB = 0; + + m_audio->get_Volume(&dB); + + m_muteVolume = decibelsToVolume(dB); + + m_audio->put_Volume(-10000); + } else { + m_muteVolume = 0; + } + + emit mutedChanged(muted); + } else if (!muted && m_muteVolume >= 0) { + if (m_audio) { + m_audio->put_Volume(volumeToDecibels(m_muteVolume)); + } + m_muteVolume = -1; + + emit mutedChanged(muted); + } +} + +int DirectShowPlayerControl::bufferStatus() const +{ + return m_service->bufferStatus(); +} + +bool DirectShowPlayerControl::isAudioAvailable() const +{ + return m_streamTypes & DirectShowPlayerService::AudioStream; +} + +bool DirectShowPlayerControl::isVideoAvailable() const +{ + return m_streamTypes & DirectShowPlayerService::VideoStream; +} + +bool DirectShowPlayerControl::isSeekable() const +{ + return m_seekable; +} + +QMediaTimeRange DirectShowPlayerControl::availablePlaybackRanges() const +{ + return m_service->availablePlaybackRanges(); +} + +qreal DirectShowPlayerControl::playbackRate() const +{ + return m_playbackRate; +} + +void DirectShowPlayerControl::setPlaybackRate(qreal rate) +{ + if (m_playbackRate != rate) { + m_service->setRate(rate); + + emit playbackRateChanged(m_playbackRate = rate); + } +} + +QMediaContent DirectShowPlayerControl::media() const +{ + return m_media; +} + +const QIODevice *DirectShowPlayerControl::mediaStream() const +{ + return m_stream; +} + +void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream) +{ + m_media = media; + m_stream = stream; + + m_updateProperties &= PlaybackRateProperty; + + m_service->load(media, stream); + + emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream); + emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); + emit durationChanged(m_duration); + emit seekableChanged(m_seekable); + emit mediaStatusChanged(m_status); + emit stateChanged(m_state); +} + +void DirectShowPlayerControl::play() +{ + m_service->play(); + emit stateChanged(m_state = QMediaPlayer::PlayingState); +} + +void DirectShowPlayerControl::pause() +{ + m_service->pause(); + emit stateChanged(m_state = QMediaPlayer::PausedState); +} + +void DirectShowPlayerControl::stop() +{ + m_service->stop(); + emit stateChanged(m_state = QMediaPlayer::StoppedState); +} + +void DirectShowPlayerControl::customEvent(QEvent *event) +{ + if (event->type() == QEvent::Type(PropertiesChanged)) { + int properties = m_updateProperties; + m_updateProperties = 0; + + if (properties & PlaybackRateProperty) + emit playbackRateChanged(m_playbackRate); + + if (properties & StreamTypesProperty) { + emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream); + emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); + } + + if (properties & DurationProperty) + emit durationChanged(m_duration); + + if (properties & SeekableProperty) + emit seekableChanged(m_seekable); + + if (properties & StatusProperty) + emit mediaStatusChanged(m_status); + + if (properties & StateProperty) + emit stateChanged(m_state); + + event->accept(); + } else { + QMediaPlayerControl::customEvent(event); + } +} + +void DirectShowPlayerControl::scheduleUpdate(int properties) +{ + if (m_updateProperties == 0) + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PropertiesChanged))); + + m_updateProperties |= properties; +} + +void DirectShowPlayerControl::updateState(QMediaPlayer::State state) +{ + if (m_state != state) { + m_state = state; + + scheduleUpdate(StateProperty); + } +} + +void DirectShowPlayerControl::updateStatus(QMediaPlayer::MediaStatus status) +{ + if (m_status != status) { + m_status = status; + + scheduleUpdate(StatusProperty); + } +} + +void DirectShowPlayerControl::updateMediaInfo(qint64 duration, int streamTypes, bool seekable) +{ + int properties = 0; + + if (m_duration != duration) { + m_duration = duration; + + properties |= DurationProperty; + } + if (m_streamTypes != streamTypes) { + m_streamTypes = streamTypes; + + properties |= StreamTypesProperty; + } + + if (m_seekable != seekable) { + m_seekable = seekable; + + properties |= SeekableProperty; + } + + if (properties != 0) + scheduleUpdate(properties); +} + +void DirectShowPlayerControl::updatePlaybackRate(qreal rate) +{ + if (m_playbackRate != rate) { + m_playbackRate = rate; + + scheduleUpdate(PlaybackRateProperty); + } +} + +void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter) +{ + if (m_audio) + m_audio->Release(); + + m_audio = com_cast(filter); +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h new file mode 100644 index 0000000..af2cd3f --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWPLAYERCONTROL_H +#define DIRECTSHOWPLAYERCONTROL_H + +#include +#include + +#include + +#include "directshowplayerservice.h" + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT +public: + DirectShowPlayerControl(DirectShowPlayerService *service, QObject *parent = 0); + ~DirectShowPlayerControl(); + + QMediaPlayer::State state() const; + + QMediaPlayer::MediaStatus mediaStatus() const; + + qint64 duration() const; + + qint64 position() const; + void setPosition(qint64 position); + + int volume() const; + void setVolume(int volume); + + bool isMuted() const; + void setMuted(bool muted); + + int bufferStatus() const; + + bool isAudioAvailable() const; + bool isVideoAvailable() const; + + bool isSeekable() const; + + QMediaTimeRange availablePlaybackRanges() const; + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent &media, QIODevice *stream); + + void play(); + void pause(); + void stop(); + + void updateState(QMediaPlayer::State state); + void updateStatus(QMediaPlayer::MediaStatus status); + void updateMediaInfo(qint64 duration, int streamTypes, bool seekable); + void updatePlaybackRate(qreal rate); + void updateAudioOutput(IBaseFilter *filter); + + using QMediaPlayerControl::error; + +protected: + void customEvent(QEvent *event); + +private: + enum Properties + { + StateProperty = 0x01, + StatusProperty = 0x02, + StreamTypesProperty = 0x04, + DurationProperty = 0x08, + PlaybackRateProperty = 0x10, + SeekableProperty = 0x20 + }; + + enum Event + { + PropertiesChanged = QEvent::User + }; + + void scheduleUpdate(int properties); + + DirectShowPlayerService *m_service; + IBasicAudio *m_audio; + QIODevice *m_stream; + int m_updateProperties; + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_status; + int m_streamTypes; + int m_muteVolume; + qint64 m_duration; + qreal m_playbackRate; + bool m_seekable; + QMediaContent m_media; + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp new file mode 100644 index 0000000..ea4b73c --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -0,0 +1,1235 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowplayerservice.h" + +#include "directshowaudioendpointcontrol.h" +#include "directshowiosource.h" +#include "directshowmetadatacontrol.h" +#include "directshowplayercontrol.h" +#include "directshowvideooutputcontrol.h" +#include "directshowvideorenderercontrol.h" +#include "vmr9videowindowcontrol.h" + +#include + +#include +#include +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + +class DirectShowPlayerServiceThread : public QThread +{ +public: + DirectShowPlayerServiceThread(DirectShowPlayerService *service) + : m_service(service) + { + } + +protected: + void run() { m_service->run(); } + +private: + DirectShowPlayerService *m_service; +}; + +DirectShowPlayerService::DirectShowPlayerService(QObject *parent) + : QMediaService(parent) + , m_playerControl(0) + , m_audioEndpointControl(0) + , m_metaDataControl(0) + , m_videoOutputControl(0) + , m_videoRendererControl(0) + , m_videoWindowControl(0) + , m_taskThread(0) + , m_pendingTasks(0) + , m_executingTask(0) + , m_executedTasks(0) + , m_graphStatus(NoMedia) + , m_stream(0) + , m_graph(0) + , m_source(0) + , m_audioOutput(0) + , m_videoOutput(0) + , m_rate(1.0) + , m_position(0) + , m_duration(0) + , m_buffering(false) + , m_seekable(false) +{ + m_playerControl = new DirectShowPlayerControl(this); + m_metaDataControl = new DirectShowMetaDataControl(this); + m_videoOutputControl = new DirectShowVideoOutputControl; + m_audioEndpointControl = new DirectShowAudioEndpointControl(this); + m_videoRendererControl = new DirectShowVideoRendererControl(&m_loop); + m_videoWindowControl = new Vmr9VideoWindowControl; + + m_taskThread = new DirectShowPlayerServiceThread(this); + m_taskThread->start(); + + connect(m_videoOutputControl, SIGNAL(outputChanged()), this, SLOT(videoOutputChanged())); + connect(m_videoRendererControl, SIGNAL(filterChanged()), this, SLOT(videoOutputChanged())); + + connect(&m_graphEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(graphEvent(HANDLE))); +} + +DirectShowPlayerService::~DirectShowPlayerService() +{ + { + QMutexLocker locker(&m_mutex); + + m_pendingTasks = Shutdown; + + if (m_graph) { + m_graphEventNotifier.setEnabled(false); + + if (IAMOpenProgress *progress = com_cast(m_graph)) { + progress->AbortOperation(); + progress->Release(); + } + + m_graph->Abort(); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + OAFilterState state; + control->GetState(INFINITE, &state); + control->Release(); + } + } + m_wait.wakeAll(); + + m_loop.wait(&m_mutex); + } + + m_taskThread->wait(); + delete m_taskThread; + + if (m_graph) { + m_graph->Release(); + m_graph = 0; + } + + if (m_source) { + m_source->Release(); + m_source = 0; + } + + if (m_audioOutput) { + m_audioOutput->Release(); + m_audioOutput = 0; + } + + if (m_videoOutput) { + m_videoOutput->Release(); + m_videoOutput = 0; + } + + delete m_playerControl; + delete m_audioEndpointControl; + delete m_metaDataControl; + delete m_videoOutputControl; + delete m_videoRendererControl; + delete m_videoWindowControl; +} + +QMediaControl *DirectShowPlayerService::control(const char *name) const +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return m_playerControl; + else if (qstrcmp(name, QAudioEndpointSelector_iid) == 0) + return m_audioEndpointControl; + else if (qstrcmp(name, QMetaDataControl_iid) == 0) + return m_metaDataControl; + else if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return m_videoOutputControl; + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return m_videoRendererControl; + else if (qstrcmp(name, QVideoWindowControl_iid) == 0) + return m_videoWindowControl; + else + return 0; +} + +void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream) +{ + QMutexLocker locker(&m_mutex); + + if (m_graph) { + m_graphEventNotifier.setEnabled(false); + + if (m_executingTask != 0) { + if (IAMOpenProgress *progress = com_cast(m_graph)) { + progress->AbortOperation(); + progress->Release(); + } else { + m_graph->Abort(); + } + + m_pendingTasks = Stop; + + m_loop.wait(&m_mutex); + } + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + + if (m_source) { + m_source->Release(); + m_source = 0; + } + + m_graph->Release(); + m_graph = 0; + } + + m_resources = media.resources(); + m_stream = stream; + m_duration = 0; + m_streamTypes = 0; + m_executedTasks = 0; + m_buffering = false; + m_seekable = false; + m_metaDataControl->updateGraph(0, 0); + + if (m_resources.isEmpty() && !stream) { + m_pendingTasks = 0; + m_graphStatus = NoMedia; + + m_url.clear(); + } else { + m_graphStatus = Loading; + + m_graph = com_new(CLSID_FilterGraph); + + if (IMediaEventEx *event = com_cast(m_graph)) { + HANDLE handle; + if (event->GetEventHandle(reinterpret_cast(&handle)) == S_OK) { + m_graphEventNotifier.setHandle(handle); + m_graphEventNotifier.setEnabled(true); + } + event->Release(); + } + + if (stream) + m_pendingTasks = SetStreamSource; + else + m_pendingTasks = SetUrlSource; + + m_wait.wakeAll(); + } + + m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); + m_playerControl->updateState(QMediaPlayer::StoppedState); + updateStatus(); +} + +void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) +{ + IBaseFilter *source = 0; + + QMediaResource resource = m_resources.takeFirst(); + QUrl url = resource.url(); + + HRESULT hr = E_FAIL; + + if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) { + if (IFileSourceFilter *fileSource = com_new(CLSID_WMAsfReader)) { + locker->unlock(); + hr = fileSource->Load(url.toString().utf16(), 0); + locker->relock(); + + if (SUCCEEDED(hr)) { + source = com_cast(fileSource); + + if (!SUCCEEDED(hr = m_graph->AddFilter(source, L"Source")) && source) { + source->Release(); + source = 0; + } + } + + fileSource->Release(); + } + } + + if (!SUCCEEDED(hr)) { + locker->unlock(); + hr = m_graph->AddSourceFilter(url.toString().utf16(), L"Source", &source); + locker->relock(); + } + + if (SUCCEEDED(hr)) { + m_executedTasks = SetSource; + m_pendingTasks |= Render; + + if (m_audioOutput) + m_pendingTasks |= SetAudioOutput; + if (m_videoOutput) + m_pendingTasks |= SetVideoOutput; + + if (m_rate != 1.0) + m_pendingTasks |= SetRate; + + m_source = source; + } else if (!m_resources.isEmpty()) { + m_pendingTasks |= SetUrlSource; + } else { + m_pendingTasks = 0; + m_graphStatus = InvalidMedia; + + switch (hr) { + case VFW_E_UNKNOWN_FILE_TYPE: + m_error = QMediaPlayer::FormatError; + break; + case E_OUTOFMEMORY: + case VFW_E_CANNOT_LOAD_SOURCE_FILTER: + case VFW_E_NOT_FOUND: + m_error = QMediaPlayer::ResourceError; + default: + m_error = QMediaPlayer::ResourceError; + qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", hr); + break; + } + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); + } +} + +void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) +{ + IBaseFilter *source = new DirectShowIOSource(m_stream, &m_loop); + + if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) { + m_executedTasks = SetSource; + m_pendingTasks |= Render; + + if (m_audioOutput) + m_pendingTasks |= SetAudioOutput; + if (m_videoOutput) + m_pendingTasks |= SetVideoOutput; + + if (m_rate != 1.0) + m_pendingTasks |= SetRate; + + m_source = source; + } else { + source->Release(); + + m_pendingTasks = 0; + m_graphStatus = InvalidMedia; + + m_error = QMediaPlayer::ResourceError; + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); + } +} + +void DirectShowPlayerService::doRender(QMutexLocker *locker) +{ + if (m_pendingTasks & SetAudioOutput) { + m_graph->AddFilter(m_audioOutput, L"AudioOutput"); + + m_pendingTasks ^= SetAudioOutput; + m_executedTasks |= SetAudioOutput; + } + if (m_pendingTasks & SetVideoOutput) { + m_graph->AddFilter(m_videoOutput, L"VideoOutput"); + + m_pendingTasks ^= SetVideoOutput; + m_executedTasks |= SetVideoOutput; + } + + IFilterGraph2 *graph = m_graph; + graph->AddRef(); + + QVarLengthArray filters; + m_source->AddRef(); + filters.append(m_source); + + bool rendered = false; + + HRESULT renderHr = S_OK; + + while (!filters.isEmpty()) { + IEnumPins *pins = 0; + IBaseFilter *filter = filters[filters.size() - 1]; + filters.removeLast(); + + if (m_executingTask == Render && SUCCEEDED(filter->EnumPins(&pins))) { + int outputs = 0; + for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { + PIN_DIRECTION direction; + if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) { + ++outputs; + + IPin *peer = 0; + if (pin->ConnectedTo(&peer) == S_OK) { + PIN_INFO peerInfo; + if (peer->QueryPinInfo(&peerInfo) == S_OK) + filters.append(peerInfo.pFilter); + peer->Release(); + } else { + locker->unlock(); + HRESULT hr; + if (SUCCEEDED(hr = graph->RenderEx( + pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, 0))) { + rendered = true; + } else if (renderHr == S_OK || renderHr == VFW_E_NO_DECOMPRESSOR){ + renderHr = hr; + } + locker->relock(); + } + } + } + if (outputs == 0) + rendered = true; + } + filter->Release(); + } + + + if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) { + graph->RemoveFilter(m_audioOutput); + + m_executedTasks &= ~SetAudioOutput; + } + + if (m_videoOutput && !isConnected(m_videoOutput, PINDIR_INPUT)) { + graph->RemoveFilter(m_videoOutput); + + m_executedTasks &= ~SetVideoOutput; + } + + graph->Release(); + + if (m_executingTask == Render) { + if (rendered) { + if (!(m_executedTasks & FinalizeLoad)) + m_pendingTasks |= FinalizeLoad; + } else { + m_pendingTasks = 0; + + m_graphStatus = InvalidMedia; + + if (!m_audioOutput && !m_videoOutput) { + m_error = QMediaPlayer::ResourceError; + } else { + switch (renderHr) { + case VFW_E_UNSUPPORTED_AUDIO: + case VFW_E_UNSUPPORTED_VIDEO: + case VFW_E_UNSUPPORTED_STREAM: + m_error = QMediaPlayer::FormatError; + default: + m_error = QMediaPlayer::ResourceError; + qWarning("DirectShowPlayerService::doRender: Unresolved error code %x", + renderHr); + } + } + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); + } + + m_executedTasks |= Render; + } + + m_loop.wake(); +} + +void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) +{ + if (m_graphStatus != Loaded) { + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG duration = 0; + seeking->GetDuration(&duration); + m_duration = duration / 10; + + DWORD capabilities = 0; + seeking->GetCapabilities(&capabilities); + m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute; + + seeking->Release(); + } + } + + if ((m_executedTasks & SetOutputs) == SetOutputs) { + m_streamTypes = AudioStream | VideoStream; + } else { + m_streamTypes = findStreamTypes(m_source); + } + + m_executedTasks |= FinalizeLoad; + + m_graphStatus = Loaded; + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(FinalizedLoad))); +} + + +void DirectShowPlayerService::doUpdateDuration(QMutexLocker *) +{ + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG duration = 0; + seeking->GetDuration(&duration); + m_duration = duration / 10; + + DWORD capabilities = 0; + seeking->GetCapabilities(&capabilities); + m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute; + + seeking->Release(); + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(DurationChange))); + } +} + +int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const +{ + QVarLengthArray filters; + source->AddRef(); + filters.append(source); + + int streamTypes = 0; + + while (!filters.isEmpty()) { + IEnumPins *pins = 0; + IBaseFilter *filter = filters[filters.size() - 1]; + filters.removeLast(); + + if (SUCCEEDED(filter->EnumPins(&pins))) { + for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { + PIN_DIRECTION direction; + if (pin->QueryDirection(&direction) == S_OK && direction == PINDIR_OUTPUT) { + AM_MEDIA_TYPE connectionType; + if (SUCCEEDED(pin->ConnectionMediaType(&connectionType))) { + IPin *peer = 0; + + if (connectionType.majortype == MEDIATYPE_Audio) { + streamTypes |= AudioStream; + } else if (connectionType.majortype == MEDIATYPE_Video) { + streamTypes |= VideoStream; + } else if (SUCCEEDED(pin->ConnectedTo(&peer))) { + PIN_INFO peerInfo; + if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) + filters.append(peerInfo.pFilter); + peer->Release(); + } + } else { + streamTypes |= findStreamType(pin); + } + } + } + } + filter->Release(); + } + return streamTypes; +} + +int DirectShowPlayerService::findStreamType(IPin *pin) const +{ + IEnumMediaTypes *types; + + if (SUCCEEDED(pin->EnumMediaTypes(&types))) { + bool video = false; + bool audio = false; + bool other = false; + + for (AM_MEDIA_TYPE *type = 0; + types->Next(1, &type, 0) == S_OK; + DirectShowMediaType::deleteType(type)) { + if (type->majortype == MEDIATYPE_Audio) + audio = true; + else if (type->majortype == MEDIATYPE_Video) + video = true; + else + other = true; + } + types->Release(); + + if (other) + return 0; + else if (audio && !video) + return AudioStream; + else if (!audio && video) + return VideoStream; + else + return 0; + } else { + return 0; + } +} + +void DirectShowPlayerService::play() +{ + QMutexLocker locker(&m_mutex); + + m_pendingTasks &= ~Pause; + m_pendingTasks |= Play; + + if (m_executedTasks & Render) { + if (m_executedTasks & Stop) { + m_position = 0; + m_pendingTasks |= Seek; + m_executedTasks ^= Stop; + } + + m_wait.wakeAll(); + } +} + +void DirectShowPlayerService::doPlay(QMutexLocker *locker) +{ + if (IMediaControl *control = com_cast(m_graph)) { + locker->unlock(); + HRESULT hr = control->Run(); + locker->relock(); + + control->Release(); + + if (SUCCEEDED(hr)) + m_executedTasks |= Play; + + if (SUCCEEDED(hr)) { + m_executedTasks |= Play; + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Started))); + } else { + m_error = QMediaPlayer::ResourceError; + qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", hr); + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); + } + } +} + +void DirectShowPlayerService::pause() +{ + QMutexLocker locker(&m_mutex); + + m_pendingTasks &= ~Play; + m_pendingTasks |= Pause; + + if (m_executedTasks & Render) { + if (m_executedTasks & Stop) { + m_position = 0; + m_pendingTasks |= Seek; + m_executedTasks ^= Stop; + } + + m_wait.wakeAll(); + } +} + +void DirectShowPlayerService::doPause(QMutexLocker *locker) +{ + if (IMediaControl *control = com_cast(m_graph)) { + locker->unlock(); + HRESULT hr = control->Pause(); + locker->relock(); + + control->Release(); + + if (SUCCEEDED(hr)) { + m_executedTasks |= Pause; + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Paused))); + } else { + m_error = QMediaPlayer::ResourceError; + qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", hr); + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); + } + } +} + +void DirectShowPlayerService::stop() +{ + QMutexLocker locker(&m_mutex); + + m_pendingTasks &= ~(Play | Pause | Seek); + + if (m_executedTasks & Render) { + if (m_executingTask & (Play | Pause | Seek)) { + m_pendingTasks |= Stop; + + m_loop.wait(&m_mutex); + } + + if (m_executedTasks & (Play | Pause)) { + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + m_executedTasks &= ~(Play | Pause); + } + } + + m_executedTasks |= Stop; +} + +void DirectShowPlayerService::setRate(qreal rate) +{ + QMutexLocker locker(&m_mutex); + + m_rate = rate; + + m_pendingTasks |= SetRate; + + if (m_executedTasks & FinalizeLoad) + m_wait.wakeAll(); +} + +void DirectShowPlayerService::doSetRate(QMutexLocker *locker) +{ + if (IMediaSeeking *seeking = com_cast(m_graph)) { + // Cache current values as we can't query IMediaSeeking during a seek due to the + // possibility of a deadlock when flushing the VideoSurfaceFilter. + LONGLONG currentPosition = 0; + seeking->GetCurrentPosition(¤tPosition); + m_position = currentPosition / 10; + + LONGLONG minimum = 0; + LONGLONG maximum = 0; + m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum)) + ? QMediaTimeRange(minimum / 10, maximum / 10) + : QMediaTimeRange(); + + locker->unlock(); + HRESULT hr = seeking->SetRate(m_rate); + locker->relock(); + + if (!SUCCEEDED(hr)) { + double rate = 0.0; + m_rate = seeking->GetRate(&rate) + ? rate + : 1.0; + } + + seeking->Release(); + } else if (m_rate != 1.0) { + m_rate = 1.0; + } + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(RateChange))); +} + +qint64 DirectShowPlayerService::position() const +{ + QMutexLocker locker(const_cast(&m_mutex)); + + if (m_graphStatus == Loaded) { + if (m_executingTask == Seek || m_executingTask == SetRate) { + return m_position; + } else if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG position = 0; + + seeking->GetCurrentPosition(&position); + seeking->Release(); + + return position / 10; + } + } + return 0; +} + +QMediaTimeRange DirectShowPlayerService::availablePlaybackRanges() const +{ + QMutexLocker locker(const_cast(&m_mutex)); + + if (m_graphStatus == Loaded) { + if (m_executingTask == Seek || m_executingTask == SetRate) { + return m_playbackRange; + } else if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG minimum = 0; + LONGLONG maximum = 0; + + HRESULT hr = seeking->GetAvailable(&minimum, &maximum); + seeking->Release(); + + if (SUCCEEDED(hr)) + return QMediaTimeRange(minimum, maximum); + } + } + return QMediaTimeRange(); +} + +void DirectShowPlayerService::seek(qint64 position) +{ + QMutexLocker locker(&m_mutex); + + m_position = position; + + m_pendingTasks |= Seek; + + if (m_executedTasks & FinalizeLoad) + m_wait.wakeAll(); +} + +void DirectShowPlayerService::doSeek(QMutexLocker *locker) +{ + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG seekPosition = LONGLONG(m_position) * 10; + + // Cache current values as we can't query IMediaSeeking during a seek due to the + // possibility of a deadlock when flushing the VideoSurfaceFilter. + LONGLONG currentPosition = 0; + seeking->GetCurrentPosition(¤tPosition); + m_position = currentPosition / 10; + + LONGLONG minimum = 0; + LONGLONG maximum = 0; + m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum)) + ? QMediaTimeRange(minimum / 10, maximum / 10) + : QMediaTimeRange(); + + locker->unlock(); + seeking->SetPositions( + &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); + locker->relock(); + + seeking->Release(); + } +} + +int DirectShowPlayerService::bufferStatus() const +{ + QMutexLocker locker(const_cast(&m_mutex)); + + if (IWMReaderAdvanced2 *reader = com_cast(m_source)) { + DWORD percentage = 0; + + reader->GetBufferProgress(&percentage, 0); + reader->Release(); + + return percentage; + } else { + return 0; + } +} + +void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) +{ + QMutexLocker locker(&m_mutex); + + if (m_graph) { + if (m_audioOutput) { + if (m_executedTasks & SetAudioOutput) { + removeOutput(m_audioOutput); + + m_executedTasks &= ~SetAudioOutput; + } + m_audioOutput->Release(); + } + + m_audioOutput = filter; + + if (m_audioOutput) { + m_audioOutput->AddRef(); + + m_pendingTasks |= SetAudioOutput; + } else { + m_pendingTasks &= ~ SetAudioOutput; + } + + if (m_executedTasks & SetSource) { + m_pendingTasks |= Render; + + m_wait.wakeAll(); + } + } else { + if (m_audioOutput) + m_audioOutput->Release(); + + m_audioOutput = filter; + + if (m_audioOutput) + m_audioOutput->AddRef(); + } + + m_playerControl->updateAudioOutput(m_audioOutput); +} + +void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) +{ + QMutexLocker locker(&m_mutex); + + if (m_graph) { + if (m_videoOutput) { + if (m_executedTasks & SetVideoOutput) { + removeOutput(m_videoOutput); + + m_executedTasks &= ~SetVideoOutput; + } + m_videoOutput->Release(); + } + + m_videoOutput = filter; + + if (m_videoOutput) { + m_videoOutput->AddRef(); + + m_pendingTasks |= SetVideoOutput; + } else { + m_pendingTasks &= ~ SetVideoOutput; + } + + if (m_executedTasks & SetSource) { + m_pendingTasks |= Render; + + m_wait.wakeAll(); + } + } else { + if (m_videoOutput) + m_videoOutput->Release(); + + m_videoOutput = filter; + + if (m_videoOutput) + m_videoOutput->AddRef(); + } +} + +void DirectShowPlayerService::customEvent(QEvent *event) +{ + if (event->type() == QEvent::Type(FinalizedLoad)) { + event->accept(); + + QMutexLocker locker(&m_mutex); + + m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); + m_metaDataControl->updateGraph(m_graph, m_source); + + updateStatus(); + } else if (event->type() == QEvent::Type(Error)) { + event->accept(); + + QMediaPlayer::Error error; + { + QMutexLocker locker(&m_mutex); + error = m_error; + + if (error != QMediaPlayer::NoError) { + m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); + m_playerControl->updateState(QMediaPlayer::StoppedState); + updateStatus(); + } + } + m_playerControl->error(error, QString()); + } else if (event->type() == QEvent::Type(RateChange)) { + event->accept(); + + QMutexLocker locker(&m_mutex); + + m_playerControl->updatePlaybackRate(m_rate); + } else if (event->type() == QEvent::Type(Started) || event->type() == QEvent::Type(Paused)) { + event->accept(); + + QMutexLocker locker(&m_mutex); + + updateStatus(); + } else if (event->type() == QEvent::Type(DurationChange)) { + event->accept(); + + QMutexLocker locker(&m_mutex); + + m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); + } else { + QMediaService::customEvent(event); + } +} + +void DirectShowPlayerService::videoOutputChanged() +{ + IBaseFilter *videoOutput = 0; + + switch (m_videoOutputControl->output()) { + case QVideoOutputControl::RendererOutput: + videoOutput = m_videoRendererControl->filter(); + break; + case QVideoOutputControl::WindowOutput: + videoOutput = m_videoWindowControl->filter(); + break; + default: + break; + } + + setVideoOutput(videoOutput); +} + +void DirectShowPlayerService::graphEvent(HANDLE handle) +{ + if (IMediaEvent *event = com_cast(m_graph)) { + long eventCode; + LONG_PTR param1; + LONG_PTR param2; + + while (event->GetEvent(&eventCode, ¶m1, ¶m2, 0) == S_OK) { + switch (eventCode) { + case EC_BUFFERING_DATA: + { + QMutexLocker locker(&m_mutex); + m_buffering = param1; + + updateStatus(); + } + break; + case EC_COMPLETE: + { + QMutexLocker locker(&m_mutex); + m_executedTasks &= ~(Play | Pause); + m_executedTasks |= Stop; + + m_buffering = false; + m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); + m_playerControl->updateState(QMediaPlayer::StoppedState); + } + break; + case EC_LENGTH_CHANGED: + { + QMutexLocker locker(&m_mutex); + if (m_executedTasks & FinalizeLoad) { + m_pendingTasks |= UpdateDuration; + + m_wait.wakeAll(); + } + } + break; + default: + break; + } + + event->FreeEventParams(eventCode, param1, param2); + } + event->Release(); + } +} + +void DirectShowPlayerService::updateStatus() +{ + switch (m_graphStatus) { + case NoMedia: + m_playerControl->updateStatus(QMediaPlayer::NoMedia); + break; + case Loading: + m_playerControl->updateStatus(QMediaPlayer::LoadingMedia); + break; + case Loaded: + if ((m_pendingTasks | m_executingTask | m_executedTasks) & (Play | Pause)) { + if (m_buffering) + m_playerControl->updateStatus(QMediaPlayer::BufferingMedia); + else + m_playerControl->updateStatus(QMediaPlayer::BufferedMedia); + } else { + m_playerControl->updateStatus(QMediaPlayer::LoadedMedia); + } + break; + case InvalidMedia: + m_playerControl->updateStatus(QMediaPlayer::InvalidMedia); + break; + default: + m_playerControl->updateStatus(QMediaPlayer::UnknownMediaStatus); + } +} + +void DirectShowPlayerService::removeOutput(IBaseFilter *output) +{ + while (m_executingTask != 0) { + if (m_executingTask == Render) { + m_executingTask = 0; + + if (IAMOpenProgress *progress = com_cast(m_graph)) { + progress->AbortOperation(); + progress->Release(); + } + } + m_loop.wait(&m_mutex); + } + + m_pendingTasks |= m_executedTasks & (Play | Pause); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + + if (IFilterChain *chain = com_cast(m_graph)) { + IBaseFilter *start = findChainStart(output); + + chain->RemoveChain(start, output); + + start->Release(); + chain->Release(); + } else { + m_graph->RemoveFilter(output); + } +} + +IBaseFilter *DirectShowPlayerService::findChainStart(IBaseFilter *end) const +{ + IBaseFilter *start = 0; + end->AddRef(); + + while (start != end) { + start = end; + + IEnumPins *pins = 0; + + if (SUCCEEDED(end->EnumPins(&pins))) { + for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { + PIN_DIRECTION direction; + if (SUCCEEDED(pin->QueryDirection(&direction)) && direction == PINDIR_INPUT) { + IPin *peer = 0; + if (SUCCEEDED(pin->ConnectedTo(&peer))) { + PIN_INFO peerInfo; + if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) { + CLSID classId; + if (SUCCEEDED(peerInfo.pFilter->GetClassID(&classId)) + && classId == CLSID_Colour) { + end->Release(); + end = peerInfo.pFilter; + } else { + peerInfo.pFilter->Release(); + } + } + peer->Release(); + } + } + } + pins->Release(); + } + } + return start; +} + +bool DirectShowPlayerService::isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const +{ + bool connected = false; + + IEnumPins *pins = 0; + + if (SUCCEEDED(filter->EnumPins(&pins))) { + for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { + PIN_DIRECTION dir; + if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) { + IPin *peer = 0; + if (SUCCEEDED(pin->ConnectedTo(&peer))) { + connected = true; + + peer->Release(); + } + } + } + pins->Release(); + } + return connected; +} + +void DirectShowPlayerService::run() +{ + QMutexLocker locker(&m_mutex); + + while (!(m_pendingTasks & Shutdown)) { + if (m_pendingTasks & SetUrlSource) { + m_pendingTasks ^= SetUrlSource; + m_executingTask = SetUrlSource; + + doSetUrlSource(&locker); + } else if (m_pendingTasks & SetStreamSource) { + m_pendingTasks ^= SetStreamSource; + m_executingTask = SetStreamSource; + + doSetStreamSource(&locker); + } else if (m_pendingTasks & Render) { + m_pendingTasks ^= Render; + m_executingTask = Render; + + doRender(&locker); + } else if (!(m_executedTasks & Render)) { + m_pendingTasks &= ~(FinalizeLoad | SetRate | Stop | Pause | Seek | Play); + } else if (m_pendingTasks & FinalizeLoad) { + m_pendingTasks ^= FinalizeLoad; + m_executingTask = FinalizeLoad; + + doFinalizeLoad(&locker); + } else if (m_pendingTasks & UpdateDuration) { + m_pendingTasks ^= UpdateDuration; + m_executingTask ^= UpdateDuration; + + doUpdateDuration(&locker); + } else if (m_pendingTasks & SetRate) { + m_pendingTasks ^= SetRate; + m_executingTask = SetRate; + + doSetRate(&locker); + } else if (m_pendingTasks & Stop) { + m_pendingTasks ^= Stop; + + m_loop.wake(); + } else if (m_pendingTasks & Pause) { + m_pendingTasks ^= Pause; + m_executingTask = Pause; + + doPause(&locker); + } else if (m_pendingTasks & Seek) { + m_pendingTasks ^= Seek; + m_executingTask = Seek; + + doSeek(&locker); + } else if (m_pendingTasks & Play) { + m_pendingTasks ^= Play; + m_executingTask = Play; + + doPlay(&locker); + } + m_executingTask = 0; + + if (m_pendingTasks == 0) + m_wait.wait(&m_mutex); + } + + m_loop.wake(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h new file mode 100644 index 0000000..3a01889 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWPLAYERSERVICE_H +#define DIRECTSHOWPLAYERSERVICE_H + +#include +#include +#include +#include + +#include "directshoweventloop.h" +#include "directshowglobal.h" + +#include +#include +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowAudioEndpointControl; +class DirectShowMetaDataControl; +class DirectShowPlayerControl; +class DirectShowVideoOutputControl; +class DirectShowVideoRendererControl; +class Vmr9VideoWindowControl; + +class DirectShowPlayerService : public QMediaService +{ + Q_OBJECT +public: + enum StreamType + { + AudioStream = 0x01, + VideoStream = 0x02 + }; + + DirectShowPlayerService(QObject *parent = 0); + ~DirectShowPlayerService(); + + QMediaControl* control(const char *name) const; + + void load(const QMediaContent &media, QIODevice *stream); + void play(); + void pause(); + void stop(); + + qint64 position() const; + QMediaTimeRange availablePlaybackRanges() const; + + void seek(qint64 position); + void setRate(qreal rate); + + int bufferStatus() const; + + void setAudioOutput(IBaseFilter *filter); + void setVideoOutput(IBaseFilter *filter); + +protected: + void customEvent(QEvent *event); + +private Q_SLOTS: + void videoOutputChanged(); + void graphEvent(HANDLE handle); + +private: + void updateStatus(); + + int findStreamTypes(IBaseFilter *source) const; + int findStreamType(IPin *pin) const; + + void removeOutput(IBaseFilter *output); + IBaseFilter *findChainStart(IBaseFilter *end) const; + bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; + + void run(); + + void doSetUrlSource(QMutexLocker *locker); + void doSetStreamSource(QMutexLocker *locker); + void doRender(QMutexLocker *locker); + void doFinalizeLoad(QMutexLocker *locker); + void doSetRate(QMutexLocker *locker); + void doSeek(QMutexLocker *locker); + void doPlay(QMutexLocker *locker); + void doPause(QMutexLocker *locker); + void doUpdateDuration(QMutexLocker *locker); + + enum Task + { + Shutdown = 0x0001, + SetUrlSource = 0x0002, + SetStreamSource = 0x0004, + SetSource = SetUrlSource | SetStreamSource, + SetAudioOutput = 0x0008, + SetVideoOutput = 0x0010, + SetOutputs = SetAudioOutput | SetVideoOutput, + Render = 0x0020, + FinalizeLoad = 0x0040, + SetRate = 0x0080, + Seek = 0x0100, + Play = 0x0200, + Pause = 0x0400, + Stop = 0x0800, + UpdateDuration = 0x1000 + }; + + enum Event + { + FinalizedLoad = QEvent::User, + Error, + RateChange, + Started, + Paused, + DurationChange + }; + + enum GraphStatus + { + NoMedia, + Loading, + Loaded, + InvalidMedia + }; + + DirectShowPlayerControl *m_playerControl; + DirectShowMetaDataControl *m_metaDataControl; + DirectShowVideoOutputControl *m_videoOutputControl; + DirectShowVideoRendererControl *m_videoRendererControl; + Vmr9VideoWindowControl *m_videoWindowControl; + DirectShowAudioEndpointControl *m_audioEndpointControl; + + QThread *m_taskThread; + int m_pendingTasks; + int m_executingTask; + int m_executedTasks; + GraphStatus m_graphStatus; + QMediaPlayer::Error m_error; + QIODevice *m_stream; + IFilterGraph2 *m_graph; + IBaseFilter *m_source; + IBaseFilter *m_audioOutput; + IBaseFilter *m_videoOutput; + int m_streamTypes; + qreal m_rate; + qint64 m_position; + qint64 m_duration; + bool m_buffering; + bool m_seekable; + QMediaTimeRange m_playbackRange; + QUrl m_url; + QMediaResourceList m_resources; + QMutex m_mutex; + QWaitCondition m_wait; + QWinEventNotifier m_graphEventNotifier; + DirectShowEventLoop m_loop; + + friend class DirectShowPlayerServiceThread; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp new file mode 100644 index 0000000..921330c --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp @@ -0,0 +1,394 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowsamplescheduler.h" + +#include + + +QT_BEGIN_NAMESPACE + +class DirectShowTimedSample +{ +public: + DirectShowTimedSample(IMediaSample *sample) + : m_next(0) + , m_sample(sample) + , m_cookie(0) + { + m_sample->AddRef(); + } + + ~DirectShowTimedSample() + { + m_sample->Release(); + } + + IMediaSample *sample() const { return m_sample; } + + DirectShowTimedSample *nextSample() const { return m_next; } + void setNextSample(DirectShowTimedSample *sample) { Q_ASSERT(!m_next); m_next = sample; } + + DirectShowTimedSample *remove() { + DirectShowTimedSample *next = m_next; delete this; return next; } + + bool schedule(IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle); + void unschedule(IReferenceClock *clock); + + bool isReady(IReferenceClock *clock) const; + +private: + DirectShowTimedSample *m_next; + IMediaSample *m_sample; + DWORD_PTR m_cookie; +}; + +bool DirectShowTimedSample::schedule( + IReferenceClock *clock, REFERENCE_TIME startTime, HANDLE handle) +{ + REFERENCE_TIME sampleStartTime; + REFERENCE_TIME sampleEndTime; + if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) { + if (clock->AdviseTime( + startTime, sampleStartTime, reinterpret_cast(handle), &m_cookie) == S_OK) { + return true; + } + } + return false; +} + +void DirectShowTimedSample::unschedule(IReferenceClock *clock) +{ + clock->Unadvise(m_cookie); +} + +bool DirectShowTimedSample::isReady(IReferenceClock *clock) const +{ + REFERENCE_TIME sampleStartTime; + REFERENCE_TIME sampleEndTime; + REFERENCE_TIME currentTime; + if (m_sample->GetTime(&sampleStartTime, &sampleEndTime) == S_OK) { + if (clock->GetTime(¤tTime) == S_OK) + return currentTime >= sampleStartTime; + } + return true; +} + +DirectShowSampleScheduler::DirectShowSampleScheduler(IUnknown *pin, QObject *parent) + : QWinEventNotifier(parent) + , m_pin(pin) + , m_clock(0) + , m_allocator(0) + , m_head(0) + , m_tail(0) + , m_maximumSamples(2) + , m_state(Stopped) + , m_startTime(0) + , m_timeoutEvent(::CreateEvent(0, 0, 0, 0)) +{ + m_semaphore.release(m_maximumSamples); + + setHandle(m_timeoutEvent); + setEnabled(true); +} + +DirectShowSampleScheduler::~DirectShowSampleScheduler() +{ + setEnabled(false); + + ::CloseHandle(m_timeoutEvent); + + Q_ASSERT(!m_clock); + Q_ASSERT(!m_allocator); +} + +HRESULT DirectShowSampleScheduler::QueryInterface(REFIID riid, void **ppvObject) +{ + return m_pin->QueryInterface(riid, ppvObject); +} + +ULONG DirectShowSampleScheduler::AddRef() +{ + return m_pin->AddRef(); +} + +ULONG DirectShowSampleScheduler::Release() +{ + return m_pin->Release(); +} + +// IMemInputPin +HRESULT DirectShowSampleScheduler::GetAllocator(IMemAllocator **ppAllocator) +{ + if (!ppAllocator) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_allocator) { + return VFW_E_NO_ALLOCATOR; + } else { + *ppAllocator = m_allocator; + + return S_OK; + } + } +} + +HRESULT DirectShowSampleScheduler::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly) +{ + Q_UNUSED(bReadOnly); + + HRESULT hr; + ALLOCATOR_PROPERTIES properties; + + if (!pAllocator) { + if (m_allocator) + m_allocator->Release(); + + m_allocator = 0; + + return S_OK; + } else if ((hr = pAllocator->GetProperties(&properties)) != S_OK) { + return hr; + } else { + if (properties.cBuffers == 1) { + ALLOCATOR_PROPERTIES actual; + + properties.cBuffers = 2; + if ((hr = pAllocator->SetProperties(&properties, &actual)) != S_OK) + return hr; + } + + QMutexLocker locker(&m_mutex); + + if (m_allocator) + m_allocator->Release(); + + m_allocator = pAllocator; + m_allocator->AddRef(); + + return S_OK; + } +} + +HRESULT DirectShowSampleScheduler::GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps) +{ + if (!pProps) + return E_POINTER; + + pProps->cBuffers = 2; + + return S_OK; +} + +HRESULT DirectShowSampleScheduler::Receive(IMediaSample *pSample) +{ + if (!pSample) + return E_POINTER; + + m_semaphore.acquire(1); + + QMutexLocker locker(&m_mutex); + + if (m_state & Flushing) { + m_semaphore.release(1); + + return S_FALSE; + } else if (m_state == Stopped) { + m_semaphore.release(); + + return VFW_E_WRONG_STATE; + } else { + DirectShowTimedSample *timedSample = new DirectShowTimedSample(pSample); + + if (m_tail) + m_tail->setNextSample(timedSample); + else + m_head = timedSample; + + m_tail = timedSample; + + if (m_state == Running) { + if (!timedSample->schedule(m_clock, m_startTime, m_timeoutEvent)) { + // Timing information is unavailable, so schedule frames immediately. + QMetaObject::invokeMethod(this, "timerActivated", Qt::QueuedConnection); + } + } else if (m_tail == m_head) { + // If this is the first frame make is available. + QMetaObject::invokeMethod(this, "timerActivated", Qt::QueuedConnection); + } + + return S_OK; + } +} + +HRESULT DirectShowSampleScheduler::ReceiveMultiple( + IMediaSample **pSamples, long nSamples, long *nSamplesProcessed) +{ + if (!pSamples || !nSamplesProcessed) + return E_POINTER; + + for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; ++(*nSamplesProcessed)) { + HRESULT hr = Receive(pSamples[*nSamplesProcessed]); + + if (hr != S_OK) + return hr; + } + return S_OK; +} + +HRESULT DirectShowSampleScheduler::ReceiveCanBlock() +{ + return S_OK; +} + +void DirectShowSampleScheduler::run(REFERENCE_TIME startTime) +{ + QMutexLocker locker(&m_mutex); + + m_state = (m_state & Flushing) | Running; + m_startTime = startTime; + + for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) { + sample->schedule(m_clock, m_startTime, m_timeoutEvent); + } +} + +void DirectShowSampleScheduler::pause() +{ + QMutexLocker locker(&m_mutex); + + m_state = (m_state & Flushing) | Paused; + + for (DirectShowTimedSample *sample = m_head; sample; sample = sample->nextSample()) + sample->unschedule(m_clock); +} + +void DirectShowSampleScheduler::stop() +{ + QMutexLocker locker(&m_mutex); + + m_state = m_state & Flushing; + + for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) { + sample->unschedule(m_clock); + + m_semaphore.release(1); + } + + m_head = 0; + m_tail = 0; +} + +void DirectShowSampleScheduler::setFlushing(bool flushing) +{ + QMutexLocker locker(&m_mutex); + + const bool isFlushing = m_state & Flushing; + + if (isFlushing != flushing) { + if (flushing) { + m_state |= Flushing; + + for (DirectShowTimedSample *sample = m_head; sample; sample = sample->remove()) { + sample->unschedule(m_clock); + + m_semaphore.release(1); + } + m_head = 0; + m_tail = 0; + } else { + m_state &= ~Flushing; + } + } +} + +void DirectShowSampleScheduler::setClock(IReferenceClock *clock) +{ + QMutexLocker locker(&m_mutex); + + if (m_clock) + m_clock->Release(); + + m_clock = clock; + + if (m_clock) + m_clock->AddRef(); +} + +IMediaSample *DirectShowSampleScheduler::takeSample() +{ + QMutexLocker locker(&m_mutex); + + if (m_head && m_head->isReady(m_clock)) { + IMediaSample *sample = m_head->sample(); + sample->AddRef(); + + if (m_state == Running) { + m_head = m_head->remove(); + + if (!m_head) + m_tail = 0; + + m_semaphore.release(1); + } + + return sample; + } else { + return 0; + } +} + +bool DirectShowSampleScheduler::event(QEvent *event) +{ + if (event->type() == QEvent::WinEventAct) { + QObject::event(event); + + emit sampleReady(); + + return true; + } else { + return QWinEventNotifier::event(event); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h new file mode 100644 index 0000000..7af9112 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWSAMPLESCHEDULER_H +#define DIRECTSHOWSAMPLESCHEDULER_H + +#include +#include +#include + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowTimedSample; + +class DirectShowSampleScheduler : public QWinEventNotifier, public IMemInputPin +{ + Q_OBJECT +public: + + enum State + { + Stopped = 0x00, + Running = 0x01, + Paused = 0x02, + RunMask = 0x03, + Flushing = 0x04 + }; + + DirectShowSampleScheduler(IUnknown *pin, QObject *parent = 0); + ~DirectShowSampleScheduler(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IMemInputPin + HRESULT STDMETHODCALLTYPE GetAllocator(IMemAllocator **ppAllocator); + HRESULT STDMETHODCALLTYPE NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly); + HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps); + + HRESULT STDMETHODCALLTYPE Receive(IMediaSample *pSample); + HRESULT STDMETHODCALLTYPE ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSamplesProcessed); + HRESULT STDMETHODCALLTYPE ReceiveCanBlock(); + + void run(REFERENCE_TIME startTime); + void pause(); + void stop(); + void setFlushing(bool flushing); + + IReferenceClock *clock() const { return m_clock; } + void setClock(IReferenceClock *clock); + + bool schedule(IMediaSample *sample); + + IMediaSample *takeSample(); + + bool event(QEvent *event); + +Q_SIGNALS: + void sampleReady(); + +private: + IUnknown *m_pin; + IReferenceClock *m_clock; + IMemAllocator *m_allocator; + DirectShowTimedSample *m_head; + DirectShowTimedSample *m_tail; + int m_maximumSamples; + int m_state; + REFERENCE_TIME m_startTime; + HANDLE m_timeoutEvent; + QSemaphore m_semaphore; + QMutex m_mutex; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.cpp new file mode 100644 index 0000000..ee2bea8 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowvideooutputcontrol.h" + + +QT_BEGIN_NAMESPACE + +DirectShowVideoOutputControl::DirectShowVideoOutputControl(QObject *parent) + : QVideoOutputControl(parent) + , m_output(NoOutput) +{ + +} + +DirectShowVideoOutputControl::~DirectShowVideoOutputControl() +{ +} + +QList DirectShowVideoOutputControl::availableOutputs() const +{ + return QList() + << RendererOutput + << WindowOutput; +} + + +QVideoOutputControl::Output DirectShowVideoOutputControl::output() const +{ + return m_output; +} + +void DirectShowVideoOutputControl::setOutput(Output output) +{ + if (output != m_output) { + switch (output) { + case NoOutput: + case RendererOutput: + case WindowOutput: + m_output = output; + emit outputChanged(); + break; + default: + break; + } + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.h new file mode 100644 index 0000000..acb2937 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideooutputcontrol.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWVIDEOUTPUTCONTROL_H +#define DIRECTSHOWVIDEOOUPUTCONTROL_H + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowVideoOutputControl : public QVideoOutputControl +{ + Q_OBJECT +public: + DirectShowVideoOutputControl(QObject *parent = 0); + ~DirectShowVideoOutputControl(); + + QList availableOutputs() const; + + Output output() const; + void setOutput(Output output); + +Q_SIGNALS: + void outputChanged(); + +private: + Output m_output; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.cpp new file mode 100644 index 0000000..f27cb10 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "directshowvideorenderercontrol.h" + +#include "videosurfacefilter.h" + + +QT_BEGIN_NAMESPACE + + +DirectShowVideoRendererControl::DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent) + : QVideoRendererControl(parent) + , m_loop(loop) + , m_surface(0) + , m_filter(0) +{ +} + +DirectShowVideoRendererControl::~DirectShowVideoRendererControl() +{ + delete m_filter; +} + +QAbstractVideoSurface *DirectShowVideoRendererControl::surface() const +{ + return m_surface; +} + +void DirectShowVideoRendererControl::setSurface(QAbstractVideoSurface *surface) +{ + if (surface != m_surface) { + m_surface = surface; + + VideoSurfaceFilter *existingFilter = m_filter; + + if (surface) { + m_filter = new VideoSurfaceFilter(surface, m_loop); + } else { + m_filter = 0; + } + + emit filterChanged(); + + delete existingFilter; + } +} + +IBaseFilter *DirectShowVideoRendererControl::filter() +{ + return m_filter; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.h new file mode 100644 index 0000000..6b4f4a2 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowvideorenderercontrol.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DIRECTSHOWVIDEORENDERERCONTROL_H +#define DIRECTSHOWVIDEORENDERERCONTROL_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class DirectShowEventLoop; +class VideoSurfaceFilter; + +class DirectShowVideoRendererControl : public QVideoRendererControl +{ + Q_OBJECT +public: + DirectShowVideoRendererControl(DirectShowEventLoop *loop, QObject *parent = 0); + ~DirectShowVideoRendererControl(); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + IBaseFilter *filter(); + +Q_SIGNALS: + void filterChanged(); + +private: + DirectShowEventLoop *m_loop; + QAbstractVideoSurface *m_surface; + VideoSurfaceFilter *m_filter; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri new file mode 100644 index 0000000..49ee9e5 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri @@ -0,0 +1,43 @@ +INCLUDEPATH += $$PWD + +DEFINES += QMEDIA_DIRECTSHOW_PLAYER + +HEADERS += \ + $$PWD/directshowaudioendpointcontrol.h \ + $$PWD/directshoweventloop.h \ + $$PWD/directshowglobal.h \ + $$PWD/directshowioreader.h \ + $$PWD/directshowiosource.h \ + $$PWD/directshowmediatype.h \ + $$PWD/directshowmediatypelist.h \ + $$PWD/directshowmetadatacontrol.h \ + $$PWD/directshowpinenum.h \ + $$PWD/directshowplayercontrol.h \ + $$PWD/directshowplayerservice.h \ + $$PWD/directshowsamplescheduler.h \ + $$PWD/directshowvideooutputcontrol.h \ + $$PWD/directshowvideorenderercontrol.h \ + $$PWD/mediasamplevideobuffer.h \ + $$PWD/videosurfacefilter.h \ + $$PWD/vmr9videowindowcontrol.h + +SOURCES += \ + $$PWD/directshowaudioendpointcontrol.cpp \ + $$PWD/directshoweventloop.cpp \ + $$PWD/directshowioreader.cpp \ + $$PWD/directshowiosource.cpp \ + $$PWD/directshowmediatype.cpp \ + $$PWD/directshowmediatypelist.cpp \ + $$PWD/directshowmetadatacontrol.cpp \ + $$PWD/directshowpinenum.cpp \ + $$PWD/directshowplayercontrol.cpp \ + $$PWD/directshowplayerservice.cpp \ + $$PWD/directshowsamplescheduler.cpp \ + $$PWD/directshowvideooutputcontrol.cpp \ + $$PWD/directshowvideorenderercontrol.cpp \ + $$PWD/mediasamplevideobuffer.cpp \ + $$PWD/videosurfacefilter.cpp \ + $$PWD/vmr9videowindowcontrol.cpp + +LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 + diff --git a/src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.cpp b/src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.cpp new file mode 100644 index 0000000..7eff226 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mediasamplevideobuffer.h" + + +QT_BEGIN_NAMESPACE + +MediaSampleVideoBuffer::MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine) + : QAbstractVideoBuffer(NoHandle) + , m_sample(sample) + , m_bytesPerLine(m_bytesPerLine) + , m_mapMode(NotMapped) +{ + m_sample->AddRef(); +} + +MediaSampleVideoBuffer::~MediaSampleVideoBuffer() +{ + m_sample->Release(); +} + +uchar *MediaSampleVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) +{ + if (m_mapMode == NotMapped && mode != NotMapped) { + if (numBytes) + *numBytes = m_sample->GetActualDataLength(); + + if (bytesPerLine) + *bytesPerLine = m_bytesPerLine; + + BYTE *bytes = 0; + + if (m_sample->GetPointer(&bytes) == S_OK) { + m_mapMode = mode; + + return reinterpret_cast(bytes); + } + } + return 0; +} + +void MediaSampleVideoBuffer::unmap() +{ + m_mapMode = NotMapped; +} + +QAbstractVideoBuffer::MapMode MediaSampleVideoBuffer::mapMode() const +{ + return m_mapMode; +} + +QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.h b/src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.h new file mode 100644 index 0000000..06dc31c --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/mediasamplevideobuffer.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MEDIASAMPLEVIDEOBUFFER_H +#define MEDIASAMPLEVIDEOBUFFER_H + +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class MediaSampleVideoBuffer : public QAbstractVideoBuffer +{ +public: + MediaSampleVideoBuffer(IMediaSample *sample, int bytesPerLine); + ~MediaSampleVideoBuffer(); + + IMediaSample *sample() { return m_sample; } + + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); + void unmap(); + + MapMode mapMode() const; + +private: + IMediaSample *m_sample; + int m_bytesPerLine; + MapMode m_mapMode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp b/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp new file mode 100644 index 0000000..a5565f1 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp @@ -0,0 +1,600 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "videosurfacefilter.h" + +#include "directshoweventloop.h" +#include "directshowpinenum.h" +#include "mediasamplevideobuffer.h" + +#include +#include +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + +// { e23cad72-153d-406c-bf3f-4c4b523d96f2 } +DEFINE_GUID(CLSID_VideoSurfaceFilter, +0xe23cad72, 0x153d, 0x406c, 0xbf, 0x3f, 0x4c, 0x4b, 0x52, 0x3d, 0x96, 0xf2); + +VideoSurfaceFilter::VideoSurfaceFilter( + QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent) + : QObject(parent) + , m_ref(1) + , m_state(State_Stopped) + , m_surface(surface) + , m_loop(loop) + , m_graph(0) + , m_peerPin(0) + , m_bytesPerLine(0) + , m_startResult(S_OK) + , m_pinId(QString::fromLatin1("reference")) + , m_sampleScheduler(static_cast(this)) +{ + connect(surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged())); + connect(&m_sampleScheduler, SIGNAL(sampleReady()), this, SLOT(sampleReady())); +} + +VideoSurfaceFilter::~VideoSurfaceFilter() +{ + Q_ASSERT(m_ref == 1); +} + +HRESULT VideoSurfaceFilter::QueryInterface(REFIID riid, void **ppvObject) +{ + if (!ppvObject) { + return E_POINTER; + } else if (riid == IID_IUnknown + || riid == IID_IPersist + || riid == IID_IMediaFilter + || riid == IID_IBaseFilter) { + *ppvObject = static_cast(this); + } else if (riid == IID_IAMFilterMiscFlags) { + *ppvObject = static_cast(this); + } else if (riid == IID_IPin) { + *ppvObject = static_cast(this); + } else if (riid == IID_IMemInputPin) { + *ppvObject = static_cast(&m_sampleScheduler); + } else { + *ppvObject = 0; + + return E_NOINTERFACE; + } + + AddRef(); + + return S_OK; +} + +ULONG VideoSurfaceFilter::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG VideoSurfaceFilter::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + Q_ASSERT(ref != 0); + + return ref; +} + +HRESULT VideoSurfaceFilter::GetClassID(CLSID *pClassID) +{ + *pClassID = CLSID_VideoSurfaceFilter; + + return S_OK; +} + +HRESULT VideoSurfaceFilter::Run(REFERENCE_TIME tStart) +{ + m_state = State_Running; + + m_sampleScheduler.run(tStart); + + return S_OK; +} + +HRESULT VideoSurfaceFilter::Pause() +{ + m_state = State_Paused; + + m_sampleScheduler.pause(); + + return S_OK; +} + +HRESULT VideoSurfaceFilter::Stop() +{ + m_state = State_Stopped; + + m_sampleScheduler.stop(); + + return S_OK; +} + +HRESULT VideoSurfaceFilter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState) +{ + if (!pState) + return E_POINTER; + + *pState = m_state; + + return S_OK; +} + +HRESULT VideoSurfaceFilter::SetSyncSource(IReferenceClock *pClock) +{ + + m_sampleScheduler.setClock(pClock); + + return S_OK; +} + +HRESULT VideoSurfaceFilter::GetSyncSource(IReferenceClock **ppClock) +{ + if (!ppClock) { + return E_POINTER; + } else { + *ppClock = m_sampleScheduler.clock(); + + if (*ppClock) { + (*ppClock)->AddRef(); + + return S_OK; + } else { + return S_FALSE; + } + } +} + +HRESULT VideoSurfaceFilter::EnumPins(IEnumPins **ppEnum) +{ + if (ppEnum) { + *ppEnum = new DirectShowPinEnum(QList() << this); + + return S_OK; + } else { + return E_POINTER; + } +} + +HRESULT VideoSurfaceFilter::FindPin(LPCWSTR pId, IPin **ppPin) +{ + if (!ppPin || !pId) { + return E_POINTER; + } else if (QString::fromWCharArray(pId) == m_pinId) { + AddRef(); + + *ppPin = this; + + return S_OK; + } else { + return VFW_E_NOT_FOUND; + } +} + +HRESULT VideoSurfaceFilter::JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName) +{ + m_graph = pGraph; + m_name = QString::fromWCharArray(pName); + + return S_OK; +} + +HRESULT VideoSurfaceFilter::QueryFilterInfo(FILTER_INFO *pInfo) +{ + if (pInfo) { + QString name = m_name; + + if (name.length() >= MAX_FILTER_NAME) + name.truncate(MAX_FILTER_NAME - 1); + + int length = name.toWCharArray(pInfo->achName); + pInfo->achName[length] = '\0'; + + if (m_graph) + m_graph->AddRef(); + + pInfo->pGraph = m_graph; + + return S_OK; + } else { + return E_POINTER; + } +} + +HRESULT VideoSurfaceFilter::QueryVendorInfo(LPWSTR *pVendorInfo) +{ + Q_UNUSED(pVendorInfo); + + return E_NOTIMPL; +} + +ULONG VideoSurfaceFilter::GetMiscFlags() +{ + return AM_FILTER_MISC_FLAGS_IS_RENDERER; +} + + +HRESULT VideoSurfaceFilter::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) +{ + // This is an input pin, you shouldn't be calling Connect on it. + return E_POINTER; +} + +HRESULT VideoSurfaceFilter::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) +{ + if (!pConnector) { + return E_POINTER; + } else if (!pmt) { + return E_POINTER; + } else { + HRESULT hr; + QMutexLocker locker(&m_mutex); + + if (m_peerPin) { + hr = VFW_E_ALREADY_CONNECTED; + } else if (pmt->majortype != MEDIATYPE_Video) { + hr = VFW_E_TYPE_NOT_ACCEPTED; + } else { + m_surfaceFormat = DirectShowMediaType::formatFromType(*pmt); + m_bytesPerLine = DirectShowMediaType::bytesPerLine(m_surfaceFormat); + + if (thread() == QThread::currentThread()) { + hr = start(); + } else { + m_loop->postEvent(this, new QEvent(QEvent::Type(StartSurface))); + + m_wait.wait(&m_mutex); + + hr = m_startResult; + } + } + if (hr == S_OK) { + m_peerPin = pConnector; + m_peerPin->AddRef(); + + DirectShowMediaType::copy(&m_mediaType, *pmt); + } + return hr; + } +} + +HRESULT VideoSurfaceFilter::start() +{ + if (!m_surface->start(m_surfaceFormat)) { + return VFW_E_TYPE_NOT_ACCEPTED; + } else { + return S_OK; + } +} + +HRESULT VideoSurfaceFilter::Disconnect() +{ + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) + return S_FALSE; + + if (thread() == QThread::currentThread()) { + stop(); + } else { + m_loop->postEvent(this, new QEvent(QEvent::Type(StopSurface))); + + m_wait.wait(&m_mutex); + } + + m_mediaType.clear(); + + m_sampleScheduler.NotifyAllocator(0, FALSE); + + m_peerPin->Release(); + m_peerPin = 0; + + return S_OK; +} + +void VideoSurfaceFilter::stop() +{ + m_surface->stop(); +} + +HRESULT VideoSurfaceFilter::ConnectedTo(IPin **ppPin) +{ + if (!ppPin) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) { + return VFW_E_NOT_CONNECTED; + } else { + m_peerPin->AddRef(); + + *ppPin = m_peerPin; + + return S_OK; + } + } +} + +HRESULT VideoSurfaceFilter::ConnectionMediaType(AM_MEDIA_TYPE *pmt) +{ + if (!pmt) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + if (!m_peerPin) { + return VFW_E_NOT_CONNECTED; + } else { + DirectShowMediaType::copy(pmt, m_mediaType); + + return S_OK; + } + } +} + +HRESULT VideoSurfaceFilter::QueryPinInfo(PIN_INFO *pInfo) +{ + if (!pInfo) { + return E_POINTER; + } else { + AddRef(); + + pInfo->pFilter = this; + pInfo->dir = PINDIR_INPUT; + + const int bytes = qMin(MAX_FILTER_NAME, (m_pinId.length() + 1) * 2); + + qMemCopy(pInfo->achName, m_pinId.utf16(), bytes); + + return S_OK; + } +} + +HRESULT VideoSurfaceFilter::QueryId(LPWSTR *Id) +{ + if (!Id) { + return E_POINTER; + } else { + const int bytes = (m_pinId.length() + 1) * 2; + + *Id = static_cast(::CoTaskMemAlloc(bytes)); + + qMemCopy(*Id, m_pinId.utf16(), bytes); + + return S_OK; + } +} + +HRESULT VideoSurfaceFilter::QueryAccept(const AM_MEDIA_TYPE *pmt) +{ + return !m_surface->isFormatSupported(DirectShowMediaType::formatFromType(*pmt)) + ? S_OK + : S_FALSE; +} + +HRESULT VideoSurfaceFilter::EnumMediaTypes(IEnumMediaTypes **ppEnum) +{ + if (!ppEnum) { + return E_POINTER; + } else { + QMutexLocker locker(&m_mutex); + + *ppEnum = createMediaTypeEnum(); + + return S_OK; + } +} + +HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin) +{ + Q_UNUSED(apPin); + Q_UNUSED(nPin); + + return E_NOTIMPL; +} + +HRESULT VideoSurfaceFilter::EndOfStream() +{ + return S_OK; +} + +HRESULT VideoSurfaceFilter::BeginFlush() +{ + QMutexLocker locker(&m_mutex); + + m_sampleScheduler.setFlushing(true); + + if (thread() == QThread::currentThread()) { + flush(); + } else { + m_loop->postEvent(this, new QEvent(QEvent::Type(FlushSurface))); + + m_wait.wait(&m_mutex); + } + + return S_OK; +} + +HRESULT VideoSurfaceFilter::EndFlush() +{ + QMutexLocker locker(&m_mutex); + + m_sampleScheduler.setFlushing(false); + + return S_OK; +} + +void VideoSurfaceFilter::flush() +{ + m_surface->present(QVideoFrame()); + + m_wait.wakeAll(); +} + +HRESULT VideoSurfaceFilter::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + Q_UNUSED(tStart); + Q_UNUSED(tStop); + Q_UNUSED(dRate); + + return S_OK; +} + +HRESULT VideoSurfaceFilter::QueryDirection(PIN_DIRECTION *pPinDir) +{ + if (!pPinDir) { + return E_POINTER; + } else { + *pPinDir = PINDIR_INPUT; + + return S_OK; + } +} + +int VideoSurfaceFilter::currentMediaTypeToken() +{ + QMutexLocker locker(&m_mutex); + + return DirectShowMediaTypeList::currentMediaTypeToken(); +} + +HRESULT VideoSurfaceFilter::nextMediaType( + int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount) +{ + QMutexLocker locker(&m_mutex); + + return DirectShowMediaTypeList::nextMediaType(token, index, count, types, fetchedCount); + +} + +HRESULT VideoSurfaceFilter::skipMediaType(int token, int *index, ULONG count) +{ + QMutexLocker locker(&m_mutex); + + return DirectShowMediaTypeList::skipMediaType(token, index, count); +} + +HRESULT VideoSurfaceFilter::cloneMediaType(int token, int index, IEnumMediaTypes **enumeration) +{ + QMutexLocker locker(&m_mutex); + + return DirectShowMediaTypeList::cloneMediaType(token, index, enumeration); +} + +void VideoSurfaceFilter::customEvent(QEvent *event) +{ + if (event->type() == StartSurface) { + QMutexLocker locker(&m_mutex); + + m_startResult = start(); + + m_wait.wakeAll(); + } else if (event->type() == StopSurface) { + QMutexLocker locker(&m_mutex); + + stop(); + + m_wait.wakeAll(); + } else if (event->type() == FlushSurface) { + QMutexLocker locker(&m_mutex); + + flush(); + + m_wait.wakeAll(); + } else { + QObject::customEvent(event); + } +} + +void VideoSurfaceFilter::supportedFormatsChanged() +{ + QMutexLocker locker(&m_mutex); + + QList formats = m_surface->supportedPixelFormats(); + + QVector mediaTypes; + mediaTypes.reserve(formats.count()); + + AM_MEDIA_TYPE type; + type.majortype = MEDIATYPE_Video; + type.bFixedSizeSamples = TRUE; + type.bTemporalCompression = FALSE; + type.lSampleSize = 0; + type.formattype = GUID_NULL; + type.pUnk = 0; + type.cbFormat = 0; + type.pbFormat = 0; + + foreach (QVideoFrame::PixelFormat format, formats) { + type.subtype = DirectShowMediaType::convertPixelFormat(format); + + if (type.subtype != MEDIASUBTYPE_None) + mediaTypes.append(type); + } + + setMediaTypes(mediaTypes); +} + +void VideoSurfaceFilter::sampleReady() +{ + IMediaSample *sample = m_sampleScheduler.takeSample(); + + if (sample) { + m_surface->present(QVideoFrame( + new MediaSampleVideoBuffer(sample, m_bytesPerLine), + m_surfaceFormat.frameSize(), + m_surfaceFormat.pixelFormat())); + + sample->Release(); + } +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.h b/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.h new file mode 100644 index 0000000..8f3a101 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.h @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef VIDEOSURFACEFILTER_H +#define VIDEOSURFACEFILTER_H + +#include "directshowmediatypelist.h" +#include "directshowsamplescheduler.h" +#include "directshowmediatype.h" + +#include +#include +#include +#include +#include +#include + +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QAbstractVideoSurface; + +class DirectShowEventLoop; + +class VideoSurfaceFilter + : public QObject + , public DirectShowMediaTypeList + , public IBaseFilter + , public IAMFilterMiscFlags + , public IPin +{ + Q_OBJECT +public: + VideoSurfaceFilter( + QAbstractVideoSurface *surface, DirectShowEventLoop *loop, QObject *parent = 0); + ~VideoSurfaceFilter(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IPersist + HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); + + // IMediaFilter + HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart); + HRESULT STDMETHODCALLTYPE Pause(); + HRESULT STDMETHODCALLTYPE Stop(); + + HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *pState); + + HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock); + HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **ppClock); + + // IBaseFilter + HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum); + HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin); + + HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName); + + HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo); + HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo); + + // IAMFilterMiscFlags + ULONG STDMETHODCALLTYPE GetMiscFlags(); + + // IPin + HRESULT STDMETHODCALLTYPE Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt); + HRESULT STDMETHODCALLTYPE Disconnect(); + HRESULT STDMETHODCALLTYPE ConnectedTo(IPin **ppPin); + + HRESULT STDMETHODCALLTYPE ConnectionMediaType(AM_MEDIA_TYPE *pmt); + + HRESULT STDMETHODCALLTYPE QueryPinInfo(PIN_INFO *pInfo); + HRESULT STDMETHODCALLTYPE QueryId(LPWSTR *Id); + + HRESULT STDMETHODCALLTYPE QueryAccept(const AM_MEDIA_TYPE *pmt); + + HRESULT STDMETHODCALLTYPE EnumMediaTypes(IEnumMediaTypes **ppEnum); + + HRESULT STDMETHODCALLTYPE QueryInternalConnections(IPin **apPin, ULONG *nPin); + + HRESULT STDMETHODCALLTYPE EndOfStream(); + + HRESULT STDMETHODCALLTYPE BeginFlush(); + HRESULT STDMETHODCALLTYPE EndFlush(); + + HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + + HRESULT STDMETHODCALLTYPE QueryDirection(PIN_DIRECTION *pPinDir); + + int currentMediaTypeToken(); + HRESULT nextMediaType( + int token, int *index, ULONG count, AM_MEDIA_TYPE **types, ULONG *fetchedCount); + HRESULT skipMediaType(int token, int *index, ULONG count); + HRESULT cloneMediaType(int token, int index, IEnumMediaTypes **enumeration); + +protected: + void customEvent(QEvent *event); + +private Q_SLOTS: + void supportedFormatsChanged(); + void sampleReady(); + +private: + HRESULT start(); + void stop(); + void flush(); + + enum + { + StartSurface = QEvent::User, + StopSurface, + FlushSurface + }; + + LONG m_ref; + FILTER_STATE m_state; + QAbstractVideoSurface *m_surface; + DirectShowEventLoop *m_loop; + IFilterGraph *m_graph; + IPin *m_peerPin; + int m_bytesPerLine; + HRESULT m_startResult; + QString m_name; + QString m_pinId; + DirectShowMediaType m_mediaType; + QVideoSurfaceFormat m_surfaceFormat; + QMutex m_mutex; + QWaitCondition m_wait; + DirectShowSampleScheduler m_sampleScheduler; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp new file mode 100644 index 0000000..a564e14 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "vmr9videowindowcontrol.h" + +#include "directshowglobal.h" + + +QT_BEGIN_NAMESPACE + +Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent) + : QVideoWindowControl(parent) + , m_filter(com_new(CLSID_VideoMixingRenderer9)) + , m_windowId(0) + , m_dirtyValues(0) + , m_brightness(0) + , m_contrast(0) + , m_hue(0) + , m_saturation(0) + , m_fullScreen(false) +{ + if (IVMRFilterConfig9 *config = com_cast(m_filter)) { + config->SetRenderingMode(VMR9Mode_Windowless); + config->SetNumberOfStreams(1); + config->Release(); + } +} + +Vmr9VideoWindowControl::~Vmr9VideoWindowControl() +{ + if (m_filter) + m_filter->Release(); +} + + +WId Vmr9VideoWindowControl::winId() const +{ + return m_windowId; + +} + +void Vmr9VideoWindowControl::setWinId(WId id) +{ + m_windowId = id; + + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + control->SetVideoClippingWindow(m_windowId); + control->Release(); + } +} + +QRect Vmr9VideoWindowControl::displayRect() const +{ + QRect rect; + + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + RECT sourceRect; + RECT displayRect; + + if (control->GetVideoPosition(&sourceRect, &displayRect) == S_OK) { + rect = QRect( + displayRect.left, + displayRect.bottom, + displayRect.right - displayRect.left, + displayRect.bottom - displayRect.top); + } + control->Release(); + } + return rect; +} + +void Vmr9VideoWindowControl::setDisplayRect(const QRect &rect) +{ + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + RECT sourceRect = { 0, 0, 0, 0 }; + RECT displayRect = { rect.left(), rect.top(), rect.right(), rect.bottom() }; + + control->GetNativeVideoSize(&sourceRect.right, &sourceRect.bottom, 0, 0); + control->SetVideoPosition(&sourceRect, &displayRect); + control->Release(); + } +} + +bool Vmr9VideoWindowControl::isFullScreen() const +{ + return m_fullScreen; +} + +void Vmr9VideoWindowControl::setFullScreen(bool fullScreen) +{ + emit fullScreenChanged(m_fullScreen = fullScreen); +} + +void Vmr9VideoWindowControl::repaint() +{ + + if (QWidget *widget = QWidget::find(m_windowId)) { + HDC dc = widget->getDC(); + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + control->RepaintVideo(m_windowId, dc); + control->Release(); + } + widget->releaseDC(dc); + } +} + +QSize Vmr9VideoWindowControl::nativeSize() const +{ + QSize size; + + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + LONG width; + LONG height; + + if (control->GetNativeVideoSize(&width, &height, 0, 0) == S_OK) + size = QSize(width, height); + control->Release(); + } + return size; +} + +QVideoWidget::AspectRatioMode Vmr9VideoWindowControl::aspectRatioMode() const +{ + QVideoWidget::AspectRatioMode mode = QVideoWidget::KeepAspectRatio; + + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + DWORD arMode; + + if (control->GetAspectRatioMode(&arMode) == S_OK && arMode == VMR9ARMode_None) + mode = QVideoWidget::IgnoreAspectRatio; + control->Release(); + } + return mode; +} + +void Vmr9VideoWindowControl::setAspectRatioMode(QVideoWidget::AspectRatioMode mode) +{ + if (IVMRWindowlessControl9 *control = com_cast(m_filter)) { + switch (mode) { + case QVideoWidget::IgnoreAspectRatio: + control->SetAspectRatioMode(VMR9ARMode_None); + break; + case QVideoWidget::KeepAspectRatio: + control->SetAspectRatioMode(VMR9ARMode_LetterBox); + break; + default: + break; + } + control->Release(); + } +} + +int Vmr9VideoWindowControl::brightness() const +{ + return m_brightness; +} + +void Vmr9VideoWindowControl::setBrightness(int brightness) +{ + m_brightness = brightness; + + m_dirtyValues |= ProcAmpControl9_Brightness; + + setProcAmpValues(); + + emit brightnessChanged(brightness); +} + +int Vmr9VideoWindowControl::contrast() const +{ + return m_contrast; +} + +void Vmr9VideoWindowControl::setContrast(int contrast) +{ + m_contrast = contrast; + + m_dirtyValues |= ProcAmpControl9_Contrast; + + setProcAmpValues(); + + emit contrastChanged(contrast); +} + +int Vmr9VideoWindowControl::hue() const +{ + return m_hue; +} + +void Vmr9VideoWindowControl::setHue(int hue) +{ + m_hue = hue; + + m_dirtyValues |= ProcAmpControl9_Hue; + + setProcAmpValues(); + + emit hueChanged(hue); +} + +int Vmr9VideoWindowControl::saturation() const +{ + return m_saturation; +} + +void Vmr9VideoWindowControl::setSaturation(int saturation) +{ + m_saturation = saturation; + + m_dirtyValues |= ProcAmpControl9_Saturation; + + setProcAmpValues(); + + emit saturationChanged(saturation); +} + +void Vmr9VideoWindowControl::setProcAmpValues() +{ + if (IVMRMixerControl9 *control = com_cast(m_filter)) { + VMR9ProcAmpControl procAmp; + procAmp.dwSize = sizeof(VMR9ProcAmpControl); + procAmp.dwFlags = m_dirtyValues; + + if (m_dirtyValues & ProcAmpControl9_Brightness) { + procAmp.Brightness = scaleProcAmpValue( + control, ProcAmpControl9_Brightness, m_brightness); + } + if (m_dirtyValues & ProcAmpControl9_Contrast) { + procAmp.Contrast = scaleProcAmpValue( + control, ProcAmpControl9_Contrast, m_contrast); + } + if (m_dirtyValues & ProcAmpControl9_Hue) { + procAmp.Hue = scaleProcAmpValue( + control, ProcAmpControl9_Hue, m_hue); + } + if (m_dirtyValues & ProcAmpControl9_Saturation) { + procAmp.Saturation = scaleProcAmpValue( + control, ProcAmpControl9_Saturation, m_saturation); + } + + if (SUCCEEDED(control->SetProcAmpControl(0, &procAmp))) { + m_dirtyValues = 0; + } + + control->Release(); + } +} + +float Vmr9VideoWindowControl::scaleProcAmpValue( + IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const +{ + float scaledValue = 0.0; + + VMR9ProcAmpControlRange range; + range.dwSize = sizeof(VMR9ProcAmpControlRange); + range.dwProperty = property; + + if (SUCCEEDED(control->GetProcAmpControlRange(0, &range))) { + scaledValue = range.DefaultValue; + if (value > 0) + scaledValue += float(value) * (range.MaxValue - range.DefaultValue) / 100; + else if (value < 0) + scaledValue -= float(value) * (range.MinValue - range.DefaultValue) / 100; + } + + return scaledValue; +} + +QT_END_NAMESPACE + diff --git a/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.h new file mode 100644 index 0000000..a0aca95 --- /dev/null +++ b/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VMR9VIDEOWINDOWCONTROL_H +#define VMR9VIDEOWINDOWCONTROL_H + +#include + +#include +#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class Vmr9VideoWindowControl : public QVideoWindowControl +{ + Q_OBJECT +public: + Vmr9VideoWindowControl(QObject *parent = 0); + ~Vmr9VideoWindowControl(); + + IBaseFilter *filter() const { return m_filter; } + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + void repaint(); + + QSize nativeSize() const; + + QVideoWidget::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(QVideoWidget::AspectRatioMode mode); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + +private: + void setProcAmpValues(); + float scaleProcAmpValue( + IVMRMixerControl9 *control, VMR9ProcAmpControlFlags property, int value) const; + + IBaseFilter *m_filter; + WId m_windowId; + DWORD m_dirtyValues; + int m_brightness; + int m_contrast; + int m_hue; + int m_saturation; + bool m_fullScreen; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/plugins/mediaservices/mediaservices.pro b/src/plugins/mediaservices/mediaservices.pro index 879d914..e48156b 100644 --- a/src/plugins/mediaservices/mediaservices.pro +++ b/src/plugins/mediaservices/mediaservices.pro @@ -1,5 +1,7 @@ TEMPLATE = subdirs +win32:!wince:SUBDIRS += directshow + mac:SUBDIRS += qt7 unix:!mac:!symbian { -- cgit v0.12 From 19a822ae09d3ccb8b3aacf96e2f4052c32722284 Mon Sep 17 00:00:00 2001 From: Nicholas Young Date: Fri, 29 Jan 2010 11:20:41 +1000 Subject: Fixed GStreamer Plugin. --- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp | 2 +- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 93151e1..016909a 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -659,7 +659,7 @@ void QGstreamerPlayerSession::getStreamsInfo() if (type == GST_STREAM_TYPE_VIDEO) haveVideo = true; else if (type == GST_STREAM_TYPE_AUDIO) - hasAudio = true; + haveAudio = true; // QMediaStreamsControl::StreamType streamType = QMediaStreamsControl::UnknownStream; // diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h index 0da5f8f..d33ffd2 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -121,7 +121,7 @@ signals: void mediaStatusChanged(QMediaPlayer::MediaStatus mediaStatus); void volumeChanged(int volume); void mutedStateChanged(bool muted); - void audioAvailalbeChanged(bool audioAvailable); + void audioAvailableChanged(bool audioAvailable); void videoAvailableChanged(bool videoAvailable); void bufferingChanged(bool buffering); void bufferingProgressChanged(int percentFilled); -- cgit v0.12 From 3941f493f124298757d7b30b30f8781719cc89cc Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 1 Feb 2010 18:13:28 +1000 Subject: Export QPainterVideoSurface for QtWebKit. --- src/multimedia/base/qpaintervideosurface_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/base/qpaintervideosurface_p.h b/src/multimedia/base/qpaintervideosurface_p.h index 67b514f..5340956 100644 --- a/src/multimedia/base/qpaintervideosurface_p.h +++ b/src/multimedia/base/qpaintervideosurface_p.h @@ -69,7 +69,7 @@ class QGLContext; class QVideoSurfacePainter; -class Q_AUTOTEST_EXPORT QPainterVideoSurface : public QAbstractVideoSurface +class Q_MULTIMEDIA_EXPORT QPainterVideoSurface : public QAbstractVideoSurface { Q_OBJECT public: -- cgit v0.12 From 6c353c246e16dcad37a000b5e9ce393be90d6b64 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 2 Feb 2010 11:07:07 +1000 Subject: Add lost QmlMediaBase header file. --- src/multimedia/qml/qmlmediabase_p.h | 155 ++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/multimedia/qml/qmlmediabase_p.h diff --git a/src/multimedia/qml/qmlmediabase_p.h b/src/multimedia/qml/qmlmediabase_p.h new file mode 100644 index 0000000..3b5c398 --- /dev/null +++ b/src/multimedia/qml/qmlmediabase_p.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLMEDIABASE_P_H +#define QMLMEDIABASE_P_H + + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QMediaPlayerControl; +class QMediaService; +class QMediaServiceProvider; +class QMetaDataControl; +class QMetaDataControlMetaObject; +class QmlMediaBaseAnimation; + +class QmlMediaBase +{ +public: + QmlMediaBase(); + virtual ~QmlMediaBase(); + + QUrl source() const; + void setSource(const QUrl &url); + + bool isPlaying() const; + void setPlaying(bool playing); + + bool isPaused() const; + void setPaused(bool paused); + + int duration() const; + + int position() const; + void setPosition(int position); + + qreal volume() const; + void setVolume(qreal volume); + + bool isMuted() const; + void setMuted(bool muted); + + qreal bufferProgress() const; + + bool isSeekable() const; + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + QString errorString() const; + + void _q_stateChanged(QMediaPlayer::State state); + void _q_mediaStatusChanged(QMediaPlayer::MediaStatus status); + + void _q_metaDataChanged(); + +protected: + void shutdown(); + + void setObject(QObject *object); + + virtual void sourceChanged() = 0; + + virtual void playingChanged() = 0; + virtual void pausedChanged() = 0; + + virtual void started() = 0; + virtual void resumed() = 0; + virtual void paused() = 0; + virtual void stopped() = 0; + + virtual void statusChanged() = 0; + + virtual void loaded() = 0; + virtual void buffering() = 0; + virtual void stalled() = 0; + virtual void buffered() = 0; + virtual void endOfMedia() = 0; + + virtual void durationChanged() = 0; + virtual void positionChanged() = 0; + + virtual void volumeChanged() = 0; + virtual void mutedChanged() = 0; + + virtual void bufferProgressChanged() = 0; + + virtual void seekableChanged() = 0; + virtual void playbackRateChanged() = 0; + + QMediaService *m_mediaService; + QMediaPlayerControl *m_playerControl; + + QMediaObject *m_mediaObject; + QMediaServiceProvider *m_mediaProvider; + QMetaDataControl *m_metaDataControl; + QMetaDataControlMetaObject *m_metaObject; + QmlMediaBaseAnimation *m_animation; + + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_status; + QMediaPlayer::Error m_error; + QString m_errorString; + + friend class QmlMediaBaseAnimation; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif -- cgit v0.12 From 48b4d736a1cb19359e385aa8b86315eb8341b003 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 10:54:31 +1000 Subject: Compile fix for Direct Show media service plug-in. Remove duplicate #ifdef. --- src/plugins/mediaservices/directshow/dsserviceplugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/mediaservices/directshow/dsserviceplugin.cpp b/src/plugins/mediaservices/directshow/dsserviceplugin.cpp index fc5d11f..f3ab889 100644 --- a/src/plugins/mediaservices/directshow/dsserviceplugin.cpp +++ b/src/plugins/mediaservices/directshow/dsserviceplugin.cpp @@ -57,7 +57,6 @@ #ifdef QMEDIA_DIRECTSHOW_CAMERA -#ifdef QMEDIA_DIRECTSHOW_CAMERA #ifndef _STRSAFE_H_INCLUDED_ #include #endif -- cgit v0.12 From 396d731af30048e3b98be14a7b97e5ba682a86f8 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 10:56:50 +1000 Subject: Compile fix for DirectShowAudioEndpointControl. QAudioEndpointControl isn't defined in QtMultimedia, so inherit directly from QMediaControl instead. --- .../mediaplayer/directshowaudioendpointcontrol.cpp | 4 ++-- .../directshow/mediaplayer/directshowaudioendpointcontrol.h | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp index 2826ba5..4bb7228 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE DirectShowAudioEndpointControl::DirectShowAudioEndpointControl( DirectShowPlayerService *service, QObject *parent) - : QAudioEndpointSelector(parent) + : QMediaControl(parent) , m_service(service) , m_bindContext(0) , m_deviceEnumerator(0) @@ -130,7 +130,7 @@ void DirectShowAudioEndpointControl::updateEndpoints() oleMalloc->Free(string); moniker->AddRef(); - m_devices.insert(QString::fromWCharArray(string), moniker); + m_devices.insert(deviceId, moniker); if (m_defaultEndpoint.isEmpty() || deviceId.endsWith(QLatin1String("Default DirectSound Device"))) { diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h index 9ab188c..2faac13 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.h @@ -42,19 +42,17 @@ #ifndef DIRECTSHOWAUDIOENDPOINTCONTROL_H #define DIRECTSHOWAUDIOENDPOINTCONTROL_H -#include +#include #include - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class DirectShowPlayerService; - -class DirectShowAudioEndpointControl : public QAudioEndpointSelector +class DirectShowAudioEndpointControl : public QMediaControl { Q_OBJECT public: @@ -82,6 +80,13 @@ private: QString m_activeEndpoint; }; +#define QAudioEndpointSelector_iid "com.nokia.Qt.QAudioEndpointSelector/1.0" + +class Duck +{ + uint quack; +}; + QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12 From 5a43e96062f7bd82ff9deb57e065b757d784607d Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:01:11 +1000 Subject: Clip the paint region of QGraphicsVideoItem to it's bounding rect. --- src/multimedia/base/qgraphicsvideoitem.cpp | 50 ++++++++++++++++---------- src/multimedia/base/qpaintervideosurface.cpp | 54 ++++++++++++++++------------ src/multimedia/base/qpaintervideosurface_p.h | 2 +- 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp index 1a5ccd7..35baabe 100644 --- a/src/multimedia/base/qgraphicsvideoitem.cpp +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -64,6 +64,7 @@ public: , rendererControl(0) , aspectRatioMode(Qt::KeepAspectRatio) , updatePaintDevice(true) + , rect(0.0, 0.0, 320, 240) { } @@ -78,10 +79,11 @@ public: bool updatePaintDevice; QRectF rect; QRectF boundingRect; + QRectF sourceRect; QSizeF nativeSize; void clearService(); - void updateBoundingRect(); + void updateRects(); void _q_present(); void _q_formatChanged(const QVideoSurfaceFormat &format); @@ -106,22 +108,32 @@ void QGraphicsVideoItemPrivate::clearService() } } -void QGraphicsVideoItemPrivate::updateBoundingRect() +void QGraphicsVideoItemPrivate::updateRects() { q_ptr->prepareGeometryChange(); if (nativeSize.isEmpty()) { boundingRect = QRectF(); - } else { - if (aspectRatioMode == Qt::IgnoreAspectRatio) { - boundingRect = rect; - } else { - QSizeF size = nativeSize; - size.scale(rect.size(), aspectRatioMode); - - boundingRect = QRectF(QPointF(), size); - boundingRect.moveCenter(rect.center()); - } + } else if (aspectRatioMode == Qt::IgnoreAspectRatio) { + boundingRect = rect; + sourceRect = QRectF(0, 0, 1, 1); + } else if (aspectRatioMode == Qt::KeepAspectRatio) { + QSizeF size = nativeSize; + size.scale(rect.size(), Qt::KeepAspectRatio); + + boundingRect = QRectF(0, 0, size.width(), size.height()); + boundingRect.moveCenter(rect.center()); + + sourceRect = QRectF(0, 0, 1, 1); + } else if (aspectRatioMode == Qt::KeepAspectRatioByExpanding) { + boundingRect = rect; + + QSizeF size = rect.size(); + size.scale(nativeSize, Qt::KeepAspectRatio); + + sourceRect = QRectF( + 0, 0, size.width() / nativeSize.width(), size.height() / nativeSize.height()); + sourceRect.moveCenter(QPointF(0.5, 0.5)); } } @@ -139,7 +151,9 @@ void QGraphicsVideoItemPrivate::_q_formatChanged(const QVideoSurfaceFormat &form { nativeSize = format.sizeHint(); - updateBoundingRect(); + updateRects(); + + emit q_ptr->nativeSizeChanged(nativeSize); } void QGraphicsVideoItemPrivate::_q_serviceDestroyed() @@ -299,7 +313,7 @@ void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode) Q_D(QGraphicsVideoItem); d->aspectRatioMode = mode; - d->updateBoundingRect(); + d->updateRects(); } /*! @@ -320,7 +334,7 @@ void QGraphicsVideoItem::setOffset(const QPointF &offset) Q_D(QGraphicsVideoItem); d->rect.moveTo(offset); - d->updateBoundingRect(); + d->updateRects(); } /*! @@ -340,8 +354,8 @@ void QGraphicsVideoItem::setSize(const QSizeF &size) { Q_D(QGraphicsVideoItem); - d->rect.setSize(size); - d->updateBoundingRect(); + d->rect.setSize(size.isValid() ? size : QSizeF(0, 0)); + d->updateRects(); } /*! @@ -380,7 +394,7 @@ void QGraphicsVideoItem::paint( Q_UNUSED(widget); if (d->surface && d->surface->isActive()) { - d->surface->paint(painter, d->boundingRect); + d->surface->paint(painter, d->boundingRect, d->sourceRect); d->surface->setReady(true); #ifndef QGRAPHICSVIDEOITEM_SHADERS // Flickers } diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index 9953ae8..533ddee 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -73,7 +73,7 @@ public: virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0; virtual QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRect &source) = 0; + const QRectF &target, QPainter *painter, const QRectF &source) = 0; virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0; }; @@ -99,7 +99,7 @@ public: QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame); QAbstractVideoSurface::Error paint( - const QRectF &target, QPainter *painter, const QRect &source); + const QRectF &target, QPainter *painter, const QRectF &source); void updateColors(int brightness, int contrast, int hue, int saturation); @@ -167,7 +167,7 @@ QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::setCurrentFrame(const Q } QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::paint( - const QRectF &target, QPainter *painter, const QRect &source) + const QRectF &target, QPainter *painter, const QRectF &source) { if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) { QImage image( @@ -183,7 +183,7 @@ QAbstractVideoSurface::Error QVideoSurfaceRasterPainter::paint( painter->scale(1, -1); painter->translate(0, -target.bottom()); painter->drawImage( - QRect(target.x(), 0, target.width(), target.height()), image, source); + QRectF(target.x(), 0, target.width(), target.height()), image, source); painter->setTransform(oldTransform); } else { painter->drawImage(target, image, source); @@ -540,7 +540,8 @@ public: QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); void stop(); - QAbstractVideoSurface::Error paint(const QRectF &target, QPainter *painter, const QRect &source); + QAbstractVideoSurface::Error paint( + const QRectF &target, QPainter *painter, const QRectF &source); private: typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *); @@ -700,19 +701,19 @@ void QVideoSurfaceArbFpPainter::stop() } QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint( - const QRectF &target, QPainter *painter, const QRect &source) + const QRectF &target, QPainter *painter, const QRectF &source) { if (m_frame.isValid()) { painter->beginNativePainting(); - const float txLeft = float(source.left()) / float(m_frameSize.width()); - const float txRight = float(source.right()) / float(m_frameSize.width()); + const float txLeft = source.left() / m_frameSize.width(); + const float txRight = source.right() / m_frameSize.width(); const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? float(source.top()) / float(m_frameSize.height()) - : float(source.bottom()) / float(m_frameSize.height()); + ? source.top() / m_frameSize.height() + : source.bottom() / m_frameSize.height(); const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? float(source.bottom()) / float(m_frameSize.height()) - : float(source.top()) / float(m_frameSize.height()); + ? source.bottom() / m_frameSize.height() + : source.top() / m_frameSize.height(); const float tx_array[] = @@ -857,7 +858,8 @@ public: QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format); void stop(); - QAbstractVideoSurface::Error paint(const QRectF &target, QPainter *painter, const QRect &source); + QAbstractVideoSurface::Error paint( + const QRectF &target, QPainter *painter, const QRectF &source); private: QGLShaderProgram m_program; @@ -975,7 +977,7 @@ void QVideoSurfaceGlslPainter::stop() } QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( - const QRectF &target, QPainter *painter, const QRect &source) + const QRectF &target, QPainter *painter, const QRectF &source) { if (m_frame.isValid()) { painter->beginNativePainting(); @@ -1021,14 +1023,14 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( target.right() + 1, target.top() }; - const GLfloat txLeft = float(source.left()) / float(m_frameSize.width()); - const GLfloat txRight = float(source.right()) / float(m_frameSize.width()); + const GLfloat txLeft = source.left() / m_frameSize.width(); + const GLfloat txRight = source.right() / m_frameSize.width(); const GLfloat txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? float(source.top()) / float(m_frameSize.height()) - : float(source.bottom()) / float(m_frameSize.height()); + ? source.top() / m_frameSize.height() + : source.bottom() / m_frameSize.height(); const GLfloat txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom - ? float(source.bottom()) / float(m_frameSize.height()) - : float(source.top()) / float(m_frameSize.height()); + ? source.bottom() / m_frameSize.height() + : source.top() / m_frameSize.height(); const GLfloat textureCoordArray[] = { @@ -1289,17 +1291,23 @@ void QPainterVideoSurface::setReady(bool ready) /*! */ -void QPainterVideoSurface::paint(QPainter *painter, const QRectF &rect) +void QPainterVideoSurface::paint(QPainter *painter, const QRectF &target, const QRectF &source) { if (!isActive()) { - painter->fillRect(rect, QBrush(Qt::black)); + painter->fillRect(target, QBrush(Qt::black)); } else { if (m_colorsDirty) { m_painter->updateColors(m_brightness, m_contrast, m_hue, m_saturation); m_colorsDirty = false; } - QAbstractVideoSurface::Error error = m_painter->paint(rect, painter, m_sourceRect); + const QRectF sourceRect( + m_sourceRect.x() + m_sourceRect.width() * source.x(), + m_sourceRect.y() + m_sourceRect.height() * source.y(), + m_sourceRect.width() * source.width(), + m_sourceRect.height() * source.height()); + + QAbstractVideoSurface::Error error = m_painter->paint(target, painter, sourceRect); if (error != QAbstractVideoSurface::NoError) { setError(error); diff --git a/src/multimedia/base/qpaintervideosurface_p.h b/src/multimedia/base/qpaintervideosurface_p.h index 5340956..d4b6740 100644 --- a/src/multimedia/base/qpaintervideosurface_p.h +++ b/src/multimedia/base/qpaintervideosurface_p.h @@ -102,7 +102,7 @@ public: bool isReady() const; void setReady(bool ready); - void paint(QPainter *painter, const QRectF &rect); + void paint(QPainter *painter, const QRectF &target, const QRectF &source = QRectF(0, 0, 1, 1)); #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) const QGLContext *glContext() const; -- cgit v0.12 From 25579113df82d0e665bb90831586b7510e52469e Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:14:49 +1000 Subject: Send an EC_COMPLETE event from the video surface filter on end of stream Otherwise the filter graph won't stop itself as it hasn't received the event from all the output filters. --- .../mediaplayer/directshowsamplescheduler.cpp | 22 +++++++++++++++++- .../mediaplayer/directshowsamplescheduler.h | 3 ++- .../directshow/mediaplayer/videosurfacefilter.cpp | 27 +++++++++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp index 921330c..733080e 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.cpp @@ -53,6 +53,7 @@ public: : m_next(0) , m_sample(sample) , m_cookie(0) + , m_lastSample(false) { m_sample->AddRef(); } @@ -75,10 +76,14 @@ public: bool isReady(IReferenceClock *clock) const; + bool isLast() const { return m_lastSample; } + void setLast() { m_lastSample = true; } + private: DirectShowTimedSample *m_next; IMediaSample *m_sample; DWORD_PTR m_cookie; + bool m_lastSample; }; bool DirectShowTimedSample::schedule( @@ -355,7 +360,7 @@ void DirectShowSampleScheduler::setClock(IReferenceClock *clock) m_clock->AddRef(); } -IMediaSample *DirectShowSampleScheduler::takeSample() +IMediaSample *DirectShowSampleScheduler::takeSample(bool *eos) { QMutexLocker locker(&m_mutex); @@ -364,6 +369,8 @@ IMediaSample *DirectShowSampleScheduler::takeSample() sample->AddRef(); if (m_state == Running) { + *eos = m_head->isLast(); + m_head = m_head->remove(); if (!m_head) @@ -378,6 +385,19 @@ IMediaSample *DirectShowSampleScheduler::takeSample() } } +bool DirectShowSampleScheduler::scheduleEndOfStream() +{ + QMutexLocker locker(&m_mutex); + + if (m_tail) { + m_tail->setLast(); + + return true; + } else { + return false; + } +} + bool DirectShowSampleScheduler::event(QEvent *event) { if (event->type() == QEvent::WinEventAct) { diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h index 7af9112..007fa99 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowsamplescheduler.h @@ -97,8 +97,9 @@ public: void setClock(IReferenceClock *clock); bool schedule(IMediaSample *sample); + bool scheduleEndOfStream(); - IMediaSample *takeSample(); + IMediaSample *takeSample(bool *eos); bool event(QEvent *event); diff --git a/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp b/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp index a5565f1..7b4aad5 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/videosurfacefilter.cpp @@ -42,6 +42,7 @@ #include "videosurfacefilter.h" #include "directshoweventloop.h" +#include "directshowglobal.h" #include "directshowpinenum.h" #include "mediasamplevideobuffer.h" @@ -442,6 +443,18 @@ HRESULT VideoSurfaceFilter::QueryInternalConnections(IPin **apPin, ULONG *nPin) HRESULT VideoSurfaceFilter::EndOfStream() { + QMutexLocker locker(&m_mutex); + + if (!m_sampleScheduler.scheduleEndOfStream()) { + if (IMediaEventSink *sink = com_cast(m_graph)) { + sink->Notify( + EC_COMPLETE, + S_OK, + reinterpret_cast(static_cast(this))); + sink->Release(); + } + } + return S_OK; } @@ -584,7 +597,9 @@ void VideoSurfaceFilter::supportedFormatsChanged() void VideoSurfaceFilter::sampleReady() { - IMediaSample *sample = m_sampleScheduler.takeSample(); + bool eos = false; + + IMediaSample *sample = m_sampleScheduler.takeSample(&eos); if (sample) { m_surface->present(QVideoFrame( @@ -593,6 +608,16 @@ void VideoSurfaceFilter::sampleReady() m_surfaceFormat.pixelFormat())); sample->Release(); + + if (eos) { + if (IMediaEventSink *sink = com_cast(m_graph)) { + sink->Notify( + EC_COMPLETE, + S_OK, + reinterpret_cast(static_cast(this))); + sink->Release(); + } + } } } -- cgit v0.12 From b136d5a9c2dbb83199d61de2ce88f801637434bb Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:18:17 +1000 Subject: Handle graph events in the service thread rather than the gui thread. This makes the service thread responsible for the last of the graph manipulation and state update tasks. --- .../mediaplayer/directshowplayerservice.cpp | 382 +++++++++------------ .../mediaplayer/directshowplayerservice.h | 52 +-- 2 files changed, 201 insertions(+), 233 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index ea4b73c..d205ac1 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -88,6 +88,8 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_pendingTasks(0) , m_executingTask(0) , m_executedTasks(0) + , m_taskHandle(::CreateEvent(0, 0, 0, 0)) + , m_eventHandle(0) , m_graphStatus(NoMedia) , m_stream(0) , m_graph(0) @@ -99,6 +101,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_duration(0) , m_buffering(false) , m_seekable(false) + , m_atEnd(false) { m_playerControl = new DirectShowPlayerControl(this); m_metaDataControl = new DirectShowMetaDataControl(this); @@ -112,8 +115,6 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) connect(m_videoOutputControl, SIGNAL(outputChanged()), this, SLOT(videoOutputChanged())); connect(m_videoRendererControl, SIGNAL(filterChanged()), this, SLOT(videoOutputChanged())); - - connect(&m_graphEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(graphEvent(HANDLE))); } DirectShowPlayerService::~DirectShowPlayerService() @@ -121,43 +122,15 @@ DirectShowPlayerService::~DirectShowPlayerService() { QMutexLocker locker(&m_mutex); - m_pendingTasks = Shutdown; - - if (m_graph) { - m_graphEventNotifier.setEnabled(false); - - if (IAMOpenProgress *progress = com_cast(m_graph)) { - progress->AbortOperation(); - progress->Release(); - } - - m_graph->Abort(); + releaseGraph(); - if (IMediaControl *control = com_cast(m_graph)) { - control->Stop(); - OAFilterState state; - control->GetState(INFINITE, &state); - control->Release(); - } - } - m_wait.wakeAll(); - - m_loop.wait(&m_mutex); + m_pendingTasks = Shutdown; + ::SetEvent(m_taskHandle); } m_taskThread->wait(); delete m_taskThread; - if (m_graph) { - m_graph->Release(); - m_graph = 0; - } - - if (m_source) { - m_source->Release(); - m_source = 0; - } - if (m_audioOutput) { m_audioOutput->Release(); m_audioOutput = 0; @@ -174,6 +147,8 @@ DirectShowPlayerService::~DirectShowPlayerService() delete m_videoOutputControl; delete m_videoRendererControl; delete m_videoWindowControl; + + ::CloseHandle(m_taskHandle); } QMediaControl *DirectShowPlayerService::control(const char *name) const @@ -198,34 +173,10 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream { QMutexLocker locker(&m_mutex); - if (m_graph) { - m_graphEventNotifier.setEnabled(false); - - if (m_executingTask != 0) { - if (IAMOpenProgress *progress = com_cast(m_graph)) { - progress->AbortOperation(); - progress->Release(); - } else { - m_graph->Abort(); - } - - m_pendingTasks = Stop; + m_pendingTasks = 0; - m_loop.wait(&m_mutex); - } - if (IMediaControl *control = com_cast(m_graph)) { - control->Stop(); - control->Release(); - } - - if (m_source) { - m_source->Release(); - m_source = 0; - } - - m_graph->Release(); - m_graph = 0; - } + if (m_graph) + releaseGraph(); m_resources = media.resources(); m_stream = stream; @@ -234,6 +185,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_executedTasks = 0; m_buffering = false; m_seekable = false; + m_atEnd = false; m_metaDataControl->updateGraph(0, 0); if (m_resources.isEmpty() && !stream) { @@ -246,21 +198,12 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_graph = com_new(CLSID_FilterGraph); - if (IMediaEventEx *event = com_cast(m_graph)) { - HANDLE handle; - if (event->GetEventHandle(reinterpret_cast(&handle)) == S_OK) { - m_graphEventNotifier.setHandle(handle); - m_graphEventNotifier.setEnabled(true); - } - event->Release(); - } - if (stream) m_pendingTasks = SetStreamSource; else m_pendingTasks = SetUrlSource; - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); @@ -399,7 +342,7 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) IBaseFilter *filter = filters[filters.size() - 1]; filters.removeLast(); - if (m_executingTask == Render && SUCCEEDED(filter->EnumPins(&pins))) { + if (!(m_pendingTasks & ReleaseFilters) && SUCCEEDED(filter->EnumPins(&pins))) { int outputs = 0; for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { PIN_DIRECTION direction; @@ -446,7 +389,7 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) graph->Release(); - if (m_executingTask == Render) { + if (!(m_pendingTasks & ReleaseFilters)) { if (rendered) { if (!(m_executedTasks & FinalizeLoad)) m_pendingTasks |= FinalizeLoad; @@ -475,13 +418,15 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) m_executedTasks |= Render; } - - m_loop.wake(); } void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) { if (m_graphStatus != Loaded) { + if (IMediaEvent *event = com_cast(m_graph)) { + event->GetEventHandle(reinterpret_cast(&m_eventHandle)); + event->Release(); + } if (IMediaSeeking *seeking = com_cast(m_graph)) { LONGLONG duration = 0; seeking->GetDuration(&duration); @@ -508,22 +453,45 @@ void DirectShowPlayerService::doFinalizeLoad(QMutexLocker *locker) QCoreApplication::postEvent(this, new QEvent(QEvent::Type(FinalizedLoad))); } - -void DirectShowPlayerService::doUpdateDuration(QMutexLocker *) +void DirectShowPlayerService::releaseGraph() { - if (IMediaSeeking *seeking = com_cast(m_graph)) { - LONGLONG duration = 0; - seeking->GetDuration(&duration); - m_duration = duration / 10; + if (m_graph) { + if (m_executingTask != 0) { + if (IAMOpenProgress *progress = com_cast(m_graph)) { + progress->AbortOperation(); + progress->Release(); + } + m_graph->Abort(); + } + + m_pendingTasks = ReleaseGraph; - DWORD capabilities = 0; - seeking->GetCapabilities(&capabilities); - m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute; + ::SetEvent(m_taskHandle); - seeking->Release(); + m_loop.wait(&m_mutex); + } +} - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(DurationChange))); +void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) +{ + Q_UNUSED(locker); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); } + + if (m_source) { + m_source->Release(); + m_source = 0; + } + + m_eventHandle = 0; + + m_graph->Release(); + m_graph = 0; + + m_loop.wake(); } int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const @@ -611,12 +579,13 @@ void DirectShowPlayerService::play() if (m_executedTasks & Render) { if (m_executedTasks & Stop) { + m_atEnd = false; m_position = 0; m_pendingTasks |= Seek; m_executedTasks ^= Stop; } - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } } @@ -635,7 +604,7 @@ void DirectShowPlayerService::doPlay(QMutexLocker *locker) if (SUCCEEDED(hr)) { m_executedTasks |= Play; - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Started))); + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); } else { m_error = QMediaPlayer::ResourceError; qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", hr); @@ -654,12 +623,13 @@ void DirectShowPlayerService::pause() if (m_executedTasks & Render) { if (m_executedTasks & Stop) { + m_atEnd = false; m_position = 0; m_pendingTasks |= Seek; m_executedTasks ^= Stop; } - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } } @@ -675,7 +645,7 @@ void DirectShowPlayerService::doPause(QMutexLocker *locker) if (SUCCEEDED(hr)) { m_executedTasks |= Pause; - QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Paused))); + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); } else { m_error = QMediaPlayer::ResourceError; qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", hr); @@ -719,7 +689,7 @@ void DirectShowPlayerService::setRate(qreal rate) m_pendingTasks |= SetRate; if (m_executedTasks & FinalizeLoad) - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } void DirectShowPlayerService::doSetRate(QMutexLocker *locker) @@ -804,7 +774,7 @@ void DirectShowPlayerService::seek(qint64 position) m_pendingTasks |= Seek; if (m_executedTasks & FinalizeLoad) - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } void DirectShowPlayerService::doSeek(QMutexLocker *locker) @@ -856,9 +826,11 @@ void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) if (m_graph) { if (m_audioOutput) { if (m_executedTasks & SetAudioOutput) { - removeOutput(m_audioOutput); + m_pendingTasks |= ReleaseAudioOutput; - m_executedTasks &= ~SetAudioOutput; + ::SetEvent(m_taskHandle); + + m_loop.wait(&m_mutex); } m_audioOutput->Release(); } @@ -876,7 +848,7 @@ void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) if (m_executedTasks & SetSource) { m_pendingTasks |= Render; - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } } else { if (m_audioOutput) @@ -891,6 +863,22 @@ void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) m_playerControl->updateAudioOutput(m_audioOutput); } +void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker) +{ + m_pendingTasks |= m_executedTasks & (Play | Pause); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + + m_graph->RemoveFilter(m_audioOutput); + + m_executedTasks &= ~SetAudioOutput; + + m_loop.wake(); +} + void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) { QMutexLocker locker(&m_mutex); @@ -898,9 +886,11 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) if (m_graph) { if (m_videoOutput) { if (m_executedTasks & SetVideoOutput) { - removeOutput(m_videoOutput); + m_pendingTasks |= ReleaseVideoOutput; - m_executedTasks &= ~SetVideoOutput; + ::SetEvent(m_taskHandle); + + m_loop.wait(&m_mutex); } m_videoOutput->Release(); } @@ -918,7 +908,7 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) if (m_executedTasks & SetSource) { m_pendingTasks |= Render; - m_wait.wakeAll(); + ::SetEvent(m_taskHandle); } } else { if (m_videoOutput) @@ -931,11 +921,25 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) } } +void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) +{ + m_pendingTasks |= m_executedTasks & (Play | Pause); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + + m_graph->RemoveFilter(m_videoOutput); + + m_executedTasks &= ~SetVideoOutput; + + m_loop.wake(); +} + void DirectShowPlayerService::customEvent(QEvent *event) { if (event->type() == QEvent::Type(FinalizedLoad)) { - event->accept(); - QMutexLocker locker(&m_mutex); m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); @@ -943,8 +947,6 @@ void DirectShowPlayerService::customEvent(QEvent *event) updateStatus(); } else if (event->type() == QEvent::Type(Error)) { - event->accept(); - QMediaPlayer::Error error; { QMutexLocker locker(&m_mutex); @@ -958,23 +960,24 @@ void DirectShowPlayerService::customEvent(QEvent *event) } m_playerControl->error(error, QString()); } else if (event->type() == QEvent::Type(RateChange)) { - event->accept(); - QMutexLocker locker(&m_mutex); m_playerControl->updatePlaybackRate(m_rate); - } else if (event->type() == QEvent::Type(Started) || event->type() == QEvent::Type(Paused)) { - event->accept(); - + } else if (event->type() == QEvent::Type(StatusChange)) { QMutexLocker locker(&m_mutex); updateStatus(); } else if (event->type() == QEvent::Type(DurationChange)) { - event->accept(); - QMutexLocker locker(&m_mutex); m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); + } else if (event->type() == QEvent::Type(EndOfMedia)) { + QMutexLocker locker(&m_mutex); + + if (m_atEnd) { + m_playerControl->updateState(QMediaPlayer::StoppedState); + m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); + } } else { QMediaService::customEvent(event); } @@ -998,7 +1001,7 @@ void DirectShowPlayerService::videoOutputChanged() setVideoOutput(videoOutput); } -void DirectShowPlayerService::graphEvent(HANDLE handle) +void DirectShowPlayerService::graphEvent(QMutexLocker *locker) { if (IMediaEvent *event = com_cast(m_graph)) { long eventCode; @@ -1008,32 +1011,32 @@ void DirectShowPlayerService::graphEvent(HANDLE handle) while (event->GetEvent(&eventCode, ¶m1, ¶m2, 0) == S_OK) { switch (eventCode) { case EC_BUFFERING_DATA: - { - QMutexLocker locker(&m_mutex); - m_buffering = param1; + m_buffering = param1; - updateStatus(); - } + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); break; case EC_COMPLETE: - { - QMutexLocker locker(&m_mutex); - m_executedTasks &= ~(Play | Pause); - m_executedTasks |= Stop; - - m_buffering = false; - m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); - m_playerControl->updateState(QMediaPlayer::StoppedState); - } + m_executedTasks &= ~(Play | Pause); + m_executedTasks |= Stop; + + m_buffering = false; + m_atEnd = true; + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia))); break; case EC_LENGTH_CHANGED: - { - QMutexLocker locker(&m_mutex); - if (m_executedTasks & FinalizeLoad) { - m_pendingTasks |= UpdateDuration; + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG duration = 0; + seeking->GetDuration(&duration); + m_duration = duration / 10; - m_wait.wakeAll(); - } + DWORD capabilities = 0; + seeking->GetCapabilities(&capabilities); + m_seekable = capabilities & AM_SEEKING_CanSeekAbsolute; + + seeking->Release(); + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(DurationChange))); } break; default: @@ -1073,76 +1076,6 @@ void DirectShowPlayerService::updateStatus() } } -void DirectShowPlayerService::removeOutput(IBaseFilter *output) -{ - while (m_executingTask != 0) { - if (m_executingTask == Render) { - m_executingTask = 0; - - if (IAMOpenProgress *progress = com_cast(m_graph)) { - progress->AbortOperation(); - progress->Release(); - } - } - m_loop.wait(&m_mutex); - } - - m_pendingTasks |= m_executedTasks & (Play | Pause); - - if (IMediaControl *control = com_cast(m_graph)) { - control->Stop(); - control->Release(); - } - - if (IFilterChain *chain = com_cast(m_graph)) { - IBaseFilter *start = findChainStart(output); - - chain->RemoveChain(start, output); - - start->Release(); - chain->Release(); - } else { - m_graph->RemoveFilter(output); - } -} - -IBaseFilter *DirectShowPlayerService::findChainStart(IBaseFilter *end) const -{ - IBaseFilter *start = 0; - end->AddRef(); - - while (start != end) { - start = end; - - IEnumPins *pins = 0; - - if (SUCCEEDED(end->EnumPins(&pins))) { - for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { - PIN_DIRECTION direction; - if (SUCCEEDED(pin->QueryDirection(&direction)) && direction == PINDIR_INPUT) { - IPin *peer = 0; - if (SUCCEEDED(pin->ConnectedTo(&peer))) { - PIN_INFO peerInfo; - if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) { - CLSID classId; - if (SUCCEEDED(peerInfo.pFilter->GetClassID(&classId)) - && classId == CLSID_Colour) { - end->Release(); - end = peerInfo.pFilter; - } else { - peerInfo.pFilter->Release(); - } - } - peer->Release(); - } - } - } - pins->Release(); - } - } - return start; -} - bool DirectShowPlayerService::isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const { bool connected = false; @@ -1170,8 +1103,45 @@ void DirectShowPlayerService::run() { QMutexLocker locker(&m_mutex); - while (!(m_pendingTasks & Shutdown)) { - if (m_pendingTasks & SetUrlSource) { + for (;;) { + ::ResetEvent(m_taskHandle); + + while (m_pendingTasks == 0) { + DWORD result = 0; + + locker.unlock(); + if (m_eventHandle) { + HANDLE handles[] = { m_taskHandle, m_eventHandle }; + + result = ::WaitForMultipleObjects(2, handles, false, INFINITE); + } else { + result = ::WaitForSingleObject(m_taskHandle, INFINITE); + } + locker.relock(); + + if (result == WAIT_OBJECT_0 + 1) { + graphEvent(&locker); + } + } + + if (m_pendingTasks & ReleaseGraph) { + m_pendingTasks ^= ReleaseGraph; + m_executingTask = ReleaseGraph; + + doReleaseGraph(&locker); + } else if (m_pendingTasks & Shutdown) { + return; + } else if (m_pendingTasks & ReleaseAudioOutput) { + m_pendingTasks ^= ReleaseAudioOutput; + m_executingTask = ReleaseAudioOutput; + + doReleaseAudioOutput(&locker); + } else if (m_pendingTasks & ReleaseVideoOutput) { + m_pendingTasks ^= ReleaseVideoOutput; + m_executingTask = ReleaseVideoOutput; + + doReleaseVideoOutput(&locker); + } else if (m_pendingTasks & SetUrlSource) { m_pendingTasks ^= SetUrlSource; m_executingTask = SetUrlSource; @@ -1193,11 +1163,6 @@ void DirectShowPlayerService::run() m_executingTask = FinalizeLoad; doFinalizeLoad(&locker); - } else if (m_pendingTasks & UpdateDuration) { - m_pendingTasks ^= UpdateDuration; - m_executingTask ^= UpdateDuration; - - doUpdateDuration(&locker); } else if (m_pendingTasks & SetRate) { m_pendingTasks ^= SetRate; m_executingTask = SetRate; @@ -1224,12 +1189,7 @@ void DirectShowPlayerService::run() doPlay(&locker); } m_executingTask = 0; - - if (m_pendingTasks == 0) - m_wait.wait(&m_mutex); } - - m_loop.wake(); } QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h index 3a01889..9ea5d7d 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -105,16 +105,14 @@ protected: private Q_SLOTS: void videoOutputChanged(); - void graphEvent(HANDLE handle); private: + void releaseGraph(); void updateStatus(); int findStreamTypes(IBaseFilter *source) const; int findStreamType(IPin *pin) const; - void removeOutput(IBaseFilter *output); - IBaseFilter *findChainStart(IBaseFilter *end) const; bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; void run(); @@ -127,25 +125,32 @@ private: void doSeek(QMutexLocker *locker); void doPlay(QMutexLocker *locker); void doPause(QMutexLocker *locker); - void doUpdateDuration(QMutexLocker *locker); + void doReleaseAudioOutput(QMutexLocker *locker); + void doReleaseVideoOutput(QMutexLocker *locker); + void doReleaseGraph(QMutexLocker *locker); + + void graphEvent(QMutexLocker *locker); enum Task { - Shutdown = 0x0001, - SetUrlSource = 0x0002, - SetStreamSource = 0x0004, - SetSource = SetUrlSource | SetStreamSource, - SetAudioOutput = 0x0008, - SetVideoOutput = 0x0010, - SetOutputs = SetAudioOutput | SetVideoOutput, - Render = 0x0020, - FinalizeLoad = 0x0040, - SetRate = 0x0080, - Seek = 0x0100, - Play = 0x0200, - Pause = 0x0400, - Stop = 0x0800, - UpdateDuration = 0x1000 + Shutdown = 0x0001, + SetUrlSource = 0x0002, + SetStreamSource = 0x0004, + SetSource = SetUrlSource | SetStreamSource, + SetAudioOutput = 0x0008, + SetVideoOutput = 0x0010, + SetOutputs = SetAudioOutput | SetVideoOutput, + Render = 0x0020, + FinalizeLoad = 0x0040, + SetRate = 0x0080, + Seek = 0x0100, + Play = 0x0200, + Pause = 0x0400, + Stop = 0x0800, + ReleaseGraph = 0x1000, + ReleaseAudioOutput = 0x2000, + ReleaseVideoOutput = 0x4000, + ReleaseFilters = ReleaseGraph | ReleaseAudioOutput | ReleaseVideoOutput }; enum Event @@ -155,7 +160,9 @@ private: RateChange, Started, Paused, - DurationChange + DurationChange, + StatusChange, + EndOfMedia }; enum GraphStatus @@ -177,6 +184,8 @@ private: int m_pendingTasks; int m_executingTask; int m_executedTasks; + HANDLE m_taskHandle; + HANDLE m_eventHandle; GraphStatus m_graphStatus; QMediaPlayer::Error m_error; QIODevice *m_stream; @@ -190,12 +199,11 @@ private: qint64 m_duration; bool m_buffering; bool m_seekable; + bool m_atEnd; QMediaTimeRange m_playbackRange; QUrl m_url; QMediaResourceList m_resources; QMutex m_mutex; - QWaitCondition m_wait; - QWinEventNotifier m_graphEventNotifier; DirectShowEventLoop m_loop; friend class DirectShowPlayerServiceThread; -- cgit v0.12 From 53ff697fb83c69e02a72a73ee13e9ca4f795c5a8 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:29:50 +1000 Subject: Compile fix for DirectShowEventLoop. QT_END_NAMESPAC -> QT_END_NAMESPACE --- src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h index eb68af3..f46e65a 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.h @@ -76,7 +76,7 @@ private: QMutex m_mutex; }; -QT_END_NAMESPAC +QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12 From 3c90f04c31d266a640ccf3b187d6971f7ade7500 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:42:04 +1000 Subject: Share a single instance of DirectShowEventLoop between services. --- .../mediaplayer/directshowplayerservice.cpp | 22 ++++++++++++---------- .../mediaplayer/directshowplayerservice.h | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index d205ac1..a3362db 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -58,6 +58,7 @@ #include +Q_GLOBAL_STATIC(DirectShowEventLoop, qt_directShowEventLoop) QT_BEGIN_NAMESPACE @@ -85,6 +86,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) , m_videoRendererControl(0) , m_videoWindowControl(0) , m_taskThread(0) + , m_loop(qt_directShowEventLoop()) , m_pendingTasks(0) , m_executingTask(0) , m_executedTasks(0) @@ -107,7 +109,7 @@ DirectShowPlayerService::DirectShowPlayerService(QObject *parent) m_metaDataControl = new DirectShowMetaDataControl(this); m_videoOutputControl = new DirectShowVideoOutputControl; m_audioEndpointControl = new DirectShowAudioEndpointControl(this); - m_videoRendererControl = new DirectShowVideoRendererControl(&m_loop); + m_videoRendererControl = new DirectShowVideoRendererControl(m_loop); m_videoWindowControl = new Vmr9VideoWindowControl; m_taskThread = new DirectShowPlayerServiceThread(this); @@ -284,7 +286,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) { - IBaseFilter *source = new DirectShowIOSource(m_stream, &m_loop); + IBaseFilter *source = new DirectShowIOSource(m_stream, m_loop); if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) { m_executedTasks = SetSource; @@ -468,7 +470,7 @@ void DirectShowPlayerService::releaseGraph() ::SetEvent(m_taskHandle); - m_loop.wait(&m_mutex); + m_loop->wait(&m_mutex); } } @@ -491,7 +493,7 @@ void DirectShowPlayerService::doReleaseGraph(QMutexLocker *locker) m_graph->Release(); m_graph = 0; - m_loop.wake(); + m_loop->wake(); } int DirectShowPlayerService::findStreamTypes(IBaseFilter *source) const @@ -665,7 +667,7 @@ void DirectShowPlayerService::stop() if (m_executingTask & (Play | Pause | Seek)) { m_pendingTasks |= Stop; - m_loop.wait(&m_mutex); + m_loop->wait(&m_mutex); } if (m_executedTasks & (Play | Pause)) { @@ -830,7 +832,7 @@ void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) ::SetEvent(m_taskHandle); - m_loop.wait(&m_mutex); + m_loop->wait(&m_mutex); } m_audioOutput->Release(); } @@ -876,7 +878,7 @@ void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker) m_executedTasks &= ~SetAudioOutput; - m_loop.wake(); + m_loop->wake(); } void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) @@ -890,7 +892,7 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) ::SetEvent(m_taskHandle); - m_loop.wait(&m_mutex); + m_loop->wait(&m_mutex); } m_videoOutput->Release(); } @@ -934,7 +936,7 @@ void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) m_executedTasks &= ~SetVideoOutput; - m_loop.wake(); + m_loop->wake(); } void DirectShowPlayerService::customEvent(QEvent *event) @@ -1171,7 +1173,7 @@ void DirectShowPlayerService::run() } else if (m_pendingTasks & Stop) { m_pendingTasks ^= Stop; - m_loop.wake(); + m_loop->wake(); } else if (m_pendingTasks & Pause) { m_pendingTasks ^= Pause; m_executingTask = Pause; diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h index 9ea5d7d..576520e 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -181,6 +181,7 @@ private: DirectShowAudioEndpointControl *m_audioEndpointControl; QThread *m_taskThread; + DirectShowEventLoop *m_loop; int m_pendingTasks; int m_executingTask; int m_executedTasks; @@ -204,7 +205,6 @@ private: QUrl m_url; QMediaResourceList m_resources; QMutex m_mutex; - DirectShowEventLoop m_loop; friend class DirectShowPlayerServiceThread; }; -- cgit v0.12 From 3cd93dfb61eee61523af02cfc117c53ef9ee1336 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:50:12 +1000 Subject: Enable building the Direct Show plugin without the Window Media SDK. --- .../mediaplayer/directshowmetadatacontrol.cpp | 27 ++++++++++++++++++---- .../mediaplayer/directshowmetadatacontrol.h | 5 ++++ .../mediaplayer/directshowplayerservice.cpp | 8 +++++++ .../directshow/mediaplayer/mediaplayer.pri | 2 ++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp index 7335e3d..e95ddcd 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp @@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_WMSDK namespace { struct QWMMetaDataKeyLookup @@ -227,11 +228,14 @@ static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key) } return QVariant(); } +#endif DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent) : QMetaDataControl(parent) , m_content(0) +#ifndef QT_NO_WMSDK , m_headerInfo(0) +#endif { } @@ -246,13 +250,18 @@ bool DirectShowMetaDataControl::isWritable() const bool DirectShowMetaDataControl::isMetaDataAvailable() const { +#ifndef QT_NO_WMSDK return m_content || m_headerInfo; +#else + return m_content; +#endif } QVariant DirectShowMetaDataControl::metaData(QtMedia::MetaData key) const { QVariant value; +#ifndef QT_NO_WMSDK if (m_headerInfo) { static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup); for (int i = 0; i < count; ++i) { @@ -262,6 +271,9 @@ QVariant DirectShowMetaDataControl::metaData(QtMedia::MetaData key) const } } } else if (m_content) { +#else + if (m_content) { +#endif BSTR string = 0; switch (key) { @@ -321,16 +333,19 @@ void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *s if (m_content) m_content->Release(); - if (m_headerInfo) - m_headerInfo->Release(); - if (!graph || graph->QueryInterface( IID_IAMMediaContent, reinterpret_cast(&m_content)) != S_OK) { m_content = 0; } - m_headerInfo = com_cast(source); +#ifdef QT_NO_WMSDK + Q_UNUSED(source); +#else + if (m_headerInfo) + m_headerInfo->Release(); + m_headerInfo = com_cast(source); +#endif // DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later // time. QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged))); @@ -342,7 +357,11 @@ void DirectShowMetaDataControl::customEvent(QEvent *event) event->accept(); emit metaDataChanged(); +#ifndef QT_NO_WMSDK emit metaDataAvailableChanged(m_content || m_headerInfo); +#else + emit metaDataAvailableChanged(m_content); +#endif } else { QMetaDataControl::customEvent(event); } diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h index 9bb5fcc..eb3bbb7 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h @@ -46,7 +46,10 @@ #include #include + +#ifndef QT_NO_WMSDK #include +#endif #include @@ -88,7 +91,9 @@ private: }; IAMMediaContent *m_content; +#ifndef QT_NO_WMSDK IWMHeaderInfo *m_headerInfo; +#endif }; QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index a3362db..fdbee81 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -222,6 +222,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) HRESULT hr = E_FAIL; +#ifndef QT_NO_WMSDK if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) { if (IFileSourceFilter *fileSource = com_new(CLSID_WMAsfReader)) { locker->unlock(); @@ -242,10 +243,13 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) } if (!SUCCEEDED(hr)) { +#endif locker->unlock(); hr = m_graph->AddSourceFilter(url.toString().utf16(), L"Source", &source); locker->relock(); +#ifndef QT_NO_WMSDK } +#endif if (SUCCEEDED(hr)) { m_executedTasks = SetSource; @@ -807,6 +811,7 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker) int DirectShowPlayerService::bufferStatus() const { +#ifndef QT_NO_WMSDK QMutexLocker locker(const_cast(&m_mutex)); if (IWMReaderAdvanced2 *reader = com_cast(m_source)) { @@ -819,6 +824,9 @@ int DirectShowPlayerService::bufferStatus() const } else { return 0; } +#else + return 0; +#endif } void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri index 49ee9e5..a7adb38 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri +++ b/src/plugins/mediaservices/directshow/mediaplayer/mediaplayer.pri @@ -2,6 +2,8 @@ INCLUDEPATH += $$PWD DEFINES += QMEDIA_DIRECTSHOW_PLAYER +win32-g++: DEFINES += QT_NO_WMSDK + HEADERS += \ $$PWD/directshowaudioendpointcontrol.h \ $$PWD/directshoweventloop.h \ -- cgit v0.12 From 6c9daca8e51726472d24200654af0015f1e54eff Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 11:51:09 +1000 Subject: Enable building the Direct Show media service plugin. Some white space is required between the condtion and declaration statements. --- src/plugins/mediaservices/mediaservices.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/mediaservices.pro b/src/plugins/mediaservices/mediaservices.pro index e48156b..55e6aba 100644 --- a/src/plugins/mediaservices/mediaservices.pro +++ b/src/plugins/mediaservices/mediaservices.pro @@ -1,8 +1,8 @@ TEMPLATE = subdirs -win32:!wince:SUBDIRS += directshow +win32:!wince: SUBDIRS += directshow -mac:SUBDIRS += qt7 +mac: SUBDIRS += qt7 unix:!mac:!symbian { TMP_GST_LIBS = \ -- cgit v0.12 From 8a37893db7e340eb1dc3076496aef448c81fd4e7 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 12:00:06 +1000 Subject: Construct the meta-object directly instead of using QMetaObjectBuilder. Removes the dependency on QtDeclarative for this class. --- src/multimedia/qml/qmetadatacontrolmetaobject.cpp | 214 +++++++++++++++++----- src/multimedia/qml/qmetadatacontrolmetaobject_p.h | 10 +- 2 files changed, 175 insertions(+), 49 deletions(-) diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp index c2b5e78..6b0164b 100644 --- a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp +++ b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp @@ -40,12 +40,68 @@ ****************************************************************************/ #include - -#include /qmetadatacontrol.h> +#include QT_BEGIN_NAMESPACE +// copied from qmetaobject.cpp +// do not touch without touching the moc as well +enum PropertyFlags { + Invalid = 0x00000000, + Readable = 0x00000001, + Writable = 0x00000002, + Resettable = 0x00000004, + EnumOrFlag = 0x00000008, + StdCppSet = 0x00000100, +// Override = 0x00000200, + Designable = 0x00001000, + ResolveDesignable = 0x00002000, + Scriptable = 0x00004000, + ResolveScriptable = 0x00008000, + Stored = 0x00010000, + ResolveStored = 0x00020000, + Editable = 0x00040000, + ResolveEditable = 0x00080000, + User = 0x00100000, + ResolveUser = 0x00200000, + Notify = 0x00400000, + Dynamic = 0x00800000 +}; + +enum MethodFlags { + AccessPrivate = 0x00, + AccessProtected = 0x01, + AccessPublic = 0x02, + AccessMask = 0x03, //mask + + MethodMethod = 0x00, + MethodSignal = 0x04, + MethodSlot = 0x08, + MethodConstructor = 0x0c, + MethodTypeMask = 0x0c, + + MethodCompatibility = 0x10, + MethodCloned = 0x20, + MethodScriptable = 0x40 +}; + +struct QMetaObjectPrivate +{ + int revision; + int className; + int classInfoCount, classInfoData; + int methodCount, methodData; + int propertyCount, propertyData; + int enumeratorCount, enumeratorData; + int constructorCount, constructorData; + int flags; +}; + +static inline const QMetaObjectPrivate *priv(const uint* m_data) +{ return reinterpret_cast(m_data); } +// end of copied lines from qmetaobject.cpp + namespace { struct MetaDataKey @@ -76,7 +132,7 @@ namespace // Media { QtMedia::Size, "size" }, { QtMedia::MediaType, "mediaType" }, - { QtMedia::Duration, "duration" }, +// { QtMedia::Duration, "duration" }, // Audio { QtMedia::AudioBitRate, "audioBitRate" }, @@ -146,37 +202,132 @@ namespace { QtMedia::Sharpness, "sharpness" }, { QtMedia::DeviceSettingDescription, "deviceSettingDescription" } }; + + class QMetaDataControlObject : public QObject + { + public: + inline QObjectData *data() { return d_ptr.data(); } + }; } QMetaDataControlMetaObject::QMetaDataControlMetaObject(QMetaDataControl *control, QObject *object) : m_control(control) , m_object(object) - , m_mem(0) + , m_data(0) + , m_string(0) , m_propertyOffset(0) , m_signalOffset(0) { - m_builder.setSuperClass(m_object->metaObject()); - m_builder.setClassName(m_object->metaObject()->className()); - m_builder.setFlags(QMetaObjectBuilder::DynamicMetaObject); + const QMetaObject *superClass = m_object->metaObject(); + + const int propertyCount = sizeof(qt_metaDataKeys) / sizeof(MetaDataKey); + const int dataSize = sizeof(uint) + * (13 // QMetaObjectPrivate members. + + 5 // 5 members per signal. + + 4 * propertyCount // 3 members per property + 1 notify signal per property. + + 1); // Terminating value. + + m_data = reinterpret_cast(qMalloc(dataSize)); + + QMetaObjectPrivate *pMeta = reinterpret_cast(m_data); + + pMeta->revision = 3; + pMeta->className = 0; + pMeta->classInfoCount = 0; + pMeta->classInfoData = 0; + pMeta->methodCount = 1; + pMeta->methodData = 13; + pMeta->propertyCount = propertyCount; + pMeta->propertyData = 18; + pMeta->enumeratorCount = 0; + pMeta->enumeratorData = 0; + pMeta->constructorCount = 0; + pMeta->constructorData = 0; + pMeta->flags = 0x01; // Dynamic meta object flag. + + const int classNameSize = qstrlen(superClass->className()) + 1; + + int stringIndex = classNameSize + 1; + + // __metaDataChanged() signal. + static const char *changeSignal = "__metaDataChanged()"; + const int changeSignalSize = qstrlen(changeSignal) + 1; + + m_data[13] = stringIndex; // Signature. + m_data[14] = classNameSize; // Parameters. + m_data[15] = classNameSize; // Type. + m_data[16] = classNameSize; // Tag. + m_data[17] = MethodSignal | AccessProtected; // Flags. + + stringIndex += changeSignalSize; + + const char *qvariantName = "QVariant"; + const int qvariantSize = qstrlen(qvariantName) + 1; + const int qvariantIndex = stringIndex; + + stringIndex += qvariantSize; + + // Properties. + for (int i = 0; i < propertyCount; ++i) { + m_data[18 + 3 * i] = stringIndex; // Name. + m_data[19 + 3 * i] = qvariantIndex; // Type. + m_data[20 + 3 * i] + = Readable | Writable | Notify | Dynamic | (0xffffffff << 24); // Flags. + m_data[18 + propertyCount * 3 + i] = 0; // Notify signal. + + stringIndex += qstrlen(qt_metaDataKeys[i].name) + 1; + } + + // Terminating value. + m_data[18 + propertyCount * 4] = 0; + + // Build string. + m_string = reinterpret_cast(qMalloc(stringIndex + 1)); + + // Class name. + qMemCopy(m_string, superClass->className(), classNameSize); + + stringIndex = classNameSize; + + // Null m_string. + m_string[stringIndex] = '\0'; + stringIndex += 1; + + // __metaDataChanged() signal. + qMemCopy(m_string + stringIndex, changeSignal, changeSignalSize); + stringIndex += changeSignalSize; - QObjectPrivate *op = QObjectPrivate::get(m_object); - if (op->metaObject) - m_builder.setSuperClass(op->metaObject); + qMemCopy(m_string + stringIndex, qvariantName, qvariantSize); + stringIndex += qvariantSize; - m_mem = m_builder.toMetaObject(); - *static_cast(this) = *m_mem; + // Properties. + for (int i = 0; i < propertyCount; ++i) { + const int propertyNameSize = qstrlen(qt_metaDataKeys[i].name) + 1; + + qMemCopy(m_string + stringIndex, qt_metaDataKeys[i].name, propertyNameSize); + stringIndex += propertyNameSize; + } + + // Terminating character. + m_string[stringIndex] = '\0'; + + d.superdata = superClass; + d.stringdata = m_string; + d.data = m_data; + d.extradata = 0; + + static_cast(m_object)->data()->metaObject = this; - op->metaObject = this; m_propertyOffset = propertyOffset(); m_signalOffset = methodOffset(); } QMetaDataControlMetaObject::~QMetaDataControlMetaObject() { - qFree(m_mem); + static_cast(m_object)->data()->metaObject = 0; - QObjectPrivate *op = QObjectPrivate::get(m_object); - op->metaObject = 0; + qFree(m_data); + qFree(m_string); } int QMetaDataControlMetaObject::metaCall(QMetaObject::Call c, int id, void **a) @@ -184,15 +335,15 @@ int QMetaDataControlMetaObject::metaCall(QMetaObject::Call c, int id, void **a) if (c == QMetaObject::ReadProperty && id >= m_propertyOffset) { int propId = id - m_propertyOffset; - *reinterpret_cast(a[0]) = m_control->metaData(m_keys.at(propId)); + *reinterpret_cast(a[0]) = m_control->metaData(qt_metaDataKeys[propId].key); return -1; } else if (c == QMetaObject::WriteProperty && id >= m_propertyOffset) { int propId = id - m_propertyOffset; - m_control->setMetaData(m_keys.at(propId), *reinterpret_cast(a[0])); + m_control->setMetaData(qt_metaDataKeys[propId].key, *reinterpret_cast(a[0])); - activate(m_object, m_signalOffset + propId, 0); + activate(m_object, m_signalOffset, 0); return -1; } else { @@ -200,35 +351,14 @@ int QMetaDataControlMetaObject::metaCall(QMetaObject::Call c, int id, void **a) } } -int QMetaDataControlMetaObject::createProperty(const char *name, const char *) +int QMetaDataControlMetaObject::createProperty(const char *, const char *) { - const int count = sizeof(qt_metaDataKeys) / sizeof(MetaDataKey); - - for (int i = 0; i < count; ++i) { - if (qstrcmp(name, qt_metaDataKeys[i].name) == 0) { - int id = m_keys.count(); - m_keys.append(qt_metaDataKeys[i].key); - - m_builder.addSignal("__" + QByteArray::number(id) + "()"); - - QMetaPropertyBuilder build = m_builder.addProperty(name, "QVariant", id); - build.setDynamic(true); - - qFree(m_mem); - m_mem = m_builder.toMetaObject(); - *static_cast(this) = *m_mem; - - return m_propertyOffset + id; - } - } - return -1; } void QMetaDataControlMetaObject::metaDataChanged() { - for (int i = 0; i < m_keys.count(); ++i) - activate(m_object, m_signalOffset + i, 0); + activate(m_object, m_signalOffset, 0); } QT_END_NAMESPACE diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject_p.h b/src/multimedia/qml/qmetadatacontrolmetaobject_p.h index b7f88fe..c0fd4e8 100644 --- a/src/multimedia/qml/qmetadatacontrolmetaobject_p.h +++ b/src/multimedia/qml/qmetadatacontrolmetaobject_p.h @@ -42,12 +42,10 @@ #ifndef QMETADATACONTROLMETAOBJECT_P_H #define QMETADATACONTROLMETAOJBECT_P_H +#include #include -#include #include -#include - QT_BEGIN_HEADER @@ -69,13 +67,11 @@ public: private: QMetaDataControl *m_control; QObject *m_object; - QMetaObject *m_mem; + char *m_string; + uint *m_data; int m_propertyOffset; int m_signalOffset; - - QVector m_keys; - QMetaObjectBuilder m_builder; }; QT_END_NAMESPACE -- cgit v0.12 From 5588657ba3b2a060e60bf8d83fd5ba60bbdc9c64 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 3 Feb 2010 12:57:47 +1000 Subject: Add tests fro QGraphicsVideoItem. --- tests/auto/auto.pro | 1 + .../auto/qgraphicsvideoitem/qgraphicsvideoitem.pro | 5 + .../qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp | 670 +++++++++++++++++++++ 3 files changed, 676 insertions(+) create mode 100644 tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro create mode 100644 tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index aacb1dc..809b523 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -171,6 +171,7 @@ SUBDIRS += \ qgraphicsscene \ qgraphicssceneindex \ qgraphicstransform \ + qgraphicsvideoitem \ qgraphicsview \ qgraphicswidget \ qgridlayout \ diff --git a/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro b/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro new file mode 100644 index 0000000..da00baf --- /dev/null +++ b/tests/auto/qgraphicsvideoitem/qgraphicsvideoitem.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +SOURCES += tst_qgraphicsvideoitem.cpp + +QT += multimedia +requires(contains(QT_CONFIG, multimedia)) diff --git a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp new file mode 100644 index 0000000..19433e4 --- /dev/null +++ b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp @@ -0,0 +1,670 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class tst_QGraphicsVideoItem : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void nullObject(); + void nullService(); + void nullOutputControl(); + 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 QtTestOutputControl : public QVideoOutputControl +{ +public: + QtTestOutputControl() : m_output(NoOutput) {} + + QList availableOutputs() const { return m_outputs; } + void setAvailableOutputs(const QList outputs) { m_outputs = outputs; } + + Output output() const { return m_output; } + virtual void setOutput(Output output) { m_output = output; } + +private: + Output m_output; + QList m_outputs; +}; + +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( + QtTestOutputControl *output, + QtTestRendererControl *renderer) + : QMediaService(0) + , outputControl(output) + , rendererControl(renderer) + { + } + + ~QtTestVideoService() + { + delete outputControl; + delete rendererControl; + } + + QMediaControl *control(const char *name) const + { + if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return outputControl; + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return rendererControl; + else + return 0; + } + + QtTestOutputControl *outputControl; + QtTestRendererControl *rendererControl; +}; + +class QtTestVideoObject : public QMediaObject +{ + Q_OBJECT +public: + QtTestVideoObject(QtTestRendererControl *renderer): + QMediaObject(0, new QtTestVideoService(new QtTestOutputControl, renderer)) + { + testService = qobject_cast(service()); + QList outputs; + + if (renderer) + outputs.append(QVideoOutputControl::RendererOutput); + + testService->outputControl->setAvailableOutputs(outputs); + } + + 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; + item->setMediaObject(&object); + + QVERIFY(item->boundingRect().isEmpty()); + + item->hide(); + item->show(); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); +} + +void tst_QGraphicsVideoItem::nullOutputControl() +{ + QtTestVideoObject object(new QtTestVideoService(0, 0)); + + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + item->setMediaObject(&object); + + 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; + item->setMediaObject(&object); + + QVERIFY(item->boundingRect().isEmpty()); + + item->hide(); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + item->show(); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); +} + +void tst_QGraphicsVideoItem::serviceDestroyed() +{ + QtTestVideoObject object(new QtTestRendererControl); + + QGraphicsVideoItem item; + item.setMediaObject(&object); + + 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; + item.setMediaObject(object); + + 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->outputControl->output(), QVideoOutputControl::NoOutput); + + item.setMediaObject(&object); + QCOMPARE(item.mediaObject(), static_cast(&object)); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); + QVERIFY(object.testService->rendererControl->surface() != 0); + + item.setMediaObject(0); + QCOMPARE(item.mediaObject(), nullObject); + + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + item.setVisible(false); + + item.setMediaObject(&object); + QCOMPARE(item.mediaObject(), static_cast(&object)); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QVERIFY(object.testService->rendererControl->surface() != 0); +} + +void tst_QGraphicsVideoItem::show() +{ + QtTestVideoObject object(new QtTestRendererControl); + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + item->setMediaObject(&object); + + // Graphics items are visible by default + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); + QVERIFY(object.testService->rendererControl->surface() != 0); + + item->hide(); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + + item->show(); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); + 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)); + + QVERIFY(!item->boundingRect().isEmpty()); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); + + QVERIFY(item->paintCount() || item->waitForPaint(1)); +} + +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; + item.setMediaObject(&object); + + QCOMPARE(item.nativeSize(), QSizeF()); + + QSignalSpy spy(&item, SIGNAL(nativeSizeChanged(QSizeF))); + + QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32); + format.setViewport(viewport); + format.setPixelAspectRatio(pixelAspectRatio); + + QVERIFY(object.testService->rendererControl->surface()->start(format)); + + QCOMPARE(item.nativeSize(), nativeSize); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.last().first().toSizeF(), nativeSize); + + object.testService->rendererControl->surface()->stop(); + + QCOMPARE(item.nativeSize(), QSizeF(0, 0)); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.last().first().toSizeF(), QSizeF(0, 0)); +} + +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; + item.setMediaObject(&object); + + item.setOffset(offset); + item.setSize(size); + item.setAspectRatioMode(aspectRatioMode); + + QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32); + + QVERIFY(object.testService->rendererControl->surface()->start(format)); + + 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; + item->setMediaObject(&object); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); + + 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); + + 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" -- cgit v0.12 From 1d48062f758ae82129583b0e95b18d06faf57547 Mon Sep 17 00:00:00 2001 From: Nicholas Young Date: Thu, 4 Feb 2010 10:45:43 +1000 Subject: Added QNetworkRequest constructor to QMediaResource. --- src/multimedia/base/base.pri | 1 + src/multimedia/base/qmediaresource.cpp | 24 +++++++++++-- src/multimedia/base/qmediaresource.h | 6 +++- tests/auto/qmediaresource/qmediaresource.pro | 2 +- tests/auto/qmediaresource/tst_qmediaresource.cpp | 45 ++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/multimedia/base/base.pri b/src/multimedia/base/base.pri index fb2784d..5aebbf0 100644 --- a/src/multimedia/base/base.pri +++ b/src/multimedia/base/base.pri @@ -1,4 +1,5 @@ +QT += network contains(QT_CONFIG, opengl):QT += opengl HEADERS += \ diff --git a/src/multimedia/base/qmediaresource.cpp b/src/multimedia/base/qmediaresource.cpp index ab18ce7..515e432 100644 --- a/src/multimedia/base/qmediaresource.cpp +++ b/src/multimedia/base/qmediaresource.cpp @@ -93,7 +93,17 @@ QMediaResource::QMediaResource() */ QMediaResource::QMediaResource(const QUrl &url, const QString &mimeType) { - values.insert(Url, qVariantFromValue(url)); + values.insert(Url, url); + values.insert(MimeType, mimeType); +} + +/*! + Constructs a media resource with the given \a mimeType from a network \a request. +*/ +QMediaResource::QMediaResource(const QNetworkRequest &request, const QString &mimeType) +{ + values.insert(Request, QVariant::fromValue(request)); + values.insert(Url, request.url()); values.insert(MimeType, mimeType); } @@ -162,6 +172,17 @@ QUrl QMediaResource::url() const } /*! + Returns the network request associated with this media resource. +*/ +QNetworkRequest QMediaResource::request() const +{ + if(values.contains(Request)) + return qvariant_cast(values.value(Request)); + + return QNetworkRequest(url()); +} + +/*! Returns the MIME type of a media resource. This may be null if the MIME type is unknown. @@ -373,6 +394,5 @@ void QMediaResource::setResolution(int width, int height) else values.remove(Resolution); } - QT_END_NAMESPACE diff --git a/src/multimedia/base/qmediaresource.h b/src/multimedia/base/qmediaresource.h index 33b5a79..516120a 100644 --- a/src/multimedia/base/qmediaresource.h +++ b/src/multimedia/base/qmediaresource.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -58,6 +59,7 @@ class Q_MULTIMEDIA_EXPORT QMediaResource public: QMediaResource(); QMediaResource(const QUrl &url, const QString &mimeType = QString()); + QMediaResource(const QNetworkRequest &request, const QString &mimeType = QString()); QMediaResource(const QMediaResource &other); QMediaResource &operator =(const QMediaResource &other); ~QMediaResource(); @@ -68,6 +70,7 @@ public: bool operator !=(const QMediaResource &other) const; QUrl url() const; + QNetworkRequest request() const; QString mimeType() const; QString language() const; @@ -103,6 +106,7 @@ private: enum Property { Url, + Request, MimeType, Language, AudioCodec, @@ -112,7 +116,7 @@ private: VideoBitRate, SampleRate, ChannelCount, - Resolution, + Resolution }; QMap values; }; diff --git a/tests/auto/qmediaresource/qmediaresource.pro b/tests/auto/qmediaresource/qmediaresource.pro index 2741608..c8e3d9c 100644 --- a/tests/auto/qmediaresource/qmediaresource.pro +++ b/tests/auto/qmediaresource/qmediaresource.pro @@ -2,5 +2,5 @@ load(qttest_p4) SOURCES = tst_qmediaresource.cpp -QT = core multimedia +QT = core multimedia network diff --git a/tests/auto/qmediaresource/tst_qmediaresource.cpp b/tests/auto/qmediaresource/tst_qmediaresource.cpp index 55ddcab..127144d 100644 --- a/tests/auto/qmediaresource/tst_qmediaresource.cpp +++ b/tests/auto/qmediaresource/tst_qmediaresource.cpp @@ -63,6 +63,7 @@ void tst_QMediaResource::constructNull() QCOMPARE(resource.isNull(), true); QCOMPARE(resource.url(), QUrl()); + QCOMPARE(resource.request(), QNetworkRequest()); QCOMPARE(resource.mimeType(), QString()); QCOMPARE(resource.language(), QString()); QCOMPARE(resource.audioCodec(), QString()); @@ -78,6 +79,7 @@ void tst_QMediaResource::constructNull() void tst_QMediaResource::construct_data() { QTest::addColumn("url"); + QTest::addColumn("request"); QTest::addColumn("mimeType"); QTest::addColumn("language"); QTest::addColumn("audioCodec"); @@ -91,6 +93,7 @@ void tst_QMediaResource::construct_data() 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") @@ -103,6 +106,7 @@ void tst_QMediaResource::construct_data() << 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() @@ -115,6 +119,7 @@ void tst_QMediaResource::construct_data() << 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") @@ -127,6 +132,7 @@ void tst_QMediaResource::construct_data() << 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() @@ -142,6 +148,7 @@ void tst_QMediaResource::construct_data() void tst_QMediaResource::construct() { QFETCH(QUrl, url); + QFETCH(QNetworkRequest, request); QFETCH(QString, mimeType); QFETCH(QString, language); QFETCH(QString, audioCodec); @@ -174,6 +181,44 @@ void tst_QMediaResource::construct() 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()); -- cgit v0.12 From 623fa99d781a5cc2ddbd330f949764333fcd7ab1 Mon Sep 17 00:00:00 2001 From: Nicholas Young Date: Thu, 4 Feb 2010 11:18:31 +1000 Subject: Revert "Added QtMultimedia audio/video to Webkit." This reverts commit 7574328b1bdfb5d7d34aa2428cb5dc623f19f4aa. --- src/3rdparty/webkit/WebCore/WebCore.pro | 28 +- .../WebCore/platform/graphics/MediaPlayer.cpp | 2 +- .../platform/graphics/qt/MediaPlayerPrivateQt.cpp | 583 --------------------- .../platform/graphics/qt/MediaPlayerPrivateQt.h | 110 ---- 4 files changed, 18 insertions(+), 705 deletions(-) delete mode 100644 src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp delete mode 100644 src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 337a6b5..04aba62 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -166,8 +166,8 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) { # HTML5 media support !contains(DEFINES, ENABLE_VIDEO=.) { - contains(QT_CONFIG, multimedia): DEFINES += ENABLE_VIDEO=1 - else: DEFINES += ENABLE_VIDEO=0 + contains(QT_CONFIG, phonon):DEFINES += ENABLE_VIDEO=1 + else:DEFINES += ENABLE_VIDEO=0 } # HTML5 datalist support @@ -2732,17 +2732,23 @@ contains(DEFINES, ENABLE_VIDEO=1) { rendering/RenderMedia.cpp \ bindings/js/JSAudioConstructor.cpp - INCLUDEPATH += \ - $$PWD/../../../multimedia/base - - HEADERS += \ - platform/graphics/qt/MediaPlayerPrivateQt.h + HEADERS += \ + platform/graphics/qt/MediaPlayerPrivatePhonon.h - SOURCES += \ - platform/graphics/qt/MediaPlayerPrivateQt.cpp + SOURCES += \ + platform/graphics/qt/MediaPlayerPrivatePhonon.cpp + + # Add phonon manually to prevent it from coming first in + # the include paths, as Phonon's path.h conflicts with + # WebCore's Path.h on case-insensitive filesystems. + qtAddLibrary(phonon) + INCLUDEPATH -= $$QMAKE_INCDIR_QT/phonon + INCLUDEPATH += $$QMAKE_INCDIR_QT/phonon + mac { + INCLUDEPATH -= $$QMAKE_LIBDIR_QT/phonon.framework/Headers + INCLUDEPATH += $$QMAKE_LIBDIR_QT/phonon.framework/Headers + } - QT += multimedia - contains(QT_CONFIG, opengl): QT += opengl } contains(DEFINES, ENABLE_XPATH=1) { diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp index 07232fd..3b32b65 100644 --- a/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp +++ b/src/3rdparty/webkit/WebCore/platform/graphics/MediaPlayer.cpp @@ -46,7 +46,7 @@ #elif PLATFORM(GTK) #include "MediaPlayerPrivateGStreamer.h" #elif PLATFORM(QT) -#include "MediaPlayerPrivateQt.h" +#include "MediaPlayerPrivatePhonon.h" #elif PLATFORM(CHROMIUM) #include "MediaPlayerPrivateChromium.h" #endif diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp deleted file mode 100644 index 967e125..0000000 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - Copyright (C) 2009 Apple Inc. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "config.h" -#include "MediaPlayerPrivateQt.h" - -#include - -// WebCore Includes -#include "CString.h" -#include "FrameView.h" -#include "GraphicsContext.h" -#include "NotImplemented.h" -#include "TimeRanges.h" -#include "Widget.h" - -// WebKit Includes -#include - -// Qt Includes -#include -#include -#include -#include -#include -#include - -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) -#include -#endif - -// Qt Multimedia Includes -#include -#include -#include -#include - - -//#define QT_WEBKIT_MEDIA_INSTRUMENTATION - -using namespace WTF; - -namespace WebCore { - -#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION -class MediaPlayerPrivateInstrumentation -{ -public: - MediaPlayerPrivateInstrumentation() - : update(false) - , frameCount(0) - , paintTimeTotal(0) - , framesPerSecond(0) - , averagePaintTime(0) - , preTime(QTime()) - , lastUpdate(QTime::currentTime()) {} - - void prePaint() { preTime = QTime::currentTime(); } - - void postPaint() - { - QTime time = QTime::currentTime(); - - // Measure seconds different - int paintTime = (time.second() - preTime.second() - 1) * 1000; - paintTime = qMax(0, paintTime); - - // Measure milliseconds different - if(time.msec() < preTime.msec()) - paintTime += time.msec() + (1000 - preTime.msec()); - else - paintTime += time.msec() - preTime.msec(); - - // Add to the total paint time for this second - paintTimeTotal += paintTime; - - // Check for update time - if(time.second() != lastUpdate.second()) { - // Calculate Values - framesPerSecond = frameCount; - averagePaintTime = static_cast(paintTimeTotal) / static_cast(frameCount); - - // Next Update - update = true; - frameCount = 1; - paintTimeTotal = 0; - lastUpdate = time; - } else { - frameCount++; - } - } - - bool updateAvailable() { return update; } - - int fps() { update = false; return framesPerSecond; } - qreal paintTime() { update = false; return averagePaintTime; } - -private: - bool update; - - int frameCount; - qint64 paintTimeTotal; - - int framesPerSecond; - qreal averagePaintTime; - - QTime preTime; - QTime lastUpdate; -}; -#endif // QT_WEBKIT_MEDIA_INSTRUMENTATION - -class MediaPlayerPrivateDefault : public MediaPlayerPrivate { -public: - IntSize naturalSize() const; - void setSize(const IntSize&) {} - void paint(GraphicsContext*, const IntRect&); - bool supportsFullscreen() const { return true; } - -private slots: - void repaint(); - -private: - friend class MediaPlayerPrivate; - MediaPlayerPrivateDefault(MediaPlayer*); - ~MediaPlayerPrivateDefault(); - - QPainterVideoSurface* m_videoSurface; - QVideoOutputControl* m_outputControl; - QVideoRendererControl* m_rendererControl; - - bool m_isActive; - -#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION - MediaPlayerPrivateInstrumentation* m_instruments; -#endif -}; - -MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) -{ - return new MediaPlayerPrivateDefault(player); -} - -void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) -{ - registrar(create, getSupportedTypes, supportsType); -} - -void MediaPlayerPrivate::getSupportedTypes(HashSet &supported) -{ - QStringList types = QMediaPlayer::supportedMimeTypes(); - - for (int i = 0; i < types.size(); i++) { - supported.add(types.at(i)); - } -} - -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, const String& codec) -{ - if(QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMedia::ProbablySupported) { - return MediaPlayer::IsSupported; - } - - return MediaPlayer::MayBeSupported; -} - -MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) - : m_player(player) - , m_mediaPlayer(new QMediaPlayer) - , m_networkState(MediaPlayer::Empty) - , m_readyState(MediaPlayer::HaveNothing) - , m_isVisible(false) - , m_endTime(std::numeric_limits::max()) -{ - // Signal Handlers - connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), - this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus))); - connect(m_mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), - this, SLOT(stateChanged(QMediaPlayer::State))); - connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)), - this, SLOT(handleError(QMediaPlayer::Error))); - connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)), - this, SLOT(durationChanged(qint64))); - connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)), - this, SLOT(positionChanged(qint64))); - - // Grab the player control - if (m_mediaPlayer) { - QMediaService *service = m_mediaPlayer->service(); - if (service) { - m_mediaPlayerControl = qobject_cast( - service->control(QMediaPlayerControl_iid)); - } - } -} - -MediaPlayerPrivate::~MediaPlayerPrivate() -{ - delete m_mediaPlayer; - m_mediaPlayer = 0; -} - -bool MediaPlayerPrivate::hasVideo() const -{ - return m_mediaPlayer->isVideoAvailable(); -} - -bool MediaPlayerPrivate::hasAudio() const -{ - return true; -} - -void MediaPlayerPrivate::load(const String& url) -{ - // We are now loading - if (m_networkState != MediaPlayer::Loading) { - m_networkState = MediaPlayer::Loading; - m_player->networkStateChanged(); - } - - // And we don't have any data yet - if (m_readyState != MediaPlayer::HaveNothing) { - m_readyState = MediaPlayer::HaveNothing; - m_player->readyStateChanged(); - } - - m_mediaPlayer->setMedia(QUrl(url)); -} - -void MediaPlayerPrivate::cancelLoad() -{ - m_mediaPlayer->setMedia(QMediaContent()); - updateStates(); -} - -void MediaPlayerPrivate::play() -{ - if(m_mediaPlayer->state() != QMediaPlayer::PlayingState) { - m_mediaPlayer->play(); - } -} - -void MediaPlayerPrivate::pause() -{ - if(m_mediaPlayer->state() == QMediaPlayer::PlayingState) { - m_mediaPlayer->pause(); - } -} - -bool MediaPlayerPrivate::paused() const -{ - return m_mediaPlayer->state() != QMediaPlayer::PlayingState; -} - -void MediaPlayerPrivate::seek(float position) -{ - if (!m_mediaPlayer->isSeekable()) - return; - - if (m_mediaPlayerControl != 0 && - !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000)) - return; - - if (position > duration()) - position = duration(); - - m_mediaPlayer->setPosition(position * 1000.0f); -} - -bool MediaPlayerPrivate::seeking() const -{ - return false; -} - -void MediaPlayerPrivate::setEndTime(float time) -{ - // Set the end time in milliseconds - m_endTime = static_cast(time * 1000.0f); - - // Duration may return a smaller value as of now - m_player->durationChanged(); -} - -float MediaPlayerPrivate::duration() const -{ - if (m_readyState < MediaPlayer::HaveMetadata) - return 0.0f; - - float duration = qMin(m_mediaPlayer->duration(), m_endTime) / 1000.0f; - - // We are streaming - if (duration <= 0.0f) - duration = std::numeric_limits::infinity(); - - return duration; -} - -float MediaPlayerPrivate::currentTime() const -{ - float currentTime = m_mediaPlayer->position() / 1000.0f; - return currentTime; -} - -PassRefPtr MediaPlayerPrivate::buffered() const -{ - RefPtr buffered = TimeRanges::create(); - - if(m_mediaPlayerControl == 0) - return buffered; - - QMediaTimeRange playbackRanges = m_mediaPlayerControl->availablePlaybackRanges(); - - foreach(const QMediaTimeInterval interval, playbackRanges.intervals()) { - float rangeMin = static_cast(interval.start()) / 1000.0f; - float rangeMax = static_cast(interval.end()) / 1000.0f; - buffered->add(rangeMin, rangeMax); - } - - return buffered.release(); -} - -float MediaPlayerPrivate::maxTimeSeekable() const -{ - if(m_mediaPlayerControl == 0) - return 0; - - return static_cast(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f; -} - -unsigned MediaPlayerPrivate::bytesLoaded() const -{ - unsigned percentage = m_mediaPlayer->bufferStatus(); - - if(percentage == 100) { - if(m_networkState != MediaPlayer::Idle) { - m_networkState = MediaPlayer::Idle; - m_player->networkStateChanged(); - } - if(m_readyState != MediaPlayer::HaveEnoughData) { - m_readyState = MediaPlayer::HaveEnoughData; - m_player->readyStateChanged(); - } - } - - QLatin1String blKey("bytes-loaded"); - if(m_mediaPlayer->availableExtendedMetaData().contains(blKey)) - return m_mediaPlayer->extendedMetaData(blKey).toInt(); - - return percentage; -} - -unsigned MediaPlayerPrivate::totalBytes() const -{ - if(m_mediaPlayer->availableMetaData().contains(QtMedia::Size)) - return m_mediaPlayer->metaData(QtMedia::Size).toInt(); - - return 100; -} - -bool MediaPlayerPrivate::totalBytesKnown() const -{ - return m_mediaPlayer->availableMetaData().contains(QtMedia::Size); -} - -void MediaPlayerPrivate::setRate(float rate) -{ - m_mediaPlayer->setPlaybackRate(rate); -} - -void MediaPlayerPrivate::setVolume(float volume) -{ - m_mediaPlayer->setVolume(static_cast(volume * 100.0)); -} - -void MediaPlayerPrivate::setMuted(bool muted) -{ - m_mediaPlayer->setMuted(muted); -} - -int MediaPlayerPrivate::dataRate() const -{ - return 0; -} - -MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const -{ - return m_networkState; -} - -MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const -{ - return m_readyState; -} - -void MediaPlayerPrivate::setVisible(bool visible) -{ - m_isVisible = visible; -} - -void MediaPlayerPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus) -{ - updateStates(); -} - -void MediaPlayerPrivate::handleError(QMediaPlayer::Error) -{ - updateStates(); -} - -void MediaPlayerPrivate::durationChanged(qint64) -{ - m_player->durationChanged(); -} - -void MediaPlayerPrivate::updateStates() -{ - // Store the old states so that we can detect a change and raise change events - MediaPlayer::NetworkState oldNetworkState = m_networkState; - MediaPlayer::ReadyState oldReadyState = m_readyState; - - QMediaPlayer::MediaStatus currentStatus = m_mediaPlayer->mediaStatus(); - QMediaPlayer::Error currentError = m_mediaPlayer->error(); - - if(currentError != QMediaPlayer::NoError) { - m_readyState = MediaPlayer::HaveNothing; - if(currentError == QMediaPlayer::FormatError) { - m_networkState = MediaPlayer::FormatError; - } else { - // ResourceError, NetworkError, AccessDeniedError, ServiceMissingError - m_networkState = MediaPlayer::NetworkError; - } - } else if(currentStatus == QMediaPlayer::UnknownMediaStatus || - currentStatus == QMediaPlayer::NoMedia) { - m_networkState = MediaPlayer::Idle; - m_readyState = MediaPlayer::HaveNothing; - } else if(currentStatus == QMediaPlayer::LoadingMedia) { - m_networkState = MediaPlayer::Loading; - m_readyState = MediaPlayer::HaveNothing; - } else if(currentStatus == QMediaPlayer::LoadedMedia) { - m_networkState = MediaPlayer::Loading; - m_readyState = MediaPlayer::HaveMetadata; - } else if(currentStatus == QMediaPlayer::BufferingMedia) { - m_networkState = MediaPlayer::Loading; - m_readyState = MediaPlayer::HaveFutureData; - } else if(currentStatus == QMediaPlayer::StalledMedia) { - m_networkState = MediaPlayer::Loading; - m_readyState = MediaPlayer::HaveCurrentData; - } else if(currentStatus == QMediaPlayer::BufferedMedia || - currentStatus == QMediaPlayer::EndOfMedia) { - m_networkState = MediaPlayer::Idle; - m_readyState = MediaPlayer::HaveEnoughData; - } else if(currentStatus == QMediaPlayer::InvalidMedia) { - m_networkState = MediaPlayer::FormatError; - m_readyState = MediaPlayer::HaveMetadata; - } - - // Log the state changes and raise the state change events - if (m_networkState != oldNetworkState) { - m_player->networkStateChanged(); - } - - if (m_readyState != oldReadyState) { - m_player->readyStateChanged(); - } -} - -MediaPlayerPrivateDefault::MediaPlayerPrivateDefault(MediaPlayer *player) - : MediaPlayerPrivate(player) - , m_videoSurface(new QPainterVideoSurface(m_mediaPlayer)) -{ -#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION - m_instruments = new MediaPlayerPrivateInstrumentation; -#endif - - if (m_mediaPlayer) { - QMediaService *service = m_mediaPlayer->service(); - if (service) { - m_outputControl = qobject_cast( - service->control(QVideoOutputControl_iid)); - m_rendererControl = qobject_cast( - service->control(QVideoRendererControl_iid)); - - if (m_outputControl != 0 && m_rendererControl != 0) { - connect(m_videoSurface, SIGNAL(frameChanged()), this, SLOT(repaint())); - - m_rendererControl->setSurface(m_videoSurface); - m_outputControl->setOutput(QVideoOutputControl::RendererOutput); - } - } - } -} - -MediaPlayerPrivateDefault::~MediaPlayerPrivateDefault() -{ -#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION - delete m_instruments; - m_instruments = 0; -#endif -} - -IntSize MediaPlayerPrivateDefault::naturalSize() const -{ - if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata) - return IntSize(); - - QSize videoSize = m_videoSurface->surfaceFormat().sizeHint(); - return IntSize(videoSize.width(), videoSize.height()); -} - -void MediaPlayerPrivateDefault::paint(GraphicsContext* context, const IntRect& rect) -{ - if (context->paintingDisabled()) - return; - - if (!m_isVisible) - return; - -#ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION - m_instruments->prePaint(); -#endif - - // Grab the painter - QPainter* painter = context->platformContext(); - - if(!m_isActive) { - // Attempt GL Setup -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) - if ((painter->paintEngine()->type() == QPaintEngine::OpenGL || - painter->paintEngine()->type() == QPaintEngine::OpenGL2)) { - // Set GL Context - m_videoSurface->setGLContext(const_cast(QGLContext::currentContext())); - - // Check Shader Types - if (m_videoSurface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) { - m_videoSurface->setShaderType(QPainterVideoSurface::GlslShader); - } else { - m_videoSurface->setShaderType(QPainterVideoSurface::FragmentProgramShader); - } - } -#endif - - // Setup Completed - m_isActive = true; - } - - // Paint the frame - m_videoSurface->paint(painter, QRect(rect.x(), rect.y(), - rect.width(), rect.height())); - m_videoSurface->setReady(true); - - #ifdef QT_WEBKIT_MEDIA_INSTRUMENTATION - m_instruments->postPaint(); - - if(m_instruments->updateAvailable()) { - qDebug("FPS: %d, Average Paint Time: %f", m_instruments->fps(), m_instruments->paintTime()); - } - #endif -} - -void MediaPlayerPrivateDefault::repaint() -{ - m_player->repaint(); -} - -} // namespace WebCore - -#include "moc_MediaPlayerPrivateQt.cpp" diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h deleted file mode 100644 index f2d4040..0000000 --- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - Copyright (C) 2009 Apple Inc. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef MediaPlayerPrivateQt_h -#define MediaPlayerPrivateQt_h - -#include "MediaPlayerPrivate.h" -#include -#include -#include - -namespace WebCore { - - class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface { - - Q_OBJECT - - public: - static MediaPlayerPrivateInterface* create(MediaPlayer* player); - virtual ~MediaPlayerPrivate(); - - static void registerMediaEngine(MediaEngineRegistrar); - static void getSupportedTypes(HashSet&); - static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); - static bool isAvailable() { return true; } - - bool hasVideo() const; - bool hasAudio() const; - - void load(const String &url); - void cancelLoad(); - - void play(); - void pause(); - - bool paused() const; - bool seeking() const; - - float duration() const; - float currentTime() const; - void seek(float); - void setEndTime(float); - - void setRate(float); - void setVolume(float); - void setMuted(bool); - - // State Information - MediaPlayer::NetworkState networkState() const; - MediaPlayer::ReadyState readyState() const; - - // Network Information - PassRefPtr buffered() const; - float maxTimeSeekable() const; - unsigned bytesLoaded() const; - unsigned totalBytes() const; - bool totalBytesKnown() const; - int dataRate() const; - - virtual void setVisible(bool); - - virtual IntSize naturalSize() const = 0; - virtual void setSize(const IntSize&) = 0; - virtual void paint(GraphicsContext*, const IntRect&) = 0; - virtual bool supportsFullscreen() const = 0; - - protected slots: - virtual void mediaStatusChanged(QMediaPlayer::MediaStatus); - virtual void handleError(QMediaPlayer::Error); - virtual void stateChanged(QMediaPlayer::State) {} - virtual void positionChanged(qint64) {} - virtual void durationChanged(qint64); - virtual void repaint() {} - - protected: - MediaPlayerPrivate(MediaPlayer*); - - MediaPlayer* m_player; - QMediaPlayer* m_mediaPlayer; - QMediaPlayerControl* m_mediaPlayerControl; - - mutable MediaPlayer::NetworkState m_networkState; - mutable MediaPlayer::ReadyState m_readyState; - - bool m_isVisible; - qint64 m_endTime; - - private: - void updateStates(); - }; -} - -#endif // MediaPlayerPrivateQt_h -- cgit v0.12 From 10888061f86eef9a73fff548b6dc325471cbb809 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:02:11 +1000 Subject: Round off volume when converting from real to int. And return a volume of 0 if there's no player control. --- src/multimedia/qml/qmlmediabase.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/multimedia/qml/qmlmediabase.cpp b/src/multimedia/qml/qmlmediabase.cpp index 0f0f1e4..e2a1832 100644 --- a/src/multimedia/qml/qmlmediabase.cpp +++ b/src/multimedia/qml/qmlmediabase.cpp @@ -78,7 +78,7 @@ public: qint64 duration() const { return 0; } qint64 position() const { return 0; } void setPosition(qint64) {} - int volume() const { return 100; } + int volume() const { return 0; } void setVolume(int) {} bool isMuted() const { return false; } void setMuted(bool) {} @@ -267,6 +267,8 @@ void QmlMediaBase::setObject(QObject *object) m_animation = new QmlMediaBaseAnimation(this); } else { + m_error = QMediaPlayer::ServiceMissingError; + m_playerControl = new QmlMediaBasePlayerControl(object); } @@ -337,7 +339,7 @@ qreal QmlMediaBase::volume() const void QmlMediaBase::setVolume(qreal volume) { - m_playerControl->setVolume(volume * 100); + m_playerControl->setVolume(qRound(volume * 100)); } bool QmlMediaBase::isMuted() const -- cgit v0.12 From 275d642215388013247e07d4b351be88422bff41 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:09:07 +1000 Subject: Connect changed signals from QMediaPlayerControl to media QML elements. --- src/multimedia/qml/qmlmediabase.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/multimedia/qml/qmlmediabase.cpp b/src/multimedia/qml/qmlmediabase.cpp index e2a1832..4b42058 100644 --- a/src/multimedia/qml/qmlmediabase.cpp +++ b/src/multimedia/qml/qmlmediabase.cpp @@ -264,6 +264,12 @@ void QmlMediaBase::setObject(QObject *object) object, SIGNAL(volumeChanged())); QObject::connect(m_playerControl, SIGNAL(mutedChanged(bool)), object, SIGNAL(mutedChanged())); + QObject::connect(m_playerControl, SIGNAL(bufferStatusChanged(int)), + object, SIGNAL(bufferProgressChanged())); + QObject::connect(m_playerControl, SIGNAL(seekableChanged(bool)), + object, SIGNAL(seekableChanged())); + QObject::connect(m_playerControl, SIGNAL(playbackRateChanged(qreal)), + object, SIGNAL(playbackRateChanged())); m_animation = new QmlMediaBaseAnimation(this); } else { -- cgit v0.12 From e6c91eacfefcaf9cab83f5cb82d1487b8a870117 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:11:29 +1000 Subject: Propagate error signals from QMediaPlayerControl to media QML elements. --- src/multimedia/qml/qmlaudio.cpp | 4 ++-- src/multimedia/qml/qmlaudio_p.h | 4 ++-- src/multimedia/qml/qmlgraphicsvideo.cpp | 4 ++-- src/multimedia/qml/qmlgraphicsvideo_p.h | 4 ++-- src/multimedia/qml/qmlmediabase.cpp | 9 +++++++++ src/multimedia/qml/qmlmediabase_p.h | 4 +++- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/multimedia/qml/qmlaudio.cpp b/src/multimedia/qml/qmlaudio.cpp index 713e36a..adff49b 100644 --- a/src/multimedia/qml/qmlaudio.cpp +++ b/src/multimedia/qml/qmlaudio.cpp @@ -58,9 +58,9 @@ QML_DEFINE_TYPE(Qt,4,6,Audio,QmlAudio); \brief The QmlAudio class provides a audio item that you can add to a QmlView. */ -void QmlAudio::_q_error(QMediaPlayer::Error errorCode, const QString &errorString) +void QmlAudio::_q_error(int errorCode, const QString &errorString) { - m_error = errorCode; + m_error = QMediaPlayer::Error(errorCode); m_errorString = errorString; emit error(Error(errorCode), errorString); diff --git a/src/multimedia/qml/qmlaudio_p.h b/src/multimedia/qml/qmlaudio_p.h index c6ab53d..f034518 100644 --- a/src/multimedia/qml/qmlaudio_p.h +++ b/src/multimedia/qml/qmlaudio_p.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QTimerEvent; -class QmlAudio : public QObject, public QmlMediaBase, public QmlParserStatus +class Q_AUTOTEST_EXPORT QmlAudio : public QObject, public QmlMediaBase, public QmlParserStatus { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) @@ -142,7 +142,7 @@ Q_SIGNALS: void error(QmlAudio::Error error, const QString &errorString); private Q_SLOTS: - void _q_error(QMediaPlayer::Error, const QString &); + void _q_error(int, const QString &); private: Q_DISABLE_COPY(QmlAudio) diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp index c96f7e9..784c7b6 100644 --- a/src/multimedia/qml/qmlgraphicsvideo.cpp +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -59,9 +59,9 @@ void QmlGraphicsVideo::_q_nativeSizeChanged(const QSizeF &size) setImplicitHeight(size.height()); } -void QmlGraphicsVideo::_q_error(QMediaPlayer::Error errorCode, const QString &errorString) +void QmlGraphicsVideo::_q_error(int errorCode, const QString &errorString) { - m_error = errorCode; + m_error = QMediaPlayer::Error(errorCode); m_errorString = errorString; emit error(Error(errorCode), errorString); diff --git a/src/multimedia/qml/qmlgraphicsvideo_p.h b/src/multimedia/qml/qmlgraphicsvideo_p.h index d89de8c..4592e31 100644 --- a/src/multimedia/qml/qmlgraphicsvideo_p.h +++ b/src/multimedia/qml/qmlgraphicsvideo_p.h @@ -58,7 +58,7 @@ class QTimerEvent; class QVideoSurfaceFormat; -class QmlGraphicsVideo : public QmlGraphicsItem, public QmlMediaBase +class Q_AUTOTEST_EXPORT QmlGraphicsVideo : public QmlGraphicsItem, public QmlMediaBase { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) @@ -170,7 +170,7 @@ protected: private Q_SLOTS: void _q_nativeSizeChanged(const QSizeF &size); - void _q_error(QMediaPlayer::Error, const QString &); + void _q_error(int, const QString &); private: Q_DISABLE_COPY(QmlGraphicsVideo) diff --git a/src/multimedia/qml/qmlmediabase.cpp b/src/multimedia/qml/qmlmediabase.cpp index 4b42058..17ec8a6 100644 --- a/src/multimedia/qml/qmlmediabase.cpp +++ b/src/multimedia/qml/qmlmediabase.cpp @@ -270,6 +270,8 @@ void QmlMediaBase::setObject(QObject *object) object, SIGNAL(seekableChanged())); QObject::connect(m_playerControl, SIGNAL(playbackRateChanged(qreal)), object, SIGNAL(playbackRateChanged())); + QObject::connect(m_playerControl, SIGNAL(error(int,QString)), + object, SLOT(_q_error(int,QString))); m_animation = new QmlMediaBaseAnimation(this); } else { @@ -293,6 +295,13 @@ QUrl QmlMediaBase::source() const void QmlMediaBase::setSource(const QUrl &url) { + if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) { + m_error = QMediaPlayer::NoError; + m_errorString = QString(); + + emit errorChanged(); + } + m_playerControl->setMedia(QMediaContent(url), 0); } diff --git a/src/multimedia/qml/qmlmediabase_p.h b/src/multimedia/qml/qmlmediabase_p.h index 3b5c398..d6c0a00 100644 --- a/src/multimedia/qml/qmlmediabase_p.h +++ b/src/multimedia/qml/qmlmediabase_p.h @@ -57,7 +57,7 @@ class QMetaDataControl; class QMetaDataControlMetaObject; class QmlMediaBaseAnimation; -class QmlMediaBase +class Q_AUTOTEST_EXPORT QmlMediaBase { public: QmlMediaBase(); @@ -131,6 +131,8 @@ protected: virtual void seekableChanged() = 0; virtual void playbackRateChanged() = 0; + virtual void errorChanged() = 0; + QMediaService *m_mediaService; QMediaPlayerControl *m_playerControl; -- cgit v0.12 From 5fae580d87add7fab16a9bda20bcc5e42df02879 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:13:24 +1000 Subject: Don't emit the metaDataChanged signal twice on a meta-data write. The QMetaDataControl implementation will emeit the changed signal when appropriate, so it's not necessary to emit it in QMetaDataControlMetaObject as well. --- src/multimedia/qml/qmetadatacontrolmetaobject.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp index 6b0164b..c4b2b42 100644 --- a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp +++ b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp @@ -213,8 +213,8 @@ namespace QMetaDataControlMetaObject::QMetaDataControlMetaObject(QMetaDataControl *control, QObject *object) : m_control(control) , m_object(object) - , m_data(0) , m_string(0) + , m_data(0) , m_propertyOffset(0) , m_signalOffset(0) { @@ -343,8 +343,6 @@ int QMetaDataControlMetaObject::metaCall(QMetaObject::Call c, int id, void **a) m_control->setMetaData(qt_metaDataKeys[propId].key, *reinterpret_cast(a[0])); - activate(m_object, m_signalOffset, 0); - return -1; } else { return m_object->qt_metacall(c, id, a); -- cgit v0.12 From 1b9b3fc62da13adc667890a84c61cc873fb941c0 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:16:31 +1000 Subject: Make the paused property of the QML media elements indepent of playing. --- src/multimedia/qml/qmlaudio.cpp | 17 ++++++++- src/multimedia/qml/qmlgraphicsvideo.cpp | 15 ++++++++ src/multimedia/qml/qmlmediabase.cpp | 65 +++++++++++++++++++++------------ src/multimedia/qml/qmlmediabase_p.h | 1 + 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/src/multimedia/qml/qmlaudio.cpp b/src/multimedia/qml/qmlaudio.cpp index adff49b..f56b6c3 100644 --- a/src/multimedia/qml/qmlaudio.cpp +++ b/src/multimedia/qml/qmlaudio.cpp @@ -86,8 +86,13 @@ QmlAudio::~QmlAudio() */ void QmlAudio::play() -{ +{ m_playerControl->play(); + + if (m_paused) { + m_paused = false; + emit pausedChanged(); + } } /*! @@ -99,6 +104,11 @@ void QmlAudio::play() void QmlAudio::pause() { m_playerControl->pause(); + + if (!m_paused && m_state == QMediaPlayer::PausedState) { + m_paused = true; + emit pausedChanged(); + } } /*! @@ -110,6 +120,11 @@ void QmlAudio::pause() void QmlAudio::stop() { m_playerControl->stop(); + + if (m_paused) { + m_paused = false; + emit pausedChanged(); + } } /*! diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp index 784c7b6..2889793 100644 --- a/src/multimedia/qml/qmlgraphicsvideo.cpp +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -338,6 +338,11 @@ void QmlGraphicsVideo::setFillMode(FillMode mode) void QmlGraphicsVideo::play() { m_playerControl->play(); + + if (m_paused) { + m_paused = false; + emit pausedChanged(); + } } /*! @@ -349,6 +354,11 @@ void QmlGraphicsVideo::play() void QmlGraphicsVideo::pause() { m_playerControl->pause(); + + if (!m_paused && m_state == QMediaPlayer::PausedState) { + m_paused = true; + emit pausedChanged(); + } } /*! @@ -360,6 +370,11 @@ void QmlGraphicsVideo::pause() void QmlGraphicsVideo::stop() { m_playerControl->stop(); + + if (m_paused) { + m_paused = false; + emit pausedChanged(); + } } void QmlGraphicsVideo::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) diff --git a/src/multimedia/qml/qmlmediabase.cpp b/src/multimedia/qml/qmlmediabase.cpp index 17ec8a6..17be240 100644 --- a/src/multimedia/qml/qmlmediabase.cpp +++ b/src/multimedia/qml/qmlmediabase.cpp @@ -132,28 +132,33 @@ private: void QmlMediaBase::_q_stateChanged(QMediaPlayer::State state) { if (state != m_state) { - QMediaPlayer::State oldState = state; + QMediaPlayer::State oldState = m_state; m_state = state; - switch (state) { - case QMediaPlayer::PlayingState: - if (oldState == QMediaPlayer::StoppedState) - emit started(); - else if (oldState == QMediaPlayer::PausedState) - emit resumed(); - break; - case QMediaPlayer::PausedState: - emit paused(); - case QMediaPlayer::StoppedState: + if (state == QMediaPlayer::StoppedState) { emit stopped(); - break; - default: - break; + emit playingChanged(); + } else if (oldState == QMediaPlayer::StoppedState) { + emit started(); + emit playingChanged(); + } else if (oldState == QMediaPlayer::PausedState) { + m_paused = false; + + emit resumed(); + emit pausedChanged(); } - emit playingChanged(); - emit pausedChanged(); + if (state == m_state && state == QMediaPlayer::PausedState) { + bool wasPaused = m_paused; + + m_paused = true; + + emit paused(); + + if (!wasPaused) + emit pausedChanged(); + } if (m_state == QMediaPlayer::PlayingState || m_status == QMediaPlayer::BufferingMedia @@ -218,6 +223,7 @@ QmlMediaBase::QmlMediaBase() , m_state(QMediaPlayer::StoppedState) , m_status(QMediaPlayer::NoMedia) , m_error(QMediaPlayer::NoError) + , m_paused(false) { } @@ -312,23 +318,34 @@ bool QmlMediaBase::isPlaying() const void QmlMediaBase::setPlaying(bool playing) { - if (playing && m_state == QMediaPlayer::StoppedState) - m_playerControl->play(); - else if (!playing) + if (playing && m_state == QMediaPlayer::StoppedState) { + if (m_paused) + m_playerControl->pause(); + else + m_playerControl->play(); + } else if (!playing) { m_playerControl->stop(); + } } bool QmlMediaBase::isPaused() const { - return m_state == QMediaPlayer::PausedState; + return m_paused; } void QmlMediaBase::setPaused(bool paused) { - if (paused && m_state == QMediaPlayer::PlayingState) - m_playerControl->pause(); - if (!paused && m_state == QMediaPlayer::PausedState) - m_playerControl->play(); + if (m_paused != paused) { + if (paused && m_state == QMediaPlayer::PlayingState) { + m_playerControl->pause(); + } else if (!paused && m_state == QMediaPlayer::PausedState) { + m_playerControl->play(); + } else { + m_paused = paused; + + emit pausedChanged(); + } + } } int QmlMediaBase::duration() const diff --git a/src/multimedia/qml/qmlmediabase_p.h b/src/multimedia/qml/qmlmediabase_p.h index d6c0a00..873e4c3 100644 --- a/src/multimedia/qml/qmlmediabase_p.h +++ b/src/multimedia/qml/qmlmediabase_p.h @@ -145,6 +145,7 @@ protected: QMediaPlayer::State m_state; QMediaPlayer::MediaStatus m_status; QMediaPlayer::Error m_error; + bool m_paused; QString m_errorString; friend class QmlMediaBaseAnimation; -- cgit v0.12 From 49797723461c812ebe2f53da0583323d0314d02a Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:20:06 +1000 Subject: Remove deprecated enum and member variables from video graphics items. --- src/multimedia/base/qgraphicsvideoitem.h | 7 ------- src/multimedia/qml/qmlgraphicsvideo.cpp | 1 - src/multimedia/qml/qmlgraphicsvideo_p.h | 4 ---- 3 files changed, 12 deletions(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.h b/src/multimedia/base/qgraphicsvideoitem.h index ac215ea..f8cffdc 100644 --- a/src/multimedia/base/qgraphicsvideoitem.h +++ b/src/multimedia/base/qgraphicsvideoitem.h @@ -63,13 +63,6 @@ class Q_MULTIMEDIA_EXPORT QGraphicsVideoItem : public QGraphicsObject Q_PROPERTY(QSizeF size READ size WRITE setSize) Q_PROPERTY(QSizeF nativeSize READ nativeSize NOTIFY nativeSizeChanged) public: - enum FillMode - { - Stretch, - PreserveAspectFit, - PreserveAspectCrop - }; - QGraphicsVideoItem(QGraphicsItem *parent = 0); ~QGraphicsVideoItem(); diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp index 2889793..f6a5eff 100644 --- a/src/multimedia/qml/qmlgraphicsvideo.cpp +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -84,7 +84,6 @@ void QmlGraphicsVideo::_q_error(int errorCode, const QString &errorString) QmlGraphicsVideo::QmlGraphicsVideo(QmlGraphicsItem *parent) : QmlGraphicsItem(parent) , m_graphicsItem(0) - , m_fillMode(QmlGraphicsVideo::PreserveAspectFit) { m_graphicsItem = new QGraphicsVideoItem(this); diff --git a/src/multimedia/qml/qmlgraphicsvideo_p.h b/src/multimedia/qml/qmlgraphicsvideo_p.h index 4592e31..a4f8e32 100644 --- a/src/multimedia/qml/qmlgraphicsvideo_p.h +++ b/src/multimedia/qml/qmlgraphicsvideo_p.h @@ -177,10 +177,6 @@ private: QGraphicsVideoItem *m_graphicsItem; - FillMode m_fillMode; - QRectF m_scaledRect; - bool m_updatePaintDevice; - Q_PRIVATE_SLOT(mediaBase(), void _q_stateChanged(QMediaPlayer::State)) Q_PRIVATE_SLOT(mediaBase(), void _q_mediaStatusChanged(QMediaPlayer::MediaStatus)) Q_PRIVATE_SLOT(mediaBase(), void _q_metaDataChanged()) -- cgit v0.12 From f4646f4810983536cbf0084cd1e5c6dc9a5b2a5d Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:22:59 +1000 Subject: Add an internal function for setting the default media servie provider. This allows auto tests to override the default service provider. --- src/multimedia/base/qmediaserviceprovider.cpp | 23 +++++++++++++++++++++++ src/multimedia/base/qmediaserviceprovider.h | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp index f7c4e1f..3b8dd2c 100644 --- a/src/multimedia/base/qmediaserviceprovider.cpp +++ b/src/multimedia/base/qmediaserviceprovider.cpp @@ -563,12 +563,35 @@ QString QMediaServiceProvider::deviceDescription(const QByteArray &serviceType, return QString(); } + +#ifdef QT_BUILD_INTERNAL + +static QMediaServiceProvider *qt_defaultMediaServiceProvider = 0; + +/*! + Sets a media service \a provider as the default. + + \internal +*/ +void QMediaServiceProvider::setDefaultServiceProvider(QMediaServiceProvider *provider) +{ + qt_defaultMediaServiceProvider = provider; +} + +#endif + /*! Returns a default provider of media services. */ QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider() { +#ifdef QT_BUILD_INTERNAL + return qt_defaultMediaServiceProvider != 0 + ? qt_defaultMediaServiceProvider + : static_cast(pluginProvider()); +#else return pluginProvider(); +#endif } /*! diff --git a/src/multimedia/base/qmediaserviceprovider.h b/src/multimedia/base/qmediaserviceprovider.h index 46f63b5..f108d32 100644 --- a/src/multimedia/base/qmediaserviceprovider.h +++ b/src/multimedia/base/qmediaserviceprovider.h @@ -115,6 +115,10 @@ public: virtual QString deviceDescription(const QByteArray &serviceType, const QByteArray &device); static QMediaServiceProvider* defaultServiceProvider(); + +#ifdef QT_BUILD_INTERNAL + static void setDefaultServiceProvider(QMediaServiceProvider *provider); +#endif }; /*! -- cgit v0.12 From 3d4297d5ea3006a135d07e0634be4a186f06ced4 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:35:00 +1000 Subject: Fix license headers. --- src/multimedia/qml/qmlmediabase_p.h | 4 ++-- tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/multimedia/qml/qmlmediabase_p.h b/src/multimedia/qml/qmlmediabase_p.h index 873e4c3..948a0e8 100644 --- a/src/multimedia/qml/qmlmediabase_p.h +++ b/src/multimedia/qml/qmlmediabase_p.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp index 19433e4..2427d64 100644 --- a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp +++ b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage -- cgit v0.12 From 6fea41c4deb23b6c0f43d05e9b4fd958d06be584 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 5 Feb 2010 11:36:22 +1000 Subject: Add tests for QML media elements. --- tests/auto/qmlaudio/qmlaudio.pro | 6 + tests/auto/qmlaudio/tst_qmlaudio.cpp | 1200 ++++++++++++++++++++ tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro | 6 + .../auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp | 911 +++++++++++++++ 4 files changed, 2123 insertions(+) create mode 100644 tests/auto/qmlaudio/qmlaudio.pro create mode 100644 tests/auto/qmlaudio/tst_qmlaudio.cpp create mode 100644 tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro create mode 100644 tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp diff --git a/tests/auto/qmlaudio/qmlaudio.pro b/tests/auto/qmlaudio/qmlaudio.pro new file mode 100644 index 0000000..4581e80 --- /dev/null +++ b/tests/auto/qmlaudio/qmlaudio.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_qmlaudio.cpp + +QT += multimedia +requires(contains(QT_CONFIG, multimedia)) +requires(contains(QT_CONFIG, declarative)) diff --git a/tests/auto/qmlaudio/tst_qmlaudio.cpp b/tests/auto/qmlaudio/tst_qmlaudio.cpp new file mode 100644 index 0000000..cb205ac --- /dev/null +++ b/tests/auto/qmlaudio/tst_qmlaudio.cpp @@ -0,0 +1,1200 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + + +class tst_QmlAudio : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void nullPlayerControl(); + void nullMetaDataControl(); + void nullService(); + + void source(); + 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(); +}; + +Q_DECLARE_METATYPE(QtMedia::MetaData); +Q_DECLARE_METATYPE(QmlAudio::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 QtTestMetaDataControl : public QMetaDataControl +{ + Q_OBJECT +public: + QtTestMetaDataControl(QObject *parent = 0) + : QMetaDataControl(parent) + { + } + + bool isWritable() const { return true; } + bool isMetaDataAvailable() const { return true; } + + QVariant metaData(QtMedia::MetaData key) const { return m_metaData.value(key); } + void setMetaData(QtMedia::MetaData key, const QVariant &value) { + m_metaData.insert(key, value); emit metaDataChanged(); } + void setMetaData(const QMap &metaData) { + m_metaData = metaData; emit metaDataChanged(); } + + QList availableMetaData() const { return m_metaData.keys(); } + + QVariant extendedMetaData(const QString &) const { return QVariant(); } + void setExtendedMetaData(const QString &, const 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 *control(const char *name) const + { + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return playerControl; + else if (qstrcmp(name, QMetaDataControl_iid) == 0) + return metaDataControl; + else + return 0; + } + + 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_QmlAudio::initTestCase() +{ + qRegisterMetaType(); +} + +void tst_QmlAudio::nullPlayerControl() +{ + QtTestMetaDataControl metaDataControl; + QtTestMediaServiceProvider provider(0, &metaDataControl); + + QmlAudio audio; + + QCOMPARE(audio.source(), QUrl()); + audio.setSource(QUrl("http://example.com")); + QCOMPARE(audio.source(), QUrl()); + + QCOMPARE(audio.isPlaying(), false); + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), 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(), 0); + + QCOMPARE(audio.volume(), qreal(0)); + audio.setVolume(50); + QCOMPARE(audio.volume(), qreal(0)); + + QCOMPARE(audio.isMuted(), false); + audio.setMuted(true); + QCOMPARE(audio.isMuted(), false); + + QCOMPARE(audio.bufferProgress(), qreal(0)); + + QCOMPARE(audio.isSeekable(), false); + + QCOMPARE(audio.playbackRate(), qreal(1.0)); + + QCOMPARE(audio.status(), QmlAudio::NoMedia); + + QCOMPARE(audio.error(), QmlAudio::ServiceMissing); +} + +void tst_QmlAudio::nullMetaDataControl() +{ + QtTestMediaPlayerControl playerControl; + QtTestMediaServiceProvider provider(&playerControl, 0); + + QmlAudio audio; + + QCOMPARE(audio.metaObject()->indexOfProperty("title"), -1); + QCOMPARE(audio.metaObject()->indexOfProperty("genre"), -1); + QCOMPARE(audio.metaObject()->indexOfProperty("description"), -1); +} + +void tst_QmlAudio::nullService() +{ + QtTestMediaServiceProvider provider(0); + + QmlAudio audio; + + QCOMPARE(audio.source(), QUrl()); + audio.setSource(QUrl("http://example.com")); + QCOMPARE(audio.source(), QUrl()); + + QCOMPARE(audio.isPlaying(), false); + audio.setPlaying(true); + QCOMPARE(audio.isPlaying(), 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(), 0); + + QCOMPARE(audio.volume(), qreal(0)); + audio.setVolume(50); + QCOMPARE(audio.volume(), qreal(0)); + + QCOMPARE(audio.isMuted(), false); + audio.setMuted(true); + QCOMPARE(audio.isMuted(), false); + + QCOMPARE(audio.bufferProgress(), qreal(0)); + + QCOMPARE(audio.isSeekable(), false); + + QCOMPARE(audio.playbackRate(), qreal(1.0)); + + QCOMPARE(audio.status(), QmlAudio::NoMedia); + + QCOMPARE(audio.error(), QmlAudio::ServiceMissing); + + QCOMPARE(audio.metaObject()->indexOfProperty("title"), -1); + QCOMPARE(audio.metaObject()->indexOfProperty("genre"), -1); + QCOMPARE(audio.metaObject()->indexOfProperty("description"), -1); +} + +void tst_QmlAudio::source() +{ + const QUrl url1("http://example.com"); + const QUrl url2("file:///local/path"); + const QUrl url3; + + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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_QmlAudio::playing() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + QSignalSpy playingChangedSpy(&audio, SIGNAL(playingChanged())); + QSignalSpy startedSpy(&audio, SIGNAL(started())); + QSignalSpy stoppedSpy(&audio, SIGNAL(stopped())); + + int playingChanged = 0; + int started = 0; + int stopped = 0; + + 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_QmlAudio::paused() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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; + + 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_QmlAudio::duration() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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_QmlAudio::position() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + QSignalSpy spy(&audio, SIGNAL(positionChanged())); + + QCOMPARE(audio.position(), 0); + + // QmlAudio 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(), 3); + + // Check the signal change signal is emitted if the change originates from the media service. + provider.playerControl()->setPosition(0); + QCOMPARE(audio.position(), 0); + QCOMPARE(spy.count(), 4); + + connect(&audio, SIGNAL(positionChanged()), &QTestEventLoop::instance(), SLOT(exitLoop())); + + provider.playerControl()->updateState(QMediaPlayer::PlayingState); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(spy.count() > 4 && spy.count() < 7); // 5 or 6 + + provider.playerControl()->updateState(QMediaPlayer::PausedState); + QTestEventLoop::instance().enterLoop(1); + QVERIFY(spy.count() < 7); +} + +void tst_QmlAudio::volume() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + QSignalSpy spy(&audio, SIGNAL(volumeChanged())); + + QCOMPARE(audio.volume(), qreal(0.5)); + + 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(), 2); + + provider.playerControl()->setVolume(30); + QCOMPARE(audio.volume(), qreal(0.3)); + QCOMPARE(spy.count(), 3); +} + +void tst_QmlAudio::muted() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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_QmlAudio::bufferProgress() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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_QmlAudio::seekable() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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_QmlAudio::playbackRate() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + 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_QmlAudio::status() +{ + QtTestMediaServiceProvider provider; + QmlAudio audio; + + QSignalSpy statusChangedSpy(&audio, SIGNAL(statusChanged())); + QSignalSpy loadedSpy(&audio, SIGNAL(loaded())); + QSignalSpy bufferingSpy(&audio, SIGNAL(buffering())); + QSignalSpy stalledSpy(&audio, SIGNAL(stalled())); + QSignalSpy bufferedSpy(&audio, SIGNAL(buffered())); + QSignalSpy endOfMediaSpy(&audio, SIGNAL(endOfMedia())); + + QCOMPARE(audio.status(), QmlAudio::NoMedia); + + // Set media, start loading. + provider.playerControl()->updateMediaStatus(QMediaPlayer::LoadingMedia); + QCOMPARE(audio.status(), QmlAudio::Loading); + QCOMPARE(statusChangedSpy.count(), 1); + QCOMPARE(loadedSpy.count(), 0); + QCOMPARE(bufferingSpy.count(), 0); + QCOMPARE(stalledSpy.count(), 0); + QCOMPARE(bufferedSpy.count(), 0); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Finish loading. + provider.playerControl()->updateMediaStatus(QMediaPlayer::LoadedMedia); + QCOMPARE(audio.status(), QmlAudio::Loaded); + QCOMPARE(statusChangedSpy.count(), 2); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 0); + QCOMPARE(stalledSpy.count(), 0); + QCOMPARE(bufferedSpy.count(), 0); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Play, start buffering. + provider.playerControl()->updateMediaStatus( + QMediaPlayer::StalledMedia, QMediaPlayer::PlayingState); + QCOMPARE(audio.status(), QmlAudio::Stalled); + QCOMPARE(statusChangedSpy.count(), 3); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 0); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 0); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Enough data buffered to proceed. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(audio.status(), QmlAudio::Buffering); + QCOMPARE(statusChangedSpy.count(), 4); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 1); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 0); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Errant second buffering status changed. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(audio.status(), QmlAudio::Buffering); + QCOMPARE(statusChangedSpy.count(), 4); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 1); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 0); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Buffer full. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia); + QCOMPARE(audio.status(), QmlAudio::Buffered); + QCOMPARE(statusChangedSpy.count(), 5); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 1); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 1); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Buffer getting low. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferingMedia); + QCOMPARE(audio.status(), QmlAudio::Buffering); + QCOMPARE(statusChangedSpy.count(), 6); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 2); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 1); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Buffer full. + provider.playerControl()->updateMediaStatus(QMediaPlayer::BufferedMedia); + QCOMPARE(audio.status(), QmlAudio::Buffered); + QCOMPARE(statusChangedSpy.count(), 7); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 2); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 2); + QCOMPARE(endOfMediaSpy.count(), 0); + + // Finished. + provider.playerControl()->updateMediaStatus( + QMediaPlayer::EndOfMedia, QMediaPlayer::StoppedState); + QCOMPARE(audio.status(), QmlAudio::EndOfMedia); + QCOMPARE(statusChangedSpy.count(), 8); + QCOMPARE(loadedSpy.count(), 1); + QCOMPARE(bufferingSpy.count(), 2); + QCOMPARE(stalledSpy.count(), 1); + QCOMPARE(bufferedSpy.count(), 2); + QCOMPARE(endOfMediaSpy.count(), 1); +} + +void tst_QmlAudio::metaData_data() +{ + QTest::addColumn("propertyName"); + QTest::addColumn("propertyKey"); + QTest::addColumn("value1"); + QTest::addColumn("value2"); + + QTest::newRow("title") + << QByteArray("title") + << QtMedia::Title + << QVariant(QString::fromLatin1("This is a title")) + << QVariant(QString::fromLatin1("This is another title")); + + QTest::newRow("genre") + << QByteArray("genre") + << QtMedia::Genre + << QVariant(QString::fromLatin1("rock")) + << QVariant(QString::fromLatin1("pop")); + + QTest::newRow("trackNumber") + << QByteArray("trackNumber") + << QtMedia::TrackNumber + << QVariant(8) + << QVariant(12); +} + +void tst_QmlAudio::metaData() +{ + QFETCH(QByteArray, propertyName); + QFETCH(QtMedia::MetaData, propertyKey); + QFETCH(QVariant, value1); + QFETCH(QVariant, value2); + + QtTestMediaServiceProvider provider; + QmlAudio audio; + + QSignalSpy spy(&audio, SIGNAL(__metaDataChanged())); + + const int index = audio.metaObject()->indexOfProperty(propertyName.constData()); + QVERIFY(index != -1); + + QMetaProperty property = audio.metaObject()->property(index); + QCOMPARE(property.read(&audio), QVariant()); + + property.write(&audio, value1); + QCOMPARE(property.read(&audio), value1); + QCOMPARE(provider.metaDataControl()->metaData(propertyKey), value1); + QCOMPARE(spy.count(), 1); + + provider.metaDataControl()->setMetaData(propertyKey, value2); + QCOMPARE(property.read(&audio), value2); + QCOMPARE(spy.count(), 2); +} + +void tst_QmlAudio::error() +{ + const QString errorString = QLatin1String("Failed to open device."); + + QtTestMediaServiceProvider provider; + QmlAudio audio; + + QSignalSpy errorSpy(&audio, SIGNAL(error(QmlAudio::Error,QString))); + QSignalSpy errorChangedSpy(&audio, SIGNAL(errorChanged())); + + QCOMPARE(audio.error(), QmlAudio::NoError); + QCOMPARE(audio.errorString(), QString()); + + provider.playerControl()->emitError(QMediaPlayer::ResourceError, errorString); + + QCOMPARE(audio.error(), QmlAudio::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(), QmlAudio::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(), QmlAudio::NoError); + QCOMPARE(audio.errorString(), QString()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 2); +} + + +QTEST_MAIN(tst_QmlAudio) + +#include "tst_qmlaudio.moc" diff --git a/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro b/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro new file mode 100644 index 0000000..994b8fe --- /dev/null +++ b/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_qmlgraphicsvideo.cpp + +QT += multimedia +requires(contains(QT_CONFIG, multimedia)) +requires(contains(QT_CONFIG, declarative)) diff --git a/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp b/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp new file mode 100644 index 0000000..a09a6a2 --- /dev/null +++ b/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp @@ -0,0 +1,911 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +class tst_QmlGraphicsVideo : 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(QtMedia::MetaData); +Q_DECLARE_METATYPE(QmlGraphicsVideo::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 QtTestOutputControl : public QVideoOutputControl +{ +public: + QtTestOutputControl(QObject *parent) : QVideoOutputControl(parent), m_output(NoOutput) {} + + QList availableOutputs() const { return m_outputs; } + void setAvailableOutputs(const QList outputs) { m_outputs = outputs; } + + Output output() const { return m_output; } + virtual void setOutput(Output output) { m_output = output; } + +private: + Output m_output; + QList m_outputs; +}; + +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 QtTestMediaService : public QMediaService +{ + Q_OBJECT +public: + QtTestMediaService( + QtTestMediaPlayerControl *playerControl, + QtTestOutputControl *outputControl, + QtTestRendererControl *rendererControl, + QObject *parent) + : QMediaService(parent) + , playerControl(playerControl) + , outputControl(outputControl) + , rendererControl(rendererControl) + { + } + + QMediaControl *control(const char *name) const + { + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) + return playerControl; + else if (qstrcmp(name, QVideoOutputControl_iid) == 0) + return outputControl; + else if (qstrcmp(name, QVideoRendererControl_iid) == 0) + return rendererControl; + else + return 0; + } + + QtTestMediaPlayerControl *playerControl; + QtTestOutputControl *outputControl; + QtTestRendererControl *rendererControl; +}; + +class QtTestMediaServiceProvider : public QMediaServiceProvider +{ + Q_OBJECT +public: + QtTestMediaServiceProvider() + : service(new QtTestMediaService( + new QtTestMediaPlayerControl(this), + new QtTestOutputControl(this), + new QtTestRendererControl(this), + this)) + { + setDefaultServiceProvider(this); + } + + QtTestMediaServiceProvider(QtTestMediaService *service) + : service(service) + { + setDefaultServiceProvider(this); + } + + QtTestMediaServiceProvider( + QtTestMediaPlayerControl *playerControl, + QtTestOutputControl *outputControl, + QtTestRendererControl *rendererControl) + : service(new QtTestMediaService(playerControl, outputControl, rendererControl, 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_QmlGraphicsVideo::initTestCase() +{ + qRegisterMetaType(); +} + +void tst_QmlGraphicsVideo::nullPlayerControl() +{ + QtTestMediaServiceProvider provider(0, 0, 0); + + QmlGraphicsVideo video; + + QCOMPARE(video.source(), QUrl()); + video.setSource(QUrl("http://example.com")); + QCOMPARE(video.source(), QUrl()); + + QCOMPARE(video.isPlaying(), false); + video.setPlaying(true); + QCOMPARE(video.isPlaying(), 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(), 0); + + QCOMPARE(video.volume(), qreal(0)); + video.setVolume(50); + QCOMPARE(video.volume(), qreal(0)); + + QCOMPARE(video.isMuted(), false); + video.setMuted(true); + QCOMPARE(video.isMuted(), false); + + 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(), QmlGraphicsVideo::NoMedia); + + QCOMPARE(video.error(), QmlGraphicsVideo::ServiceMissing); +} + +void tst_QmlGraphicsVideo::nullService() +{ + QtTestMediaServiceProvider provider(0); + + QmlGraphicsVideo video; + + QCOMPARE(video.source(), QUrl()); + video.setSource(QUrl("http://example.com")); + QCOMPARE(video.source(), QUrl()); + + QCOMPARE(video.isPlaying(), false); + video.setPlaying(true); + QCOMPARE(video.isPlaying(), 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(), 0); + + QCOMPARE(video.volume(), qreal(0)); + video.setVolume(50); + QCOMPARE(video.volume(), qreal(0)); + + QCOMPARE(video.isMuted(), false); + video.setMuted(true); + QCOMPARE(video.isMuted(), false); + + 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(), QmlGraphicsVideo::NoMedia); + + QCOMPARE(video.error(), QmlGraphicsVideo::ServiceMissing); + + QCOMPARE(video.metaObject()->indexOfProperty("title"), -1); + QCOMPARE(video.metaObject()->indexOfProperty("genre"), -1); + QCOMPARE(video.metaObject()->indexOfProperty("description"), -1); +} + +void tst_QmlGraphicsVideo::playing() +{ + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + 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_QmlGraphicsVideo::paused() +{ + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + 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_QmlGraphicsVideo::error() +{ + const QString errorString = QLatin1String("Failed to open device."); + + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + QSignalSpy errorSpy(&video, SIGNAL(error(QmlGraphicsVideo::Error,QString))); + QSignalSpy errorChangedSpy(&video, SIGNAL(errorChanged())); + + QCOMPARE(video.error(), QmlGraphicsVideo::NoError); + QCOMPARE(video.errorString(), QString()); + + provider.playerControl()->emitError(QMediaPlayer::ResourceError, errorString); + + QCOMPARE(video.error(), QmlGraphicsVideo::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(), QmlGraphicsVideo::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(), QmlGraphicsVideo::NoError); + QCOMPARE(video.errorString(), QString()); + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorChangedSpy.count(), 2); +} + + +void tst_QmlGraphicsVideo::hasAudio() +{ + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + 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_QmlGraphicsVideo::hasVideo() +{ + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + 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_QmlGraphicsVideo::fillMode() +{ + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + QList children = video.childItems(); + QCOMPARE(children.count(), 1); + QGraphicsVideoItem *videoItem = qgraphicsitem_cast(children.first()); + QVERIFY(videoItem != 0); + + QCOMPARE(video.fillMode(), QmlGraphicsVideo::PreserveAspectFit); + + video.setFillMode(QmlGraphicsVideo::PreserveAspectCrop); + QCOMPARE(video.fillMode(), QmlGraphicsVideo::PreserveAspectCrop); + QCOMPARE(videoItem->aspectRatioMode(), Qt::KeepAspectRatioByExpanding); + + video.setFillMode(QmlGraphicsVideo::Stretch); + QCOMPARE(video.fillMode(), QmlGraphicsVideo::Stretch); + QCOMPARE(videoItem->aspectRatioMode(), Qt::IgnoreAspectRatio); + + video.setFillMode(QmlGraphicsVideo::PreserveAspectFit); + QCOMPARE(video.fillMode(), QmlGraphicsVideo::PreserveAspectFit); + QCOMPARE(videoItem->aspectRatioMode(), Qt::KeepAspectRatio); +} + +void tst_QmlGraphicsVideo::geometry() +{ + QtTestMediaServiceProvider provider; + QmlGraphicsVideo video; + + QAbstractVideoSurface *surface = provider.rendererControl()->surface(); + QVERIFY(surface != 0); + + QList children = video.childItems(); + QCOMPARE(children.count(), 1); + QGraphicsVideoItem *videoItem = qgraphicsitem_cast(children.first()); + QVERIFY(videoItem != 0); + + QVideoSurfaceFormat format(QSize(640, 480), QVideoFrame::Format_RGB32); + + QVERIFY(surface->start(format)); + + 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_QmlGraphicsVideo) + +#include "tst_qmlgraphicsvideo.moc" -- cgit v0.12 From 5f1c9dd14e1a6f6fc479dc8103a1166c71b61746 Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Fri, 5 Feb 2010 11:55:41 +1000 Subject: Added support for XvImage shm based video frames to gstreamer backend. Gstreamer backend will use XvShmPutImage without copying frames data if possible with overlay video output, and provide XvImage based video frames to renderer video output surface. --- .../mediaservices/gstreamer/qgstvideobuffer.cpp | 12 + .../mediaservices/gstreamer/qgstvideobuffer.h | 5 + .../mediaservices/gstreamer/qgstxvimagebuffer.cpp | 276 ++++++++++++++++++++ .../mediaservices/gstreamer/qgstxvimagebuffer.h | 131 ++++++++++ .../gstreamer/qvideosurfacegstsink.cpp | 280 +++++++++++++++------ .../mediaservices/gstreamer/qvideosurfacegstsink.h | 18 +- .../mediaservices/gstreamer/qx11videosurface.cpp | 81 ++++-- 7 files changed, 709 insertions(+), 94 deletions(-) create mode 100644 src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.cpp create mode 100644 src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.h diff --git a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp index 384bdff..9519db6 100644 --- a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp +++ b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.cpp @@ -51,6 +51,18 @@ QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine) gst_buffer_ref(m_buffer); } +QGstVideoBuffer::QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine, + QGstVideoBuffer::HandleType handleType, + const QVariant &handle) + : QAbstractVideoBuffer(handleType) + , m_buffer(buffer) + , m_bytesPerLine(bytesPerLine) + , m_mode(NotMapped) + , m_handle(handle) +{ + gst_buffer_ref(m_buffer); +} + QGstVideoBuffer::~QGstVideoBuffer() { gst_buffer_unref(m_buffer); diff --git a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h index 36b7c08..5133e2e 100644 --- a/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h +++ b/src/plugins/mediaservices/gstreamer/qgstvideobuffer.h @@ -43,6 +43,7 @@ #define QGSTVIDEOBUFFER_H #include +#include #include @@ -55,6 +56,8 @@ class QGstVideoBuffer : public QAbstractVideoBuffer { public: QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine); + QGstVideoBuffer(GstBuffer *buffer, int bytesPerLine, + HandleType handleType, const QVariant &handle); ~QGstVideoBuffer(); MapMode mapMode() const; @@ -62,10 +65,12 @@ public: uchar *map(MapMode mode, int *numBytes, int *bytesPerLine); void unmap(); + QVariant handle() const { return m_handle; } private: GstBuffer *m_buffer; int m_bytesPerLine; MapMode m_mode; + QVariant m_handle; }; QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.cpp b/src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.cpp new file mode 100644 index 0000000..0e47c98 --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "qgstxvimagebuffer.h" +#include "qvideosurfacegstsink.h" + +GstBufferClass *QGstXvImageBuffer::parent_class = NULL; + +GType QGstXvImageBuffer::get_type(void) +{ + static GType buffer_type = 0; + + if (buffer_type == 0) { + static const GTypeInfo buffer_info = { + sizeof (GstBufferClass), + NULL, + NULL, + QGstXvImageBuffer::class_init, + NULL, + NULL, + sizeof(QGstXvImageBuffer), + 0, + (GInstanceInitFunc)QGstXvImageBuffer::buffer_init, + NULL + }; + buffer_type = g_type_register_static(GST_TYPE_BUFFER, + "QGstXvImageBuffer", &buffer_info, GTypeFlags(0)); + } + return buffer_type; +} + +void QGstXvImageBuffer::class_init(gpointer g_class, gpointer class_data) +{ + Q_UNUSED(class_data); + GST_MINI_OBJECT_CLASS(g_class)->finalize = + (GstMiniObjectFinalizeFunction)buffer_finalize; + parent_class = (GstBufferClass*)g_type_class_peek_parent(g_class); +} + +void QGstXvImageBuffer::buffer_init(QGstXvImageBuffer *xvImage, gpointer g_class) +{ + Q_UNUSED(g_class); + xvImage->pool = 0; + xvImage->shmInfo.shmaddr = ((char *) -1); + xvImage->shmInfo.shmid = -1; + xvImage->markedForDeletion = false; +} + +void QGstXvImageBuffer::buffer_finalize(QGstXvImageBuffer * xvImage) +{ + if (xvImage->pool) { + if (xvImage->markedForDeletion) + xvImage->pool->destroyBuffer(xvImage); + else + xvImage->pool->recycleBuffer(xvImage); + } +} + + +QGstXvImageBufferPool::QGstXvImageBufferPool(QObject *parent) + :QObject(parent) +{ +} + +QGstXvImageBufferPool::~QGstXvImageBufferPool() +{ +} + +bool QGstXvImageBufferPool::isFormatSupported(const QVideoSurfaceFormat &surfaceFormat) +{ + bool ok = true; + surfaceFormat.property("portId").toULongLong(&ok); + if (!ok) + return false; + + int xvFormatId = surfaceFormat.property("xvFormatId").toInt(&ok); + if (!ok || xvFormatId < 0) + return false; + + int dataSize = surfaceFormat.property("dataSize").toInt(&ok); + if (!ok || dataSize<=0) + return false; + + return true; +} + +QGstXvImageBuffer *QGstXvImageBufferPool::takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps) +{ + m_poolMutex.lock(); + + m_caps = caps; + if (format != m_format) { + doClear(); + m_format = format; + } + + + if (m_pool.isEmpty()) { + //qDebug() << "QGstXvImageBufferPool::takeBuffer: no buffer available, allocate the new one"; + if (QThread::currentThread() == thread()) { + m_poolMutex.unlock(); + queuedAlloc(); + m_poolMutex.lock(); + } else { + QMetaObject::invokeMethod(this, "queuedAlloc", Qt::QueuedConnection); + m_allocWaitCondition.wait(&m_poolMutex, 300); + } + } + QGstXvImageBuffer *res = 0; + + if (!m_pool.isEmpty()) { + res = m_pool.takeLast(); + } + + m_poolMutex.unlock(); + + return res; +} + +void QGstXvImageBufferPool::queuedAlloc() +{ + QMutexLocker lock(&m_poolMutex); + + Q_ASSERT(QThread::currentThread() == thread()); + + QGstXvImageBuffer *xvBuffer = (QGstXvImageBuffer *)gst_mini_object_new(QGstXvImageBuffer::get_type()); + + quint64 portId = m_format.property("portId").toULongLong(); + int xvFormatId = m_format.property("xvFormatId").toInt(); + + xvBuffer->xvImage = XvShmCreateImage( + QX11Info::display(), + portId, + xvFormatId, + 0, + m_format.frameWidth(), + m_format.frameHeight(), + &xvBuffer->shmInfo + ); + + if (!xvBuffer->xvImage) { + qDebug() << "QGstXvImageBufferPool: XvShmCreateImage failed"; + m_allocWaitCondition.wakeOne(); + return; + } + + xvBuffer->shmInfo.shmid = shmget(IPC_PRIVATE, xvBuffer->xvImage->data_size, IPC_CREAT | 0777); + xvBuffer->shmInfo.shmaddr = xvBuffer->xvImage->data = (char*)shmat(xvBuffer->shmInfo.shmid, 0, 0); + xvBuffer->shmInfo.readOnly = False; + + if (!XShmAttach(QX11Info::display(), &xvBuffer->shmInfo)) { + qDebug() << "QGstXvImageBufferPool: XShmAttach failed"; + m_allocWaitCondition.wakeOne(); + return; + } + + shmctl (xvBuffer->shmInfo.shmid, IPC_RMID, NULL); + + xvBuffer->pool = this; + GST_MINI_OBJECT_CAST(xvBuffer)->flags = 0; + gst_buffer_set_caps(GST_BUFFER_CAST(xvBuffer), m_caps); + GST_BUFFER_DATA(xvBuffer) = (uchar*)xvBuffer->xvImage->data; + GST_BUFFER_SIZE(xvBuffer) = xvBuffer->xvImage->data_size; + + m_allBuffers.append(xvBuffer); + m_pool.append(xvBuffer); + + m_allocWaitCondition.wakeOne(); +} + + +void QGstXvImageBufferPool::clear() +{ + QMutexLocker lock(&m_poolMutex); + doClear(); +} + +void QGstXvImageBufferPool::doClear() +{ + foreach (QGstXvImageBuffer *xvBuffer, m_allBuffers) { + xvBuffer->markedForDeletion = true; + } + m_allBuffers.clear(); + + foreach (QGstXvImageBuffer *xvBuffer, m_pool) { + gst_buffer_unref(GST_BUFFER(xvBuffer)); + } + m_pool.clear(); + + m_format = QVideoSurfaceFormat(); +} + +void QGstXvImageBufferPool::queuedDestroy() +{ + QMutexLocker lock(&m_destroyMutex); + + foreach(XvShmImage xvImage, m_imagesToDestroy) { + if (xvImage.shmInfo.shmaddr != ((void *) -1)) { + XShmDetach(QX11Info::display(), &xvImage.shmInfo); + XSync(QX11Info::display(), false); + + shmdt(xvImage.shmInfo.shmaddr); + } + + if (xvImage.xvImage) + XFree(xvImage.xvImage); + } + + m_imagesToDestroy.clear(); + + XSync(QX11Info::display(), false); +} + +void QGstXvImageBufferPool::recycleBuffer(QGstXvImageBuffer *xvBuffer) +{ + QMutexLocker lock(&m_poolMutex); + gst_buffer_ref(GST_BUFFER_CAST(xvBuffer)); + m_pool.append(xvBuffer); +} + +void QGstXvImageBufferPool::destroyBuffer(QGstXvImageBuffer *xvBuffer) +{ + XvShmImage imageToDestroy; + imageToDestroy.xvImage = xvBuffer->xvImage; + imageToDestroy.shmInfo = xvBuffer->shmInfo; + + m_destroyMutex.lock(); + m_imagesToDestroy.append(imageToDestroy); + m_destroyMutex.unlock(); + + if (m_imagesToDestroy.size() == 1) + QMetaObject::invokeMethod(this, "queuedDestroy", Qt::QueuedConnection); +} diff --git a/src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.h b/src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.h new file mode 100644 index 0000000..beeb01f --- /dev/null +++ b/src/plugins/mediaservices/gstreamer/qgstxvimagebuffer.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTXVIMAGEBUFFER_H +#define QGSTXVIMAGEBUFFER_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +class QGstXvImageBufferPool; + +struct QGstXvImageBuffer { + GstBuffer buffer; + QGstXvImageBufferPool *pool; + XvImage *xvImage; + XShmSegmentInfo shmInfo; + bool markedForDeletion; + + static GType get_type(void); + static void class_init(gpointer g_class, gpointer class_data); + static void buffer_init(QGstXvImageBuffer *xvimage, gpointer g_class); + static void buffer_finalize(QGstXvImageBuffer * xvimage); + static GstBufferClass *parent_class; +}; + +const QAbstractVideoBuffer::HandleType XvHandleType = QAbstractVideoBuffer::HandleType(4); + +Q_DECLARE_METATYPE(XvImage*) + + +class QGstXvImageBufferPool : public QObject { +Q_OBJECT +friend class QGstXvImageBuffer; +public: + QGstXvImageBufferPool(QObject *parent = 0); + virtual ~QGstXvImageBufferPool(); + + bool isFormatSupported(const QVideoSurfaceFormat &format); + + QGstXvImageBuffer *takeBuffer(const QVideoSurfaceFormat &format, GstCaps *caps); + void clear(); + +private slots: + void queuedAlloc(); + void queuedDestroy(); + + void doClear(); + + void recycleBuffer(QGstXvImageBuffer *); + void destroyBuffer(QGstXvImageBuffer *); + +private: + struct XvShmImage { + XvImage *xvImage; + XShmSegmentInfo shmInfo; + }; + + QMutex m_poolMutex; + QMutex m_allocMutex; + QWaitCondition m_allocWaitCondition; + QMutex m_destroyMutex; + QVideoSurfaceFormat m_format; + GstCaps *m_caps; + QList m_pool; + QList m_allBuffers; + QList m_imagesToDestroy; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index 41e3f77..ca91522 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -39,16 +39,19 @@ ** ****************************************************************************/ -#include "qvideosurfacegstsink.h" - -#include "qgstvideobuffer.h" - #include #include #include #include #include #include +#include + +#include "qvideosurfacegstsink.h" + +#include "qgstvideobuffer.h" +#include "qgstxvimagebuffer.h" + Q_DECLARE_METATYPE(QVideoSurfaceFormat) @@ -62,11 +65,20 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QAbstractVideoSurface *surfac connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(supportedFormatsChanged())); } -QList QVideoSurfaceGstDelegate::supportedPixelFormats() const +QList QVideoSurfaceGstDelegate::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const { QMutexLocker locker(const_cast(&m_mutex)); - return m_supportedPixelFormats; + if (handleType == QAbstractVideoBuffer::NoHandle) + return m_supportedPixelFormats; + else + return m_surface->supportedPixelFormats(handleType); +} + +QVideoSurfaceFormat QVideoSurfaceGstDelegate::surfaceFormat() const +{ + QMutexLocker locker(const_cast(&m_mutex)); + return m_format; } bool QVideoSurfaceGstDelegate::start(const QVideoSurfaceFormat &format, int bytesPerLine) @@ -84,6 +96,8 @@ bool QVideoSurfaceGstDelegate::start(const QVideoSurfaceFormat &format, int byte m_setupCondition.wait(&m_mutex); } + m_format = m_surface->surfaceFormat(); + return m_started; } @@ -103,12 +117,27 @@ void QVideoSurfaceGstDelegate::stop() m_started = false; } +bool QVideoSurfaceGstDelegate::isActive() +{ + QMutexLocker locker(&m_mutex); + return m_surface->isActive(); +} + GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) { QMutexLocker locker(&m_mutex); + QGstVideoBuffer *videoBuffer = 0; + + if (G_TYPE_CHECK_INSTANCE_TYPE(buffer, QGstXvImageBuffer::get_type())) { + QGstXvImageBuffer *xvBuffer = reinterpret_cast(buffer); + QVariant handle = QVariant::fromValue(xvBuffer->xvImage); + videoBuffer = new QGstVideoBuffer(buffer, m_bytesPerLine, XvHandleType, handle); + } else + videoBuffer = new QGstVideoBuffer(buffer, m_bytesPerLine); + m_frame = QVideoFrame( - new QGstVideoBuffer(buffer, m_bytesPerLine), + videoBuffer, m_format.frameSize(), m_format.pixelFormat()); @@ -134,7 +163,6 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) } } - void QVideoSurfaceGstDelegate::queuedStart() { QMutexLocker locker(&m_mutex); @@ -196,8 +224,8 @@ static const YuvFormat qt_yuvColorLookup[] = { { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 }, { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 }, - { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 8 }, - { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','V'), 8 }, + { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 }, + { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','V'), 16 }, { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 8 }, { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 }, { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 } @@ -210,16 +238,18 @@ static int indexOfYuvColor(QVideoFrame::PixelFormat format) for (int i = 0; i < count; ++i) if (qt_yuvColorLookup[i].pixelFormat == format) return i; + return -1; } static int indexOfYuvColor(guint32 fourcc) { - const int count = sizeof(YuvFormat) / sizeof(YuvFormat); + const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat); for (int i = 0; i < count; ++i) if (qt_yuvColorLookup[i].fourcc == fourcc) return i; + return -1; } @@ -313,7 +343,7 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) GstBaseSinkClass *base_sink_class = reinterpret_cast(g_class); base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; - // base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc; // Not implemented. + base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc; base_sink_class->start = QVideoSurfaceGstSink::start; base_sink_class->stop = QVideoSurfaceGstSink::stop; // base_sink_class->unlock = QVideoSurfaceGstSink::unlock; // Not implemented. @@ -352,11 +382,27 @@ void QVideoSurfaceGstSink::instance_init(GTypeInstance *instance, gpointer g_cla Q_UNUSED(g_class); sink->delegate = 0; + sink->pool = new QGstXvImageBufferPool(); + sink->lastRequestedCaps = 0; + sink->lastBufferCaps = 0; + sink->lastSurfaceFormat = new QVideoSurfaceFormat; } void QVideoSurfaceGstSink::finalize(GObject *object) { - Q_UNUSED(object); + VO_SINK(object); + delete sink->pool; + sink->pool = 0; + delete sink->lastSurfaceFormat; + sink->lastSurfaceFormat = 0; + + if (sink->lastBufferCaps) + gst_caps_unref(sink->lastBufferCaps); + sink->lastBufferCaps = 0; + + if (sink->lastRequestedCaps) + gst_caps_unref(sink->lastRequestedCaps); + sink->lastRequestedCaps = 0; } GstStateChangeReturn QVideoSurfaceGstSink::change_state( @@ -421,92 +467,184 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) { VO_SINK(base); + //qDebug() << "set_caps"; + //qDebug() << gst_caps_to_string(caps); + if (!caps) { sink->delegate->stop(); return TRUE; } else { - const GstStructure *structure = gst_caps_get_structure(caps, 0); + int bytesPerLine = 0; + QVideoSurfaceFormat format = formatForCaps(caps, &bytesPerLine); - //qDebug() << gst_caps_to_string(caps); + if (sink->delegate->isActive()) { + QVideoSurfaceFormat surfaceFormst = sink->delegate->surfaceFormat(); - QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid; - int bitsPerPixel = 0; + if (format.pixelFormat() == surfaceFormst.pixelFormat() && + format.frameSize() == surfaceFormst.frameSize()) + return TRUE; + else + sink->delegate->stop(); + } - QSize size; - gst_structure_get_int(structure, "width", &size.rwidth()); - gst_structure_get_int(structure, "height", &size.rheight()); + if (sink->lastRequestedCaps) + gst_caps_unref(sink->lastRequestedCaps); + sink->lastRequestedCaps = 0; - if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) { - guint32 fourcc = 0; - gst_structure_get_fourcc(structure, "format", &fourcc); + //qDebug() << "Staring video surface:"; + //qDebug() << format; + //qDebug() << bytesPerLine; - int index = indexOfYuvColor(fourcc); - if (index != -1) { - pixelFormat = qt_yuvColorLookup[index].pixelFormat; - bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel; - } - } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) { - int depth = 0; - int endianness = 0; - int red = 0; - int green = 0; - int blue = 0; - int alpha = 0; - - gst_structure_get_int(structure, "bpp", &bitsPerPixel); - gst_structure_get_int(structure, "depth", &depth); - gst_structure_get_int(structure, "endianness", &endianness); - gst_structure_get_int(structure, "red_mask", &red); - gst_structure_get_int(structure, "green_mask", &green); - gst_structure_get_int(structure, "blue_mask", &blue); - gst_structure_get_int(structure, "alpha_mask", &alpha); - - int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha); - - if (index != -1) - pixelFormat = qt_rgbColorLookup[index].pixelFormat; - } + if (sink->delegate->start(format, bytesPerLine)) + return TRUE; - if (pixelFormat != QVideoFrame::Format_Invalid) { - QVideoSurfaceFormat format(size, pixelFormat); + } - QPair rate; - gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second); + return FALSE; +} - if (rate.second) - format.setFrameRate(qreal(rate.first)/rate.second); +QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *bytesPerLine) +{ + const GstStructure *structure = gst_caps_get_structure(caps, 0); - gint aspectNum = 0; - gint aspectDenum = 0; - if (gst_structure_get_fraction( - structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { - if (aspectDenum > 0) - format.setPixelAspectRatio(aspectNum, aspectDenum); - } + QVideoFrame::PixelFormat pixelFormat = QVideoFrame::Format_Invalid; + int bitsPerPixel = 0; - int bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3; + QSize size; + gst_structure_get_int(structure, "width", &size.rwidth()); + gst_structure_get_int(structure, "height", &size.rheight()); - if (sink->delegate->start(format, bytesPerLine)) - return TRUE; + if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) { + guint32 fourcc = 0; + gst_structure_get_fourcc(structure, "format", &fourcc); + + int index = indexOfYuvColor(fourcc); + if (index != -1) { + pixelFormat = qt_yuvColorLookup[index].pixelFormat; + bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel; } + } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) { + int depth = 0; + int endianness = 0; + int red = 0; + int green = 0; + int blue = 0; + int alpha = 0; + + gst_structure_get_int(structure, "bpp", &bitsPerPixel); + gst_structure_get_int(structure, "depth", &depth); + gst_structure_get_int(structure, "endianness", &endianness); + gst_structure_get_int(structure, "red_mask", &red); + gst_structure_get_int(structure, "green_mask", &green); + gst_structure_get_int(structure, "blue_mask", &blue); + gst_structure_get_int(structure, "alpha_mask", &alpha); + + int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha); + + if (index != -1) + pixelFormat = qt_rgbColorLookup[index].pixelFormat; + } + + if (pixelFormat != QVideoFrame::Format_Invalid) { + QVideoSurfaceFormat format(size, pixelFormat); + + QPair rate; + gst_structure_get_fraction(structure, "framerate", &rate.first, &rate.second); + + if (rate.second) + format.setFrameRate(qreal(rate.first)/rate.second); + + gint aspectNum = 0; + gint aspectDenum = 0; + if (gst_structure_get_fraction( + structure, "pixel-aspect-ratio", &aspectNum, &aspectDenum)) { + if (aspectDenum > 0) + format.setPixelAspectRatio(aspectNum, aspectDenum); + } + + if (bytesPerLine) + *bytesPerLine = ((size.width() * bitsPerPixel / 8) + 3) & ~3; + return format; } - return FALSE; + return QVideoSurfaceFormat(); } + GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( GstBaseSink *base, guint64 offset, guint size, GstCaps *caps, GstBuffer **buffer) { - // Should implement this when the buffer pool situation is sorted. - Q_UNUSED(base); + VO_SINK(base); + Q_UNUSED(offset); Q_UNUSED(size); - Q_UNUSED(caps); - Q_UNUSED(buffer); - return GST_FLOW_NOT_SUPPORTED; + *buffer = 0; + + if (sink->lastRequestedCaps && gst_caps_is_equal(sink->lastRequestedCaps, caps)) { + //qDebug() << "reusing last caps"; + *buffer = GST_BUFFER(sink->pool->takeBuffer(*sink->lastSurfaceFormat, sink->lastBufferCaps)); + return GST_FLOW_OK; + } + + if (sink->delegate->supportedPixelFormats(XvHandleType).isEmpty()) { + //qDebug() << "sink doesn't support Xv buffers, skip buffers allocation"; + return GST_FLOW_OK; + } + + GstCaps *intersection = gst_caps_intersect(get_caps(GST_BASE_SINK(sink)), caps); + + if (gst_caps_is_empty (intersection)) { + gst_caps_unref(intersection); + return GST_FLOW_NOT_NEGOTIATED; + } + + if (sink->delegate->isActive()) { + //if format was changed, restart the surface + QVideoSurfaceFormat format = formatForCaps(intersection); + QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat(); + + if (format.pixelFormat() != surfaceFormat.pixelFormat() || + format.frameSize() != surfaceFormat.frameSize()) { + //qDebug() << "new format requested, restart video surface"; + sink->delegate->stop(); + } + } + + if (!sink->delegate->isActive()) { + int bytesPerLine = 0; + QVideoSurfaceFormat format = formatForCaps(intersection, &bytesPerLine); + + if (!sink->delegate->start(format, bytesPerLine)) { + qDebug() << "failed to start video surface"; + return GST_FLOW_NOT_NEGOTIATED; + } + } + + QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat(); + + if (!sink->pool->isFormatSupported(surfaceFormat)) { + //qDebug() << "sink doesn't provide Xv buffer details, skip buffers allocation"; + return GST_FLOW_OK; + } + + if (sink->lastRequestedCaps) + gst_caps_unref(sink->lastRequestedCaps); + sink->lastRequestedCaps = caps; + gst_caps_ref(sink->lastRequestedCaps); + + if (sink->lastBufferCaps) + gst_caps_unref(sink->lastBufferCaps); + sink->lastBufferCaps = intersection; + gst_caps_ref(sink->lastBufferCaps); + + *sink->lastSurfaceFormat = surfaceFormat; + + *buffer = GST_BUFFER(sink->pool->takeBuffer(surfaceFormat, intersection)); + + return GST_FLOW_OK; } gboolean QVideoSurfaceGstSink::start(GstBaseSink *base) diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h index f02f9a5..f59a43c 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.h @@ -50,6 +50,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -58,17 +59,27 @@ QT_BEGIN_NAMESPACE class QAbstractVideoSurface; +class QGstXvImageBuffer; +class QGstXvImageBufferPool; + + class QVideoSurfaceGstDelegate : public QObject { Q_OBJECT public: QVideoSurfaceGstDelegate(QAbstractVideoSurface *surface); - QList supportedPixelFormats() const; + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + + QVideoSurfaceFormat surfaceFormat() const; + bool start(const QVideoSurfaceFormat &format, int bytesPerLine); void stop(); + bool isActive(); + GstFlowReturn render(GstBuffer *buffer); private slots: @@ -97,6 +108,7 @@ public: GstVideoSink parent; static QVideoSurfaceGstSink *createSink(QAbstractVideoSurface *surface); + static QVideoSurfaceFormat formatForCaps(GstCaps *caps, int *bytesPerLine = 0); private: static GType get_type(); @@ -125,6 +137,10 @@ private: private: QVideoSurfaceGstDelegate *delegate; + QGstXvImageBufferPool *pool; + GstCaps *lastRequestedCaps; + GstCaps *lastBufferCaps; + QVideoSurfaceFormat *lastSurfaceFormat; }; diff --git a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp index 30b7e55..7a98384 100644 --- a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp +++ b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp @@ -39,11 +39,17 @@ ** ****************************************************************************/ +#include +#include #include #include #include "qx11videosurface.h" +Q_DECLARE_METATYPE(XvImage*); + +static QAbstractVideoBuffer::HandleType XvHandleType = QAbstractVideoBuffer::HandleType(4); + struct XvFormatRgb { QVideoFrame::PixelFormat pixelFormat; @@ -284,7 +290,7 @@ int QX11VideoSurface::redistribute( QList QX11VideoSurface::supportedPixelFormats( QAbstractVideoBuffer::HandleType handleType) const { - return handleType == QAbstractVideoBuffer::NoHandle + return handleType == QAbstractVideoBuffer::NoHandle || handleType == XvHandleType ? m_supportedPixelFormats : QList(); } @@ -319,7 +325,12 @@ bool QX11VideoSurface::start(const QVideoSurfaceFormat &format) m_viewport = format.viewport(); m_image = image; - return QAbstractVideoSurface::start(format); + QVideoSurfaceFormat newFormat = format; + newFormat.setProperty("portId", QVariant(quint64(m_portId))); + newFormat.setProperty("xvFormatId", xvFormatId); + newFormat.setProperty("dataSize", image->data_size); + + return QAbstractVideoSurface::start(newFormat); } } @@ -359,31 +370,57 @@ bool QX11VideoSurface::present(const QVideoFrame &frame) } else { bool presented = false; - if (m_image->data_size > frame.mappedBytes()) { + if (frame.handleType() != XvHandleType && + m_image->data_size > frame.mappedBytes()) { qWarning("Insufficient frame buffer size"); setError(IncorrectFormatError); - } else if (m_image->num_planes > 0 && m_image->pitches[0] != frame.bytesPerLine()) { + } else if (frame.handleType() != XvHandleType && + m_image->num_planes > 0 && + m_image->pitches[0] != frame.bytesPerLine()) { qWarning("Incompatible frame pitches"); setError(IncorrectFormatError); } else { - m_image->data = reinterpret_cast(frameCopy.bits()); - - XvPutImage( - QX11Info::display(), - m_portId, - m_winId, - m_gc, - m_image, - m_viewport.x(), - m_viewport.y(), - m_viewport.width(), - m_viewport.height(), - m_displayRect.x(), - m_displayRect.y(), - m_displayRect.width(), - m_displayRect.height()); - - m_image->data = 0; + if (frame.handleType() != XvHandleType) { + m_image->data = reinterpret_cast(frameCopy.bits()); + + //qDebug() << "copy frame"; + XvPutImage( + QX11Info::display(), + m_portId, + m_winId, + m_gc, + m_image, + m_viewport.x(), + m_viewport.y(), + m_viewport.width(), + m_viewport.height(), + m_displayRect.x(), + m_displayRect.y(), + m_displayRect.width(), + m_displayRect.height()); + + m_image->data = 0; + } else { + XvImage *img = frame.handle().value(); + + //qDebug() << "render directly"; + if (img) + XvShmPutImage( + QX11Info::display(), + m_portId, + m_winId, + m_gc, + img, + m_viewport.x(), + m_viewport.y(), + m_viewport.width(), + m_viewport.height(), + m_displayRect.x(), + m_displayRect.y(), + m_displayRect.width(), + m_displayRect.height(), + false); + } presented = true; } -- cgit v0.12 From 229154b202c26a809e2f502eb9acb99f6307fbb9 Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Fri, 5 Feb 2010 13:15:15 +1000 Subject: Gstreamer and XVideo use YUY2 fourcc, not YUYV. --- src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp | 3 +-- src/plugins/mediaservices/gstreamer/qx11videosurface.cpp | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index ca91522..8c61846 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -225,8 +225,7 @@ static const YuvFormat qt_yuvColorLookup[] = { QVideoFrame::Format_YUV420P, GST_MAKE_FOURCC('I','4','2','0'), 8 }, { QVideoFrame::Format_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 }, { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 }, - { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','V'), 16 }, - { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 8 }, + { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 16 }, { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 }, { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 } }; diff --git a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp index 7a98384..6e282ff 100644 --- a/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp +++ b/src/plugins/mediaservices/gstreamer/qx11videosurface.cpp @@ -130,6 +130,7 @@ static const XvFormatYuv qt_xvYuvLookup[] = { QVideoFrame::Format_YUV420P, 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" }, { QVideoFrame::Format_YV12 , 12, XvPlanar, 3, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" }, { QVideoFrame::Format_UYVY , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "UYVY" }, + { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUY2" }, { QVideoFrame::Format_YUYV , 16, XvPacked, 1, 8, 8, 8, 1, 2, 2, 1, 1, 1, "YUYV" }, { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YUV" }, { QVideoFrame::Format_NV12 , 12, XvPlanar, 2, 8, 8, 8, 1, 2, 2, 1, 2, 2, "YVU" }, -- cgit v0.12 From abf04def344aeb14dbb8539ba73fb5de26237bcc Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Fri, 5 Feb 2010 14:08:30 +1000 Subject: Added Q_WS_MAEMO_5 to mkspec file. --- mkspecs/linux-g++-maemo/qmake.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/linux-g++-maemo/qmake.conf b/mkspecs/linux-g++-maemo/qmake.conf index 38c26a6..e586ed0 100644 --- a/mkspecs/linux-g++-maemo/qmake.conf +++ b/mkspecs/linux-g++-maemo/qmake.conf @@ -32,4 +32,6 @@ DEFINES += QT_GL_NO_SCISSOR_TEST # Work round SGX 1.4 driver bug (text corrupted), modify glyph cache width: DEFINES += QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH=1024 +DEFINES += Q_WS_MAEMO_5 + load(qt_config) -- cgit v0.12 From f14e3b86e6b7b496017ddd462821325bdb40c779 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Fri, 5 Feb 2010 14:12:04 +1000 Subject: qmlsound changed to soundeffect element. --- src/multimedia/qml/qml.pri | 24 +- src/multimedia/qml/qmlsound.cpp | 168 --------- src/multimedia/qml/qmlsound_p.h | 126 ------- src/multimedia/qml/qsoundeffect.cpp | 253 ++++++++++++++ src/multimedia/qml/qsoundeffect_p.h | 116 +++++++ src/multimedia/qml/qsoundeffect_pulse_p.cpp | 502 +++++++++++++++++++++++++++ src/multimedia/qml/qsoundeffect_pulse_p.h | 134 +++++++ src/multimedia/qml/qsoundeffect_qmedia_p.cpp | 163 +++++++++ src/multimedia/qml/qsoundeffect_qmedia_p.h | 105 ++++++ src/multimedia/qml/qsoundeffect_qsound_p.cpp | 223 ++++++++++++ src/multimedia/qml/qsoundeffect_qsound_p.h | 124 +++++++ src/multimedia/qml/wavedecoder_p.cpp | 136 ++++++++ src/multimedia/qml/wavedecoder_p.h | 113 ++++++ 13 files changed, 1889 insertions(+), 298 deletions(-) delete mode 100644 src/multimedia/qml/qmlsound.cpp delete mode 100644 src/multimedia/qml/qmlsound_p.h create mode 100644 src/multimedia/qml/qsoundeffect.cpp create mode 100644 src/multimedia/qml/qsoundeffect_p.h create mode 100644 src/multimedia/qml/qsoundeffect_pulse_p.cpp create mode 100644 src/multimedia/qml/qsoundeffect_pulse_p.h create mode 100644 src/multimedia/qml/qsoundeffect_qmedia_p.cpp create mode 100644 src/multimedia/qml/qsoundeffect_qmedia_p.h create mode 100644 src/multimedia/qml/qsoundeffect_qsound_p.cpp create mode 100644 src/multimedia/qml/qsoundeffect_qsound_p.h create mode 100644 src/multimedia/qml/wavedecoder_p.cpp create mode 100644 src/multimedia/qml/wavedecoder_p.h diff --git a/src/multimedia/qml/qml.pri b/src/multimedia/qml/qml.pri index 6b44e0c..a30c3ad 100644 --- a/src/multimedia/qml/qml.pri +++ b/src/multimedia/qml/qml.pri @@ -2,18 +2,34 @@ contains(QT_CONFIG, declarative) { QT += declarative + system(pkg-config --exists \'libpulse >= 0.9.10\') { + DEFINES += QT_MULTIMEDIA_PULSEAUDIO + HEADERS += qsoundeffect_pulse_p.h + SOURCES += qsoundeffect_pulse_p.cpp + LIBS += -lpulse + } else:x11 { + DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER + HEADERS += qsoundeffect_qmedia_p.h + SOURCES += qsoundeffect_qmedia_p.cpp + } else { + HEADERS += qsoundeffect_qsound_p.h + SOURCES += qsoundeffect_qsound_p.cpp + } + HEADERS += \ - $$PWD/qmlsound_p.h \ $$PWD/qmetadatacontrolmetaobject_p.h \ $$PWD/qmlaudio_p.h \ $$PWD/qmlgraphicsvideo_p.h \ - $$PWD/qmlmediabase_p.h + $$PWD/qmlmediabase_p.h \ + $$PWD/qsoundeffect_p.h \ + $$PWD/wavedecoder_p.h SOURCES += \ - $$PWD/qmlsound.cpp \ $$PWD/qmetadatacontrolmetaobject.cpp \ $$PWD/qmlaudio.cpp \ $$PWD/qmlgraphicsvideo.cpp \ - $$PWD/qmlmediabase.cpp + $$PWD/qmlmediabase.cpp \ + $$PWD/qsoundeffect.cpp \ + $$PWD/wavedecoder_p.cpp } diff --git a/src/multimedia/qml/qmlsound.cpp b/src/multimedia/qml/qmlsound.cpp deleted file mode 100644 index b0693b7..0000000 --- a/src/multimedia/qml/qmlsound.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/**************************************************************************** -** -** 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 QtMultimedia module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qmlsound_p.h" - -#include - - -QT_BEGIN_NAMESPACE - -QML_DEFINE_TYPE(Qt,4,6,Sound,QmlSound) - -QmlSound::QmlSound(QObject *parent) : - QObject(parent), - m_loopCount(1), - m_volume(100), - m_muted(false), - m_runningCount(0), - m_player(0) -{ -} - -QmlSound::~QmlSound() -{ - delete m_player; -} - -QUrl QmlSound::source() const -{ - return m_player != 0 ? m_player->media().canonicalUrl() : QUrl(); -} - -void QmlSound::setSource(const QUrl &url) -{ - if (m_player != 0 && m_player->media().canonicalUrl() == url) - return; - - if (m_player == 0) { - m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency); - m_player->setVolume(m_volume); - m_player->setMuted(m_muted); - - connect(m_player, SIGNAL(volumeChanged()), SIGNAL(volumeChanged())); - connect(m_player, SIGNAL(mutedChanged()), SIGNAL(mutedChanged())); - connect(m_player, SIGNAL(durationChanged()), SIGNAL(durationChanged())); - connect(m_player, SIGNAL(stateChanged()), SLOT(repeat())); - } - - m_player->setMedia(url); - if (url.isEmpty()) - return; - - emit sourceChanged(); -} - -int QmlSound::loopCount() const -{ - return m_loopCount; -} - -void QmlSound::setLoopCount(int loopCount) -{ - if (m_loopCount == loopCount) - return; - - m_loopCount = loopCount; - emit loopCountChanged(); -} - -int QmlSound::volume() const -{ - return m_player != 0 ? m_player->volume() : m_volume; -} - -void QmlSound::setVolume(int volume) -{ - if (m_volume == volume) - return; - - m_volume = volume; - if (m_player != 0) - m_player->setVolume(volume); - else - emit volumeChanged(); -} - -bool QmlSound::isMuted() const -{ - return m_player != 0 ? m_player->isMuted() : m_muted; -} - -void QmlSound::setMuted(bool muted) -{ - if (m_muted == muted) - return; - - m_muted = muted; - if (m_player != 0) - m_player->setMuted(muted); - else - emit mutedChanged(); -} - -int QmlSound::duration() const -{ - return m_player != 0 ? m_player->duration() : 0; -} - -void QmlSound::play() -{ - m_runningCount = 0; - if (m_player != 0) - m_player->play(); -} - -void QmlSound::stop() -{ - if (m_player != 0) - m_player->stop(); -} - -void QmlSound::repeat() -{ - if (m_player->state() == QMediaPlayer::StoppedState) { - if (++m_runningCount < m_loopCount) - m_player->play(); - } -} - -QT_END_NAMESPACE diff --git a/src/multimedia/qml/qmlsound_p.h b/src/multimedia/qml/qmlsound_p.h deleted file mode 100644 index 0a149c0..0000000 --- a/src/multimedia/qml/qmlsound_p.h +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** 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 QtMultimedia module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLSOUND_H -#define QMLSOUND_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - - -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Multimedia) - -class QMediaPlayer; - -class QmlSound : public QObject -{ - Q_OBJECT - Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount NOTIFY loopCountChanged) - Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) - Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) - Q_PROPERTY(int duration READ duration NOTIFY durationChanged) - -public: - explicit QmlSound(QObject *parent = 0); - ~QmlSound(); - - QUrl source() const; - void setSource(const QUrl &url); - - int loopCount() const; - void setLoopCount(int loopCount); - - int volume() const; - void setVolume(int volume); - - bool isMuted() const; - void setMuted(bool muted); - - int duration() const; - -signals: - void sourceChanged(); - void loopCountChanged(); - void volumeChanged(); - void mutedChanged(); - void durationChanged(); - -public slots: - void play(); - void stop(); - -private slots: - void repeat(); - -private: - Q_DISABLE_COPY(QmlSound) - - int m_loopCount; - int m_volume; - bool m_muted; - int m_runningCount; - QMediaPlayer *m_player; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -QML_DECLARE_TYPE(QmlSound) - -#endif // QMLSOUND_H diff --git a/src/multimedia/qml/qsoundeffect.cpp b/src/multimedia/qml/qsoundeffect.cpp new file mode 100644 index 0000000..9692c89 --- /dev/null +++ b/src/multimedia/qml/qsoundeffect.cpp @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmediacontent.h" +#include "qmediaplayer.h" + +#include "qsoundeffect_p.h" + +#if defined(QT_MULTIMEDIA_PULSEAUDIO) +#include "qsoundeffect_pulse_p.h" +#elif(QT_MULTIMEDIA_QMEDIAPLAYER) +#include "qsoundeffect_qmedia_p.h" +#else +#include "qsoundeffect_qsound_p.h" +#endif + +QML_DEFINE_TYPE(Qt,4,6,SoundEffect,QSoundEffect) + +/*! + \qmlclass QSoundEffect + \brief The SoundEffect element provides a way to play sound effects in qml. + + The following example plays a wav file on mouse click. + + \qml + SoundEffect { + id: playSound + source: "test.wav" + } + MouseRegion { + id: playArea + anchors.fill: parent + onPressed: { + playSound.play() + } + } + \endeml + + \sa SoundEffect +*/ + +/*! + \qmlproperty QUrl SoundEffect::source + + This property provides a way to control the sound to play. +*/ + +/*! + \qmlproperty int SoundEffect::loopCount + + This property provides a way to control the number of times to repeat the sound on each play(). +*/ + +/*! + \qmlproperty int SoundEffect::volume + + This property provides a way to control the volume for playback. +*/ + +/*! + \qmlproperty bool SoundEffect::muted + + This property provides a way to control muting. +*/ + +/*! + \qmlproperty int SoundEffect::duration + + This property holds the duration in milliseconds of the current source audio. +*/ + +/*! + \qmlsignal SoundEffect::sourceChanged() + + This handler is called when the source has changed. +*/ + +/*! + \qmlsignal SoundEffect::loopCountChanged() + + This handler is called when the number of loops has changes. +*/ + +/*! + \qmlsignal SoundEffect::volumeChanged() + + This handler is called when the volume has changed. +*/ + +/*! + \qmlsignal SoundEffect::mutedChanged() + + This handler is called when the mute state has changed. +*/ + +/*! + \qmlsignal SoundEffect::durationChanged() + + This handler is called when the duration has changed. +*/ + +QSoundEffect::QSoundEffect(QObject *parent) : + QObject(parent), + m_loopCount(1), + m_volume(100), + m_muted(false), + m_runningCount(0) +{ + d = new QSoundEffectPrivate(this); + connect(d, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged())); + connect(d, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged())); + connect(d, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged())); + connect(d, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(repeat())); +} + +QSoundEffect::~QSoundEffect() +{ + delete d; +} + +QUrl QSoundEffect::source() const +{ + return d != 0 ? d->media().canonicalUrl() : QUrl(); +} + +void QSoundEffect::setSource(const QUrl &url) +{ + if (d != 0 && d->media().canonicalUrl() == url) + return; + + d->setVolume(m_volume); + d->setMuted(m_muted); + d->setMedia(url); + + if (url.isEmpty()) + return; + + emit sourceChanged(); +} + +int QSoundEffect::loopCount() const +{ + return m_loopCount; +} + +void QSoundEffect::setLoopCount(int loopCount) +{ + if (m_loopCount == loopCount) + return; + + m_loopCount = loopCount; + emit loopCountChanged(); +} + +int QSoundEffect::volume() const +{ + return d != 0 ? d->volume() : m_volume; +} + +void QSoundEffect::setVolume(int volume) +{ + if (m_volume == volume) + return; + + m_volume = volume; + if (d != 0) + d->setVolume(volume); + else + emit volumeChanged(); +} + +bool QSoundEffect::isMuted() const +{ + return d != 0 ? d->isMuted() : m_muted; +} + +void QSoundEffect::setMuted(bool muted) +{ + if (m_muted == muted) + return; + + m_muted = muted; + if (d != 0) + d->setMuted(muted); + else + emit mutedChanged(); +} + +int QSoundEffect::duration() const +{ + return d != 0 ? d->duration() : 0; +} + +void QSoundEffect::play() +{ + m_runningCount = 0; + + if (d != 0) + d->play(); +} + +void QSoundEffect::stop() +{ + if (d != 0) + d->stop(); +} + +void QSoundEffect::repeat() +{ + if (d->state() == QMediaPlayer::StoppedState) { + if (++m_runningCount < m_loopCount) + d->play(); + } +} + diff --git a/src/multimedia/qml/qsoundeffect_p.h b/src/multimedia/qml/qsoundeffect_p.h new file mode 100644 index 0000000..de7070e --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_p.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSOUNDEFFECT_H +#define QSOUNDEFFECT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include +#include +#include + +class QSoundEffectPrivate; +class QSoundEffect : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount NOTIFY loopCountChanged) + Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) + Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged) + Q_PROPERTY(int duration READ duration NOTIFY durationChanged) + +public: + explicit QSoundEffect(QObject *parent = 0); + ~QSoundEffect(); + + QUrl source() const; + void setSource(const QUrl &url); + + int loopCount() const; + void setLoopCount(int loopCount); + + int volume() const; + void setVolume(int volume); + + bool isMuted() const; + void setMuted(bool muted); + + int duration() const; + +signals: + void sourceChanged(); + void loopCountChanged(); + void volumeChanged(); + void mutedChanged(); + void durationChanged(); + +public slots: + void play(); + void stop(); + +private slots: + void repeat(); + +private: + Q_DISABLE_COPY(QSoundEffect) + + int m_loopCount; + int m_volume; + bool m_muted; + int m_runningCount; + + QSoundEffectPrivate* d; +}; + +QML_DECLARE_TYPE(QSoundEffect) + +#endif // QSOUNDEFFECT_H diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.cpp b/src/multimedia/qml/qsoundeffect_pulse_p.cpp new file mode 100644 index 0000000..fa2119d --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_pulse_p.cpp @@ -0,0 +1,502 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +#include "qmediacontent.h" +#include "qmediaplayer.h" +#include "qsoundeffect_p.h" + +#include "wavedecoder_p.h" + +#include "qsoundeffect_pulse_p.h" + +#if(Q_WS_MAEMO_5) +#include +#endif + +// Less than ideal +#define PA_SCACHE_ENTRY_SIZE_MAX (1024*1024*16) + +namespace +{ +inline pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format) +{ + pa_sample_spec spec; + + spec.rate = format.frequency(); + spec.channels = format.channels(); + + if (format.sampleSize() == 8) + spec.format = PA_SAMPLE_U8; + else if (format.sampleSize() == 16) { + switch (format.byteOrder()) { + case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S16BE; break; + case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S16LE; break; + } + } + else if (format.sampleSize() == 32) { + switch (format.byteOrder()) { + case QAudioFormat::BigEndian: spec.format = PA_SAMPLE_S32BE; break; + case QAudioFormat::LittleEndian: spec.format = PA_SAMPLE_S32LE; break; + } + } + + return spec; +} + +class PulseDaemon +{ +public: + PulseDaemon():m_prepared(false) + { + prepare(); + } + + ~PulseDaemon() + { + if (m_prepared) + release(); + } + + inline void lock() + { + pa_threaded_mainloop_lock(m_mainLoop); + } + + inline void unlock() + { + pa_threaded_mainloop_unlock(m_mainLoop); + } + + inline pa_context *context() const + { + return m_context; + } + + int volume() + { + return m_volume; + } + +private: + void prepare() + { + m_volume = 100; + + m_mainLoop = pa_threaded_mainloop_new(); + if (m_mainLoop == 0) { + qWarning("PulseAudioService: unable to create pulseaudio mainloop"); + return; + } + + if (pa_threaded_mainloop_start(m_mainLoop) != 0) { + qWarning("PulseAudioService: unable to start pulseaudio mainloop"); + pa_threaded_mainloop_free(m_mainLoop); + return; + } + + m_mainLoopApi = pa_threaded_mainloop_get_api(m_mainLoop); + + lock(); + m_context = pa_context_new(m_mainLoopApi, QString("QtPulseAudio:%1").arg(::getpid()).toAscii().constData()); + +#if(Q_WS_MAEMO_5) + pa_context_set_state_callback(m_context, context_state_callback, this); +#endif + if (m_context == 0) { + qWarning("PulseAudioService: Unable to create new pulseaudio context"); + pa_threaded_mainloop_free(m_mainLoop); + return; + } + + if (pa_context_connect(m_context, NULL, (pa_context_flags_t)0, NULL) < 0) { + qWarning("PulseAudioService: pa_context_connect() failed"); + pa_context_unref(m_context); + pa_threaded_mainloop_free(m_mainLoop); + return; + } + unlock(); + + m_prepared = true; + } + + void release() + { + if (!m_prepared) return; + pa_threaded_mainloop_stop(m_mainLoop); + pa_threaded_mainloop_free(m_mainLoop); + m_prepared = false; + } + +#if(QWS_MAEMO_5) + static void context_state_callback(pa_context *c, void *userdata) + { + PulseDaemon *self = reinterpret_cast(userdata); + switch (pa_context_get_state(c)) { + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + case PA_CONTEXT_READY: + pa_ext_stream_restore_set_subscribe_cb(c, &stream_restore_monitor_callback, self); + pa_ext_stream_restore_subscribe(c, 1, NULL, self); + break; + default: + break; + } + } + static void stream_restore_monitor_callback(pa_context *c, void *userdata) + { + PulseDaemon *self = reinterpret_cast(userdata); + pa_ext_stream_restore2_read(c, &stream_restore_info_callback, self); + } + static void stream_restore_info_callback(pa_context *c, const pa_ext_stream_restore2_info *info, + int eol, void *userdata) + { + Q_UNUSED(c) + + PulseDaemon *self = reinterpret_cast(userdata); + + if (!eol) { + if (QString(info->name).startsWith(QLatin1String("sink-input-by-media-role:x-maemo"))) { + const unsigned str_length = 256; + char str[str_length]; + pa_cvolume_snprint(str, str_length, &info->volume); + self->m_volume = QString(str).replace(" ","").replace("%","").mid(2).toInt(); + } + } + } +#endif + + int m_volume; + bool m_prepared; + pa_context *m_context; + pa_threaded_mainloop *m_mainLoop; + pa_mainloop_api *m_mainLoopApi; +}; +} + +Q_GLOBAL_STATIC(PulseDaemon, daemon) + + +QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): + QObject(parent), + m_muted(false), + m_playQueued(false), + m_volume(100), + m_duration(0), + m_dataUploaded(0), + m_state(QMediaPlayer::StoppedState), + m_status(QMediaPlayer::NoMedia), + m_reply(0), + m_stream(0), + m_networkAccessManager(0) +{ +} + +QSoundEffectPrivate::~QSoundEffectPrivate() +{ + delete m_reply; + unloadSample(); +} + +qint64 QSoundEffectPrivate::duration() const +{ + return m_duration; +} + +int QSoundEffectPrivate::volume() const +{ + return m_volume; +} + +bool QSoundEffectPrivate::isMuted() const +{ + return m_muted; +} + +QMediaContent QSoundEffectPrivate::media() const +{ + return m_media; +} + +QMediaPlayer::State QSoundEffectPrivate::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus QSoundEffectPrivate::mediaStatus() const +{ + return m_status; +} + +void QSoundEffectPrivate::play() +{ + if (m_status == QMediaPlayer::LoadingMedia) { + m_playQueued = true; + return; + } + + if (m_status != QMediaPlayer::BufferedMedia || + m_state == QMediaPlayer::PlayingState) + return; + + pa_volume_t m_vol = PA_VOLUME_NORM; + + daemon()->lock(); +#if(Q_WS_MAEMO_5) + m_vol = PA_VOLUME_NORM/100*((daemon()->volume()+m_volume)/2); +#endif + pa_operation_unref( + pa_context_play_sample(daemon()->context(), + m_name.constData(), + 0, + m_vol, + play_callback, + this) + ); + daemon()->unlock(); + + m_playbackTime.start(); + + emit stateChanged(m_state = QMediaPlayer::PlayingState); +} + +void QSoundEffectPrivate::stop() +{ + emit stateChanged(m_state = QMediaPlayer::StoppedState); +} + +void QSoundEffectPrivate::setVolume(int volume) +{ + m_volume = volume; +} + +void QSoundEffectPrivate::setMuted(bool muted) +{ + m_muted = muted; +} + +void QSoundEffectPrivate::setMedia(const QMediaContent &media) +{ + if (media.isNull()) { + m_media = QMediaContent(); + unloadSample(); + return; + } + if (m_media == media) + return; + m_media = media; + + if (m_networkAccessManager == 0) + m_networkAccessManager = new QNetworkAccessManager(this); + + m_stream = m_networkAccessManager->get(QNetworkRequest(m_media.canonicalUrl())); + + unloadSample(); + loadSample(); + + emit mediaChanged(m_media); +} + +void QSoundEffectPrivate::decoderReady() +{ + if (m_waveDecoder->size() >= PA_SCACHE_ENTRY_SIZE_MAX) { + m_status = QMediaPlayer::InvalidMedia; + emit mediaStatusChanged(m_status); + qWarning("QtPulseAudio: attempting to load to large a sample"); + return; + } + + if (m_name.isNull()) + m_name = QString("QtPulseSample-%1-%2").arg(::getpid()).arg(int(this)).toUtf8(); + + pa_sample_spec spec = audioFormatToSampleSpec(m_waveDecoder->audioFormat()); + + daemon()->lock(); + pa_stream *stream = pa_stream_new(daemon()->context(), m_name.constData(), &spec, 0); + pa_stream_set_state_callback(stream, stream_state_callback, this); + pa_stream_set_write_callback(stream, stream_write_callback, this); + pa_stream_connect_upload(stream, (size_t)m_waveDecoder->size()); + daemon()->unlock(); +} + +void QSoundEffectPrivate::decoderError() +{ + emit mediaStatusChanged(m_status = QMediaPlayer::InvalidMedia); +} + +void QSoundEffectPrivate::checkPlayTime() +{ + int elapsed = m_playbackTime.elapsed(); + + if (elapsed >= m_duration) { + m_state = QMediaPlayer::StoppedState; + emit stateChanged(m_state); + } + else + startTimer(m_duration - elapsed); +} + +void QSoundEffectPrivate::loadSample() +{ + m_waveDecoder = new WaveDecoder(m_stream); + connect(m_waveDecoder, SIGNAL(formatKnown()), SLOT(decoderReady())); + connect(m_waveDecoder, SIGNAL(invalidFormat()), SLOT(decoderError())); + + m_status = QMediaPlayer::LoadingMedia; + emit mediaStatusChanged(m_status); +} + +void QSoundEffectPrivate::unloadSample() +{ + if (m_status != QMediaPlayer::BufferedMedia) + return; + + m_status = QMediaPlayer::NoMedia; + + daemon()->lock(); + pa_context_remove_sample(daemon()->context(), m_name.constData(), NULL, NULL); + daemon()->unlock(); + + m_duration = 0; + m_dataUploaded = 0; +} + +void QSoundEffectPrivate::timerEvent(QTimerEvent *event) +{ + if (m_state == QMediaPlayer::PlayingState) { + m_state = QMediaPlayer::StoppedState; + emit stateChanged(m_state); + } + + killTimer(event->timerId()); +} + +void QSoundEffectPrivate::stream_write_callback(pa_stream *s, size_t length, void *userdata) +{ + Q_UNUSED(length); + + QSoundEffectPrivate *self = reinterpret_cast(userdata); + + size_t bufferSize = qMin(pa_stream_writable_size(s), + size_t(self->m_waveDecoder->bytesAvailable())); + char buffer[bufferSize]; + + size_t len = 0; + while (len < length) { + qint64 read = self->m_waveDecoder->read(buffer, qMin(bufferSize, length -len)); + if (read > 0) { + if (pa_stream_write(s, buffer, size_t(read), 0, 0, PA_SEEK_RELATIVE) == 0) + len += size_t(read); + else + break; + } + } + self->m_dataUploaded += len; + + if (self->m_waveDecoder->size() == self->m_dataUploaded) { + pa_stream_finish_upload(s); + + self->m_duration = self->m_waveDecoder->duration(); + emit self->durationChanged(self->m_duration); + + self->m_status = QMediaPlayer::BufferedMedia; + emit self->mediaStatusChanged(self->m_status); + + self->m_waveDecoder->deleteLater(); + if (!self->m_media.isNull()) + self->m_stream->deleteLater(); + + if (self->m_playQueued) { + self->m_playQueued = false; + QMetaObject::invokeMethod(self, "play"); + } + } +} + +void QSoundEffectPrivate::stream_state_callback(pa_stream *s, void *userdata) +{ + QSoundEffectPrivate *self = reinterpret_cast(userdata); + + switch (pa_stream_get_state(s)) { + case PA_STREAM_CREATING: + case PA_STREAM_READY: + case PA_STREAM_TERMINATED: + break; + + case PA_STREAM_FAILED: + default: + self->m_status = QMediaPlayer::InvalidMedia; + emit self->mediaStatusChanged(self->m_status); + break; + } +} + +void QSoundEffectPrivate::play_callback(pa_context *c, int success, void *userdata) +{ + Q_UNUSED(c); + + QSoundEffectPrivate *self = reinterpret_cast(userdata); + + if (success == 1) + QMetaObject::invokeMethod(self, "checkPlayTime", Qt::QueuedConnection); + else { + self->m_state = QMediaPlayer::StoppedState; + emit self->stateChanged(self->m_state); + } +} + diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.h b/src/multimedia/qml/qsoundeffect_pulse_p.h new file mode 100644 index 0000000..05728d0 --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_pulse_p.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSOUNDEFFECT_PULSE_H +#define QSOUNDEFFECT_PULSE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include + +#include + +#include + +#include "qsoundeffect_p.h" + +#include + +QTM_USE_NAMESPACE + +class QNetworkReply; +class QNetworkAccessManager; +class WaveDecoder; + +class QSoundEffectPrivate : public QObject +{ + Q_OBJECT +public: + explicit QSoundEffectPrivate(QObject* parent); + ~QSoundEffectPrivate(); + + qint64 duration() const; + int volume() const; + bool isMuted() const; + QMediaContent media() const; + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + +public Q_SLOTS: + void play(); + void stop(); + void setVolume(int volume); + void setMuted(bool muted); + void setMedia(const QMediaContent &media); + +Q_SIGNALS: + void mediaChanged(const QMediaContent &media); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void stateChanged(QMediaPlayer::State newState); + void durationChanged(qint64 duration); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void error(QMediaPlayer::Error error); + +private slots: + void decoderReady(); + void decoderError(); + void checkPlayTime(); + +private: + void loadSample(); + void unloadSample(); + + void timerEvent(QTimerEvent *event); + + static void stream_write_callback(pa_stream *s, size_t length, void *userdata); + static void stream_state_callback(pa_stream *s, void *userdata); + static void play_callback(pa_context *c, int success, void *userdata); + + bool m_muted; + bool m_playQueued; + int m_volume; + int m_duration; + int m_dataUploaded; + QTime m_playbackTime; + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_status; + QByteArray m_name; + QMediaContent m_media; + QNetworkReply *m_reply; + WaveDecoder *m_waveDecoder; + QIODevice *m_stream; + QNetworkAccessManager *m_networkAccessManager; +}; + +#endif // QSOUNDEFFECT_PULSE_H diff --git a/src/multimedia/qml/qsoundeffect_qmedia_p.cpp b/src/multimedia/qml/qsoundeffect_qmedia_p.cpp new file mode 100644 index 0000000..26354a5 --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_qmedia_p.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#include "qmediacontent.h" +#include "qmediaplayer.h" + +#include "qsoundeffect_p.h" +#include "qsoundeffect_qmedia_p.h" + + +QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): + QObject(parent), + m_muted(false), + m_volume(100), + m_player(0) +{ +} + +QSoundEffectPrivate::~QSoundEffectPrivate() +{ + if (m_player) delete m_player; +} + +qint64 QSoundEffectPrivate::duration() const +{ + if (m_player) return m_player->duration(); + + return 0; +} + +int QSoundEffectPrivate::volume() const +{ + if (m_player) return m_player->volume(); + + return m_volume; +} + +bool QSoundEffectPrivate::isMuted() const +{ + if (m_player) return m_player->isMuted(); + + return m_muted; +} + +QMediaContent QSoundEffectPrivate::media() const +{ + if (m_player) return m_player->media(); + + return QMediaContent(); +} + +QMediaPlayer::State QSoundEffectPrivate::state() const +{ + if (m_player) return m_player->state(); + + return QMediaPlayer::StoppedState; +} + +QMediaPlayer::MediaStatus QSoundEffectPrivate::mediaStatus() const +{ + if (m_player) return m_player->mediaStatus(); + + return QMediaPlayer::UnknownMediaStatus; +} + +void QSoundEffectPrivate::play() +{ + if (m_player && !m_player->isMuted()) + m_player->play(); +} + +void QSoundEffectPrivate::stop() +{ + if (m_player) + m_player->stop(); +} + +void QSoundEffectPrivate::setVolume(int volume) +{ + m_volume = volume; + + if (m_player) + m_player->setVolume(volume); +} + +void QSoundEffectPrivate::setMuted(bool muted) +{ + m_muted = muted; + + if (m_player) + m_player->setMuted(muted); +} + +void QSoundEffectPrivate::setMedia(const QMediaContent &media) +{ + if (media.isNull()) + return; + + if (m_player == 0) { + m_player = new QMediaPlayer(this, QMediaPlayer::LowLatency); + m_player->setVolume(m_volume); + m_player->setMuted(m_muted); + + connect(m_player, SIGNAL(volumeChanged(int)), SIGNAL(volumeChanged(int))); + connect(m_player, SIGNAL(mutedChanged(bool)), SIGNAL(mutedChanged(bool))); + connect(m_player, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64))); + connect(m_player, SIGNAL(stateChanged(QMediaPlayer::State)), SIGNAL(stateChanged(QMediaPlayer::State))); + } + + m_player->setMedia(media.canonicalUrl()); +} + diff --git a/src/multimedia/qml/qsoundeffect_qmedia_p.h b/src/multimedia/qml/qsoundeffect_qmedia_p.h new file mode 100644 index 0000000..8b3165a --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_qmedia_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSOUNDEFFECT_QMEDIA_H +#define QSOUNDEFFECT_QMEDIA_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include +#include + +#include +#include + +#include "qsoundeffect_p.h" + +QTM_USE_NAMESPACE + +class WaveDecoder; + +class QSoundEffectPrivate : public QObject +{ + Q_OBJECT +public: + explicit QSoundEffectPrivate(QObject* parent); + ~QSoundEffectPrivate(); + + qint64 duration() const; + int volume() const; + bool isMuted() const; + QMediaContent media() const; + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + +public Q_SLOTS: + void play(); + void stop(); + void setVolume(int volume); + void setMuted(bool muted); + void setMedia(const QMediaContent &media); + +Q_SIGNALS: + void mediaChanged(const QMediaContent &media); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void stateChanged(QMediaPlayer::State newState); + void durationChanged(qint64 duration); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void error(QMediaPlayer::Error error); + +private: + bool m_muted; + int m_volume; + QMediaPlayer *m_player; +}; + +#endif // QSOUNDEFFECT_QMEDIA_H diff --git a/src/multimedia/qml/qsoundeffect_qsound_p.cpp b/src/multimedia/qml/qsoundeffect_qsound_p.cpp new file mode 100644 index 0000000..fd40a05 --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_qsound_p.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include + +#include "qmediacontent.h" +#include "qmediaplayer.h" +#include "qsoundeffect_p.h" + +#include "wavedecoder_p.h" + +#include "qsoundeffect_qsound_p.h" + + +QSoundEffectPrivate::QSoundEffectPrivate(QObject* parent): + QObject(parent), + m_queued(false), + m_muted(false), + m_state(QMediaPlayer::StoppedState), + m_status(QMediaPlayer::NoMedia), + m_file(0), + m_sound(0) +{ + m_timer = new QTimer(this); + connect(m_timer,SIGNAL(timeout()),SLOT(checkPlayTime())); + m_media = QMediaContent(); +} + +QSoundEffectPrivate::~QSoundEffectPrivate() +{ + if (m_sound) delete m_sound; + if (m_waveDecoder) delete m_waveDecoder; + m_file->close(); +} + +qint64 QSoundEffectPrivate::duration() const +{ + if (m_waveDecoder) + return m_waveDecoder->size(); + + return 0; +} + +int QSoundEffectPrivate::volume() const +{ + return 100; +} + +bool QSoundEffectPrivate::isMuted() const +{ + return m_muted; +} + +QMediaContent QSoundEffectPrivate::media() const +{ + return m_media; +} + +QMediaPlayer::State QSoundEffectPrivate::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus QSoundEffectPrivate::mediaStatus() const +{ + return m_status; +} + +void QSoundEffectPrivate::play() +{ + if (m_sound && !m_muted) { + m_queued = false; + m_timer->start(20); + m_playbackTime.start(); + m_sound->play(); + emit stateChanged(m_state = QMediaPlayer::PlayingState); + } else if (m_status == QMediaPlayer::LoadingMedia) + m_queued = true; +} + +void QSoundEffectPrivate::stop() +{ + m_timer->stop(); + + if (m_sound) { + m_sound->stop(); + emit stateChanged(m_state = QMediaPlayer::StoppedState); + } +} + +void QSoundEffectPrivate::setVolume(int volume) +{ + Q_UNUSED(volume) +} + +void QSoundEffectPrivate::setMuted(bool muted) +{ + m_muted = muted; +} + +void QSoundEffectPrivate::setMedia(const QMediaContent &media) +{ + m_queued = false; + + if (media.isNull() || media.canonicalUrl().scheme() != "file") { + m_media = QMediaContent(); + return; + } + if (m_media == media) + return; + + m_media = media; + m_file = new QFile(m_media.canonicalUrl().toLocalFile()); + m_file->open(QIODevice::ReadOnly|QIODevice::Unbuffered); + + unloadSample(); + loadSample(); + + emit mediaChanged(m_media); +} + +void QSoundEffectPrivate::decoderReady() +{ + m_file->close(); + m_sound = new QSound(m_media.canonicalUrl().toLocalFile()); + emit mediaStatusChanged(m_status = QMediaPlayer::LoadedMedia); + + if (m_queued) + play(); +} + +void QSoundEffectPrivate::decoderError() +{ + m_file->close(); + emit mediaStatusChanged(m_status = QMediaPlayer::InvalidMedia); +} + +void QSoundEffectPrivate::checkPlayTime() +{ + if (m_sound->isFinished()) { + m_timer->stop(); + m_state = QMediaPlayer::StoppedState; + emit stateChanged(m_state); + } +} + +void QSoundEffectPrivate::loadSample() +{ + m_waveDecoder = new WaveDecoder(m_file); + connect(m_waveDecoder, SIGNAL(formatKnown()), SLOT(decoderReady())); + connect(m_waveDecoder, SIGNAL(invalidFormat()), SLOT(decoderError())); + + m_status = QMediaPlayer::LoadingMedia; + emit mediaStatusChanged(m_status); +} + +void QSoundEffectPrivate::unloadSample() +{ + if (m_sound == 0) + return; + + m_status = QMediaPlayer::NoMedia; + + if (m_sound) + delete m_sound; + + m_sound = 0; +} + diff --git a/src/multimedia/qml/qsoundeffect_qsound_p.h b/src/multimedia/qml/qsoundeffect_qsound_p.h new file mode 100644 index 0000000..ac47e8f --- /dev/null +++ b/src/multimedia/qml/qsoundeffect_qsound_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSOUNDEFFECT_QSOUND_H +#define QSOUNDEFFECT_QSOUND_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include +#include + +#include + +#include "qsoundeffect_p.h" + + +QTM_USE_NAMESPACE + +class QTimer; +class QSound; +class QFile; +class WaveDecoder; + +class QSoundEffectPrivate : public QObject +{ + Q_OBJECT +public: + explicit QSoundEffectPrivate(QObject* parent); + ~QSoundEffectPrivate(); + + qint64 duration() const; + int volume() const; + bool isMuted() const; + QMediaContent media() const; + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + +public Q_SLOTS: + void play(); + void stop(); + void setVolume(int volume); + void setMuted(bool muted); + void setMedia(const QMediaContent &media); + +Q_SIGNALS: + void mediaChanged(const QMediaContent &media); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + void stateChanged(QMediaPlayer::State newState); + void durationChanged(qint64 duration); + void volumeChanged(int volume); + void mutedChanged(bool muted); + void error(QMediaPlayer::Error error); + +private slots: + void decoderReady(); + void decoderError(); + void checkPlayTime(); + +private: + void loadSample(); + void unloadSample(); + + bool m_queued; + bool m_muted; + QTime m_playbackTime; + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_status; + QFile *m_file; + QByteArray m_name; + QMediaContent m_media; + WaveDecoder *m_waveDecoder; + QSound *m_sound; + QTimer *m_timer; +}; + +#endif // QSOUNDEFFECT_QSOUND_H diff --git a/src/multimedia/qml/wavedecoder_p.cpp b/src/multimedia/qml/wavedecoder_p.cpp new file mode 100644 index 0000000..f45f25c --- /dev/null +++ b/src/multimedia/qml/wavedecoder_p.cpp @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "wavedecoder_p.h" + +#include +#include + +WaveDecoder::WaveDecoder(QIODevice *s, QObject *parent): + QIODevice(parent), + haveFormat(false), + dataSize(0), + remaining(0), + source(s) +{ + open(QIODevice::ReadOnly | QIODevice::Unbuffered); + + if (source->bytesAvailable() >= sizeof(CombinedHeader)) + QTimer::singleShot(0, this, SLOT(handleData())); + else + connect(source, SIGNAL(readyRead()), SLOT(handleData())); +} + +WaveDecoder::~WaveDecoder() +{ +} + +QAudioFormat WaveDecoder::audioFormat() const +{ + return format; +} + +int WaveDecoder::duration() const +{ + return size() * 1000 / (format.sampleSize() / 8) / format.channels() / format.frequency(); +} + +qint64 WaveDecoder::size() const +{ + return haveFormat ? dataSize : 0; +} + +bool WaveDecoder::isSequential() const +{ + return source->isSequential(); +} + +qint64 WaveDecoder::bytesAvailable() const +{ + return haveFormat ? source->bytesAvailable() : 0; +} + +qint64 WaveDecoder::readData(char *data, qint64 maxlen) +{ + return haveFormat ? source->read(data, maxlen) : 0; +} + +qint64 WaveDecoder::writeData(const char *data, qint64 len) +{ + Q_UNUSED(data); + Q_UNUSED(len); + + return -1; +} + +void WaveDecoder::handleData() +{ + if (source->bytesAvailable() < sizeof(CombinedHeader)) + return; + + source->disconnect(SIGNAL(readyRead()), this, SLOT(handleData())); + source->read((char*)&header, sizeof(CombinedHeader)); + + if (qstrncmp(header.riff.descriptor.id, "RIFF", 4) != 0 || + qstrncmp(header.riff.type, "WAVE", 4) != 0 || + qstrncmp(header.wave.descriptor.id, "fmt ", 4) != 0 || + (header.wave.audioFormat != 0 && header.wave.audioFormat != 1) || + qstrncmp(header.data.descriptor.id, "data", 4) != 0) { + + emit invalidFormat(); + } + else { + int bps = qFromLittleEndian(header.wave.bitsPerSample); + + format.setCodec("audio/pcm"); + format.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); + format.setByteOrder(QAudioFormat::LittleEndian); + format.setFrequency(qFromLittleEndian(header.wave.sampleRate)); + format.setSampleSize(bps); + format.setChannels(qFromLittleEndian(header.wave.numChannels)); + + dataSize = qFromLittleEndian(header.data.descriptor.size); + + haveFormat = true; + connect(source, SIGNAL(readyRead()), SIGNAL(readyRead())); + emit formatKnown(); + } +} diff --git a/src/multimedia/qml/wavedecoder_p.h b/src/multimedia/qml/wavedecoder_p.h new file mode 100644 index 0000000..010fec6 --- /dev/null +++ b/src/multimedia/qml/wavedecoder_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WAVEDECODER_H +#define WAVEDECODER_H + +#include +#include + +class WaveDecoder : public QIODevice +{ +Q_OBJECT + +public: + explicit WaveDecoder(QIODevice *source, QObject *parent = 0); + ~WaveDecoder(); + + QAudioFormat audioFormat() const; + int duration() const; + + qint64 size() const; + bool isSequential() const; + qint64 bytesAvailable() const; + +signals: + void formatKnown(); + void invalidFormat(); + +private slots: + void handleData(); + +private: + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + + struct chunk + { + char id[4]; + quint32 size; + }; + struct RIFFHeader + { + chunk descriptor; + char type[4]; + }; + 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; + }; + + bool haveFormat; + qint64 dataSize; + qint64 remaining; + QAudioFormat format; + QIODevice *source; + CombinedHeader header; +}; + +#endif // WAVEDECODER_H -- cgit v0.12 From af34b8b726600e1f63484d86495a7514bd79c163 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 13:36:30 +1000 Subject: Make nativeSizeChanged() signal non-const. --- src/multimedia/base/qgraphicsvideoitem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.h b/src/multimedia/base/qgraphicsvideoitem.h index f8cffdc..06f471f 100644 --- a/src/multimedia/base/qgraphicsvideoitem.h +++ b/src/multimedia/base/qgraphicsvideoitem.h @@ -85,7 +85,7 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); Q_SIGNALS: - void nativeSizeChanged(const QSizeF &size) const; + void nativeSizeChanged(const QSizeF &size); protected: QVariant itemChange(GraphicsItemChange change, const QVariant &value); -- cgit v0.12 From 1c58f3fa6b0bc2cfab9b32bb315bbef4270f6649 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 13:37:55 +1000 Subject: Remove documentation for QGraphicsVideoItem::FillMode. No longer exists. --- src/multimedia/base/qgraphicsvideoitem.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp index 35baabe..3cd0449 100644 --- a/src/multimedia/base/qgraphicsvideoitem.cpp +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -203,18 +203,6 @@ void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed() */ /*! - \enum QGraphicsVideoItem::FillMode - - Enumerates the methods of scaling a video to fit a graphics item. - - \value Stretch The video is stretched to fit the item's size. - \value PreserveAspectFit The video is uniformly scaled to fix the item's - size without cropping. - \value PreserveAspectCrop The video is uniformly scaled to fill the item's - size, cropping if necessary. -*/ - -/*! Constructs a graphics item that displays video. The \a parent is passed to QGraphicsItem. -- cgit v0.12 From 903e52cdad8be0c23aaba303389cc4bff675bbb2 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 13:40:00 +1000 Subject: Correct QtMedia::SampleRate property mapping. Was mapped to frequency instead of sampleRate. --- src/multimedia/qml/qmetadatacontrolmetaobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp index c4b2b42..882d8a6 100644 --- a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp +++ b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp @@ -140,7 +140,7 @@ namespace { QtMedia::AverageLevel, "averageLevel" }, { QtMedia::ChannelCount, "channelCount" }, { QtMedia::PeakValue, "peakValue" }, - { QtMedia::SampleRate, "frequency" }, + { QtMedia::SampleRate, "sampleRate" }, // Music { QtMedia::AlbumTitle, "albumTitle" }, -- cgit v0.12 From 923af5cd17dcfa2038998addec44f70154b385d2 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 13:41:54 +1000 Subject: Update QML media element documentation. --- src/multimedia/qml/qmlaudio.cpp | 72 ++-- src/multimedia/qml/qmlgraphicsvideo.cpp | 610 ++++++++++++++++++++++++++++++-- 2 files changed, 628 insertions(+), 54 deletions(-) diff --git a/src/multimedia/qml/qmlaudio.cpp b/src/multimedia/qml/qmlaudio.cpp index f56b6c3..fc340d0 100644 --- a/src/multimedia/qml/qmlaudio.cpp +++ b/src/multimedia/qml/qmlaudio.cpp @@ -49,13 +49,19 @@ QML_DEFINE_TYPE(Qt,4,6,Audio,QmlAudio); /*! \qmlclass Audio QmlAudio - \brief The Audio element allows you to add audio to a scene. + \brief The Audio element allows you to add audio playback to a scene. + + \qml + Audio { source: "audio/song.mp3" } + \endqml + + \sa Video */ /*! \internal \class QmlAudio - \brief The QmlAudio class provides a audio item that you can add to a QmlView. + \brief The QmlAudio class provides an audio item that you can add to a QmlView. */ void QmlAudio::_q_error(int errorCode, const QString &errorString) @@ -82,7 +88,9 @@ QmlAudio::~QmlAudio() /*! \qmlmethod Audio::play() - Starts playback of the audio. + Starts playback of the media. + + Sets the \l playing property to true, and the \l paused property to false. */ void QmlAudio::play() @@ -98,7 +106,9 @@ void QmlAudio::play() /*! \qmlmethod Audio::pause() - Pauses playback of the audio. + Pauses playback of the media. + + Sets the \l playing and \l paused properties to true. */ void QmlAudio::pause() @@ -114,7 +124,9 @@ void QmlAudio::pause() /*! \qmlmethod Audio::stop() - Stops playback of the audio. + Stops playback of the media. + + Sets the \l playing and \l paused properties to false. */ void QmlAudio::stop() @@ -130,19 +142,23 @@ void QmlAudio::stop() /*! \qmlproperty url Audio::source - This property holds the source URL of the audio. + This property holds the source URL of the media. */ /*! \qmlproperty bool Audio::playing - This property holds whether the audio is playing. + This property holds whether the media is playing. + + Defaults to false, and can be set to true to start playback. */ /*! \qmlproperty bool Audio::paused - This property holds whether the audio is paused. + This property holds whether the media is paused. + + Defaults to false, and can be set to true to pause playback. */ /*! @@ -172,18 +188,18 @@ void QmlAudio::stop() /*! \qmlproperty enum Audio::status - This property holds the status of audio loading. It can be one of: + This property holds the status of media loading. It can be one of: \list - \o NoMedia - no audio has been set. - \o Loading - the audio is currently being loaded. - \o Loaded - the audio has been loaded. - \o Buffering - the audio is buffering data. - \o Stalled - playback has been interrupted while the audio is buffering data. - \o Buffered - the audio has buffered data. - \o EndOfMedia - the audio has played to the end. - \o InvalidMedia - the audio cannot be played. - \o UnknownStatus - the status of the audio is unknown. + \o NoMedia - no media has been set. + \o Loading - the media is currently being loaded. + \o Loaded - the media has been loaded. + \o Buffering - the media is buffering data. + \o Stalled - playback has been interrupted while the media is buffering data. + \o Buffered - the media has buffered data. + \o EndOfMedia - the media has played to the end. + \o InvalidMedia - the media cannot be played. + \o UnknownStatus - the status of the media is unknown. \endlist */ @@ -195,44 +211,46 @@ QmlAudio::Status QmlAudio::status() const /*! \qmlsignal Audio::onLoaded() - This handler is called when the video source has been loaded. + This handler is called when the media source has been loaded. */ /*! \qmlsignal Audio::onBuffering() - This handler is called when the video stream starts buffering. + This handler is called when the media starts buffering. */ /*! \qmlsignal Audio::onStalled() - This handler is called when playback has stalled while the video stream buffers. + This handler is called when playback has stalled while the media buffers. */ /*! \qmlsignal Audio::onBuffered() - This handler is called when the video stream has finished buffering. + This handler is called when the media has finished buffering. */ /*! - \qmlsignal Audio::onEndOfMedia + \qmlsignal Audio::onEndOfMedia() - This handler is called when playback stops because end of the video has been reached. + This handler is called when playback stops because end of the media has been reached. */ /*! \qmlproperty int Audio::duration - This property holds the duration of the audio in milliseconds. + This property holds the duration of the media in milliseconds. - If the audio doesn't have a fixed duration (a live stream for example) this will be 0. + If the media doesn't have a fixed duration (a live stream for example) this will be 0. */ /*! \qmlproperty int Audio::position This property holds the current playback position in milliseconds. + + If the \l seekable property is true, this property can be set to seek to a new position. */ /*! @@ -258,6 +276,8 @@ QmlAudio::Status QmlAudio::status() const \qmlproperty bool Audio::seekable This property holds whether position of the audio can be changed. + + If true; setting a \l position value will cause playback to seek to the new position. */ /*! diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp index f6a5eff..236387e 100644 --- a/src/multimedia/qml/qmlgraphicsvideo.cpp +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -73,6 +73,18 @@ void QmlGraphicsVideo::_q_error(int errorCode, const QString &errorString) \qmlclass Video QmlGraphicsVideo \brief The Video element allows you to add videos to a scene. \inherits Item + + \qml + Video { source: "video/movie.mpg" } + \endqml + + The video item supports untransformed, stretched, and uniformly scaled video presentation. + For a description of stretched uniformly scaled presentation, see the \l fillMode property + description. + + The video item is only visible when the \l hasVideo property is true and the video is playing. + + \sa Audio */ /*! @@ -112,19 +124,23 @@ QmlGraphicsVideo::~QmlGraphicsVideo() /*! \qmlproperty url Video::source - This property holds the source URL of the video. + This property holds the source URL of the media. */ /*! \qmlproperty bool Video::playing - This property holds whether the video is playing. + This property holds whether the media is playing. + + Defaults to false, and can be set to true to start playback. */ /*! \qmlproperty bool Video::paused - This property holds whether the video is paused. + This property holds whether the media is paused. + + Defaults to false, and can be set to true to pause playback. */ /*! @@ -154,18 +170,18 @@ QmlGraphicsVideo::~QmlGraphicsVideo() /*! \qmlproperty enum Video::status - This property holds the status of video loading. It can be one of: + This property holds the status of media loading. It can be one of: \list - \o NoMedia - no video has been set. - \o Loading - the video is currently being loaded. - \o Loaded - the video has been loaded. - \o Buffering - the video is buffering data. - \o Stalled - playback has been interrupted while the video is buffering data. - \o Buffered - the video has buffered data. - \o EndOfMedia - the video has played to the end. - \o InvalidMedia - the video cannot be played. - \o UnknownStatus - the status of the video is unknown. + \o NoMedia - no media has been set. + \o Loading - the media is currently being loaded. + \o Loaded - the media has been loaded. + \o Buffering - the media is buffering data. + \o Stalled - playback has been interrupted while the media is buffering data. + \o Buffered - the media has buffered data. + \o EndOfMedia - the media has played to the end. + \o InvalidMedia - the media cannot be played. + \o UnknownStatus - the status of the media is cannot be determined. \endlist */ @@ -177,39 +193,39 @@ QmlGraphicsVideo::Status QmlGraphicsVideo::status() const /*! \qmlsignal Video::onLoaded() - This handler is called when the video source has been loaded. + This handler is called when the media source has been loaded. */ /*! \qmlsignal Video::onBuffering() - This handler is called when the video stream starts buffering. + This handler is called when the media starts buffering. */ /*! \qmlsignal Video::onStalled() - This handler is called when playback has stalled while the video stream buffers. + This handler is called when playback has stalled while the media buffers. */ /*! \qmlsignal Video::onBuffered() - This handler is called when the video stream has finished buffering. + This handler is called when the media has finished buffering. */ /*! - \qmlsignal Video::onEndOfMedia + \qmlsignal Video::onEndOfMedia() - This handler is called when playback stops because end of the video has been reached. + This handler is called when playback stops because end of the media has been reached. */ /*! \qmlproperty int Video::duration - This property holds the duration of the video in milliseconds. + This property holds the duration of the media in milliseconds. - If the video doesn't have a fixed duration (a live stream for example) this will be 0. + If the media doesn't have a fixed duration (a live stream for example) this will be 0. */ /*! @@ -231,9 +247,9 @@ QmlGraphicsVideo::Status QmlGraphicsVideo::status() const */ /*! - \qmlproperty bool Audio::hasAudio + \qmlproperty bool Video::hasAudio - This property holds whether the source contains audio. + This property holds whether the media contains audio. */ bool QmlGraphicsVideo::hasAudio() const @@ -244,7 +260,7 @@ bool QmlGraphicsVideo::hasAudio() const /*! \qmlproperty bool Video::hasVideo - This property holds whether the source contains video. + This property holds whether the media contains video. */ bool QmlGraphicsVideo::hasVideo() const @@ -307,7 +323,7 @@ QmlGraphicsVideo::Error QmlGraphicsVideo::error() const */ /*! - \qmlproperty enum Video::FillMode + \qmlproperty enum Video::fillMode Set this property to define how the video is scaled to fit the target area. @@ -316,6 +332,8 @@ QmlGraphicsVideo::Error QmlGraphicsVideo::error() const \o PreserveAspectFit - the video is scaled uniformly to fit without cropping \o PreserveAspectCrop - the video is scaled uniformly to fill, cropping if necessary \endlist + + The default fill mode is PreserveAspectFit. */ QmlGraphicsVideo::FillMode QmlGraphicsVideo::fillMode() const @@ -331,7 +349,9 @@ void QmlGraphicsVideo::setFillMode(FillMode mode) /*! \qmlmethod Video::play() - Starts playback of the video. + Starts playback of the media. + + Sets the \l playing property to true, and the \l paused property to false. */ void QmlGraphicsVideo::play() @@ -347,7 +367,9 @@ void QmlGraphicsVideo::play() /*! \qmlmethod Video::pause() - Pauses playback of the video. + Pauses playback of the media. + + Sets the \l playing and \l paused properties to true. */ void QmlGraphicsVideo::pause() @@ -363,7 +385,9 @@ void QmlGraphicsVideo::pause() /*! \qmlmethod Video::stop() - Stops playback of the video. + Stops playback of the media. + + Sets the \l playing and \l paused properties to false. */ void QmlGraphicsVideo::stop() @@ -389,4 +413,534 @@ void QmlGraphicsVideo::geometryChanged(const QRectF &newGeometry, const QRectF & QT_END_NAMESPACE +// *************************************** +// Documentation for meta-data properties. +// *************************************** + +/*! + \qmlproperty variant Video::title + + This property holds the tile of the media. + + \sa {QtMedia::Title} +*/ + +/*! + \qmlproperty variant Video::subTitle + + This property holds the sub-title of the media. + + \sa {QtMedia::SubTitle} +*/ + +/*! + \qmlproperty variant Video::author + + This property holds the author of the media. + + \sa {QtMedia::Author} +*/ + +/*! + \qmlproperty variant Video::comment + + This property holds a user comment about the media. + + \sa {QtMedia::Comment} +*/ + +/*! + \qmlproperty variant Video::description + + This property holds a description of the media. + + \sa {QtMedia::Description} +*/ + +/*! + \qmlproperty variant Video::category + + This property holds the category of the media + + \sa {QtMedia::Category} +*/ + +/*! + \qmlproperty variant Video::genre + + This property holds the genre of the media. + + \sa {QtMedia::Genre} +*/ + +/*! + \qmlproperty variant Video::year + + This property holds the year of release of the media. + + \sa {QtMedia::Year} +*/ + +/*! + \qmlproperty variant Video::date + + This property holds the date of the media. + + \sa {QtMedia::Date} +*/ + +/*! + \qmlproperty variant Video::userRating + + This property holds a user rating of the media in the range of 0 to 100. + + \sa {QtMedia::UserRating} +*/ + +/*! + \qmlproperty variant Video::keywords + + This property holds a list of keywords describing the media. + + \sa {QtMedia::Keywords} +*/ + +/*! + \qmlproperty variant Video::language + + This property holds the language of the media, as an ISO 639-2 code. + + \sa {QtMedia::Language} +*/ + +/*! + \qmlproperty variant Video::publisher + + This property holds the publisher of the media. + + \sa {QtMedia::Publisher} +*/ + +/*! + \qmlproperty variant Video::copyright + + This property holds the media's copyright notice. + + \sa {QtMedia::Copyright} +*/ + +/*! + \qmlproperty variant Video::parentalRating + + This property holds the parental rating of the media. + + \sa {QtMedia::ParentalRating} +*/ + +/*! + \qmlproperty variant Video::ratingOrganisation + + This property holds the name of the rating organisation responsible for the + parental rating of the media. + + \sa {QtMedia::RatingOrganisation} +*/ + +/*! + \qmlproperty variant Video::size + + This property property holds the size of the media in bytes. + + \sa {QtMedia::Size} +*/ + +/*! + \qmlproperty variant Video::mediaType + + This property holds the type of the media. + + \sa {QtMedia::MediaType} +*/ + +/*! + \qmlproperty variant Video::audioBitRate + + This property holds the bit rate of the media's audio stream ni bits per + second. + + \sa {QtMedia::AudioBitRate} +*/ + +/*! + \qmlproperty variant Video::audioCodec + + This property holds the encoding of the media audio stream. + + \sa {QtMedia::AudioCodec} +*/ + +/*! + \qmlproperty variant Video::averageLevel + + This property holds the average volume level of the media. + + \sa {QtMedia::AverageLevel} +*/ + +/*! + \qmlproperty variant Video::channelCount + + This property holds the number of channels in the media's audio stream. + + \sa {QtMedia::ChannelCount} +*/ + +/*! + \qmlproperty variant Video::peakValue + + This property holds the peak volume of media's audio stream. + + \sa {QtMedia::PeakValue} +*/ + +/*! + \qmlproperty variant Video::sampleRate + + This property holds the sample rate of the media's audio stream in hertz. + + \sa {QtMedia::SampleRate} +*/ + +/*! + \qmlproperty variant Video::albumTitle + + This property holds the title of the album the media belongs to. + + \sa {QtMedia::AlbumTitle} +*/ + +/*! + \qmlproperty variant Video::albumArtist + + This property holds the name of the principal artist of the album the media + belongs to. + + \sa {QtMedia::AlbumArtist} +*/ + +/*! + \qmlproperty variant Video::contributingArtist + + This property holds the names of artists contributing to the media. + + \sa {QtMedia::ContributingArtist} +*/ + +/*! + \qmlproperty variant Video::composer + + This property holds the composer of the media. + + \sa {QtMedia::Composer} +*/ + +/*! + \qmlproperty variant Video::conductor + + This property holds the conductor of the media. + + \sa {QtMedia::Conductor} +*/ + +/*! + \qmlproperty variant Video::lyrics + + This property holds the lyrics to the media. + + \sa {QtMedia::Lyrics} +*/ + +/*! + \qmlproperty variant Video::mood + + This property holds the mood of the media. + + \sa {QtMedia::Mood} +*/ + +/*! + \qmlproperty variant Video::trackNumber + + This property holds the track number of the media. + + \sa {QtMedia::TrackNumber} +*/ + +/*! + \qmlproperty variant Video::trackCount + + This property holds the number of track on the album containing the media. + + \sa {QtMedia::TrackNumber} +*/ + +/*! + \qmlproperty variant Video::coverArtUrlSmall + + This property holds the URL of a small cover art image. + + \sa {QtMedia::CoverArtUrlSmall} +*/ + +/*! + \qmlproperty variant Video::coverArtUrlLarge + + This property holds the URL of a large cover art image. + + \sa {QtMedia::CoverArtUrlLarge} +*/ + +/*! + \qmlproperty variant Video::resolution + + This property holds the dimension of an image or video. + + \sa {QtMedia::Resolution} +*/ + +/*! + \qmlproperty variant Video::pixelAspectRatio + + This property holds the pixel aspect ratio of an image or video. + + \sa {QtMedia::PixelAspectRatio} +*/ + +/*! + \qmlproperty variant Video::videoFrameRate + + This property holds the frame rate of the media's video stream. + + \sa {QtMedia::VideoFrameRate} +*/ + +/*! + \qmlproperty variant Video::videoBitRate + + This property holds the bit rate of the media's video stream in bits per + second. + + \sa {QtMedia::VideoBitRate} +*/ + +/*! + \qmlproperty variant Video::videoCodec + + This property holds the encoding of the media's video stream. + + \sa {QtMedia::VideoCodec} +*/ + +/*! + \qmlproperty variant Video::posterUrl + + This property holds the URL of a poster image. + + \sa {QtMedia::PosterUrl} +*/ + +/*! + \qmlproperty variant Video::chapterNumber + + This property holds the chapter number of the media. + + \sa {QtMedia::ChapterNumber} +*/ + +/*! + \qmlproperty variant Video::director + + This property holds the director of the media. + + \sa {QtMedia::Director} +*/ + +/*! + \qmlproperty variant Video::leadPerformer + + This property holds the lead performer in the media. + + \sa {QtMedia::LeadPerformer} +*/ + +/*! + \qmlproperty variant Video::writer + + This property holds the writer of the media. + + \sa {QtMedia::Writer} +*/ + +// The remaining properties are related to photos, and are technically +// available but will certainly never have values. +#ifndef Q_QDOC + +/*! + \qmlproperty variant Video::cameraManufacturer + + \sa {QtMedia::CameraManufacturer} +*/ + +/*! + \qmlproperty variant Video::cameraModel + + \sa {QtMedia::CameraModel} +*/ + +/*! + \qmlproperty variant Video::event + + \sa {QtMedia::Event} +*/ + +/*! + \qmlproperty variant Video::subject + + \sa {QtMedia::Subject} +*/ + +/*! + \qmlproperty variant Video::orientation + + \sa {QtMedia::Orientation} +*/ + +/*! + \qmlproperty variant Video::exposureTime + + \sa {QtMedia::ExposureTime} +*/ + +/*! + \qmlproperty variant Video::fNumber + + \sa {QtMedia::FNumber} +*/ + +/*! + \qmlproperty variant Video::exposureProgram + + \sa {QtMedia::ExposureProgram} +*/ + +/*! + \qmlproperty variant Video::isoSpeedRatings + + \sa {QtMedia::ISOSpeedRatings} +*/ + +/*! + \qmlproperty variant Video::exposureBiasValue + + \sa {QtMedia::ExposureBiasValue} +*/ + +/*! + \qmlproperty variant Video::dateTimeDigitized + + \sa {QtMedia::DateTimeDigitized} +*/ + +/*! + \qmlproperty variant Video::subjectDistance + + \sa {QtMedia::SubjectDistance} +*/ + +/*! + \qmlproperty variant Video::meteringMode + + \sa {QtMedia::MeteringMode} +*/ + +/*! + \qmlproperty variant Video::lightSource + + \sa {QtMedia::LightSource} +*/ + +/*! + \qmlproperty variant Video::flash + + \sa {QtMedia::Flash} +*/ + +/*! + \qmlproperty variant Video::focalLength + + \sa {QtMedia::FocalLength} +*/ + +/*! + \qmlproperty variant Video::exposureMode + + \sa {QtMedia::ExposureMode} +*/ + +/*! + \qmlproperty variant Video::whiteBalance + + \sa {QtMedia::WhiteBalance} +*/ + +/*! + \qmlproperty variant Video::DigitalZoomRatio + + \sa {QtMedia::DigitalZoomRatio} +*/ + +/*! + \qmlproperty variant Video::focalLengthIn35mmFilm + + \sa {QtMedia::FocalLengthIn35mmFile} +*/ + +/*! + \qmlproperty variant Video::sceneCaptureType + + \sa {QtMedia::SceneCaptureType} +*/ + +/*! + \qmlproperty variant Video::gainControl + + \sa {QtMedia::GainControl} +*/ + +/*! + \qmlproperty variant Video::contrast + + \sa {QtMedia::contrast} +*/ + +/*! + \qmlproperty variant Video::saturation + + \sa {QtMedia::Saturation} +*/ + +/*! + \qmlproperty variant Video::sharpness + + \sa {QtMedia::Sharpness} +*/ + +/*! + \qmlproperty variant Video::deviceSettingDescription + + \sa {QtMedia::DeviceSettingDescription} +*/ + +#endif + #include "moc_qmlgraphicsvideo_p.cpp" -- cgit v0.12 From da727b5aadf64128de0eb39fc1ce26e587211272 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 17:50:42 +1000 Subject: Fix stall in graph when removing video and audio outputs. Must remove the decoder as well as the output otherwise the graph wont be able to resume because a disconnected decoder cant. And the graph must be stopped to connect a new output. --- .../mediaplayer/directshowplayerservice.cpp | 107 +++++++++++++++++---- .../mediaplayer/directshowplayerservice.h | 1 + 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index fdbee81..3c0a43a 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -319,6 +319,13 @@ void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) void DirectShowPlayerService::doRender(QMutexLocker *locker) { + m_pendingTasks |= m_executedTasks & (Play | Pause); + + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); + } + if (m_pendingTasks & SetAudioOutput) { m_graph->AddFilter(m_audioOutput, L"AudioOutput"); @@ -358,7 +365,7 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) IPin *peer = 0; if (pin->ConnectedTo(&peer) == S_OK) { PIN_INFO peerInfo; - if (peer->QueryPinInfo(&peerInfo) == S_OK) + if (SUCCEEDED(peer->QueryPinInfo(&peerInfo))) filters.append(peerInfo.pFilter); peer->Release(); } else { @@ -374,13 +381,15 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) } } } + + pins->Release(); + if (outputs == 0) rendered = true; } filter->Release(); } - if (m_audioOutput && !isConnected(m_audioOutput, PINDIR_INPUT)) { graph->RemoveFilter(m_audioOutput); @@ -604,9 +613,6 @@ void DirectShowPlayerService::doPlay(QMutexLocker *locker) control->Release(); - if (SUCCEEDED(hr)) - m_executedTasks |= Play; - if (SUCCEEDED(hr)) { m_executedTasks |= Play; @@ -851,14 +857,14 @@ void DirectShowPlayerService::setAudioOutput(IBaseFilter *filter) m_audioOutput->AddRef(); m_pendingTasks |= SetAudioOutput; - } else { - m_pendingTasks &= ~ SetAudioOutput; - } - if (m_executedTasks & SetSource) { - m_pendingTasks |= Render; + if (m_executedTasks & SetSource) { + m_pendingTasks |= Render; - ::SetEvent(m_taskHandle); + ::SetEvent(m_taskHandle); + } + } else { + m_pendingTasks &= ~ SetAudioOutput; } } else { if (m_audioOutput) @@ -882,7 +888,20 @@ void DirectShowPlayerService::doReleaseAudioOutput(QMutexLocker *locker) control->Release(); } - m_graph->RemoveFilter(m_audioOutput); + IBaseFilter *decoder = getConnected(m_audioOutput, PINDIR_INPUT); + if (!decoder) { + decoder = m_audioOutput; + decoder->AddRef(); + } + + if (IFilterChain *chain = com_cast(m_graph)) { + chain->RemoveChain(decoder, m_audioOutput); + chain->Release(); + } else { + m_graph->RemoveFilter(m_audioOutput); + } + + decoder->Release(); m_executedTasks &= ~SetAudioOutput; @@ -911,14 +930,12 @@ void DirectShowPlayerService::setVideoOutput(IBaseFilter *filter) m_videoOutput->AddRef(); m_pendingTasks |= SetVideoOutput; - } else { - m_pendingTasks &= ~ SetVideoOutput; - } - if (m_executedTasks & SetSource) { - m_pendingTasks |= Render; + if (m_executedTasks & SetSource) { + m_pendingTasks |= Render; - ::SetEvent(m_taskHandle); + ::SetEvent(m_taskHandle); + } } } else { if (m_videoOutput) @@ -940,7 +957,27 @@ void DirectShowPlayerService::doReleaseVideoOutput(QMutexLocker *locker) control->Release(); } - m_graph->RemoveFilter(m_videoOutput); + IBaseFilter *intermediate = 0; + if (!SUCCEEDED(m_graph->FindFilterByName(L"Color Space Converter", &intermediate))) { + intermediate = m_videoOutput; + intermediate->AddRef(); + } + + IBaseFilter *decoder = getConnected(intermediate, PINDIR_INPUT); + if (!decoder) { + decoder = intermediate; + decoder->AddRef(); + } + + if (IFilterChain *chain = com_cast(m_graph)) { + chain->RemoveChain(decoder, m_videoOutput); + chain->Release(); + } else { + m_graph->RemoveFilter(m_videoOutput); + } + + intermediate->Release(); + decoder->Release(); m_executedTasks &= ~SetVideoOutput; @@ -1109,6 +1146,38 @@ bool DirectShowPlayerService::isConnected(IBaseFilter *filter, PIN_DIRECTION dir return connected; } +IBaseFilter *DirectShowPlayerService::getConnected( + IBaseFilter *filter, PIN_DIRECTION direction) const +{ + IBaseFilter *connected = 0; + + IEnumPins *pins = 0; + + if (SUCCEEDED(filter->EnumPins(&pins))) { + for (IPin *pin = 0; pins->Next(1, &pin, 0) == S_OK; pin->Release()) { + PIN_DIRECTION dir; + if (SUCCEEDED(pin->QueryDirection(&dir)) && dir == direction) { + IPin *peer = 0; + if (SUCCEEDED(pin->ConnectedTo(&peer))) { + PIN_INFO info; + + if (SUCCEEDED(peer->QueryPinInfo(&info))) { + if (connected) { + qWarning("DirectShowPlayerService::getConnected: " + "Multiple connected filters"); + connected->Release(); + } + connected = info.pFilter; + } + peer->Release(); + } + } + } + pins->Release(); + } + return connected; +} + void DirectShowPlayerService::run() { QMutexLocker locker(&m_mutex); diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h index 576520e..906d23b 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -114,6 +114,7 @@ private: int findStreamType(IPin *pin) const; bool isConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; + IBaseFilter *getConnected(IBaseFilter *filter, PIN_DIRECTION direction) const; void run(); -- cgit v0.12 From 4603dc768d8c98770311a9136f956f3cefa90362 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 8 Feb 2010 17:53:56 +1000 Subject: Don't clear the video output when the video widget is hidden. Changing the video output is a heavy task and is likely to interrupt playback. Not really worth the cost for knowing the video isn't being decoded while it cant be seen. This also applies to the QGraphicsVideoItem. --- src/multimedia/base/qgraphicsvideoitem.cpp | 16 +--------------- src/multimedia/base/qvideowidget.cpp | 3 --- tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp | 2 +- tests/auto/qvideowidget/tst_qvideowidget.cpp | 6 +++--- 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp index 3cd0449..8aba269 100644 --- a/src/multimedia/base/qgraphicsvideoitem.cpp +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -408,21 +408,7 @@ void QGraphicsVideoItem::paint( */ QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value) { - Q_D(QGraphicsVideoItem); - - if (change == ItemVisibleChange && d->outputControl != 0 && d->rendererControl != 0) { - if (value.toBool()) { - d->outputControl->setOutput(QVideoOutputControl::RendererOutput); - - return d->outputControl->output() == QVideoOutputControl::RendererOutput; - } else { - d->outputControl->setOutput(QVideoOutputControl::NoOutput); - - return value; - } - } else { - return QGraphicsItem::itemChange(change, value); - } + return QGraphicsItem::itemChange(change, value); } QT_END_NAMESPACE diff --git a/src/multimedia/base/qvideowidget.cpp b/src/multimedia/base/qvideowidget.cpp index 31cfd8d..5df245e 100644 --- a/src/multimedia/base/qvideowidget.cpp +++ b/src/multimedia/base/qvideowidget.cpp @@ -868,9 +868,6 @@ void QVideoWidget::hideEvent(QHideEvent *event) if (d->currentBackend) d->currentBackend->hideEvent(event); - if (d->outputControl) - d->outputControl->setOutput(QVideoOutputControl::NoOutput); - QWidget::hideEvent(event); } diff --git a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp index 2427d64..7fb6005 100644 --- a/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp +++ b/tests/auto/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp @@ -357,7 +357,7 @@ void tst_QGraphicsVideoItem::show() QVERIFY(object.testService->rendererControl->surface() != 0); item->hide(); - QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); item->show(); QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); diff --git a/tests/auto/qvideowidget/tst_qvideowidget.cpp b/tests/auto/qvideowidget/tst_qvideowidget.cpp index 37676cf..e30d16b 100644 --- a/tests/auto/qvideowidget/tst_qvideowidget.cpp +++ b/tests/auto/qvideowidget/tst_qvideowidget.cpp @@ -653,7 +653,7 @@ void tst_QVideoWidget::showWindowControl() widget.hide(); - QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::WindowOutput); } void tst_QVideoWidget::showWidgetControl() @@ -677,7 +677,7 @@ void tst_QVideoWidget::showWidgetControl() widget.hide(); - QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::WidgetOutput); QCOMPARE(object.testService->widgetControl->videoWidget()->isVisible(), false); } @@ -702,7 +702,7 @@ void tst_QVideoWidget::showRendererControl() widget.hide(); - QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput); + QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput); } void tst_QVideoWidget::aspectRatioWindowControl() -- cgit v0.12 From bced83df38693948bb815cbfad1a8dc1a9c66baa Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Tue, 9 Feb 2010 15:56:36 +1000 Subject: Added errors reporting to gst playback backend. --- .../gstreamer/mediaplayer/qgstreamerplayercontrol.cpp | 2 ++ .../gstreamer/mediaplayer/qgstreamerplayersession.cpp | 13 +++++++++++++ .../gstreamer/mediaplayer/qgstreamerplayersession.h | 1 + 3 files changed, 16 insertions(+) diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index f008e81..d417266 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -86,6 +86,8 @@ QGstreamerPlayerControl::QGstreamerPlayerControl(QGstreamerPlayerSession *sessio this, SIGNAL(videoAvailableChanged(bool))); connect(m_session, SIGNAL(seekableChanged(bool)), this, SIGNAL(seekableChanged(bool))); + connect(m_session, SIGNAL(error(int,QString)), + this, SIGNAL(error(int,QString))); } QGstreamerPlayerControl::~QGstreamerPlayerControl() diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 016909a..355df2f 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -266,6 +266,8 @@ void QGstreamerPlayerSession::play() emit stateChanged(m_state); emit mediaStatusChanged(m_mediaStatus); + + emit error(int(QMediaPlayer::ResourceError), tr("Unable to play %1").arg(m_url.path())); } } } @@ -525,7 +527,18 @@ void QGstreamerPlayerSession::busMessage(const QGstreamerMessage &message) case GST_MESSAGE_TAG: case GST_MESSAGE_STREAM_STATUS: case GST_MESSAGE_UNKNOWN: + break; case GST_MESSAGE_ERROR: + { + GError *err; + gchar *debug; + gst_message_parse_error (gm, &err, &debug); + emit error(int(QMediaPlayer::ResourceError), QString::fromUtf8(err->message)); + qWarning() << "Error:" << QString::fromUtf8(err->message); + g_error_free (err); + g_free (debug); + } + break; case GST_MESSAGE_WARNING: case GST_MESSAGE_INFO: break; diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h index d33ffd2..e277ba9 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -129,6 +129,7 @@ signals: void tagsChanged(); void streamsChanged(); void seekableChanged(bool); + void error(int error, const QString &errorString); private slots: void busMessage(const QGstreamerMessage &message); -- cgit v0.12 From 46c9f5174d208fd98903a6f95e4e3bc8af6df9e4 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Wed, 10 Feb 2010 07:45:50 +1000 Subject: maemo define spelling incorrect. --- src/multimedia/qml/qsoundeffect_pulse_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.cpp b/src/multimedia/qml/qsoundeffect_pulse_p.cpp index fa2119d..c16e999 100644 --- a/src/multimedia/qml/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/qml/qsoundeffect_pulse_p.cpp @@ -181,7 +181,7 @@ private: m_prepared = false; } -#if(QWS_MAEMO_5) +#if(Q_WS_MAEMO_5) static void context_state_callback(pa_context *c, void *userdata) { PulseDaemon *self = reinterpret_cast(userdata); -- cgit v0.12 From e6646c68cf273934b74acd40492d63b447cf800c Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Wed, 10 Feb 2010 11:40:38 +1000 Subject: Added missing qgstxvimagebuffer.h/cpp to gstreamer.pro --- src/plugins/mediaservices/gstreamer/gstreamer.pro | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/gstreamer/gstreamer.pro b/src/plugins/mediaservices/gstreamer/gstreamer.pro index e4e8d5a..5a16f03 100644 --- a/src/plugins/mediaservices/gstreamer/gstreamer.pro +++ b/src/plugins/mediaservices/gstreamer/gstreamer.pro @@ -33,7 +33,9 @@ HEADERS += \ qgstreamervideorenderer.h \ qgstvideobuffer.h \ qvideosurfacegstsink.h \ - qx11videosurface.h + qx11videosurface.h \ + qgstxvimagebuffer.h + SOURCES += \ qgstreamermessage.cpp \ @@ -48,7 +50,8 @@ SOURCES += \ qgstreamervideorenderer.cpp \ qgstvideobuffer.cpp \ qvideosurfacegstsink.cpp \ - qx11videosurface.cpp + qx11videosurface.cpp \ + qgstxvimagebuffer.cpp include(mediaplayer/mediaplayer.pri) -- cgit v0.12 From aec0628295cda95f2169e3007368797ba6585ee3 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 10 Feb 2010 15:46:53 +1000 Subject: Fix crash on exit in player example on Windows. Explicitly clear the QPointer to QVideoWidget on destruction, otherwise the destruction of the QVideoWidget will seeminly attempt to clear an invalidated QPointer. --- src/multimedia/playback/qmediaplayer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 0853597..d3dfbb2 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -308,6 +308,8 @@ QMediaPlayer::~QMediaPlayer() Q_D(QMediaPlayer); d->provider->releaseService(d->service); + d->videoWidget = 0; + d->videoItem = 0; } QMediaContent QMediaPlayer::media() const -- cgit v0.12 From eab600d2d58a2f638636281ec5db65b4a07b890f Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 10 Feb 2010 16:51:43 +1000 Subject: Emit an error if given a QIODevice that is unusable. Where unusable is not readable or sequential. --- .../mediaplayer/directshowplayercontrol.cpp | 65 +++++++++++++--------- .../mediaplayer/directshowplayercontrol.h | 9 ++- .../mediaplayer/directshowplayerservice.cpp | 34 +++++++---- .../mediaplayer/directshowplayerservice.h | 1 + 4 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp index a4308d7..587f4b1 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp @@ -82,6 +82,7 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic , m_updateProperties(0) , m_state(QMediaPlayer::StoppedState) , m_status(QMediaPlayer::UnknownMediaStatus) + , m_error(QMediaPlayer::NoError) , m_streamTypes(0) , m_muteVolume(-1) , m_duration(0) @@ -240,12 +241,7 @@ void DirectShowPlayerControl::setMedia(const QMediaContent &media, QIODevice *st m_service->load(media, stream); - emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream); - emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); - emit durationChanged(m_duration); - emit seekableChanged(m_seekable); - emit mediaStatusChanged(m_status); - emit stateChanged(m_state); + emitPropertyChanges(); } void DirectShowPlayerControl::play() @@ -269,33 +265,41 @@ void DirectShowPlayerControl::stop() void DirectShowPlayerControl::customEvent(QEvent *event) { if (event->type() == QEvent::Type(PropertiesChanged)) { - int properties = m_updateProperties; - m_updateProperties = 0; + emitPropertyChanges(); - if (properties & PlaybackRateProperty) - emit playbackRateChanged(m_playbackRate); + event->accept(); + } else { + QMediaPlayerControl::customEvent(event); + } +} - if (properties & StreamTypesProperty) { - emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream); - emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); - } +void DirectShowPlayerControl::emitPropertyChanges() +{ + int properties = m_updateProperties; + m_updateProperties = 0; - if (properties & DurationProperty) - emit durationChanged(m_duration); + if ((properties & ErrorProperty) && m_error != QMediaPlayer::NoError) + emit error(m_error, m_errorString); - if (properties & SeekableProperty) - emit seekableChanged(m_seekable); + if (properties & PlaybackRateProperty) + emit playbackRateChanged(m_playbackRate); - if (properties & StatusProperty) - emit mediaStatusChanged(m_status); + if (properties & StreamTypesProperty) { + emit audioAvailableChanged(m_streamTypes & DirectShowPlayerService::AudioStream); + emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); + } - if (properties & StateProperty) - emit stateChanged(m_state); + if (properties & DurationProperty) + emit durationChanged(m_duration); - event->accept(); - } else { - QMediaPlayerControl::customEvent(event); - } + if (properties & SeekableProperty) + emit seekableChanged(m_seekable); + + if (properties & StatusProperty) + emit mediaStatusChanged(m_status); + + if (properties & StateProperty) + emit stateChanged(m_state); } void DirectShowPlayerControl::scheduleUpdate(int properties) @@ -366,4 +370,13 @@ void DirectShowPlayerControl::updateAudioOutput(IBaseFilter *filter) m_audio = com_cast(filter); } +void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QString &errorString) +{ + m_error = error; + m_errorString = errorString; + + if (m_error != QMediaPlayer::NoError) + scheduleUpdate(ErrorProperty); +} + QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h index af2cd3f..6706bab 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h @@ -101,8 +101,7 @@ public: void updateMediaInfo(qint64 duration, int streamTypes, bool seekable); void updatePlaybackRate(qreal rate); void updateAudioOutput(IBaseFilter *filter); - - using QMediaPlayerControl::error; + void updateError(QMediaPlayer::Error error, const QString &errorString); protected: void customEvent(QEvent *event); @@ -115,7 +114,8 @@ private: StreamTypesProperty = 0x04, DurationProperty = 0x08, PlaybackRateProperty = 0x10, - SeekableProperty = 0x20 + SeekableProperty = 0x20, + ErrorProperty = 0x40 }; enum Event @@ -124,6 +124,7 @@ private: }; void scheduleUpdate(int properties); + void emitPropertyChanges(); DirectShowPlayerService *m_service; IBasicAudio *m_audio; @@ -131,12 +132,14 @@ private: int m_updateProperties; QMediaPlayer::State m_state; QMediaPlayer::MediaStatus m_status; + QMediaPlayer::Error m_error; int m_streamTypes; int m_muteVolume; qint64 m_duration; qreal m_playbackRate; bool m_seekable; QMediaContent m_media; + QString m_errorString; }; diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index 3c0a43a..e9bce71 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -182,6 +182,8 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_resources = media.resources(); m_stream = stream; + m_error = QMediaPlayer::NoError; + m_errorString = QString(); m_duration = 0; m_streamTypes = 0; m_executedTasks = 0; @@ -195,6 +197,10 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_graphStatus = NoMedia; m_url.clear(); + } else if (stream && (!stream->isReadable() || stream->isSequential())) { + m_pendingTasks = 0; + m_graphStatus = InvalidMedia; + m_error = QMediaPlayer::ResourceError; } else { m_graphStatus = Loading; @@ -208,6 +214,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream ::SetEvent(m_taskHandle); } + m_playerControl->updateError(m_error, m_errorString); m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); m_playerControl->updateState(QMediaPlayer::StoppedState); updateStatus(); @@ -273,13 +280,16 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) switch (hr) { case VFW_E_UNKNOWN_FILE_TYPE: m_error = QMediaPlayer::FormatError; + m_errorString = QString(); break; case E_OUTOFMEMORY: case VFW_E_CANNOT_LOAD_SOURCE_FILTER: case VFW_E_NOT_FOUND: m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); default: m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); qWarning("DirectShowPlayerService::doSetUrlSource: Unresolved error code %x", hr); break; } @@ -312,6 +322,7 @@ void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) m_graphStatus = InvalidMedia; m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); } @@ -415,14 +426,17 @@ void DirectShowPlayerService::doRender(QMutexLocker *locker) if (!m_audioOutput && !m_videoOutput) { m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); } else { switch (renderHr) { case VFW_E_UNSUPPORTED_AUDIO: case VFW_E_UNSUPPORTED_VIDEO: case VFW_E_UNSUPPORTED_STREAM: m_error = QMediaPlayer::FormatError; + m_errorString = QString(); default: m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); qWarning("DirectShowPlayerService::doRender: Unresolved error code %x", renderHr); } @@ -619,6 +633,7 @@ void DirectShowPlayerService::doPlay(QMutexLocker *locker) QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); } else { m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); qWarning("DirectShowPlayerService::doPlay: Unresolved error code %x", hr); QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); @@ -660,6 +675,7 @@ void DirectShowPlayerService::doPause(QMutexLocker *locker) QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); } else { m_error = QMediaPlayer::ResourceError; + m_errorString = QString(); qWarning("DirectShowPlayerService::doPause: Unresolved error code %x", hr); QCoreApplication::postEvent(this, new QEvent(QEvent::Type(Error))); @@ -994,18 +1010,14 @@ void DirectShowPlayerService::customEvent(QEvent *event) updateStatus(); } else if (event->type() == QEvent::Type(Error)) { - QMediaPlayer::Error error; - { - QMutexLocker locker(&m_mutex); - error = m_error; - - if (error != QMediaPlayer::NoError) { - m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); - m_playerControl->updateState(QMediaPlayer::StoppedState); - updateStatus(); - } + QMutexLocker locker(&m_mutex); + + if (m_error != QMediaPlayer::NoError) { + m_playerControl->updateError(m_error, m_errorString); + m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); + m_playerControl->updateState(QMediaPlayer::StoppedState); + updateStatus(); } - m_playerControl->error(error, QString()); } else if (event->type() == QEvent::Type(RateChange)) { QMutexLocker locker(&m_mutex); diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h index 906d23b..f9d3232 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -205,6 +205,7 @@ private: QMediaTimeRange m_playbackRange; QUrl m_url; QMediaResourceList m_resources; + QString m_errorString; QMutex m_mutex; friend class DirectShowPlayerServiceThread; -- cgit v0.12 From 510d619f86c3f5464e05ab4d27b3f5eddd7b5135 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 11 Feb 2010 10:29:27 +1000 Subject: Add virtual destructors to QMediaObjectPrivate and QMediaServicePrivate. This reverts aec0628295cda95f2169e3007368797ba6585ee3 and fixes the actual problem, which is the destructors for for classes inheriting QMediaObjectPrivate weren't being called resulting in QPointer destructors also not being called. --- src/multimedia/base/qmediaobject_p.h | 1 + src/multimedia/base/qmediaservice_p.h | 1 + src/multimedia/playback/qmediaplayer.cpp | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/multimedia/base/qmediaobject_p.h b/src/multimedia/base/qmediaobject_p.h index 4bbe06a..ec2f75a 100644 --- a/src/multimedia/base/qmediaobject_p.h +++ b/src/multimedia/base/qmediaobject_p.h @@ -76,6 +76,7 @@ class QMediaObjectPrivate public: QMediaObjectPrivate():metaDataControl(0), notifyTimer(0) {} + virtual ~QMediaObjectPrivate() {} void _q_notify(); diff --git a/src/multimedia/base/qmediaservice_p.h b/src/multimedia/base/qmediaservice_p.h index 5993a7e..7dbcd8a 100644 --- a/src/multimedia/base/qmediaservice_p.h +++ b/src/multimedia/base/qmediaservice_p.h @@ -63,6 +63,7 @@ class QMediaServicePrivate { public: QMediaServicePrivate(): q_ptr(0) {} + virtual ~QMediaServicePrivate() {} QMediaService *q_ptr; }; diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index d3dfbb2..0853597 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -308,8 +308,6 @@ QMediaPlayer::~QMediaPlayer() Q_D(QMediaPlayer); d->provider->releaseService(d->service); - d->videoWidget = 0; - d->videoItem = 0; } QMediaContent QMediaPlayer::media() const -- cgit v0.12 From 7c8835b2dd350978ebb226c15d1a3c9d03f683e2 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 11 Feb 2010 13:20:10 +1000 Subject: Don't call free() on 'this' in DirectShowMediaType. The correct function is freeData(). --- .../mediaservices/directshow/mediaplayer/directshowmediatype.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h index 3ba907e..3cc7307 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.h @@ -60,9 +60,9 @@ public: DirectShowMediaType(const AM_MEDIA_TYPE &type) { copy(this, type); } DirectShowMediaType(const DirectShowMediaType &other) { copy(this, other); } DirectShowMediaType &operator =(const AM_MEDIA_TYPE &type) { - free(this); copy(this, type); return *this; } + freeData(this); copy(this, type); return *this; } DirectShowMediaType &operator =(const DirectShowMediaType &other) { - free(this); copy(this, other); return *this; } + freeData(this); copy(this, other); return *this; } ~DirectShowMediaType() { freeData(this); } void clear() { freeData(this); memset(this, 0, sizeof(DirectShowMediaType)); } -- cgit v0.12 From b2b80a93cd5ec39ce5bdcf5836e2b07ccb65389b Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 11 Feb 2010 13:26:31 +1000 Subject: Add support for reading from resource files to Direct Show media service --- .../directshow/mediaplayer/directshowiosource.cpp | 46 +++++++++++++++++++--- .../directshow/mediaplayer/directshowiosource.h | 18 +++++++-- .../mediaplayer/directshowplayerservice.cpp | 10 ++++- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp index bf83dcf..c2fb0d4 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.cpp @@ -45,6 +45,8 @@ #include "directshowmediatype.h" #include "directshowpinenum.h" +#include +#include QT_BEGIN_NAMESPACE @@ -55,15 +57,16 @@ static const GUID directshow_subtypes[] = MEDIASUBTYPE_NULL }; -DirectShowIOSource::DirectShowIOSource(QIODevice *device, DirectShowEventLoop *loop) +DirectShowIOSource::DirectShowIOSource(DirectShowEventLoop *loop) : m_ref(1) , m_state(State_Stopped) + , m_reader(0) + , m_loop(loop) , m_graph(0) , m_clock(0) , m_allocator(0) , m_peerPin(0) , m_pinId(QLatin1String("Data")) - , m_reader(device, this, loop) { QVector mediaTypes; @@ -93,6 +96,15 @@ DirectShowIOSource::DirectShowIOSource(QIODevice *device, DirectShowEventLoop *l DirectShowIOSource::~DirectShowIOSource() { Q_ASSERT(m_ref == 0); + + delete m_reader; +} + +void DirectShowIOSource::setDevice(QIODevice *device) +{ + Q_ASSERT(!m_reader); + + m_reader = new DirectShowIOReader(device, this, m_loop); } void DirectShowIOSource::setAllocator(IMemAllocator *allocator) @@ -121,7 +133,7 @@ HRESULT DirectShowIOSource::QueryInterface(REFIID riid, void **ppvObject) } else if (riid == IID_IPin) { *ppvObject = static_cast(this); } else if (riid == IID_IAsyncReader) { - *ppvObject = static_cast(&m_reader); + *ppvObject = static_cast(m_reader); } else { *ppvObject = 0; @@ -571,12 +583,12 @@ HRESULT DirectShowIOSource::EndOfStream() HRESULT DirectShowIOSource::BeginFlush() { - return m_reader.BeginFlush(); + return m_reader->BeginFlush(); } HRESULT DirectShowIOSource::EndFlush() { - return m_reader.EndFlush(); + return m_reader->EndFlush(); } HRESULT DirectShowIOSource::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) @@ -601,3 +613,27 @@ HRESULT DirectShowIOSource::QueryDirection(PIN_DIRECTION *pPinDir) QT_END_NAMESPACE +DirectShowRcSource::DirectShowRcSource(DirectShowEventLoop *loop) + : DirectShowIOSource(loop) +{ +} + +bool DirectShowRcSource::open(const QUrl &url) +{ + m_file.moveToThread(QCoreApplication::instance()->thread()); + + m_file.setFileName(QLatin1Char(':') + url.path()); + + qDebug("qrc file %s", qPrintable(m_file.fileName())); + + if (m_file.open(QIODevice::ReadOnly)) { + qDebug("Size %d", m_file.size()); + qDebug("Sequential %d", int(m_file.isSequential())); + + setDevice(&m_file); + + return true; + } else { + return false; + } +} diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h index a8ed56a..b626473 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowiosource.h @@ -51,7 +51,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QIODevice; +#include class DirectShowIOSource : public DirectShowMediaTypeList @@ -60,9 +60,10 @@ class DirectShowIOSource , public IPin { public: - DirectShowIOSource(QIODevice *device, DirectShowEventLoop *loop); + DirectShowIOSource(DirectShowEventLoop *loop); ~DirectShowIOSource(); + void setDevice(QIODevice *device); void setAllocator(IMemAllocator *allocator); // IUnknown @@ -126,6 +127,8 @@ private: volatile LONG m_ref; FILTER_STATE m_state; + DirectShowIOReader *m_reader; + DirectShowEventLoop *m_loop; IFilterGraph *m_graph; IReferenceClock *m_clock; IMemAllocator *m_allocator; @@ -134,8 +137,17 @@ private: QString m_filterName; const QString m_pinId; QMutex m_mutex; - DirectShowIOReader m_reader; +}; + +class DirectShowRcSource : public DirectShowIOSource +{ +public: + DirectShowRcSource(DirectShowEventLoop *loop); + + bool open(const QUrl &url); +private: + QFile m_file; }; QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index e9bce71..6e6b2f2 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -247,6 +247,13 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) fileSource->Release(); } + } else if (url.scheme() == QLatin1String("qrc")) { + DirectShowRcSource *rcSource = new DirectShowRcSource(m_loop); + + if (rcSource->open(url) && SUCCEEDED(hr = m_graph->AddFilter(rcSource, L"Source"))) + source = rcSource; + else + rcSource->Release(); } if (!SUCCEEDED(hr)) { @@ -300,7 +307,8 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker) void DirectShowPlayerService::doSetStreamSource(QMutexLocker *locker) { - IBaseFilter *source = new DirectShowIOSource(m_stream, m_loop); + DirectShowIOSource *source = new DirectShowIOSource(m_loop); + source->setDevice(m_stream); if (SUCCEEDED(m_graph->AddFilter(source, L"Source"))) { m_executedTasks = SetSource; -- cgit v0.12 From dc7a0b2842a5866b6248e56d41db0af05f7efbc2 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 11 Feb 2010 13:30:00 +1000 Subject: Fix incorrect buffer size calculation. Was off by one resulting in repeated playback of mp3s being cutt off. --- .../mediaservices/directshow/mediaplayer/directshowioreader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp index dcb9a40..54446b8 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowioreader.cpp @@ -179,7 +179,7 @@ HRESULT DirectShowIOReader::Request(IMediaSample *pSample, DWORD_PTR dwUser) return VFW_E_SAMPLE_TIME_NOT_SET; } else { LONGLONG position = startTime / 10000000; - LONG length = ((endTime - startTime) / 10000000) + 1; + LONG length = (endTime - startTime) / 10000000; DirectShowSampleRequest *request = new DirectShowSampleRequest( pSample, dwUser, position, length, buffer); @@ -251,7 +251,7 @@ HRESULT DirectShowIOReader::SyncReadAligned(IMediaSample *pSample) return VFW_E_SAMPLE_TIME_NOT_SET; } else { LONGLONG position = startTime / 10000000; - LONG length = ((endTime - startTime) / 10000000) + 1; + LONG length = (endTime - startTime) / 10000000; QMutexLocker locker(&m_mutex); -- cgit v0.12 From 476970c2a1d00cfbf3f8bd6ac4b5c835633641ca Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 12 Feb 2010 15:46:48 +1000 Subject: Emit positionChanged signals whenever playback is interrupted. When stopped, paused, at the end of media, and after a seek. This prevents progress bars stopping just short of the end because the last timed progress updates was 300ms before the end of playback. --- .../mediaplayer/directshowplayercontrol.cpp | 15 +++- .../mediaplayer/directshowplayercontrol.h | 5 +- .../mediaplayer/directshowplayerservice.cpp | 88 ++++++++++++++++++---- .../mediaplayer/directshowplayerservice.h | 4 +- 4 files changed, 94 insertions(+), 18 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp index 587f4b1..b024557 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.cpp @@ -85,6 +85,7 @@ DirectShowPlayerControl::DirectShowPlayerControl(DirectShowPlayerService *servic , m_error(QMediaPlayer::NoError) , m_streamTypes(0) , m_muteVolume(-1) + , m_position(0) , m_duration(0) , m_playbackRate(0) , m_seekable(false) @@ -114,7 +115,7 @@ qint64 DirectShowPlayerControl::duration() const qint64 DirectShowPlayerControl::position() const { - return m_service->position(); + return const_cast(m_position) = m_service->position(); } void DirectShowPlayerControl::setPosition(qint64 position) @@ -289,6 +290,9 @@ void DirectShowPlayerControl::emitPropertyChanges() emit videoAvailableChanged(m_streamTypes & DirectShowPlayerService::VideoStream); } + if (properties & PositionProperty) + emit positionChanged(m_position); + if (properties & DurationProperty) emit durationChanged(m_duration); @@ -379,4 +383,13 @@ void DirectShowPlayerControl::updateError(QMediaPlayer::Error error, const QStri scheduleUpdate(ErrorProperty); } +void DirectShowPlayerControl::updatePosition(qint64 position) +{ + if (m_position != position) { + m_position = position; + + scheduleUpdate(PositionProperty); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h index 6706bab..dd25d30 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayercontrol.h @@ -102,6 +102,7 @@ public: void updatePlaybackRate(qreal rate); void updateAudioOutput(IBaseFilter *filter); void updateError(QMediaPlayer::Error error, const QString &errorString); + void updatePosition(qint64 position); protected: void customEvent(QEvent *event); @@ -115,7 +116,8 @@ private: DurationProperty = 0x08, PlaybackRateProperty = 0x10, SeekableProperty = 0x20, - ErrorProperty = 0x40 + ErrorProperty = 0x40, + PositionProperty = 0x80 }; enum Event @@ -135,6 +137,7 @@ private: QMediaPlayer::Error m_error; int m_streamTypes; int m_muteVolume; + qint64 m_position; qint64 m_duration; qreal m_playbackRate; bool m_seekable; diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp index 6e6b2f2..57f4bec 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.cpp @@ -184,6 +184,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_stream = stream; m_error = QMediaPlayer::NoError; m_errorString = QString(); + m_position = 0; m_duration = 0; m_streamTypes = 0; m_executedTasks = 0; @@ -217,6 +218,7 @@ void DirectShowPlayerService::load(const QMediaContent &media, QIODevice *stream m_playerControl->updateError(m_error, m_errorString); m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable); m_playerControl->updateState(QMediaPlayer::StoppedState); + m_playerControl->updatePosition(m_position); updateStatus(); } @@ -678,6 +680,17 @@ void DirectShowPlayerService::doPause(QMutexLocker *locker) control->Release(); if (SUCCEEDED(hr)) { + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG position = 0; + + seeking->GetCurrentPosition(&position); + seeking->Release(); + + m_position = position / 10; + } else { + m_position = 0; + } + m_executedTasks |= Pause; QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); @@ -697,23 +710,43 @@ void DirectShowPlayerService::stop() m_pendingTasks &= ~(Play | Pause | Seek); - if (m_executedTasks & Render) { - if (m_executingTask & (Play | Pause | Seek)) { - m_pendingTasks |= Stop; + if ((m_executingTask | m_executedTasks) & (Play | Pause | Seek)) { + m_pendingTasks |= Stop; + + ::SetEvent(m_taskHandle); + + m_loop->wait(&m_mutex); + } + +} - m_loop->wait(&m_mutex); +void DirectShowPlayerService::doStop(QMutexLocker *locker) +{ + if (m_executedTasks & (Play | Pause)) { + if (IMediaControl *control = com_cast(m_graph)) { + control->Stop(); + control->Release(); } - if (m_executedTasks & (Play | Pause)) { - if (IMediaControl *control = com_cast(m_graph)) { - control->Stop(); - control->Release(); - } - m_executedTasks &= ~(Play | Pause); + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG position = 0; + + seeking->GetCurrentPosition(&position); + seeking->Release(); + + m_position = position / 10; + } else { + m_position = 0; } + + m_executedTasks &= ~(Play | Pause); + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(StatusChange))); } m_executedTasks |= Stop; + + m_loop->wake(); } void DirectShowPlayerService::setRate(qreal rate) @@ -774,7 +807,9 @@ qint64 DirectShowPlayerService::position() const seeking->GetCurrentPosition(&position); seeking->Release(); - return position / 10; + const_cast(m_position) = position / 10; + + return m_position; } } return 0; @@ -835,8 +870,15 @@ void DirectShowPlayerService::doSeek(QMutexLocker *locker) &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); locker->relock(); + seeking->GetCurrentPosition(¤tPosition); + m_position = currentPosition / 10; + seeking->Release(); + } else { + m_position = 0; } + + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(PositionChange))); } int DirectShowPlayerService::bufferStatus() const @@ -1034,6 +1076,7 @@ void DirectShowPlayerService::customEvent(QEvent *event) QMutexLocker locker(&m_mutex); updateStatus(); + m_playerControl->updatePosition(m_position); } else if (event->type() == QEvent::Type(DurationChange)) { QMutexLocker locker(&m_mutex); @@ -1044,7 +1087,12 @@ void DirectShowPlayerService::customEvent(QEvent *event) if (m_atEnd) { m_playerControl->updateState(QMediaPlayer::StoppedState); m_playerControl->updateStatus(QMediaPlayer::EndOfMedia); + m_playerControl->updatePosition(m_position); } + } else if (event->type() == QEvent::Type(PositionChange)) { + QMutexLocker locker(&m_mutex); + + m_playerControl->updatePosition(m_position); } else { QMediaService::customEvent(event); } @@ -1089,6 +1137,15 @@ void DirectShowPlayerService::graphEvent(QMutexLocker *locker) m_buffering = false; m_atEnd = true; + if (IMediaSeeking *seeking = com_cast(m_graph)) { + LONGLONG position = 0; + + seeking->GetCurrentPosition(&position); + seeking->Release(); + + m_position = position / 10; + } + QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EndOfMedia))); break; case EC_LENGTH_CHANGED: @@ -1262,15 +1319,16 @@ void DirectShowPlayerService::run() m_executingTask = FinalizeLoad; doFinalizeLoad(&locker); + } else if (m_pendingTasks & Stop) { + m_pendingTasks ^= Stop; + m_executingTask = Stop; + + doStop(&locker); } else if (m_pendingTasks & SetRate) { m_pendingTasks ^= SetRate; m_executingTask = SetRate; doSetRate(&locker); - } else if (m_pendingTasks & Stop) { - m_pendingTasks ^= Stop; - - m_loop->wake(); } else if (m_pendingTasks & Pause) { m_pendingTasks ^= Pause; m_executingTask = Pause; diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h index f9d3232..a5da9a4 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowplayerservice.h @@ -126,6 +126,7 @@ private: void doSeek(QMutexLocker *locker); void doPlay(QMutexLocker *locker); void doPause(QMutexLocker *locker); + void doStop(QMutexLocker *locker); void doReleaseAudioOutput(QMutexLocker *locker); void doReleaseVideoOutput(QMutexLocker *locker); void doReleaseGraph(QMutexLocker *locker); @@ -163,7 +164,8 @@ private: Paused, DurationChange, StatusChange, - EndOfMedia + EndOfMedia, + PositionChange }; enum GraphStatus -- cgit v0.12 From 9bca64fc5eee598f97eba1052f1db250c5c7e43b Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 12 Feb 2010 16:51:32 +1000 Subject: Fix corruption of Direct Show event queue. The mutex proctecting the queue was being released and reacquired between when the head and tail are cleared, making it possible to append a new item to a popped, or even deleted tail, resulting in a lost event. --- .../mediaservices/directshow/mediaplayer/directshoweventloop.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp index 4f9a19d..07541c2 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshoweventloop.cpp @@ -148,13 +148,14 @@ void DirectShowEventLoop::processEvents() DirectShowPostedEvent *post = m_postsHead; m_postsHead = m_postsHead->next; + if (!m_postsHead) + m_postsTail = 0; + locker.unlock(); QCoreApplication::sendEvent(post->receiver, post->event); delete post; locker.relock(); } - - m_postsTail = 0; } QT_END_NAMESPACE -- cgit v0.12 From 3cc41dc8cd0c3d1e0540f3f3e975d62a4dc89e9b Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 15 Feb 2010 10:48:28 +1000 Subject: Fix hue rotation in QPainterVideoSurface. --- src/multimedia/base/qpaintervideosurface.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index 533ddee..f097db8 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -368,17 +368,17 @@ void QVideoSurfaceGLPainter::updateColors(int brightness, int contrast, int hue, const qreal cosH = qCos(M_PI * h); const qreal sinH = qSin(M_PI * h); - const qreal h11 = -0.4728 * cosH + 0.7954 * sinH + 1.4728; - const qreal h21 = -0.9253 * cosH - 0.0118 * sinH + 0.9523; - const qreal h31 = 0.4525 * cosH + 0.8072 * sinH - 0.4524; + const qreal h11 = 0.787 * cosH - 0.213 * sinH + 0.213; + const qreal h21 = -0.213 * cosH + 0.143 * sinH + 0.213; + const qreal h31 = -0.213 * cosH - 0.787 * sinH + 0.213; - const qreal h12 = 1.4728 * cosH - 1.3728 * sinH - 1.4728; - const qreal h22 = 1.9253 * cosH + 0.5891 * sinH - 0.9253; - const qreal h32 = -0.4525 * cosH - 1.9619 * sinH + 0.4525; + const qreal h12 = -0.715 * cosH - 0.715 * sinH + 0.715; + const qreal h22 = 0.285 * cosH + 0.140 * sinH + 0.715; + const qreal h32 = -0.715 * cosH + 0.715 * sinH + 0.715; - const qreal h13 = 1.4728 * cosH - 0.2181 * sinH - 1.4728; - const qreal h23 = 0.9253 * cosH + 1.1665 * sinH - 0.9253; - const qreal h33 = 0.5475 * cosH - 1.3846 * sinH + 0.4525; + const qreal h13 = -0.072 * cosH + 0.928 * sinH + 0.072; + const qreal h23 = -0.072 * cosH - 0.283 * sinH + 0.072; + const qreal h33 = 0.928 * cosH + 0.072 * sinH + 0.072; const qreal sr = (1.0 - s) * 0.3086; const qreal sg = (1.0 - s) * 0.6094; -- cgit v0.12 From ec2a1fc447112d7200a378d56cf83894cdd00653 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 15 Feb 2010 11:09:09 +1000 Subject: Extend hue rotation to a full 360 degrees. --- src/multimedia/base/qpaintervideosurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index f097db8..f451809 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -362,7 +362,7 @@ void QVideoSurfaceGLPainter::updateColors(int brightness, int contrast, int hue, { const qreal b = brightness / 200.0; const qreal c = contrast / 100.0 + 1.0; - const qreal h = hue / 200.0; + const qreal h = hue / 100.0; const qreal s = saturation / 100.0 + 1.0; const qreal cosH = qCos(M_PI * h); -- cgit v0.12 From e9c56612c633a19c8abbe9215aa46091c454846d Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 11:33:31 +1000 Subject: Use correct path for headers and source in qml.pri. --- src/multimedia/qml/qml.pri | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/multimedia/qml/qml.pri b/src/multimedia/qml/qml.pri index a30c3ad..370232e 100644 --- a/src/multimedia/qml/qml.pri +++ b/src/multimedia/qml/qml.pri @@ -4,16 +4,16 @@ contains(QT_CONFIG, declarative) { system(pkg-config --exists \'libpulse >= 0.9.10\') { DEFINES += QT_MULTIMEDIA_PULSEAUDIO - HEADERS += qsoundeffect_pulse_p.h - SOURCES += qsoundeffect_pulse_p.cpp + HEADERS += $$PWD/qsoundeffect_pulse_p.h + SOURCES += $$PWD/qsoundeffect_pulse_p.cpp LIBS += -lpulse } else:x11 { DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER - HEADERS += qsoundeffect_qmedia_p.h - SOURCES += qsoundeffect_qmedia_p.cpp + HEADERS += $$PWD/qsoundeffect_qmedia_p.h + SOURCES += $$PWD/qsoundeffect_qmedia_p.cpp } else { - HEADERS += qsoundeffect_qsound_p.h - SOURCES += qsoundeffect_qsound_p.cpp + HEADERS += $$PWD/qsoundeffect_qsound_p.h + SOURCES += $$PWD/qsoundeffect_qsound_p.cpp } HEADERS += \ -- cgit v0.12 From f58f47afb83ddeb5e3374c3089f2e602df27b48d Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 11:34:44 +1000 Subject: Use correct path for private header. --- src/multimedia/qml/qmlmediabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/qml/qmlmediabase.cpp b/src/multimedia/qml/qmlmediabase.cpp index 17be240..11b4337 100644 --- a/src/multimedia/qml/qmlmediabase.cpp +++ b/src/multimedia/qml/qmlmediabase.cpp @@ -48,7 +48,7 @@ #include #include #include -#include +#include -- cgit v0.12 From 11d3a73d43553a28cf6fae4e8741f09f419f7d90 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 11:36:27 +1000 Subject: Use correct license headers. --- src/multimedia/qml/qsoundeffect.cpp | 4 ++-- src/multimedia/qml/qsoundeffect_p.h | 4 ++-- src/multimedia/qml/qsoundeffect_pulse_p.cpp | 4 ++-- src/multimedia/qml/qsoundeffect_pulse_p.h | 4 ++-- src/multimedia/qml/qsoundeffect_qmedia_p.cpp | 4 ++-- src/multimedia/qml/qsoundeffect_qmedia_p.h | 4 ++-- src/multimedia/qml/qsoundeffect_qsound_p.cpp | 4 ++-- src/multimedia/qml/qsoundeffect_qsound_p.h | 4 ++-- src/multimedia/qml/wavedecoder_p.cpp | 4 ++-- src/multimedia/qml/wavedecoder_p.h | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/multimedia/qml/qsoundeffect.cpp b/src/multimedia/qml/qsoundeffect.cpp index 9692c89..b9174b7 100644 --- a/src/multimedia/qml/qsoundeffect.cpp +++ b/src/multimedia/qml/qsoundeffect.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_p.h b/src/multimedia/qml/qsoundeffect_p.h index de7070e..00bf64b 100644 --- a/src/multimedia/qml/qsoundeffect_p.h +++ b/src/multimedia/qml/qsoundeffect_p.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.cpp b/src/multimedia/qml/qsoundeffect_pulse_p.cpp index c16e999..6d7b222 100644 --- a/src/multimedia/qml/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/qml/qsoundeffect_pulse_p.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.h b/src/multimedia/qml/qsoundeffect_pulse_p.h index 05728d0..7e857d2 100644 --- a/src/multimedia/qml/qsoundeffect_pulse_p.h +++ b/src/multimedia/qml/qsoundeffect_pulse_p.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_qmedia_p.cpp b/src/multimedia/qml/qsoundeffect_qmedia_p.cpp index 26354a5..e5ac0d3 100644 --- a/src/multimedia/qml/qsoundeffect_qmedia_p.cpp +++ b/src/multimedia/qml/qsoundeffect_qmedia_p.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_qmedia_p.h b/src/multimedia/qml/qsoundeffect_qmedia_p.h index 8b3165a..d04c0d6 100644 --- a/src/multimedia/qml/qsoundeffect_qmedia_p.h +++ b/src/multimedia/qml/qsoundeffect_qmedia_p.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_qsound_p.cpp b/src/multimedia/qml/qsoundeffect_qsound_p.cpp index fd40a05..33f5bd4 100644 --- a/src/multimedia/qml/qsoundeffect_qsound_p.cpp +++ b/src/multimedia/qml/qsoundeffect_qsound_p.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/qsoundeffect_qsound_p.h b/src/multimedia/qml/qsoundeffect_qsound_p.h index ac47e8f..991da22 100644 --- a/src/multimedia/qml/qsoundeffect_qsound_p.h +++ b/src/multimedia/qml/qsoundeffect_qsound_p.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/wavedecoder_p.cpp b/src/multimedia/qml/wavedecoder_p.cpp index f45f25c..5fc5a96 100644 --- a/src/multimedia/qml/wavedecoder_p.cpp +++ b/src/multimedia/qml/wavedecoder_p.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/qml/wavedecoder_p.h b/src/multimedia/qml/wavedecoder_p.h index 010fec6..70b485c 100644 --- a/src/multimedia/qml/wavedecoder_p.h +++ b/src/multimedia/qml/wavedecoder_p.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage -- cgit v0.12 From 215608a69f3ff889b75df600a2f9fbfbe850e430 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 11:38:02 +1000 Subject: Cleanup include files. --- src/multimedia/qml/qsoundeffect_p.h | 14 ++++++++++++-- src/multimedia/qml/qsoundeffect_pulse_p.h | 18 +++++++++++------- src/multimedia/qml/qsoundeffect_qmedia_p.h | 12 ++++++++---- src/multimedia/qml/qsoundeffect_qsound_p.h | 11 ++++++++--- src/multimedia/qml/wavedecoder_p.h | 12 +++++++++++- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/multimedia/qml/qsoundeffect_p.h b/src/multimedia/qml/qsoundeffect_p.h index 00bf64b..6d5790d 100644 --- a/src/multimedia/qml/qsoundeffect_p.h +++ b/src/multimedia/qml/qsoundeffect_p.h @@ -56,7 +56,12 @@ #include #include -#include +#include + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE class QSoundEffectPrivate; class QSoundEffect : public QObject @@ -111,6 +116,11 @@ private: QSoundEffectPrivate* d; }; -QML_DECLARE_TYPE(QSoundEffect) +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QSoundEffect)) + +QT_END_HEADER + #endif // QSOUNDEFFECT_H diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.h b/src/multimedia/qml/qsoundeffect_pulse_p.h index 7e857d2..155d7fc 100644 --- a/src/multimedia/qml/qsoundeffect_pulse_p.h +++ b/src/multimedia/qml/qsoundeffect_pulse_p.h @@ -54,17 +54,17 @@ // -#include - -#include - -#include - #include "qsoundeffect_p.h" +#include +#include +#include #include -QTM_USE_NAMESPACE + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE class QNetworkReply; class QNetworkAccessManager; @@ -131,4 +131,8 @@ private: QNetworkAccessManager *m_networkAccessManager; }; +QT_END_NAMESPACE + +QT_END_HEADER + #endif // QSOUNDEFFECT_PULSE_H diff --git a/src/multimedia/qml/qsoundeffect_qmedia_p.h b/src/multimedia/qml/qsoundeffect_qmedia_p.h index d04c0d6..e17d720 100644 --- a/src/multimedia/qml/qsoundeffect_qmedia_p.h +++ b/src/multimedia/qml/qsoundeffect_qmedia_p.h @@ -56,13 +56,13 @@ #include #include +#include +#include "qsoundeffect_p.h" -#include -#include -#include "qsoundeffect_p.h" +QT_BEGIN_HEADER -QTM_USE_NAMESPACE +QT_BEGIN_NAMESPACE class WaveDecoder; @@ -102,4 +102,8 @@ private: QMediaPlayer *m_player; }; +QT_END_NAMESPACE + +QT_END_HEADER + #endif // QSOUNDEFFECT_QMEDIA_H diff --git a/src/multimedia/qml/qsoundeffect_qsound_p.h b/src/multimedia/qml/qsoundeffect_qsound_p.h index 991da22..45c0888 100644 --- a/src/multimedia/qml/qsoundeffect_qsound_p.h +++ b/src/multimedia/qml/qsoundeffect_qsound_p.h @@ -56,13 +56,14 @@ #include #include - -#include +#include #include "qsoundeffect_p.h" -QTM_USE_NAMESPACE +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE class QTimer; class QSound; @@ -121,4 +122,8 @@ private: QTimer *m_timer; }; +QT_END_NAMESPACE + +QT_END_HEADER + #endif // QSOUNDEFFECT_QSOUND_H diff --git a/src/multimedia/qml/wavedecoder_p.h b/src/multimedia/qml/wavedecoder_p.h index 70b485c..3bcd90d 100644 --- a/src/multimedia/qml/wavedecoder_p.h +++ b/src/multimedia/qml/wavedecoder_p.h @@ -45,9 +45,15 @@ #include #include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + class WaveDecoder : public QIODevice { -Q_OBJECT + Q_OBJECT public: explicit WaveDecoder(QIODevice *source, QObject *parent = 0); @@ -110,4 +116,8 @@ private: CombinedHeader header; }; +QT_END_NAMESPACE + +QT_END_HEADER + #endif // WAVEDECODER_H -- cgit v0.12 From a0839595a5738b4c9b3f2e80a8265df885d8d80c Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 15 Feb 2010 11:48:25 +1000 Subject: Fix flickering when items are overlaid on QGraphicsVideoItem. Re-enable scissor and stencil tests so the texture frame is clipped correctly. Otherwise when an overlaid item is updated the entire frame will be redrawn not just the part intersecting the updated item, resulting in other items being drawn over. --- src/multimedia/base/qgraphicsvideoitem.cpp | 6 +----- src/multimedia/base/qpaintervideosurface.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp index 8aba269..85369db 100644 --- a/src/multimedia/base/qgraphicsvideoitem.cpp +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -47,7 +47,7 @@ #include #include #include - +#include QT_BEGIN_NAMESPACE @@ -384,9 +384,6 @@ void QGraphicsVideoItem::paint( if (d->surface && d->surface->isActive()) { d->surface->paint(painter, d->boundingRect, d->sourceRect); d->surface->setReady(true); -#ifndef QGRAPHICSVIDEOITEM_SHADERS // Flickers - } -#else } else if (d->updatePaintDevice && (painter->paintEngine()->type() == QPaintEngine::OpenGL || painter->paintEngine()->type() == QPaintEngine::OpenGL2)) { d->updatePaintDevice = false; @@ -398,7 +395,6 @@ void QGraphicsVideoItem::paint( d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader); } } -#endif } /*! diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index f451809..f7ffb02 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -982,6 +982,9 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( if (m_frame.isValid()) { painter->beginNativePainting(); + glEnable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + const int width = QGLContext::currentContext()->device()->width(); const int height = QGLContext::currentContext()->device()->height(); @@ -1072,6 +1075,9 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::paint( m_program.release(); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_STENCIL_TEST); painter->endNativePainting(); } return QAbstractVideoSurface::NoError; -- cgit v0.12 From 24c116deb1459b2f20aa724e092c0232e9902461 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 16:21:48 +1000 Subject: Add missing QT_MODULE to header. --- src/multimedia/base/qgraphicsvideoitem.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/multimedia/base/qgraphicsvideoitem.h b/src/multimedia/base/qgraphicsvideoitem.h index 06f471f..c339606 100644 --- a/src/multimedia/base/qgraphicsvideoitem.h +++ b/src/multimedia/base/qgraphicsvideoitem.h @@ -51,6 +51,8 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +QT_MODULE(Multimedia) + class QVideoSurfaceFormat; class QGraphicsVideoItemPrivate; -- cgit v0.12 From 1679980392e9784bf0c0d321d541aee6efeaba15 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 16:25:06 +1000 Subject: Express dependencies for QtMultimedia. --- src/src.pro | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/src.pro b/src/src.pro index f2070ae..2b9dc30 100644 --- a/src/src.pro +++ b/src/src.pro @@ -19,7 +19,6 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, o contains(QT_CONFIG, openvg): SRC_SUBDIRS += src_openvg contains(QT_CONFIG, xmlpatterns): SRC_SUBDIRS += src_xmlpatterns contains(QT_CONFIG, phonon): SRC_SUBDIRS += src_phonon -contains(QT_CONFIG, multimedia): SRC_SUBDIRS += src_multimedia contains(QT_CONFIG, svg): SRC_SUBDIRS += src_svg contains(QT_CONFIG, webkit) { #exists($$QT_SOURCE_TREE/src/3rdparty/webkit/JavaScriptCore/JavaScriptCore.pro): SRC_SUBDIRS += src_javascriptcore @@ -28,6 +27,7 @@ contains(QT_CONFIG, webkit) { contains(QT_CONFIG, script): SRC_SUBDIRS += src_script contains(QT_CONFIG, scripttools): SRC_SUBDIRS += src_scripttools contains(QT_CONFIG, declarative): SRC_SUBDIRS += src_declarative +contains(QT_CONFIG, multimedia): SRC_SUBDIRS += src_multimedia SRC_SUBDIRS += src_plugins src_s60main.subdir = $$QT_SOURCE_TREE/src/s60main @@ -102,7 +102,7 @@ src_declarative.target = sub-declarative src_multimedia.depends = src_gui src_tools_activeqt.depends = src_tools_idc src_gui src_declarative.depends = src_xml src_gui src_script src_network src_svg - src_plugins.depends = src_gui src_sql src_svg + src_plugins.depends = src_gui src_sql src_svg src_multimedia contains(QT_CONFIG, webkit) { src_webkit.depends = src_gui src_sql src_network src_xml contains(QT_CONFIG, phonon):src_webkit.depends += src_phonon @@ -116,6 +116,7 @@ src_declarative.target = sub-declarative src_phonon.depends += src_dbus } contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): src_plugins.depends += src_opengl + contains(QT_CONFIG, declarative): src_multimedia.depends += src_declarative } !symbian { -- cgit v0.12 From e486ec3b4730d470033a0a88b1cc56bc98d8d00e Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Mon, 15 Feb 2010 16:27:42 +1000 Subject: Revert "Added Q_WS_MAEMO_5 to mkspec file." Defined elsewhere. This reverts commit abf04def344aeb14dbb8539ba73fb5de26237bcc. --- mkspecs/linux-g++-maemo/qmake.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/mkspecs/linux-g++-maemo/qmake.conf b/mkspecs/linux-g++-maemo/qmake.conf index e586ed0..38c26a6 100644 --- a/mkspecs/linux-g++-maemo/qmake.conf +++ b/mkspecs/linux-g++-maemo/qmake.conf @@ -32,6 +32,4 @@ DEFINES += QT_GL_NO_SCISSOR_TEST # Work round SGX 1.4 driver bug (text corrupted), modify glyph cache width: DEFINES += QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH=1024 -DEFINES += Q_WS_MAEMO_5 - load(qt_config) -- cgit v0.12 From 2d264a80f9fc759e979dfe2583425cb419688a70 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 16 Feb 2010 10:56:47 +1000 Subject: Exclude OpenGL from QGraphicsVideoItem if Qt doesn't include QtOpenGL. --- src/multimedia/base/qgraphicsvideoitem.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp index 85369db..21ba8c9 100644 --- a/src/multimedia/base/qgraphicsvideoitem.cpp +++ b/src/multimedia/base/qgraphicsvideoitem.cpp @@ -47,7 +47,10 @@ #include #include #include + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) #include +#endif QT_BEGIN_NAMESPACE @@ -384,6 +387,7 @@ void QGraphicsVideoItem::paint( if (d->surface && d->surface->isActive()) { d->surface->paint(painter, d->boundingRect, d->sourceRect); d->surface->setReady(true); +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1) } else if (d->updatePaintDevice && (painter->paintEngine()->type() == QPaintEngine::OpenGL || painter->paintEngine()->type() == QPaintEngine::OpenGL2)) { d->updatePaintDevice = false; @@ -394,6 +398,7 @@ void QGraphicsVideoItem::paint( } else { d->surface->setShaderType(QPainterVideoSurface::FragmentProgramShader); } +#endif } } -- cgit v0.12 From 4374a796e1986b0b7f50256aefce4e9859fc4703 Mon Sep 17 00:00:00 2001 From: Nicholas Young Date: Tue, 16 Feb 2010 12:13:41 +1000 Subject: Always pass encoded URLs to GStreamer. Fixes issue with spaces in filenames. --- .../mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 355df2f..6945c2a 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -116,7 +116,7 @@ void QGstreamerPlayerSession::load(const QUrl &url) m_tags.clear(); emit tagsChanged(); - g_object_set(G_OBJECT(m_playbin), "uri", m_url.toString().toLocal8Bit().constData(), NULL); + g_object_set(G_OBJECT(m_playbin), "uri", m_url.toEncoded().constData(), NULL); // if (!m_streamTypes.isEmpty()) { // m_streamProperties.clear(); -- cgit v0.12 From 2f29860320796ad6f94f51daf6af84515c288ec8 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Tue, 16 Feb 2010 12:33:05 +1000 Subject: Fixed compile error in pulseaudio soundeffect implementation --- src/multimedia/qml/qsoundeffect_pulse_p.cpp | 4 ++-- src/multimedia/qml/qsoundeffect_pulse_p.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.cpp b/src/multimedia/qml/qsoundeffect_pulse_p.cpp index 6d7b222..b1e5982 100644 --- a/src/multimedia/qml/qsoundeffect_pulse_p.cpp +++ b/src/multimedia/qml/qsoundeffect_pulse_p.cpp @@ -151,7 +151,7 @@ private: m_mainLoopApi = pa_threaded_mainloop_get_api(m_mainLoop); lock(); - m_context = pa_context_new(m_mainLoopApi, QString("QtPulseAudio:%1").arg(::getpid()).toAscii().constData()); + m_context = pa_context_new(m_mainLoopApi, QString(QLatin1String("QtPulseAudio:%1")).arg(::getpid()).toAscii().constData()); #if(Q_WS_MAEMO_5) pa_context_set_state_callback(m_context, context_state_callback, this); @@ -362,7 +362,7 @@ void QSoundEffectPrivate::decoderReady() } if (m_name.isNull()) - m_name = QString("QtPulseSample-%1-%2").arg(::getpid()).arg(int(this)).toUtf8(); + m_name = QString(QLatin1String("QtPulseSample-%1-%2")).arg(::getpid()).arg(int(this)).toUtf8(); pa_sample_spec spec = audioFormatToSampleSpec(m_waveDecoder->audioFormat()); diff --git a/src/multimedia/qml/qsoundeffect_pulse_p.h b/src/multimedia/qml/qsoundeffect_pulse_p.h index 155d7fc..58a05d2 100644 --- a/src/multimedia/qml/qsoundeffect_pulse_p.h +++ b/src/multimedia/qml/qsoundeffect_pulse_p.h @@ -57,7 +57,7 @@ #include "qsoundeffect_p.h" #include -#include +#include #include #include -- cgit v0.12 From 78967c9f7cfba6142a5f987a1fe81692b479a6d2 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Tue, 16 Feb 2010 12:33:26 +1000 Subject: Added multimedia to qmlviewer --- tools/qmlviewer/qmlviewer.pro | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro index 35e4ba8..003115d 100644 --- a/tools/qmlviewer/qmlviewer.pro +++ b/tools/qmlviewer/qmlviewer.pro @@ -7,6 +7,10 @@ QT += declarative \ network \ sql +contains(QT_CONFIG, multimedia) { + QT += multimedia +} + contains(QT_CONFIG, opengl) { QT += opengl DEFINES += GL_SUPPORTED -- cgit v0.12 From a7f6af9817771b8211433c8cf24fe7150c5b7bf5 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 16 Feb 2010 14:26:14 +1000 Subject: Don't paint RGB24 frames as BGR24. A non-swizzling shader was being used for RGB24. This looked correct on linux because the gstreamer backend was misidentifying BGR24 as RGB24. And since BGR is supported include it in the list of supported formats. --- src/multimedia/base/qpaintervideosurface.cpp | 26 ++++++++++++++++++++++ .../gstreamer/qvideosurfacegstsink.cpp | 5 ++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index f7ffb02..58d7412 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -579,8 +579,10 @@ QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context) m_imagePixelFormats << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_BGR32 << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB24 + << QVideoFrame::Format_BGR24 << QVideoFrame::Format_RGB565 << QVideoFrame::Format_YV12 << QVideoFrame::Format_YUV420P; @@ -605,6 +607,10 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); program = qt_arbfp_xrgbShaderProgram; break; + case QVideoFrame::Format_BGR32: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_rgbShaderProgram; + break; case QVideoFrame::Format_ARGB32: initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); program = qt_arbfp_argbShaderProgram; @@ -613,6 +619,10 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); program = qt_arbfp_argbShaderProgram; break; + case QVideoFrame::Format_BGR24: + initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_rgbShaderProgram; + break; case QVideoFrame::Format_RGB565: initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize()); program = qt_arbfp_rgbShaderProgram; @@ -706,6 +716,9 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint( if (m_frame.isValid()) { painter->beginNativePainting(); + glEnable(GL_STENCIL_TEST); + glEnable(GL_SCISSOR_TEST); + const float txLeft = source.left() / m_frameSize.width(); const float txRight = source.right() / m_frameSize.width(); const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom @@ -779,6 +792,9 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::paint( glDisableClientState(GL_VERTEX_ARRAY); glDisable(GL_FRAGMENT_PROGRAM_ARB); + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + painter->endNativePainting(); } return QAbstractVideoSurface::NoError; @@ -872,9 +888,11 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context) { m_imagePixelFormats << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_BGR32 << QVideoFrame::Format_ARGB32 #ifndef QT_OPENGL_ES << QVideoFrame::Format_RGB24 + << QVideoFrame::Format_BGR24 #endif << QVideoFrame::Format_RGB565 << QVideoFrame::Format_YV12 @@ -900,6 +918,10 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); fragmentProgram = qt_glsl_xrgbShaderProgram; break; + case QVideoFrame::Format_BGR32: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_rgbShaderProgram; + break; case QVideoFrame::Format_ARGB32: initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); fragmentProgram = qt_glsl_argbShaderProgram; @@ -907,6 +929,10 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface #ifndef QT_OPENGL_ES case QVideoFrame::Format_RGB24: initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_argbShaderProgram; + break; + case QVideoFrame::Format_BGR24: + initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); fragmentProgram = qt_glsl_rgbShaderProgram; break; #endif diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index 8c61846..3108e1a 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -268,9 +268,12 @@ static const RgbFormat qt_rgbColorLookup[] = { { QVideoFrame::Format_RGB32 , 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, { QVideoFrame::Format_RGB32 , 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { QVideoFrame::Format_BGR32 , 32, 24, 4321, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, + { QVideoFrame::Format_BGR32 , 32, 24, 1234, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, - { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, + { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 } }; -- cgit v0.12 From 65f63b1151378606a482a9df471d5b1a54ace69a Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 16 Feb 2010 15:22:04 +1000 Subject: Extend the mappings between Direct Show and QVideoFrame color formats. --- .../directshow/mediaplayer/directshowmediatype.cpp | 35 +++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp index 8edf93e..b60a903 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp @@ -54,9 +54,20 @@ namespace static const TypeLookup qt_typeLookup[] = { - { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, { QVideoFrame::Format_RGB32, MEDIASUBTYPE_RGB32 }, - { QVideoFrame::Format_YV12, MEDIASUBTYPE_YV12 } + { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, + { QVideoFrame::Format_RGB565, MEDIASUBTYPE_RGB565 }, + { QVideoFrame::Format_RGB555, MEDIASUBTYPE_RGB555 }, + { QVideoFrame::Format_AYUV444, MEDIASUBTYPE_AYUV }, + { QVideoFrame::Format_YUYV, MEDIASUBTYPE_YUY2 }, + { QVideoFrame::Format_UYVY, MEDIASUBTYPE_UYVY }, + { QVideoFrame::Format_IMC1, MEDIASUBTYPE_IMC1 }, + { QVideoFrame::Format_IMC2, MEDIASUBTYPE_IMC2 }, + { QVideoFrame::Format_IMC3, MEDIASUBTYPE_IMC3 }, + { QVideoFrame::Format_IMC4, MEDIASUBTYPE_IMC4 }, + { QVideoFrame::Format_YV12, MEDIASUBTYPE_YV12 }, + { QVideoFrame::Format_NV12, MEDIASUBTYPE_NV12 }, + { QVideoFrame::Format_YUV420P, MEDIASUBTYPE_IYUV } }; } @@ -144,11 +155,27 @@ QVideoSurfaceFormat DirectShowMediaType::formatFromType(const AM_MEDIA_TYPE &typ int DirectShowMediaType::bytesPerLine(const QVideoSurfaceFormat &format) { switch (format.pixelFormat()) { - case QVideoFrame::Format_RGB24: - return format.frameWidth() * 4 + 3 - format.frameWidth() % 4; + // 32 bpp packed formats. case QVideoFrame::Format_RGB32: + case QVideoFrame::Format_AYUV444: return format.frameWidth() * 4; + // 24 bpp packed formats. + case QVideoFrame::Format_RGB24: + return format.frameWidth() * 3 + 3 - format.frameWidth() % 4; + // 16 bpp packed formats. + case QVideoFrame::Format_RGB565: + case QVideoFrame::Format_RGB555: + case QVideoFrame::Format_YUYV: + case QVideoFrame::Format_UYVY: + return format.frameWidth() * 2 + 3 - format.frameWidth() % 4; + // Planar formats. + case QVideoFrame::Format_IMC1: + case QVideoFrame::Format_IMC2: + case QVideoFrame::Format_IMC3: + case QVideoFrame::Format_IMC4: case QVideoFrame::Format_YV12: + case QVideoFrame::Format_NV12: + case QVideoFrame::Format_YUV420P: return format.frameWidth() + 3 - format.frameWidth() % 4; default: return 0; -- cgit v0.12 From afae8c9f9f62b59c148718ab9ec1bbafc4bb4170 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 10:46:04 +1000 Subject: Remove unused files. --- src/plugins/mediaservices/gstreamer/gstreamer.pro | 2 - .../gstreamer/mediaplayer/mediaplayer.pri | 2 - .../mediaplayer/qgstreamerstreamscontrol.cpp | 89 ----------- .../mediaplayer/qgstreamerstreamscontrol.h | 71 --------- .../qgstreameraudioinputendpointselector.cpp | 172 --------------------- .../qgstreameraudioinputendpointselector.h | 83 ---------- 6 files changed, 419 deletions(-) delete mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp delete mode 100644 src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h delete mode 100644 src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp delete mode 100644 src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h diff --git a/src/plugins/mediaservices/gstreamer/gstreamer.pro b/src/plugins/mediaservices/gstreamer/gstreamer.pro index 5a16f03..db0ee4e 100644 --- a/src/plugins/mediaservices/gstreamer/gstreamer.pro +++ b/src/plugins/mediaservices/gstreamer/gstreamer.pro @@ -27,7 +27,6 @@ HEADERS += \ qgstreamervideorendererinterface.h \ qgstreamervideowidget.h \ qgstreamerserviceplugin.h \ -# qgstreameraudioinputendpointselector.h \ qgstreamervideoinputdevicecontrol.h \ qgstreamervideooverlay.h \ qgstreamervideorenderer.h \ @@ -44,7 +43,6 @@ SOURCES += \ qgstreamervideorendererinterface.cpp \ qgstreamervideowidget.cpp \ qgstreamerserviceplugin.cpp \ -# qgstreameraudioinputendpointselector.cpp \ qgstreamervideoinputdevicecontrol.cpp \ qgstreamervideooverlay.cpp \ qgstreamervideorenderer.cpp \ diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri b/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri index dda641c..19ff034 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/mediaplayer.pri @@ -6,14 +6,12 @@ HEADERS += \ $$PWD/qgstreamerplayercontrol.h \ $$PWD/qgstreamerplayerservice.h \ $$PWD/qgstreamerplayersession.h \ -# $$PWD/qgstreamerstreamscontrol.h \ $$PWD/qgstreamermetadataprovider.h SOURCES += \ $$PWD/qgstreamerplayercontrol.cpp \ $$PWD/qgstreamerplayerservice.cpp \ $$PWD/qgstreamerplayersession.cpp \ -# $$PWD/qgstreamerstreamscontrol.cpp \ $$PWD/qgstreamermetadataprovider.cpp diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp deleted file mode 100644 index 22c0b95..0000000 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgstreamerstreamscontrol.h" -#include "qgstreamerplayersession.h" - -QGstreamerStreamsControl::QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent) - :QMediaStreamsControl(parent), m_session(session) -{ - connect(m_session, SIGNAL(streamsChanged()), SIGNAL(streamsChanged())); -} - -QGstreamerStreamsControl::~QGstreamerStreamsControl() -{ -} - -int QGstreamerStreamsControl::streamCount() -{ - return m_session->streamCount(); -} - -QMediaStreamsControl::StreamType QGstreamerStreamsControl::streamType(int streamNumber) -{ - return m_session->streamType(streamNumber); -} - -QVariant QGstreamerStreamsControl::metaData(int streamNumber, QtMedia::MetaData key) -{ - return m_session->streamProperties(streamNumber).value(key); -} - -bool QGstreamerStreamsControl::isActive(int streamNumber) -{ - return streamNumber != -1 && streamNumber == m_session->activeStream(streamType(streamNumber)); -} - -void QGstreamerStreamsControl::setActive(int streamNumber, bool state) -{ - QMediaStreamsControl::StreamType type = m_session->streamType(streamNumber); - if (type == QMediaStreamsControl::UnknownStream) - return; - - if (state) - m_session->setActiveStream(type, streamNumber); - else { - //only one active stream of certain type is supported - if (m_session->activeStream(type) == streamNumber) - m_session->setActiveStream(type, -1); - } -} - diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h deleted file mode 100644 index c115bce..0000000 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerstreamscontrol.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGSTREAMERSTREAMSCONTROL_H -#define QGSTREAMERSTREAMSCONTROL_H - -#include - -QTM_USE_NAMESPACE - -class QGstreamerPlayerSession; - -class QGstreamerStreamsControl : public QMediaStreamsControl -{ - Q_OBJECT -public: - QGstreamerStreamsControl(QGstreamerPlayerSession *session, QObject *parent); - virtual ~QGstreamerStreamsControl(); - - virtual int streamCount(); - virtual StreamType streamType(int streamNumber); - - virtual QVariant metaData(int streamNumber, QtMedia::MetaData key); - - virtual bool isActive(int streamNumber); - virtual void setActive(int streamNumber, bool state); - -private: - QGstreamerPlayerSession *m_session; -}; - -#endif // QGSTREAMERSTREAMSCONTROL_H - diff --git a/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp b/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp deleted file mode 100644 index ce6ab30..0000000 --- a/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgstreameraudioinputendpointselector.h" - -#include -#include -#include - -#include - -#ifdef HAVE_ALSA -#include -#endif - -QGstreamerAudioInputEndpointSelector::QGstreamerAudioInputEndpointSelector(QObject *parent) - :QAudioEndpointSelector(parent) -{ - update(); -} - -QGstreamerAudioInputEndpointSelector::~QGstreamerAudioInputEndpointSelector() -{ -} - -QList QGstreamerAudioInputEndpointSelector::availableEndpoints() const -{ - return m_names; -} - -QString QGstreamerAudioInputEndpointSelector::endpointDescription(const QString& name) const -{ - QString desc; - - for (int i = 0; i < m_names.size(); i++) { - if (m_names.at(i).compare(name) == 0) { - desc = m_descriptions.at(i); - break; - } - } - return desc; -} - -QString QGstreamerAudioInputEndpointSelector::defaultEndpoint() const -{ - if (m_names.size() > 0) - return m_names.at(0); - - return QString(); -} - -QString QGstreamerAudioInputEndpointSelector::activeEndpoint() const -{ - return m_audioInput; -} - -void QGstreamerAudioInputEndpointSelector::setActiveEndpoint(const QString& name) -{ - if (m_audioInput.compare(name) != 0) { - m_audioInput = name; - emit activeEndpointChanged(name); - } -} - -void QGstreamerAudioInputEndpointSelector::update() -{ - m_names.clear(); - m_descriptions.clear(); - updateAlsaDevices(); - updateOssDevices(); - updatePulseDevices(); - if (m_names.size() > 0) - m_audioInput = m_names.at(0); -} - -void QGstreamerAudioInputEndpointSelector::updateAlsaDevices() -{ -#ifdef HAVE_ALSA - void **hints, **n; - if (snd_device_name_hint(-1, "pcm", &hints) < 0) { - qWarning()<<"no alsa devices available"; - return; - } - n = hints; - - while (*n != NULL) { - char *name = snd_device_name_get_hint(*n, "NAME"); - char *descr = snd_device_name_get_hint(*n, "DESC"); - char *io = snd_device_name_get_hint(*n, "IOID"); - - if ((name != NULL) && (descr != NULL)) { - if ( io == NULL || qstrcmp(io,"Input") == 0 ) { - m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name)); - m_descriptions.append(QString::fromUtf8(descr)); - } - } - - if (name != NULL) - free(name); - if (descr != NULL) - free(descr); - if (io != NULL) - free(io); - n++; - } - snd_device_name_free_hint(hints); -#endif -} - -void QGstreamerAudioInputEndpointSelector::updateOssDevices() -{ - QDir devDir("/dev"); - devDir.setFilter(QDir::System); -#ifndef QT_QWS_N810 - QFileInfoList entries = devDir.entryInfoList(QStringList() << "dsp*"); - foreach(const QFileInfo& entryInfo, entries) { - m_names.append(QLatin1String("oss:")+entryInfo.filePath()); - m_descriptions.append(QString("OSS device %1").arg(entryInfo.fileName())); - } -#else - m_names.append("dsppcm"); - m_descriptions.append("PCM audio input"); -#endif -} - -void QGstreamerAudioInputEndpointSelector::updatePulseDevices() -{ - GstElementFactory *factory = gst_element_factory_find("pulsesrc"); - if (factory) { - m_names.append("pulseaudio:"); - m_descriptions.append("PulseAudio device."); - gst_object_unref(GST_OBJECT(factory)); - } -} diff --git a/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h b/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h deleted file mode 100644 index 9b15939..0000000 --- a/src/plugins/mediaservices/gstreamer/qgstreameraudioinputendpointselector.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** 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$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H -#define QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H - -#include -#include - - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QGstreamerAudioInputEndpointSelector : public QAudioEndpointSelector -{ -Q_OBJECT -public: - QGstreamerAudioInputEndpointSelector(QObject *parent); - ~QGstreamerAudioInputEndpointSelector(); - - QList availableEndpoints() const; - QString endpointDescription(const QString& name) const; - QString defaultEndpoint() const; - QString activeEndpoint() const; - -public Q_SLOTS: - void setActiveEndpoint(const QString& name); - -private: - void update(); - void updateAlsaDevices(); - void updateOssDevices(); - void updatePulseDevices(); - - QString m_audioInput; - QList m_names; - QList m_descriptions; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGSTREAMERAUDIOINPUTENDPOINTSELECTOR_H -- cgit v0.12 From 2a1ac3d80411054651880b6887f8db5f77bc7cb9 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 10:48:49 +1000 Subject: Fix license headers. --- src/multimedia/base/qmediatimerange.cpp | 4 ++-- src/multimedia/base/qmediatimerange.h | 4 ++-- tests/auto/qmediacontent/tst_qmediacontent.cpp | 4 ++-- tests/auto/qmediaobject/tst_qmediaobject.cpp | 4 ++-- tests/auto/qmediaplayer/tst_qmediaplayer.cpp | 4 ++-- tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp | 4 ++-- tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp | 4 ++-- tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp | 4 ++-- tests/auto/qmediaresource/tst_qmediaresource.cpp | 4 ++-- tests/auto/qmediaservice/tst_qmediaservice.cpp | 4 ++-- tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp | 4 ++-- tests/auto/qmediatimerange/tst_qmediatimerange.cpp | 4 ++-- tests/auto/qvideowidget/tst_qvideowidget.cpp | 4 ++-- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/multimedia/base/qmediatimerange.cpp b/src/multimedia/base/qmediatimerange.cpp index 38a8aea..0ca1948 100644 --- a/src/multimedia/base/qmediatimerange.cpp +++ b/src/multimedia/base/qmediatimerange.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/multimedia/base/qmediatimerange.h b/src/multimedia/base/qmediatimerange.h index d065368..a65629e 100644 --- a/src/multimedia/base/qmediatimerange.h +++ b/src/multimedia/base/qmediatimerange.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the QtMultimedia module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediacontent/tst_qmediacontent.cpp b/tests/auto/qmediacontent/tst_qmediacontent.cpp index 4857672..35dd0a9 100644 --- a/tests/auto/qmediacontent/tst_qmediacontent.cpp +++ b/tests/auto/qmediacontent/tst_qmediacontent.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaobject/tst_qmediaobject.cpp b/tests/auto/qmediaobject/tst_qmediaobject.cpp index 0370fff..1dbb2c1 100644 --- a/tests/auto/qmediaobject/tst_qmediaobject.cpp +++ b/tests/auto/qmediaobject/tst_qmediaobject.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp index a3cba3f..7f3cb3a 100644 --- a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp +++ b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp index 88a2f31..07971ca 100644 --- a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp +++ b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp index a5eb3fe..9130db0 100644 --- a/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp +++ b/tests/auto/qmediaplaylistnavigator/tst_qmediaplaylistnavigator.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp index 1ed23a0..0d35b05 100644 --- a/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp +++ b/tests/auto/qmediapluginloader/tst_qmediapluginloader.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaresource/tst_qmediaresource.cpp b/tests/auto/qmediaresource/tst_qmediaresource.cpp index 127144d..546c415 100644 --- a/tests/auto/qmediaresource/tst_qmediaresource.cpp +++ b/tests/auto/qmediaresource/tst_qmediaresource.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaservice/tst_qmediaservice.cpp b/tests/auto/qmediaservice/tst_qmediaservice.cpp index 3c3684a..35f661d 100644 --- a/tests/auto/qmediaservice/tst_qmediaservice.cpp +++ b/tests/auto/qmediaservice/tst_qmediaservice.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp index a2c1be5..204ed14 100644 --- a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp +++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qmediatimerange/tst_qmediatimerange.cpp b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp index a8c58db..54de3f1 100644 --- a/tests/auto/qmediatimerange/tst_qmediatimerange.cpp +++ b/tests/auto/qmediatimerange/tst_qmediatimerange.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/tests/auto/qvideowidget/tst_qvideowidget.cpp b/tests/auto/qvideowidget/tst_qvideowidget.cpp index e30d16b..9da4b9e 100644 --- a/tests/auto/qvideowidget/tst_qvideowidget.cpp +++ b/tests/auto/qvideowidget/tst_qvideowidget.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** 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. +** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage -- cgit v0.12 From 44a52d6667de0230f8c23e1b32bb4d53c831a27f Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 10:49:40 +1000 Subject: Add qmlaudio test to auto.pro --- tests/auto/auto.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 4eda172..e47d95c 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -311,6 +311,7 @@ SUBDIRS += \ qmediaserviceprovider \ qmediatimerange \ qvideowidget \ + qmlaudio \ qspinbox \ qsplitter \ qsql \ -- cgit v0.12 From de18d264f1ed0cde99fcc0482c55e2999497ce7a Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 17 Feb 2010 10:57:50 +1000 Subject: Support YUV444 formats in QPainterVideoSurface. --- src/multimedia/base/qpaintervideosurface.cpp | 76 +++++++++++++++++++++- .../gstreamer/qvideosurfacegstsink.cpp | 3 +- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index 58d7412..dcc81d9 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -531,6 +531,32 @@ static const char *qt_arbfp_yuvPlanarShaderProgram = "DP4 result.color.z, yuv, matrix[2];\n" "END"; +// Paints a YUV444 frame. +static const char *qt_arbfp_xyuvShaderProgram = + "!!ARBfp1.0\n" + "PARAM matrix[4] = { program.local[0..2]," + "{ 0.0, 0.0, 0.0, 1.0 } };\n" + "TEMP ayuv;\n" + "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n" + "MOV ayuv.x, matrix[3].w;\n" + "DP4 result.color.x, ayuv.yzwx, matrix[0];\n" + "DP4 result.color.y, ayuv.yzwx, matrix[1];\n" + "DP4 result.color.z, ayuv.yzwx, matrix[2];\n" + "END"; + +// Paints a AYUV444 frame. +static const char *qt_arbfp_ayuvShaderProgram = + "!!ARBfp1.0\n" + "PARAM matrix[4] = { program.local[0..2]," + "{ 0.0, 0.0, 0.0, 1.0 } };\n" + "TEMP ayuv;\n" + "TEX ayuv, fragment.texcoord[0], texture[0], 2D;\n" + "MOV ayuv.x, matrix[3].w;\n" + "DP4 result.color.x, ayuv.yzwx, matrix[0];\n" + "DP4 result.color.y, ayuv.yzwx, matrix[1];\n" + "DP4 result.color.z, ayuv.yzwx, matrix[2];\n" + "TEX result.color.w, fragment.texcoord[0], texture, 2D;\n" + "END"; class QVideoSurfaceArbFpPainter : public QVideoSurfaceGLPainter { @@ -584,6 +610,8 @@ QVideoSurfaceArbFpPainter::QVideoSurfaceArbFpPainter(QGLContext *context) << QVideoFrame::Format_RGB24 << QVideoFrame::Format_BGR24 << QVideoFrame::Format_RGB565 + << QVideoFrame::Format_AYUV444 + << QVideoFrame::Format_YUV444 << QVideoFrame::Format_YV12 << QVideoFrame::Format_YUV420P; m_glPixelFormats @@ -617,7 +645,7 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac break; case QVideoFrame::Format_RGB24: initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); - program = qt_arbfp_argbShaderProgram; + program = qt_arbfp_xrgbShaderProgram; break; case QVideoFrame::Format_BGR24: initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); @@ -627,6 +655,16 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize()); program = qt_arbfp_rgbShaderProgram; break; + case QVideoFrame::Format_YUV444: + initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_xyuvShaderProgram; + m_yuv = true; + break; + case QVideoFrame::Format_AYUV444: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + program = qt_arbfp_ayuvShaderProgram; + m_yuv = true; + break; case QVideoFrame::Format_YV12: initYv12TextureInfo(format.frameSize()); program = qt_arbfp_yuvPlanarShaderProgram; @@ -865,6 +903,28 @@ static const char *qt_glsl_yuvPlanarShaderProgram = " gl_FragColor = colorMatrix * color;\n" "}\n"; +// Paints a YUV444 frame. +static const char *qt_glsl_xyuvShaderProgram = + "uniform sampler2D texRgb;\n" + "uniform mediump mat4 colorMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n" + " gl_FragColor = colorMatrix * color;\n" + "}\n"; + +// Paints a AYUV444 frame. +static const char *qt_glsl_ayuvShaderProgram = + "uniform sampler2D texRgb;\n" + "uniform mediump mat4 colorMatrix;\n" + "varying highp vec2 textureCoord;\n" + "void main(void)\n" + "{\n" + " highp vec4 color = vec4(texture2D(texRgb, textureCoord.st).gba, 1.0);\n" + " color = colorMatrix * color;\n" + " gl_FragColor = vec4(color.rgb, texture2D(texRgb, textureCoord.st).r);\n" + "}\n"; class QVideoSurfaceGlslPainter : public QVideoSurfaceGLPainter { @@ -895,6 +955,8 @@ QVideoSurfaceGlslPainter::QVideoSurfaceGlslPainter(QGLContext *context) << QVideoFrame::Format_BGR24 #endif << QVideoFrame::Format_RGB565 + << QVideoFrame::Format_YUV444 + << QVideoFrame::Format_AYUV444 << QVideoFrame::Format_YV12 << QVideoFrame::Format_YUV420P; m_glPixelFormats @@ -919,7 +981,7 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface fragmentProgram = qt_glsl_xrgbShaderProgram; break; case QVideoFrame::Format_BGR32: - initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + initRgbTextureInfo(GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); fragmentProgram = qt_glsl_rgbShaderProgram; break; case QVideoFrame::Format_ARGB32: @@ -940,6 +1002,16 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize()); fragmentProgram = qt_glsl_rgbShaderProgram; break; + case QVideoFrame::Format_YUV444: + initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_xyuvShaderProgram; + m_yuv = true; + break; + case QVideoFrame::Format_AYUV444: + initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); + fragmentProgram = qt_glsl_ayuvShaderProgram; + m_yuv = true; + break; case QVideoFrame::Format_YV12: initYv12TextureInfo(format.frameSize()); fragmentProgram = qt_glsl_yuvPlanarShaderProgram; diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index 3108e1a..a3c7157 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -227,7 +227,8 @@ static const YuvFormat qt_yuvColorLookup[] = { QVideoFrame::Format_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 }, { QVideoFrame::Format_YUYV, GST_MAKE_FOURCC('Y','U','Y','2'), 16 }, { QVideoFrame::Format_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 }, - { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 } + { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 }, + { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 } }; static int indexOfYuvColor(QVideoFrame::PixelFormat format) -- cgit v0.12 From 25190874d12d97a9f7c9d9c25ca7aa2d6d6cfd6d Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 11:01:48 +1000 Subject: Remove tests that depend on playlist plugins. --- tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp | 28 ------------------------ 1 file changed, 28 deletions(-) diff --git a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp index 07971ca..adaa56c 100644 --- a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp +++ b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp @@ -425,34 +425,6 @@ void tst_QMediaPlaylist::saveAndLoad() 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)); - - res = playlist.save(QUrl(QLatin1String("tmp.m3u")), "m3u"); - QVERIFY(res); - - playlist2.clear(); - QVERIFY(playlist2.isEmpty()); - playlist2.load(QUrl(QLatin1String("tmp.m3u")), "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)); } void tst_QMediaPlaylist::playbackMode_data() -- cgit v0.12 From 08815ab306eb61d4a6abdfce0fe3ea9d50d46212 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 11:02:28 +1000 Subject: Remove tests not relevant to playback functionality. --- .../tst_qmediaserviceprovider.cpp | 54 +--------------------- 1 file changed, 2 insertions(+), 52 deletions(-) diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp index 204ed14..671cfa4 100644 --- a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp +++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp @@ -72,8 +72,7 @@ public: QStringList keys() const { return QStringList() << - QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) << - QLatin1String(Q_MEDIASERVICE_CAMERA); + QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); } QMediaService* create(QString const& key) @@ -109,8 +108,6 @@ public: QList devices(const QByteArray &service) const { QList res; - if (service == QByteArray(Q_MEDIASERVICE_CAMERA)) - res << "camera1" << "camera2"; return res; } @@ -183,9 +180,7 @@ public: QStringList keys() const { return QStringList() << - QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) << - QLatin1String(Q_MEDIASERVICE_CAMERA) << - QLatin1String(Q_MEDIASERVICE_AUDIOSOURCE); + QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER); } QMediaService* create(QString const& key) @@ -204,11 +199,6 @@ public: QList devices(const QByteArray &service) const { QList res; - if (service == QByteArray(Q_MEDIASERVICE_CAMERA)) - res << "camera3" << "camera4"; - else if (service == QByteArray(Q_MEDIASERVICE_AUDIOSOURCE)) - res << "audiosource1" << "audiosource2"; - return res; } @@ -250,7 +240,6 @@ private slots: void testObtainService(); void testHasSupport(); void testSupportedMimeTypes(); - void testDevices(); void testProviderHints(); private: @@ -341,45 +330,6 @@ void tst_QMediaServiceProvider::testSupportedMimeTypes() QVERIFY(!provider->supportedMimeTypes(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)).contains("audio/mp3")); } -void tst_QMediaServiceProvider::testDevices() -{ - MockMediaServiceProvider mockProvider; - QVERIFY(mockProvider.devices(QByteArray(Q_MEDIASERVICE_CAMERA)).isEmpty()); - QVERIFY(mockProvider.deviceDescription(QByteArray(Q_MEDIASERVICE_CAMERA), - QByteArray()).isEmpty()); - - QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); - - QList cameraDevices = provider->devices(QByteArray(Q_MEDIASERVICE_CAMERA)); - QCOMPARE(cameraDevices.count(), 4); - QVERIFY(cameraDevices.contains(QByteArray("camera1"))); - QVERIFY(cameraDevices.contains(QByteArray("camera2"))); - QVERIFY(cameraDevices.contains(QByteArray("camera3"))); - QVERIFY(cameraDevices.contains(QByteArray("camera4"))); - - /* - //ensure the right plugin is choosen for a device - QCamera camera1(QByteArray("camera1")); - QCOMPARE( camera1.service()->objectName(), QLatin1String("MockServicePlugin1") ); - QCamera camera2(QByteArray("camera2")); - QCOMPARE( camera2.service()->objectName(), QLatin1String("MockServicePlugin1") ); - QCamera camera3(QByteArray("camera3")); - QCOMPARE( camera3.service()->objectName(), QLatin1String("MockServicePlugin3") ); - QCamera camera4(QByteArray("camera4")); - QCOMPARE( camera4.service()->objectName(), QLatin1String("MockServicePlugin3") ); - - QList audioSourceDevices = provider->devices(QByteArray(Q_MEDIASERVICE_AUDIOSOURCE)); - QCOMPARE(audioSourceDevices.count(), 2); - QVERIFY(audioSourceDevices.contains(QByteArray("audiosource1"))); - QVERIFY(audioSourceDevices.contains(QByteArray("audiosource2"))); - - QVERIFY(provider->devices(QByteArray("non existing service")).isEmpty()); - */ -} - - - - void tst_QMediaServiceProvider::testProviderHints() { { -- cgit v0.12 From 1f93babe307efa37f0ca93c235ae1b616f303ee4 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 17 Feb 2010 11:39:20 +1000 Subject: Make QMediaPlayer test compile. Test changes weren't ported with the rest of the changes for isAudioAvailable(). --- tests/auto/qmediaplayer/tst_qmediaplayer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp index a3cba3f..6fac409 100644 --- a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp +++ b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp @@ -96,6 +96,7 @@ public: int bufferStatus() const { return _bufferStatus; } + bool isAudioAvailable() const { return _audioAvailable; } bool isVideoAvailable() const { return _videoAvailable; } bool isSeekable() const { return _isSeekable; } @@ -131,6 +132,7 @@ public: int _volume; bool _muted; int _bufferStatus; + bool _audioAvailable; bool _videoAvailable; bool _isSeekable; QPair _seekRange; -- cgit v0.12 From 4cbeafe5be5f7d20525518fa9c9686fd68869171 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 11:54:24 +1000 Subject: Fix qmlaudio.pro. --- tests/auto/qmlaudio/qmlaudio.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qmlaudio/qmlaudio.pro b/tests/auto/qmlaudio/qmlaudio.pro index 4581e80..fe18761 100644 --- a/tests/auto/qmlaudio/qmlaudio.pro +++ b/tests/auto/qmlaudio/qmlaudio.pro @@ -1,6 +1,6 @@ load(qttest_p4) SOURCES += tst_qmlaudio.cpp -QT += multimedia +QT += multimedia declarative requires(contains(QT_CONFIG, multimedia)) requires(contains(QT_CONFIG, declarative)) -- cgit v0.12 From a2aaed149cffdde161fc1fc7d718b3fd7f6c96c5 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 17 Feb 2010 12:41:11 +1000 Subject: Fix QMediaPlayer test failure. Prepending the Qt namespace with QT_PREPEND_NAMESPACE in a Q_DECLARE_METATYPE statement is unecessary and appears not to work with signal declarations in QSignalSpy. --- src/multimedia/base/qmediacontent.h | 2 +- src/multimedia/base/qmediaplaylist.h | 4 ++-- src/multimedia/base/qmediaresource.h | 4 ++-- src/multimedia/playback/qmediaplayer.cpp | 7 +++---- src/multimedia/playback/qmediaplayer.h | 6 +++--- tests/auto/qmediaplayer/tst_qmediaplayer.cpp | 29 +--------------------------- 6 files changed, 12 insertions(+), 40 deletions(-) diff --git a/src/multimedia/base/qmediacontent.h b/src/multimedia/base/qmediacontent.h index 49d1155..1ea4898 100644 --- a/src/multimedia/base/qmediacontent.h +++ b/src/multimedia/base/qmediacontent.h @@ -83,7 +83,7 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaContent)) +Q_DECLARE_METATYPE(QMediaContent) QT_END_HEADER diff --git a/src/multimedia/base/qmediaplaylist.h b/src/multimedia/base/qmediaplaylist.h index c16541a..494cf11 100644 --- a/src/multimedia/base/qmediaplaylist.h +++ b/src/multimedia/base/qmediaplaylist.h @@ -139,8 +139,8 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlaylist::PlaybackMode)) -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlaylist::Error)) +Q_DECLARE_METATYPE(QMediaPlaylist::PlaybackMode) +Q_DECLARE_METATYPE(QMediaPlaylist::Error) QT_END_HEADER diff --git a/src/multimedia/base/qmediaresource.h b/src/multimedia/base/qmediaresource.h index 516120a..a535bbd 100644 --- a/src/multimedia/base/qmediaresource.h +++ b/src/multimedia/base/qmediaresource.h @@ -125,8 +125,8 @@ typedef QList QMediaResourceList; QT_END_NAMESPACE -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaResource)) -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaResourceList)) +Q_DECLARE_METATYPE(QMediaResource) +Q_DECLARE_METATYPE(QMediaResourceList) QT_END_HEADER diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 0853597..6ce34ab 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -112,9 +111,9 @@ class MediaPlayerRegisterMetaTypes public: MediaPlayerRegisterMetaTypes() { - qRegisterMetaType("QMediaPlayer::State"); - qRegisterMetaType("QMediaPlayer::MediaStatus"); - qRegisterMetaType("QMediaPlayer::Error"); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); } } _registerPlayerMetaTypes; } diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index dc9d4f0..91d6790 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -193,9 +193,9 @@ private: QT_END_NAMESPACE -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlayer::State)) -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlayer::MediaStatus)) -Q_DECLARE_METATYPE(QT_PREPEND_NAMESPACE(QMediaPlayer::Error)) +Q_DECLARE_METATYPE(QMediaPlayer::State) +Q_DECLARE_METATYPE(QMediaPlayer::MediaStatus) +Q_DECLARE_METATYPE(QMediaPlayer::Error) QT_END_HEADER diff --git a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp index 1775ec6..a96e08d 100644 --- a/tests/auto/qmediaplayer/tst_qmediaplayer.cpp +++ b/tests/auto/qmediaplayer/tst_qmediaplayer.cpp @@ -304,10 +304,7 @@ void tst_QMediaPlayer::initTestCase_data() void tst_QMediaPlayer::initTestCase() { - qRegisterMetaType("QMediaPlayer::State"); - qRegisterMetaType("QMediaPlayer::Error"); - qRegisterMetaType("QMediaPlayer::MediaStatus"); - qRegisterMetaType("QMediaContent"); + qRegisterMetaType(); mockService = new MockPlayerService; mockProvider = new MockProvider(mockService); @@ -738,10 +735,6 @@ void tst_QMediaPlayer::testMediaStatus() QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadingMedia); QCOMPARE(statusSpy.count(), 1); -#ifdef QTM_NAMESPACE - //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace - QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); -#endif QCOMPARE(qvariant_cast(statusSpy.last().value(0)), QMediaPlayer::LoadingMedia); @@ -749,10 +742,6 @@ void tst_QMediaPlayer::testMediaStatus() QCOMPARE(player->mediaStatus(), QMediaPlayer::LoadedMedia); QCOMPARE(statusSpy.count(), 2); -#ifdef QTM_NAMESPACE - //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace - QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); -#endif QCOMPARE(qvariant_cast(statusSpy.last().value(0)), QMediaPlayer::LoadedMedia); @@ -764,10 +753,6 @@ void tst_QMediaPlayer::testMediaStatus() QCOMPARE(player->mediaStatus(), QMediaPlayer::StalledMedia); QCOMPARE(statusSpy.count(), 3); -#ifdef QTM_NAMESPACE - //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace - QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); -#endif QCOMPARE(qvariant_cast(statusSpy.last().value(0)), QMediaPlayer::StalledMedia); @@ -781,10 +766,6 @@ void tst_QMediaPlayer::testMediaStatus() QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferingMedia); QCOMPARE(statusSpy.count(), 4); -#ifdef QTM_NAMESPACE - //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace - QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); -#endif QCOMPARE(qvariant_cast(statusSpy.last().value(0)), QMediaPlayer::BufferingMedia); @@ -798,10 +779,6 @@ void tst_QMediaPlayer::testMediaStatus() QCOMPARE(player->mediaStatus(), QMediaPlayer::BufferedMedia); QCOMPARE(statusSpy.count(), 5); -#ifdef QTM_NAMESPACE - //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace - QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); -#endif QCOMPARE(qvariant_cast(statusSpy.last().value(0)), QMediaPlayer::BufferedMedia); @@ -813,10 +790,6 @@ void tst_QMediaPlayer::testMediaStatus() QCOMPARE(player->mediaStatus(), QMediaPlayer::EndOfMedia); QCOMPARE(statusSpy.count(), 6); -#ifdef QTM_NAMESPACE - //looks like the correct value is emited, but QSignalSpy doesn't work correctly with QtMobility namespace - QEXPECT_FAIL("", "QSignalSpy doesn't grab the correct value from signal because of QtMobility namespace", Continue); -#endif QCOMPARE(qvariant_cast(statusSpy.last().value(0)), QMediaPlayer::EndOfMedia); } -- cgit v0.12 From 401ee4c7b14146b39419dafe1981c6a8a108196e Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Wed, 17 Feb 2010 13:51:43 +1000 Subject: Make QMediaPlaylist test pass. The test was failing because an ignored warning wasn't being output. Remove both the warning and ignore statements. --- src/multimedia/base/qmediapluginloader.cpp | 1 - tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/multimedia/base/qmediapluginloader.cpp b/src/multimedia/base/qmediapluginloader.cpp index 8130413..24c5aba 100644 --- a/src/multimedia/base/qmediapluginloader.cpp +++ b/src/multimedia/base/qmediapluginloader.cpp @@ -88,7 +88,6 @@ void QMediaPluginLoader::load() return; if (staticMediaPlugins() && staticMediaPlugins()->contains(m_location)) { - qWarning() << "Load static plugins for" << m_location; foreach(QObject *o, staticMediaPlugins()->value(m_location)) { if (o != 0 && o->qt_metacast(m_iid) != 0) { QFactoryInterface* p = qobject_cast(o); diff --git a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp index adaa56c..383a407 100644 --- a/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp +++ b/tests/auto/qmediaplaylist/tst_qmediaplaylist.cpp @@ -403,7 +403,6 @@ void tst_QMediaPlaylist::saveAndLoad() QBuffer buffer; buffer.open(QBuffer::ReadWrite); - QTest::ignoreMessage(QtWarningMsg, "Load static plugins for \"/playlistformats/\" "); bool res = playlist.save(&buffer, "unsupported_format"); QVERIFY(!res); QVERIFY(playlist.error() != QMediaPlaylist::NoError); -- cgit v0.12 From e1dfd11e73095bcdea7265afa3595b1c8a9e5502 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 15:56:37 +1000 Subject: Fix QMediaServiceProvider test. --- tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp index 671cfa4..9409394 100644 --- a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp +++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp @@ -107,6 +107,7 @@ public: QList devices(const QByteArray &service) const { + Q_UNUSED(service); QList res; return res; } @@ -198,6 +199,7 @@ public: QList devices(const QByteArray &service) const { + Q_UNUSED(service); QList res; return res; } @@ -252,7 +254,7 @@ void tst_QMediaServiceProvider::initTestCase() plugins << new MockServicePlugin2; plugins << new MockServicePlugin3; - QMediaPluginLoader::setStaticPlugins(QLatin1String("/mediaservice"), plugins); + QMediaPluginLoader::setStaticPlugins(QLatin1String("/mediaservices"), plugins); } void tst_QMediaServiceProvider::testDefaultProviderAvailable() @@ -270,7 +272,6 @@ void tst_QMediaServiceProvider::testObtainService() QMediaService *service = 0; - QTest::ignoreMessage(QtWarningMsg, "Load static plugins for \"/mediaservice/\" "); // Player service = provider->requestService(Q_MEDIASERVICE_MEDIAPLAYER); QVERIFY(service != 0); -- cgit v0.12 From 24b8f6b60adc004d70e3c6e09d974ff752d91e71 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 17:09:44 +1000 Subject: Add qmlgraphicsvideo test to auto.pro --- tests/auto/auto.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index e47d95c..6a0645b 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -312,6 +312,7 @@ SUBDIRS += \ qmediatimerange \ qvideowidget \ qmlaudio \ + qmlgraphicsvideo \ qspinbox \ qsplitter \ qsql \ -- cgit v0.12 From ad2e68cc20d8515a29930da6a247e21fbed472a4 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Wed, 17 Feb 2010 17:10:47 +1000 Subject: Fix qmlgraphicsvideo.pro --- tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro b/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro index 994b8fe..0a83124 100644 --- a/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro +++ b/tests/auto/qmlgraphicsvideo/qmlgraphicsvideo.pro @@ -1,6 +1,6 @@ load(qttest_p4) SOURCES += tst_qmlgraphicsvideo.cpp -QT += multimedia +QT += multimedia declarative requires(contains(QT_CONFIG, multimedia)) requires(contains(QT_CONFIG, declarative)) -- cgit v0.12 From 562eca42906870f5871400d0899c8e8d1fb2576c Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 18 Feb 2010 10:12:17 +1000 Subject: Use the IPropertyBag interface to get audio device names. This is instead of parsing the identifier, which is guaranteed to have a readable name in it. --- .../mediaplayer/directshowaudioendpointcontrol.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp index 4bb7228..570b44a 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowaudioendpointcontrol.cpp @@ -82,7 +82,21 @@ QList DirectShowAudioEndpointControl::availableEndpoints() const QString DirectShowAudioEndpointControl::endpointDescription(const QString &name) const { - return name.section(QLatin1Char('\\'), -1); + QString description; + + if (IMoniker *moniker = m_devices.value(name, 0)) { + IPropertyBag *propertyBag = 0; + if (SUCCEEDED(moniker->BindToStorage( + 0, 0, IID_IPropertyBag, reinterpret_cast(&propertyBag)))) { + VARIANT name; + VariantInit(&name); + if (SUCCEEDED(propertyBag->Read(L"FriendlyName", &name, 0))) + description = QString::fromWCharArray(name.bstrVal); + VariantClear(&name); + propertyBag->Release(); + } + } + return description;; } QString DirectShowAudioEndpointControl::defaultEndpoint() const -- cgit v0.12 From c166173cde49ad76bc8c6904df01af8cfe8eb401 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 18 Feb 2010 15:39:42 +1000 Subject: Disable the full screen video widget tests on X11. Too susceptible to timing problems. --- tests/auto/qvideowidget/tst_qvideowidget.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/auto/qvideowidget/tst_qvideowidget.cpp b/tests/auto/qvideowidget/tst_qvideowidget.cpp index 9da4b9e..f703055 100644 --- a/tests/auto/qvideowidget/tst_qvideowidget.cpp +++ b/tests/auto/qvideowidget/tst_qvideowidget.cpp @@ -69,7 +69,6 @@ private slots: void setMediaObject(); void showWindowControl(); - void fullScreenWindowControl(); void aspectRatioWindowControl(); void sizeHintWindowControl_data() { sizeHint_data(); } void sizeHintWindowControl(); @@ -83,7 +82,6 @@ private slots: void saturationWindowControl(); void showWidgetControl(); - void fullScreenWidgetControl(); void aspectRatioWidgetControl(); void sizeHintWidgetControl_data() { sizeHint_data(); } void sizeHintWidgetControl(); @@ -97,7 +95,6 @@ private slots: void saturationWidgetControl(); void showRendererControl(); - void fullScreenRendererControl(); void aspectRatioRendererControl(); void sizeHintRendererControl_data(); void sizeHintRendererControl(); @@ -112,6 +109,12 @@ private slots: void paintRendererControl(); +#ifndef Q_WS_X11 + void fullScreenWindowControl(); + void fullScreenWidgetControl(); + void fullScreenRendererControl(); +#endif + private: void sizeHint_data(); void color_data(); @@ -890,6 +893,7 @@ void tst_QVideoWidget::sizeHintRendererControl() QCOMPARE(widget.sizeHint(), expectedSize); } +#ifndef Q_WS_X11 void tst_QVideoWidget::fullScreenWindowControl() { @@ -1115,6 +1119,7 @@ void tst_QVideoWidget::fullScreenRendererControl() QCOMPARE(spy.count(), 5); } +#endif void tst_QVideoWidget::color_data() { -- cgit v0.12 From 7c2ccecd96631caf290e070f9e34bbe54be275ce Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 18 Feb 2010 16:05:27 +1000 Subject: Switch RGB24 and BGR24 shaders back. This reverts a7f6af9817771b8211433c8cf24fe7150c5b7bf5. The original relationship was consistent with QImage's RGB24, making the direct show RGB24 format BGR24. --- src/multimedia/base/qpaintervideosurface.cpp | 8 ++++---- .../mediaservices/directshow/mediaplayer/directshowmediatype.cpp | 2 +- src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp index dcc81d9..97fddc9 100644 --- a/src/multimedia/base/qpaintervideosurface.cpp +++ b/src/multimedia/base/qpaintervideosurface.cpp @@ -645,11 +645,11 @@ QAbstractVideoSurface::Error QVideoSurfaceArbFpPainter::start(const QVideoSurfac break; case QVideoFrame::Format_RGB24: initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); - program = qt_arbfp_xrgbShaderProgram; + program = qt_arbfp_rgbShaderProgram; break; case QVideoFrame::Format_BGR24: initRgbTextureInfo(GL_RGB8, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize()); - program = qt_arbfp_rgbShaderProgram; + program = qt_arbfp_xrgbShaderProgram; break; case QVideoFrame::Format_RGB565: initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize()); @@ -991,11 +991,11 @@ QAbstractVideoSurface::Error QVideoSurfaceGlslPainter::start(const QVideoSurface #ifndef QT_OPENGL_ES case QVideoFrame::Format_RGB24: initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); - fragmentProgram = qt_glsl_argbShaderProgram; + fragmentProgram = qt_glsl_rgbShaderProgram; break; case QVideoFrame::Format_BGR24: initRgbTextureInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize()); - fragmentProgram = qt_glsl_rgbShaderProgram; + fragmentProgram = qt_glsl_argbShaderProgram; break; #endif case QVideoFrame::Format_RGB565: diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp index b60a903..f719b29 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmediatype.cpp @@ -55,7 +55,7 @@ namespace static const TypeLookup qt_typeLookup[] = { { QVideoFrame::Format_RGB32, MEDIASUBTYPE_RGB32 }, - { QVideoFrame::Format_RGB24, MEDIASUBTYPE_RGB24 }, + { QVideoFrame::Format_BGR24, MEDIASUBTYPE_RGB24 }, { QVideoFrame::Format_RGB565, MEDIASUBTYPE_RGB565 }, { QVideoFrame::Format_RGB555, MEDIASUBTYPE_RGB555 }, { QVideoFrame::Format_AYUV444, MEDIASUBTYPE_AYUV }, diff --git a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp index a3c7157..9e3807b 100644 --- a/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp +++ b/src/plugins/mediaservices/gstreamer/qvideosurfacegstsink.cpp @@ -273,8 +273,8 @@ static const RgbFormat qt_rgbColorLookup[] = { QVideoFrame::Format_BGR32 , 32, 24, 1234, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, { QVideoFrame::Format_ARGB32, 32, 24, 4321, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, { QVideoFrame::Format_ARGB32, 32, 24, 1234, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, - { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, - { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { QVideoFrame::Format_RGB24 , 24, 24, 4321, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { QVideoFrame::Format_BGR24 , 24, 24, 4321, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, { QVideoFrame::Format_RGB565, 16, 16, 1234, 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 } }; -- cgit v0.12 From 7b8f7efa9c71dfea7d1182824e921cf261ce1c6f Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Fri, 19 Feb 2010 12:05:42 +1000 Subject: QuickTime playback backend: Listen for movie load state changes. To start playback and notify video output when movie reached playable state. --- .../qt7/mediaplayer/qt7playersession.h | 4 + .../qt7/mediaplayer/qt7playersession.mm | 135 ++++++++++++++++----- 2 files changed, 111 insertions(+), 28 deletions(-) diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h index 2a6bab7..8187f72 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h @@ -93,6 +93,8 @@ public: bool isSeekable() const; qreal playbackRate() const; + +public slots: void setPlaybackRate(qreal rate); void setPosition(qint64 pos); @@ -105,6 +107,8 @@ public: void setMuted(bool muted); void processEOS(); + void processStateChange(); + void processVolumeChange(); signals: void positionChanged(qint64 position); diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm index d9bb646..9ea33e4 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -68,6 +68,7 @@ QT_BEGIN_NAMESPACE - (QTMovieObserver *) initWithPlayerSession:(QT7PlayerSession*)session; - (void) setMovie:(QTMovie *)movie; - (void) processEOS:(NSNotification *)notification; +- (void) processStateChange:(NSNotification *)notification; @end @implementation QTMovieObserver @@ -97,6 +98,12 @@ QT_BEGIN_NAMESPACE [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: + @selector(processStateChange:) name: QTMovieLoadStateDidChangeNotification object: m_movie]; + + [[NSNotificationCenter defaultCenter] addObserver: self selector: + @selector(processVolumeChange:) name: QTMovieVolumeDidChangeNotification object: m_movie]; + [movie retain]; } } @@ -107,6 +114,19 @@ QT_BEGIN_NAMESPACE m_session->processEOS(); } +- (void) processStateChange:(NSNotification *)notification +{ + Q_UNUSED(notification); + m_session->processStateChange(); +} + +- (void) processVolumeChange:(NSNotification *)notification +{ + Q_UNUSED(notification); + m_session->processVolumeChange(); +} + + @end static CFStringRef qString2CFStringRef(const QString &string) @@ -145,8 +165,6 @@ void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output) if (m_videoOutput == output) return; - qDebug() << "set output" << output; - if (m_videoOutput) { m_videoOutput->setEnabled(false); m_videoOutput->setMovie(0); @@ -251,12 +269,11 @@ void QT7PlayerSession::setPosition(qint64 pos) void QT7PlayerSession::play() { - m_state = QMediaPlayer::PlayingState; - float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue]; [(QTMovie*)m_QTMovie setRate:preferredRate*m_rate]; - emit stateChanged(m_state); + if (m_state != QMediaPlayer::PlayingState) + emit stateChanged(m_state = QMediaPlayer::PlayingState); } void QT7PlayerSession::pause() @@ -327,6 +344,7 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) m_resources = content; m_mediaStream = stream; + m_mediaStatus = QMediaPlayer::NoMedia; QUrl url; @@ -336,24 +354,15 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) return; NSError *err = 0; - QTDataReference *dataRef = 0; - - if ( url.scheme() == "file" ) { - NSString *nsFileName = (NSString *)qString2CFStringRef( url.toLocalFile() ); - dataRef = [QTDataReference dataReferenceWithReferenceToFile:nsFileName]; - } else { - NSString *urlString = (NSString *)qString2CFStringRef( url.toString() ); - NSURL *url = [NSURL URLWithString: urlString]; - dataRef = [QTDataReference dataReferenceWithReferenceToURL:url]; - } + NSString *urlString = (NSString *)qString2CFStringRef(url.toString()); NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys: - dataRef, QTMovieDataReferenceAttribute, - [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute, - [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute, - [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute, - [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute, - nil]; + [NSURL URLWithString:urlString], QTMovieURLAttribute, + [NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute, + [NSNumber numberWithBool:YES], QTMovieIsActiveAttribute, + [NSNumber numberWithBool:YES], QTMovieResolveDataRefsAttribute, + [NSNumber numberWithBool:YES], QTMovieDontInteractWithUserAttribute, + nil]; m_QTMovie = [[QTMovie movieWithAttributes:attr error:&err] retain]; @@ -362,19 +371,15 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) m_QTMovie = 0; QString description = QString::fromUtf8([[err localizedDescription] UTF8String]); - qDebug() << "QT7PlayerSession::setMedia error" << description; emit error(QMediaPlayer::FormatError, description ); } else { [(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie]; - if (m_videoOutput) { - m_videoOutput->setEnabled(true); + if (m_videoOutput) { m_videoOutput->setMovie(m_QTMovie); + m_videoOutput->setEnabled(true); } - - emit durationChanged(duration()); - emit audioAvailableChanged(isAudioAvailable()); - emit videoAvailableChanged(isVideoAvailable()); + processStateChange(); [(QTMovie*)m_QTMovie setMuted:m_muted]; setVolume(m_volume); @@ -406,6 +411,80 @@ void QT7PlayerSession::processEOS() emit mediaStatusChanged(m_mediaStatus); } +void QT7PlayerSession::processStateChange() +{ + signed long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute] + longValue]; + //qDebug() << "new State:" << state; + +#ifndef QUICKTIME_C_API_AVAILABLE + enum { + kMovieLoadStateError = -1L, + kMovieLoadStateLoading = 1000, + kMovieLoadStateLoaded = 2000, + kMovieLoadStatePlayable = 10000, + kMovieLoadStatePlaythroughOK = 20000, + kMovieLoadStateComplete = 100000 + }; +#endif + + QMediaPlayer::MediaStatus newStatus = QMediaPlayer::NoMedia; + bool isPlaying = (m_state != QMediaPlayer::StoppedState); + + if (state >= kMovieLoadStateComplete) { + newStatus = isPlaying ? QMediaPlayer::BufferedMedia : QMediaPlayer::LoadedMedia; + } else if (state >= kMovieLoadStatePlayable) + newStatus = isPlaying ? QMediaPlayer::BufferingMedia : QMediaPlayer::LoadingMedia; + else if (state >= kMovieLoadStateLoading) + newStatus = isPlaying ? QMediaPlayer::StalledMedia : QMediaPlayer::LoadingMedia; + + if (state == kMovieLoadStateError) { + newStatus = QMediaPlayer::InvalidMedia; + emit error(QMediaPlayer::FormatError, tr("Playback failed")); + } + + if (newStatus != m_mediaStatus) { + switch (newStatus) { + case QMediaPlayer::BufferedMedia: + case QMediaPlayer::BufferingMedia: + //delayed playback start is necessary for network sources + if (m_state == QMediaPlayer::PlayingState) { + QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection); + } + //fall + case QMediaPlayer::LoadedMedia: + case QMediaPlayer::LoadingMedia: + emit durationChanged(duration()); + emit audioAvailableChanged(isAudioAvailable()); + emit videoAvailableChanged(isVideoAvailable()); + + //give output a change to re-read movie properties + if (m_videoOutput) + m_videoOutput->setMovie(m_QTMovie); + + break; + case QMediaPlayer::InvalidMedia: + emit stateChanged(m_state = QMediaPlayer::StoppedState); + default: + break; + } + + emit mediaStatusChanged(m_mediaStatus = newStatus); + } +} + +void QT7PlayerSession::processVolumeChange() +{ + if (!m_QTMovie) + return; + + int newVolume = qRound(100.0f*[((QTMovie*)m_QTMovie) volume]); + + if (newVolume != m_volume) { + emit volumeChanged(m_volume = newVolume); + } +} + #include "moc_qt7playersession.cpp" QT_END_NAMESPACE -- cgit v0.12 From 881164993418b15697faefc6989b7d3d217dba0a Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Fri, 19 Feb 2010 15:00:33 +1000 Subject: Quicktime playback backend: Recreate the visual context on video native size changes. --- src/plugins/mediaservices/qt7/qt7movierenderer.mm | 72 +++++++++++++---------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.mm b/src/plugins/mediaservices/qt7/qt7movierenderer.mm index 8cb0f46..9a35f5d 100644 --- a/src/plugins/mediaservices/qt7/qt7movierenderer.mm +++ b/src/plugins/mediaservices/qt7/qt7movierenderer.mm @@ -269,7 +269,7 @@ void QT7MovieRenderer::setupVideoOutput() return; } - NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue]; + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; m_nativeSize = QSize(size.width, size.height); #ifdef QUICKTIME_C_API_AVAILABLE @@ -320,34 +320,36 @@ void QT7MovieRenderer::setupVideoOutput() (m_usingGLContext && (m_currentGLContext != QGLContext::currentContext())) || (!m_usingGLContext && (m_pixelBufferContextGeometry != m_nativeSize))) { QTVisualContextRelease(m_visualContext); + m_pixelBufferContextGeometry = QSize(); m_visualContext = 0; } } - if (!m_visualContext) { - if (m_usingGLContext) { - qDebug() << "Building OpenGL visual context"; - m_currentGLContext = QGLContext::currentContext(); - if (!createGLVisualContext()) { - qWarning() << "QT7MovieRenderer: failed to create visual context"; - return; - } - } else { - qDebug() << "Building Pixel Buffer visual context"; - if (!createPixelBufferVisualContext()) { - qWarning() << "QT7MovieRenderer: failed to create visual context"; - return; + if (!m_nativeSize.isEmpty()) { + if (!m_visualContext) { + if (m_usingGLContext) { + qDebug() << "Building OpenGL visual context" << m_nativeSize; + m_currentGLContext = QGLContext::currentContext(); + if (!createGLVisualContext()) { + qWarning() << "QT7MovieRenderer: failed to create visual context"; + return; + } + } else { + qDebug() << "Building Pixel Buffer visual context" << m_nativeSize; + if (!createPixelBufferVisualContext()) { + qWarning() << "QT7MovieRenderer: failed to create visual context"; + return; + } } } - } - - // targets a Movie to render into a visual context - SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext); + // targets a Movie to render into a visual context + SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], m_visualContext); + m_displayLink->start(); + } #endif - m_displayLink->start(); } void QT7MovieRenderer::setEnabled(bool) @@ -358,19 +360,29 @@ void QT7MovieRenderer::setMovie(void *movie) { qDebug() << "QT7MovieRenderer::setMovie" << movie; - if (m_movie == movie) - return; - +#ifdef QUICKTIME_C_API_AVAILABLE QMutexLocker locker(&m_mutex); -#ifdef QUICKTIME_C_API_AVAILABLE - //ensure the old movie doesn't hold the visual context, otherwise it can't be reused - if (m_movie && m_visualContext) - SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], 0); -#endif + if (m_movie != movie) { + if (m_movie) { + //ensure the old movie doesn't hold the visual context, otherwise it can't be reused + SetMovieVisualContext([(QTMovie*)m_movie quickTimeMovie], nil); + [(QTMovie*)m_movie release]; + } - m_movie = movie; - setupVideoOutput(); + m_movie = movie; + [(QTMovie*)m_movie retain]; + + setupVideoOutput(); + } else { + if (m_movie) { + //reset video output if native size was changed + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; + if (m_nativeSize != QSize(size.width, size.height)) + setupVideoOutput(); + } + } +#endif } QAbstractVideoSurface *QT7MovieRenderer::surface() const @@ -426,7 +438,7 @@ void QT7MovieRenderer::updateVideoFrame(const CVTimeStamp &ts) CVPixelBufferRelease((CVPixelBufferRef)imageBuffer); } - QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_RGB32); + QVideoFrame frame(buffer, m_nativeSize, QVideoFrame::Format_RGB32); m_surface->present(frame); QTVisualContextTask(m_visualContext); } -- cgit v0.12 From f80b82ed61bece1843c6ae011fb5678ba8210949 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 16:16:44 +1000 Subject: Change namespace; QtMedia -> QtMultimedia --- demos/multimedia/player/player.cpp | 8 +- src/multimedia/base/qmediaobject.cpp | 12 +- src/multimedia/base/qmediaobject.h | 8 +- src/multimedia/base/qmediaserviceprovider.cpp | 20 +-- src/multimedia/base/qmediaserviceprovider.h | 2 +- src/multimedia/base/qmediaserviceproviderplugin.h | 2 +- src/multimedia/base/qmetadatacontrol.h | 6 +- src/multimedia/base/qtmedianamespace.h | 2 +- src/multimedia/playback/qmediaplayer.cpp | 2 +- src/multimedia/playback/qmediaplayer.h | 2 +- src/multimedia/qml/qmetadatacontrolmetaobject.cpp | 148 ++++++++++----------- .../mediaplayer/directshowmetadatacontrol.cpp | 98 +++++++------- .../mediaplayer/directshowmetadatacontrol.h | 6 +- .../mediaplayer/qgstreamermetadataprovider.cpp | 48 +++---- .../mediaplayer/qgstreamermetadataprovider.h | 6 +- .../mediaplayer/qgstreamerplayersession.h | 4 +- .../qt7/mediaplayer/qt7playermetadata.h | 8 +- .../qt7/mediaplayer/qt7playermetadata.mm | 20 +-- 18 files changed, 201 insertions(+), 201 deletions(-) diff --git a/demos/multimedia/player/player.cpp b/demos/multimedia/player/player.cpp index 38d96d6..64b1f25 100644 --- a/demos/multimedia/player/player.cpp +++ b/demos/multimedia/player/player.cpp @@ -184,14 +184,14 @@ void Player::positionChanged(qint64 progress) void Player::metaDataChanged() { - //qDebug() << "update metadata" << player->metaData(QtMedia::Title).toString(); + //qDebug() << "update metadata" << player->metaData(QtMultimedia::Title).toString(); if (player->isMetaDataAvailable()) { setTrackInfo(QString("%1 - %2") - .arg(player->metaData(QtMedia::AlbumArtist).toString()) - .arg(player->metaData(QtMedia::Title).toString())); + .arg(player->metaData(QtMultimedia::AlbumArtist).toString()) + .arg(player->metaData(QtMultimedia::Title).toString())); if (coverLabel) { - QUrl url = player->metaData(QtMedia::CoverArtUrlLarge).value(); + QUrl url = player->metaData(QtMultimedia::CoverArtUrlLarge).value(); coverLabel->setPixmap(!url.isEmpty() ? QPixmap(url.toString()) diff --git a/src/multimedia/base/qmediaobject.cpp b/src/multimedia/base/qmediaobject.cpp index 34b57c9..b2b8c1b 100644 --- a/src/multimedia/base/qmediaobject.cpp +++ b/src/multimedia/base/qmediaobject.cpp @@ -96,9 +96,9 @@ QMediaObject::~QMediaObject() Returns the service availability error state. */ -QtMedia::AvailabilityError QMediaObject::availabilityError() const +QtMultimedia::AvailabilityError QMediaObject::availabilityError() const { - return QtMedia::ServiceMissingError; + return QtMultimedia::ServiceMissingError; } /*! @@ -305,7 +305,7 @@ bool QMediaObject::isMetaDataWritable() const /*! Returns the value associated with a meta-data \a key. */ -QVariant QMediaObject::metaData(QtMedia::MetaData key) const +QVariant QMediaObject::metaData(QtMultimedia::MetaData key) const { Q_D(const QMediaObject); @@ -317,7 +317,7 @@ QVariant QMediaObject::metaData(QtMedia::MetaData key) const /*! Sets a \a value for a meta-data \a key. */ -void QMediaObject::setMetaData(QtMedia::MetaData key, const QVariant &value) +void QMediaObject::setMetaData(QtMultimedia::MetaData key, const QVariant &value) { Q_D(QMediaObject); @@ -328,13 +328,13 @@ void QMediaObject::setMetaData(QtMedia::MetaData key, const QVariant &value) /*! Returns a list of keys there is meta-data available for. */ -QList QMediaObject::availableMetaData() const +QList QMediaObject::availableMetaData() const { Q_D(const QMediaObject); return d->metaDataControl ? d->metaDataControl->availableMetaData() - : QList(); + : QList(); } /*! diff --git a/src/multimedia/base/qmediaobject.h b/src/multimedia/base/qmediaobject.h index a6eff1e..d09b1af 100644 --- a/src/multimedia/base/qmediaobject.h +++ b/src/multimedia/base/qmediaobject.h @@ -67,7 +67,7 @@ public: ~QMediaObject(); virtual bool isAvailable() const; - virtual QtMedia::AvailabilityError availabilityError() const; + virtual QtMultimedia::AvailabilityError availabilityError() const; virtual QMediaService* service() const; @@ -80,9 +80,9 @@ public: bool isMetaDataAvailable() const; bool isMetaDataWritable() const; - QVariant metaData(QtMedia::MetaData key) const; - void setMetaData(QtMedia::MetaData key, const QVariant &value); - QList availableMetaData() const; + QVariant metaData(QtMultimedia::MetaData key) const; + void setMetaData(QtMultimedia::MetaData key, const QVariant &value); + QList availableMetaData() const; QVariant extendedMetaData(const QString &key) const; void setExtendedMetaData(const QString &key, const QVariant &value); diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp index 3b8dd2c..fcf06d3 100644 --- a/src/multimedia/base/qmediaserviceprovider.cpp +++ b/src/multimedia/base/qmediaserviceprovider.cpp @@ -333,9 +333,9 @@ public: } break; case QMediaServiceProviderHint::ContentType: { - QtMedia::SupportEstimate estimate = QtMedia::NotSupported; + QtMultimedia::SupportEstimate estimate = QtMultimedia::NotSupported; foreach (QMediaServiceProviderPlugin *currentPlugin, plugins) { - QtMedia::SupportEstimate currentEstimate = QtMedia::MaybeSupported; + QtMultimedia::SupportEstimate currentEstimate = QtMultimedia::MaybeSupported; QMediaServiceSupportedFormatsInterface *iface = qobject_cast(currentPlugin); @@ -346,7 +346,7 @@ public: estimate = currentEstimate; plugin = currentPlugin; - if (currentEstimate == QtMedia::PreferedService) + if (currentEstimate == QtMultimedia::PreferedService) break; } } @@ -377,7 +377,7 @@ public: } } - QtMedia::SupportEstimate hasSupport(const QByteArray &serviceType, + QtMultimedia::SupportEstimate hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags) const @@ -385,10 +385,10 @@ public: QList instances = loader()->instances(serviceType); if (instances.isEmpty()) - return QtMedia::NotSupported; + return QtMultimedia::NotSupported; bool allServicesProvideInterface = true; - QtMedia::SupportEstimate supportEstimate = QtMedia::NotSupported; + QtMultimedia::SupportEstimate supportEstimate = QtMultimedia::NotSupported; foreach(QObject *obj, instances) { QMediaServiceSupportedFormatsInterface *iface = @@ -411,12 +411,12 @@ public: } //don't return PreferedService - supportEstimate = qMin(supportEstimate, QtMedia::ProbablySupported); + supportEstimate = qMin(supportEstimate, QtMultimedia::ProbablySupported); //Return NotSupported only if no services are available of serviceType //or all the services returned NotSupported, otherwise return at least MaybeSupported if (!allServicesProvideInterface) - supportEstimate = qMax(QtMedia::MaybeSupported, supportEstimate); + supportEstimate = qMax(QtMultimedia::MaybeSupported, supportEstimate); return supportEstimate; } @@ -515,7 +515,7 @@ Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider); service that is able to play media of a specific \a mimeType that is encoded using the listed \a codecs while adhearing to constraints identified in \a flags. */ -QtMedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, +QtMultimedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags) const @@ -525,7 +525,7 @@ QtMedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &ser Q_UNUSED(codecs); Q_UNUSED(flags); - return QtMedia::MaybeSupported; + return QtMultimedia::MaybeSupported; } /*! diff --git a/src/multimedia/base/qmediaserviceprovider.h b/src/multimedia/base/qmediaserviceprovider.h index f108d32..2ee0ae4 100644 --- a/src/multimedia/base/qmediaserviceprovider.h +++ b/src/multimedia/base/qmediaserviceprovider.h @@ -105,7 +105,7 @@ public: virtual QMediaService* requestService(const QByteArray &type, const QMediaServiceProviderHint &hint = QMediaServiceProviderHint()) = 0; virtual void releaseService(QMediaService *service) = 0; - virtual QtMedia::SupportEstimate hasSupport(const QByteArray &serviceType, + virtual QtMultimedia::SupportEstimate hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags = 0) const; diff --git a/src/multimedia/base/qmediaserviceproviderplugin.h b/src/multimedia/base/qmediaserviceproviderplugin.h index 0381093..b1e728b 100644 --- a/src/multimedia/base/qmediaserviceproviderplugin.h +++ b/src/multimedia/base/qmediaserviceproviderplugin.h @@ -76,7 +76,7 @@ Q_DECLARE_INTERFACE(QMediaServiceProviderFactoryInterface, QMediaServiceProvider struct Q_MULTIMEDIA_EXPORT QMediaServiceSupportedFormatsInterface { virtual ~QMediaServiceSupportedFormatsInterface() {} - virtual QtMedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const = 0; + virtual QtMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const = 0; virtual QStringList supportedMimeTypes() const = 0; }; diff --git a/src/multimedia/base/qmetadatacontrol.h b/src/multimedia/base/qmetadatacontrol.h index 5609f10..8e18c16 100644 --- a/src/multimedia/base/qmetadatacontrol.h +++ b/src/multimedia/base/qmetadatacontrol.h @@ -63,9 +63,9 @@ public: virtual bool isWritable() const = 0; virtual bool isMetaDataAvailable() const = 0; - virtual QVariant metaData(QtMedia::MetaData key) const = 0; - virtual void setMetaData(QtMedia::MetaData key, const QVariant &value) = 0; - virtual QList availableMetaData() const = 0; + virtual QVariant metaData(QtMultimedia::MetaData key) const = 0; + virtual void setMetaData(QtMultimedia::MetaData key, const QVariant &value) = 0; + virtual QList availableMetaData() const = 0; virtual QVariant extendedMetaData(const QString &key) const = 0; virtual void setExtendedMetaData(const QString &key, const QVariant &value) = 0; diff --git a/src/multimedia/base/qtmedianamespace.h b/src/multimedia/base/qtmedianamespace.h index c3b4896..2a56fc3 100644 --- a/src/multimedia/base/qtmedianamespace.h +++ b/src/multimedia/base/qtmedianamespace.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Multimedia) -namespace QtMedia +namespace QtMultimedia { enum MetaData { diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 6ce34ab..5f50fdb 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -645,7 +645,7 @@ void QMediaPlayer::unbind(QObject *obj) The \a flags argument allows additional requirements such as performance indicators to be specified. */ -QtMedia::SupportEstimate QMediaPlayer::hasSupport(const QString &mimeType, +QtMultimedia::SupportEstimate QMediaPlayer::hasSupport(const QString &mimeType, const QStringList& codecs, Flags flags) { diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index 91d6790..1b761ce 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -116,7 +116,7 @@ public: QMediaPlayer(QObject *parent = 0, Flags flags = 0, QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider()); ~QMediaPlayer(); - static QtMedia::SupportEstimate hasSupport(const QString &mimeType, + static QtMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs = QStringList(), Flags flags = 0); static QStringList supportedMimeTypes(Flags flags = 0); diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp index 882d8a6..7f9575e 100644 --- a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp +++ b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp @@ -106,101 +106,101 @@ namespace { struct MetaDataKey { - QtMedia::MetaData key; + QtMultimedia::MetaData key; const char *name; }; const MetaDataKey qt_metaDataKeys[] = { - { QtMedia::Title, "title" }, - { QtMedia::SubTitle, "subTitle" }, - { QtMedia::Author, "author" }, - { QtMedia::Comment, "comment" }, - { QtMedia::Description, "description" }, - { QtMedia::Category, "category" }, - { QtMedia::Genre, "genre" }, - { QtMedia::Year, "year" }, - { QtMedia::Date, "date" }, - { QtMedia::UserRating, "userRating" }, - { QtMedia::Keywords, "keywords" }, - { QtMedia::Language, "language" }, - { QtMedia::Publisher, "publisher" }, - { QtMedia::Copyright, "copyright" }, - { QtMedia::ParentalRating, "parentalRating" }, - { QtMedia::RatingOrganisation, "ratingOrganisation" }, + { QtMultimedia::Title, "title" }, + { QtMultimedia::SubTitle, "subTitle" }, + { QtMultimedia::Author, "author" }, + { QtMultimedia::Comment, "comment" }, + { QtMultimedia::Description, "description" }, + { QtMultimedia::Category, "category" }, + { QtMultimedia::Genre, "genre" }, + { QtMultimedia::Year, "year" }, + { QtMultimedia::Date, "date" }, + { QtMultimedia::UserRating, "userRating" }, + { QtMultimedia::Keywords, "keywords" }, + { QtMultimedia::Language, "language" }, + { QtMultimedia::Publisher, "publisher" }, + { QtMultimedia::Copyright, "copyright" }, + { QtMultimedia::ParentalRating, "parentalRating" }, + { QtMultimedia::RatingOrganisation, "ratingOrganisation" }, // Media - { QtMedia::Size, "size" }, - { QtMedia::MediaType, "mediaType" }, + { QtMultimedia::Size, "size" }, + { QtMultimedia::MediaType, "mediaType" }, // { QtMedia::Duration, "duration" }, // Audio - { QtMedia::AudioBitRate, "audioBitRate" }, - { QtMedia::AudioCodec, "audioCodec" }, - { QtMedia::AverageLevel, "averageLevel" }, - { QtMedia::ChannelCount, "channelCount" }, - { QtMedia::PeakValue, "peakValue" }, - { QtMedia::SampleRate, "sampleRate" }, + { QtMultimedia::AudioBitRate, "audioBitRate" }, + { QtMultimedia::AudioCodec, "audioCodec" }, + { QtMultimedia::AverageLevel, "averageLevel" }, + { QtMultimedia::ChannelCount, "channelCount" }, + { QtMultimedia::PeakValue, "peakValue" }, + { QtMultimedia::SampleRate, "sampleRate" }, // Music - { QtMedia::AlbumTitle, "albumTitle" }, - { QtMedia::AlbumArtist, "albumArtist" }, - { QtMedia::ContributingArtist, "contributingArtist" }, - { QtMedia::Composer, "composer" }, - { QtMedia::Conductor, "conductor" }, - { QtMedia::Lyrics, "lyrics" }, - { QtMedia::Mood, "mood" }, - { QtMedia::TrackNumber, "trackNumber" }, - { QtMedia::TrackCount, "trackCount" }, - - { QtMedia::CoverArtUrlSmall, "coverArtUrlSmall" }, - { QtMedia::CoverArtUrlLarge, "coverArtUrlLarge" }, + { QtMultimedia::AlbumTitle, "albumTitle" }, + { QtMultimedia::AlbumArtist, "albumArtist" }, + { QtMultimedia::ContributingArtist, "contributingArtist" }, + { QtMultimedia::Composer, "composer" }, + { QtMultimedia::Conductor, "conductor" }, + { QtMultimedia::Lyrics, "lyrics" }, + { QtMultimedia::Mood, "mood" }, + { QtMultimedia::TrackNumber, "trackNumber" }, + { QtMultimedia::TrackCount, "trackCount" }, + + { QtMultimedia::CoverArtUrlSmall, "coverArtUrlSmall" }, + { QtMultimedia::CoverArtUrlLarge, "coverArtUrlLarge" }, // Image/Video - { QtMedia::Resolution, "resolution" }, - { QtMedia::PixelAspectRatio, "pixelAspectRatio" }, + { QtMultimedia::Resolution, "resolution" }, + { QtMultimedia::PixelAspectRatio, "pixelAspectRatio" }, // Video - { QtMedia::VideoFrameRate, "videoFrameRate" }, - { QtMedia::VideoBitRate, "videoBitRate" }, - { QtMedia::VideoCodec, "videoCodec" }, + { QtMultimedia::VideoFrameRate, "videoFrameRate" }, + { QtMultimedia::VideoBitRate, "videoBitRate" }, + { QtMultimedia::VideoCodec, "videoCodec" }, - { QtMedia::PosterUrl, "posterUrl" }, + { QtMultimedia::PosterUrl, "posterUrl" }, // Movie - { QtMedia::ChapterNumber, "chapterNumber" }, - { QtMedia::Director, "director" }, - { QtMedia::LeadPerformer, "leadPerformer" }, - { QtMedia::Writer, "writer" }, + { QtMultimedia::ChapterNumber, "chapterNumber" }, + { QtMultimedia::Director, "director" }, + { QtMultimedia::LeadPerformer, "leadPerformer" }, + { QtMultimedia::Writer, "writer" }, // Photos - { QtMedia::CameraManufacturer, "cameraManufacturer" }, - { QtMedia::CameraModel, "cameraModel" }, - { QtMedia::Event, "event" }, - { QtMedia::Subject, "subject" }, - { QtMedia::Orientation, "orientation" }, - { QtMedia::ExposureTime, "exposureTime" }, - { QtMedia::FNumber, "fNumber" }, - { QtMedia::ExposureProgram, "exposureProgram" }, - { QtMedia::ISOSpeedRatings, "isoSpeedRatings" }, - { QtMedia::ExposureBiasValue, "exposureBiasValue" }, - { QtMedia::DateTimeOriginal, "dateTimeOriginal" }, - { QtMedia::DateTimeDigitized, "dateTimeDigitized" }, - { QtMedia::SubjectDistance, "subjectDistance" }, - { QtMedia::MeteringMode, "meteringMode" }, - { QtMedia::LightSource, "lightSource" }, - { QtMedia::Flash, "flash" }, - { QtMedia::FocalLength, "focalLength" }, - { QtMedia::ExposureMode, "exposureMode" }, - { QtMedia::WhiteBalance, "whiteBalance" }, - { QtMedia::DigitalZoomRatio, "digitalZoomRatio" }, - { QtMedia::FocalLengthIn35mmFilm, "focalLengthIn35mmFilm" }, - { QtMedia::SceneCaptureType, "sceneCaptureType" }, - { QtMedia::GainControl, "gainControl" }, - { QtMedia::Contrast, "contrast" }, - { QtMedia::Saturation, "saturation" }, - { QtMedia::Sharpness, "sharpness" }, - { QtMedia::DeviceSettingDescription, "deviceSettingDescription" } + { QtMultimedia::CameraManufacturer, "cameraManufacturer" }, + { QtMultimedia::CameraModel, "cameraModel" }, + { QtMultimedia::Event, "event" }, + { QtMultimedia::Subject, "subject" }, + { QtMultimedia::Orientation, "orientation" }, + { QtMultimedia::ExposureTime, "exposureTime" }, + { QtMultimedia::FNumber, "fNumber" }, + { QtMultimedia::ExposureProgram, "exposureProgram" }, + { QtMultimedia::ISOSpeedRatings, "isoSpeedRatings" }, + { QtMultimedia::ExposureBiasValue, "exposureBiasValue" }, + { QtMultimedia::DateTimeOriginal, "dateTimeOriginal" }, + { QtMultimedia::DateTimeDigitized, "dateTimeDigitized" }, + { QtMultimedia::SubjectDistance, "subjectDistance" }, + { QtMultimedia::MeteringMode, "meteringMode" }, + { QtMultimedia::LightSource, "lightSource" }, + { QtMultimedia::Flash, "flash" }, + { QtMultimedia::FocalLength, "focalLength" }, + { QtMultimedia::ExposureMode, "exposureMode" }, + { QtMultimedia::WhiteBalance, "whiteBalance" }, + { QtMultimedia::DigitalZoomRatio, "digitalZoomRatio" }, + { QtMultimedia::FocalLengthIn35mmFilm, "focalLengthIn35mmFilm" }, + { QtMultimedia::SceneCaptureType, "sceneCaptureType" }, + { QtMultimedia::GainControl, "gainControl" }, + { QtMultimedia::Contrast, "contrast" }, + { QtMultimedia::Saturation, "saturation" }, + { QtMultimedia::Sharpness, "sharpness" }, + { QtMultimedia::DeviceSettingDescription, "deviceSettingDescription" } }; class QMetaDataControlObject : public QObject diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp index e95ddcd..56820d2 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp @@ -57,50 +57,50 @@ namespace { struct QWMMetaDataKeyLookup { - QtMedia::MetaData key; + QtMultimedia::MetaData key; const wchar_t *token; }; } static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = { - { QtMedia::Title, L"Title" }, - { QtMedia::SubTitle, L"WM/SubTitle" }, - { QtMedia::Author, L"Author" }, - { QtMedia::Comment, L"Comment" }, - { QtMedia::Description, L"Description" }, - { QtMedia::Category, L"WM/Category" }, - { QtMedia::Genre, L"WM/Genre" }, + { QtMultimedia::Title, L"Title" }, + { QtMultimedia::SubTitle, L"WM/SubTitle" }, + { QtMultimedia::Author, L"Author" }, + { QtMultimedia::Comment, L"Comment" }, + { QtMultimedia::Description, L"Description" }, + { QtMultimedia::Category, L"WM/Category" }, + { QtMultimedia::Genre, L"WM/Genre" }, //{ QtMedia::Date, 0 }, - { QtMedia::Year, L"WM/Year" }, - { QtMedia::UserRating, L"UserRating" }, + { QtMultimedia::Year, L"WM/Year" }, + { QtMultimedia::UserRating, L"UserRating" }, //{ QtMedia::MetaDatawords, 0 }, - { QtMedia::Language, L"Language" }, - { QtMedia::Publisher, L"WM/Publisher" }, - { QtMedia::Copyright, L"Copyright" }, - { QtMedia::ParentalRating, L"ParentalRating" }, - { QtMedia::RatingOrganisation, L"RatingOrganisation" }, + { QtMultimedia::Language, L"Language" }, + { QtMultimedia::Publisher, L"WM/Publisher" }, + { QtMultimedia::Copyright, L"Copyright" }, + { QtMultimedia::ParentalRating, L"ParentalRating" }, + { QtMultimedia::RatingOrganisation, L"RatingOrganisation" }, // Media - { QtMedia::Size, L"FileSize" }, - { QtMedia::MediaType, L"MediaType" }, - { QtMedia::Duration, L"Duration" }, + { QtMultimedia::Size, L"FileSize" }, + { QtMultimedia::MediaType, L"MediaType" }, + { QtMultimedia::Duration, L"Duration" }, // Audio - { QtMedia::AudioBitRate, L"AudioBitRate" }, - { QtMedia::AudioCodec, L"AudioCodec" }, - { QtMedia::ChannelCount, L"ChannelCount" }, - { QtMedia::SampleRate, L"Frequency" }, + { QtMultimedia::AudioBitRate, L"AudioBitRate" }, + { QtMultimedia::AudioCodec, L"AudioCodec" }, + { QtMultimedia::ChannelCount, L"ChannelCount" }, + { QtMultimedia::SampleRate, L"Frequency" }, // Music - { QtMedia::AlbumTitle, L"WM/AlbumTitle" }, - { QtMedia::AlbumArtist, L"WM/AlbumArtist" }, - { QtMedia::ContributingArtist, L"Author" }, - { QtMedia::Composer, L"WM/Composer" }, - { QtMedia::Conductor, L"WM/Conductor" }, - { QtMedia::Lyrics, L"WM/Lyrics" }, - { QtMedia::Mood, L"WM/Mood" }, - { QtMedia::TrackNumber, L"WM/TrackNumber" }, + { QtMultimedia::AlbumTitle, L"WM/AlbumTitle" }, + { QtMultimedia::AlbumArtist, L"WM/AlbumArtist" }, + { QtMultimedia::ContributingArtist, L"Author" }, + { QtMultimedia::Composer, L"WM/Composer" }, + { QtMultimedia::Conductor, L"WM/Conductor" }, + { QtMultimedia::Lyrics, L"WM/Lyrics" }, + { QtMultimedia::Mood, L"WM/Mood" }, + { QtMultimedia::TrackNumber, L"WM/TrackNumber" }, //{ QtMedia::TrackCount, 0 }, //{ QtMedia::CoverArtUriSmall, 0 }, //{ QtMedia::CoverArtUriLarge, 0 }, @@ -111,22 +111,22 @@ static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = // Video //{ QtMedia::FrameRate, 0 }, - { QtMedia::VideoBitRate, L"VideoBitRate" }, - { QtMedia::VideoCodec, L"VideoCodec" }, + { QtMultimedia::VideoBitRate, L"VideoBitRate" }, + { QtMultimedia::VideoCodec, L"VideoCodec" }, //{ QtMedia::PosterUri, 0 }, // Movie - { QtMedia::ChapterNumber, L"ChapterNumber" }, - { QtMedia::Director, L"WM/Director" }, - { QtMedia::LeadPerformer, L"LeadPerformer" }, - { QtMedia::Writer, L"WM/Writer" }, + { QtMultimedia::ChapterNumber, L"ChapterNumber" }, + { QtMultimedia::Director, L"WM/Director" }, + { QtMultimedia::LeadPerformer, L"LeadPerformer" }, + { QtMultimedia::Writer, L"WM/Writer" }, // Photos - { QtMedia::CameraManufacturer, L"CameraManufacturer" }, - { QtMedia::CameraModel, L"CameraModel" }, - { QtMedia::Event, L"Event" }, - { QtMedia::Subject, L"Subject" } + { QtMultimedia::CameraManufacturer, L"CameraManufacturer" }, + { QtMultimedia::CameraModel, L"CameraModel" }, + { QtMultimedia::Event, L"Event" }, + { QtMultimedia::Subject, L"Subject" } }; static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key) @@ -257,7 +257,7 @@ bool DirectShowMetaDataControl::isMetaDataAvailable() const #endif } -QVariant DirectShowMetaDataControl::metaData(QtMedia::MetaData key) const +QVariant DirectShowMetaDataControl::metaData(QtMultimedia::MetaData key) const { QVariant value; @@ -277,19 +277,19 @@ QVariant DirectShowMetaDataControl::metaData(QtMedia::MetaData key) const BSTR string = 0; switch (key) { - case QtMedia::Author: + case QtMultimedia::Author: m_content->get_AuthorName(&string); break; - case QtMedia::Title: + case QtMultimedia::Title: m_content->get_Title(&string); break; - case QtMedia::ParentalRating: + case QtMultimedia::ParentalRating: m_content->get_Rating(&string); break; - case QtMedia::Description: + case QtMultimedia::Description: m_content->get_Description(&string); break; - case QtMedia::Copyright: + case QtMultimedia::Copyright: m_content->get_Copyright(&string); break; default: @@ -305,13 +305,13 @@ QVariant DirectShowMetaDataControl::metaData(QtMedia::MetaData key) const return value; } -void DirectShowMetaDataControl::setMetaData(QtMedia::MetaData, const QVariant &) +void DirectShowMetaDataControl::setMetaData(QtMultimedia::MetaData, const QVariant &) { } -QList DirectShowMetaDataControl::availableMetaData() const +QList DirectShowMetaDataControl::availableMetaData() const { - return QList(); + return QList(); } QVariant DirectShowMetaDataControl::extendedMetaData(const QString &) const diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h index eb3bbb7..966f9b8 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.h @@ -71,9 +71,9 @@ public: bool isWritable() const; bool isMetaDataAvailable() const; - QVariant metaData(QtMedia::MetaData key) const; - void setMetaData(QtMedia::MetaData key, const QVariant &value); - QList availableMetaData() const; + QVariant metaData(QtMultimedia::MetaData key) const; + void setMetaData(QtMultimedia::MetaData key, const QVariant &value); + QList availableMetaData() const; QVariant extendedMetaData(const QString &key) const; void setExtendedMetaData(const QString &key, const QVariant &value); diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index e38f80f..456dcfd 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -47,51 +47,51 @@ struct QGstreamerMetaDataKeyLookup { - QtMedia::MetaData key; + QtMultimedia::MetaData key; const char *token; }; static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = { - { QtMedia::Title, GST_TAG_TITLE }, + { QtMultimedia::Title, GST_TAG_TITLE }, //{ QtMedia::SubTitle, 0 }, //{ QtMedia::Author, 0 }, - { QtMedia::Comment, GST_TAG_COMMENT }, - { QtMedia::Description, GST_TAG_DESCRIPTION }, + { QtMultimedia::Comment, GST_TAG_COMMENT }, + { QtMultimedia::Description, GST_TAG_DESCRIPTION }, //{ QtMedia::Category, 0 }, - { QtMedia::Genre, GST_TAG_GENRE }, - { QtMedia::Year, "year" }, + { QtMultimedia::Genre, GST_TAG_GENRE }, + { QtMultimedia::Year, "year" }, //{ QtMedia::UserRating, 0 }, - { QtMedia::Language, GST_TAG_LANGUAGE_CODE }, + { QtMultimedia::Language, GST_TAG_LANGUAGE_CODE }, - { QtMedia::Publisher, GST_TAG_ORGANIZATION }, - { QtMedia::Copyright, GST_TAG_COPYRIGHT }, + { QtMultimedia::Publisher, GST_TAG_ORGANIZATION }, + { QtMultimedia::Copyright, GST_TAG_COPYRIGHT }, //{ QtMedia::ParentalRating, 0 }, //{ QtMedia::RatingOrganisation, 0 }, // Media //{ QtMedia::Size, 0 }, //{ QtMedia::MediaType, 0 }, - { QtMedia::Duration, GST_TAG_DURATION }, + { QtMultimedia::Duration, GST_TAG_DURATION }, // Audio - { QtMedia::AudioBitRate, GST_TAG_BITRATE }, - { QtMedia::AudioCodec, GST_TAG_AUDIO_CODEC }, + { QtMultimedia::AudioBitRate, GST_TAG_BITRATE }, + { QtMultimedia::AudioCodec, GST_TAG_AUDIO_CODEC }, //{ QtMedia::ChannelCount, 0 }, //{ QtMedia::Frequency, 0 }, // Music - { QtMedia::AlbumTitle, GST_TAG_ALBUM }, - { QtMedia::AlbumArtist, GST_TAG_ARTIST}, - { QtMedia::ContributingArtist, GST_TAG_PERFORMER }, + { QtMultimedia::AlbumTitle, GST_TAG_ALBUM }, + { QtMultimedia::AlbumArtist, GST_TAG_ARTIST}, + { QtMultimedia::ContributingArtist, GST_TAG_PERFORMER }, #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) { QtMedia::Composer, GST_TAG_COMPOSER }, #endif //{ QtMedia::Conductor, 0 }, //{ QtMedia::Lyrics, 0 }, //{ QtMedia::Mood, 0 }, - { QtMedia::TrackNumber, GST_TAG_TRACK_NUMBER }, + { QtMultimedia::TrackNumber, GST_TAG_TRACK_NUMBER }, //{ QtMedia::CoverArtUrlSmall, 0 }, //{ QtMedia::CoverArtUrlLarge, 0 }, @@ -103,14 +103,14 @@ static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = // Video //{ QtMedia::VideoFrameRate, 0 }, //{ QtMedia::VideoBitRate, 0 }, - { QtMedia::VideoCodec, GST_TAG_VIDEO_CODEC }, + { QtMultimedia::VideoCodec, GST_TAG_VIDEO_CODEC }, //{ QtMedia::PosterUrl, 0 }, // Movie //{ QtMedia::ChapterNumber, 0 }, //{ QtMedia::Director, 0 }, - { QtMedia::LeadPerformer, GST_TAG_PERFORMER }, + { QtMultimedia::LeadPerformer, GST_TAG_PERFORMER }, //{ QtMedia::Writer, 0 }, // Photos @@ -140,7 +140,7 @@ bool QGstreamerMetaDataProvider::isWritable() const return false; } -QVariant QGstreamerMetaDataProvider::metaData(QtMedia::MetaData key) const +QVariant QGstreamerMetaDataProvider::metaData(QtMultimedia::MetaData key) const { static const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); @@ -152,15 +152,15 @@ QVariant QGstreamerMetaDataProvider::metaData(QtMedia::MetaData key) const return QVariant(); } -void QGstreamerMetaDataProvider::setMetaData(QtMedia::MetaData key, QVariant const &value) +void QGstreamerMetaDataProvider::setMetaData(QtMultimedia::MetaData key, QVariant const &value) { Q_UNUSED(key); Q_UNUSED(value); } -QList QGstreamerMetaDataProvider::availableMetaData() const +QList QGstreamerMetaDataProvider::availableMetaData() const { - static QMap keysMap; + static QMap keysMap; if (keysMap.isEmpty()) { const int count = sizeof(qt_gstreamerMetaDataKeys) / sizeof(QGstreamerMetaDataKeyLookup); for (int i = 0; i < count; ++i) { @@ -168,9 +168,9 @@ QList QGstreamerMetaDataProvider::availableMetaData() const } } - QList res; + QList res; foreach (const QByteArray &key, m_session->tags().keys()) { - QtMedia::MetaData tag = keysMap.value(key, QtMedia::MetaData(-1)); + QtMultimedia::MetaData tag = keysMap.value(key, QtMultimedia::MetaData(-1)); if (tag != -1) res.append(tag); } diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h index cdf82d9..267c2d7 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.h @@ -61,9 +61,9 @@ public: bool isMetaDataAvailable() const; bool isWritable() const; - QVariant metaData(QtMedia::MetaData key) const; - void setMetaData(QtMedia::MetaData key, const QVariant &value); - QList availableMetaData() const; + QVariant metaData(QtMultimedia::MetaData key) const; + void setMetaData(QtMultimedia::MetaData key, const QVariant &value); + QList availableMetaData() const; QVariant extendedMetaData(const QString &key) const ; void setExtendedMetaData(const QString &key, const QVariant &value); diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h index e277ba9..d650ec7 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -93,7 +93,7 @@ public: void setPlaybackRate(qreal rate); QMap tags() const { return m_tags; } - QMap streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; } + QMap streamProperties(int streamNumber) const { return m_streamProperties[streamNumber]; } // int streamCount() const { return m_streamProperties.count(); } // QMediaStreamsControl::StreamType streamType(int streamNumber) { return m_streamTypes.value(streamNumber, QMediaStreamsControl::UnknownStream); } // @@ -149,7 +149,7 @@ private: QGstreamerVideoRendererInterface *m_renderer; QMap m_tags; - QList< QMap > m_streamProperties; + QList< QMap > m_streamProperties; // QList m_streamTypes; // QMap m_playbin2StreamOffset; diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h index 9aa9887..f16807a 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.h @@ -61,9 +61,9 @@ public: bool isMetaDataAvailable() const; bool isWritable() const; - QVariant metaData(QtMedia::MetaData key) const; - void setMetaData(QtMedia::MetaData key, const QVariant &value); - QList availableMetaData() const; + QVariant metaData(QtMultimedia::MetaData key) const; + void setMetaData(QtMultimedia::MetaData key, const QVariant &value); + QList availableMetaData() const; QVariant extendedMetaData(const QString &key) const ; void setExtendedMetaData(const QString &key, const QVariant &value); @@ -74,7 +74,7 @@ private slots: private: QT7PlayerSession *m_session; - QMap m_tags; + QMap m_tags; }; QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm index 96b7a68..a14981a 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playermetadata.mm @@ -72,18 +72,18 @@ bool QT7PlayerMetaDataControl::isWritable() const return false; } -QVariant QT7PlayerMetaDataControl::metaData(QtMedia::MetaData key) const +QVariant QT7PlayerMetaDataControl::metaData(QtMultimedia::MetaData key) const { return m_tags.value(key); } -void QT7PlayerMetaDataControl::setMetaData(QtMedia::MetaData key, QVariant const &value) +void QT7PlayerMetaDataControl::setMetaData(QtMultimedia::MetaData key, QVariant const &value) { Q_UNUSED(key); Q_UNUSED(value); } -QList QT7PlayerMetaDataControl::availableMetaData() const +QList QT7PlayerMetaDataControl::availableMetaData() const { return m_tags.keys(); } @@ -243,13 +243,13 @@ void QT7PlayerMetaDataControl::updateTags() metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String])); #endif // QUICKTIME_C_API_AVAILABLE - m_tags.insert(QtMedia::AlbumArtist, metaMap.value(QLatin1String("ART"))); - m_tags.insert(QtMedia::AlbumTitle, metaMap.value(QLatin1String("alb"))); - m_tags.insert(QtMedia::Title, metaMap.value(QLatin1String("nam"))); - m_tags.insert(QtMedia::Date, metaMap.value(QLatin1String("day"))); - m_tags.insert(QtMedia::Genre, metaMap.value(QLatin1String("gnre"))); - m_tags.insert(QtMedia::TrackNumber, metaMap.value(QLatin1String("trk"))); - m_tags.insert(QtMedia::Description, metaMap.value(QLatin1String("des"))); + m_tags.insert(QtMultimedia::AlbumArtist, metaMap.value(QLatin1String("ART"))); + m_tags.insert(QtMultimedia::AlbumTitle, metaMap.value(QLatin1String("alb"))); + m_tags.insert(QtMultimedia::Title, metaMap.value(QLatin1String("nam"))); + m_tags.insert(QtMultimedia::Date, metaMap.value(QLatin1String("day"))); + m_tags.insert(QtMultimedia::Genre, metaMap.value(QLatin1String("gnre"))); + m_tags.insert(QtMultimedia::TrackNumber, metaMap.value(QLatin1String("trk"))); + m_tags.insert(QtMultimedia::Description, metaMap.value(QLatin1String("des"))); } if (!wasEmpty || !m_tags.isEmpty()) -- cgit v0.12 From 8c38a945eaa2c13af4bfc812e80bbccfb2243e5f Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 16:18:33 +1000 Subject: Revert "Added multimedia to qmlviewer" This reverts commit 78967c9f7cfba6142a5f987a1fe81692b479a6d2. --- tools/qmlviewer/qmlviewer.pro | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro index 003115d..35e4ba8 100644 --- a/tools/qmlviewer/qmlviewer.pro +++ b/tools/qmlviewer/qmlviewer.pro @@ -7,10 +7,6 @@ QT += declarative \ network \ sql -contains(QT_CONFIG, multimedia) { - QT += multimedia -} - contains(QT_CONFIG, opengl) { QT += opengl DEFINES += GL_SUPPORTED -- cgit v0.12 From 6fa813a4d5b46523940f6af8ed74e6855bad49c9 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 16:23:26 +1000 Subject: Use the qmlmodule method for adding multimedia qml elements. --- src/multimedia/qml/qmlaudio.cpp | 1 - src/multimedia/qml/qmlaudio_p.h | 2 +- src/multimedia/qml/qmlgraphicsvideo.cpp | 2 - src/multimedia/qml/qmlgraphicsvideo_p.h | 2 +- src/multimedia/qml/qsoundeffect.cpp | 1 - src/multimedia/qml/qsoundeffect_p.h | 2 +- src/plugins/plugins.pro | 2 + src/plugins/qmlmodules/multimedia/multimedia.cpp | 75 ++++++++++++++++++++++++ src/plugins/qmlmodules/multimedia/multimedia.pro | 11 ++++ src/plugins/qmlmodules/qmlmodules.pro | 4 ++ 10 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 src/plugins/qmlmodules/multimedia/multimedia.cpp create mode 100644 src/plugins/qmlmodules/multimedia/multimedia.pro create mode 100644 src/plugins/qmlmodules/qmlmodules.pro diff --git a/src/multimedia/qml/qmlaudio.cpp b/src/multimedia/qml/qmlaudio.cpp index fc340d0..5719050 100644 --- a/src/multimedia/qml/qmlaudio.cpp +++ b/src/multimedia/qml/qmlaudio.cpp @@ -45,7 +45,6 @@ QT_BEGIN_NAMESPACE -QML_DEFINE_TYPE(Qt,4,6,Audio,QmlAudio); /*! \qmlclass Audio QmlAudio diff --git a/src/multimedia/qml/qmlaudio_p.h b/src/multimedia/qml/qmlaudio_p.h index f034518..f6c5cbf 100644 --- a/src/multimedia/qml/qmlaudio_p.h +++ b/src/multimedia/qml/qmlaudio_p.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QTimerEvent; -class Q_AUTOTEST_EXPORT QmlAudio : public QObject, public QmlMediaBase, public QmlParserStatus +class Q_MULTIMEDIA_EXPORT QmlAudio : public QObject, public QmlMediaBase, public QmlParserStatus { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp index 236387e..1dd1f8b 100644 --- a/src/multimedia/qml/qmlgraphicsvideo.cpp +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -50,8 +50,6 @@ QT_BEGIN_NAMESPACE -QML_DEFINE_TYPE(Qt,4,6,Video,QmlGraphicsVideo); - void QmlGraphicsVideo::_q_nativeSizeChanged(const QSizeF &size) { diff --git a/src/multimedia/qml/qmlgraphicsvideo_p.h b/src/multimedia/qml/qmlgraphicsvideo_p.h index a4f8e32..bd15b7f 100644 --- a/src/multimedia/qml/qmlgraphicsvideo_p.h +++ b/src/multimedia/qml/qmlgraphicsvideo_p.h @@ -58,7 +58,7 @@ class QTimerEvent; class QVideoSurfaceFormat; -class Q_AUTOTEST_EXPORT QmlGraphicsVideo : public QmlGraphicsItem, public QmlMediaBase +class Q_MULTIMEDIA_EXPORT QmlGraphicsVideo : public QmlGraphicsItem, public QmlMediaBase { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) diff --git a/src/multimedia/qml/qsoundeffect.cpp b/src/multimedia/qml/qsoundeffect.cpp index b9174b7..1a67414 100644 --- a/src/multimedia/qml/qsoundeffect.cpp +++ b/src/multimedia/qml/qsoundeffect.cpp @@ -52,7 +52,6 @@ #include "qsoundeffect_qsound_p.h" #endif -QML_DEFINE_TYPE(Qt,4,6,SoundEffect,QSoundEffect) /*! \qmlclass QSoundEffect diff --git a/src/multimedia/qml/qsoundeffect_p.h b/src/multimedia/qml/qsoundeffect_p.h index 6d5790d..2610a69 100644 --- a/src/multimedia/qml/qsoundeffect_p.h +++ b/src/multimedia/qml/qsoundeffect_p.h @@ -64,7 +64,7 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QSoundEffectPrivate; -class QSoundEffect : public QObject +class Q_MULTIMEDIA_EXPORT QSoundEffect : public QObject { Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 5eca0f4..dc2266b 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -12,4 +12,6 @@ embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio mediaservices +contains(QT_CONFIG, declarative): SUBDIRS *= qmlmodules + diff --git a/src/plugins/qmlmodules/multimedia/multimedia.cpp b/src/plugins/qmlmodules/multimedia/multimedia.cpp new file mode 100644 index 0000000..9710486 --- /dev/null +++ b/src/plugins/qmlmodules/multimedia/multimedia.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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 plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QMultimediaQmlModule : public QmlModulePlugin +{ + Q_OBJECT +public: + QStringList keys() const + { + return QStringList() << QLatin1String("qt.multimedia"); + } + + void defineModule(const QString& uri) + { + Q_UNUSED(uri) + Q_ASSERT(uri == QLatin1String("qt.multimedia")); + + qmlRegisterType("qt.multimedia", 4, 7, "SoundEffect", "SoundEffect"); + qmlRegisterType("qt.multimedia", 4, 7, "Audio", "Audio"); + qmlRegisterType("qt.multimedia", 4, 7, "Video", "Video"); + } +}; + +QT_END_NAMESPACE + +#include "multimedia.moc" + +Q_EXPORT_PLUGIN2(qmultimediaqmlmodule, QT_PREPEND_NAMESPACE(QMultimediaQmlModule)); + diff --git a/src/plugins/qmlmodules/multimedia/multimedia.pro b/src/plugins/qmlmodules/multimedia/multimedia.pro new file mode 100644 index 0000000..f04cc14 --- /dev/null +++ b/src/plugins/qmlmodules/multimedia/multimedia.pro @@ -0,0 +1,11 @@ +TARGET = multimedia +include(../../qpluginbase.pri) + +QT += multimedia declarative + +SOURCES += multimedia.cpp + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmlmodules +target.path = $$[QT_INSTALL_PLUGINS]/plugins/qmlmodules +INSTALLS += target + diff --git a/src/plugins/qmlmodules/qmlmodules.pro b/src/plugins/qmlmodules/qmlmodules.pro new file mode 100644 index 0000000..b1dc0ef --- /dev/null +++ b/src/plugins/qmlmodules/qmlmodules.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +contains(QT_CONFIG, multimedia): SUBDIRS += multimedia + -- cgit v0.12 From 90b9d45d77b25769834d4b879baff13a3327f4ce Mon Sep 17 00:00:00 2001 From: Dmytro Poplavskiy Date: Fri, 19 Feb 2010 16:28:56 +1000 Subject: QuickTime playback backend: listen for natural size changes and update video outputs. --- .../qt7/mediaplayer/qt7playersession.h | 1 + .../qt7/mediaplayer/qt7playersession.mm | 26 +++++++++++++++++----- src/plugins/mediaservices/qt7/qt7movierenderer.h | 1 + src/plugins/mediaservices/qt7/qt7movierenderer.mm | 15 +++++++------ .../mediaservices/qt7/qt7movievideowidget.h | 1 + .../mediaservices/qt7/qt7movievideowidget.mm | 10 ++++++++- src/plugins/mediaservices/qt7/qt7movieviewoutput.h | 1 + .../mediaservices/qt7/qt7movieviewoutput.mm | 7 +++++- .../mediaservices/qt7/qt7movieviewrenderer.h | 1 + .../mediaservices/qt7/qt7movieviewrenderer.mm | 8 +++++++ .../mediaservices/qt7/qt7videooutputcontrol.h | 2 ++ 11 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h index 8187f72..4742e2e 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.h @@ -109,6 +109,7 @@ public slots: void processEOS(); void processStateChange(); void processVolumeChange(); + void processNaturalSizeChange(); signals: void positionChanged(qint64 position); diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm index 9ea33e4..d1381fe 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -104,6 +104,9 @@ QT_BEGIN_NAMESPACE [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(processVolumeChange:) name: QTMovieVolumeDidChangeNotification object: m_movie]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: + @selector(processNaturalSizeChange:) name: QTMovieNaturalSizeDidChangeNotification object: m_movie]; + [movie retain]; } } @@ -126,6 +129,11 @@ QT_BEGIN_NAMESPACE m_session->processVolumeChange(); } +- (void) processNaturalSizeChange :(NSNotification *)notification +{ + Q_UNUSED(notification); + m_session->processNaturalSizeChange(); +} @end @@ -353,6 +361,8 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) else return; + qDebug() << "Open media" << url; + NSError *err = 0; NSString *urlString = (NSString *)qString2CFStringRef(url.toString()); @@ -415,7 +425,7 @@ void QT7PlayerSession::processStateChange() { signed long state = [[(QTMovie*)m_QTMovie attributeForKey:QTMovieLoadStateAttribute] longValue]; - //qDebug() << "new State:" << state; + qDebug() << "Moview load state changed:" << state; #ifndef QUICKTIME_C_API_AVAILABLE enum { @@ -457,11 +467,6 @@ void QT7PlayerSession::processStateChange() emit durationChanged(duration()); emit audioAvailableChanged(isAudioAvailable()); emit videoAvailableChanged(isVideoAvailable()); - - //give output a change to re-read movie properties - if (m_videoOutput) - m_videoOutput->setMovie(m_QTMovie); - break; case QMediaPlayer::InvalidMedia: emit stateChanged(m_state = QMediaPlayer::StoppedState); @@ -485,6 +490,15 @@ void QT7PlayerSession::processVolumeChange() } } +void QT7PlayerSession::processNaturalSizeChange() +{ + if (m_videoOutput) { + NSSize size = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; + qDebug() << "Native size changed:" << QSize(size.width, size.height); + m_videoOutput->updateNaturalSize(QSize(size.width, size.height)); + } +} + #include "moc_qt7playersession.cpp" QT_END_NAMESPACE diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.h b/src/plugins/mediaservices/qt7/qt7movierenderer.h index 4543152..a547329 100644 --- a/src/plugins/mediaservices/qt7/qt7movierenderer.h +++ b/src/plugins/mediaservices/qt7/qt7movierenderer.h @@ -76,6 +76,7 @@ public: void setEnabled(bool); void setMovie(void *movie); + void updateNaturalSize(const QSize &newSize); QAbstractVideoSurface *surface() const; void setSurface(QAbstractVideoSurface *surface); diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.mm b/src/plugins/mediaservices/qt7/qt7movierenderer.mm index 9a35f5d..587f3b9 100644 --- a/src/plugins/mediaservices/qt7/qt7movierenderer.mm +++ b/src/plugins/mediaservices/qt7/qt7movierenderer.mm @@ -374,17 +374,18 @@ void QT7MovieRenderer::setMovie(void *movie) [(QTMovie*)m_movie retain]; setupVideoOutput(); - } else { - if (m_movie) { - //reset video output if native size was changed - NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; - if (m_nativeSize != QSize(size.width, size.height)) - setupVideoOutput(); - } } #endif } +void QT7MovieRenderer::updateNaturalSize(const QSize &newSize) +{ + if (m_nativeSize != newSize) { + m_nativeSize = newSize; + setupVideoOutput(); + } +} + QAbstractVideoSurface *QT7MovieRenderer::surface() const { return m_surface; diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.h b/src/plugins/mediaservices/qt7/qt7movievideowidget.h index 266dad4..3acd373 100644 --- a/src/plugins/mediaservices/qt7/qt7movievideowidget.h +++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.h @@ -74,6 +74,7 @@ public: void setEnabled(bool); void setMovie(void *movie); + void updateNaturalSize(const QSize &newSize); QWidget *videoWidget(); diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.mm b/src/plugins/mediaservices/qt7/qt7movievideowidget.mm index e1e0162..6e74fcd 100644 --- a/src/plugins/mediaservices/qt7/qt7movievideowidget.mm +++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.mm @@ -256,7 +256,7 @@ void QT7MovieVideoWidget::setupVideoOutput() return; } - NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue]; + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; m_nativeSize = QSize(size.width, size.height); m_videoWidget->setNativeSize(m_nativeSize); @@ -290,6 +290,14 @@ void QT7MovieVideoWidget::setMovie(void *movie) setupVideoOutput(); } +void QT7MovieVideoWidget::updateNaturalSize(const QSize &newSize) +{ + if (m_nativeSize != newSize) { + m_nativeSize = newSize; + setupVideoOutput(); + } +} + bool QT7MovieVideoWidget::isFullScreen() const { return m_fullscreen; diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.h b/src/plugins/mediaservices/qt7/qt7movieviewoutput.h index 7f3ff91..30eefa7 100644 --- a/src/plugins/mediaservices/qt7/qt7movieviewoutput.h +++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.h @@ -65,6 +65,7 @@ public: void setEnabled(bool); void setMovie(void *movie); + void updateNaturalSize(const QSize &newSize); WId winId() const; void setWinId(WId id); diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm index 8182797..b549487 100644 --- a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm +++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm @@ -177,7 +177,7 @@ void QT7MovieViewOutput::setupVideoOutput() if (m_movie == 0 || m_winId <= 0) return; - NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieCurrentSizeAttribute"] sizeValue]; + NSSize size = [[(QTMovie*)m_movie attributeForKey:@"QTMovieNaturalSizeAttribute"] sizeValue]; m_nativeSize = QSize(size.width, size.height); if (!m_movieView) @@ -201,6 +201,11 @@ void QT7MovieViewOutput::setMovie(void *movie) setupVideoOutput(); } +void QT7MovieViewOutput::updateNaturalSize(const QSize &newSize) +{ + m_nativeSize = newSize; +} + WId QT7MovieViewOutput::winId() const { return m_winId; diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h index 6f381f8..336006c 100644 --- a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h +++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h @@ -69,6 +69,7 @@ public: void setEnabled(bool); void setMovie(void *movie); + void updateNaturalSize(const QSize &newSize); QAbstractVideoSurface *surface() const; void setSurface(QAbstractVideoSurface *surface); diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm index e08d0f3..342feb8 100644 --- a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm +++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm @@ -298,6 +298,14 @@ void QT7MovieViewRenderer::setMovie(void *movie) setupVideoOutput(); } +void QT7MovieViewRenderer::updateNaturalSize(const QSize &newSize) +{ + if (m_nativeSize != newSize) { + m_nativeSize = newSize; + setupVideoOutput(); + } +} + QAbstractVideoSurface *QT7MovieViewRenderer::surface() const { return m_surface; diff --git a/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h index 2faf6bb..2c60919 100644 --- a/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h +++ b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h @@ -43,6 +43,7 @@ #define QT7VIDEOOUTPUTCONTROL_H #include +#include #include #include @@ -68,6 +69,7 @@ public: virtual ~QT7VideoOutput() {} virtual void setEnabled(bool enabled) = 0; virtual void setMovie(void *movie) = 0; + virtual void updateNaturalSize(const QSize &newSize) = 0; }; class QT7VideoWindowControl : public QVideoWindowControl, public QT7VideoOutput -- cgit v0.12 From 723d412d2b3fcb2f64594ff75ad94d469285aeb1 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 17:05:50 +1000 Subject: Complete namespace move; QtMedia -> QtMultimedia --- src/multimedia/base/qmediaserviceprovider.cpp | 2 +- src/multimedia/base/qmetadatacontrol.cpp | 6 +- src/multimedia/qml/qmetadatacontrolmetaobject.cpp | 2 +- src/multimedia/qml/qmlgraphicsvideo.cpp | 142 ++++++++++----------- .../mediaplayer/directshowmetadatacontrol.cpp | 18 +-- .../mediaplayer/qgstreamermetadataprovider.cpp | 56 ++++---- .../mediaplayer/qgstreamerplayersession.cpp | 8 +- tests/auto/qmediaobject/tst_qmediaobject.cpp | 38 +++--- .../tst_qmediaserviceprovider.cpp | 32 ++--- tests/auto/qmlaudio/tst_qmlaudio.cpp | 22 ++-- .../auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp | 2 +- 11 files changed, 164 insertions(+), 164 deletions(-) diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp index fcf06d3..8d1e0fa 100644 --- a/src/multimedia/base/qmediaserviceprovider.cpp +++ b/src/multimedia/base/qmediaserviceprovider.cpp @@ -509,7 +509,7 @@ Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider); */ /*! - \fn QtMedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags) const + \fn QtMultimedia::SupportEstimate QMediaServiceProvider::hasSupport(const QByteArray &serviceType, const QString &mimeType, const QStringList& codecs, int flags) const Returns how confident a media service provider is that is can provide a \a serviceType service that is able to play media of a specific \a mimeType that is encoded using the listed diff --git a/src/multimedia/base/qmetadatacontrol.cpp b/src/multimedia/base/qmetadatacontrol.cpp index e45bb0c..3ecbe8d 100644 --- a/src/multimedia/base/qmetadatacontrol.cpp +++ b/src/multimedia/base/qmetadatacontrol.cpp @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE its current media it will implement QMetaDataControl. This control provides functions for both retrieving and setting meta-data values. Meta-data may be addressed by the well defined keys in the - QtMedia::MetaData enumeration using the metaData() functions, or by + QtMultimedia::MetaData enumeration using the metaData() functions, or by string keys using the extendedMetaData() functions. The functionality provided by this control is exposed to application @@ -117,13 +117,13 @@ QMetaDataControl::~QMetaDataControl() */ /*! - \fn QVariant QMetaDataControl::metaData(QtMedia::MetaData key) const + \fn QVariant QMetaDataControl::metaData(QtMultimedia::MetaData key) const Returns the meta-data for the given \a key. */ /*! - \fn void QMetaDataControl::setMetaData(QtMedia::MetaData key, const QVariant &value) + \fn void QMetaDataControl::setMetaData(QtMultimedia::MetaData key, const QVariant &value) Sets the \a value of the meta-data element with the given \a key. */ diff --git a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp index 7f9575e..47b6382 100644 --- a/src/multimedia/qml/qmetadatacontrolmetaobject.cpp +++ b/src/multimedia/qml/qmetadatacontrolmetaobject.cpp @@ -132,7 +132,7 @@ namespace // Media { QtMultimedia::Size, "size" }, { QtMultimedia::MediaType, "mediaType" }, -// { QtMedia::Duration, "duration" }, +// { QtMultimedia::Duration, "duration" }, // Audio { QtMultimedia::AudioBitRate, "audioBitRate" }, diff --git a/src/multimedia/qml/qmlgraphicsvideo.cpp b/src/multimedia/qml/qmlgraphicsvideo.cpp index 1dd1f8b..fde505d 100644 --- a/src/multimedia/qml/qmlgraphicsvideo.cpp +++ b/src/multimedia/qml/qmlgraphicsvideo.cpp @@ -420,7 +420,7 @@ QT_END_NAMESPACE This property holds the tile of the media. - \sa {QtMedia::Title} + \sa {QtMultimedia::Title} */ /*! @@ -428,7 +428,7 @@ QT_END_NAMESPACE This property holds the sub-title of the media. - \sa {QtMedia::SubTitle} + \sa {QtMultimedia::SubTitle} */ /*! @@ -436,7 +436,7 @@ QT_END_NAMESPACE This property holds the author of the media. - \sa {QtMedia::Author} + \sa {QtMultimedia::Author} */ /*! @@ -444,7 +444,7 @@ QT_END_NAMESPACE This property holds a user comment about the media. - \sa {QtMedia::Comment} + \sa {QtMultimedia::Comment} */ /*! @@ -452,7 +452,7 @@ QT_END_NAMESPACE This property holds a description of the media. - \sa {QtMedia::Description} + \sa {QtMultimedia::Description} */ /*! @@ -460,7 +460,7 @@ QT_END_NAMESPACE This property holds the category of the media - \sa {QtMedia::Category} + \sa {QtMultimedia::Category} */ /*! @@ -468,7 +468,7 @@ QT_END_NAMESPACE This property holds the genre of the media. - \sa {QtMedia::Genre} + \sa {QtMultimedia::Genre} */ /*! @@ -476,7 +476,7 @@ QT_END_NAMESPACE This property holds the year of release of the media. - \sa {QtMedia::Year} + \sa {QtMultimedia::Year} */ /*! @@ -484,7 +484,7 @@ QT_END_NAMESPACE This property holds the date of the media. - \sa {QtMedia::Date} + \sa {QtMultimedia::Date} */ /*! @@ -492,7 +492,7 @@ QT_END_NAMESPACE This property holds a user rating of the media in the range of 0 to 100. - \sa {QtMedia::UserRating} + \sa {QtMultimedia::UserRating} */ /*! @@ -500,7 +500,7 @@ QT_END_NAMESPACE This property holds a list of keywords describing the media. - \sa {QtMedia::Keywords} + \sa {QtMultimedia::Keywords} */ /*! @@ -508,7 +508,7 @@ QT_END_NAMESPACE This property holds the language of the media, as an ISO 639-2 code. - \sa {QtMedia::Language} + \sa {QtMultimedia::Language} */ /*! @@ -516,7 +516,7 @@ QT_END_NAMESPACE This property holds the publisher of the media. - \sa {QtMedia::Publisher} + \sa {QtMultimedia::Publisher} */ /*! @@ -524,7 +524,7 @@ QT_END_NAMESPACE This property holds the media's copyright notice. - \sa {QtMedia::Copyright} + \sa {QtMultimedia::Copyright} */ /*! @@ -532,7 +532,7 @@ QT_END_NAMESPACE This property holds the parental rating of the media. - \sa {QtMedia::ParentalRating} + \sa {QtMultimedia::ParentalRating} */ /*! @@ -541,7 +541,7 @@ QT_END_NAMESPACE This property holds the name of the rating organisation responsible for the parental rating of the media. - \sa {QtMedia::RatingOrganisation} + \sa {QtMultimedia::RatingOrganisation} */ /*! @@ -549,7 +549,7 @@ QT_END_NAMESPACE This property property holds the size of the media in bytes. - \sa {QtMedia::Size} + \sa {QtMultimedia::Size} */ /*! @@ -557,7 +557,7 @@ QT_END_NAMESPACE This property holds the type of the media. - \sa {QtMedia::MediaType} + \sa {QtMultimedia::MediaType} */ /*! @@ -566,7 +566,7 @@ QT_END_NAMESPACE This property holds the bit rate of the media's audio stream ni bits per second. - \sa {QtMedia::AudioBitRate} + \sa {QtMultimedia::AudioBitRate} */ /*! @@ -574,7 +574,7 @@ QT_END_NAMESPACE This property holds the encoding of the media audio stream. - \sa {QtMedia::AudioCodec} + \sa {QtMultimedia::AudioCodec} */ /*! @@ -582,7 +582,7 @@ QT_END_NAMESPACE This property holds the average volume level of the media. - \sa {QtMedia::AverageLevel} + \sa {QtMultimedia::AverageLevel} */ /*! @@ -590,7 +590,7 @@ QT_END_NAMESPACE This property holds the number of channels in the media's audio stream. - \sa {QtMedia::ChannelCount} + \sa {QtMultimedia::ChannelCount} */ /*! @@ -598,7 +598,7 @@ QT_END_NAMESPACE This property holds the peak volume of media's audio stream. - \sa {QtMedia::PeakValue} + \sa {QtMultimedia::PeakValue} */ /*! @@ -606,7 +606,7 @@ QT_END_NAMESPACE This property holds the sample rate of the media's audio stream in hertz. - \sa {QtMedia::SampleRate} + \sa {QtMultimedia::SampleRate} */ /*! @@ -614,7 +614,7 @@ QT_END_NAMESPACE This property holds the title of the album the media belongs to. - \sa {QtMedia::AlbumTitle} + \sa {QtMultimedia::AlbumTitle} */ /*! @@ -623,7 +623,7 @@ QT_END_NAMESPACE This property holds the name of the principal artist of the album the media belongs to. - \sa {QtMedia::AlbumArtist} + \sa {QtMultimedia::AlbumArtist} */ /*! @@ -631,7 +631,7 @@ QT_END_NAMESPACE This property holds the names of artists contributing to the media. - \sa {QtMedia::ContributingArtist} + \sa {QtMultimedia::ContributingArtist} */ /*! @@ -639,7 +639,7 @@ QT_END_NAMESPACE This property holds the composer of the media. - \sa {QtMedia::Composer} + \sa {QtMultimedia::Composer} */ /*! @@ -647,7 +647,7 @@ QT_END_NAMESPACE This property holds the conductor of the media. - \sa {QtMedia::Conductor} + \sa {QtMultimedia::Conductor} */ /*! @@ -655,7 +655,7 @@ QT_END_NAMESPACE This property holds the lyrics to the media. - \sa {QtMedia::Lyrics} + \sa {QtMultimedia::Lyrics} */ /*! @@ -663,7 +663,7 @@ QT_END_NAMESPACE This property holds the mood of the media. - \sa {QtMedia::Mood} + \sa {QtMultimedia::Mood} */ /*! @@ -671,7 +671,7 @@ QT_END_NAMESPACE This property holds the track number of the media. - \sa {QtMedia::TrackNumber} + \sa {QtMultimedia::TrackNumber} */ /*! @@ -679,7 +679,7 @@ QT_END_NAMESPACE This property holds the number of track on the album containing the media. - \sa {QtMedia::TrackNumber} + \sa {QtMultimedia::TrackNumber} */ /*! @@ -687,7 +687,7 @@ QT_END_NAMESPACE This property holds the URL of a small cover art image. - \sa {QtMedia::CoverArtUrlSmall} + \sa {QtMultimedia::CoverArtUrlSmall} */ /*! @@ -695,7 +695,7 @@ QT_END_NAMESPACE This property holds the URL of a large cover art image. - \sa {QtMedia::CoverArtUrlLarge} + \sa {QtMultimedia::CoverArtUrlLarge} */ /*! @@ -703,7 +703,7 @@ QT_END_NAMESPACE This property holds the dimension of an image or video. - \sa {QtMedia::Resolution} + \sa {QtMultimedia::Resolution} */ /*! @@ -711,7 +711,7 @@ QT_END_NAMESPACE This property holds the pixel aspect ratio of an image or video. - \sa {QtMedia::PixelAspectRatio} + \sa {QtMultimedia::PixelAspectRatio} */ /*! @@ -719,7 +719,7 @@ QT_END_NAMESPACE This property holds the frame rate of the media's video stream. - \sa {QtMedia::VideoFrameRate} + \sa {QtMultimedia::VideoFrameRate} */ /*! @@ -728,7 +728,7 @@ QT_END_NAMESPACE This property holds the bit rate of the media's video stream in bits per second. - \sa {QtMedia::VideoBitRate} + \sa {QtMultimedia::VideoBitRate} */ /*! @@ -736,7 +736,7 @@ QT_END_NAMESPACE This property holds the encoding of the media's video stream. - \sa {QtMedia::VideoCodec} + \sa {QtMultimedia::VideoCodec} */ /*! @@ -744,7 +744,7 @@ QT_END_NAMESPACE This property holds the URL of a poster image. - \sa {QtMedia::PosterUrl} + \sa {QtMultimedia::PosterUrl} */ /*! @@ -752,7 +752,7 @@ QT_END_NAMESPACE This property holds the chapter number of the media. - \sa {QtMedia::ChapterNumber} + \sa {QtMultimedia::ChapterNumber} */ /*! @@ -760,7 +760,7 @@ QT_END_NAMESPACE This property holds the director of the media. - \sa {QtMedia::Director} + \sa {QtMultimedia::Director} */ /*! @@ -768,7 +768,7 @@ QT_END_NAMESPACE This property holds the lead performer in the media. - \sa {QtMedia::LeadPerformer} + \sa {QtMultimedia::LeadPerformer} */ /*! @@ -776,7 +776,7 @@ QT_END_NAMESPACE This property holds the writer of the media. - \sa {QtMedia::Writer} + \sa {QtMultimedia::Writer} */ // The remaining properties are related to photos, and are technically @@ -786,157 +786,157 @@ QT_END_NAMESPACE /*! \qmlproperty variant Video::cameraManufacturer - \sa {QtMedia::CameraManufacturer} + \sa {QtMultimedia::CameraManufacturer} */ /*! \qmlproperty variant Video::cameraModel - \sa {QtMedia::CameraModel} + \sa {QtMultimedia::CameraModel} */ /*! \qmlproperty variant Video::event - \sa {QtMedia::Event} + \sa {QtMultimedia::Event} */ /*! \qmlproperty variant Video::subject - \sa {QtMedia::Subject} + \sa {QtMultimedia::Subject} */ /*! \qmlproperty variant Video::orientation - \sa {QtMedia::Orientation} + \sa {QtMultimedia::Orientation} */ /*! \qmlproperty variant Video::exposureTime - \sa {QtMedia::ExposureTime} + \sa {QtMultimedia::ExposureTime} */ /*! \qmlproperty variant Video::fNumber - \sa {QtMedia::FNumber} + \sa {QtMultimedia::FNumber} */ /*! \qmlproperty variant Video::exposureProgram - \sa {QtMedia::ExposureProgram} + \sa {QtMultimedia::ExposureProgram} */ /*! \qmlproperty variant Video::isoSpeedRatings - \sa {QtMedia::ISOSpeedRatings} + \sa {QtMultimedia::ISOSpeedRatings} */ /*! \qmlproperty variant Video::exposureBiasValue - \sa {QtMedia::ExposureBiasValue} + \sa {QtMultimedia::ExposureBiasValue} */ /*! \qmlproperty variant Video::dateTimeDigitized - \sa {QtMedia::DateTimeDigitized} + \sa {QtMultimedia::DateTimeDigitized} */ /*! \qmlproperty variant Video::subjectDistance - \sa {QtMedia::SubjectDistance} + \sa {QtMultimedia::SubjectDistance} */ /*! \qmlproperty variant Video::meteringMode - \sa {QtMedia::MeteringMode} + \sa {QtMultimedia::MeteringMode} */ /*! \qmlproperty variant Video::lightSource - \sa {QtMedia::LightSource} + \sa {QtMultimedia::LightSource} */ /*! \qmlproperty variant Video::flash - \sa {QtMedia::Flash} + \sa {QtMultimedia::Flash} */ /*! \qmlproperty variant Video::focalLength - \sa {QtMedia::FocalLength} + \sa {QtMultimedia::FocalLength} */ /*! \qmlproperty variant Video::exposureMode - \sa {QtMedia::ExposureMode} + \sa {QtMultimedia::ExposureMode} */ /*! \qmlproperty variant Video::whiteBalance - \sa {QtMedia::WhiteBalance} + \sa {QtMultimedia::WhiteBalance} */ /*! \qmlproperty variant Video::DigitalZoomRatio - \sa {QtMedia::DigitalZoomRatio} + \sa {QtMultimedia::DigitalZoomRatio} */ /*! \qmlproperty variant Video::focalLengthIn35mmFilm - \sa {QtMedia::FocalLengthIn35mmFile} + \sa {QtMultimedia::FocalLengthIn35mmFile} */ /*! \qmlproperty variant Video::sceneCaptureType - \sa {QtMedia::SceneCaptureType} + \sa {QtMultimedia::SceneCaptureType} */ /*! \qmlproperty variant Video::gainControl - \sa {QtMedia::GainControl} + \sa {QtMultimedia::GainControl} */ /*! \qmlproperty variant Video::contrast - \sa {QtMedia::contrast} + \sa {QtMultimedia::contrast} */ /*! \qmlproperty variant Video::saturation - \sa {QtMedia::Saturation} + \sa {QtMultimedia::Saturation} */ /*! \qmlproperty variant Video::sharpness - \sa {QtMedia::Sharpness} + \sa {QtMultimedia::Sharpness} */ /*! \qmlproperty variant Video::deviceSettingDescription - \sa {QtMedia::DeviceSettingDescription} + \sa {QtMultimedia::DeviceSettingDescription} */ #endif diff --git a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp index 56820d2..7b2552f 100644 --- a/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp +++ b/src/plugins/mediaservices/directshow/mediaplayer/directshowmetadatacontrol.cpp @@ -71,10 +71,10 @@ static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = { QtMultimedia::Description, L"Description" }, { QtMultimedia::Category, L"WM/Category" }, { QtMultimedia::Genre, L"WM/Genre" }, - //{ QtMedia::Date, 0 }, + //{ QtMultimedia::Date, 0 }, { QtMultimedia::Year, L"WM/Year" }, { QtMultimedia::UserRating, L"UserRating" }, - //{ QtMedia::MetaDatawords, 0 }, + //{ QtMultimedia::MetaDatawords, 0 }, { QtMultimedia::Language, L"Language" }, { QtMultimedia::Publisher, L"WM/Publisher" }, { QtMultimedia::Copyright, L"Copyright" }, @@ -101,20 +101,20 @@ static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] = { QtMultimedia::Lyrics, L"WM/Lyrics" }, { QtMultimedia::Mood, L"WM/Mood" }, { QtMultimedia::TrackNumber, L"WM/TrackNumber" }, - //{ QtMedia::TrackCount, 0 }, - //{ QtMedia::CoverArtUriSmall, 0 }, - //{ QtMedia::CoverArtUriLarge, 0 }, + //{ QtMultimedia::TrackCount, 0 }, + //{ QtMultimedia::CoverArtUriSmall, 0 }, + //{ QtMultimedia::CoverArtUriLarge, 0 }, // Image/Video - //{ QtMedia::Resolution, 0 }, - //{ QtMedia::PixelAspectRatio, 0 }, + //{ QtMultimedia::Resolution, 0 }, + //{ QtMultimedia::PixelAspectRatio, 0 }, // Video - //{ QtMedia::FrameRate, 0 }, + //{ QtMultimedia::FrameRate, 0 }, { QtMultimedia::VideoBitRate, L"VideoBitRate" }, { QtMultimedia::VideoCodec, L"VideoCodec" }, - //{ QtMedia::PosterUri, 0 }, + //{ QtMultimedia::PosterUri, 0 }, // Movie { QtMultimedia::ChapterNumber, L"ChapterNumber" }, diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index 456dcfd..49eeb23 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -54,70 +54,70 @@ struct QGstreamerMetaDataKeyLookup static const QGstreamerMetaDataKeyLookup qt_gstreamerMetaDataKeys[] = { { QtMultimedia::Title, GST_TAG_TITLE }, - //{ QtMedia::SubTitle, 0 }, - //{ QtMedia::Author, 0 }, + //{ QtMultimedia::SubTitle, 0 }, + //{ QtMultimedia::Author, 0 }, { QtMultimedia::Comment, GST_TAG_COMMENT }, { QtMultimedia::Description, GST_TAG_DESCRIPTION }, - //{ QtMedia::Category, 0 }, + //{ QtMultimedia::Category, 0 }, { QtMultimedia::Genre, GST_TAG_GENRE }, { QtMultimedia::Year, "year" }, - //{ QtMedia::UserRating, 0 }, + //{ QtMultimedia::UserRating, 0 }, { QtMultimedia::Language, GST_TAG_LANGUAGE_CODE }, { QtMultimedia::Publisher, GST_TAG_ORGANIZATION }, { QtMultimedia::Copyright, GST_TAG_COPYRIGHT }, - //{ QtMedia::ParentalRating, 0 }, - //{ QtMedia::RatingOrganisation, 0 }, + //{ QtMultimedia::ParentalRating, 0 }, + //{ QtMultimedia::RatingOrganisation, 0 }, // Media - //{ QtMedia::Size, 0 }, - //{ QtMedia::MediaType, 0 }, + //{ QtMultimedia::Size, 0 }, + //{ QtMultimedia::MediaType, 0 }, { QtMultimedia::Duration, GST_TAG_DURATION }, // Audio { QtMultimedia::AudioBitRate, GST_TAG_BITRATE }, { QtMultimedia::AudioCodec, GST_TAG_AUDIO_CODEC }, - //{ QtMedia::ChannelCount, 0 }, - //{ QtMedia::Frequency, 0 }, + //{ QtMultimedia::ChannelCount, 0 }, + //{ QtMultimedia::Frequency, 0 }, // Music { QtMultimedia::AlbumTitle, GST_TAG_ALBUM }, { QtMultimedia::AlbumArtist, GST_TAG_ARTIST}, { QtMultimedia::ContributingArtist, GST_TAG_PERFORMER }, #if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - { QtMedia::Composer, GST_TAG_COMPOSER }, + { QtMultimedia::Composer, GST_TAG_COMPOSER }, #endif - //{ QtMedia::Conductor, 0 }, - //{ QtMedia::Lyrics, 0 }, - //{ QtMedia::Mood, 0 }, + //{ QtMultimedia::Conductor, 0 }, + //{ QtMultimedia::Lyrics, 0 }, + //{ QtMultimedia::Mood, 0 }, { QtMultimedia::TrackNumber, GST_TAG_TRACK_NUMBER }, - //{ QtMedia::CoverArtUrlSmall, 0 }, - //{ QtMedia::CoverArtUrlLarge, 0 }, + //{ QtMultimedia::CoverArtUrlSmall, 0 }, + //{ QtMultimedia::CoverArtUrlLarge, 0 }, // Image/Video - //{ QtMedia::Resolution, 0 }, - //{ QtMedia::PixelAspectRatio, 0 }, + //{ QtMultimedia::Resolution, 0 }, + //{ QtMultimedia::PixelAspectRatio, 0 }, // Video - //{ QtMedia::VideoFrameRate, 0 }, - //{ QtMedia::VideoBitRate, 0 }, + //{ QtMultimedia::VideoFrameRate, 0 }, + //{ QtMultimedia::VideoBitRate, 0 }, { QtMultimedia::VideoCodec, GST_TAG_VIDEO_CODEC }, - //{ QtMedia::PosterUrl, 0 }, + //{ QtMultimedia::PosterUrl, 0 }, // Movie - //{ QtMedia::ChapterNumber, 0 }, - //{ QtMedia::Director, 0 }, + //{ QtMultimedia::ChapterNumber, 0 }, + //{ QtMultimedia::Director, 0 }, { QtMultimedia::LeadPerformer, GST_TAG_PERFORMER }, - //{ QtMedia::Writer, 0 }, + //{ QtMultimedia::Writer, 0 }, // Photos - //{ QtMedia::CameraManufacturer, 0 }, - //{ QtMedia::CameraModel, 0 }, - //{ QtMedia::Event, 0 }, - //{ QtMedia::Subject, 0 } + //{ QtMultimedia::CameraManufacturer, 0 }, + //{ QtMultimedia::CameraModel, 0 }, + //{ QtMultimedia::Event, 0 }, + //{ QtMultimedia::Subject, 0 } }; QGstreamerMetaDataProvider::QGstreamerMetaDataProvider(QGstreamerPlayerSession *session, QObject *parent) diff --git a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 6945c2a..2e5d10f 100644 --- a/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/mediaservices/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -616,7 +616,7 @@ void QGstreamerPlayerSession::getStreamsInfo() for (int i=0; i streamProperties; + QMap streamProperties; int streamIndex = i - m_playbin2StreamOffset[streamType]; @@ -638,7 +638,7 @@ void QGstreamerPlayerSession::getStreamsInfo() if (tags && gst_is_tag_list(tags)) { gchar *languageCode = 0; if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode)) - streamProperties[QtMedia::Language] = QString::fromUtf8(languageCode); + streamProperties[QtMultimedia::Language] = QString::fromUtf8(languageCode); //qDebug() << "language for setream" << i << QString::fromUtf8(languageCode); g_free (languageCode); @@ -691,8 +691,8 @@ void QGstreamerPlayerSession::getStreamsInfo() // break; // } // -// QMap streamProperties; -// streamProperties[QtMedia::Language] = QString::fromUtf8(languageCode); +// QMap streamProperties; +// streamProperties[QtMultimedia::Language] = QString::fromUtf8(languageCode); // // m_streamProperties.append(streamProperties); // m_streamTypes.append(streamType); diff --git a/tests/auto/qmediaobject/tst_qmediaobject.cpp b/tests/auto/qmediaobject/tst_qmediaobject.cpp index 1dbb2c1..2128b35 100644 --- a/tests/auto/qmediaobject/tst_qmediaobject.cpp +++ b/tests/auto/qmediaobject/tst_qmediaobject.cpp @@ -93,13 +93,13 @@ public: if (m_available != available) emit metaDataAvailableChanged(m_available = available); } - QList availableMetaData() const { return m_data.keys(); } + QList availableMetaData() const { return m_data.keys(); } bool isWritable() const { return m_writable; } void setWritable(bool writable) { emit writableChanged(m_writable = writable); } - QVariant metaData(QtMedia::MetaData key) const { return m_data.value(key); } - void setMetaData(QtMedia::MetaData key, const QVariant &value) { + QVariant metaData(QtMultimedia::MetaData key) const { return m_data.value(key); } + void setMetaData(QtMultimedia::MetaData key, const QVariant &value) { m_data.insert(key, value); } QVariant extendedMetaData(const QString &key) const { return m_extendedData.value(key); } @@ -117,7 +117,7 @@ public: bool m_available; bool m_writable; - QMap m_data; + QMap m_data; QMap m_extendedData; }; @@ -376,12 +376,12 @@ void tst_QMediaObject::nullMetaDataControl() QCOMPARE(object.isMetaDataAvailable(), false); QCOMPARE(object.isMetaDataWritable(), false); - object.setMetaData(QtMedia::Title, title); + object.setMetaData(QtMultimedia::Title, title); object.setExtendedMetaData(titleKey, title); - QCOMPARE(object.metaData(QtMedia::Title).toString(), QString()); + QCOMPARE(object.metaData(QtMultimedia::Title).toString(), QString()); QCOMPARE(object.extendedMetaData(titleKey).toString(), QString()); - QCOMPARE(object.availableMetaData(), QList()); + QCOMPARE(object.availableMetaData(), QList()); QCOMPARE(object.availableExtendedMetaData(), QStringList()); QCOMPARE(spy.count(), 0); } @@ -470,18 +470,18 @@ void tst_QMediaObject::metaData() QtTestMediaObject object(&service); QVERIFY(object.availableMetaData().isEmpty()); - service.metaData.m_data.insert(QtMedia::AlbumArtist, artist); - service.metaData.m_data.insert(QtMedia::Title, title); - service.metaData.m_data.insert(QtMedia::Genre, genre); + service.metaData.m_data.insert(QtMultimedia::AlbumArtist, artist); + service.metaData.m_data.insert(QtMultimedia::Title, title); + service.metaData.m_data.insert(QtMultimedia::Genre, genre); - QCOMPARE(object.metaData(QtMedia::AlbumArtist).toString(), artist); - QCOMPARE(object.metaData(QtMedia::Title).toString(), title); + QCOMPARE(object.metaData(QtMultimedia::AlbumArtist).toString(), artist); + QCOMPARE(object.metaData(QtMultimedia::Title).toString(), title); - QList metaDataKeys = object.availableMetaData(); + QList metaDataKeys = object.availableMetaData(); QCOMPARE(metaDataKeys.size(), 3); - QVERIFY(metaDataKeys.contains(QtMedia::AlbumArtist)); - QVERIFY(metaDataKeys.contains(QtMedia::Title)); - QVERIFY(metaDataKeys.contains(QtMedia::Genre)); + QVERIFY(metaDataKeys.contains(QtMultimedia::AlbumArtist)); + QVERIFY(metaDataKeys.contains(QtMultimedia::Title)); + QVERIFY(metaDataKeys.contains(QtMultimedia::Genre)); } void tst_QMediaObject::setMetaData_data() @@ -501,9 +501,9 @@ void tst_QMediaObject::setMetaData() QtTestMediaObject object(&service); - object.setMetaData(QtMedia::Title, title); - QCOMPARE(object.metaData(QtMedia::Title).toString(), title); - QCOMPARE(service.metaData.m_data.value(QtMedia::Title).toString(), title); + object.setMetaData(QtMultimedia::Title, title); + QCOMPARE(object.metaData(QtMultimedia::Title).toString(), title); + QCOMPARE(service.metaData.m_data.value(QtMultimedia::Title).toString(), title); } void tst_QMediaObject::extendedMetaData() diff --git a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp index 9409394..9bca189 100644 --- a/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp +++ b/tests/auto/qmediaserviceprovider/tst_qmediaserviceprovider.cpp @@ -88,16 +88,16 @@ public: delete service; } - QtMedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + QtMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const { if (codecs.contains(QLatin1String("mpeg4"))) - return QtMedia::NotSupported; + return QtMultimedia::NotSupported; if (mimeType == "audio/ogg") { - return QtMedia::ProbablySupported; + return QtMultimedia::ProbablySupported; } - return QtMedia::MaybeSupported; + return QtMultimedia::MaybeSupported; } QStringList supportedMimeTypes() const @@ -147,14 +147,14 @@ public: delete service; } - QtMedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const + QtMultimedia::SupportEstimate hasSupport(const QString &mimeType, const QStringList& codecs) const { Q_UNUSED(codecs); if (mimeType == "audio/wav") - return QtMedia::PreferedService; + return QtMultimedia::PreferedService; - return QtMedia::NotSupported; + return QtMultimedia::NotSupported; } QStringList supportedMimeTypes() const @@ -282,7 +282,7 @@ void tst_QMediaServiceProvider::testHasSupport() { MockMediaServiceProvider mockProvider; QCOMPARE(mockProvider.hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()), - QtMedia::MaybeSupported); + QtMultimedia::MaybeSupported); QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); @@ -290,27 +290,27 @@ void tst_QMediaServiceProvider::testHasSupport() QSKIP("No default provider", SkipSingle); QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "video/ogv", QStringList()), - QtMedia::MaybeSupported); + QtMultimedia::MaybeSupported); QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/ogg", QStringList()), - QtMedia::ProbablySupported); + QtMultimedia::ProbablySupported); //while the service returns PreferredService, provider should return ProbablySupported QCOMPARE(provider->hasSupport(QByteArray(Q_MEDIASERVICE_MEDIAPLAYER), "audio/wav", QStringList()), - QtMedia::ProbablySupported); + QtMultimedia::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"), - QtMedia::MaybeSupported); + QtMultimedia::MaybeSupported); QCOMPARE(provider->hasSupport(QByteArray("non existing service"), "video/ogv", QStringList()), - QtMedia::NotSupported); + QtMultimedia::NotSupported); - QCOMPARE(QMediaPlayer::hasSupport("video/ogv"), QtMedia::MaybeSupported); - QCOMPARE(QMediaPlayer::hasSupport("audio/ogg"), QtMedia::ProbablySupported); - QCOMPARE(QMediaPlayer::hasSupport("audio/wav"), QtMedia::ProbablySupported); + QCOMPARE(QMediaPlayer::hasSupport("video/ogv"), QtMultimedia::MaybeSupported); + QCOMPARE(QMediaPlayer::hasSupport("audio/ogg"), QtMultimedia::ProbablySupported); + QCOMPARE(QMediaPlayer::hasSupport("audio/wav"), QtMultimedia::ProbablySupported); //ensure the correct media player plugin is choosen for mime type QMediaPlayer simplePlayer(0, QMediaPlayer::LowLatency); diff --git a/tests/auto/qmlaudio/tst_qmlaudio.cpp b/tests/auto/qmlaudio/tst_qmlaudio.cpp index cb205ac..068317f 100644 --- a/tests/auto/qmlaudio/tst_qmlaudio.cpp +++ b/tests/auto/qmlaudio/tst_qmlaudio.cpp @@ -76,7 +76,7 @@ private slots: void error(); }; -Q_DECLARE_METATYPE(QtMedia::MetaData); +Q_DECLARE_METATYPE(QtMultimedia::MetaData); Q_DECLARE_METATYPE(QmlAudio::Error); class QtTestMediaPlayerControl : public QMediaPlayerControl @@ -192,20 +192,20 @@ public: bool isWritable() const { return true; } bool isMetaDataAvailable() const { return true; } - QVariant metaData(QtMedia::MetaData key) const { return m_metaData.value(key); } - void setMetaData(QtMedia::MetaData key, const QVariant &value) { + QVariant metaData(QtMultimedia::MetaData key) const { return m_metaData.value(key); } + void setMetaData(QtMultimedia::MetaData key, const QVariant &value) { m_metaData.insert(key, value); emit metaDataChanged(); } - void setMetaData(const QMap &metaData) { + void setMetaData(const QMap &metaData) { m_metaData = metaData; emit metaDataChanged(); } - QList availableMetaData() const { return m_metaData.keys(); } + QList availableMetaData() const { return m_metaData.keys(); } QVariant extendedMetaData(const QString &) const { return QVariant(); } void setExtendedMetaData(const QString &, const QVariant &) {} QStringList availableExtendedMetaData() const { return QStringList(); } private: - QMap m_metaData; + QMap m_metaData; }; class QtTestMediaService : public QMediaService @@ -1108,25 +1108,25 @@ void tst_QmlAudio::status() void tst_QmlAudio::metaData_data() { QTest::addColumn("propertyName"); - QTest::addColumn("propertyKey"); + QTest::addColumn("propertyKey"); QTest::addColumn("value1"); QTest::addColumn("value2"); QTest::newRow("title") << QByteArray("title") - << QtMedia::Title + << QtMultimedia::Title << QVariant(QString::fromLatin1("This is a title")) << QVariant(QString::fromLatin1("This is another title")); QTest::newRow("genre") << QByteArray("genre") - << QtMedia::Genre + << QtMultimedia::Genre << QVariant(QString::fromLatin1("rock")) << QVariant(QString::fromLatin1("pop")); QTest::newRow("trackNumber") << QByteArray("trackNumber") - << QtMedia::TrackNumber + << QtMultimedia::TrackNumber << QVariant(8) << QVariant(12); } @@ -1134,7 +1134,7 @@ void tst_QmlAudio::metaData_data() void tst_QmlAudio::metaData() { QFETCH(QByteArray, propertyName); - QFETCH(QtMedia::MetaData, propertyKey); + QFETCH(QtMultimedia::MetaData, propertyKey); QFETCH(QVariant, value1); QFETCH(QVariant, value2); diff --git a/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp b/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp index a09a6a2..0da094d 100644 --- a/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp +++ b/tests/auto/qmlgraphicsvideo/tst_qmlgraphicsvideo.cpp @@ -73,7 +73,7 @@ private slots: void geometry(); }; -Q_DECLARE_METATYPE(QtMedia::MetaData); +Q_DECLARE_METATYPE(QtMultimedia::MetaData); Q_DECLARE_METATYPE(QmlGraphicsVideo::Error); class QtTestMediaPlayerControl : public QMediaPlayerControl -- cgit v0.12 From f95a3014171361672c3307b8dd080e5369d6e017 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 17:11:35 +1000 Subject: Lowercase Q to uppercase in QML elment URI. --- src/plugins/qmlmodules/multimedia/multimedia.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/qmlmodules/multimedia/multimedia.cpp b/src/plugins/qmlmodules/multimedia/multimedia.cpp index 9710486..381fb56 100644 --- a/src/plugins/qmlmodules/multimedia/multimedia.cpp +++ b/src/plugins/qmlmodules/multimedia/multimedia.cpp @@ -53,17 +53,17 @@ class QMultimediaQmlModule : public QmlModulePlugin public: QStringList keys() const { - return QStringList() << QLatin1String("qt.multimedia"); + return QStringList() << QLatin1String("Qt.multimedia"); } void defineModule(const QString& uri) { Q_UNUSED(uri) - Q_ASSERT(uri == QLatin1String("qt.multimedia")); + Q_ASSERT(uri == QLatin1String("Qt.multimedia")); - qmlRegisterType("qt.multimedia", 4, 7, "SoundEffect", "SoundEffect"); - qmlRegisterType("qt.multimedia", 4, 7, "Audio", "Audio"); - qmlRegisterType("qt.multimedia", 4, 7, "Video", "Video"); + qmlRegisterType("Qt.multimedia", 4, 7, "SoundEffect", "SoundEffect"); + qmlRegisterType("Qt.multimedia", 4, 7, "Audio", "Audio"); + qmlRegisterType("Qt.multimedia", 4, 7, "Video", "Video"); } }; -- cgit v0.12 From baac955843c7eefe7a6f94fbb696a2d3cfa2afba Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 17:15:05 +1000 Subject: QT7; make compile on 10.5. --- src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm index d1381fe..74b1cae 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -104,9 +104,10 @@ QT_BEGIN_NAMESPACE [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(processVolumeChange:) name: QTMovieVolumeDidChangeNotification object: m_movie]; + /* [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(processNaturalSizeChange:) name: QTMovieNaturalSizeDidChangeNotification object: m_movie]; - + */ [movie retain]; } } -- cgit v0.12 From d51b797d9003dff128e72fbd5e26a48c040c9d98 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 17:40:10 +1000 Subject: Use old notification name for OSX < 10.6. --- .../mediaservices/qt7/mediaplayer/qt7playersession.mm | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm index 74b1cae..2a82ffa 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -101,13 +101,15 @@ QT_BEGIN_NAMESPACE [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(processStateChange:) name: QTMovieLoadStateDidChangeNotification object: m_movie]; - [[NSNotificationCenter defaultCenter] addObserver: self selector: - @selector(processVolumeChange:) name: QTMovieVolumeDidChangeNotification object: m_movie]; - - /* - [[NSNotificationCenter defaultCenter] addObserver: self selector: - @selector(processNaturalSizeChange:) name: QTMovieNaturalSizeDidChangeNotification object: m_movie]; - */ + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(processVolumeChange:) + name: +#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) + QTMovieNaturalSizeDidChangeNotification +#else + QTMovieEditedNotification +#endif + object: m_movie]; [movie retain]; } } -- cgit v0.12 From b817c92f1fc1a2ae0f566940fea3f43630fb9783 Mon Sep 17 00:00:00 2001 From: Justin McPherson Date: Fri, 19 Feb 2010 17:49:28 +1000 Subject: QT5; Add back volume notification. --- .../qt7/mediaplayer/qt7playersession.mm | 31 ++++++++++++++-------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm index 2a82ffa..5507633 100644 --- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm +++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm @@ -95,21 +95,30 @@ QT_BEGIN_NAMESPACE m_movie = movie; if (movie) { - [[NSNotificationCenter defaultCenter] addObserver: self selector: - @selector(processEOS:) name: QTMovieDidEndNotification object: m_movie]; - - [[NSNotificationCenter defaultCenter] addObserver: self selector: - @selector(processStateChange:) name: QTMovieLoadStateDidChangeNotification object: m_movie]; - - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector(processVolumeChange:) + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(processEOS:) + name:QTMovieDidEndNotification + object:m_movie]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(processStateChange:) + name:QTMovieLoadStateDidChangeNotification + object:m_movie]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(processVolumeChange:) + name:QTMovieVolumeDidChangeNotification + object:m_movie]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(processNaturalSizeChange:) name: #if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) - QTMovieNaturalSizeDidChangeNotification + QTMovieNaturalSizeDidChangeNotification #else - QTMovieEditedNotification + QTMovieEditedNotification #endif - object: m_movie]; + object:m_movie]; [movie retain]; } } -- cgit v0.12