Support plain QNX in mm-renderer mediaplayer impl
authorFrank Osterfeld <frank.osterfeld.qnx@kdab.com>
Mon, 4 Nov 2013 14:52:43 +0000 (15:52 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sat, 9 Nov 2013 09:51:16 +0000 (10:51 +0100)
On plain QNX, the native events are plain screen_event_t's,
instead of being wrapped in bps_event_t.

The bps/mm-renderer interface isn't available on QNX, thus
those parts are replaced by reading directly from mm-renderer's
PPS objects.

Change-Id: I38772ddad04432ff099455a730ce0034f07db70d
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
18 files changed:
src/plugins/blackberry/blackberry.pro
src/plugins/blackberry/common/windowgrabber.cpp
src/plugins/blackberry/common/windowgrabber.h
src/plugins/blackberry/mediaplayer/bbmediaplayercontrol.cpp
src/plugins/blackberry/mediaplayer/bbmediaplayercontrol.h
src/plugins/blackberry/mediaplayer/bbmediaplayerservice.cpp
src/plugins/blackberry/mediaplayer/bbplayervideorenderercontrol.h
src/plugins/blackberry/mediaplayer/bbvideowindowcontrol.cpp
src/plugins/blackberry/mediaplayer/bbvideowindowcontrol.h
src/plugins/blackberry/mediaplayer/bpsmediaplayercontrol.cpp [new file with mode: 0644]
src/plugins/blackberry/mediaplayer/bpsmediaplayercontrol.h [new file with mode: 0644]
src/plugins/blackberry/mediaplayer/mediaplayer.pri
src/plugins/blackberry/mediaplayer/ppsmediaplayercontrol.cpp [new file with mode: 0644]
src/plugins/blackberry/mediaplayer/ppsmediaplayercontrol.h [new file with mode: 0644]
src/plugins/blackberry/neutrino_mediaservice.json [new file with mode: 0644]
src/plugins/blackberry/neutrinoserviceplugin.cpp [new file with mode: 0644]
src/plugins/blackberry/neutrinoserviceplugin.h [new file with mode: 0644]
src/plugins/plugins.pro

index e0a6233..fa1d07f 100644 (file)
@@ -7,13 +7,16 @@ load(qt_plugin)
 
 LIBS += -lscreen
 
-HEADERS += bbserviceplugin.h
-SOURCES += bbserviceplugin.cpp
-
 include(common/common.pri)
-
-include(camera/camera.pri)
-
 include(mediaplayer/mediaplayer.pri)
 
-OTHER_FILES += blackberry_mediaservice.json
+blackberry {
+    include(camera/camera.pri)
+    HEADERS += bbserviceplugin.h
+    SOURCES += bbserviceplugin.cpp
+    OTHER_FILES += blackberry_mediaservice.json
+} else {
+    HEADERS += neutrinoserviceplugin.h
+    SOURCES += neutrinoserviceplugin.cpp
+    OTHER_FILES += neutrino_mediaservice.json
+}
index 144b5a6..5ed54b8 100644 (file)
 #include <QImage>
 #include <qpa/qplatformnativeinterface.h>
 
+#ifdef Q_OS_BLACKBERRY
+#include <bps/event.h>
 #include <bps/screen.h>
+#endif
 #include <errno.h>
 
 QT_BEGIN_NAMESPACE
@@ -232,40 +235,55 @@ void WindowGrabber::resume()
     m_timer.start();
 }
 
-bool WindowGrabber::nativeEventFilter(const QByteArray&, void *message, long*)
+bool WindowGrabber::handleScreenEvent(screen_event_t screen_event)
 {
-    bps_event_t * const event = static_cast<bps_event_t *>(message);
 
-    if (event && bps_event_get_domain(event) == screen_get_domain()) {
-        const screen_event_t screen_event = screen_event_get_event(event);
+    int eventType;
+    if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) {
+        qWarning() << "WindowGrabber: Failed to query screen event type";
+        return false;
+    }
 
-        int eventType;
-        if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) {
-            qWarning() << "WindowGrabber: Failed to query screen event type";
-            return false;
-        }
+    if (eventType != SCREEN_EVENT_CREATE)
+        return false;
 
-        if (eventType != SCREEN_EVENT_CREATE)
-            return false;
+    screen_window_t window = 0;
+    if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) {
+        qWarning() << "WindowGrabber: Failed to query window property";
+        return false;
+    }
 
-        screen_window_t window = 0;
-        if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) {
-            qWarning() << "WindowGrabber: Failed to query window property";
-            return false;
-        }
+    const int maxIdStrLength = 128;
+    char idString[maxIdStrLength];
+    if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) {
+        qWarning() << "WindowGrabber: Failed to query window ID string";
+        return false;
+    }
 
-        const int maxIdStrLength = 128;
-        char idString[maxIdStrLength];
-        if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) {
-            qWarning() << "WindowGrabber: Failed to query window ID string";
-            return false;
-        }
+    if (m_windowId == idString) {
+        m_window = window;
+        start();
+    }
 
-        if (m_windowId == idString) {
-            m_window = window;
-            start();
-        }
+    return false;
+}
+
+bool WindowGrabber::nativeEventFilter(const QByteArray &eventType, void *message, long*)
+{
+#ifdef Q_OS_BLACKBERRY
+    Q_UNUSED(eventType)
+    bps_event_t * const event = static_cast<bps_event_t *>(message);
+
+    if (event && bps_event_get_domain(event) == screen_get_domain()) {
+        const screen_event_t screen_event = screen_event_get_event(event);
+        return handleScreenEvent(screen_event);
     }
+#else
+    if (eventType == "screen_event_t") {
+        const screen_event_t event = static_cast<screen_event_t>(message);
+        return handleScreenEvent(event);
+    }
+#endif
 
     return false;
 }
index f8e3686..7ec4202 100644 (file)
@@ -69,6 +69,8 @@ public:
 
     bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
 
+    bool handleScreenEvent(screen_event_t event);
+
     QByteArray windowGroupId() const;
 
 signals:
index c7a0fdd..6304b66 100644 (file)
@@ -49,8 +49,7 @@
 #include <QtCore/qfileinfo.h>
 #include <QtCore/quuid.h>
 #include <mm/renderer.h>
-#include <bps/mmrenderer.h>
-#include <bps/screen.h>
+
 #include <errno.h>
 #include <sys/strm.h>
 #include <sys/stat.h>
@@ -69,7 +68,6 @@ BbMediaPlayerControl::BbMediaPlayerControl(QObject *parent)
       m_muted(false),
       m_rate(1),
       m_id(-1),
-      m_eventMonitor(0),
       m_position(0),
       m_mediaStatus(QMediaPlayer::NoMedia),
       m_playAfterMediaLoaded(false),
@@ -81,10 +79,9 @@ BbMediaPlayerControl::BbMediaPlayerControl(QObject *parent)
     m_loadingTimer.setInterval(0);
     connect(&m_loadingTimer, SIGNAL(timeout()), this, SLOT(continueLoadMedia()));
     QCoreApplication::eventDispatcher()->installNativeEventFilter(this);
-    openConnection();
 }
 
-BbMediaPlayerControl::~BbMediaPlayerControl()
+void BbMediaPlayerControl::destroy()
 {
     stop();
     detach();
@@ -111,19 +108,41 @@ void BbMediaPlayerControl::openConnection()
         return;
     }
 
-    m_eventMonitor = mmrenderer_request_events(m_contextName.toLatin1(), 0, m_id);
-    if (!m_eventMonitor) {
-        qDebug() << "Unable to request multimedia events";
-        emit error(0, "Unable to request multimedia events");
+    startMonitoring(m_id, m_contextName);
+}
+
+void BbMediaPlayerControl::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 BbMediaPlayerControl::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 BbMediaPlayerControl::closeConnection()
 {
-    if (m_eventMonitor) {
-        mmrenderer_stop_events(m_eventMonitor);
-        m_eventMonitor = 0;
-    }
+    stopMonitoring();
 
     if (m_context) {
         mmr_context_destroy(m_context);
@@ -468,6 +487,16 @@ void BbMediaPlayerControl::continueLoadMedia()
         play();
 }
 
+QString BbMediaPlayerControl::contextName() const
+{
+    return m_contextName;
+}
+
+BbVideoWindowControl *BbMediaPlayerControl::videoWindowControl() const
+{
+    return m_videoWindowControl;
+}
+
 void BbMediaPlayerControl::play()
 {
     if (m_playAfterMediaLoaded)
@@ -526,6 +555,11 @@ void BbMediaPlayerControl::stop()
     stopInternal(StopMmRenderer);
 }
 
+BbPlayerVideoRendererControl *BbMediaPlayerControl::videoRendererControl() const
+{
+    return m_videoRendererControl;
+}
+
 void BbMediaPlayerControl::setVideoRendererControl(BbPlayerVideoRendererControl *videoControl)
 {
     m_videoRendererControl = videoControl;
@@ -541,71 +575,25 @@ void BbMediaPlayerControl::setMetaDataReaderControl(BbMetaDataReaderControl *met
     m_metaDataReaderControl = metaDataReaderControl;
 }
 
-bool BbMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
+void BbMediaPlayerControl::setMmPosition(qint64 newPosition)
 {
-    Q_UNUSED(eventType);
-    Q_UNUSED(result);
-
-    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 (m_videoWindowControl)
-        m_videoWindowControl->bpsEventHandler(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) {
-
-                // 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);
-                }
-                return false;
-            }
-        }
-
-        if (bps_event_get_code(event) == MMRENDERER_STATUS_UPDATE) {
-
-            // 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 false;
-
-            const qint64 newPosition = QString::fromLatin1(mmrenderer_event_get_position(event)).toLongLong();
-            if (newPosition != 0 && newPosition != m_position) {
-                m_position = newPosition;
-                emit positionChanged(m_position);
-            }
+    if (newPosition != 0 && newPosition != m_position) {
+        m_position = newPosition;
+        emit positionChanged(m_position);
+    }
+}
 
-            const QString bufferStatus = QString::fromLatin1(mmrenderer_event_get_bufferlevel(event));
-            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 BbMediaPlayerControl::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);
         }
     }
-
-    return false;
 }
 
 void BbMediaPlayerControl::updateMetaData()
index 16505fd..6d6f5e8 100644 (file)
@@ -47,7 +47,6 @@
 #include <QtCore/qpointer.h>
 #include <QtCore/qtimer.h>
 
-struct bps_event_t;
 typedef struct mmr_connection mmr_connection_t;
 typedef struct mmr_context mmr_context_t;
 typedef struct mmrenderer_monitor mmrenderer_monitor_t;
@@ -63,7 +62,6 @@ class BbMediaPlayerControl : public QMediaPlayerControl, public QAbstractNativeE
     Q_OBJECT
 public:
     explicit BbMediaPlayerControl(QObject *parent = 0);
-    ~BbMediaPlayerControl();
 
     QMediaPlayer::State state() const Q_DECL_OVERRIDE;
 
@@ -100,25 +98,39 @@ public:
     void pause() Q_DECL_OVERRIDE;
     void stop() Q_DECL_OVERRIDE;
 
+    BbPlayerVideoRendererControl *videoRendererControl() const;
     void setVideoRendererControl(BbPlayerVideoRendererControl *videoControl);
+
+    BbVideoWindowControl *videoWindowControl() const;
     void setVideoWindowControl(BbVideoWindowControl *videoControl);
     void setMetaDataReaderControl(BbMetaDataReaderControl *metaDataReaderControl);
-    bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
+
+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 openConnection();
     void closeConnection();
     void attach();
     void detach();
     void updateMetaData();
 
-    void emitMmError(const QString &msg);
-    void emitPError(const QString &msg);
-
     // All these set the specified value to the backend, but neither emit changed signals
     // nor change the member value.
     void setVolumeInternal(int newVolume);
@@ -145,7 +157,6 @@ private:
     QPointer<BbMetaDataReaderControl> m_metaDataReaderControl;
     BbMetaData m_metaData;
     int m_id;
-    mmrenderer_monitor_t *m_eventMonitor;
     qint64 m_position;
     QMediaPlayer::MediaStatus m_mediaStatus;
     bool m_playAfterMediaLoaded;
index 5846cc0..5eb2ae6 100644 (file)
 #include "bbutil.h"
 #include "bbvideowindowcontrol.h"
 
+#ifdef Q_OS_BLACKBERRY
+#include "bpsmediaplayercontrol.h"
+typedef BpsMediaPlayerControl PlatformSpecificMediaPlayerControl;
+#else
+#include "ppsmediaplayercontrol.h"
+typedef PpsMediaPlayerControl PlatformSpecificMediaPlayerControl;
+#endif
+
 QT_BEGIN_NAMESPACE
 
 BbMediaPlayerService::BbMediaPlayerService(QObject *parent)
@@ -72,7 +80,7 @@ QMediaControl *BbMediaPlayerService::requestControl(const char *name)
 {
     if (qstrcmp(name, QMediaPlayerControl_iid) == 0) {
         if (!m_mediaPlayerControl) {
-            m_mediaPlayerControl = new BbMediaPlayerControl();
+            m_mediaPlayerControl = new PlatformSpecificMediaPlayerControl;
             updateControls();
         }
         return m_mediaPlayerControl;
index fff80df..a2deaa2 100644 (file)
@@ -46,7 +46,6 @@
 #include <qvideorenderercontrol.h>
 
 typedef struct mmr_context mmr_context_t;
-struct bps_event_t;
 
 QT_BEGIN_NAMESPACE
 
index 8c1ca19..28029c9 100644 (file)
@@ -46,7 +46,6 @@
 #include <QtGui/qscreen.h>
 #include <QtGui/qwindow.h>
 #include <mm/renderer.h>
-#include <bps/screen.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -368,42 +367,38 @@ void BbVideoWindowControl::setMetaData(const BbMetaData &metaData)
     updateVideoPosition();
 }
 
-void BbVideoWindowControl::bpsEventHandler(bps_event_t *event)
+void BbVideoWindowControl::screenEventHandler(const screen_event_t &screen_event)
 {
-    if (event && bps_event_get_domain(event) == screen_get_domain()) {
-        const screen_event_t screen_event = screen_event_get_event(event);
-
-        int eventType;
-        if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) {
-            perror("BbVideoWindowControl: Failed to query screen event type");
-            return;
-        }
+    int eventType;
+    if (screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &eventType) != 0) {
+        perror("BbVideoWindowControl: Failed to query screen event type");
+        return;
+    }
 
-        if (eventType != SCREEN_EVENT_CREATE)
-            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("BbVideoWindowControl: Failed to query window property");
-            return;
-        }
+    screen_window_t window = 0;
+    if (screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) {
+        perror("BbVideoWindowControl: 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("BbVideoWindowControl: Failed to query window ID string");
-            return;
-        }
+    const int maxIdStrLength = 128;
+    char idString[maxIdStrLength];
+    if (screen_get_window_property_cv(window, SCREEN_PROPERTY_ID_STRING, maxIdStrLength, idString) != 0) {
+        perror("BbVideoWindowControl: Failed to query window ID string");
+        return;
+    }
 
-        if (m_windowName == idString) {
-            m_window = window;
-            updateVideoPosition();
+    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("BbVideoWindowControl: Failed to make window visible");
-                return;
-            }
+        const int visibleFlag = 1;
+        if (screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &visibleFlag) != 0) {
+            perror("BbVideoWindowControl: Failed to make window visible");
+            return;
         }
     }
 }
index 81bf796..98751d3 100644 (file)
@@ -46,7 +46,6 @@
 #include <screen/screen.h>
 
 typedef struct mmr_context mmr_context_t;
-struct bps_event_t;
 
 QT_BEGIN_NAMESPACE
 
@@ -91,7 +90,7 @@ public:
     void detachDisplay();
     void attachDisplay(mmr_context_t *context);
     void setMetaData(const BbMetaData &metaData);
-    void bpsEventHandler(bps_event_t *event);
+    void screenEventHandler(const screen_event_t &event);
 
 private:
     QWindow *findWindow(WId id) const;
diff --git a/src/plugins/blackberry/mediaplayer/bpsmediaplayercontrol.cpp b/src/plugins/blackberry/mediaplayer/bpsmediaplayercontrol.cpp
new file mode 100644 (file)
index 0000000..7345d8a
--- /dev/null
@@ -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 "bbvideowindowcontrol.h"
+
+#include <bps/mmrenderer.h>
+#include <bps/screen.h>
+
+QT_BEGIN_NAMESPACE
+
+BpsMediaPlayerControl::BpsMediaPlayerControl(QObject *parent)
+    : BbMediaPlayerControl(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 (BbVideoWindowControl *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/blackberry/mediaplayer/bpsmediaplayercontrol.h b/src/plugins/blackberry/mediaplayer/bpsmediaplayercontrol.h
new file mode 100644 (file)
index 0000000..a2d4e09
--- /dev/null
@@ -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 "bbmediaplayercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class BpsMediaPlayerControl Q_DECL_FINAL : public BbMediaPlayerControl
+{
+    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
index 065c799..c5d012e 100644 (file)
@@ -19,3 +19,13 @@ SOURCES += \
     $$PWD/bbvideowindowcontrol.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/blackberry/mediaplayer/ppsmediaplayercontrol.cpp b/src/plugins/blackberry/mediaplayer/ppsmediaplayercontrol.cpp
new file mode 100644 (file)
index 0000000..889819b
--- /dev/null
@@ -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 "bbvideowindowcontrol.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)
+    : BbMediaPlayerControl(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 (BbVideoWindowControl *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/blackberry/mediaplayer/ppsmediaplayercontrol.h b/src/plugins/blackberry/mediaplayer/ppsmediaplayercontrol.h
new file mode 100644 (file)
index 0000000..20da639
--- /dev/null
@@ -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 "bbmediaplayercontrol.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSocketNotifier;
+
+class PpsMediaPlayerControl  Q_DECL_FINAL : public BbMediaPlayerControl
+{
+    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
diff --git a/src/plugins/blackberry/neutrino_mediaservice.json b/src/plugins/blackberry/neutrino_mediaservice.json
new file mode 100644 (file)
index 0000000..919368d
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "Keys": ["neutrinomultimedia"],
+    "Services": ["org.qt-project.qt.mediaplayer"]
+}
diff --git a/src/plugins/blackberry/neutrinoserviceplugin.cpp b/src/plugins/blackberry/neutrinoserviceplugin.cpp
new file mode 100644 (file)
index 0000000..9ceae7d
--- /dev/null
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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 "neutrinoserviceplugin.h"
+
+#include "bbmediaplayerservice.h"
+
+QT_BEGIN_NAMESPACE
+
+NeutrinoServicePlugin::NeutrinoServicePlugin()
+{
+}
+
+QMediaService *NeutrinoServicePlugin::create(const QString &key)
+{
+    if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
+        return new BbMediaPlayerService();
+
+    return 0;
+}
+
+void NeutrinoServicePlugin::release(QMediaService *service)
+{
+    delete service;
+}
+
+QMediaServiceProviderHint::Features NeutrinoServicePlugin::supportedFeatures(const QByteArray &service) const
+{
+    Q_UNUSED(service)
+    return QMediaServiceProviderHint::Features();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/blackberry/neutrinoserviceplugin.h b/src/plugins/blackberry/neutrinoserviceplugin.h
new file mode 100644 (file)
index 0000000..2fc2823
--- /dev/null
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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 NEUTRINOSERVICEPLUGIN_H
+#define NEUTRINOSERVICEPLUGIN_H
+
+#include <qmediaserviceproviderplugin.h>
+
+QT_BEGIN_NAMESPACE
+
+class NeutrinoServicePlugin
+    : public QMediaServiceProviderPlugin,
+      public QMediaServiceFeaturesInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(QMediaServiceFeaturesInterface)
+    Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "neutrino_mediaservice.json")
+public:
+    NeutrinoServicePlugin();
+
+    QMediaService *create(const QString &key) Q_DECL_OVERRIDE;
+    void release(QMediaService *service) Q_DECL_OVERRIDE;
+    QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif
index 20b0ccd..d5e3e80 100644 (file)
@@ -12,11 +12,8 @@ android {
    SUBDIRS += android opensles
 }
 
-blackberry {
-    SUBDIRS += blackberry
-}
-
 qnx {
+    SUBDIRS += blackberry
     SUBDIRS += audiocapture qnx
 }