Compare commits

...

8 Commits

7
.gitmodules vendored

@ -1,10 +1,9 @@
[submodule "contrib/KDMacTouchBar"] [submodule "contrib/KDMacTouchBar"]
path = contrib/KDMacTouchBar path = contrib/KDMacTouchBar
url = https://github.com/KDAB/KDMacTouchBar.git url = https://github.com/KDAB/KDMacTouchBar.git
[submodule "monero"]
path = monero
url = https://git.wownero.com/wownero/wownero
branch = wowlet
[submodule "contrib/quirc"] [submodule "contrib/quirc"]
path = contrib/quirc path = contrib/quirc
url = https://github.com/dlbeer/quirc.git url = https://github.com/dlbeer/quirc.git
[submodule "wownero"]
path = wownero
url = https://git.wownero.com/wownero/wownero.git

@ -4,13 +4,13 @@ project(wowlet)
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}") message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
set(VERSION_MAJOR "2") set(VERSION_MAJOR "3")
set(VERSION_MINOR "1") set(VERSION_MINOR "0")
set(VERSION_REVISION "0") set(VERSION_REVISION "0")
set(VERSION "beta-3") set(VERSION "beta-4")
option(FETCH_DEPS "Download dependencies if they are not found" ON) option(FETCH_DEPS "Download dependencies if they are not found" ON)
option(XMRIG "Include XMRig module" ON) option(XMRIG "Include XMRig module")
option(OPENVR "Include OpenVR support") option(OPENVR "Include OpenVR support")
option(QML "Include QtQuick (QML)") option(QML "Include QtQuick (QML)")
option(ANDROID "Android deployment") option(ANDROID "Android deployment")
@ -57,7 +57,7 @@ if(STATIC)
# manually set the unbound submodule the right commit that has the fix. # manually set the unbound submodule the right commit that has the fix.
# This only works with -DMANUAL_SUBMODULES=1 # This only works with -DMANUAL_SUBMODULES=1
message(STATUS "applying unbound static build fix contrib/unbound_static.patch") message(STATUS "applying unbound static build fix contrib/unbound_static.patch")
execute_process(COMMAND bash -c "git -C ${CMAKE_SOURCE_DIR}/monero/external/unbound apply ${CMAKE_SOURCE_DIR}/contrib/unbound_static.patch") execute_process(COMMAND bash -c "git -C ${CMAKE_SOURCE_DIR}/wownero/external/unbound apply ${CMAKE_SOURCE_DIR}/contrib/unbound_static.patch")
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON) set(Boost_USE_STATIC_RUNTIME ON)
@ -90,21 +90,19 @@ function (add_linker_flag_if_supported flag var)
endfunction() endfunction()
find_package(Git) find_package(Git)
if(GIT_FOUND) #if(GIT_FOUND)
message(STATUS "Initializing submodules") # message(STATUS "Initializing submodules")
execute_process(COMMAND git "submodule" "update" "--init" "--recursive") # execute_process(COMMAND git "submodule" "update" "--init" "--recursive")
execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/monero OUTPUT_VARIABLE _WOWNERO_HEAD OUTPUT_STRIP_TRAILING_WHITESPACE) # execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero OUTPUT_VARIABLE _WOWNERO_HEAD OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT _WOWNERO_HEAD STREQUAL WOWNERO_HEAD) # if(NOT _WOWNERO_HEAD STREQUAL WOWNERO_HEAD)
message(FATAL_ERROR "[submodule] Monero HEAD was at ${_WOWNERO_HEAD} but should be at ${WOWNERO_HEAD}") # message(FATAL_ERROR "[submodule] Wownero HEAD was at ${_WOWNERO_HEAD} but should be at ${WOWNERO_HEAD}")
else() # else()
message(STATUS "[submodule] Wownero HEAD @ ${WOWNERO_HEAD}") # message(STATUS "[submodule] Wownero HEAD @ ${WOWNERO_HEAD}")
endif() # endif()
endif() #endif()
add_subdirectory(monero) add_subdirectory(wownero)
set_property(TARGET wallet_merged PROPERTY FOLDER "monero") get_directory_property(ARCH_WIDTH DIRECTORY "wownero" DEFINITION ARCH_WIDTH)
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
include(VersionMonero) include(VersionMonero)

@ -262,7 +262,7 @@ RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
make -j$THREADS install && \ make -j$THREADS install && \
rm -rf $(pwd) rm -rf $(pwd)
RUN wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \ RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.gz && \
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \ echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
tar -xzf boost_1_73_0.tar.gz && \ tar -xzf boost_1_73_0.tar.gz && \
rm boost_1_73_0.tar.gz && \ rm boost_1_73_0.tar.gz && \

@ -42,7 +42,7 @@ CMAKEFLAGS = \
$(CMAKEFLAGS_EXTRA) $(CMAKEFLAGS_EXTRA)
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64" release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
release-static: CMAKEFLAGS += -DXMRIG=ON release-static: CMAKEFLAGS += -DXMRIG=OFF
release-static: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF) release-static: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
release-static: CMAKEFLAGS += -DREPRODUCIBLE=$(or ${SOURCE_DATE_EPOCH},OFF) release-static: CMAKEFLAGS += -DREPRODUCIBLE=$(or ${SOURCE_DATE_EPOCH},OFF)

@ -35,7 +35,7 @@ if(RET)
message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.") message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.")
set(VERSIONTAG "unknown") set(VERSIONTAG "unknown")
set(VERSION_IS_RELEASE "false") set(VERSION_IS_RELEASE "false")
configure_file("monero/src/version.cpp.in" "${TO}") configure_file("wownero/src/version.cpp.in" "${TO}")
else() else()
string(SUBSTRING ${COMMIT} 0 9 COMMIT) string(SUBSTRING ${COMMIT} 0 9 COMMIT)
message(STATUS "You are currently on commit ${COMMIT}") message(STATUS "You are currently on commit ${COMMIT}")
@ -61,5 +61,5 @@ else()
set(VERSION_IS_RELEASE "false") set(VERSION_IS_RELEASE "false")
endif() endif()
endif() endif()
configure_file("monero/src/version.cpp.in" "${TO}") configure_file("wownero/src/version.cpp.in" "${TO}")
endif() endif()

@ -4,7 +4,7 @@
find_package(Git QUIET) find_package(Git QUIET)
# Check what commit we're on # Check what commit we're on
execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --short=9 HEAD RESULT_VARIABLE RET OUTPUT_VARIABLE COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --short=9 HEAD RESULT_VARIABLE RET OUTPUT_VARIABLE COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/monero) WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero)
if(RET) if(RET)
# Something went wrong, set the version tag to -unknown # Something went wrong, set the version tag to -unknown
@ -37,7 +37,7 @@ endif()
# Check latest tagged release # Check latest tagged release
execute_process(COMMAND "${GIT_EXECUTABLE}" describe --abbrev=0 RESULT_VARIABLE RET OUTPUT_VARIABLE TAG OUTPUT_STRIP_TRAILING_WHITESPACE execute_process(COMMAND "${GIT_EXECUTABLE}" describe --abbrev=0 RESULT_VARIABLE RET OUTPUT_VARIABLE TAG OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/monero) WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero)
if(RET) if(RET)
message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.") message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")

@ -96,13 +96,28 @@ Clone the repository.
```bash ```bash
git clone --recursive https://git.wownero.com/wowlet/wowlet.git git clone --recursive https://git.wownero.com/wowlet/wowlet.git
``` ```
Download Qt5.15.1 from here:
https://download.qt.io/archive/qt/5.15/5.15.1/single/
and build Qt 5.15.1:
Get the latest LTS from here: https://www.qt.io/offline-installers and install. Qt build on Mac OS:
Build WOWlet. ```bash
cd ~/Downloads/qt-everywhere-src-5.15.1
./configure -prefix $PWD/qtbase -release -nomake examples -nomake tests -skip qtwebchannel -skip qtpurchasing -skip webengine -skip qtwebview
make -j 4
```
Build WOWlet:
```bash
CMAKE_PREFIX_PATH=/Users/$username/Downloads/qt-everywhere-src-5.15.1/qtbase/ make mac-release
```
Install and start tor service for ticker/forums:
```bash ```bash
CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release brew install tor
brew services start tor
``` ```
The resulting Mac OS application can be found `build/bin/wowlet.app` and will **not** have Tor embedded. The resulting Mac OS application can be found `build/bin/wowlet.app` and will **not** have Tor embedded.

@ -1 +0,0 @@
Subproject commit f611d5c9e32bc62f1735f6571b0bdb95cc020531

@ -40,9 +40,9 @@ file(GLOB SOURCE_FILES
) )
if(QML) 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() 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() endif()
if(OPENVR) if(OPENVR)
@ -136,10 +136,10 @@ file(GLOB_RECURSE SRC_HEADERS *.h)
target_include_directories(wowlet PUBLIC target_include_directories(wowlet PUBLIC
${CMAKE_BINARY_DIR}/src/wowlet_autogen/include ${CMAKE_BINARY_DIR}/src/wowlet_autogen/include
${CMAKE_SOURCE_DIR}/monero/include ${CMAKE_SOURCE_DIR}/wownero/include
${CMAKE_SOURCE_DIR}/monero/src ${CMAKE_SOURCE_DIR}/wownero/src
${CMAKE_SOURCE_DIR}/monero/external/easylogging++ ${CMAKE_SOURCE_DIR}/wownero/external/easylogging++
${CMAKE_SOURCE_DIR}/monero/contrib/epee/include ${CMAKE_SOURCE_DIR}/wownero/contrib/epee/include
${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/daemon ${CMAKE_CURRENT_SOURCE_DIR}/daemon
@ -148,6 +148,7 @@ target_include_directories(wowlet PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_CURRENT_SOURCE_DIR}/utils
${CMAKE_CURRENT_SOURCE_DIR}/tor ${CMAKE_CURRENT_SOURCE_DIR}/tor
${CMAKE_CURRENT_SOURCE_DIR}/qrcode ${CMAKE_CURRENT_SOURCE_DIR}/qrcode
${CMAKE_CURRENT_SOURCE_DIR}/widgets
${X11_INCLUDE_DIR} ${X11_INCLUDE_DIR}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}
@ -158,6 +159,8 @@ target_include_directories(wowlet PUBLIC
${Qt5Svg_INCLUDE_DIRS} ${Qt5Svg_INCLUDE_DIRS}
${Qt5Xml_INCLUDE_DIRS} ${Qt5Xml_INCLUDE_DIRS}
${Qt5WebSockets_INCLUDE_DIRS} ${Qt5WebSockets_INCLUDE_DIRS}
${Qt5Multimedia_INCLUDE_DIRS}
${Qt5MultimediaWidgets_INCLUDE_DIRS}
) )
if(OPENVR) if(OPENVR)
@ -230,6 +233,8 @@ target_compile_definitions(wowlet
${Qt5Svg_DEFINITIONS} ${Qt5Svg_DEFINITIONS}
${Qt5Xml_DEFINITIONS} ${Qt5Xml_DEFINITIONS}
${Qt5WebSockets_DEFINITIONS} ${Qt5WebSockets_DEFINITIONS}
${Qt5Multimedia_DEFINITIONS}
${Qt5MultimediaWidgets_DEFINITIONS}
) )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
@ -251,14 +256,9 @@ endif()
# Link Wownero core libraries # Link Wownero core libraries
target_link_libraries(wowlet PUBLIC target_link_libraries(wowlet PUBLIC
wallet_merged
${LMDB_LIBRARY}
epee epee
${UNBOUND_LIBRARY} wallet_api
${SODIUM_LIBRARY}
easylogging easylogging
blockchain_db
hardforks
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OPENSSL_LIBRARIES} ${OPENSSL_LIBRARIES}
${CMAKE_DL_LIBS} ${CMAKE_DL_LIBS}
@ -278,7 +278,9 @@ if(QML)
Qt5::WebSockets Qt5::WebSockets
Qt5::Quick Qt5::Quick
Qt5::Qml Qt5::Qml
Qt5::QuickControls2) Qt5::QuickControls2
Qt5::Multimedia
Qt5::MultimediaWidgets)
else() else()
target_link_libraries(wowlet PUBLIC target_link_libraries(wowlet PUBLIC
Qt5::Core Qt5::Core
@ -287,7 +289,9 @@ else()
Qt5::Network Qt5::Network
Qt5::Svg Qt5::Svg
Qt5::Xml Qt5::Xml
Qt5::WebSockets) Qt5::WebSockets
Qt5::Multimedia
Qt5::MultimediaWidgets)
endif() endif()
if(ANDROID) if(ANDROID)
@ -400,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 "This build is for testing the Android app on desktop: ${ANDROID_DEBUG}")
message(STATUS "TOR_BIN: ${TOR_BIN}") message(STATUS "TOR_BIN: ${TOR_BIN}")
message(STATUS "DONATE_BEG: ${DONATE_BEG}") message(STATUS "DONATE_BEG: ${DONATE_BEG}")
message(STATUS "=============================================") message(STATUS "=============================================")

@ -224,6 +224,7 @@
<file>assets/images/xmrig.svg</file> <file>assets/images/xmrig.svg</file>
<file>assets/images/zoom.png</file> <file>assets/images/zoom.png</file>
<file>assets/mnemonic_25_english.txt</file> <file>assets/mnemonic_25_english.txt</file>
<file>assets/videos/do_you_even_wow_special_friend.mp4</file>
<file>assets/restore_heights_wownero_mainnet.txt</file> <file>assets/restore_heights_wownero_mainnet.txt</file>
</qresource> </qresource>
</RCC> </RCC>

@ -93,8 +93,8 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
}); });
connect(ui->actionReport_bug, &QAction::triggered, [this](){ connect(ui->actionReport_bug, &QAction::triggered, [this](){
QMessageBox::information(this, "Reporting Bugs", QMessageBox::information(this, "Reporting Bugs",
"<body>Please report any bugs as issues on our git repo:<br>\n" "<body>Please report any bugs as issues on the forum:<br>\n"
"<a href=\"https://git.wownero.com/wowlet/wowlet/issues\" style=\"color: #33A4DF\">https://git.wownero.com/wowlet/wowlet/issues</a><br/><br/>" "<a href=\"https://forum.wownero.com\" style=\"color: #33A4DF\">https://forum.wownero.com/</a><br/><br/>"
"\n" "\n"
"Before reporting a bug, upgrade to the most recent version of WOWlet " "Before reporting a bug, upgrade to the most recent version of WOWlet "
"(latest release or git HEAD), and include the version number in your report. " "(latest release or git HEAD), and include the version number in your report. "

@ -181,6 +181,35 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_player">
<attribute name="title">
<string>WowPlayer</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_player">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="WowPlayerWidget" name="wowPlayerWidget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>320</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
<string>WFS</string> <string>WFS</string>
@ -784,6 +813,12 @@
<header>widgets/suchwowwidget.h</header> <header>widgets/suchwowwidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>WowPlayerWidget</class>
<extends>QWidget</extends>
<header>widgets/wowplayerwidget.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>ForumWidget</class> <class>ForumWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>

@ -16,5 +16,6 @@ target_include_directories(openpgp PUBLIC
target_link_libraries(openpgp target_link_libraries(openpgp
PUBLIC PUBLIC
epee
${GCRYPT_LIBRARY} ${GCRYPT_LIBRARY}
${GPG_ERROR_LIBRARY}) ${GPG_ERROR_LIBRARY})

@ -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 <QBoxLayout>
#include <QSlider>
#include <QStyle>
#include <QToolButton>
#include <QComboBox>
#include <QAudio>
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<int>::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());
}

@ -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 <QMediaPlayer>
#include <QWidget>
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

@ -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 <QMediaPlaylist>
#include "wowplayercontrols.h"
#include "wowvideowidget.h"
#include "wowplaylistmodel.h"
//#include "wowhistogramwidget.h"
#include <QMediaService>
#include <QVideoProbe>
#include <QAudioProbe>
#include <QMediaMetaData>
#include <QtWidgets>
#include <QVideoWidget>
#include <QStandardItemModel>
#include <QtMultimedia>
#include <QtMultimediaWidgets>
#include <QMediaService>
#include <QMediaPlaylist>
#include <QVideoProbe>
#include <QAudioProbe>
#include <QMediaMetaData>
#include <QtWidgets>
#include <QMediaPlayer>
//#include <QtMultimedia/QMediaPlayer>
#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<QMediaPlayer::Error>::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("<a href = \"https://radio.wownero.com/history.txt\"> History </a>");
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<QUrl> &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<QUrl>();
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()));
}

@ -0,0 +1,95 @@
//
// Created by rapeafed on 2021.
//
#ifndef WOWLET_WOWPLAYERWIDGET_H
#define WOWLET_WOWPLAYERWIDGET_H
#include <QWidget>
#include <QList>
#include <QtMultimedia>
#include <QtMultimediaWidgets>
#include <QtMultimedia/QMediaPlayer>
#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<QUrl> &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

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>WowPlayerWidget</class>
<widget class="QWidget" name="WowPlayerWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>WowPlayerWidget</string>
</property>
<widget class="QWidget" name="verticalWidget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>160</y>
<width>401</width>
<height>31</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</widget>
<resources/>
<connections/>
</ui>

@ -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 <QFileInfo>
#include <QUrl>
#include <QMediaPlaylist>
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));
}

@ -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 <QAbstractItemModel>
#include <QScopedPointer>
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<QMediaPlaylist> m_playlist;
QMap<QModelIndex, QVariant> m_data;
};
#endif // PLAYLISTMODEL_H

@ -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 <QKeyEvent>
#include <QMouseEvent>
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);
}

@ -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 <QVideoWidget>
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

@ -0,0 +1 @@
Subproject commit ff5182f7f2825263e93e88064931597b3c6cf928
Loading…
Cancel
Save