diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e899ba7..8200ef1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -40,9 +40,9 @@ file(GLOB SOURCE_FILES
)
if(QML)
- find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Network Svg Xml WebSockets Quick Qml QuickControls2 QmlImportScanner Multimedia)
+ find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Network Svg Xml WebSockets Quick Qml QuickControls2 QmlImportScanner Multimedia MultimediaWidgets)
else()
- find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Network Svg Xml WebSockets Multimedia)
+ find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Network Svg Xml WebSockets Multimedia MultimediaWidgets)
endif()
if(OPENVR)
@@ -148,6 +148,7 @@ target_include_directories(wowlet PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/utils
${CMAKE_CURRENT_SOURCE_DIR}/tor
${CMAKE_CURRENT_SOURCE_DIR}/qrcode
+ ${CMAKE_CURRENT_SOURCE_DIR}/widgets
${X11_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
@@ -158,6 +159,8 @@ target_include_directories(wowlet PUBLIC
${Qt5Svg_INCLUDE_DIRS}
${Qt5Xml_INCLUDE_DIRS}
${Qt5WebSockets_INCLUDE_DIRS}
+ ${Qt5Multimedia_INCLUDE_DIRS}
+ ${Qt5MultimediaWidgets_INCLUDE_DIRS}
)
if(OPENVR)
@@ -230,6 +233,8 @@ target_compile_definitions(wowlet
${Qt5Svg_DEFINITIONS}
${Qt5Xml_DEFINITIONS}
${Qt5WebSockets_DEFINITIONS}
+ ${Qt5Multimedia_DEFINITIONS}
+ ${Qt5MultimediaWidgets_DEFINITIONS}
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
@@ -273,7 +278,9 @@ if(QML)
Qt5::WebSockets
Qt5::Quick
Qt5::Qml
- Qt5::QuickControls2)
+ Qt5::QuickControls2
+ Qt5::Multimedia
+ Qt5::MultimediaWidgets)
else()
target_link_libraries(wowlet PUBLIC
Qt5::Core
@@ -282,7 +289,9 @@ else()
Qt5::Network
Qt5::Svg
Qt5::Xml
- Qt5::WebSockets)
+ Qt5::WebSockets
+ Qt5::Multimedia
+ Qt5::MultimediaWidgets)
endif()
if(ANDROID)
@@ -395,4 +404,4 @@ message(STATUS "This build is for Android: ${ANDROID}")
message(STATUS "This build is for testing the Android app on desktop: ${ANDROID_DEBUG}")
message(STATUS "TOR_BIN: ${TOR_BIN}")
message(STATUS "DONATE_BEG: ${DONATE_BEG}")
-message(STATUS "=============================================")
\ No newline at end of file
+message(STATUS "=============================================")
diff --git a/src/assets.qrc b/src/assets.qrc
index da545e3..2f1eae1 100644
--- a/src/assets.qrc
+++ b/src/assets.qrc
@@ -224,6 +224,7 @@
assets/images/xmrig.svg
assets/images/zoom.png
assets/mnemonic_25_english.txt
+ assets/videos/do_you_even_wow_special_friend.mp4
assets/restore_heights_wownero_mainnet.txt
diff --git a/src/assets/videos/do_you_even_wow_special_friend.mp4 b/src/assets/videos/do_you_even_wow_special_friend.mp4
new file mode 100644
index 0000000..cf073e8
Binary files /dev/null and b/src/assets/videos/do_you_even_wow_special_friend.mp4 differ
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 574c282..6d8a9de 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -181,6 +181,35 @@
+
+
+ WowPlayer
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 320
+
+
+
+
+
+
WFS
@@ -784,6 +813,12 @@
1
+
+ WowPlayerWidget
+ QWidget
+ widgets/wowplayerwidget.h
+ 1
+
ForumWidget
QWidget
diff --git a/src/widgets/wowplayercontrols.cpp b/src/widgets/wowplayercontrols.cpp
new file mode 100644
index 0000000..74ae38c
--- /dev/null
+++ b/src/widgets/wowplayercontrols.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** 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 "wowplayercontrols.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+PlayerControls::PlayerControls(QWidget *parent)
+ : QWidget(parent)
+{
+ m_playButton = new QToolButton(this);
+ m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+
+ connect(m_playButton, &QAbstractButton::clicked, this, &PlayerControls::playClicked);
+
+ m_stopButton = new QToolButton(this);
+ m_stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
+ m_stopButton->setEnabled(false);
+
+ connect(m_stopButton, &QAbstractButton::clicked, this, &PlayerControls::stop);
+
+ m_nextButton = new QToolButton(this);
+ m_nextButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipForward));
+
+ connect(m_nextButton, &QAbstractButton::clicked, this, &PlayerControls::next);
+
+ m_previousButton = new QToolButton(this);
+ m_previousButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
+
+ connect(m_previousButton, &QAbstractButton::clicked, this, &PlayerControls::previous);
+
+ m_muteButton = new QToolButton(this);
+ m_muteButton->setIcon(style()->standardIcon(QStyle::SP_MediaVolume));
+
+ connect(m_muteButton, &QAbstractButton::clicked, this, &PlayerControls::muteClicked);
+
+ m_volumeSlider = new QSlider(Qt::Horizontal, this);
+ m_volumeSlider->setRange(0, 100);
+
+ connect(m_volumeSlider, &QSlider::valueChanged, this, &PlayerControls::onVolumeSliderValueChanged);
+
+ m_rateBox = new QComboBox(this);
+ m_rateBox->addItem("0.5x", QVariant(0.5));
+ m_rateBox->addItem("1.0x", QVariant(1.0));
+ m_rateBox->addItem("2.0x", QVariant(2.0));
+ m_rateBox->setCurrentIndex(1);
+
+ connect(m_rateBox, QOverload::of(&QComboBox::activated), this, &PlayerControls::updateRate);
+
+ QBoxLayout *layout = new QHBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(m_stopButton);
+ layout->addWidget(m_previousButton);
+ layout->addWidget(m_playButton);
+ layout->addWidget(m_nextButton);
+ layout->addWidget(m_muteButton);
+ layout->addWidget(m_volumeSlider);
+ layout->addWidget(m_rateBox);
+ setLayout(layout);
+}
+
+QMediaPlayer::State PlayerControls::state() const
+{
+ return m_playerState;
+}
+
+void PlayerControls::setState(QMediaPlayer::State state)
+{
+ if (state != m_playerState) {
+ m_playerState = state;
+
+ switch (state) {
+ case QMediaPlayer::StoppedState:
+ m_stopButton->setEnabled(false);
+ m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ case QMediaPlayer::PlayingState:
+ m_stopButton->setEnabled(true);
+ m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause));
+ break;
+ case QMediaPlayer::PausedState:
+ m_stopButton->setEnabled(true);
+ m_playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
+ break;
+ }
+ }
+}
+
+int PlayerControls::volume() const
+{
+ qreal linearVolume = QAudio::convertVolume(m_volumeSlider->value() / qreal(100),
+ QAudio::LogarithmicVolumeScale,
+ QAudio::LinearVolumeScale);
+
+ return qRound(linearVolume * 100);
+}
+
+void PlayerControls::setVolume(int volume)
+{
+ qreal logarithmicVolume = QAudio::convertVolume(volume / qreal(100),
+ QAudio::LinearVolumeScale,
+ QAudio::LogarithmicVolumeScale);
+
+ m_volumeSlider->setValue(qRound(logarithmicVolume * 100));
+}
+
+bool PlayerControls::isMuted() const
+{
+ return m_playerMuted;
+}
+
+void PlayerControls::setMuted(bool muted)
+{
+ if (muted != m_playerMuted) {
+ m_playerMuted = muted;
+
+ m_muteButton->setIcon(style()->standardIcon(muted
+ ? QStyle::SP_MediaVolumeMuted
+ : QStyle::SP_MediaVolume));
+ }
+}
+
+void PlayerControls::playClicked()
+{
+ switch (m_playerState) {
+ case QMediaPlayer::StoppedState:
+ case QMediaPlayer::PausedState:
+ emit play();
+ break;
+ case QMediaPlayer::PlayingState:
+ emit pause();
+ break;
+ }
+}
+
+void PlayerControls::muteClicked()
+{
+ emit changeMuting(!m_playerMuted);
+}
+
+qreal PlayerControls::playbackRate() const
+{
+ return m_rateBox->itemData(m_rateBox->currentIndex()).toDouble();
+}
+
+void PlayerControls::setPlaybackRate(float rate)
+{
+ for (int i = 0; i < m_rateBox->count(); ++i) {
+ if (qFuzzyCompare(rate, float(m_rateBox->itemData(i).toDouble()))) {
+ m_rateBox->setCurrentIndex(i);
+ return;
+ }
+ }
+
+ m_rateBox->addItem(QString("%1x").arg(rate), QVariant(rate));
+ m_rateBox->setCurrentIndex(m_rateBox->count() - 1);
+}
+
+void PlayerControls::updateRate()
+{
+ emit changeRate(playbackRate());
+}
+
+void PlayerControls::onVolumeSliderValueChanged()
+{
+ emit changeVolume(volume());
+}
diff --git a/src/widgets/wowplayercontrols.h b/src/widgets/wowplayercontrols.h
new file mode 100644
index 0000000..11114fc
--- /dev/null
+++ b/src/widgets/wowplayercontrols.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** 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 PLAYERCONTROLS_H
+#define PLAYERCONTROLS_H
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+class QAbstractButton;
+class QAbstractSlider;
+class QComboBox;
+QT_END_NAMESPACE
+
+class PlayerControls : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit PlayerControls(QWidget *parent = nullptr);
+
+ QMediaPlayer::State state() const;
+ int volume() const;
+ bool isMuted() const;
+ qreal playbackRate() const;
+
+public slots:
+ void setState(QMediaPlayer::State state);
+ void setVolume(int volume);
+ void setMuted(bool muted);
+ void setPlaybackRate(float rate);
+
+signals:
+ void play();
+ void pause();
+ void stop();
+ void next();
+ void previous();
+ void changeVolume(int volume);
+ void changeMuting(bool muting);
+ void changeRate(qreal rate);
+
+private slots:
+ void playClicked();
+ void muteClicked();
+ void updateRate();
+ void onVolumeSliderValueChanged();
+
+private:
+ QMediaPlayer::State m_playerState = QMediaPlayer::StoppedState;
+ bool m_playerMuted = false;
+ QAbstractButton *m_playButton = nullptr;
+ QAbstractButton *m_stopButton = nullptr;
+ QAbstractButton *m_nextButton = nullptr;
+ QAbstractButton *m_previousButton = nullptr;
+ QAbstractButton *m_muteButton = nullptr;
+ QAbstractSlider *m_volumeSlider = nullptr;
+ QComboBox *m_rateBox = nullptr;
+};
+
+#endif // PLAYERCONTROLS_H
diff --git a/src/widgets/wowplayerwidget.cpp b/src/widgets/wowplayerwidget.cpp
new file mode 100644
index 0000000..ade37c4
--- /dev/null
+++ b/src/widgets/wowplayerwidget.cpp
@@ -0,0 +1,568 @@
+//
+// Created by rapeafed on 2021.
+//
+
+// You may need to build the project (run Qt uic code generator) to get "ui_WowPlayerWidget.h" resolved
+
+#include
+#include "wowplayercontrols.h"
+
+#include "wowvideowidget.h"
+#include "wowplaylistmodel.h"
+//#include "wowhistogramwidget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+//#include
+#include "wowplayerwidget.h"
+#include "ui_wowplayerwidget.h"
+
+
+
+
+WowPlayerWidget::WowPlayerWidget(QWidget *parent) :
+ QWidget(parent), ui(new Ui::WowPlayerWidget) {
+
+// d = new Private;
+ // d->mediaPlayer = new QMediaPlayer(this, QMediaPlayer::StreamPlayback);
+ //d->networkAccessManager = new QNetworkAccessManager(this);
+// QMediaPlayer myAudio;
+ ui->setupUi(this);
+ //QMediaPlayer *player = new QMediaPlayer();
+
+
+//! [create-objs]
+ //QMediaPlayer player = new QMediaPlayer;
+ //QMediaPlayer *player = new QMediaPlayer();
+ //m_player = new QMediaPlayer;
+ //QMediaPlayer *player = new QMediaPlayer;
+ m_player = new QMediaPlayer(this);
+ m_player->setAudioRole(QAudio::VideoRole);
+ qInfo() << "Supported audio roles:";
+ for (QAudio::Role role : m_player->supportedAudioRoles())
+ qInfo() << " " << role;
+ // owned by PlaylistModel
+ m_playlist = new QMediaPlaylist();
+ m_player->setPlaylist(m_playlist);
+//! [create-objs]
+
+ connect(m_player, &QMediaPlayer::durationChanged, this, &WowPlayerWidget::durationChanged);
+ connect(m_player, &QMediaPlayer::positionChanged, this, &WowPlayerWidget::positionChanged);
+ connect(m_player, QOverload<>::of(&QMediaPlayer::metaDataChanged), this, &WowPlayerWidget::metaDataChanged);
+ connect(m_playlist, &QMediaPlaylist::currentIndexChanged, this, &WowPlayerWidget::playlistPositionChanged);
+ connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &WowPlayerWidget::statusChanged);
+ connect(m_player, &QMediaPlayer::bufferStatusChanged, this, &WowPlayerWidget::bufferingProgress);
+ connect(m_player, &QMediaPlayer::videoAvailableChanged, this, &WowPlayerWidget::videoAvailableChanged);
+ connect(m_player, QOverload::of(&QMediaPlayer::error), this, &WowPlayerWidget::displayErrorMessage);
+ connect(m_player, &QMediaPlayer::stateChanged, this, &WowPlayerWidget::stateChanged);
+
+ // QHBoxLayout *wowPlayerLayout = new QHBoxLayout(this);;
+//! [2]
+ m_videoWidget = new VideoWidget(ui->verticalWidget);
+ m_player->setVideoOutput(m_videoWidget);
+
+ m_playlistModel = new PlaylistModel(this);
+ m_playlistModel->setPlaylist(m_playlist);
+//! [2]
+
+ m_playlistView = new QListView(this);
+ m_playlistView->setModel(m_playlistModel);
+ m_playlistView->setCurrentIndex(m_playlistModel->index(m_playlist->currentIndex(), 0));
+
+ connect(m_playlistView, &QAbstractItemView::activated, this, &WowPlayerWidget::jump);
+
+ m_slider = new QSlider(Qt::Horizontal, this);
+ m_slider->setRange(0, m_player->duration() / 1000);
+
+ m_labelDuration = new QLabel(this);
+ connect(m_slider, &QSlider::sliderMoved, this, &WowPlayerWidget::seek);
+ //connect(m_slider, &QSlider::, this, &WowPlayerWidget::seek);
+ //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);
+
+ //m_videoProbe = new QVideoProbe(this);
+ //connect(m_videoProbe, &QVideoProbe::videoFrameProbed, m_videoHistogram, &HistogramWidget::processFrame);
+ //m_videoProbe->setSource(m_player);
+
+ //m_audioProbe = new QAudioProbe(this);
+ //connect(m_audioProbe, &QAudioProbe::audioBufferProbed, m_audioHistogram, &HistogramWidget::processBuffer);
+ //m_audioProbe->setSource(m_player);
+
+ QPushButton *playWowIRCRadioButton = new QPushButton(tr("Play IRC!Radio"), this);
+ QPushButton *taesteWowButton = new QPushButton(tr("Tæste Wow"), ui->verticalWidget);
+ QPushButton *tuneButton = new QPushButton(tr("!Tune"), ui->verticalWidget);
+ QPushButton *openButton = new QPushButton(tr("Open"), this);
+
+
+ connect(playWowIRCRadioButton, &QPushButton::clicked, this, &WowPlayerWidget::playWowIRCRadio);
+ connect(taesteWowButton, &QPushButton::clicked, this, &WowPlayerWidget::taesteWow);
+ connect(tuneButton, &QPushButton::clicked, this, &WowPlayerWidget::tune);
+ connect(openButton, &QPushButton::clicked, this, &WowPlayerWidget::open);
+
+
+ PlayerControls *controls = new PlayerControls(this);
+ controls->setState(m_player->state());
+ controls->setVolume(m_player->volume());
+ controls->setMuted(controls->isMuted());
+
+ connect(controls, &PlayerControls::play, m_player, &QMediaPlayer::play);
+ connect(controls, &PlayerControls::pause, m_player, &QMediaPlayer::pause);
+ connect(controls, &PlayerControls::stop, m_player, &QMediaPlayer::stop);
+ connect(controls, &PlayerControls::next, m_playlist, &QMediaPlaylist::next);
+ connect(controls, &PlayerControls::previous, this, &WowPlayerWidget::previousClicked);
+ connect(controls, &PlayerControls::changeVolume, m_player, &QMediaPlayer::setVolume);
+ connect(controls, &PlayerControls::changeMuting, m_player, &QMediaPlayer::setMuted);
+ connect(controls, &PlayerControls::changeRate, m_player, &QMediaPlayer::setPlaybackRate);
+ connect(controls, &PlayerControls::stop, m_videoWidget, QOverload<>::of(&QVideoWidget::update));
+
+ connect(m_player, &QMediaPlayer::stateChanged, controls, &PlayerControls::setState);
+ connect(m_player, &QMediaPlayer::volumeChanged, controls, &PlayerControls::setVolume);
+ connect(m_player, &QMediaPlayer::mutedChanged, controls, &PlayerControls::setMuted);
+
+ m_fullScreenButton = new QPushButton(tr("FullScreen"), this);
+ m_fullScreenButton->setCheckable(true);
+
+ //m_colorButton = new QPushButton(tr("Color Options..."), this);
+ //m_colorButton->setEnabled(false);
+ //connect(m_colorButton, &QPushButton::clicked, this, &WowPlayerWidget::showColorDialog);
+
+ QBoxLayout *infoPanelLayout = new QVBoxLayout;
+ m_statusBar = new QPlainTextEdit;
+ m_statusLabel = new QLabel;
+ m_statusLabel->setMaximumHeight(30);
+
+ //m_TextBrowser = new QTextBrowser;
+ m_statusBar->setMaximumHeight(66);
+ //m_statusBar->sizeHint();
+ m_statusBar->setPlainText("More fun with Wowmero IRC!Radio\nIRC 140.211.166.64:6667\n#wownero-music");
+ m_statusLabel->setText("WowPlayer ready");
+ QUrl *history = new QUrl("https://radio.wownero.com/history.txt");
+
+ //m_TextBrowser->setSource(QUrl("https://radio.wownero.com/history.txt"));
+ //m_TextBrowser->reload();
+ //m_TextBrowser->setPlainText(history->toString());
+ //m_TextBrowser->append(" History ");
+ infoPanelLayout->addWidget(m_statusLabel);//, 2);
+ infoPanelLayout->addWidget(m_statusBar);//, 2);
+ //infoPlanelLayout->addWidget(m_TextBrowser);
+ //infoPlanelLayout->addWidget(playWowIRCRadioButton);
+
+ QBoxLayout *playerButtonsLayout = new QHBoxLayout;
+ playerButtonsLayout->addWidget(playWowIRCRadioButton);
+ playerButtonsLayout->addWidget(taesteWowButton);
+ playerButtonsLayout->addWidget(tuneButton);
+ playerButtonsLayout->addWidget(openButton);
+
+ QBoxLayout *displayLayout = new QHBoxLayout;
+ displayLayout->addWidget(m_videoWidget, 2);
+ displayLayout->addWidget(m_playlistView);
+
+ QBoxLayout *controlLayout = new QHBoxLayout;
+ controlLayout->setContentsMargins(0, 0, 0, 0);
+ controlLayout->addLayout(playerButtonsLayout);
+ controlLayout->addStretch(1);
+ controlLayout->addWidget(controls);
+ controlLayout->addStretch(1);
+ controlLayout->addWidget(m_fullScreenButton);
+ //controlLayout->addWidget(m_colorButton);
+
+ QBoxLayout *layout = new QVBoxLayout;
+
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->addWidget(m_slider);
+ hLayout->addWidget(m_labelDuration);
+
+ layout->addLayout(infoPanelLayout);
+ layout->addLayout(hLayout);
+ layout->addLayout(controlLayout);
+ layout->addLayout(displayLayout);
+ //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);
+
+ if (!isPlayerAvailable()) {
+ QMessageBox::warning(this, tr("Service not available"),
+ tr("The QMediaPlayer object does not have a valid service.\n"\
+ "Please check the media service plugins are installed."));
+
+ controls->setEnabled(false);
+ m_playlistView->setEnabled(false);
+ openButton->setEnabled(false);
+ m_colorButton->setEnabled(false);
+ m_fullScreenButton->setEnabled(false);
+ }
+
+ metaDataChanged();
+
+}
+
+WowPlayerWidget::~WowPlayerWidget() {
+ delete ui;
+}
+
+bool WowPlayerWidget::isPlayerAvailable() const
+{
+ return m_player->isAvailable();
+}
+
+void WowPlayerWidget::playWowIRCRadio()
+{
+ //PrepareSuchWowSlideShow();
+
+/*
+ QImage img = QImage("qrc:///assets/images/wowlet.png").convertToFormat(QImage::Format_ARGB32);
+ QVideoSurfaceFormat format(img.size(), QVideoFrame::Format_ARGB32);
+ //QVideoWidget *videoWidget = new QVideoWidget;
+ m_videoWidget->videoSurface()->start(format);
+ m_videoWidget->videoSurface()->present(img);
+ //m_videoWidget->show();
+*/
+
+ m_playlist->clear();
+ m_playlist->addMedia(QUrl("https://radio.wownero.com/wow.ogg"));
+ m_player->play();
+}
+
+void WowPlayerWidget::taesteWow()
+{
+ setStatusInfo(tr("Wow"));
+ m_playlist->clear();
+ m_playlist->addMedia(QUrl("qrc:///assets/videos/do_you_even_wow_special_friend.mp4"));
+ m_playlist->addMedia(QUrl("https://radio.wownero.com/wow.ogg"));
+ m_player->play();
+
+}
+
+void WowPlayerWidget::tune()
+{
+ setStatusInfo(tr("Undefined reference HellGate::TrollConnect(me, like, wownero, music)"));
+}
+
+void WowPlayerWidget::open()
+{
+
+ QFileDialog fileDialog(this);
+ fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
+ fileDialog.setWindowTitle(tr("Open Files"));
+ QStringList supportedMimeTypes = m_player->supportedMimeTypes();
+ if (!supportedMimeTypes.isEmpty()) {
+ supportedMimeTypes.append("audio/x-m3u"); // MP3 playlists
+ fileDialog.setMimeTypeFilters(supportedMimeTypes);
+ }
+ fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MoviesLocation).value(0, QDir::homePath()));
+ if (fileDialog.exec() == QDialog::Accepted)
+ addToPlaylist(fileDialog.selectedUrls());
+ //m_playlist->load(QUrl("https://radio.wownero.com/wow.ogg"));
+ //m_player->setMedia(QUrl("https://radio.wownero.com/wow.ogg"));
+
+ /*m_player->setMedia(QUrl("gst-pipeline: appsrc blocksize=4294967295 ! \
+ video/x-raw,format=BGRx,framerate=30/1,width=200,height=147 ! \
+ coloreffects preset=heat ! videoconvert ! video/x-raw,format=I420 ! jpegenc ! rtpjpegpay ! \
+ udpsink host=127.0.0.1 port=5000"));*/
+ // setMedia(QUrl::fromLocalFile("~/ Music/coolsong.mp3"));
+//playbin uri=file:///projects/demo.ogv
+
+}
+
+static bool isPlaylist(const QUrl &url) // Check for ".m3u" playlists.
+{
+ if (!url.isLocalFile())
+ return false;
+ const QFileInfo fileInfo(url.toLocalFile());
+ return fileInfo.exists() && !fileInfo.suffix().compare(QLatin1String("m3u"), Qt::CaseInsensitive);
+}
+
+void WowPlayerWidget::addToPlaylist(const QList &urls)
+{
+ for (auto &url: urls) {
+ if (isPlaylist(url))
+ m_playlist->load(url);
+ else
+ m_playlist->addMedia(url);
+ }
+}
+
+void WowPlayerWidget::setCustomAudioRole(const QString &role)
+{
+ m_player->setCustomAudioRole(role);
+}
+
+void WowPlayerWidget::durationChanged(qint64 duration)
+{
+ m_duration = duration / 1000;
+ m_slider->setMaximum(m_duration);
+}
+
+void WowPlayerWidget::positionChanged(qint64 progress)
+{
+ if (!m_slider->isSliderDown())
+ m_slider->setValue(progress / 1000);
+
+ updateDurationInfo(progress / 1000);
+}
+
+void WowPlayerWidget::metaDataChanged()
+{
+ if (m_player->isMetaDataAvailable()) {
+ setTrackInfo(QString("%1 - %2")
+ .arg(m_player->metaData(QMediaMetaData::AlbumArtist).toString())
+ .arg(m_player->metaData(QMediaMetaData::Title).toString()));
+
+ if (m_coverLabel) {
+ QUrl url = m_player->metaData(QMediaMetaData::CoverArtUrlLarge).value();
+
+ m_coverLabel->setPixmap(!url.isEmpty()
+ ? QPixmap(url.toString())
+ : QPixmap());
+ }
+ }
+}
+
+void WowPlayerWidget::previousClicked()
+{
+ // Go to previous track if we are within the first 5 seconds of playback
+ // Otherwise, seek to the beginning.
+ if (m_player->position() <= 5000)
+ m_playlist->previous();
+ else
+ m_player->setPosition(0);
+}
+
+void WowPlayerWidget::jump(const QModelIndex &index)
+{
+ if (index.isValid()) {
+ m_playlist->setCurrentIndex(index.row());
+ m_player->play();
+ }
+}
+
+void WowPlayerWidget::playlistPositionChanged(int currentItem)
+{
+ //clearHistogram();
+ m_playlistView->setCurrentIndex(m_playlistModel->index(currentItem, 0));
+}
+
+void WowPlayerWidget::seek(int seconds)
+{
+ m_player->setPosition(seconds * 1000);
+}
+
+void WowPlayerWidget::statusChanged(QMediaPlayer::MediaStatus status)
+{
+ handleCursor(status);
+
+ // handle status message
+ switch (status) {
+ case QMediaPlayer::UnknownMediaStatus:
+ case QMediaPlayer::NoMedia:
+ case QMediaPlayer::LoadedMedia:
+ 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("Stalled %1%").arg(m_player->bufferStatus()));
+ break;
+ case QMediaPlayer::EndOfMedia:
+ QApplication::alert(this);
+ break;
+ case QMediaPlayer::InvalidMedia:
+ displayErrorMessage();
+ break;
+ }
+}
+
+void WowPlayerWidget::stateChanged(QMediaPlayer::State state)
+{
+ //if (state == QMediaPlayer::StoppedState)
+ // clearHistogram();
+}
+
+void WowPlayerWidget::handleCursor(QMediaPlayer::MediaStatus status)
+{
+#ifndef QT_NO_CURSOR
+ if (status == QMediaPlayer::LoadingMedia ||
+ status == QMediaPlayer::BufferingMedia ||
+ status == QMediaPlayer::StalledMedia)
+ setCursor(QCursor(Qt::BusyCursor));
+ else
+ unsetCursor();
+#endif
+}
+
+void WowPlayerWidget::bufferingProgress(int progress)
+{
+ if (m_player->mediaStatus() == QMediaPlayer::StalledMedia)
+ setStatusInfo(tr("Stalled %1%").arg(progress));
+ else
+ setStatusInfo(tr("Buffering %1%").arg(progress));
+}
+
+void WowPlayerWidget::videoAvailableChanged(bool available)
+{
+ if (!available) {
+ disconnect(m_fullScreenButton, &QPushButton::clicked, m_videoWidget, &QVideoWidget::setFullScreen);
+ disconnect(m_videoWidget, &QVideoWidget::fullScreenChanged, m_fullScreenButton, &QPushButton::setChecked);
+ m_videoWidget->setFullScreen(false);
+ } else {
+ connect(m_fullScreenButton, &QPushButton::clicked, m_videoWidget, &QVideoWidget::setFullScreen);
+ connect(m_videoWidget, &QVideoWidget::fullScreenChanged, m_fullScreenButton, &QPushButton::setChecked);
+
+ if (m_fullScreenButton->isChecked())
+ m_videoWidget->setFullScreen(true);
+ }
+ //m_colorButton->setEnabled(available);
+}
+
+void WowPlayerWidget::setTrackInfo(const QString &info)
+{
+ m_trackInfo = info;
+ //m_statusBar->setPlainText(m_trackInfo);
+// m_statusBar->setPlainText("Wownero IRC!Radio"+m_trackInfo);
+ // m_statusLabel->setText(m_statusInfo);
+
+ if (m_statusBar) {
+ //if (!m_trackInfo.isEmpty()) m_statusBar->setPlainText("Wownero +++IRC!Radio"+m_trackInfo); else m_statusBar->setPlainText("");
+ m_statusBar->setPlainText(m_trackInfo);
+ m_statusLabel->setText(m_statusInfo);
+ } else {
+ if (!m_statusInfo.isEmpty())
+ m_statusBar->setPlainText(QString("%1 | %2").arg(m_trackInfo).arg(m_statusInfo));
+ else
+ m_statusBar->setPlainText(m_trackInfo);
+ }
+}
+
+void WowPlayerWidget::setStatusInfo(const QString &info)
+{
+ m_statusInfo = info;
+ //m_statusBar->setPlainText(m_trackInfo);
+ //QFile *radioHistoryFile = new QFile("https://radio.wownero.com/history.txt");
+ //radioHistoryFile->open(QIODevice::ReadOnly);
+ //QString content = QString::fromUtf8(radioHistoryFile->readAll());
+ //content+="test";
+// radioHistoryFile->close();
+ //m_TextBrowser->setSource(QUrl("https://radio.wownero.com/history.txt"));
+ //m_TextBrowser->reload();
+ if (!m_trackInfo.isEmpty()) m_statusBar->setPlainText("Wownero IRC!Radio"+m_trackInfo); else m_statusBar->setPlainText("");
+// m_statusBar->setPlainText("Wownero IRC!Radio"+m_trackInfo);
+ m_statusLabel->setText(m_statusInfo);
+/* 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 WowPlayerWidget::displayErrorMessage()
+{
+ setStatusInfo(m_player->errorString());
+}
+
+void WowPlayerWidget::updateDurationInfo(qint64 currentInfo)
+{
+ QString tStr;
+ if (currentInfo || m_duration) {
+ QTime currentTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60,
+ currentInfo % 60, (currentInfo * 1000) % 1000);
+ QTime totalTime((m_duration / 3600) % 60, (m_duration / 60) % 60,
+ m_duration % 60, (m_duration * 1000) % 1000);
+ QString format = "mm:ss";
+ if (m_duration > 3600)
+ format = "hh:mm:ss";
+ tStr = currentTime.toString(format) + " / " + totalTime.toString(format);
+ }
+ m_labelDuration->setText(tStr);
+}
+
+void WowPlayerWidget::showColorDialog()
+{
+ if (!m_colorDialog) {
+ QSlider *brightnessSlider = new QSlider(Qt::Horizontal);
+ brightnessSlider->setRange(-100, 100);
+ brightnessSlider->setValue(m_videoWidget->brightness());
+ connect(brightnessSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setBrightness);
+ connect(m_videoWidget, &QVideoWidget::brightnessChanged, brightnessSlider, &QSlider::setValue);
+
+ QSlider *contrastSlider = new QSlider(Qt::Horizontal);
+ contrastSlider->setRange(-100, 100);
+ contrastSlider->setValue(m_videoWidget->contrast());
+ connect(contrastSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setContrast);
+ connect(m_videoWidget, &QVideoWidget::contrastChanged, contrastSlider, &QSlider::setValue);
+
+ QSlider *hueSlider = new QSlider(Qt::Horizontal);
+ hueSlider->setRange(-100, 100);
+ hueSlider->setValue(m_videoWidget->hue());
+ connect(hueSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setHue);
+ connect(m_videoWidget, &QVideoWidget::hueChanged, hueSlider, &QSlider::setValue);
+
+ QSlider *saturationSlider = new QSlider(Qt::Horizontal);
+ saturationSlider->setRange(-100, 100);
+ saturationSlider->setValue(m_videoWidget->saturation());
+ connect(saturationSlider, &QSlider::sliderMoved, m_videoWidget, &QVideoWidget::setSaturation);
+ connect(m_videoWidget, &QVideoWidget::saturationChanged, saturationSlider, &QSlider::setValue);
+
+ QFormLayout *layout = new QFormLayout;
+ layout->addRow(tr("Brightness"), brightnessSlider);
+ layout->addRow(tr("Contrast"), contrastSlider);
+ layout->addRow(tr("Hue"), hueSlider);
+ layout->addRow(tr("Saturation"), saturationSlider);
+
+ QPushButton *button = new QPushButton(tr("Close"));
+ layout->addRow(button);
+
+ m_colorDialog = new QDialog(this);
+ m_colorDialog->setWindowTitle(tr("Color Options"));
+ m_colorDialog->setLayout(layout);
+
+ connect(button, &QPushButton::clicked, m_colorDialog, &QDialog::close);
+ }
+ m_colorDialog->show();
+}
+
+void WowPlayerWidget::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/src/widgets/wowplayerwidget.h b/src/widgets/wowplayerwidget.h
new file mode 100644
index 0000000..3ae1ce6
--- /dev/null
+++ b/src/widgets/wowplayerwidget.h
@@ -0,0 +1,95 @@
+//
+// Created by rapeafed on 2021.
+//
+
+#ifndef WOWLET_WOWPLAYERWIDGET_H
+#define WOWLET_WOWPLAYERWIDGET_H
+
+#include
+#include
+#include
+#include
+#include
+#include "wowplaylistmodel.h"
+#include "wowplayercontrols.h"
+//#include "wowhistogramwidget.h"
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class WowPlayerWidget; }
+QT_END_NAMESPACE
+
+class WowPlayerWidget : public QWidget {
+Q_OBJECT
+
+public:
+ explicit WowPlayerWidget(QWidget *parent = nullptr);
+
+ ~WowPlayerWidget() override;
+ bool isPlayerAvailable() const;
+
+ void addToPlaylist(const QList &urls);
+ void setCustomAudioRole(const QString &role);
+signals:
+ void fullScreenChanged(bool fullScreen);
+
+private slots:
+ void open();
+ void playWowIRCRadio();
+ void taesteWow();
+ void tune();
+ void durationChanged(qint64 duration);
+ void positionChanged(qint64 progress);
+ void metaDataChanged();
+
+ void previousClicked();
+
+ void seek(int seconds);
+ void jump(const QModelIndex &index);
+ void playlistPositionChanged(int);
+
+ void statusChanged(QMediaPlayer::MediaStatus status);
+ void stateChanged(QMediaPlayer::State state);
+ void bufferingProgress(int progress);
+ void videoAvailableChanged(bool available);
+
+ void displayErrorMessage();
+
+ void showColorDialog();
+
+private:
+ void clearHistogram();
+ void setTrackInfo(const QString &info);
+ void setStatusInfo(const QString &info);
+ void handleCursor(QMediaPlayer::MediaStatus status);
+ void updateDurationInfo(qint64 currentInfo);
+ Ui::WowPlayerWidget *ui;
+
+ QMediaPlayer *m_player = nullptr;
+ QMediaPlaylist *m_playlist = nullptr;
+ QVideoWidget *m_videoWidget = nullptr;
+ QTextBrowser *m_TextBrowser = nullptr;
+ QLabel *m_coverLabel = nullptr;
+ QSlider *m_slider = nullptr;
+ QLabel *m_labelDuration = nullptr;
+ QPushButton *m_fullScreenButton = nullptr;
+ QPushButton *m_colorButton = nullptr;
+ QDialog *m_colorDialog = nullptr;
+ QLabel *m_statusLabel = nullptr;
+ QPlainTextEdit *m_statusBar = nullptr;
+
+ QLabel *m_labelHistogram = nullptr;
+ //HistogramWidget *m_videoHistogram = nullptr;
+ //HistogramWidget *m_audioHistogram = nullptr;
+ QVideoProbe *m_videoProbe = nullptr;
+ QAudioProbe *m_audioProbe = nullptr;
+
+ PlaylistModel *m_playlistModel = nullptr;
+ QAbstractItemView *m_playlistView = nullptr;
+ QString m_trackInfo;
+ QString m_statusInfo;
+ qint64 m_duration;
+
+};
+
+
+#endif //WOWLET_WOWPLAYERWIDGET_H
diff --git a/src/widgets/wowplayerwidget.ui b/src/widgets/wowplayerwidget.ui
new file mode 100644
index 0000000..1e9f89b
--- /dev/null
+++ b/src/widgets/wowplayerwidget.ui
@@ -0,0 +1,36 @@
+
+
+ WowPlayerWidget
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ WowPlayerWidget
+
+
+
+
+ 0
+ 160
+ 401
+ 31
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
diff --git a/src/widgets/wowplaylistmodel.cpp b/src/widgets/wowplaylistmodel.cpp
new file mode 100644
index 0000000..ed484b1
--- /dev/null
+++ b/src/widgets/wowplaylistmodel.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** 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 "wowplaylistmodel.h"
+
+#include
+#include
+#include
+
+PlaylistModel::PlaylistModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+}
+
+PlaylistModel::~PlaylistModel()
+{
+}
+
+int PlaylistModel::rowCount(const QModelIndex &parent) const
+{
+ return m_playlist && !parent.isValid() ? m_playlist->mediaCount() : 0;
+}
+
+int PlaylistModel::columnCount(const QModelIndex &parent) const
+{
+ return !parent.isValid() ? ColumnCount : 0;
+}
+
+QModelIndex PlaylistModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return m_playlist && !parent.isValid()
+ && row >= 0 && row < m_playlist->mediaCount()
+ && column >= 0 && column < ColumnCount
+ ? createIndex(row, column)
+ : QModelIndex();
+}
+
+QModelIndex PlaylistModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child);
+
+ return QModelIndex();
+}
+
+QVariant PlaylistModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && role == Qt::DisplayRole) {
+ QVariant value = m_data[index];
+ if (!value.isValid() && index.column() == Title) {
+ QUrl location = m_playlist->media(index.row()).request().url();
+ return QFileInfo(location.path()).fileName();
+ }
+
+ return value;
+ }
+ return QVariant();
+}
+
+QMediaPlaylist *PlaylistModel::playlist() const
+{
+ return m_playlist.data();
+}
+
+void PlaylistModel::setPlaylist(QMediaPlaylist *playlist)
+{
+ if (m_playlist) {
+ disconnect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeInserted, this, &PlaylistModel::beginInsertItems);
+ disconnect(m_playlist.data(), &QMediaPlaylist::mediaInserted, this, &PlaylistModel::endInsertItems);
+ disconnect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeRemoved, this, &PlaylistModel::beginRemoveItems);
+ disconnect(m_playlist.data(), &QMediaPlaylist::mediaRemoved, this, &PlaylistModel::endRemoveItems);
+ disconnect(m_playlist.data(), &QMediaPlaylist::mediaChanged, this, &PlaylistModel::changeItems);
+ }
+
+ beginResetModel();
+ m_playlist.reset(playlist);
+
+ if (m_playlist) {
+ connect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeInserted, this, &PlaylistModel::beginInsertItems);
+ connect(m_playlist.data(), &QMediaPlaylist::mediaInserted, this, &PlaylistModel::endInsertItems);
+ connect(m_playlist.data(), &QMediaPlaylist::mediaAboutToBeRemoved, this, &PlaylistModel::beginRemoveItems);
+ connect(m_playlist.data(), &QMediaPlaylist::mediaRemoved, this, &PlaylistModel::endRemoveItems);
+ connect(m_playlist.data(), &QMediaPlaylist::mediaChanged, this, &PlaylistModel::changeItems);
+ }
+
+ endResetModel();
+}
+
+bool PlaylistModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ Q_UNUSED(role);
+ m_data[index] = value;
+ emit dataChanged(index, index);
+ return true;
+}
+
+void PlaylistModel::beginInsertItems(int start, int end)
+{
+ m_data.clear();
+ beginInsertRows(QModelIndex(), start, end);
+}
+
+void PlaylistModel::endInsertItems()
+{
+ endInsertRows();
+}
+
+void PlaylistModel::beginRemoveItems(int start, int end)
+{
+ m_data.clear();
+ beginRemoveRows(QModelIndex(), start, end);
+}
+
+void PlaylistModel::endRemoveItems()
+{
+ endInsertRows();
+}
+
+void PlaylistModel::changeItems(int start, int end)
+{
+ m_data.clear();
+ emit dataChanged(index(start,0), index(end,ColumnCount));
+}
diff --git a/src/widgets/wowplaylistmodel.h b/src/widgets/wowplaylistmodel.h
new file mode 100644
index 0000000..28cc835
--- /dev/null
+++ b/src/widgets/wowplaylistmodel.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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 PLAYLISTMODEL_H
+#define PLAYLISTMODEL_H
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+class QMediaPlaylist;
+QT_END_NAMESPACE
+
+class PlaylistModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ enum Column
+ {
+ Title = 0,
+ ColumnCount
+ };
+
+ explicit PlaylistModel(QObject *parent = nullptr);
+ ~PlaylistModel();
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex &child) const override;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ QMediaPlaylist *playlist() const;
+ void setPlaylist(QMediaPlaylist *playlist);
+
+ bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole) override;
+
+private slots:
+ void beginInsertItems(int start, int end);
+ void endInsertItems();
+ void beginRemoveItems(int start, int end);
+ void endRemoveItems();
+ void changeItems(int start, int end);
+
+private:
+ QScopedPointer m_playlist;
+ QMap m_data;
+};
+
+#endif // PLAYLISTMODEL_H
diff --git a/src/widgets/wowvideowidget.cpp b/src/widgets/wowvideowidget.cpp
new file mode 100644
index 0000000..3bb52dd
--- /dev/null
+++ b/src/widgets/wowvideowidget.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 "wowvideowidget.h"
+
+#include
+#include
+
+VideoWidget::VideoWidget(QWidget *parent)
+ : QVideoWidget(parent)
+{
+ setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+
+ QPalette p = palette();
+ p.setColor(QPalette::Window, Qt::black);
+ setPalette(p);
+
+ setAttribute(Qt::WA_OpaquePaintEvent);
+}
+
+void VideoWidget::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Escape && isFullScreen()) {
+ setFullScreen(false);
+ event->accept();
+ } else if (event->key() == Qt::Key_Enter && event->modifiers() & Qt::Key_Alt) {
+ setFullScreen(!isFullScreen());
+ event->accept();
+ } else {
+ QVideoWidget::keyPressEvent(event);
+ }
+}
+
+void VideoWidget::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ setFullScreen(!isFullScreen());
+ event->accept();
+}
+
+void VideoWidget::mousePressEvent(QMouseEvent *event)
+{
+ QVideoWidget::mousePressEvent(event);
+}
+
diff --git a/src/widgets/wowvideowidget.h b/src/widgets/wowvideowidget.h
new file mode 100644
index 0000000..8152d6c
--- /dev/null
+++ b/src/widgets/wowvideowidget.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 VIDEOWIDGET_H
+#define VIDEOWIDGET_H
+
+#include
+
+class VideoWidget : public QVideoWidget
+{
+ Q_OBJECT
+
+public:
+ explicit VideoWidget(QWidget *parent = nullptr);
+
+protected:
+ void keyPressEvent(QKeyEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+};
+
+#endif // VIDEOWIDGET_H