diff options
-rw-r--r-- | examples/multimediawidgets/player/CMakeLists.txt | 1 | ||||
-rw-r--r-- | examples/multimediawidgets/player/histogramwidget.cpp | 259 | ||||
-rw-r--r-- | examples/multimediawidgets/player/histogramwidget.h | 98 | ||||
-rw-r--r-- | examples/multimediawidgets/player/player.cpp | 205 | ||||
-rw-r--r-- | examples/multimediawidgets/player/player.h | 9 | ||||
-rw-r--r-- | examples/multimediawidgets/player/player.pro | 2 |
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 |