summaryrefslogtreecommitdiffstats
path: root/src/plugins/qnx/mediaplayer
diff options
context:
space:
mode:
authorFrank Osterfeld <frank.osterfeld.qnx@kdab.com>2013-11-05 14:28:08 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-09 12:23:53 +0100
commit99667804e1c64cace1246d4ce342a218fc1fb1ba (patch)
tree8cf7716d447f9f2dace3efd2877a8683a99c6d4e /src/plugins/qnx/mediaplayer
parent66219c9a289db01808a15b6416dea1b4cf9314dd (diff)
QNX: Restructure plugins
Now that the MmRenderer implementation is ported to plain QNX, rename the directories and files accordingly: "blackberry" becomes "qnx", replace the Bb prefix with MmRenderer for classes concerned with mm-renderer. The legacy alsa support for plain qnx is now "qnx-audio". Change-Id: I6abd98ecdd713b2d5e554d42224dc30f13772f43 Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
Diffstat (limited to 'src/plugins/qnx/mediaplayer')
-rw-r--r--src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp117
-rw-r--r--src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h66
-rw-r--r--src/plugins/qnx/mediaplayer/mediaplayer.pri31
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp634
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h172
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp149
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h78
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp269
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermetadata.h99
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp170
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h68
-rw-r--r--src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp158
-rw-r--r--src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h84
-rw-r--r--src/plugins/qnx/mediaplayer/mmrendererutil.cpp129
-rw-r--r--src/plugins/qnx/mediaplayer/mmrendererutil.h58
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp414
-rw-r--r--src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h120
-rw-r--r--src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp199
-rw-r--r--src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h75
19 files changed, 3090 insertions, 0 deletions
diff --git a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp
new file mode 100644
index 000000000..dde03ad59
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "bpsmediaplayercontrol.h"
+#include "mmrenderervideowindowcontrol.h"
+
+#include <bps/mmrenderer.h>
+#include <bps/screen.h>
+
+QT_BEGIN_NAMESPACE
+
+BpsMediaPlayerControl::BpsMediaPlayerControl(QObject *parent)
+ : MmRendererMediaPlayerControl(parent),
+ m_eventMonitor(0)
+{
+ openConnection();
+}
+
+BpsMediaPlayerControl::~BpsMediaPlayerControl()
+{
+ destroy();
+}
+
+void BpsMediaPlayerControl::startMonitoring(int contextId, const QString &contextName)
+{
+ m_eventMonitor = mmrenderer_request_events(contextName.toLatin1().constData(), 0, contextId);
+ if (!m_eventMonitor) {
+ qDebug() << "Unable to request multimedia events";
+ emit error(0, "Unable to request multimedia events");
+ }
+}
+
+void BpsMediaPlayerControl::stopMonitoring()
+{
+ if (m_eventMonitor) {
+ mmrenderer_stop_events(m_eventMonitor);
+ m_eventMonitor = 0;
+ }
+}
+
+bool BpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+{
+ Q_UNUSED(result)
+ Q_UNUSED(eventType)
+
+ bps_event_t * const event = static_cast<bps_event_t *>(message);
+ if (!event ||
+ (bps_event_get_domain(event) != mmrenderer_get_domain() &&
+ bps_event_get_domain(event) != screen_get_domain()))
+ return false;
+
+ if (event && bps_event_get_domain(event) == screen_get_domain()) {
+ const screen_event_t screen_event = screen_event_get_event(event);
+ if (MmRendererVideoWindowControl *control = videoWindowControl())
+ control->screenEventHandler(screen_event);
+ }
+
+ if (bps_event_get_domain(event) == mmrenderer_get_domain()) {
+ if (bps_event_get_code(event) == MMRENDERER_STATE_CHANGE) {
+ const mmrenderer_state_t newState = mmrenderer_event_get_state(event);
+ if (newState == MMR_STOPPED) {
+ handleMmStopped();
+ return false;
+ }
+ }
+
+ if (bps_event_get_code(event) == MMRENDERER_STATUS_UPDATE) {
+ const qint64 newPosition = QString::fromLatin1(mmrenderer_event_get_position(event)).toLongLong();
+ handleMmStatusUpdate(newPosition);
+
+ const QString bufferStatus = QString::fromLatin1(mmrenderer_event_get_bufferlevel(event));
+ setMmBufferStatus(bufferStatus);
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h
new file mode 100644
index 000000000..f0c132346
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/bpsmediaplayercontrol.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef BPSMEDIAPLAYERCONTROL_H
+#define BPSMEDIAPLAYERCONTROL_H
+
+#include "mmrenderermediaplayercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class BpsMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ explicit BpsMediaPlayerControl(QObject *parent = 0);
+ ~BpsMediaPlayerControl();
+
+ void startMonitoring(int contextId, const QString &contextName) Q_DECL_OVERRIDE;
+ void stopMonitoring() Q_DECL_OVERRIDE;
+
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
+
+private:
+ mmrenderer_monitor_t *m_eventMonitor;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mediaplayer.pri b/src/plugins/qnx/mediaplayer/mediaplayer.pri
new file mode 100644
index 000000000..9dedab0fd
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mediaplayer.pri
@@ -0,0 +1,31 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/mmrenderermediaplayercontrol.h \
+ $$PWD/mmrenderermediaplayerservice.h \
+ $$PWD/mmrenderermetadata.h \
+ $$PWD/mmrenderermetadatareadercontrol.h \
+ $$PWD/mmrendererplayervideorenderercontrol.h \
+ $$PWD/mmrendererutil.h \
+ $$PWD/mmrenderervideowindowcontrol.h
+
+SOURCES += \
+ $$PWD/mmrenderermediaplayercontrol.cpp \
+ $$PWD/mmrenderermediaplayerservice.cpp \
+ $$PWD/mmrenderermetadata.cpp \
+ $$PWD/mmrenderermetadatareadercontrol.cpp \
+ $$PWD/mmrendererplayervideorenderercontrol.cpp \
+ $$PWD/mmrendererutil.cpp \
+ $$PWD/mmrenderervideowindowcontrol.cpp
+
+LIBS += -lmmrndclient -lstrm
+
+blackberry {
+ HEADERS += $$PWD/bpsmediaplayercontrol.h
+ SOURCES += $$PWD/bpsmediaplayercontrol.cpp
+} else {
+ HEADERS += $$PWD/ppsmediaplayercontrol.h
+ SOURCES += $$PWD/ppsmediaplayercontrol.cpp
+ QT += core-private
+ LIBS += -lpps
+}
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp
new file mode 100644
index 000000000..2a376198b
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp
@@ -0,0 +1,634 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "mmrenderermediaplayercontrol.h"
+#include "mmrenderermetadatareadercontrol.h"
+#include "mmrendererplayervideorenderercontrol.h"
+#include "mmrendererutil.h"
+#include "mmrenderervideowindowcontrol.h"
+#include <QtCore/qabstracteventdispatcher.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/quuid.h>
+#include <mm/renderer.h>
+
+#include <errno.h>
+#include <sys/strm.h>
+#include <sys/stat.h>
+
+QT_BEGIN_NAMESPACE
+
+static int idCounter = 0;
+
+MmRendererMediaPlayerControl::MmRendererMediaPlayerControl(QObject *parent)
+ : QMediaPlayerControl(parent),
+ m_connection(0),
+ m_context(0),
+ m_audioId(-1),
+ m_state(QMediaPlayer::StoppedState),
+ m_volume(100),
+ m_muted(false),
+ m_rate(1),
+ m_id(-1),
+ m_position(0),
+ m_mediaStatus(QMediaPlayer::NoMedia),
+ m_playAfterMediaLoaded(false),
+ m_inputAttached(false),
+ m_stopEventsToIgnore(0),
+ m_bufferStatus(0)
+{
+ m_loadingTimer.setSingleShot(true);
+ m_loadingTimer.setInterval(0);
+ connect(&m_loadingTimer, SIGNAL(timeout()), this, SLOT(continueLoadMedia()));
+ QCoreApplication::eventDispatcher()->installNativeEventFilter(this);
+}
+
+void MmRendererMediaPlayerControl::destroy()
+{
+ stop();
+ detach();
+ closeConnection();
+ QCoreApplication::eventDispatcher()->removeNativeEventFilter(this);
+}
+
+void MmRendererMediaPlayerControl::openConnection()
+{
+ m_connection = mmr_connect(NULL);
+ if (!m_connection) {
+ emitPError("Unable to connect to the multimedia renderer");
+ return;
+ }
+
+ m_id = idCounter++;
+ m_contextName = QString("MmRendererMediaPlayerControl_%1_%2").arg(m_id)
+ .arg(QCoreApplication::applicationPid());
+ m_context = mmr_context_create(m_connection, m_contextName.toLatin1(),
+ 0, S_IRWXU|S_IRWXG|S_IRWXO);
+ if (!m_context) {
+ emitPError("Unable to create context");
+ closeConnection();
+ return;
+ }
+
+ startMonitoring(m_id, m_contextName);
+}
+
+void MmRendererMediaPlayerControl::handleMmStatusUpdate(qint64 newPosition)
+{
+ // Prevent spurious position change events from overriding our own position, for example
+ // when setting the position to 0 in stop().
+ // Also, don't change the position while we're loading the media, as then play() would
+ // set a wrong initial position.
+ if (m_state != QMediaPlayer::PlayingState ||
+ m_mediaStatus == QMediaPlayer::LoadingMedia ||
+ m_mediaStatus == QMediaPlayer::NoMedia ||
+ m_mediaStatus == QMediaPlayer::InvalidMedia)
+ return;
+
+ setMmPosition(newPosition);
+}
+
+void MmRendererMediaPlayerControl::handleMmStopped()
+{
+ // Only react to stop events that happen when the end of the stream is reached and
+ // playback is stopped because of this.
+ // Ignore other stop event sources, souch as calling mmr_stop() ourselves and
+ // mmr_input_attach().
+ if (m_stopEventsToIgnore > 0) {
+ --m_stopEventsToIgnore;
+ } else {
+ setMediaStatus(QMediaPlayer::EndOfMedia);
+ stopInternal(IgnoreMmRenderer);
+ }
+}
+
+void MmRendererMediaPlayerControl::closeConnection()
+{
+ stopMonitoring();
+
+ if (m_context) {
+ mmr_context_destroy(m_context);
+ m_context = 0;
+ m_contextName.clear();
+ }
+
+ if (m_connection) {
+ mmr_disconnect(m_connection);
+ m_connection = 0;
+ }
+}
+
+QByteArray MmRendererMediaPlayerControl::resourcePathForUrl(const QUrl &url)
+{
+ // If this is a local file, mmrenderer expects the file:// prefix and an absolute path.
+ // We treat URLs without scheme as local files, most likely someone just forgot to set the
+ // file:// prefix when constructing the URL.
+ if (url.isLocalFile() || url.scheme().isEmpty()) {
+ QString relativeFilePath;
+ if (!url.scheme().isEmpty())
+ relativeFilePath = url.toLocalFile();
+ else
+ relativeFilePath = url.path();
+ const QFileInfo fileInfo(relativeFilePath);
+ return QFile::encodeName(QStringLiteral("file://") + fileInfo.absoluteFilePath());
+
+ // QRC, copy to temporary file, as mmrenderer does not support resource files
+ } else if (url.scheme() == QStringLiteral("qrc")) {
+ const QString qrcPath = ':' + url.path();
+ const QFileInfo resourceFileInfo(qrcPath);
+ m_tempMediaFileName = QDir::tempPath() + QStringLiteral("/qtmedia_") +
+ QUuid::createUuid().toString() + QStringLiteral(".") +
+ resourceFileInfo.suffix();
+ if (!QFile::copy(qrcPath, m_tempMediaFileName)) {
+ const QString errorMsg = QString("Failed to copy resource file to temporary file "
+ "%1 for playback").arg(m_tempMediaFileName);
+ qDebug() << errorMsg;
+ emit error(0, errorMsg);
+ return QByteArray();
+ }
+ return QFile::encodeName(m_tempMediaFileName);
+
+ // HTTP or similar URL
+ } else {
+ return url.toEncoded();
+ }
+}
+
+void MmRendererMediaPlayerControl::attach()
+{
+ // Should only be called in detached state
+ Q_ASSERT(m_audioId == -1 && !m_inputAttached && m_tempMediaFileName.isEmpty());
+
+ if (m_media.isNull() || !m_context) {
+ setMediaStatus(QMediaPlayer::NoMedia);
+ return;
+ }
+
+ if (m_videoRendererControl)
+ m_videoRendererControl->attachDisplay(m_context);
+
+ if (m_videoWindowControl)
+ m_videoWindowControl->attachDisplay(m_context);
+
+ m_audioId = mmr_output_attach(m_context, "audio:default", "audio");
+ if (m_audioId == -1) {
+ emitMmError("mmr_output_attach() for audio failed");
+ return;
+ }
+
+ const QByteArray resourcePath = resourcePathForUrl(m_media.canonicalUrl());
+ if (resourcePath.isEmpty()) {
+ detach();
+ return;
+ }
+
+ if (mmr_input_attach(m_context, resourcePath.constData(), "track") != 0) {
+ emitMmError(QStringLiteral("mmr_input_attach() failed for ") + QString(resourcePath));
+ setMediaStatus(QMediaPlayer::InvalidMedia);
+ detach();
+ return;
+ }
+
+ // For whatever reason, the mmrenderer sends out a MMR_STOPPED event when calling
+ // mmr_input_attach() above. Ignore it, as otherwise we'll trigger stopping right after we
+ // started.
+ m_stopEventsToIgnore++;
+
+ m_inputAttached = true;
+ setMediaStatus(QMediaPlayer::LoadedMedia);
+ m_bufferStatus = 0;
+ emit bufferStatusChanged(m_bufferStatus);
+}
+
+void MmRendererMediaPlayerControl::detach()
+{
+ if (m_context) {
+ if (m_inputAttached) {
+ mmr_input_detach(m_context);
+ m_inputAttached = false;
+ }
+ if (m_videoRendererControl)
+ m_videoRendererControl->detachDisplay();
+ if (m_videoWindowControl)
+ m_videoWindowControl->detachDisplay();
+ if (m_audioId != -1 && m_context) {
+ mmr_output_detach(m_context, m_audioId);
+ m_audioId = -1;
+ }
+ }
+
+ if (!m_tempMediaFileName.isEmpty()) {
+ QFile::remove(m_tempMediaFileName);
+ m_tempMediaFileName.clear();
+ }
+ m_loadingTimer.stop();
+}
+
+QMediaPlayer::State MmRendererMediaPlayerControl::state() const
+{
+ return m_state;
+}
+
+QMediaPlayer::MediaStatus MmRendererMediaPlayerControl::mediaStatus() const
+{
+ return m_mediaStatus;
+}
+
+qint64 MmRendererMediaPlayerControl::duration() const
+{
+ return m_metaData.duration();
+}
+
+qint64 MmRendererMediaPlayerControl::position() const
+{
+ return m_position;
+}
+
+void MmRendererMediaPlayerControl::setPosition(qint64 position)
+{
+ if (m_position != position) {
+ m_position = position;
+
+ // Don't update in stopped state, it would not have any effect. Instead, the position is
+ // updated in play().
+ if (m_state != QMediaPlayer::StoppedState)
+ setPositionInternal(m_position);
+
+ emit positionChanged(m_position);
+ }
+}
+
+int MmRendererMediaPlayerControl::volume() const
+{
+ return m_volume;
+}
+
+void MmRendererMediaPlayerControl::setVolumeInternal(int newVolume)
+{
+ if (!m_context)
+ return;
+
+ newVolume = qBound(0, newVolume, 100);
+ if (m_audioId != -1) {
+ strm_dict_t * dict = strm_dict_new();
+ dict = strm_dict_set(dict, "volume", QString::number(newVolume).toLatin1());
+ if (mmr_output_parameters(m_context, m_audioId, dict) != 0)
+ emitMmError("mmr_output_parameters: Setting volume failed");
+ }
+}
+
+void MmRendererMediaPlayerControl::setPlaybackRateInternal(qreal rate)
+{
+ if (!m_context)
+ return;
+
+ const int mmRate = rate * 1000;
+ if (mmr_speed_set(m_context, mmRate) != 0)
+ emitMmError("mmr_speed_set failed");
+}
+
+void MmRendererMediaPlayerControl::setPositionInternal(qint64 position)
+{
+ if (!m_context)
+ return;
+
+ if (m_metaData.isSeekable()) {
+ if (mmr_seek(m_context, QString::number(position).toLatin1()) != 0)
+ emitMmError("Seeking failed");
+ }
+}
+
+void MmRendererMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status)
+{
+ if (m_mediaStatus != status) {
+ m_mediaStatus = status;
+ emit mediaStatusChanged(m_mediaStatus);
+ }
+}
+
+void MmRendererMediaPlayerControl::setState(QMediaPlayer::State state)
+{
+ if (m_state != state) {
+ if (m_videoRendererControl) {
+ if (state == QMediaPlayer::PausedState)
+ m_videoRendererControl->pause();
+ else if ((state == QMediaPlayer::PlayingState)
+ && (m_state == QMediaPlayer::PausedState)) {
+ m_videoRendererControl->resume();
+ }
+ }
+
+ m_state = state;
+ emit stateChanged(m_state);
+ }
+}
+
+void MmRendererMediaPlayerControl::stopInternal(StopCommand stopCommand)
+{
+ if (m_state != QMediaPlayer::StoppedState) {
+
+ if (stopCommand == StopMmRenderer) {
+ ++m_stopEventsToIgnore;
+ mmr_stop(m_context);
+ }
+
+ setState(QMediaPlayer::StoppedState);
+ }
+
+ if (m_position != 0) {
+ m_position = 0;
+ emit positionChanged(0);
+ }
+}
+
+void MmRendererMediaPlayerControl::setVolume(int volume)
+{
+ const int newVolume = qBound(0, volume, 100);
+ if (m_volume != newVolume) {
+ m_volume = newVolume;
+ if (!m_muted)
+ setVolumeInternal(m_volume);
+ emit volumeChanged(m_volume);
+ }
+}
+
+bool MmRendererMediaPlayerControl::isMuted() const
+{
+ return m_muted;
+}
+
+void MmRendererMediaPlayerControl::setMuted(bool muted)
+{
+ if (m_muted != muted) {
+ m_muted = muted;
+ setVolumeInternal(muted ? 0 : m_volume);
+ emit mutedChanged(muted);
+ }
+}
+
+int MmRendererMediaPlayerControl::bufferStatus() const
+{
+ return m_bufferStatus;
+}
+
+bool MmRendererMediaPlayerControl::isAudioAvailable() const
+{
+ return m_metaData.hasAudio();
+}
+
+bool MmRendererMediaPlayerControl::isVideoAvailable() const
+{
+ return m_metaData.hasVideo();
+}
+
+bool MmRendererMediaPlayerControl::isSeekable() const
+{
+ return m_metaData.isSeekable();
+}
+
+QMediaTimeRange MmRendererMediaPlayerControl::availablePlaybackRanges() const
+{
+ // We can't get this information from the mmrenderer API yet, so pretend we can seek everywhere
+ return QMediaTimeRange(0, m_metaData.duration());
+}
+
+qreal MmRendererMediaPlayerControl::playbackRate() const
+{
+ return m_rate;
+}
+
+void MmRendererMediaPlayerControl::setPlaybackRate(qreal rate)
+{
+ if (m_rate != rate) {
+ m_rate = rate;
+ setPlaybackRateInternal(m_rate);
+ emit playbackRateChanged(m_rate);
+ }
+}
+
+QMediaContent MmRendererMediaPlayerControl::media() const
+{
+ return m_media;
+}
+
+const QIODevice *MmRendererMediaPlayerControl::mediaStream() const
+{
+ // Always 0, we don't support QIODevice streams
+ return 0;
+}
+
+void MmRendererMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream)
+{
+ Q_UNUSED(stream); // not supported
+
+ stop();
+ detach();
+
+ m_media = media;
+ emit mediaChanged(m_media);
+
+ // Slight hack: With MediaPlayer QtQuick elements that have autoPlay set to true, playback
+ // would start before the QtQuick canvas is propagated to all elements, and therefore our
+ // video output would not work. Therefore, delay actually playing the media a bit so that the
+ // canvas is ready.
+ // The mmrenderer doesn't allow to attach video outputs after playing has started, otherwise
+ // this would be unnecessary.
+ if (!m_media.isNull()) {
+ setMediaStatus(QMediaPlayer::LoadingMedia);
+ m_loadingTimer.start(); // singleshot timer to continueLoadMedia()
+ } else {
+ continueLoadMedia(); // still needed, as it will update the media status and clear metadata
+ }
+}
+
+void MmRendererMediaPlayerControl::continueLoadMedia()
+{
+ attach();
+ updateMetaData();
+ if (m_playAfterMediaLoaded)
+ play();
+}
+
+QString MmRendererMediaPlayerControl::contextName() const
+{
+ return m_contextName;
+}
+
+MmRendererVideoWindowControl *MmRendererMediaPlayerControl::videoWindowControl() const
+{
+ return m_videoWindowControl;
+}
+
+void MmRendererMediaPlayerControl::play()
+{
+ if (m_playAfterMediaLoaded)
+ m_playAfterMediaLoaded = false;
+
+ // No-op if we are already playing, except if we were called from continueLoadMedia(), in which
+ // case m_playAfterMediaLoaded is true (hence the 'else').
+ else if (m_state == QMediaPlayer::PlayingState)
+ return;
+
+ if (m_mediaStatus == QMediaPlayer::LoadingMedia) {
+
+ // State changes are supposed to be synchronous
+ setState(QMediaPlayer::PlayingState);
+
+ // Defer playing to later, when the timer triggers continueLoadMedia()
+ m_playAfterMediaLoaded = true;
+ return;
+ }
+
+ // Un-pause the state when it is paused
+ if (m_state == QMediaPlayer::PausedState) {
+ setPlaybackRateInternal(m_rate);
+ setState(QMediaPlayer::PlayingState);
+ return;
+ }
+
+ if (m_media.isNull() || !m_connection || !m_context || m_audioId == -1) {
+ setState(QMediaPlayer::StoppedState);
+ return;
+ }
+
+ setPositionInternal(m_position);
+ setVolumeInternal(m_volume);
+ setPlaybackRateInternal(m_rate);
+
+ if (mmr_play(m_context) != 0) {
+ setState(QMediaPlayer::StoppedState);
+ emitMmError("mmr_play() failed");
+ return;
+ }
+
+ setState( QMediaPlayer::PlayingState);
+}
+
+void MmRendererMediaPlayerControl::pause()
+{
+ if (m_state == QMediaPlayer::PlayingState) {
+ setPlaybackRateInternal(0);
+ setState(QMediaPlayer::PausedState);
+ }
+}
+
+void MmRendererMediaPlayerControl::stop()
+{
+ stopInternal(StopMmRenderer);
+}
+
+MmRendererPlayerVideoRendererControl *MmRendererMediaPlayerControl::videoRendererControl() const
+{
+ return m_videoRendererControl;
+}
+
+void MmRendererMediaPlayerControl::setVideoRendererControl(MmRendererPlayerVideoRendererControl *videoControl)
+{
+ m_videoRendererControl = videoControl;
+}
+
+void MmRendererMediaPlayerControl::setVideoWindowControl(MmRendererVideoWindowControl *videoControl)
+{
+ m_videoWindowControl = videoControl;
+}
+
+void MmRendererMediaPlayerControl::setMetaDataReaderControl(MmRendererMetaDataReaderControl *metaDataReaderControl)
+{
+ m_metaDataReaderControl = metaDataReaderControl;
+}
+
+void MmRendererMediaPlayerControl::setMmPosition(qint64 newPosition)
+{
+ if (newPosition != 0 && newPosition != m_position) {
+ m_position = newPosition;
+ emit positionChanged(m_position);
+ }
+}
+
+void MmRendererMediaPlayerControl::setMmBufferStatus(const QString &bufferStatus)
+{
+ const int slashPos = bufferStatus.indexOf('/');
+ if (slashPos != -1) {
+ const int fill = bufferStatus.left(slashPos).toInt();
+ const int capacity = bufferStatus.mid(slashPos + 1).toInt();
+ if (capacity != 0) {
+ m_bufferStatus = fill / static_cast<float>(capacity) * 100.0f;
+ emit bufferStatusChanged(m_bufferStatus);
+ }
+ }
+}
+
+void MmRendererMediaPlayerControl::updateMetaData()
+{
+ if (m_mediaStatus == QMediaPlayer::LoadedMedia)
+ m_metaData.parse(m_contextName);
+ else
+ m_metaData.clear();
+
+ if (m_videoWindowControl)
+ m_videoWindowControl->setMetaData(m_metaData);
+
+ if (m_metaDataReaderControl)
+ m_metaDataReaderControl->setMetaData(m_metaData);
+
+ emit durationChanged(m_metaData.duration());
+ emit audioAvailableChanged(m_metaData.hasAudio());
+ emit videoAvailableChanged(m_metaData.hasVideo());
+ emit availablePlaybackRangesChanged(availablePlaybackRanges());
+ emit seekableChanged(m_metaData.isSeekable());
+}
+
+void MmRendererMediaPlayerControl::emitMmError(const QString &msg)
+{
+ int errorCode = MMR_ERROR_NONE;
+ const QString errorMessage = mmErrorMessage(msg, m_context, &errorCode);
+ qDebug() << errorMessage;
+ emit error(errorCode, errorMessage);
+}
+
+void MmRendererMediaPlayerControl::emitPError(const QString &msg)
+{
+ const QString errorMessage = QString("%1: %2").arg(msg).arg(strerror(errno));
+ qDebug() << errorMessage;
+ emit error(errno, errorMessage);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h
new file mode 100644
index 000000000..a22e71bfc
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERMEDIAPLAYERCONTROL_H
+#define MMRENDERERMEDIAPLAYERCONTROL_H
+
+#include "mmrenderermetadata.h"
+#include <qmediaplayercontrol.h>
+#include <QtCore/qabstractnativeeventfilter.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qtimer.h>
+
+typedef struct mmr_connection mmr_connection_t;
+typedef struct mmr_context mmr_context_t;
+typedef struct mmrenderer_monitor mmrenderer_monitor_t;
+
+QT_BEGIN_NAMESPACE
+
+class MmRendererMetaDataReaderControl;
+class MmRendererPlayerVideoRendererControl;
+class MmRendererVideoWindowControl;
+
+class MmRendererMediaPlayerControl : public QMediaPlayerControl, public QAbstractNativeEventFilter
+{
+ Q_OBJECT
+public:
+ explicit MmRendererMediaPlayerControl(QObject *parent = 0);
+
+ QMediaPlayer::State state() const Q_DECL_OVERRIDE;
+
+ QMediaPlayer::MediaStatus mediaStatus() const Q_DECL_OVERRIDE;
+
+ qint64 duration() const Q_DECL_OVERRIDE;
+
+ qint64 position() const Q_DECL_OVERRIDE;
+ void setPosition(qint64 position) Q_DECL_OVERRIDE;
+
+ int volume() const Q_DECL_OVERRIDE;
+ void setVolume(int volume) Q_DECL_OVERRIDE;
+
+ bool isMuted() const Q_DECL_OVERRIDE;
+ void setMuted(bool muted) Q_DECL_OVERRIDE;
+
+ int bufferStatus() const Q_DECL_OVERRIDE;
+
+ bool isAudioAvailable() const Q_DECL_OVERRIDE;
+ bool isVideoAvailable() const Q_DECL_OVERRIDE;
+
+ bool isSeekable() const Q_DECL_OVERRIDE;
+
+ QMediaTimeRange availablePlaybackRanges() const Q_DECL_OVERRIDE;
+
+ qreal playbackRate() const Q_DECL_OVERRIDE;
+ void setPlaybackRate(qreal rate) Q_DECL_OVERRIDE;
+
+ QMediaContent media() const Q_DECL_OVERRIDE;
+ const QIODevice *mediaStream() const Q_DECL_OVERRIDE;
+ void setMedia(const QMediaContent &media, QIODevice *stream) Q_DECL_OVERRIDE;
+
+ void play() Q_DECL_OVERRIDE;
+ void pause() Q_DECL_OVERRIDE;
+ void stop() Q_DECL_OVERRIDE;
+
+ MmRendererPlayerVideoRendererControl *videoRendererControl() const;
+ void setVideoRendererControl(MmRendererPlayerVideoRendererControl *videoControl);
+
+ MmRendererVideoWindowControl *videoWindowControl() const;
+ void setVideoWindowControl(MmRendererVideoWindowControl *videoControl);
+ void setMetaDataReaderControl(MmRendererMetaDataReaderControl *metaDataReaderControl);
+
+protected:
+ virtual void startMonitoring(int contextId, const QString &contextName) = 0;
+ virtual void stopMonitoring() = 0;
+
+ QString contextName() const;
+ void openConnection();
+ void emitMmError(const QString &msg);
+ void emitPError(const QString &msg);
+ void setMmPosition(qint64 newPosition);
+ void setMmBufferStatus(const QString &bufferStatus);
+ void handleMmStopped();
+ void handleMmStatusUpdate(qint64 position);
+
+ // must be called from subclass dtors (calls virtual function stopMonitoring())
+ void destroy();
+
+private Q_SLOTS:
+ void continueLoadMedia();
+
+private:
+ QByteArray resourcePathForUrl(const QUrl &url);
+ void closeConnection();
+ void attach();
+ void detach();
+ void updateMetaData();
+
+ // All these set the specified value to the backend, but neither emit changed signals
+ // nor change the member value.
+ void setVolumeInternal(int newVolume);
+ void setPlaybackRateInternal(qreal rate);
+ void setPositionInternal(qint64 position);
+
+ void setMediaStatus(QMediaPlayer::MediaStatus status);
+ void setState(QMediaPlayer::State state);
+
+ enum StopCommand { StopMmRenderer, IgnoreMmRenderer };
+ void stopInternal(StopCommand stopCommand);
+
+ QMediaContent m_media;
+ mmr_connection_t *m_connection;
+ mmr_context_t *m_context;
+ QString m_contextName;
+ int m_audioId;
+ QMediaPlayer::State m_state;
+ int m_volume;
+ bool m_muted;
+ qreal m_rate;
+ QPointer<MmRendererPlayerVideoRendererControl> m_videoRendererControl;
+ QPointer<MmRendererVideoWindowControl> m_videoWindowControl;
+ QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl;
+ MmRendererMetaData m_metaData;
+ int m_id;
+ qint64 m_position;
+ QMediaPlayer::MediaStatus m_mediaStatus;
+ bool m_playAfterMediaLoaded;
+ bool m_inputAttached;
+ int m_stopEventsToIgnore;
+ int m_bufferStatus;
+ QString m_tempMediaFileName;
+ QTimer m_loadingTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp
new file mode 100644
index 000000000..1e75674e3
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.cpp
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "mmrenderermediaplayerservice.h"
+
+#include "mmrenderermediaplayercontrol.h"
+#include "mmrenderermetadatareadercontrol.h"
+#include "mmrendererplayervideorenderercontrol.h"
+#include "mmrendererutil.h"
+#include "mmrenderervideowindowcontrol.h"
+
+#ifdef Q_OS_BLACKBERRY
+#include "bpsmediaplayercontrol.h"
+typedef BpsMediaPlayerControl PlatformSpecificMediaPlayerControl;
+#else
+#include "ppsmediaplayercontrol.h"
+typedef PpsMediaPlayerControl PlatformSpecificMediaPlayerControl;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+MmRendererMediaPlayerService::MmRendererMediaPlayerService(QObject *parent)
+ : QMediaService(parent),
+ m_videoRendererControl(0),
+ m_videoWindowControl(0),
+ m_mediaPlayerControl(0),
+ m_metaDataReaderControl(0),
+ m_appHasDrmPermission(false),
+ m_appHasDrmPermissionChecked(false)
+{
+}
+
+MmRendererMediaPlayerService::~MmRendererMediaPlayerService()
+{
+ // Someone should have called releaseControl(), but better be safe
+ delete m_videoRendererControl;
+ delete m_videoWindowControl;
+ delete m_mediaPlayerControl;
+ delete m_metaDataReaderControl;
+}
+
+QMediaControl *MmRendererMediaPlayerService::requestControl(const char *name)
+{
+ if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
+ if (!m_mediaPlayerControl) {
+ m_mediaPlayerControl = new PlatformSpecificMediaPlayerControl;
+ updateControls();
+ }
+ return m_mediaPlayerControl;
+ }
+ else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) {
+ if (!m_metaDataReaderControl) {
+ m_metaDataReaderControl = new MmRendererMetaDataReaderControl();
+ updateControls();
+ }
+ return m_metaDataReaderControl;
+ }
+ else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+ if (!m_appHasDrmPermissionChecked) {
+ m_appHasDrmPermission = checkForDrmPermission();
+ m_appHasDrmPermissionChecked = true;
+ }
+
+ if (m_appHasDrmPermission) {
+ // When the application wants to play back DRM secured media, we can't use
+ // the QVideoRendererControl, because we won't have access to the pixel data
+ // in this case.
+ return 0;
+ }
+
+ if (!m_videoRendererControl) {
+ m_videoRendererControl = new MmRendererPlayerVideoRendererControl();
+ updateControls();
+ }
+ return m_videoRendererControl;
+ }
+ else if (qstrcmp(name, QVideoWindowControl_iid) == 0) {
+ if (!m_videoWindowControl) {
+ m_videoWindowControl = new MmRendererVideoWindowControl();
+ updateControls();
+ }
+ return m_videoWindowControl;
+ }
+ return 0;
+}
+
+void MmRendererMediaPlayerService::releaseControl(QMediaControl *control)
+{
+ if (control == m_videoRendererControl)
+ m_videoRendererControl = 0;
+ if (control == m_videoWindowControl)
+ m_videoWindowControl = 0;
+ if (control == m_mediaPlayerControl)
+ m_mediaPlayerControl = 0;
+ if (control == m_metaDataReaderControl)
+ m_metaDataReaderControl = 0;
+ delete control;
+}
+
+void MmRendererMediaPlayerService::updateControls()
+{
+ if (m_videoRendererControl && m_mediaPlayerControl)
+ m_mediaPlayerControl->setVideoRendererControl(m_videoRendererControl);
+
+ if (m_videoWindowControl && m_mediaPlayerControl)
+ m_mediaPlayerControl->setVideoWindowControl(m_videoWindowControl);
+
+ if (m_metaDataReaderControl && m_mediaPlayerControl)
+ m_mediaPlayerControl->setMetaDataReaderControl(m_metaDataReaderControl);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h
new file mode 100644
index 000000000..3d55de8d5
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayerservice.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERMEDIAPLAYERSERVICE_H
+#define MMRENDERERMEDIAPLAYERSERVICE_H
+
+#include <qmediaservice.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class MmRendererMediaPlayerControl;
+class MmRendererMetaDataReaderControl;
+class MmRendererPlayerVideoRendererControl;
+class MmRendererVideoWindowControl;
+
+class MmRendererMediaPlayerService : public QMediaService
+{
+ Q_OBJECT
+public:
+ explicit MmRendererMediaPlayerService(QObject *parent = 0);
+ ~MmRendererMediaPlayerService();
+
+ QMediaControl *requestControl(const char *name) Q_DECL_OVERRIDE;
+ void releaseControl(QMediaControl *control) Q_DECL_OVERRIDE;
+
+private:
+ void updateControls();
+
+ QPointer<MmRendererPlayerVideoRendererControl> m_videoRendererControl;
+ QPointer<MmRendererVideoWindowControl> m_videoWindowControl;
+ QPointer<MmRendererMediaPlayerControl> m_mediaPlayerControl;
+ QPointer<MmRendererMetaDataReaderControl> m_metaDataReaderControl;
+
+ bool m_appHasDrmPermission : 1;
+ bool m_appHasDrmPermissionChecked : 1;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp b/src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp
new file mode 100644
index 000000000..07f5ddd62
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermetadata.cpp
@@ -0,0 +1,269 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "mmrenderermetadata.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+MmRendererMetaData::MmRendererMetaData()
+{
+ clear();
+}
+
+static const char * titleKey = "md_title_name";
+static const char * artistKey = "md_title_artist";
+static const char * commentKey = "md_title_comment";
+static const char * genreKey = "md_title_genre";
+static const char * yearKey = "md_title_year";
+static const char * durationKey = "md_title_duration";
+static const char * bitRateKey = "md_title_bitrate";
+static const char * sampleKey = "md_title_samplerate";
+static const char * albumKey = "md_title_album";
+static const char * trackKey = "md_title_track";
+static const char * widthKey = "md_video_width";
+static const char * heightKey = "md_video_height";
+static const char * mediaTypeKey = "md_title_mediatype";
+static const char * pixelWidthKey = "md_video_pixel_width";
+static const char * pixelHeightKey = "md_video_pixel_height";
+static const char * seekableKey = "md_title_seekable";
+
+static const int mediaTypeAudioFlag = 4;
+static const int mediaTypeVideoFlag = 2;
+
+bool MmRendererMetaData::parse(const QString &contextName)
+{
+ clear();
+ QString fileName =
+ QString("/pps/services/multimedia/renderer/context/%1/metadata").arg(contextName);
+
+ // In newer OS versions, the filename is "metadata0", not metadata, so try both.
+ if (!QFile::exists(fileName))
+ fileName += '0';
+
+ QFile metaDataFile(fileName);
+ if (!metaDataFile.open(QFile::ReadOnly)) {
+ qWarning() << "Unable to open media metadata file" << fileName << ":"
+ << metaDataFile.errorString();
+ return false;
+ }
+
+ const QString separator("::");
+ QTextStream stream(&metaDataFile);
+ Q_FOREVER {
+ const QString line = stream.readLine();
+ if (line.isNull())
+ break;
+
+ const int separatorPos = line.indexOf(separator);
+ if (separatorPos != -1) {
+ const QString key = line.left(separatorPos);
+ const QString value = line.mid(separatorPos + separator.length());
+
+ if (key == durationKey)
+ m_duration = value.toLongLong();
+ else if (key == widthKey)
+ m_width = value.toInt();
+ else if (key == heightKey)
+ m_height = value.toInt();
+ else if (key == mediaTypeKey)
+ m_mediaType = value.toInt();
+ else if (key == pixelWidthKey)
+ m_pixelWidth = value.toFloat();
+ else if (key == pixelHeightKey)
+ m_pixelHeight = value.toFloat();
+ else if (key == titleKey)
+ m_title = value;
+ else if (key == seekableKey)
+ m_seekable = !(value == QLatin1String("0"));
+ else if (key == artistKey)
+ m_artist = value;
+ else if (key == commentKey)
+ m_comment = value;
+ else if (key == genreKey)
+ m_genre = value;
+ else if (key == yearKey)
+ m_year = value.toInt();
+ else if (key == bitRateKey)
+ m_audioBitRate = value.toInt();
+ else if (key == sampleKey)
+ m_sampleRate = value.toInt();
+ else if (key == albumKey)
+ m_album = value;
+ else if (key == trackKey)
+ m_track = value.toInt();
+ }
+ }
+
+ return true;
+}
+
+void MmRendererMetaData::clear()
+{
+ m_duration = 0;
+ m_height = 0;
+ m_width = 0;
+ m_mediaType = -1;
+ m_pixelWidth = 1;
+ m_pixelHeight = 1;
+ m_seekable = true;
+ m_title.clear();
+ m_artist.clear();
+ m_comment.clear();
+ m_genre.clear();
+ m_year = 0;
+ m_audioBitRate = 0;
+ m_sampleRate = 0;
+ m_album.clear();
+ m_track = 0;
+}
+
+qlonglong MmRendererMetaData::duration() const
+{
+ return m_duration;
+}
+
+// Handling of pixel aspect ratio
+//
+// If the pixel aspect ratio is different from 1:1, it means the video needs to be stretched in
+// order to look natural.
+// For example, if the pixel width is 2, and the pixel height is 1, it means a video of 300x200
+// pixels needs to be displayed as 600x200 to look correct.
+// In order to support this the easiest way, we simply pretend that the actual size of the video
+// is 600x200, which will cause the video to be displayed in an aspect ratio of 3:1 instead of 3:2,
+// and therefore look correct.
+
+int MmRendererMetaData::height() const
+{
+ return m_height * m_pixelHeight;
+}
+
+int MmRendererMetaData::width() const
+{
+ return m_width * m_pixelWidth;
+}
+
+bool MmRendererMetaData::hasVideo() const
+{
+ // By default, assume no video if we can't extract the information
+ if (m_mediaType == -1)
+ return false;
+
+ return (m_mediaType & mediaTypeVideoFlag);
+}
+
+bool MmRendererMetaData::hasAudio() const
+{
+ // By default, assume audio only if we can't extract the information
+ if (m_mediaType == -1)
+ return true;
+
+ return (m_mediaType & mediaTypeAudioFlag);
+}
+
+QString MmRendererMetaData::title() const
+{
+ return m_title;
+}
+
+bool MmRendererMetaData::isSeekable() const
+{
+ return m_seekable;
+}
+
+QString MmRendererMetaData::artist() const
+{
+ return m_artist;
+}
+
+QString MmRendererMetaData::comment() const
+{
+ return m_comment;
+}
+
+QString MmRendererMetaData::genre() const
+{
+ return m_genre;
+}
+
+int MmRendererMetaData::year() const
+{
+ return m_year;
+}
+
+QString MmRendererMetaData::mediaType() const
+{
+ if (hasVideo())
+ return QLatin1String("video");
+ else if (hasAudio())
+ return QLatin1String("audio");
+ else
+ return QString();
+}
+
+int MmRendererMetaData::audioBitRate() const
+{
+ return m_audioBitRate;
+}
+
+int MmRendererMetaData::sampleRate() const
+{
+ return m_sampleRate;
+}
+
+QString MmRendererMetaData::album() const
+{
+ return m_album;
+}
+
+int MmRendererMetaData::track() const
+{
+ return m_track;
+}
+
+QSize MmRendererMetaData::resolution() const
+{
+ return QSize(width(), height());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadata.h b/src/plugins/qnx/mediaplayer/mmrenderermetadata.h
new file mode 100644
index 000000000..deb848a80
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermetadata.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERMETADATA_H
+#define MMRENDERERMETADATA_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QSize>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class MmRendererMetaData
+{
+public:
+ MmRendererMetaData();
+ bool parse(const QString &contextName);
+ void clear();
+
+ // Duration in milliseconds
+ qlonglong duration() const;
+
+ int height() const;
+ int width() const;
+ bool hasVideo() const;
+ bool hasAudio() const;
+ bool isSeekable() const;
+
+ QString title() const;
+ QString artist() const;
+ QString comment() const;
+ QString genre() const;
+ int year() const;
+ QString mediaType() const;
+ int audioBitRate() const;
+ int sampleRate() const;
+ QString album() const;
+ int track() const;
+ QSize resolution() const;
+
+private:
+ qlonglong m_duration;
+ int m_height;
+ int m_width;
+ int m_mediaType;
+ float m_pixelWidth;
+ float m_pixelHeight;
+ bool m_seekable;
+ QString m_title;
+ QString m_artist;
+ QString m_comment;
+ QString m_genre;
+ int m_year;
+ int m_audioBitRate;
+ int m_sampleRate;
+ QString m_album;
+ int m_track;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp
new file mode 100644
index 000000000..c0fe7d085
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "mmrenderermetadatareadercontrol.h"
+#include <QtMultimedia/qmediametadata.h>
+
+QT_BEGIN_NAMESPACE
+
+MmRendererMetaDataReaderControl::MmRendererMetaDataReaderControl(QObject *parent)
+ : QMetaDataReaderControl(parent)
+{
+}
+
+bool MmRendererMetaDataReaderControl::isMetaDataAvailable() const
+{
+ return !availableMetaData().isEmpty();
+}
+
+QVariant MmRendererMetaDataReaderControl::metaData(const QString &key) const
+{
+ if (key == QMediaMetaData::Title)
+ return m_metaData.title();
+ else if (key == QMediaMetaData::Author)
+ return m_metaData.artist();
+ else if (key == QMediaMetaData::Comment)
+ return m_metaData.comment();
+ else if (key == QMediaMetaData::Genre)
+ return m_metaData.genre();
+ else if (key == QMediaMetaData::Year)
+ return m_metaData.year();
+ else if (key == QMediaMetaData::MediaType)
+ return m_metaData.mediaType();
+ else if (key == QMediaMetaData::Duration)
+ return m_metaData.duration();
+ else if (key == QMediaMetaData::AudioBitRate)
+ return m_metaData.audioBitRate();
+ else if (key == QMediaMetaData::SampleRate)
+ return m_metaData.sampleRate();
+ else if (key == QMediaMetaData::AlbumTitle)
+ return m_metaData.album();
+ else if (key == QMediaMetaData::TrackNumber)
+ return m_metaData.track();
+ else if (key == QMediaMetaData::Resolution)
+ return m_metaData.resolution();
+
+ return QVariant();
+}
+
+QStringList MmRendererMetaDataReaderControl::availableMetaData() const
+{
+ QStringList metaData;
+
+ if (!m_metaData.title().isEmpty())
+ metaData << QMediaMetaData::Title;
+ if (!m_metaData.artist().isEmpty())
+ metaData << QMediaMetaData::Author;
+ if (!m_metaData.comment().isEmpty())
+ metaData << QMediaMetaData::Comment;
+ if (!m_metaData.genre().isEmpty())
+ metaData << QMediaMetaData::Genre;
+ if (m_metaData.year() != 0)
+ metaData << QMediaMetaData::Year;
+ if (!m_metaData.mediaType().isEmpty())
+ metaData << QMediaMetaData::MediaType;
+ if (m_metaData.duration() != 0)
+ metaData << QMediaMetaData::Duration;
+ if (m_metaData.audioBitRate() != 0)
+ metaData << QMediaMetaData::AudioBitRate;
+ if (m_metaData.sampleRate() != 0)
+ metaData << QMediaMetaData::SampleRate;
+ if (!m_metaData.album().isEmpty())
+ metaData << QMediaMetaData::AlbumTitle;
+ if (m_metaData.track() != 0)
+ metaData << QMediaMetaData::TrackNumber;
+ if (m_metaData.resolution().isValid())
+ metaData << QMediaMetaData::Resolution;
+
+ return metaData;
+}
+
+void MmRendererMetaDataReaderControl::setMetaData(const MmRendererMetaData &data)
+{
+ const MmRendererMetaData oldMetaData = m_metaData;
+ const bool oldMetaDataAvailable = isMetaDataAvailable();
+
+ m_metaData = data;
+
+ bool changed = false;
+ if (m_metaData.title() != oldMetaData.title()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Title, m_metaData.title());
+ } else if (m_metaData.artist() != oldMetaData.artist()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Author, m_metaData.artist());
+ } else if (m_metaData.comment() != oldMetaData.comment()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Comment, m_metaData.comment());
+ } else if (m_metaData.genre() != oldMetaData.genre()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Genre, m_metaData.genre());
+ } else if (m_metaData.year() != oldMetaData.year()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Year, m_metaData.year());
+ } else if (m_metaData.mediaType() != oldMetaData.mediaType()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::MediaType, m_metaData.mediaType());
+ } else if (m_metaData.duration() != oldMetaData.duration()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Duration, m_metaData.duration());
+ } else if (m_metaData.audioBitRate() != oldMetaData.audioBitRate()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::AudioBitRate, m_metaData.audioBitRate());
+ } else if (m_metaData.sampleRate() != oldMetaData.sampleRate()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::SampleRate, m_metaData.sampleRate());
+ } else if (m_metaData.album() != oldMetaData.album()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::AlbumTitle, m_metaData.album());
+ } else if (m_metaData.track() != oldMetaData.track()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::TrackNumber, m_metaData.track());
+ } else if (m_metaData.resolution() != oldMetaData.resolution()) {
+ changed = true;
+ emit metaDataChanged(QMediaMetaData::Resolution, m_metaData.resolution());
+ }
+
+ if (changed)
+ emit metaDataChanged();
+
+ const bool metaDataAvailable = isMetaDataAvailable();
+ if (metaDataAvailable != oldMetaDataAvailable)
+ emit metaDataAvailableChanged(metaDataAvailable);
+}
diff --git a/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h
new file mode 100644
index 000000000..f824ca4d0
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderermetadatareadercontrol.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERMETADATAREADERCONTROL_H
+#define MMRENDERERMETADATAREADERCONTROL_H
+
+#include "mmrenderermetadata.h"
+#include <qmetadatareadercontrol.h>
+
+QT_BEGIN_NAMESPACE
+
+class MmRendererMetaDataReaderControl : public QMetaDataReaderControl
+{
+ Q_OBJECT
+public:
+ explicit MmRendererMetaDataReaderControl(QObject *parent = 0);
+
+ bool isMetaDataAvailable() const Q_DECL_OVERRIDE;
+
+ QVariant metaData(const QString &key) const Q_DECL_OVERRIDE;
+ QStringList availableMetaData() const Q_DECL_OVERRIDE;
+
+ void setMetaData(const MmRendererMetaData &data);
+
+private:
+ MmRendererMetaData m_metaData;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp
new file mode 100644
index 000000000..0abdfec49
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mmrendererplayervideorenderercontrol.h"
+
+#include "windowgrabber.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QVideoSurfaceFormat>
+
+#include <mm/renderer.h>
+
+QT_BEGIN_NAMESPACE
+
+static int winIdCounter = 0;
+
+MmRendererPlayerVideoRendererControl::MmRendererPlayerVideoRendererControl(QObject *parent)
+ : QVideoRendererControl(parent)
+ , m_windowGrabber(new WindowGrabber(this))
+ , m_context(0)
+ , m_videoId(-1)
+{
+ connect(m_windowGrabber, SIGNAL(frameGrabbed(QImage)), SLOT(frameGrabbed(QImage)));
+}
+
+MmRendererPlayerVideoRendererControl::~MmRendererPlayerVideoRendererControl()
+{
+ detachDisplay();
+}
+
+QAbstractVideoSurface *MmRendererPlayerVideoRendererControl::surface() const
+{
+ return m_surface;
+}
+
+void MmRendererPlayerVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
+{
+ m_surface = QPointer<QAbstractVideoSurface>(surface);
+}
+
+void MmRendererPlayerVideoRendererControl::attachDisplay(mmr_context_t *context)
+{
+ if (m_videoId != -1) {
+ qWarning() << "MmRendererPlayerVideoRendererControl: Video output already attached!";
+ return;
+ }
+
+ if (!context) {
+ qWarning() << "MmRendererPlayerVideoRendererControl: No media player context!";
+ return;
+ }
+
+ const QByteArray windowGroupId = m_windowGrabber->windowGroupId();
+ if (windowGroupId.isEmpty()) {
+ qWarning() << "MmRendererPlayerVideoRendererControl: Unable to find window group";
+ return;
+ }
+
+ const QString windowName = QStringLiteral("MmRendererPlayerVideoRendererControl_%1_%2")
+ .arg(winIdCounter++)
+ .arg(QCoreApplication::applicationPid());
+
+ m_windowGrabber->setWindowId(windowName.toLatin1());
+
+ // Start with an invisible window, because we just want to grab the frames from it.
+ const QString videoDeviceUrl = QStringLiteral("screen:?winid=%1&wingrp=%2&initflags=invisible&nodstviewport=1")
+ .arg(windowName)
+ .arg(QString::fromLatin1(windowGroupId));
+
+ m_videoId = mmr_output_attach(context, videoDeviceUrl.toLatin1(), "video");
+ if (m_videoId == -1) {
+ qWarning() << "mmr_output_attach() for video failed";
+ return;
+ }
+
+ m_context = context;
+}
+
+void MmRendererPlayerVideoRendererControl::detachDisplay()
+{
+ m_windowGrabber->stop();
+
+ if (m_surface)
+ m_surface->stop();
+
+ if (m_context && m_videoId != -1)
+ mmr_output_detach(m_context, m_videoId);
+
+ m_context = 0;
+ m_videoId = -1;
+}
+
+void MmRendererPlayerVideoRendererControl::pause()
+{
+ m_windowGrabber->pause();
+}
+
+void MmRendererPlayerVideoRendererControl::resume()
+{
+ m_windowGrabber->resume();
+}
+
+void MmRendererPlayerVideoRendererControl::frameGrabbed(const QImage &frame)
+{
+ if (m_surface) {
+ if (!m_surface->isActive()) {
+ m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32));
+ } else {
+ if (m_surface->surfaceFormat().frameSize() != frame.size()) {
+ m_surface->stop();
+ m_surface->start(QVideoSurfaceFormat(frame.size(), QVideoFrame::Format_ARGB32));
+ }
+ }
+
+ m_surface->present(frame.copy());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h
new file mode 100644
index 000000000..4e271ad5d
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrendererplayervideorenderercontrol.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERPLAYERVIDEORENDERERCONTROL_H
+#define MMRENDERERPLAYERVIDEORENDERERCONTROL_H
+
+#include <QPointer>
+#include <qabstractvideosurface.h>
+#include <qvideorenderercontrol.h>
+
+typedef struct mmr_context mmr_context_t;
+
+QT_BEGIN_NAMESPACE
+
+class WindowGrabber;
+
+class MmRendererPlayerVideoRendererControl : public QVideoRendererControl
+{
+ Q_OBJECT
+public:
+ explicit MmRendererPlayerVideoRendererControl(QObject *parent = 0);
+ ~MmRendererPlayerVideoRendererControl();
+
+ QAbstractVideoSurface *surface() const Q_DECL_OVERRIDE;
+ void setSurface(QAbstractVideoSurface *surface) Q_DECL_OVERRIDE;
+
+ // Called by media control
+ void attachDisplay(mmr_context_t *context);
+ void detachDisplay();
+ void pause();
+ void resume();
+
+private Q_SLOTS:
+ void frameGrabbed(const QImage &frame);
+
+private:
+ QPointer<QAbstractVideoSurface> m_surface;
+
+ WindowGrabber* m_windowGrabber;
+ mmr_context_t *m_context;
+
+ int m_videoId;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mmrendererutil.cpp b/src/plugins/qnx/mediaplayer/mmrendererutil.cpp
new file mode 100644
index 000000000..61f85f3d9
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrendererutil.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "mmrendererutil.h"
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QString>
+#include <QXmlStreamReader>
+
+#include <mm/renderer.h>
+
+QT_BEGIN_NAMESPACE
+
+struct MmError {
+ int errorCode;
+ const char *name;
+};
+
+#define MM_ERROR_ENTRY(error) { error, #error }
+static const MmError mmErrors[] = {
+ MM_ERROR_ENTRY(MMR_ERROR_NONE),
+ MM_ERROR_ENTRY(MMR_ERROR_UNKNOWN ),
+ MM_ERROR_ENTRY(MMR_ERROR_INVALID_PARAMETER ),
+ MM_ERROR_ENTRY(MMR_ERROR_INVALID_STATE),
+ MM_ERROR_ENTRY(MMR_ERROR_UNSUPPORTED_VALUE),
+ MM_ERROR_ENTRY(MMR_ERROR_UNSUPPORTED_MEDIA_TYPE),
+ MM_ERROR_ENTRY(MMR_ERROR_MEDIA_PROTECTED),
+ MM_ERROR_ENTRY(MMR_ERROR_UNSUPPORTED_OPERATION),
+ MM_ERROR_ENTRY(MMR_ERROR_READ),
+ MM_ERROR_ENTRY(MMR_ERROR_WRITE),
+ MM_ERROR_ENTRY(MMR_ERROR_MEDIA_UNAVAILABLE),
+ MM_ERROR_ENTRY(MMR_ERROR_MEDIA_CORRUPTED),
+ MM_ERROR_ENTRY(MMR_ERROR_OUTPUT_UNAVAILABLE),
+ MM_ERROR_ENTRY(MMR_ERROR_NO_MEMORY),
+ MM_ERROR_ENTRY(MMR_ERROR_RESOURCE_UNAVAILABLE),
+ MM_ERROR_ENTRY(MMR_ERROR_MEDIA_DRM_NO_RIGHTS),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_CORRUPTED_DATA_STORE),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OUTPUT_PROTECTION),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_HDMI),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_DISPLAYPORT),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_DVI),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_ANALOG_VIDEO),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_ANALOG_AUDIO),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_TOSLINK),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_SPDIF),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_BLUETOOTH),
+ MM_ERROR_ENTRY(MMR_ERROR_DRM_OPL_WIRELESSHD),
+};
+static const unsigned int numMmErrors = sizeof(mmErrors) / sizeof(MmError);
+
+QString mmErrorMessage(const QString &msg, mmr_context_t *context, int *errorCode)
+{
+ const mmr_error_info_t * const mmError = mmr_error_info(context);
+
+ if (errorCode)
+ *errorCode = mmError->error_code;
+
+ if (mmError->error_code < numMmErrors) {
+ return QString("%1: %2 (code %3)").arg(msg).arg(mmErrors[mmError->error_code].name)
+ .arg(mmError->error_code);
+ } else {
+ return QString("%1: Unknown error code %2").arg(msg).arg(mmError->error_code);
+ }
+}
+
+bool checkForDrmPermission()
+{
+ QDir sandboxDir = QDir::home(); // always returns 'data' directory
+ sandboxDir.cdUp(); // change to app sandbox directory
+
+ QFile file(sandboxDir.filePath("app/native/bar-descriptor.xml"));
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "checkForDrmPermission: Unable to open bar-descriptor.xml";
+ return false;
+ }
+
+ QXmlStreamReader reader(&file);
+ while (!reader.atEnd()) {
+ reader.readNextStartElement();
+ if (reader.name() == QLatin1String("action")
+ || reader.name() == QLatin1String("permission")) {
+ if (reader.readElementText().trimmed() == QLatin1String("access_protected_media"))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrendererutil.h b/src/plugins/qnx/mediaplayer/mmrendererutil.h
new file mode 100644
index 000000000..4b9adc27e
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrendererutil.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERUTIL_H
+#define MMRENDERERUTIL_H
+
+#include <QtCore/qglobal.h>
+
+typedef struct mmr_context mmr_context_t;
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+
+QString mmErrorMessage(const QString &msg, mmr_context_t *context, int * errorCode = 0);
+
+bool checkForDrmPermission();
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp
new file mode 100644
index 000000000..c35c6d1ad
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "mmrenderervideowindowcontrol.h"
+#include "mmrendererutil.h"
+#include <QtCore/qdebug.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qpa/qplatformnativeinterface.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qwindow.h>
+#include <mm/renderer.h>
+
+QT_BEGIN_NAMESPACE
+
+static int winIdCounter = 0;
+
+MmRendererVideoWindowControl::MmRendererVideoWindowControl(QObject *parent)
+ : QVideoWindowControl(parent),
+ m_videoId(-1),
+ m_winId(0),
+ m_context(0),
+ m_fullscreen(false),
+ m_aspectRatioMode(Qt::IgnoreAspectRatio),
+ m_window(0),
+ m_hue(0),
+ m_brightness(0),
+ m_contrast(0),
+ m_saturation(0)
+{
+}
+
+MmRendererVideoWindowControl::~MmRendererVideoWindowControl()
+{
+}
+
+WId MmRendererVideoWindowControl::winId() const
+{
+ return m_winId;
+}
+
+void MmRendererVideoWindowControl::setWinId(WId id)
+{
+ m_winId = id;
+}
+
+QRect MmRendererVideoWindowControl::displayRect() const
+{
+ return m_displayRect ;
+}
+
+void MmRendererVideoWindowControl::setDisplayRect(const QRect &rect)
+{
+ if (m_displayRect != rect) {
+ m_displayRect = rect;
+ updateVideoPosition();
+ }
+}
+
+bool MmRendererVideoWindowControl::isFullScreen() const
+{
+ return m_fullscreen;
+}
+
+void MmRendererVideoWindowControl::setFullScreen(bool fullScreen)
+{
+ if (m_fullscreen != fullScreen) {
+ m_fullscreen = fullScreen;
+ updateVideoPosition();
+ emit fullScreenChanged(m_fullscreen);
+ }
+}
+
+void MmRendererVideoWindowControl::repaint()
+{
+ // Nothing we can or should do here
+}
+
+QSize MmRendererVideoWindowControl::nativeSize() const
+{
+ return QSize(m_metaData.width(), m_metaData.height());
+}
+
+Qt::AspectRatioMode MmRendererVideoWindowControl::aspectRatioMode() const
+{
+ return m_aspectRatioMode;
+}
+
+void MmRendererVideoWindowControl::setAspectRatioMode(Qt::AspectRatioMode mode)
+{
+ m_aspectRatioMode = mode;
+}
+
+int MmRendererVideoWindowControl::brightness() const
+{
+ return m_brightness;
+}
+
+void MmRendererVideoWindowControl::setBrightness(int brightness)
+{
+ if (m_brightness != brightness) {
+ m_brightness = brightness;
+ updateBrightness();
+ emit brightnessChanged(m_brightness);
+ }
+}
+
+int MmRendererVideoWindowControl::contrast() const
+{
+ return m_contrast;
+}
+
+void MmRendererVideoWindowControl::setContrast(int contrast)
+{
+ if (m_contrast != contrast) {
+ m_contrast = contrast;
+ updateContrast();
+ emit contrastChanged(m_contrast);
+ }
+}
+
+int MmRendererVideoWindowControl::hue() const
+{
+ return m_hue;
+}
+
+void MmRendererVideoWindowControl::setHue(int hue)
+{
+ if (m_hue != hue) {
+ m_hue = hue;
+ updateHue();
+ emit hueChanged(m_hue);
+ }
+}
+
+int MmRendererVideoWindowControl::saturation() const
+{
+ return m_saturation;
+}
+
+void MmRendererVideoWindowControl::setSaturation(int saturation)
+{
+ if (m_saturation != saturation) {
+ m_saturation = saturation;
+ updateSaturation();
+ emit saturationChanged(m_saturation);
+ }
+}
+
+void MmRendererVideoWindowControl::attachDisplay(mmr_context_t *context)
+{
+ if (m_videoId != -1) {
+ qDebug() << "MmRendererVideoWindowControl: Video output already attached!";
+ return;
+ }
+
+ if (!context) {
+ qDebug() << "MmRendererVideoWindowControl: No media player context!";
+ return;
+ }
+
+ QWindow *window = findWindow(m_winId);
+ if (!window) {
+ qDebug() << "MmRendererVideoWindowControl: No video window!";
+ return;
+ }
+
+ QPlatformNativeInterface * const nativeInterface = QGuiApplication::platformNativeInterface();
+ if (!nativeInterface) {
+ qDebug() << "MmRendererVideoWindowControl: Unable to get platform native interface";
+ return;
+ }
+
+ const char * const groupNameData = static_cast<const char *>(
+ nativeInterface->nativeResourceForWindow("windowGroup", window));
+ if (!groupNameData) {
+ qDebug() << "MmRendererVideoWindowControl: Unable to find window group for window" << window;
+ return;
+ }
+
+ const QString groupName = QString::fromLatin1(groupNameData);
+ m_windowName = QString("MmRendererVideoWindowControl_%1_%2").arg(winIdCounter++)
+ .arg(QCoreApplication::applicationPid());
+
+ nativeInterface->setWindowProperty(window->handle(),
+ QStringLiteral("mmRendererWindowName"), m_windowName);
+
+ // Start with an invisible window. If it would be visible right away, it would be at the wrong
+ // position, and we can only change the position once we get the window handle.
+ const QString videoDeviceUrl =
+ QString("screen:?winid=%1&wingrp=%2&initflags=invisible&nodstviewport=1").arg(m_windowName).arg(groupName);
+
+ m_videoId = mmr_output_attach(context, videoDeviceUrl.toLatin1(), "video");
+ if (m_videoId == -1) {
+ qDebug() << mmErrorMessage("mmr_output_attach() for video failed", context);
+ return;
+ }
+
+ m_context = context;
+ updateVideoPosition();
+ updateHue();
+ updateContrast();
+ updateBrightness();
+ updateSaturation();
+}
+
+void MmRendererVideoWindowControl::updateVideoPosition()
+{
+ QWindow * const window = findWindow(m_winId);
+ if (m_context && m_videoId != -1 && window) {
+ QPoint topLeft = m_fullscreen ?
+ QPoint(0,0) :
+ window->mapToGlobal(m_displayRect.topLeft());
+
+ QScreen * const screen = window->screen();
+ int width = m_fullscreen ?
+ screen->size().width() :
+ m_displayRect.width();
+ int height = m_fullscreen ?
+ screen->size().height() :
+ m_displayRect.height();
+
+ if (m_metaData.hasVideo()) { // We need the source size to do aspect ratio scaling
+ const qreal sourceRatio = m_metaData.width() / static_cast<float>(m_metaData.height());
+ const qreal targetRatio = width / static_cast<float>(height);
+
+ if (m_aspectRatioMode == Qt::KeepAspectRatio) {
+ if (targetRatio < sourceRatio) {
+ // Need to make height smaller
+ const int newHeight = width / sourceRatio;
+ const int heightDiff = height - newHeight;
+ topLeft.ry() += heightDiff / 2;
+ height = newHeight;
+ } else {
+ // Need to make width smaller
+ const int newWidth = sourceRatio * height;
+ const int widthDiff = width - newWidth;
+ topLeft.rx() += widthDiff / 2;
+ width = newWidth;
+ }
+
+ } else if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
+ if (targetRatio < sourceRatio) {
+ // Need to make width larger
+ const int newWidth = sourceRatio * height;
+ const int widthDiff = newWidth - width;
+ topLeft.rx() -= widthDiff / 2;
+ width = newWidth;
+ } else {
+ // Need to make height larger
+ const int newHeight = width / sourceRatio;
+ const int heightDiff = newHeight - height;
+ topLeft.ry() -= heightDiff / 2;
+ height = newHeight;
+ }
+ }
+ }
+
+ if (m_window != 0) {
+ const int position[2] = { topLeft.x(), topLeft.y() };
+ const int size[2] = { width, height };
+ const int visible = m_displayRect.isValid();
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, position) != 0)
+ perror("Setting video position failed");
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, size) != 0)
+ perror("Setting video size failed");
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &visible) != 0)
+ perror("Setting video visibility failed");
+ }
+ }
+}
+
+void MmRendererVideoWindowControl::updateBrightness()
+{
+ if (m_window != 0) {
+ const int backendValue = m_brightness * 2.55f;
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BRIGHTNESS, &backendValue) != 0)
+ perror("Setting brightness failed");
+ }
+}
+
+void MmRendererVideoWindowControl::updateContrast()
+{
+ if (m_window != 0) {
+ const int backendValue = m_contrast * 1.27f;
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_CONTRAST, &backendValue) != 0)
+ perror("Setting contrast failed");
+ }
+}
+
+void MmRendererVideoWindowControl::updateHue()
+{
+ if (m_window != 0) {
+ const int backendValue = m_hue * 1.27f;
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_HUE, &backendValue) != 0)
+ perror("Setting hue failed");
+ }
+}
+
+void MmRendererVideoWindowControl::updateSaturation()
+{
+ if (m_window != 0) {
+ const int backendValue = m_saturation * 1.27f;
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SATURATION, &backendValue) != 0)
+ perror("Setting saturation failed");
+ }
+}
+
+void MmRendererVideoWindowControl::detachDisplay()
+{
+ if (m_context && m_videoId != -1)
+ mmr_output_detach(m_context, m_videoId);
+
+ m_context = 0;
+ m_videoId = -1;
+ m_metaData.clear();
+ m_windowName.clear();
+ m_window = 0;
+ m_hue = 0;
+ m_brightness = 0;
+ m_contrast = 0;
+ m_saturation = 0;
+}
+
+void MmRendererVideoWindowControl::setMetaData(const MmRendererMetaData &metaData)
+{
+ m_metaData = metaData;
+ emit nativeSizeChanged();
+
+ // To handle the updated source size data
+ updateVideoPosition();
+}
+
+void MmRendererVideoWindowControl::screenEventHandler(const screen_event_t &screen_event)
+{
+ int eventType;
+ if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) {
+ perror("MmRendererVideoWindowControl: Failed to query screen event type");
+ return;
+ }
+
+ if (eventType != SCREEN_EVENT_CREATE)
+ return;
+
+ screen_window_t window = 0;
+ if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) {
+ perror("MmRendererVideoWindowControl: Failed to query window property");
+ return;
+ }
+
+ const int maxIdStrLength = 128;
+ char idString[maxIdStrLength];
+ if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) {
+ perror("MmRendererVideoWindowControl: Failed to query window ID string");
+ return;
+ }
+
+ if (m_windowName == idString) {
+ m_window = window;
+ updateVideoPosition();
+
+ const int visibleFlag = 1;
+ if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &visibleFlag) != 0) {
+ perror("MmRendererVideoWindowControl: Failed to make window visible");
+ return;
+ }
+ }
+}
+
+QWindow *MmRendererVideoWindowControl::findWindow(WId id) const
+{
+ Q_FOREACH (QWindow *window, QGuiApplication::allWindows())
+ if (window->winId() == id)
+ return window;
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h
new file mode 100644
index 000000000..cfc9603bb
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/mmrenderervideowindowcontrol.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MMRENDERERVIDEOWINDOWCONTROL_H
+#define MMRENDERERVIDEOWINDOWCONTROL_H
+
+#include "mmrenderermetadata.h"
+#include <qvideowindowcontrol.h>
+#include <screen/screen.h>
+
+typedef struct mmr_context mmr_context_t;
+
+QT_BEGIN_NAMESPACE
+
+class MmRendererVideoWindowControl : public QVideoWindowControl
+{
+ Q_OBJECT
+public:
+ explicit MmRendererVideoWindowControl(QObject *parent = 0);
+ ~MmRendererVideoWindowControl();
+
+ WId winId() const Q_DECL_OVERRIDE;
+ void setWinId(WId id) Q_DECL_OVERRIDE;
+
+ QRect displayRect() const Q_DECL_OVERRIDE;
+ void setDisplayRect(const QRect &rect) Q_DECL_OVERRIDE;
+
+ bool isFullScreen() const Q_DECL_OVERRIDE;
+ void setFullScreen(bool fullScreen) Q_DECL_OVERRIDE;
+
+ void repaint() Q_DECL_OVERRIDE;
+
+ QSize nativeSize() const Q_DECL_OVERRIDE;
+
+ Qt::AspectRatioMode aspectRatioMode() const Q_DECL_OVERRIDE;
+ void setAspectRatioMode(Qt::AspectRatioMode mode) Q_DECL_OVERRIDE;
+
+ int brightness() const Q_DECL_OVERRIDE;
+ void setBrightness(int brightness) Q_DECL_OVERRIDE;
+
+ int contrast() const Q_DECL_OVERRIDE;
+ void setContrast(int contrast) Q_DECL_OVERRIDE;
+
+ int hue() const Q_DECL_OVERRIDE;
+ void setHue(int hue) Q_DECL_OVERRIDE;
+
+ int saturation() const Q_DECL_OVERRIDE;
+ void setSaturation(int saturation) Q_DECL_OVERRIDE;
+
+ //
+ // Called by media control
+ //
+ void detachDisplay();
+ void attachDisplay(mmr_context_t *context);
+ void setMetaData(const MmRendererMetaData &metaData);
+ void screenEventHandler(const screen_event_t &event);
+
+private:
+ QWindow *findWindow(WId id) const;
+ void updateVideoPosition();
+ void updateBrightness();
+ void updateContrast();
+ void updateHue();
+ void updateSaturation();
+
+ int m_videoId;
+ WId m_winId;
+ QRect m_displayRect;
+ mmr_context_t *m_context;
+ bool m_fullscreen;
+ MmRendererMetaData m_metaData;
+ Qt::AspectRatioMode m_aspectRatioMode;
+ QString m_windowName;
+ screen_window_t m_window;
+ int m_hue;
+ int m_brightness;
+ int m_contrast;
+ int m_saturation;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp
new file mode 100644
index 000000000..eb0842fb9
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "ppsmediaplayercontrol.h"
+#include "mmrenderervideowindowcontrol.h"
+
+#include <QtCore/qfile.h>
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/private/qcore_unix_p.h>
+
+#include <screen/screen.h>
+#include <sys/pps.h>
+
+QT_BEGIN_NAMESPACE
+
+PpsMediaPlayerControl::PpsMediaPlayerControl(QObject *parent)
+ : MmRendererMediaPlayerControl(parent),
+ m_ppsStatusNotifier(0),
+ m_ppsStatusFd(-1),
+ m_ppsStateNotifier(0),
+ m_ppsStateFd(-1)
+ , m_previouslySeenState("STOPPED")
+{
+ openConnection();
+}
+
+PpsMediaPlayerControl::~PpsMediaPlayerControl()
+{
+ destroy();
+}
+
+void PpsMediaPlayerControl::startMonitoring(int, const QString &contextName)
+{
+ const QString ppsContextPath = QStringLiteral("/pps/services/multimedia/renderer/context/%1/").arg(contextName);
+ const QString ppsStatusPath = ppsContextPath + QStringLiteral("/status");
+
+ Q_ASSERT(m_ppsStatusFd == -1);
+ errno = 0;
+ m_ppsStatusFd = qt_safe_open(QFile::encodeName(ppsStatusPath).constData(), O_RDONLY);
+ if (m_ppsStatusFd == -1) {
+ emitPError(QStringLiteral("Unable to open %1: %2").arg(ppsStatusPath, qt_error_string(errno)));
+ return;
+ }
+
+ Q_ASSERT(!m_ppsStatusNotifier);
+ m_ppsStatusNotifier = new QSocketNotifier(m_ppsStatusFd, QSocketNotifier::Read);
+ connect(m_ppsStatusNotifier, SIGNAL(activated(int)), this, SLOT(ppsReadyRead(int)));
+
+
+ const QString ppsStatePath = ppsContextPath + QStringLiteral("/state");
+
+ Q_ASSERT(m_ppsStateFd == -1);
+ errno = 0;
+ m_ppsStateFd = qt_safe_open(QFile::encodeName(ppsStatePath).constData(), O_RDONLY);
+ if (m_ppsStateFd == -1) {
+ emitPError(QStringLiteral("Unable to open %1: %2").arg(ppsStatePath, qt_error_string(errno)));
+ return;
+ }
+
+ Q_ASSERT(!m_ppsStateNotifier);
+ m_ppsStateNotifier = new QSocketNotifier(m_ppsStateFd, QSocketNotifier::Read);
+ connect(m_ppsStateNotifier, SIGNAL(activated(int)), this, SLOT(ppsReadyRead(int)));
+
+ //ensure we receive any initial state
+ ppsReadyRead(m_ppsStatusFd);
+ ppsReadyRead(m_ppsStateFd);
+}
+
+void PpsMediaPlayerControl::stopMonitoring()
+{
+
+ if (m_ppsStatusFd != -1) {
+ ::close(m_ppsStatusFd);
+ m_ppsStatusFd = -1;
+ }
+
+ delete m_ppsStatusNotifier;
+ m_ppsStatusNotifier = 0;
+
+ if (m_ppsStateFd != -1) {
+ ::close(m_ppsStateFd);
+ m_ppsStateFd = -1;
+ }
+
+ delete m_ppsStateNotifier;
+ m_ppsStateNotifier = 0;
+}
+
+bool PpsMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+{
+ Q_UNUSED(result)
+ if (eventType == "screen_event_t") {
+ screen_event_t event = static_cast<screen_event_t>(message);
+ if (MmRendererVideoWindowControl *control = videoWindowControl())
+ control->screenEventHandler(event);
+ }
+
+ return false;
+}
+
+void PpsMediaPlayerControl::ppsReadyRead(int fd)
+{
+ Q_ASSERT(fd == m_ppsStateFd || fd == m_ppsStatusFd);
+ const int bufferSize = 2048;
+ char buffer[bufferSize];
+ const ssize_t nread = qt_safe_read(fd, buffer, bufferSize - 1);
+ if (nread < 0) {
+ //TODO emit error?
+ }
+
+ if (nread == 0) {
+ return;
+ }
+
+ // nread is the real space necessary, not the amount read.
+ if (static_cast<size_t>(nread) > bufferSize - 1) {
+ //TODO emit error?
+ qCritical("BBMediaPlayerControl: PPS buffer size too short; need %u.", nread + 1);
+ return;
+ }
+
+ buffer[nread] = 0;
+
+ pps_decoder_t decoder;
+
+ if (pps_decoder_initialize(&decoder, buffer) != PPS_DECODER_OK) {
+ //TODO emit error?
+ qCritical("Could not initialize pps_decoder");
+ pps_decoder_cleanup(&decoder);
+ return;
+ }
+
+ pps_decoder_push(&decoder, 0);
+
+ const char *value = 0;
+ if (pps_decoder_get_string(&decoder, "bufferlevel", &value) == PPS_DECODER_OK) {
+ setMmBufferStatus(QString::fromLatin1(value));
+ }
+
+ if (pps_decoder_get_string(&decoder, "state", &value) == PPS_DECODER_OK) {
+ const QByteArray state = value;
+ if (state != m_previouslySeenState && state == "STOPPED")
+ handleMmStopped();
+ m_previouslySeenState = state;
+ }
+
+ if (pps_decoder_get_string(&decoder, "position", &value) == PPS_DECODER_OK) {
+ const QByteArray valueBa = QByteArray(value);
+ bool ok;
+ const qint64 position = valueBa.toLongLong(&ok);
+ if (!ok) {
+ qCritical("Could not parse position from '%s'", valueBa.constData());
+ } else {
+ setMmPosition(position);
+ }
+ }
+
+ pps_decoder_cleanup(&decoder);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h
new file mode 100644
index 000000000..e00d44dfd
--- /dev/null
+++ b/src/plugins/qnx/mediaplayer/ppsmediaplayercontrol.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PPSMEDIAPLAYERCONTROL_H
+#define PPSMEDIAPLAYERCONTROL_H
+
+#include "mmrenderermediaplayercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class PpsMediaPlayerControl Q_DECL_FINAL : public MmRendererMediaPlayerControl
+{
+ Q_OBJECT
+public:
+ explicit PpsMediaPlayerControl(QObject *parent = 0);
+ ~PpsMediaPlayerControl();
+
+ void startMonitoring(int contextId, const QString &contextName) Q_DECL_OVERRIDE;
+ void stopMonitoring() Q_DECL_OVERRIDE;
+
+ bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void ppsReadyRead(int fd);
+
+private:
+ QSocketNotifier *m_ppsStatusNotifier;
+ int m_ppsStatusFd;
+ QSocketNotifier *m_ppsStateNotifier;
+ int m_ppsStateFd;
+ QByteArray m_previouslySeenState;
+};
+
+QT_END_NAMESPACE
+
+#endif