summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/multimediawidgets/player/CMakeLists.txt1
-rw-r--r--examples/multimediawidgets/player/histogramwidget.cpp259
-rw-r--r--examples/multimediawidgets/player/histogramwidget.h98
-rw-r--r--examples/multimediawidgets/player/player.cpp205
-rw-r--r--examples/multimediawidgets/player/player.h9
-rw-r--r--examples/multimediawidgets/player/player.pro2
6 files changed, 92 insertions, 482 deletions
diff --git a/examples/multimediawidgets/player/CMakeLists.txt b/examples/multimediawidgets/player/CMakeLists.txt
index d38416626..8aa735e96 100644
--- a/examples/multimediawidgets/player/CMakeLists.txt
+++ b/examples/multimediawidgets/player/CMakeLists.txt
@@ -19,7 +19,6 @@ find_package(Qt6 COMPONENTS Network)
find_package(Qt6 COMPONENTS MultimediaWidgets)
qt_add_executable(player
- histogramwidget.cpp histogramwidget.h
main.cpp
player.cpp player.h
playercontrols.cpp playercontrols.h
diff --git a/examples/multimediawidgets/player/histogramwidget.cpp b/examples/multimediawidgets/player/histogramwidget.cpp
deleted file mode 100644
index 26595dd8a..000000000
--- a/examples/multimediawidgets/player/histogramwidget.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "histogramwidget.h"
-#include <QPainter>
-#include <QHBoxLayout>
-
-class QAudioLevel : public QWidget
-{
- Q_OBJECT
-public:
- explicit QAudioLevel(QWidget *parent = nullptr);
-
- // Using [0; 1.0] range
- void setLevel(qreal level);
-
-protected:
- void paintEvent(QPaintEvent *event) override;
-
-private:
- qreal m_level = 0;
-};
-
-QAudioLevel::QAudioLevel(QWidget *parent)
- : QWidget(parent)
-{
- setMinimumHeight(15);
- setMaximumHeight(50);
-}
-
-void QAudioLevel::setLevel(qreal level)
-{
- if (m_level != level) {
- m_level = level;
- update();
- }
-}
-
-void QAudioLevel::paintEvent(QPaintEvent *event)
-{
- Q_UNUSED(event);
-
- QPainter painter(this);
- // draw level
- qreal widthLevel = m_level * width();
- painter.fillRect(0, 0, widthLevel, height(), Qt::red);
- // clear the rest of the control
- painter.fillRect(widthLevel, 0, width(), height(), Qt::black);
-}
-
-HistogramWidget::HistogramWidget(QWidget *parent)
- : QWidget(parent)
-{
- m_processor.moveToThread(&m_processorThread);
- connect(&m_processor, &FrameProcessor::histogramReady, this, &HistogramWidget::setHistogram);
- m_processorThread.start(QThread::LowestPriority);
- setLayout(new QHBoxLayout);
-}
-
-HistogramWidget::~HistogramWidget()
-{
- m_processorThread.quit();
- m_processorThread.wait(10000);
-}
-
-void HistogramWidget::processFrame(const QVideoFrame &frame)
-{
- if (m_isBusy && frame.isValid())
- return; //drop frame
-
- m_isBusy = true;
- QMetaObject::invokeMethod(&m_processor, "processFrame",
- Qt::QueuedConnection, Q_ARG(QVideoFrame, frame), Q_ARG(int, m_levels));
-}
-
-// returns the audio level for each channel
-QList<qreal> getBufferLevels(const QAudioBuffer &buffer)
-{
- QList<qreal> values;
-
- if (!buffer.isValid())
- return values;
-
- if (!buffer.format().isValid())
- return values;
-
- auto format = buffer.format();
- int channelCount = format.channelCount();
- int bytesPerSample = format.bytesPerFrame();
- int frames = buffer.frameCount();
-
- values.fill(0, channelCount);
-
- const char *data = buffer.constData<char>();
- for (int i = 0; i < frames; ++i) {
- for (int j = 0; j < channelCount; ++j) {
- qreal value = format.normalizedSampleValue(data);
- if (value > values.at(j))
- values[j] = value;
- data += bytesPerSample;
- }
- }
-
- return values;
-}
-
-void HistogramWidget::processBuffer(const QAudioBuffer &buffer)
-{
- if (m_audioLevels.count() != buffer.format().channelCount()) {
- qDeleteAll(m_audioLevels);
- m_audioLevels.clear();
- for (int i = 0; i < buffer.format().channelCount(); ++i) {
- QAudioLevel *level = new QAudioLevel(this);
- m_audioLevels.append(level);
- layout()->addWidget(level);
- }
- }
-
- QList<qreal> levels = getBufferLevels(buffer);
- for (int i = 0; i < levels.count(); ++i)
- m_audioLevels.at(i)->setLevel(levels.at(i));
-}
-
-void HistogramWidget::setHistogram(const QList<qreal> &histogram)
-{
- m_isBusy = false;
- m_histogram = histogram;
- update();
-}
-
-void HistogramWidget::paintEvent(QPaintEvent *event)
-{
- Q_UNUSED(event);
-
- if (!m_audioLevels.isEmpty())
- return;
-
- QPainter painter(this);
-
- if (m_histogram.isEmpty()) {
- painter.fillRect(0, 0, width(), height(), QColor::fromRgb(0, 0, 0));
- return;
- }
-
- qreal barWidth = width() / (qreal)m_histogram.size();
-
- for (int i = 0; i < m_histogram.size(); ++i) {
- qreal h = m_histogram[i] * height();
- // draw level
- painter.fillRect(barWidth * i, height() - h, barWidth * (i + 1), height(), Qt::red);
- // clear the rest of the control
- painter.fillRect(barWidth * i, 0, barWidth * (i + 1), height() - h, Qt::black);
- }
-}
-
-void FrameProcessor::processFrame(QVideoFrame frame, int levels)
-{
- QList<qreal> histogram(levels);
-
- do {
- if (!levels)
- break;
-
- if (!frame.map(QVideoFrame::ReadOnly))
- break;
-
- if (frame.pixelFormat() == QVideoFrameFormat::Format_YUV420P ||
- frame.pixelFormat() == QVideoFrameFormat::Format_NV12) {
- // Process YUV data
- uchar *b = frame.bits(0);
- for (int y = 0; y < frame.height(); ++y) {
- uchar *lastPixel = b + frame.width();
- for (uchar *curPixel = b; curPixel < lastPixel; curPixel++)
- histogram[(*curPixel * levels) >> 8] += 1.0;
- b += frame.bytesPerLine(0);
- }
- } else {
- QImage::Format imageFormat = QVideoFrameFormat::imageFormatFromPixelFormat(frame.pixelFormat());
- if (imageFormat != QImage::Format_Invalid) {
- // Process RGB data
- QImage image(frame.bits(0), frame.width(), frame.height(), imageFormat);
- image = image.convertToFormat(QImage::Format_RGB32);
-
- const QRgb* b = (const QRgb*)image.bits();
- for (int y = 0; y < image.height(); ++y) {
- const QRgb *lastPixel = b + frame.width();
- for (const QRgb *curPixel = b; curPixel < lastPixel; curPixel++)
- histogram[(qGray(*curPixel) * levels) >> 8] += 1.0;
- b = (const QRgb*)((uchar*)b + image.bytesPerLine());
- }
- }
- }
-
- // find maximum value
- qreal maxValue = 0.0;
- for (double i : qAsConst(histogram)) {
- if (i > maxValue)
- maxValue = i;
- }
-
- if (maxValue > 0.0) {
- for (double &i : histogram)
- i /= maxValue;
- }
-
- frame.unmap();
- } while (false);
-
- emit histogramReady(histogram);
-}
-
-#include "histogramwidget.moc"
diff --git a/examples/multimediawidgets/player/histogramwidget.h b/examples/multimediawidgets/player/histogramwidget.h
deleted file mode 100644
index 08ba4f342..000000000
--- a/examples/multimediawidgets/player/histogramwidget.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef HISTOGRAMWIDGET_H
-#define HISTOGRAMWIDGET_H
-
-#include <QThread>
-#include <QVideoFrame>
-#include <QAudioBuffer>
-#include <QWidget>
-
-class QAudioLevel;
-
-class FrameProcessor: public QObject
-{
- Q_OBJECT
-
-public slots:
- void processFrame(QVideoFrame frame, int levels);
-
-signals:
- void histogramReady(const QList<qreal> &histogram);
-};
-
-class HistogramWidget : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit HistogramWidget(QWidget *parent = nullptr);
- ~HistogramWidget();
- void setLevels(int levels) { m_levels = levels; }
-
-public slots:
- void processFrame(const QVideoFrame &frame);
- void processBuffer(const QAudioBuffer &buffer);
- void setHistogram(const QList<qreal> &histogram);
-
-protected:
- void paintEvent(QPaintEvent *event) override;
-
-private:
- QList<qreal> m_histogram;
- int m_levels = 128;
- FrameProcessor m_processor;
- QThread m_processorThread;
- bool m_isBusy = false;
- QList<QAudioLevel *> m_audioLevels;
-};
-
-#endif // HISTOGRAMWIDGET_H
diff --git a/examples/multimediawidgets/player/player.cpp b/examples/multimediawidgets/player/player.cpp
index cabf43b63..c818d3f16 100644
--- a/examples/multimediawidgets/player/player.cpp
+++ b/examples/multimediawidgets/player/player.cpp
@@ -52,7 +52,6 @@
#include "playercontrols.h"
#include "playlistmodel.h"
-#include "histogramwidget.h"
#include "videowidget.h"
#include <qmediaplaylist.h>
@@ -71,6 +70,14 @@ Player::Player(QWidget *parent)
m_audioOutput = new QAudioOutput(this);
m_player->setAudioOutput(m_audioOutput);
//! [create-objs]
+ connect(m_player, &QMediaPlayer::durationChanged, this, &Player::durationChanged);
+ connect(m_player, &QMediaPlayer::positionChanged, this, &Player::positionChanged);
+ connect(m_player, QOverload<>::of(&QMediaPlayer::metaDataChanged), this, &Player::metaDataChanged);
+ connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &Player::statusChanged);
+ connect(m_player, &QMediaPlayer::bufferProgressChanged, this, &Player::bufferingProgress);
+ connect(m_player, &QMediaPlayer::hasVideoChanged, this, &Player::videoAvailableChanged);
+ connect(m_player, &QMediaPlayer::errorChanged, this, &Player::displayErrorMessage);
+ connect(m_player, &QMediaPlayer::tracksChanged, this, &Player::tracksChanged);
//! [2]
m_videoWidget = new VideoWidget(this);
@@ -80,89 +87,46 @@ Player::Player(QWidget *parent)
m_playlistModel = new PlaylistModel(this);
m_playlist = m_playlistModel->playlist();
//! [2]
-
- connect(m_player, &QMediaPlayer::durationChanged, this, &Player::durationChanged);
- connect(m_player, &QMediaPlayer::positionChanged, this, &Player::positionChanged);
- connect(m_player, QOverload<>::of(&QMediaPlayer::metaDataChanged), this, &Player::metaDataChanged);
connect(m_playlist, &QMediaPlaylist::currentIndexChanged, this, &Player::playlistPositionChanged);
- connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &Player::statusChanged);
- connect(m_player, &QMediaPlayer::bufferProgressChanged, this, &Player::bufferingProgress);
- connect(m_player, &QMediaPlayer::hasVideoChanged, this, &Player::videoAvailableChanged);
- connect(m_player, &QMediaPlayer::errorChanged, this, &Player::displayErrorMessage);
- connect(m_player, &QMediaPlayer::playbackStateChanged, this, &Player::stateChanged);
- connect(m_player, &QMediaPlayer::tracksChanged, this, &Player::tracksChanged);
- m_playlistView = new QListView(this);
+ // player layout
+ QBoxLayout *layout = new QVBoxLayout(this);
+
+ // display
+ QBoxLayout *displayLayout = new QHBoxLayout;
+ displayLayout->addWidget(m_videoWidget, 2);
+#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
+ m_playlistView = new QListView();
m_playlistView->setModel(m_playlistModel);
m_playlistView->setCurrentIndex(m_playlistModel->index(m_playlist->currentIndex(), 0));
-
connect(m_playlistView, &QAbstractItemView::activated, this, &Player::jump);
+ displayLayout->addWidget(m_playlistView);
+#endif
+ layout->addLayout(displayLayout);
+
+ // duration slider and label
+ QHBoxLayout *hLayout = new QHBoxLayout;
m_slider = new QSlider(Qt::Horizontal, this);
m_slider->setRange(0, m_player->duration() / 1000);
-
- m_labelDuration = new QLabel(this);
- m_labelDuration->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
connect(m_slider, &QSlider::sliderMoved, this, &Player::seek);
+ hLayout->addWidget(m_slider);
- m_audioTracks = new QComboBox(this);
- m_videoTracks = new QComboBox(this);
- m_subtitleTracks = new QComboBox(this);
- connect(m_audioTracks, &QComboBox::activated, this, &Player::selectAudioStream);
- connect(m_videoTracks, &QComboBox::activated, this, &Player::selectVideoStream);
- connect(m_subtitleTracks, &QComboBox::activated, this, &Player::selectSubtitleStream);
- QGridLayout *tracksLayout = new QGridLayout;
- tracksLayout->addWidget(new QLabel(tr("Audio Tracks:"), this), 0, 0);
- tracksLayout->addWidget(m_audioTracks, 0, 1);
- tracksLayout->addWidget(new QLabel(tr("Video Tracks:"), this), 1, 0);
- tracksLayout->addWidget(m_videoTracks, 1, 1);
- tracksLayout->addWidget(new QLabel(tr("Subtitle Tracks:"), this), 2, 0);
- tracksLayout->addWidget(m_subtitleTracks, 2, 1);
-
- m_labelHistogram = new QLabel(this);
- m_labelHistogram->setText("Histogram:");
- m_videoHistogram = new HistogramWidget(this);
- m_audioHistogram = new HistogramWidget(this);
- QHBoxLayout *histogramLayout = new QHBoxLayout;
- histogramLayout->addWidget(m_labelHistogram);
- histogramLayout->addWidget(m_videoHistogram, 1);
- histogramLayout->addWidget(m_audioHistogram, 2);
-
- QGridLayout *metaDataLayout = new QGridLayout;
- int key = QMediaMetaData::Title;
- for (int i = 0; i < (QMediaMetaData::NumMetaData + 2)/3; i++) {
- for (int j = 0; j < 6; j+=2) {
- m_metaDataLabels[key] = new QLabel(QMediaMetaData::metaDataKeyToString
- (static_cast<QMediaMetaData::Key>(key)));
- if (key == QMediaMetaData::ThumbnailImage
- || key == QMediaMetaData::CoverArtImage)
- m_metaDataFields[key] = new QLabel;
- else
- m_metaDataFields[key] = new QLineEdit;
- m_metaDataLabels[key]->setDisabled(true);
- m_metaDataFields[key]->setDisabled(true);
- metaDataLayout->addWidget(m_metaDataLabels[key], i, j);
- metaDataLayout->addWidget(m_metaDataFields[key], i, j+1);
- key++;
- if (key == QMediaMetaData::NumMetaData)
- break;
- }
- }
-
- // ### replace by a monitoring outputs once we have them
-// m_videoProbe = new QVideoProbe(this);
-// connect(m_videoProbe, &QVideoProbe::videoFrameProbed, m_videoHistogram, &HistogramWidget::processFrame);
-// m_videoProbe->setSource(m_player);
+ m_labelDuration = new QLabel();
+ m_labelDuration->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ hLayout->addWidget(m_labelDuration);
+ layout->addLayout(hLayout);
-// m_audioProbe = new QAudioProbe(this);
-// connect(m_audioProbe, &QAudioProbe::audioBufferProbed, m_audioHistogram, &HistogramWidget::processBuffer);
-// m_audioProbe->setSource(m_player);
+ // controls
+ QBoxLayout *controlLayout = new QHBoxLayout;
+ controlLayout->setContentsMargins(0, 0, 0, 0);
QPushButton *openButton = new QPushButton(tr("Open"), this);
-
connect(openButton, &QPushButton::clicked, this, &Player::open);
+ controlLayout->addWidget(openButton);
+ controlLayout->addStretch(1);
- PlayerControls *controls = new PlayerControls(this);
+ PlayerControls *controls = new PlayerControls();
controls->setState(m_player->playbackState());
controls->setVolume(m_audioOutput->volume());
controls->setMuted(controls->isMuted());
@@ -181,49 +145,74 @@ Player::Player(QWidget *parent)
connect(m_audioOutput, &QAudioOutput::volumeChanged, controls, &PlayerControls::setVolume);
connect(m_audioOutput, &QAudioOutput::mutedChanged, controls, &PlayerControls::setMuted);
+ controlLayout->addWidget(controls);
+ controlLayout->addStretch(1);
+
m_fullScreenButton = new QPushButton(tr("FullScreen"), this);
m_fullScreenButton->setCheckable(true);
-
+ controlLayout->addWidget(m_fullScreenButton);
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
m_audioOutputCombo = new QComboBox(this);
m_audioOutputCombo->addItem(QString::fromUtf8("Default"), QVariant::fromValue(QAudioDevice()));
for (auto &deviceInfo: QMediaDevices::audioOutputs())
m_audioOutputCombo->addItem(deviceInfo.description(), QVariant::fromValue(deviceInfo));
- connect(m_audioOutputCombo, QOverload<int>::of(&QComboBox::activated), this, &Player::audioOutputChanged);
-#endif
-
- QBoxLayout *displayLayout = new QHBoxLayout;
- displayLayout->addWidget(m_videoWidget, 2);
-#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
- displayLayout->addWidget(m_playlistView);
-#endif
-
- QBoxLayout *controlLayout = new QHBoxLayout;
- controlLayout->setContentsMargins(0, 0, 0, 0);
- controlLayout->addWidget(openButton);
- controlLayout->addStretch(1);
- controlLayout->addWidget(controls);
- controlLayout->addStretch(1);
- controlLayout->addWidget(m_fullScreenButton);
-#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
+ connect(m_audioOutputCombo, QOverload<int>::of(&QComboBox::activated), this,
+ &Player::audioOutputChanged);
controlLayout->addWidget(m_audioOutputCombo);
#endif
- QBoxLayout *layout = new QVBoxLayout;
- layout->addLayout(displayLayout);
- QHBoxLayout *hLayout = new QHBoxLayout;
- hLayout->addWidget(m_slider);
- hLayout->addWidget(m_labelDuration);
- layout->addLayout(hLayout);
layout->addLayout(controlLayout);
+
+ // tracks
+ QGridLayout *tracksLayout = new QGridLayout;
+
+ m_audioTracks = new QComboBox(this);
+ connect(m_audioTracks, &QComboBox::activated, this, &Player::selectAudioStream);
+ tracksLayout->addWidget(new QLabel(tr("Audio Tracks:")), 0, 0);
+ tracksLayout->addWidget(m_audioTracks, 0, 1);
+
+ m_videoTracks = new QComboBox(this);
+ connect(m_videoTracks, &QComboBox::activated, this, &Player::selectVideoStream);
+ tracksLayout->addWidget(new QLabel(tr("Video Tracks:")), 1, 0);
+ tracksLayout->addWidget(m_videoTracks, 1, 1);
+
+ m_subtitleTracks = new QComboBox(this);
+ connect(m_subtitleTracks, &QComboBox::activated, this, &Player::selectSubtitleStream);
+ tracksLayout->addWidget(new QLabel(tr("Subtitle Tracks:")), 2, 0);
+ tracksLayout->addWidget(m_subtitleTracks, 2, 1);
+
layout->addLayout(tracksLayout);
+
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
- layout->addLayout(histogramLayout);
+ // metadata
+
QLabel *metaDataLabel = new QLabel(tr("Metadata for file:"));
layout->addWidget(metaDataLabel);
+
+ QGridLayout *metaDataLayout = new QGridLayout;
+ int key = QMediaMetaData::Title;
+ for (int i = 0; i < (QMediaMetaData::NumMetaData + 2) / 3; i++) {
+ for (int j = 0; j < 6; j += 2) {
+ m_metaDataLabels[key] = new QLabel(
+ QMediaMetaData::metaDataKeyToString(static_cast<QMediaMetaData::Key>(key)));
+ if (key == QMediaMetaData::ThumbnailImage || key == QMediaMetaData::CoverArtImage)
+ m_metaDataFields[key] = new QLabel;
+ else
+ m_metaDataFields[key] = new QLineEdit;
+ m_metaDataLabels[key]->setDisabled(true);
+ m_metaDataFields[key]->setDisabled(true);
+ metaDataLayout->addWidget(m_metaDataLabels[key], i, j);
+ metaDataLayout->addWidget(m_metaDataFields[key], i, j + 1);
+ key++;
+ if (key == QMediaMetaData::NumMetaData)
+ break;
+ }
+ }
+
layout->addLayout(metaDataLayout);
#endif
+
#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.
@@ -242,7 +231,8 @@ Player::Player(QWidget *parent)
"Please check the media service plugins are installed."));
controls->setEnabled(false);
- m_playlistView->setEnabled(false);
+ if (m_playlistView)
+ m_playlistView->setEnabled(false);
openButton->setEnabled(false);
m_fullScreenButton->setEnabled(false);
}
@@ -250,10 +240,6 @@ Player::Player(QWidget *parent)
metaDataChanged();
}
-Player::~Player()
-{
-}
-
bool Player::isPlayerAvailable() const
{
return m_player->isAvailable();
@@ -288,7 +274,8 @@ void Player::addToPlaylist(const QList<QUrl> &urls)
}
if (m_playlist->mediaCount() > previousMediaCount) {
auto index = m_playlistModel->index(previousMediaCount, 0);
- m_playlistView->setCurrentIndex(index);
+ if (m_playlistView)
+ m_playlistView->setCurrentIndex(index);
jump(index);
}
}
@@ -314,6 +301,7 @@ void Player::metaDataChanged()
.arg(metaData.value(QMediaMetaData::AlbumArtist).toString())
.arg(metaData.value(QMediaMetaData::Title).toString()));
+#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
for (int i = 0; i < QMediaMetaData::NumMetaData; i++) {
if (QLineEdit* field = qobject_cast<QLineEdit*>(m_metaDataFields[i]))
field->clear();
@@ -344,6 +332,7 @@ void Player::metaDataChanged()
m_metaDataFields[i]->setDisabled(false);
m_metaDataLabels[i]->setDisabled(false);
}
+#endif
}
QString Player::trackName(const QMediaMetaData &metaData, int index)
@@ -411,8 +400,8 @@ void Player::jump(const QModelIndex &index)
void Player::playlistPositionChanged(int currentItem)
{
- clearHistogram();
- m_playlistView->setCurrentIndex(m_playlistModel->index(currentItem, 0));
+ if (m_playlistView)
+ m_playlistView->setCurrentIndex(m_playlistModel->index(currentItem, 0));
m_player->setSource(m_playlist->currentMedia());
}
@@ -451,12 +440,6 @@ void Player::statusChanged(QMediaPlayer::MediaStatus status)
}
}
-void Player::stateChanged(QMediaPlayer::PlaybackState state)
-{
- if (state == QMediaPlayer::StoppedState)
- clearHistogram();
-}
-
void Player::handleCursor(QMediaPlayer::MediaStatus status)
{
#ifndef QT_NO_CURSOR
@@ -568,9 +551,3 @@ void Player::audioOutputChanged(int index)
auto device = m_audioOutputCombo->itemData(index).value<QAudioDevice>();
m_player->audioOutput()->setDevice(device);
}
-
-void Player::clearHistogram()
-{
- QMetaObject::invokeMethod(m_videoHistogram, "processFrame", Qt::QueuedConnection, Q_ARG(QVideoFrame, QVideoFrame()));
- QMetaObject::invokeMethod(m_audioHistogram, "processBuffer", Qt::QueuedConnection, Q_ARG(QAudioBuffer, QAudioBuffer()));
-}
diff --git a/examples/multimediawidgets/player/player.h b/examples/multimediawidgets/player/player.h
index 89bf39008..b5d9970da 100644
--- a/examples/multimediawidgets/player/player.h
+++ b/examples/multimediawidgets/player/player.h
@@ -69,7 +69,6 @@ class QVideoWidget;
QT_END_NAMESPACE
class PlaylistModel;
-class HistogramWidget;
class Player : public QWidget
{
@@ -77,7 +76,7 @@ class Player : public QWidget
public:
explicit Player(QWidget *parent = nullptr);
- ~Player();
+ ~Player() = default;
bool isPlayerAvailable() const;
@@ -100,7 +99,6 @@ private slots:
void playlistPositionChanged(int);
void statusChanged(QMediaPlayer::MediaStatus status);
- void stateChanged(QMediaPlayer::PlaybackState state);
void bufferingProgress(float progress);
void videoAvailableChanged(bool available);
@@ -113,7 +111,6 @@ private slots:
void audioOutputChanged(int);
private:
- void clearHistogram();
void setTrackInfo(const QString &info);
void setStatusInfo(const QString &info);
void handleCursor(QMediaPlayer::MediaStatus status);
@@ -135,10 +132,6 @@ private:
QComboBox *m_videoTracks = nullptr;
QComboBox *m_subtitleTracks = nullptr;
- QLabel *m_labelHistogram = nullptr;
- HistogramWidget *m_videoHistogram = nullptr;
- HistogramWidget *m_audioHistogram = nullptr;
-
PlaylistModel *m_playlistModel = nullptr;
QAbstractItemView *m_playlistView = nullptr;
QString m_trackInfo;
diff --git a/examples/multimediawidgets/player/player.pro b/examples/multimediawidgets/player/player.pro
index 42a56e5d9..950fe8e0d 100644
--- a/examples/multimediawidgets/player/player.pro
+++ b/examples/multimediawidgets/player/player.pro
@@ -11,7 +11,6 @@ HEADERS = \
playercontrols.h \
playlistmodel.h \
videowidget.h \
- histogramwidget.h \
qmediaplaylist.h \
qmediaplaylist_p.h \
qplaylistfileparser_p.h
@@ -21,7 +20,6 @@ SOURCES = main.cpp \
playercontrols.cpp \
playlistmodel.cpp \
videowidget.cpp \
- histogramwidget.cpp \
qmediaplaylist.cpp \
qplaylistfileparser.cpp