diff options
6 files changed, 182 insertions, 31 deletions
diff --git a/examples/multimediawidgets/player/player.cpp b/examples/multimediawidgets/player/player.cpp index 4d3340855..89246e65c 100644 --- a/examples/multimediawidgets/player/player.cpp +++ b/examples/multimediawidgets/player/player.cpp @@ -174,6 +174,15 @@ Player::Player(QWidget *parent) layout->addLayout(hLayout); layout->addLayout(controlLayout); layout->addLayout(histogramLayout); +#if defined(Q_OS_QNX) + // On QNX, the main window doesn't have a title bar (or any other decorations). + // Create a status bar for the status information instead. + m_statusLabel = new QLabel; + m_statusBar = new QStatusBar; + m_statusBar->addPermanentWidget(m_statusLabel); + m_statusBar->setSizeGripEnabled(false); // Without mouse grabbing, it doesn't work very well. + layout->addWidget(m_statusBar); +#endif setLayout(layout); @@ -308,15 +317,17 @@ void Player::statusChanged(QMediaPlayer::MediaStatus status) case QMediaPlayer::UnknownMediaStatus: case QMediaPlayer::NoMedia: case QMediaPlayer::LoadedMedia: - case QMediaPlayer::BufferingMedia: - case QMediaPlayer::BufferedMedia: setStatusInfo(QString()); break; case QMediaPlayer::LoadingMedia: setStatusInfo(tr("Loading...")); break; + case QMediaPlayer::BufferingMedia: + case QMediaPlayer::BufferedMedia: + setStatusInfo(tr("Buffering %1%").arg(m_player->bufferStatus())); + break; case QMediaPlayer::StalledMedia: - setStatusInfo(tr("Media Stalled")); + setStatusInfo(tr("Stalled %1%").arg(m_player->bufferStatus())); break; case QMediaPlayer::EndOfMedia: QApplication::alert(this); @@ -347,7 +358,10 @@ void Player::handleCursor(QMediaPlayer::MediaStatus status) void Player::bufferingProgress(int progress) { - setStatusInfo(tr("Buffering %4%").arg(progress)); + if (m_player->mediaStatus() == QMediaPlayer::StalledMedia) + setStatusInfo(tr("Stalled %1%").arg(progress)); + else + setStatusInfo(tr("Buffering %1%").arg(progress)); } void Player::videoAvailableChanged(bool available) @@ -369,19 +383,31 @@ void Player::videoAvailableChanged(bool available) void Player::setTrackInfo(const QString &info) { m_trackInfo = info; - if (!m_statusInfo.isEmpty()) - setWindowTitle(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo)); - else - setWindowTitle(m_trackInfo); + + if (m_statusBar) { + m_statusBar->showMessage(m_trackInfo); + m_statusLabel->setText(m_statusInfo); + } else { + if (!m_statusInfo.isEmpty()) + setWindowTitle(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo)); + else + setWindowTitle(m_trackInfo); + } } void Player::setStatusInfo(const QString &info) { m_statusInfo = info; - if (!m_statusInfo.isEmpty()) - setWindowTitle(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo)); - else - setWindowTitle(m_trackInfo); + + if (m_statusBar) { + m_statusBar->showMessage(m_trackInfo); + m_statusLabel->setText(m_statusInfo); + } else { + if (!m_statusInfo.isEmpty()) + setWindowTitle(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo)); + else + setWindowTitle(m_trackInfo); + } } void Player::displayErrorMessage() diff --git a/examples/multimediawidgets/player/player.h b/examples/multimediawidgets/player/player.h index a15d27bd7..3002c9811 100644 --- a/examples/multimediawidgets/player/player.h +++ b/examples/multimediawidgets/player/player.h @@ -62,6 +62,7 @@ class QMediaPlayer; class QModelIndex; class QPushButton; class QSlider; +class QStatusBar; class QVideoProbe; class QVideoWidget; class QAudioProbe; @@ -123,6 +124,8 @@ private: QPushButton *m_fullScreenButton = nullptr; QPushButton *m_colorButton = nullptr; QDialog *m_colorDialog = nullptr; + QLabel *m_statusLabel = nullptr; + QStatusBar *m_statusBar = nullptr; QLabel *m_labelHistogram = nullptr; HistogramWidget *m_videoHistogram = nullptr; diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp index be2739941..c66ac937d 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.cpp @@ -121,6 +121,40 @@ void MmRendererMediaPlayerControl::handleMmStopped() } } +void MmRendererMediaPlayerControl::handleMmSuspend(const QString &reason) +{ + if (m_state == QMediaPlayer::StoppedState) + return; + + Q_UNUSED(reason); + setMediaStatus(QMediaPlayer::StalledMedia); +} + +void MmRendererMediaPlayerControl::handleMmSuspendRemoval(const QString &bufferStatus) +{ + if (m_state == QMediaPlayer::StoppedState) + return; + + if (bufferStatus == QLatin1String("buffering")) + setMediaStatus(QMediaPlayer::BufferingMedia); + else + setMediaStatus(QMediaPlayer::BufferedMedia); +} + +void MmRendererMediaPlayerControl::handleMmPause() +{ + if (m_state == QMediaPlayer::PlayingState) { + setState(QMediaPlayer::PausedState); + } +} + +void MmRendererMediaPlayerControl::handleMmPlay() +{ + if (m_state == QMediaPlayer::PausedState) { + setState(QMediaPlayer::PlayingState); + } +} + void MmRendererMediaPlayerControl::closeConnection() { stopMonitoring(); @@ -167,6 +201,8 @@ void MmRendererMediaPlayerControl::attach() return; } + resetMonitoring(); + if (m_videoRendererControl) m_videoRendererControl->attachDisplay(m_context); @@ -338,6 +374,7 @@ void MmRendererMediaPlayerControl::setState(QMediaPlayer::State state) void MmRendererMediaPlayerControl::stopInternal(StopCommand stopCommand) { + resetMonitoring(); setPosition(0); if (m_state != QMediaPlayer::StoppedState) { @@ -500,6 +537,7 @@ void MmRendererMediaPlayerControl::play() if (m_mediaStatus == QMediaPlayer::EndOfMedia) m_position = 0; + resetMonitoring(); setPositionInternal(m_position); setVolumeInternal(m_muted ? 0 : m_volume); setPlaybackRateInternal(m_rate); @@ -573,18 +611,11 @@ void MmRendererMediaPlayerControl::setMmBufferStatus(const QString &bufferStatus // ignore "idle" buffer status } -void MmRendererMediaPlayerControl::setMmBufferLevel(const QString &bufferLevel) +void MmRendererMediaPlayerControl::setMmBufferLevel(int level, int capacity) { - // buffer level has format level/capacity, e.g. "91319/124402" - const int slashPos = bufferLevel.indexOf('/'); - if (slashPos != -1) { - const int fill = bufferLevel.leftRef(slashPos).toInt(); - const int capacity = bufferLevel.midRef(slashPos + 1).toInt(); - if (capacity != 0) { - m_bufferLevel = fill / static_cast<float>(capacity) * 100.0f; - emit bufferStatusChanged(m_bufferLevel); - } - } + m_bufferLevel = capacity == 0 ? 0 : level / static_cast<float>(capacity) * 100.0f; + m_bufferLevel = qBound(0, m_bufferLevel, 100); + emit bufferStatusChanged(m_bufferLevel); } void MmRendererMediaPlayerControl::updateMetaData(const strm_dict *dict) diff --git a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h index e1530689e..3426ef2f2 100644 --- a/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h +++ b/src/plugins/qnx/mediaplayer/mmrenderermediaplayercontrol.h @@ -111,14 +111,19 @@ public: protected: virtual void startMonitoring() = 0; virtual void stopMonitoring() = 0; + virtual void resetMonitoring() = 0; void openConnection(); void emitMmError(const QString &msg); void emitPError(const QString &msg); void setMmPosition(qint64 newPosition); void setMmBufferStatus(const QString &bufferStatus); - void setMmBufferLevel(const QString &bufferLevel); + void setMmBufferLevel(int level, int capacity); void handleMmStopped(); + void handleMmSuspend(const QString &reason); + void handleMmSuspendRemoval(const QString &bufferStatus); + void handleMmPause(); + void handleMmPlay(); void updateMetaData(const strm_dict_t *dict); // must be called from subclass dtors (calls virtual function stopMonitoring()) diff --git a/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp index a0bac1261..c050c03c5 100644 --- a/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp +++ b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.cpp @@ -42,13 +42,39 @@ #include "mmrenderervideowindowcontrol.h" #include <mm/renderer.h> +#include <tuple> QT_BEGIN_NAMESPACE +static std::tuple<int, int, bool> parseBufferLevel(const QByteArray &value) +{ + const int slashPos = value.indexOf('/'); + if (slashPos <= 0) + return std::make_tuple(0, 0, false); + + bool ok = false; + const int level = value.left(slashPos).toInt(&ok); + if (!ok || level < 0) + return std::make_tuple(0, 0, false); + + const int capacity = value.mid(slashPos + 1).toInt(&ok); + if (!ok || capacity < 0) + return std::make_tuple(0, 0, false); + + return std::make_tuple(level, capacity, true); +} + MmrEventMediaPlayerControl::MmrEventMediaPlayerControl(QObject *parent) : MmRendererMediaPlayerControl(parent) , m_eventThread(nullptr) + , m_bufferStatus("") + , m_bufferLevel(0) + , m_bufferCapacity(0) + , m_position(0) + , m_suspended(false) + , m_suspendedReason("unknown") , m_state(MMR_STATE_IDLE) + , m_speed(0) { openConnection(); } @@ -75,6 +101,18 @@ void MmrEventMediaPlayerControl::stopMonitoring() m_eventThread = nullptr; } +void MmrEventMediaPlayerControl::resetMonitoring() +{ + m_bufferStatus = ""; + m_bufferLevel = 0; + m_bufferCapacity = 0; + m_position = 0; + m_suspended = false; + m_suspendedReason = "unknown"; + m_state = MMR_STATE_IDLE; + m_speed = 0; +} + bool MmrEventMediaPlayerControl::nativeEventFilter(const QByteArray &eventType, void *message, long *result) @@ -102,32 +140,68 @@ void MmrEventMediaPlayerControl::readEvents() if (event->data) { const strm_string_t *value; value = strm_dict_find_rstr(event->data, "bufferstatus"); - if (value) - setMmBufferStatus(QString::fromLatin1(strm_string_get(value))); + if (value) { + m_bufferStatus = QByteArray(strm_string_get(value)); + if (!m_suspended) + setMmBufferStatus(m_bufferStatus); + } value = strm_dict_find_rstr(event->data, "bufferlevel"); - if (value) - setMmBufferLevel(QString::fromLatin1(strm_string_get(value))); + if (value) { + const char *cstrValue = strm_string_get(value); + int level; + int capacity; + bool ok; + std::tie(level, capacity, ok) = parseBufferLevel(QByteArray(cstrValue)); + if (!ok) { + qCritical("Could not parse buffer capacity from '%s'", cstrValue); + } else { + m_bufferLevel = level; + m_bufferCapacity = capacity; + setMmBufferLevel(level, capacity); + } + } + + value = strm_dict_find_rstr(event->data, "suspended"); + if (value) { + if (!m_suspended) { + m_suspended = true; + m_suspendedReason = strm_string_get(value); + handleMmSuspend(m_suspendedReason); + } + } else if (m_suspended) { + m_suspended = false; + handleMmSuspendRemoval(m_bufferStatus); + } } if (event->pos_str) { const QByteArray valueBa = QByteArray(event->pos_str); bool ok; - const qint64 position = valueBa.toLongLong(&ok); + m_position = valueBa.toLongLong(&ok); if (!ok) { qCritical("Could not parse position from '%s'", valueBa.constData()); } else { - setMmPosition(position); + setMmPosition(m_position); } } break; } + case MMR_EVENT_STATE: { + if (event->state == MMR_STATE_PLAYING && m_speed != event->speed) { + m_speed = event->speed; + if (m_speed == 0) + handleMmPause(); + else + handleMmPlay(); + } + break; + } case MMR_EVENT_METADATA: { updateMetaData(event->data); break; } case MMR_EVENT_ERROR: - case MMR_EVENT_STATE: case MMR_EVENT_NONE: case MMR_EVENT_OVERFLOW: case MMR_EVENT_WARNING: diff --git a/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h index cc1ded3b1..0e4defc5c 100644 --- a/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h +++ b/src/plugins/qnx/mediaplayer/mmreventmediaplayercontrol.h @@ -56,6 +56,7 @@ public: void startMonitoring() override; void stopMonitoring() override; + void resetMonitoring() override; bool nativeEventFilter(const QByteArray &eventType, void *message, @@ -66,7 +67,18 @@ private Q_SLOTS: private: MmrEventThread *m_eventThread; + + // status properties. + QByteArray m_bufferStatus; + int m_bufferLevel; + int m_bufferCapacity; + qint64 m_position; + bool m_suspended; + QByteArray m_suspendedReason; + + // state properties. mmr_state_t m_state; + int m_speed; }; QT_END_NAMESPACE |