[Tidy] Tidyed up things, removed QML Reloading and Discord support.
This commit is contained in:
parent
5be24ac560
commit
b6d5547453
|
@ -4,21 +4,12 @@ project(KittehPlayer)
|
||||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
|
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
|
||||||
option(DEVELOP "Enable runtime QML reloading for developing." OFF)
|
|
||||||
option(DISCORD "Enable Discord SDK." OFF)
|
|
||||||
|
|
||||||
|
|
||||||
find_package(Qt5Core REQUIRED)
|
find_package(Qt5Core REQUIRED)
|
||||||
find_package(Qt5Gui REQUIRED)
|
find_package(Qt5Gui REQUIRED)
|
||||||
find_package(Qt5 CONFIG REQUIRED COMPONENTS Qml Quick Gui Widgets Core X11Extras)
|
find_package(Qt5 CONFIG REQUIRED COMPONENTS Qml Quick Gui Widgets Core X11Extras)
|
||||||
|
|
||||||
find_package(Qt5QuickCompiler)
|
find_package(Qt5QuickCompiler)
|
||||||
if(DEVELOP)
|
|
||||||
qt5_add_resources(QT_RESOURCES qml.qrc)
|
|
||||||
else()
|
|
||||||
qtquick_compiler_add_resources(qml_QRC src/qml/qml.qrc)
|
qtquick_compiler_add_resources(qml_QRC src/qml/qml.qrc)
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
pkg_check_modules(MPV REQUIRED mpv)
|
pkg_check_modules(MPV REQUIRED mpv)
|
||||||
|
@ -29,7 +20,6 @@ if(X11_FOUND AND Xext_FOUND)
|
||||||
add_definitions(-DENABLE_X11)
|
add_definitions(-DENABLE_X11)
|
||||||
endif(X11_FOUND AND Xext_FOUND)
|
endif(X11_FOUND AND Xext_FOUND)
|
||||||
|
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/DirectMpvPlayerBackend.cpp
|
src/DirectMpvPlayerBackend.cpp
|
||||||
|
@ -37,14 +27,13 @@ set(SOURCES
|
||||||
src/enums.hpp
|
src/enums.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if(MPV_VERSION VERSION_GREATER_EQUAL "1.28.0")
|
if(MPV_VERSION VERSION_GREATER_EQUAL "1.28.0")
|
||||||
set(SOURCES ${SOURCES} src/MpvPlayerBackend.cpp)
|
set(SOURCES ${SOURCES} src/MpvPlayerBackend.cpp)
|
||||||
else()
|
else()
|
||||||
add_definitions(-DDISABLE_MpvPlayerBackend)
|
add_definitions(-DDISABLE_MpvPlayerBackend)
|
||||||
endif(MPV_VERSION VERSION_GREATER_EQUAL "1.28.0")
|
endif(MPV_VERSION VERSION_GREATER_EQUAL "1.28.0")
|
||||||
|
|
||||||
find_program(CCACHE_FOUND ccache)
|
find_program(CCACHE_FOUND cache)
|
||||||
if(CCACHE_FOUND)
|
if(CCACHE_FOUND)
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||||
|
@ -52,7 +41,7 @@ endif(CCACHE_FOUND)
|
||||||
|
|
||||||
set(CMAKE_BUILD_TYPE RELEASE)
|
set(CMAKE_BUILD_TYPE RELEASE)
|
||||||
|
|
||||||
if(TESTING OR DEFINED ENV{TRAVIS})
|
if(DEFINED ENV{TRAVIS})
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git rev-parse HEAD
|
COMMAND git rev-parse HEAD
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
@ -61,37 +50,7 @@ execute_process(
|
||||||
)
|
)
|
||||||
find_package(Qt5Network REQUIRED)
|
find_package(Qt5Network REQUIRED)
|
||||||
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
||||||
endif(TESTING OR DEFINED ENV{TRAVIS})
|
endif(DEFINED ENV{TRAVIS})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(TESTING)
|
|
||||||
SET(CMAKE_C_COMPILER "/usr/bin/clang")
|
|
||||||
SET(CMAKE_CXX_COMPILER "/usr/bin/clang++")
|
|
||||||
SET(CMAKE_AR "/usr/bin/llvm-ar")
|
|
||||||
SET(CMAKE_LINKER "/usr/bin/llvm-link")
|
|
||||||
SET(CMAKE_NM "/usr/bin/llvm-nm")
|
|
||||||
SET(CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
|
|
||||||
SET(CMAKE_RANLIB "/usr/bin/llvm-ranlib")
|
|
||||||
endif(TESTING)
|
|
||||||
|
|
||||||
|
|
||||||
if(DEVELOP)
|
|
||||||
set(SOURCES ${SOURCES} runtimeqml/runtimeqml.cpp)
|
|
||||||
add_definitions(-DQRC_SOURCE_PATH="${PROJECT_SOURCE_DIR}/src/qml")
|
|
||||||
add_definitions(-DQT_QML_DEBUG)
|
|
||||||
endif(DEVELOP)
|
|
||||||
|
|
||||||
if(DISCORD)
|
|
||||||
add_definitions(-DDISCORD)
|
|
||||||
execute_process(
|
|
||||||
COMMAND git clone --depth 1 https://github.com/discordapp/discord-rpc
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
add_subdirectory(discord-rpc)
|
|
||||||
INCLUDE_DIRECTORIES(discord-rpc/include)
|
|
||||||
target_link_libraries(KittehPlayer discord-rpc)
|
|
||||||
endif(DISCORD)
|
|
||||||
|
|
||||||
add_executable(KittehPlayer ${SOURCES} ${qml_QRC})
|
add_executable(KittehPlayer ${SOURCES} ${qml_QRC})
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
TARGET = KittehPlayer
|
|
||||||
|
|
||||||
TEMPLATE = app
|
|
||||||
QT += qml quickcontrols2 widgets
|
|
||||||
|
|
||||||
SOURCES += src/main.cpp src/MpvPlayerBackend.cpp src/DirectMpvPlayerBackend.cpp src/utils.cpp
|
|
||||||
|
|
||||||
CONFIG += debug
|
|
||||||
CONFIG-=qtquickcompiler
|
|
||||||
QT_CONFIG -= no-pkg-config
|
|
||||||
CONFIG += link_pkgconfig
|
|
||||||
PKGCONFIG += mpv
|
|
||||||
RESOURCES += src/qml/qml.qrc
|
|
||||||
|
|
||||||
unix {
|
|
||||||
isEmpty {
|
|
||||||
PREFIX = /usr
|
|
||||||
}
|
|
||||||
|
|
||||||
target.path = $$PREFIX/bin
|
|
||||||
|
|
||||||
desktop.files = KittehPlayer.desktop
|
|
||||||
desktop.path = $$PREFIX/share/applications/
|
|
||||||
icon.files += KittehPlayer.png
|
|
||||||
icon.path = $$PREFIX/share/icons/hicolor/256x256/apps/
|
|
||||||
|
|
||||||
INSTALLS += desktop
|
|
||||||
INSTALLS += icon
|
|
||||||
}
|
|
||||||
|
|
||||||
INSTALLS += target
|
|
||||||
|
|
||||||
HEADERS += src/MpvPlayerBackend.h src/DirectMpvPlayerBackend.h src/utils.hpp
|
|
||||||
|
|
||||||
|
|
||||||
DISTFILES += KittehPlayer.desktop KittehPlayer.png README.md LICENSE.txt
|
|
|
@ -27,13 +27,12 @@ pacman -S git cmake qt5-svg qt5-declarative qt5-quickcontrols qt5-quickcontrols2
|
||||||
```
|
```
|
||||||
sudo add-apt-repository ppa:beineri/opt-qt-5.11.1-xenial -y
|
sudo add-apt-repository ppa:beineri/opt-qt-5.11.1-xenial -y
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install build-essential git nasm qt511-meta-minimal qt511quickcontrols qt511quickcontrols2 qt511imageformats qt511svg libgl1-mesa-dev
|
sudo apt install build-essential git nasm qt511-meta-minimal qt511quickcontrols qt511quickcontrols2 qt511imageformats qt511svg libgl1-mesa-dev libmpv-dev
|
||||||
sudo apt-get build-dep mpv libmpv* ffmpeg
|
sudo apt-get build-dep mpv libmpv* ffmpeg
|
||||||
```
|
```
|
||||||
#### Instructions
|
#### Instructions
|
||||||
- `git clone https://github.com/NamedKitten/KittehPlayer KittehPlayer`
|
- `git clone https://github.com/NamedKitten/KittehPlayer KittehPlayer`
|
||||||
- `cd KittehPlayer`
|
- `cd KittehPlayer`
|
||||||
- If you are running Ubuntu you will need to run `sudo ./scripts/build-mpv.sh` because ubuntu's MPV version is way too old.
|
|
||||||
- `mkdir build && cd build`
|
- `mkdir build && cd build`
|
||||||
- `cmake .. -DCMAKE_INSTALL_PREFIX=/usr`
|
- `cmake .. -DCMAKE_INSTALL_PREFIX=/usr`
|
||||||
- `make`
|
- `make`
|
||||||
|
|
75
runtimeqml/.gitignore
vendored
75
runtimeqml/.gitignore
vendored
|
@ -1,75 +0,0 @@
|
||||||
# This file is used to ignore files which are generated
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
*~
|
|
||||||
*.autosave
|
|
||||||
*.a
|
|
||||||
*.core
|
|
||||||
*.moc
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
*.orig
|
|
||||||
*.rej
|
|
||||||
*.so
|
|
||||||
*.so.*
|
|
||||||
*_pch.h.cpp
|
|
||||||
*_resource.rc
|
|
||||||
*.qm
|
|
||||||
.#*
|
|
||||||
*.*#
|
|
||||||
core
|
|
||||||
!core/
|
|
||||||
tags
|
|
||||||
.DS_Store
|
|
||||||
.directory
|
|
||||||
*.debug
|
|
||||||
Makefile*
|
|
||||||
*.prl
|
|
||||||
*.app
|
|
||||||
moc_*.cpp
|
|
||||||
ui_*.h
|
|
||||||
qrc_*.cpp
|
|
||||||
Thumbs.db
|
|
||||||
*.res
|
|
||||||
*.rc
|
|
||||||
/.qmake.cache
|
|
||||||
/.qmake.stash
|
|
||||||
|
|
||||||
# qtcreator generated files
|
|
||||||
*.pro.user*
|
|
||||||
# qtcreator builds of test project
|
|
||||||
build-RuntimeQML-*
|
|
||||||
|
|
||||||
# xemacs temporary files
|
|
||||||
*.flc
|
|
||||||
|
|
||||||
# Vim temporary files
|
|
||||||
.*.swp
|
|
||||||
|
|
||||||
# Visual Studio generated files
|
|
||||||
*.ib_pdb_index
|
|
||||||
*.idb
|
|
||||||
*.ilk
|
|
||||||
*.pdb
|
|
||||||
*.sln
|
|
||||||
*.suo
|
|
||||||
*.vcproj
|
|
||||||
*vcproj.*.*.user
|
|
||||||
*.ncb
|
|
||||||
*.sdf
|
|
||||||
*.opensdf
|
|
||||||
*.vcxproj
|
|
||||||
*vcxproj.*
|
|
||||||
|
|
||||||
# MinGW generated files
|
|
||||||
*.Debug
|
|
||||||
*.Release
|
|
||||||
|
|
||||||
# Python byte code
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Binaries
|
|
||||||
# --------
|
|
||||||
*.dll
|
|
||||||
*.exe
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
Copyright (c) 2018, Benjamin Balga
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
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 <organization> 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 <COPYRIGHT HOLDER> 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.
|
|
|
@ -1,87 +0,0 @@
|
||||||
# Runtime QML for Qt
|
|
||||||
|
|
||||||
**Written by**: *Benjamin Balga.*
|
|
||||||
**Copyright**: ***2018***, *Benjamin Balga*, released under BSD license.
|
|
||||||
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
This is a base project to get runtime QML reload in your Qt project.
|
|
||||||
It allows you to reload all QML code at runtime, without recompiling or restarting your app, saving time.
|
|
||||||
|
|
||||||
With auto-reload, QML files are watched (based on the QRC file) and reloaded when you save them, or can trigger it manually.
|
|
||||||
|
|
||||||
On reload, all windows are closed, and the main window is reloaded. All "QML-only data" is lost, so use links to C++ models/properties as needed.
|
|
||||||
|
|
||||||
It only works with Window component as top object, or QQuickWindow subclasses.
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
Example project is located here: https://github.com/GIPdA/runtimeqml_examples
|
|
||||||
|
|
||||||
|
|
||||||
## How to use it in your project
|
|
||||||
|
|
||||||
Clone the repo into your project (or copy-paste the ```runtimeqml``` folder) and import the ```.pri``` project file into your ```.pro``` file:
|
|
||||||
|
|
||||||
include(runtimeqml/runtimeqml.pri)
|
|
||||||
|
|
||||||
|
|
||||||
### With Qbs
|
|
||||||
The Qbs project file includes RuntimeQML as a static library. Check the example project to see how to include it in your project.
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Include ```runtimeqml.h``` header file, and create the RuntimeQML object (after the QML engine) :
|
|
||||||
|
|
||||||
RuntimeQML *rt = new RuntimeQML(&engine, QRC_SOURCE_PATH"/qml.qrc");
|
|
||||||
|
|
||||||
The second argument is the path to your qrc file listing all your QML files, needed for the auto-reload feature only. You can omit it if you don't want auto-reload.
|
|
||||||
```QRC_SOURCE_PATH``` is defined in the ```.pri/.qbs``` file to its parent path, just to not have to manually set an absolute path...
|
|
||||||
|
|
||||||
|
|
||||||
Set the "options" you want, or not:
|
|
||||||
|
|
||||||
rt->noDebug(); // Removes debug prints
|
|
||||||
rt->setAutoReload(true); // Enable auto-reload (begin to watch files)
|
|
||||||
//rt->setCloseAllOnReload(false); // Don't close all windows on reload. Not advised!
|
|
||||||
rt->setMainQmlFilename("main.qml"); // This is the file that loaded on reload, default is "main.qml"
|
|
||||||
|
|
||||||
For the auto-reload feature:
|
|
||||||
|
|
||||||
rt->addSuffix("conf"); // Adds a file suffix to the "white list" for watched files. "qml" is already in.
|
|
||||||
rt->ignorePrefix("/test"); // Ignore a prefix in the QRC file.
|
|
||||||
rt->ignoreFile("/Page2.qml"); // Ignore a file name with prefix (supports classic wildcard matching)
|
|
||||||
|
|
||||||
|
|
||||||
Then load the main QML file :
|
|
||||||
|
|
||||||
rt->reload();
|
|
||||||
|
|
||||||
And you're all set!
|
|
||||||
|
|
||||||
|
|
||||||
You can also check the test project. Beware, includes and defines differs a bit...
|
|
||||||
|
|
||||||
|
|
||||||
## Manual reload
|
|
||||||
|
|
||||||
Add the RuntimeQML object to the QML context:
|
|
||||||
|
|
||||||
engine.rootContext()->setContextProperty("RuntimeQML", rt);
|
|
||||||
|
|
||||||
Trigger the reload when and where you want, like with a button:
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: "Reload"
|
|
||||||
onClicked: {
|
|
||||||
RuntimeQML.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
You can do it in C++ too, of course.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
See LICENSE file.
|
|
|
@ -1,398 +0,0 @@
|
||||||
#include "runtimeqml.h"
|
|
||||||
|
|
||||||
#include <QXmlStreamReader>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QRegExp>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Construct a RuntimeQML object with a path to the qrc file.
|
|
||||||
* \param engine App engine to reload.
|
|
||||||
* \param qrcFilename File name of the QRC file for auto reload.
|
|
||||||
* \param parent Pointer to a parent object.
|
|
||||||
*/
|
|
||||||
RuntimeQML::RuntimeQML(QQmlApplicationEngine* engine, const QString &qrcFilename, QObject *parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_engine(engine),
|
|
||||||
m_qrcFilename(qrcFilename),
|
|
||||||
m_mainQmlFilename("main.qml")
|
|
||||||
{
|
|
||||||
m_allowedSuffixList << "qml";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the absolute path for the given qml file.
|
|
||||||
* \param qmlFile Qml filename
|
|
||||||
*/
|
|
||||||
QString RuntimeQML::adjustPath(QString qmlFile)
|
|
||||||
{
|
|
||||||
return m_selector.select(qrcAbsolutePath() + "/" + qmlFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the absolute path to the QRC file.
|
|
||||||
*/
|
|
||||||
QString RuntimeQML::qrcAbsolutePath() const
|
|
||||||
{
|
|
||||||
return QFileInfo(m_qrcFilename).absolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Filename of the QRC file.
|
|
||||||
*/
|
|
||||||
QString RuntimeQML::qrcFilename() const
|
|
||||||
{
|
|
||||||
return m_qrcFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief If true, files are watched for changes and auto-reloaded.
|
|
||||||
* Otherwise, you need to trigger a reload manually from your code by calling reload().
|
|
||||||
* \sa reload
|
|
||||||
*/
|
|
||||||
bool RuntimeQML::autoReload() const
|
|
||||||
{
|
|
||||||
return m_autoReload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief If true, all open windows will be closed upon reload.
|
|
||||||
* \default true
|
|
||||||
*/
|
|
||||||
bool RuntimeQML::closeAllOnReload() const
|
|
||||||
{
|
|
||||||
return m_closeAllOnReload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief QRC prefixes that are ignored.
|
|
||||||
*/
|
|
||||||
const QList<QString>& RuntimeQML::prefixIgnoreList() const
|
|
||||||
{
|
|
||||||
return m_prefixIgnoreList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Files that are ignored.
|
|
||||||
*/
|
|
||||||
const QList<QString> &RuntimeQML::fileIgnoreList() const
|
|
||||||
{
|
|
||||||
return m_fileIgnoreList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Allowed suffixes to filter files to watch for changes.
|
|
||||||
* By default contains only "qml".
|
|
||||||
*/
|
|
||||||
const QList<QString> &RuntimeQML::allowedSuffixes() const
|
|
||||||
{
|
|
||||||
return m_allowedSuffixList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Call it if you don't want debug outputs from this class.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::noDebug()
|
|
||||||
{
|
|
||||||
if (m_noDebug)
|
|
||||||
return;
|
|
||||||
m_noDebug = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Reload the window.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::reload()
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(this, "reloadQml", Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Call it from QML to set the current QQuickWindow.
|
|
||||||
* You shouldn't need to call it as it is done automatically on reload.
|
|
||||||
* \param window
|
|
||||||
*/
|
|
||||||
void RuntimeQML::setWindow(QQuickWindow* window)
|
|
||||||
{
|
|
||||||
if (window == m_window)
|
|
||||||
return;
|
|
||||||
m_window = window;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Set the QRC filename for files to watch for changes.
|
|
||||||
* \param qrcFilename Path to a .qrc file.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::setQrcFilename(QString qrcFilename)
|
|
||||||
{
|
|
||||||
if (m_qrcFilename == qrcFilename)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_qrcFilename = qrcFilename;
|
|
||||||
emit qrcFilenameChanged(qrcFilename);
|
|
||||||
|
|
||||||
loadQrcFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Set the name of the main qml file.
|
|
||||||
* Default is "main.qml".
|
|
||||||
* \param filename The main qml filename.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::setMainQmlFilename(QString filename)
|
|
||||||
{
|
|
||||||
if (m_mainQmlFilename == filename)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_mainQmlFilename = filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief If true, files are watched for changes and auto-reloaded.
|
|
||||||
* Otherwise, you need to trigger a reload manually from your code by calling reload().
|
|
||||||
* \param reload True to auto-reload, false otherwise.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::setAutoReload(bool autoReload)
|
|
||||||
{
|
|
||||||
if (m_autoReload == autoReload)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_autoReload = autoReload;
|
|
||||||
emit autoReloadChanged(autoReload);
|
|
||||||
|
|
||||||
if (autoReload)
|
|
||||||
loadQrcFiles();
|
|
||||||
else
|
|
||||||
unloadFileWatcher();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief If true, all open windows are closed upon reload. Otherwise, might cause "link" errors with QML components.
|
|
||||||
* \param closeAllOnReload True to close all windows on reload, false otherwise.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::setCloseAllOnReload(bool closeAllOnReload)
|
|
||||||
{
|
|
||||||
if (m_closeAllOnReload == closeAllOnReload)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_closeAllOnReload = closeAllOnReload;
|
|
||||||
emit closeAllOnReloadChanged(m_closeAllOnReload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Add a QRC prefix to ignore.
|
|
||||||
* \note Relevant for auto-reload only.
|
|
||||||
* \param prefix Prefix to ignore.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::ignoreQrcPrefix(const QString& prefix)
|
|
||||||
{
|
|
||||||
if (m_prefixIgnoreList.contains(prefix))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_prefixIgnoreList.append(prefix);
|
|
||||||
|
|
||||||
if (m_autoReload)
|
|
||||||
loadQrcFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Add a filename to ignore from changes.
|
|
||||||
* Applies to the full filename in the QRC entry (i.e. the local "path"), with the prefix.
|
|
||||||
* Supports "file globbing" matching using wildcards.
|
|
||||||
* \note Relevant for auto-reload only.
|
|
||||||
* \param filename Filename to ignore.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::ignoreFile(const QString &filename)
|
|
||||||
{
|
|
||||||
if (m_fileIgnoreList.contains(filename))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_fileIgnoreList.append(filename);
|
|
||||||
|
|
||||||
if (m_autoReload)
|
|
||||||
loadQrcFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Allow a file suffix to be watched for changes.
|
|
||||||
* \note Relevant for auto-reload only.
|
|
||||||
* \param suffix
|
|
||||||
*/
|
|
||||||
void RuntimeQML::addSuffix(const QString &suffix)
|
|
||||||
{
|
|
||||||
if (m_allowedSuffixList.contains(suffix))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_allowedSuffixList.append(suffix);
|
|
||||||
|
|
||||||
if (m_autoReload)
|
|
||||||
loadQrcFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Reload the QML. Do not call it directly, use reload() instead.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::reloadQml()
|
|
||||||
{
|
|
||||||
if (m_mainQmlFilename.isEmpty()) {
|
|
||||||
qWarning("No QML file specified.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_window) {
|
|
||||||
if (m_closeAllOnReload) {
|
|
||||||
// Find all child windows and close them
|
|
||||||
auto const allWindows = m_window->findChildren<QQuickWindow*>();
|
|
||||||
for (int i {0}; i < allWindows.size(); ++i) {
|
|
||||||
QQuickWindow* w = qobject_cast<QQuickWindow*>(allWindows.at(i));
|
|
||||||
if (w) {
|
|
||||||
w->close();
|
|
||||||
w->deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_window->close();
|
|
||||||
m_window->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_engine->clearComponentCache();
|
|
||||||
// TODO: test with network files
|
|
||||||
// TODO: QString path to QUrl doesn't work under Windows with load() (load fail)
|
|
||||||
m_engine->load(m_selector.select(qrcAbsolutePath() + "/" + m_mainQmlFilename));
|
|
||||||
// NOTE: QQmlApplicationEngine::rootObjects() isn't cleared, should it be?
|
|
||||||
|
|
||||||
if (!m_engine->rootObjects().isEmpty()) {
|
|
||||||
QQuickWindow* w = qobject_cast<QQuickWindow*>(m_engine->rootObjects().last());
|
|
||||||
if (w) m_window = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for (auto *o : m_engine->rootObjects()) {
|
|
||||||
// qDebug() << "> " << o;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Called when a watched file changed, from QFileSystemWatcher.
|
|
||||||
* \param path Path/file that triggered the signal.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::fileChanged(const QString& path)
|
|
||||||
{
|
|
||||||
if (!m_noDebug)
|
|
||||||
qDebug() << "Reloading qml:" << path;
|
|
||||||
reload();
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
// Deleted files are removed from the watcher, re-add the file for
|
|
||||||
// systems that delete files to update them
|
|
||||||
if (m_fileWatcher)
|
|
||||||
QTimer::singleShot(500, m_fileWatcher, [this,path](){
|
|
||||||
m_fileWatcher->addPath(path);
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Load qml from the QRC file to watch them.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::loadQrcFiles()
|
|
||||||
{
|
|
||||||
unloadFileWatcher();
|
|
||||||
|
|
||||||
m_fileWatcher = new QFileSystemWatcher(this);
|
|
||||||
connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &RuntimeQML::fileChanged);
|
|
||||||
|
|
||||||
QFile file(m_qrcFilename);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
qWarning("Unable to open resource file '%s', RuntimeQML will not work! Error: %s",
|
|
||||||
qPrintable(m_qrcFilename), qPrintable(file.errorString()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString const basePath = qrcAbsolutePath() + "/";
|
|
||||||
QString currentPrefix;
|
|
||||||
|
|
||||||
// Read each entry
|
|
||||||
QXmlStreamReader inputStream(&file);
|
|
||||||
while (!inputStream.atEnd() && !inputStream.hasError()) {
|
|
||||||
inputStream.readNext();
|
|
||||||
if (inputStream.isStartElement()) {
|
|
||||||
QString name { inputStream.name().toString() };
|
|
||||||
|
|
||||||
// Check prefix
|
|
||||||
if (name == "qresource") {
|
|
||||||
if (inputStream.attributes().hasAttribute("prefix")) {
|
|
||||||
auto p = inputStream.attributes().value("prefix").toString();
|
|
||||||
if (m_prefixIgnoreList.contains(p)) {
|
|
||||||
// Ignore this prefix, loop through elements in this 'qresource' tag
|
|
||||||
while (!inputStream.atEnd() && !inputStream.hasError()) {
|
|
||||||
inputStream.readNext();
|
|
||||||
if (inputStream.isEndElement() && inputStream.name() == "qresource")
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
currentPrefix = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check file name
|
|
||||||
if (name == "file") {
|
|
||||||
QString const filename { inputStream.readElementText() };
|
|
||||||
|
|
||||||
// Check ignore list
|
|
||||||
QString const fullFilename { currentPrefix + filename };
|
|
||||||
auto it = std::find_if(m_fileIgnoreList.cbegin(), m_fileIgnoreList.cend(), [&](QString const& pattern) {
|
|
||||||
QRegExp re(pattern);
|
|
||||||
re.setPatternSyntax(QRegExp::WildcardUnix);
|
|
||||||
return re.exactMatch(fullFilename);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (it != m_fileIgnoreList.cend())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QFileInfo const file { filename };
|
|
||||||
|
|
||||||
// Add to the watch list if the file suffix is allowed
|
|
||||||
if (m_allowedSuffixList.contains(file.suffix())) {
|
|
||||||
QString fp { m_selector.select(basePath + filename) };
|
|
||||||
m_fileWatcher->addPath(fp);
|
|
||||||
//qDebug() << " " << file.absoluteFilePath() << fp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_noDebug) {
|
|
||||||
qDebug("Watching QML files:");
|
|
||||||
int const fileCount = m_fileWatcher->files().size();
|
|
||||||
|
|
||||||
for (auto &f : m_fileWatcher->files()) {
|
|
||||||
qDebug() << " " << f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileCount > 0)
|
|
||||||
qDebug(" Total: %d", fileCount);
|
|
||||||
else
|
|
||||||
qDebug(" None.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Unload the file watcher.
|
|
||||||
*/
|
|
||||||
void RuntimeQML::unloadFileWatcher()
|
|
||||||
{
|
|
||||||
if (m_fileWatcher) {
|
|
||||||
disconnect(m_fileWatcher);
|
|
||||||
delete m_fileWatcher;
|
|
||||||
m_fileWatcher = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
#ifndef RUNTIMEQML_H
|
|
||||||
#define RUNTIMEQML_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QQmlApplicationEngine>
|
|
||||||
#include <QQuickWindow>
|
|
||||||
#include <QFileSelector>
|
|
||||||
#include <QFileSystemWatcher>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
|
|
||||||
class RuntimeQML : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString qrcFilename READ qrcFilename WRITE setQrcFilename NOTIFY qrcFilenameChanged)
|
|
||||||
Q_PROPERTY(bool autoReload READ autoReload WRITE setAutoReload NOTIFY autoReloadChanged)
|
|
||||||
Q_PROPERTY(bool closeAllOnReload READ closeAllOnReload WRITE setCloseAllOnReload NOTIFY closeAllOnReloadChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit RuntimeQML(QQmlApplicationEngine *engine, QString const& qrcFilename = QString(), QObject *parent = 0);
|
|
||||||
|
|
||||||
// If using QQmlFileSelector with Loader
|
|
||||||
Q_INVOKABLE QString adjustPath(QString qmlFile);
|
|
||||||
Q_INVOKABLE QString qrcAbsolutePath() const;
|
|
||||||
|
|
||||||
QString qrcFilename() const;
|
|
||||||
|
|
||||||
bool autoReload() const;
|
|
||||||
bool closeAllOnReload() const;
|
|
||||||
|
|
||||||
QList<QString> const & prefixIgnoreList() const;
|
|
||||||
QList<QString> const & fileIgnoreList() const;
|
|
||||||
QList<QString> const & allowedSuffixes() const;
|
|
||||||
|
|
||||||
void noDebug();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void autoReloadChanged(bool autoReload);
|
|
||||||
void qrcFilenameChanged(QString qrcFilename);
|
|
||||||
void closeAllOnReloadChanged(bool closeAllOnReload);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void reload();
|
|
||||||
void setWindow(QQuickWindow* window);
|
|
||||||
|
|
||||||
void setQrcFilename(QString qrcFilename);
|
|
||||||
void setMainQmlFilename(QString filename);
|
|
||||||
|
|
||||||
void setAutoReload(bool autoReload);
|
|
||||||
void setCloseAllOnReload(bool closeAllOnReload);
|
|
||||||
|
|
||||||
void ignoreQrcPrefix(QString const& prefix);
|
|
||||||
void ignoreFile(QString const& filename);
|
|
||||||
|
|
||||||
void addSuffix(QString const& suffix);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void reloadQml();
|
|
||||||
void fileChanged(const QString &path);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void loadQrcFiles();
|
|
||||||
void unloadFileWatcher();
|
|
||||||
|
|
||||||
QQmlApplicationEngine *m_engine {nullptr};
|
|
||||||
QQuickWindow *m_window {nullptr};
|
|
||||||
QFileSelector m_selector;
|
|
||||||
|
|
||||||
QString m_qrcFilename;
|
|
||||||
QString m_mainQmlFilename;
|
|
||||||
|
|
||||||
bool m_autoReload {false};
|
|
||||||
QFileSystemWatcher* m_fileWatcher {nullptr};
|
|
||||||
QList<QString> m_prefixIgnoreList;
|
|
||||||
QList<QString> m_fileIgnoreList;
|
|
||||||
QList<QString> m_allowedSuffixList;
|
|
||||||
bool m_noDebug {false};
|
|
||||||
bool m_closeAllOnReload {true};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // RUNTIMEQML_H
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Qt Quick Runtime Reloader
|
|
||||||
|
|
||||||
QT += core qml quick
|
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD
|
|
||||||
|
|
||||||
DEFINES += "QRC_SOURCE_PATH=\\\"$$PWD/..\\\""
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
$$PWD/runtimeqml.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$PWD/runtimeqml.h
|
|
|
@ -1,18 +0,0 @@
|
||||||
import qbs 1.0
|
|
||||||
|
|
||||||
StaticLibrary {
|
|
||||||
name: "runtimeqml"
|
|
||||||
files: [
|
|
||||||
"runtimeqml.cpp",
|
|
||||||
"runtimeqml.h",
|
|
||||||
]
|
|
||||||
Depends { name: 'cpp' }
|
|
||||||
Depends { name: "Qt.core" }
|
|
||||||
Depends { name: "Qt.quick" }
|
|
||||||
|
|
||||||
Export {
|
|
||||||
Depends { name: "cpp" }
|
|
||||||
cpp.includePaths: [product.sourceDirectory]
|
|
||||||
cpp.defines: ['QRC_SOURCE_PATH="'+path+'/.."']
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,10 +14,6 @@
|
||||||
#include <QSequentialIterable>
|
#include <QSequentialIterable>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef DISCORD
|
|
||||||
#include "discord_rpc.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
wakeup(void* ctx)
|
wakeup(void* ctx)
|
||||||
{
|
{
|
||||||
|
@ -79,12 +75,6 @@ DirectMpvPlayerBackend::DirectMpvPlayerBackend(QQuickItem* parent)
|
||||||
if (!mpv)
|
if (!mpv)
|
||||||
throw std::runtime_error("could not create mpv context");
|
throw std::runtime_error("could not create mpv context");
|
||||||
|
|
||||||
#ifdef DISCORD
|
|
||||||
DiscordEventHandlers handlers;
|
|
||||||
memset(&handlers, 0, sizeof(handlers));
|
|
||||||
Discord_Initialize("511220330996432896", &handlers, 1, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mpv_set_option_string(mpv, "terminal", "yes");
|
mpv_set_option_string(mpv, "terminal", "yes");
|
||||||
mpv_set_option_string(mpv, "msg-level", "all=v");
|
mpv_set_option_string(mpv, "msg-level", "all=v");
|
||||||
|
|
||||||
|
@ -234,25 +224,6 @@ DirectMpvPlayerBackend::launchAboutQt()
|
||||||
qapp->aboutQt();
|
qapp->aboutQt();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DISCORD
|
|
||||||
void
|
|
||||||
DirectMpvPlayerBackend::updateDiscord()
|
|
||||||
{
|
|
||||||
char buffer[256];
|
|
||||||
DiscordRichPresence discordPresence;
|
|
||||||
memset(&discordPresence, 0, sizeof(discordPresence));
|
|
||||||
discordPresence.state = getProperty("pause").toBool() ? "Paused" : "Playing";
|
|
||||||
sprintf(buffer,
|
|
||||||
"Currently Playing: Video %s",
|
|
||||||
getProperty("media-title").toString().toUtf8().constData());
|
|
||||||
discordPresence.details = buffer;
|
|
||||||
discordPresence.startTimestamp = time(0);
|
|
||||||
discordPresence.endTimestamp = time(0) + (getProperty("duration").toFloat() -
|
|
||||||
getProperty("time-pos").toFloat());
|
|
||||||
discordPresence.instance = 0;
|
|
||||||
Discord_UpdatePresence(&discordPresence);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
QVariant
|
QVariant
|
||||||
DirectMpvPlayerBackend::playerCommand(const Enums::Commands& cmd)
|
DirectMpvPlayerBackend::playerCommand(const Enums::Commands& cmd)
|
||||||
{
|
{
|
||||||
|
@ -606,9 +577,6 @@ DirectMpvPlayerBackend::handle_mpv_event(mpv_event* event)
|
||||||
double speed = *(double*)prop->data;
|
double speed = *(double*)prop->data;
|
||||||
emit speedChanged(speed);
|
emit speedChanged(speed);
|
||||||
}
|
}
|
||||||
#ifdef DISCORD
|
|
||||||
updateDiscord();
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MPV_EVENT_SHUTDOWN: {
|
case MPV_EVENT_SHUTDOWN: {
|
||||||
|
|
|
@ -103,9 +103,6 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_mpv_event(mpv_event* event);
|
void handle_mpv_event(mpv_event* event);
|
||||||
#ifdef DISCORD
|
|
||||||
void updateDiscord();
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,10 +12,6 @@
|
||||||
#include <QSequentialIterable>
|
#include <QSequentialIterable>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifdef DISCORD
|
|
||||||
#include "discord_rpc.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <QX11Info>
|
#include <QX11Info>
|
||||||
#include <QtX11Extras/QX11Info>
|
#include <QtX11Extras/QX11Info>
|
||||||
|
@ -136,12 +132,6 @@ MpvPlayerBackend::MpvPlayerBackend(QQuickItem* parent)
|
||||||
if (!mpv)
|
if (!mpv)
|
||||||
throw std::runtime_error("could not create mpv context");
|
throw std::runtime_error("could not create mpv context");
|
||||||
|
|
||||||
#ifdef DISCORD
|
|
||||||
DiscordEventHandlers handlers;
|
|
||||||
memset(&handlers, 0, sizeof(handlers));
|
|
||||||
Discord_Initialize("511220330996432896", &handlers, 1, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mpv_set_option_string(mpv, "terminal", "yes");
|
mpv_set_option_string(mpv, "terminal", "yes");
|
||||||
mpv_set_option_string(mpv, "msg-level", "all=v");
|
mpv_set_option_string(mpv, "msg-level", "all=v");
|
||||||
|
|
||||||
|
@ -243,33 +233,6 @@ MpvPlayerBackend::setOption(const QString& name, const QVariant& value)
|
||||||
mpv::qt::set_option_variant(mpv, name, value);
|
mpv::qt::set_option_variant(mpv, name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MpvPlayerBackend::launchAboutQt()
|
|
||||||
{
|
|
||||||
QApplication* qapp =
|
|
||||||
qobject_cast<QApplication*>(QCoreApplication::instance());
|
|
||||||
qapp->aboutQt();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DISCORD
|
|
||||||
void
|
|
||||||
MpvPlayerBackend::updateDiscord()
|
|
||||||
{
|
|
||||||
char buffer[256];
|
|
||||||
DiscordRichPresence discordPresence;
|
|
||||||
memset(&discordPresence, 0, sizeof(discordPresence));
|
|
||||||
discordPresence.state = getProperty("pause").toBool() ? "Paused" : "Playing";
|
|
||||||
sprintf(buffer,
|
|
||||||
"Currently Playing: Video %s",
|
|
||||||
getProperty("media-title").toString().toUtf8().constData());
|
|
||||||
discordPresence.details = buffer;
|
|
||||||
discordPresence.startTimestamp = time(0);
|
|
||||||
discordPresence.endTimestamp = time(0) + (getProperty("duration").toFloat() -
|
|
||||||
getProperty("time-pos").toFloat());
|
|
||||||
discordPresence.instance = 0;
|
|
||||||
Discord_UpdatePresence(&discordPresence);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
QVariant
|
QVariant
|
||||||
MpvPlayerBackend::playerCommand(const Enums::Commands& cmd)
|
MpvPlayerBackend::playerCommand(const Enums::Commands& cmd)
|
||||||
{
|
{
|
||||||
|
@ -496,12 +459,6 @@ MpvPlayerBackend::updateDurationString(int numTime)
|
||||||
emit durationStringChanged(durationString);
|
emit durationStringChanged(durationString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MpvPlayerBackend::updateAppImage()
|
|
||||||
{
|
|
||||||
Utils::updateAppImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap
|
QVariantMap
|
||||||
MpvPlayerBackend::getAudioDevices(const QVariant& drivers) const
|
MpvPlayerBackend::getAudioDevices(const QVariant& drivers) const
|
||||||
{
|
{
|
||||||
|
@ -591,9 +548,6 @@ MpvPlayerBackend::handle_mpv_event(mpv_event* event)
|
||||||
double speed = *(double*)prop->data;
|
double speed = *(double*)prop->data;
|
||||||
emit speedChanged(speed);
|
emit speedChanged(speed);
|
||||||
}
|
}
|
||||||
#ifdef DISCORD
|
|
||||||
updateDiscord();
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MPV_EVENT_SHUTDOWN: {
|
case MPV_EVENT_SHUTDOWN: {
|
||||||
|
|
|
@ -46,9 +46,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
QVariant playerCommand(const Enums::Commands& command, const QVariant& args);
|
QVariant playerCommand(const Enums::Commands& command, const QVariant& args);
|
||||||
QVariant playerCommand(const Enums::Commands& command);
|
QVariant playerCommand(const Enums::Commands& command);
|
||||||
void launchAboutQt();
|
|
||||||
void toggleOnTop();
|
void toggleOnTop();
|
||||||
void updateAppImage();
|
|
||||||
// Optional but handy for MPV or custom backend settings.
|
// Optional but handy for MPV or custom backend settings.
|
||||||
void command(const QVariant& params);
|
void command(const QVariant& params);
|
||||||
void setProperty(const QString& name, const QVariant& value);
|
void setProperty(const QString& name, const QVariant& value);
|
||||||
|
@ -87,9 +85,6 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_mpv_event(mpv_event* event);
|
void handle_mpv_event(mpv_event* event);
|
||||||
#ifdef DISCORD
|
|
||||||
void updateDiscord();
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,9 +17,7 @@ public slots:
|
||||||
virtual QVariant playerCommand(const Enums::Commands& command,
|
virtual QVariant playerCommand(const Enums::Commands& command,
|
||||||
const QVariant& args) = 0;
|
const QVariant& args) = 0;
|
||||||
virtual QVariant playerCommand(const Enums::Commands& command) = 0;
|
virtual QVariant playerCommand(const Enums::Commands& command) = 0;
|
||||||
virtual void launchAboutQt() = 0;
|
|
||||||
virtual void toggleOnTop() = 0;
|
virtual void toggleOnTop() = 0;
|
||||||
virtual void updateAppImage() = 0;
|
|
||||||
// Optional but handy for MPV or custom backend settings.
|
// Optional but handy for MPV or custom backend settings.
|
||||||
virtual void command(const QVariant& params) = 0;
|
virtual void command(const QVariant& params) = 0;
|
||||||
virtual void setProperty(const QString& name, const QVariant& value) = 0;
|
virtual void setProperty(const QString& name, const QVariant& value) = 0;
|
||||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -1,7 +1,3 @@
|
||||||
#ifdef QRC_SOURCE_PATH
|
|
||||||
#include "runtimeqml/runtimeqml.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "DirectMpvPlayerBackend.h"
|
#include "DirectMpvPlayerBackend.h"
|
||||||
#ifndef DISABLE_MpvPlayerBackend
|
#ifndef DISABLE_MpvPlayerBackend
|
||||||
#include "MpvPlayerBackend.h"
|
#include "MpvPlayerBackend.h"
|
||||||
|
@ -138,7 +134,6 @@ main(int argc, char* argv[])
|
||||||
qRegisterMetaType<Enums::PlayStatus>("Enums.PlayStatus");
|
qRegisterMetaType<Enums::PlayStatus>("Enums.PlayStatus");
|
||||||
qRegisterMetaType<Enums::VolumeStatus>("Enums.VolumeStatus");
|
qRegisterMetaType<Enums::VolumeStatus>("Enums.VolumeStatus");
|
||||||
qRegisterMetaType<Enums::Backends>("Enums.Backends");
|
qRegisterMetaType<Enums::Backends>("Enums.Backends");
|
||||||
|
|
||||||
qRegisterMetaType<Enums::Commands>("Enums.Commands");
|
qRegisterMetaType<Enums::Commands>("Enums.Commands");
|
||||||
|
|
||||||
qmlRegisterType<UtilsClass>("player", 1, 0, "Utils");
|
qmlRegisterType<UtilsClass>("player", 1, 0, "Utils");
|
||||||
|
@ -164,15 +159,7 @@ main(int argc, char* argv[])
|
||||||
std::setlocale(LC_NUMERIC, "C");
|
std::setlocale(LC_NUMERIC, "C");
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
#ifdef QRC_SOURCE_PATH
|
|
||||||
RuntimeQML* rt = new RuntimeQML(&engine, QRC_SOURCE_PATH "/qml.qrc");
|
|
||||||
|
|
||||||
rt->setAutoReload(true);
|
|
||||||
rt->setMainQmlFilename("main.qml");
|
|
||||||
rt->reload();
|
|
||||||
#else
|
|
||||||
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
||||||
#endif
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ Item {
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: controlsBar
|
id: controlsBar
|
||||||
height: controlsBar.visible ? mainWindow.virtualHeight / 24 : 0
|
height: controlsBar.visible ? mainWindow.virtualHeight / 20 : 0
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: parent.width / 128
|
anchors.rightMargin: parent.width / 128
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
|
|
@ -218,7 +218,7 @@ MenuBar {
|
||||||
}
|
}
|
||||||
Action {
|
Action {
|
||||||
text: translate.getTranslation("UPDATE", i18n.language)
|
text: translate.getTranslation("UPDATE", i18n.language)
|
||||||
onTriggered: player.updateAppImage()
|
onTriggered: utils.updateAppImage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ MenuBar {
|
||||||
Action {
|
Action {
|
||||||
text: translate.getTranslation("ABOUT_QT", i18n.language)
|
text: translate.getTranslation("ABOUT_QT", i18n.language)
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
player.launchAboutQt()
|
utils.launchAboutQt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -19,7 +19,6 @@ Button {
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var aptn = appearance.themeName
|
var aptn = appearance.themeName
|
||||||
appearance.themeName = aptn == "YouTube" ? "RoosterTeeth" : aptn
|
appearance.themeName = aptn == "YouTube" ? "RoosterTeeth" : aptn
|
||||||
|
|
|
@ -24,17 +24,17 @@ Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateStatus(status) {
|
function updateStatus(status) {
|
||||||
if (volumeButton == null)
|
if (volumeButton == null)
|
||||||
console.log("OwO")
|
console.log("OwO")
|
||||||
|
|
||||||
if (status == Enums.VolumeStatus.Muted) {
|
if (status == Enums.VolumeStatus.Muted) {
|
||||||
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-mute.svg"
|
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-mute.svg"
|
||||||
} else if (status == Enums.VolumeStatus.Low) {
|
} else if (status == Enums.VolumeStatus.Low) {
|
||||||
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-down.svg"
|
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-down.svg"
|
||||||
} else if (status == Enums.VolumeStatus.Normal) {
|
} else if (status == Enums.VolumeStatus.Normal) {
|
||||||
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-up.svg"
|
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-up.svg"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
|
|
|
@ -45,7 +45,7 @@ Slider {
|
||||||
x: volumeBar.leftPadding
|
x: volumeBar.leftPadding
|
||||||
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
||||||
implicitWidth: layout.width / 11
|
implicitWidth: layout.width / 11
|
||||||
implicitHeight: appearance.themeName == "Niconico" ? layout.height / 8 : layout.height / 10
|
implicitHeight: appearance.themeName == "Niconico" ? layout.height / 6 : layout.height / 10
|
||||||
width: volumeBar.availableWidth
|
width: volumeBar.availableWidth
|
||||||
height: implicitHeight
|
height: implicitHeight
|
||||||
color: getAppearanceValueForTheme(appearance.themeName,
|
color: getAppearanceValueForTheme(appearance.themeName,
|
||||||
|
|
|
@ -45,8 +45,7 @@ Item {
|
||||||
anchors.left: volumeButton.left
|
anchors.left: volumeButton.left
|
||||||
anchors.right: volumeSlider.right
|
anchors.right: volumeSlider.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: volumeButton.width
|
width: volumeButton.width + (volumeSlider.visible ? volumeSlider.width : 0)
|
||||||
+ (volumeSlider.visible ? volumeSlider.width : 0)
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
acceptedButtons: Qt.NoButton
|
acceptedButtons: Qt.NoButton
|
||||||
|
|
|
@ -25,6 +25,15 @@ getPlatformName()
|
||||||
qobject_cast<QGuiApplication*>(QCoreApplication::instance());
|
qobject_cast<QGuiApplication*>(QCoreApplication::instance());
|
||||||
return qapp->platformName();
|
return qapp->platformName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
launchAboutQt()
|
||||||
|
{
|
||||||
|
QApplication* qapp =
|
||||||
|
qobject_cast<QApplication*>(QCoreApplication::instance());
|
||||||
|
qapp->aboutQt();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
updateAppImage()
|
updateAppImage()
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,8 +15,12 @@ void
|
||||||
AlwaysOnTop(WId wid, bool on);
|
AlwaysOnTop(WId wid, bool on);
|
||||||
void
|
void
|
||||||
updateAppImage();
|
updateAppImage();
|
||||||
|
int
|
||||||
|
fast_mod(const int input, const int ceil);
|
||||||
QString
|
QString
|
||||||
createTimestamp(int seconds);
|
createTimestamp(int seconds);
|
||||||
|
void
|
||||||
|
launchAboutQt();
|
||||||
}
|
}
|
||||||
|
|
||||||
class UtilsClass : public QObject
|
class UtilsClass : public QObject
|
||||||
|
@ -26,6 +30,8 @@ public slots:
|
||||||
void SetDPMS(bool on) { Utils::SetDPMS(on); };
|
void SetDPMS(bool on) { Utils::SetDPMS(on); };
|
||||||
void AlwaysOnTop(WId wid, bool on) { Utils::AlwaysOnTop(wid, on); };
|
void AlwaysOnTop(WId wid, bool on) { Utils::AlwaysOnTop(wid, on); };
|
||||||
void updateAppImage() { Utils::updateAppImage(); };
|
void updateAppImage() { Utils::updateAppImage(); };
|
||||||
|
void launchAboutQt() { Utils::launchAboutQt(); };
|
||||||
|
|
||||||
QString createTimestamp(int seconds)
|
QString createTimestamp(int seconds)
|
||||||
{
|
{
|
||||||
return Utils::createTimestamp(seconds);
|
return Utils::createTimestamp(seconds);
|
||||||
|
|
Loading…
Reference in a new issue