1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-06 19:12:30 +01:00

Merge branch 'qt6-kde' into 'master'

Add basic kde wallpaper support via Websockets

See merge request kelteseth/ScreenPlay!91
This commit is contained in:
Elias Steurer 2021-12-31 13:14:49 +00:00
commit d9ad963a81
37 changed files with 677 additions and 184 deletions

1
.gitignore vendored
View File

@ -95,3 +95,4 @@ _deps
/Common/ffmpeg/*
/Docs/html/screenplay.index
/ContentBuilder/**
/aqtinstall.log

View File

@ -2,7 +2,6 @@ stages:
- check
- build
- test
- benchmark
check:
stage: check

View File

@ -1,7 +1,7 @@
project(CMake)
set(FILES # cmake-format: sortable
QtUpdateTranslations.cmake)
CopyRecursive.cmake QtUpdateTranslations.cmake)
add_custom_target(
${PROJECT_NAME}

29
CMake/CopyRecursive.cmake Normal file
View File

@ -0,0 +1,29 @@
# Copies all files with the same hierarchy (folder)
# via configure_file but only when the file content is different:
#
# copy_recursive(${SOURCE_PATH} ${DESTINATION_PATH} ${REGEX})
#
# If you want to copy all files simply set the parameter to: "*"
# Example:
#
# include(CopyRecursive)
# copy_recursive(${CMAKE_CURRENT_SOURCE_DIR}/kde/ScreenPlay ${CMAKE_BINARY_DIR}/bin/kde/ScreenPlay "*")
#
function(copy_recursive SOURCE_PATH DESTINATION_PATH REGEX)
file(GLOB_RECURSE
FILES
${SOURCE_PATH}
"${SOURCE_PATH}/${REGEX}")
foreach(file ${FILES})
# To recreate the same folder structure we first need to read the base folder
file(RELATIVE_PATH RELATIVE_FILE_PATH ${SOURCE_PATH} ${file})
get_filename_component(FOLDER ${RELATIVE_FILE_PATH} DIRECTORY ${SOURCE_PATH})
file(MAKE_DIRECTORY ${DESTINATION_PATH}/${FOLDER} )
message(STATUS "${file} - ${DESTINATION_PATH}/${RELATIVE_FILE_PATH}")
configure_file(${file} "${DESTINATION_PATH}/${RELATIVE_FILE_PATH}" COPYONLY)
endforeach()
endfunction()

View File

@ -1,6 +1,11 @@
cmake_minimum_required(VERSION 3.16.0)
project(ScreenPlay LANGUAGES CXX)
project(
ScreenPlay
VERSION 0.15.0
DESCRIPTION "Modern, Cross Plattform, Live Wallpaper, Widgets and AppDrawer!"
HOMEPAGE_URL "https://screen-play.app/"
LANGUAGES CXX)
# This sets cmake to compile all dlls into the main directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@ -8,7 +13,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
option(SCREENPLAY_STEAM "For FOSS distribution so we do not bundle proprietary code." ON)
option(TESTS_ENABLED OFF)
option(SCREENPLAY_TESTS "Enables UI tests." OFF)
option(SCREENPLAY_CREATE_INSTALLER "Indicates whether an installer via the Qt Installer Framework is created." OFF)
# Add our *.cmake diretory to the CMAKE_MODULE_PATH, so that our includes are found
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
@ -25,14 +31,13 @@ elseif(APPLE)
set(VCPKG_ARCH "x64-osx")
endif()
if(${TESTS_ENABLED})
if(${SCREENPLAY_TESTS})
enable_testing()
endif()
set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlay-vcpkg")
set(VCPKG_INSTALLED_PATH "${VCPKG_PATH}/installed/${VCPKG_ARCH}")
find_package(Git REQUIRED)
if(WIN32)
set(date_command "CMD")
@ -74,6 +79,7 @@ add_subdirectory(ScreenPlayWallpaper)
add_subdirectory(ScreenPlayWidget)
add_subdirectory(ScreenPlayUtil)
add_subdirectory(CMake)
add_subdirectory(Tools)
if(${SCREENPLAY_STEAM})
add_subdirectory(ScreenPlayWorkshop)
@ -86,13 +92,69 @@ if(WIN32)
add_subdirectory(ScreenPlaySysInfo)
endif()
message(STATUS "[DEFINE] SOURCE_DIR = ${SOURCE_DIR}")
message(STATUS "[DEFINE] SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "[DEFINE] BUILD_DATE = ${BUILD_DATE}")
message(STATUS "[DEFINE] BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
message(STATUS "[DEFINE] GIT_COMMIT_HASH = ${GIT_COMMIT_HASH}")
message(STATUS "[OPTION] SCREENPLAY_CREATE_INSTALLER = ${SCREENPLAY_CREATE_INSTALLER}")
message(STATUS "[OPTION] SCREENPLAY_STEAM = ${SCREENPLAY_STEAM}")
message(STATUS "[OPTION] TESTS_ENABLED = ${TESTS_ENABLED}")
message(STATUS "[OPTION] SCREENPLAY_TESTS = ${SCREENPLAY_TESTS}")
message(STATUS "[PROJECT] CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}")
message(STATUS "[PROJECT] VCPKG_PATH = ${VCPKG_PATH}")
message(STATUS "[PROJECT] VCPKG_ARCH = ${VCPKG_ARCH}")
message(STATUS "[PROJECT] CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
message(STATUS "[PROJECT] VCPKG_TARGET_TRIPLET = ${VCPKG_TARGET_TRIPLET}")
message(STATUS "[PROJECT] CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
message(STATUS "[PROJECT] CPACK_GENERATOR = ${CPACK_GENERATOR}")
if(${SCREENPLAY_CREATE_INSTALLER})
# Hardcoded Qt paths that are used by the QtMaintanance tool for now...
if(WIN32)
set(CPACK_IFW_ROOT "C:/Qt/Tools/QtInstallerFramework/4.2")
elseif(UNIX AND NOT APPLE)
set(CPACK_IFW_ROOT "$ENV{HOME}/Qt/Tools/QtInstallerFramework/4.2")
endif()
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-Installer")
set(CPACK_PACKAGE_VENDOR "Elias Steurer")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}")
# Ensures that contents written to the CPack configuration files is escaped properly.
set(CPACK_VERBATIM_VARIABLES TRUE)
set(CPACK_GENERATOR IFW)
set(CPACK_IFW_PACKAGE_START_MENU_DIRECTORY "") # empty => default is install to top-level (?)
set(CPACK_IFW_TARGET_DIRECTORY "@HomeDir@/Apps/${CMAKE_PROJECT_NAME}")
set(CPACK_IFW_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/ScreenPlay/assets/icons/app.ico")
set(CPACK_IFW_PACKAGE_WINDOW_ICON "${CMAKE_CURRENT_SOURCE_DIR}/ScreenPlay/assets/icons/app.ico")
set(CPACK_IFW_PACKAGE_CONTROL_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/Tools/Installer/installscript.qs")
set(CPACK_COMPONENTS_GROUPING IGNORE)
set(CPACK_IFW_PACKAGE_GROUP ScreenPlay)
set(CPACK_IFW_VERBOSE ON)
include(CPack)
include(CPackIFW)
# Install all files from /bin
install(
DIRECTORY "${CMAKE_BINARY_DIR}/bin/"
COMPONENT ScreenPlay
DESTINATION ".")
cpack_add_component(
ScreenPlay
DISPLAY_NAME "ScreenPlay"
DESCRIPTION "This installs ScreenPlay.")
cpack_ifw_configure_component(
ScreenPlayApp FORCED_INSTALLATION
NAME "ScreenPlay"
VERSION ${PROJECT_VERSION} # Version of component
DESCRIPTION "Welcome to the K3000 installer."
# Gets ignored and I do not know why
SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/Tools/Installer/installscript.qs"
CHECKABLE FALSE)
endif()

View File

@ -31,7 +31,7 @@ py setup.py
Append this:
``` bash
CMAKE_TOOLCHAIN_FILE:STRING=%{CurrentProject:Path}/../ScreenPlay-vcpkg/vcpkg/scripts/buildsystems/vcpkg.cmake
CMAKE_TOOLCHAIN_FILE:STRING=%{CurrentProject:Path}/../ScreenPlay-vcpkg/scripts/buildsystems/vcpkg.cmake
# Only _one_ of these lines that match your OS:
VCPKG_TARGET_TRIPLET:STRING=x64-windows
VCPKG_TARGET_TRIPLET:STRING=x64-linux
@ -67,7 +67,7 @@ VCPKG_TARGET_TRIPLET:STRING=x64-osx
1. Install dependencies for your distro:
``` bash
# Debian/Ubuntu
sudo apt install build-essential libgl1-mesa-dev lld ninja-build cmake
sudo apt install build-essential libgl1-mesa-dev lld ninja-build cmake git curl pkg-config ffmpeg qml-module-qt-websockets qtwebengine5-*
# Fedora/RHEL/CentOS (yum)
sudo yum groupinstall "C Development Tools and Libraries"

View File

@ -160,7 +160,6 @@ qt_update_translations("${CMAKE_CURRENT_SOURCE_DIR}/qml" "${L10N_LIST}")
# Needed on macos
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(benchmark CONFIG REQUIRED)
find_package(doctest CONFIG REQUIRED)
# CURL must be included before sentry because sentry needs the module and does not include it itself on macos...
@ -183,14 +182,10 @@ qt_add_big_resources(FONTS fonts.qrc)
add_library(ScreenPlayLib ${SOURCES} ${HEADER} ${RESOURCES} ${FONTS})
target_include_directories(ScreenPlayLib PUBLIC ./ src/)
target_link_libraries(
ScreenPlayLib
PUBLIC ScreenPlaySDK
ScreenPlayUtil
benchmark::benchmark
benchmark::benchmark_main
doctest::doctest
sentry::sentry
Threads::Threads

View File

@ -1,6 +1,8 @@
#include "app.h"
#include "steam/steam_qt_enums_generated.h"
#include <QProcessEnvironment>
#include <QVersionNumber>
namespace ScreenPlay {
/*!
@ -98,7 +100,6 @@ App::App()
qRegisterMetaType<MonitorListModel*>();
qRegisterMetaType<ProfileListModel*>();
// TODO: This is a workaround because I don't know how to
// init this in the ScreenPlayWorkshop plugin.
// Move to workshop plugin.
@ -211,6 +212,10 @@ void App::init()
qmlRegisterSingletonInstance("ScreenPlay", 1, 0, "ScreenPlay", this);
QGuiApplication::instance()->addLibraryPath(QGuiApplication::instance()->applicationDirPath());
if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::KDE) {
setupKDE();
}
m_mainWindowEngine->load(QUrl(QStringLiteral("qrc:/ScreenPlay/main.qml")));
// Must be called last to display a error message on startup by the qml engine
@ -232,4 +237,72 @@ void App::exit()
QApplication::instance()->quit();
}
/*!
\brief
*/
bool App::setupKDE()
{
QProcessEnvironment env;
qInfo() << qgetenv("KDE_FULL_SESSION");
qInfo() << qgetenv("DESKTOP_SESSION");
qInfo() << qgetenv("XDG_CURRENT_DESKTOP");
QProcess plasmaShellVersionProcess;
plasmaShellVersionProcess.start("plasmashell", { "--version" });
plasmaShellVersionProcess.waitForFinished();
QString versionOut = plasmaShellVersionProcess.readAll();
if (!versionOut.contains("plasmashell ")) {
qWarning() << "Unable to read plasma shell version";
return false;
}
const QString kdeWallpaperPath = QDir(QDir::homePath() + "/.local/share/plasma/wallpapers/ScreenPlay/").canonicalPath();
const QFileInfo installedWallpaperMetadata(kdeWallpaperPath + "/metadata.desktop");
const QString appKdeWallapperPath = QGuiApplication::instance()->applicationDirPath() + "/kde";
const QFileInfo currentWallpaperMetadata(appKdeWallapperPath + "/ScreenPlay/metadata.desktop");
if (!installedWallpaperMetadata.exists()) {
process.setWorkingDirectory(appKdeWallapperPath);
process.start("plasmapkg2", { "--install", "ScreenPlay" });
process.waitForFinished();
process.terminate();
qInfo() << "Install ScreenPlay KDE Wallpaper";
} else {
QSettings installedWallpaperSettings(installedWallpaperMetadata.absoluteFilePath(), QSettings::Format::IniFormat);
installedWallpaperSettings.beginGroup("Desktop Entry");
const QString installedWallpaperVersion = installedWallpaperSettings.value("Version").toString();
installedWallpaperSettings.endGroup();
const QVersionNumber installedVersionNumber = QVersionNumber::fromString(installedWallpaperVersion);
QSettings currentWallpaperSettings(currentWallpaperMetadata.absoluteFilePath(), QSettings::Format::IniFormat);
currentWallpaperSettings.beginGroup("Desktop Entry");
const QString currentWallpaperVersion = currentWallpaperSettings.value("Version").toString();
currentWallpaperSettings.endGroup();
const QVersionNumber currentVersionNumber = QVersionNumber::fromString(installedWallpaperVersion);
if (installedVersionNumber.isNull() || currentVersionNumber.isNull()) {
qCritical() << "Unable to parse version number from:" << currentWallpaperVersion << installedWallpaperVersion;
return false;
}
if (installedVersionNumber <= currentVersionNumber)
return true;
qInfo() << "Upgrade ScreenPlay KDE Wallpaper";
process.setWorkingDirectory(appKdeWallapperPath);
process.start("plasmapkg2", { "--upgrade", "ScreenPlay" });
process.waitForFinished();
process.terminate();
qInfo() << process.readAllStandardError() << process.readAllStandardOutput();
}
qInfo() << "Restart KDE ";
process.start("kquitapp5", { "plasmashell" });
process.waitForFinished();
process.terminate();
qInfo() << process.readAllStandardError() << process.readAllStandardOutput();
process.startDetached("kstart5", { "plasmashell" });
qInfo() << process.readAllStandardError() << process.readAllStandardOutput();
return true;
}
}

View File

@ -63,7 +63,6 @@
#include <memory>
#include <sentry.h>
namespace ScreenPlay {
class App : public QObject {
@ -216,6 +215,9 @@ public slots:
emit wizardsChanged(m_wizards.get());
}
private:
bool setupKDE();
private:
QNetworkAccessManager m_networkAccessManager;
QElapsedTimer m_continuousIntegrationMetricsTimer;
@ -233,5 +235,6 @@ private:
std::shared_ptr<MonitorListModel> m_monitorListModel;
std::shared_ptr<ProfileListModel> m_profileListModel;
std::shared_ptr<InstalledListFilter> m_installedListFilter;
QProcess process;
};
}

View File

@ -125,7 +125,7 @@ Item {
id: folderDialogSaveLocation
folder: ScreenPlay.globalVariables.localStoragePath
onAccepted: {
ScreenPlay.settings.setLocalStoragePath(folderDialogSaveLocation.fileUrls[0]);
ScreenPlay.settings.setLocalStoragePath(folderDialogSaveLocation.currentFolder);
}
}

View File

@ -53,8 +53,15 @@ CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& ex
void CreateImportVideo::setupFFMPEG()
{
#ifdef Q_OS_LINUX
// Use system ffmpeg
m_ffprobeExecutable = "ffprobe";
m_ffmpegExecutable = "ffmpeg";
#else
m_ffprobeExecutable = QApplication::applicationDirPath() + "/ffprobe" + ScreenPlayUtil::executableBinEnding();
m_ffmpegExecutable = QApplication::applicationDirPath() + "/ffmpeg" + ScreenPlayUtil::executableBinEnding();
#endif
if (!QFileInfo::exists(m_ffprobeExecutable)) {
qFatal("FFPROBE executable not found!");
@ -126,10 +133,9 @@ bool CreateImportVideo::createWallpaperInfo()
}
if (obj->empty()) {
qWarning() << "Error! File could not be parsed.";
qCritical() << "Error! File could not be parsed.";
emit processOutput("Error! File could not be parsed.");
emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError);
return false;
}

View File

@ -83,10 +83,21 @@ void ScreenPlayManager::init(
if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::KDE) {
m_websocketServer = std::make_unique<QWebSocketServer>(QStringLiteral("ScreenPlayWebSocket"), QWebSocketServer::SslMode::NonSecureMode);
m_websocketServer->listen(QHostAddress::Any, m_webSocketPort);
const bool success = m_websocketServer->listen(QHostAddress::Any, m_webSocketPort);
qInfo() << "Open Websocket:" << success << "port:" << m_webSocketPort;
QObject::connect(m_websocketServer.get(), &QWebSocketServer::newConnection, this, [this]() {
qInfo() << "New Websocket Connection";
auto* socket = m_websocketServer->nextPendingConnection();
QObject::connect(socket, &QWebSocket::textMessageReceived, this, [this](const QString& message) {
qInfo() << "Message:" << message;
});
QObject::connect(socket, &QWebSocket::disconnected, this, [this, socket]() {
m_connections.removeOne(socket);
qInfo() << "Disconnected connection count: " << m_connections.count();
});
m_connections.push_back(socket);
// socket->flush();
});
}
@ -116,6 +127,7 @@ bool ScreenPlayManager::createWallpaper(
const QJsonObject& properties,
const bool saveToProfilesConfigFile)
{
const int screenCount = QGuiApplication::screens().count();
QJsonArray monitors;
@ -137,6 +149,22 @@ bool ScreenPlayManager::createWallpaper(
const QString path = QUrl::fromUserInput(absoluteStoragePath).toLocalFile();
const QString appID = ScreenPlayUtil::generateRandomString();
if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::KDE) {
if (m_connections.empty())
return false;
QJsonObject msg;
msg.insert("command", "replace");
msg.insert("absolutePath", path);
msg.insert("type", static_cast<int>(type));
msg.insert("fillMode", static_cast<int>(fillMode));
msg.insert("volume", volume);
msg.insert("file", file);
m_connections.first()->sendTextMessage(QJsonDocument(msg).toJson());
m_connections.first()->flush();
}
// Only support remove wallpaper that spans over 1 monitor
if (monitorIndex.length() == 1) {
int i = 0;
@ -172,14 +200,16 @@ bool ScreenPlayManager::createWallpaper(
fillMode,
type,
properties,
m_settings->checkWallpaperVisible());
m_settings);
QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::requestSave, this, &ScreenPlayManager::requestSaveProfiles);
QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::requestClose, this, &ScreenPlayManager::removeWallpaper);
QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::error, this, &ScreenPlayManager::displayErrorPopup);
if (m_settings->desktopEnvironment() != Settings::DesktopEnvironment::KDE) {
if (!wallpaper->start()) {
return false;
}
}
m_screenPlayWallpapers.append(wallpaper);
m_monitorListModel->setWallpaperMonitor(wallpaper, monitorIndex);
increaseActiveWallpaperCounter();
@ -254,6 +284,15 @@ bool ScreenPlayManager::removeAllWallpapers()
return false;
}
}
if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::KDE) {
for (auto& connection : m_connections) {
QJsonObject obj;
obj.insert("command", "quit");
connection->sendTextMessage(QJsonDocument(obj).toJson(QJsonDocument::Compact));
connection->flush();
connection->close();
}
}
emit requestSaveProfiles();
@ -445,6 +484,8 @@ bool ScreenPlayManager::removeWallpaper(const QString& appID)
return false;
}
if (m_settings->desktopEnvironment() == Settings::DesktopEnvironment::Windows || m_settings->desktopEnvironment() == Settings::DesktopEnvironment::OSX)
wallpaper->messageKDECloseWallpaper();
qInfo() << "Remove wallpaper " << wallpaper->file() << "at monitor " << wallpaper->screenNumber();

View File

@ -183,6 +183,7 @@ private:
std::shared_ptr<Settings> m_settings;
std::unique_ptr<QLocalServer> m_server;
std::unique_ptr<QWebSocketServer> m_websocketServer;
QVector<QWebSocket*> m_connections;
QVector<std::shared_ptr<ScreenPlayWallpaper>> m_screenPlayWallpapers;
QVector<std::shared_ptr<ScreenPlayWidget>> m_screenPlayWidgets;

View File

@ -24,7 +24,7 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector<int>& screenNumber,
const FillMode::FillMode fillMode,
const InstalledType::InstalledType type,
const QJsonObject& properties,
const bool checkWallpaperVisible,
const std::shared_ptr<Settings>& settings,
QObject* parent)
: QObject(parent)
, m_globalVariables { globalVariables }
@ -37,6 +37,7 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector<int>& screenNumber,
, m_file { file }
, m_volume { volume }
, m_playbackRate { playbackRate }
, m_settings { settings }
{
QJsonObject projectSettingsListModelProperties;
@ -81,7 +82,7 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector<int>& screenNumber,
QString::number(static_cast<double>(volume)),
QVariant::fromValue(fillMode).toString(),
QVariant::fromValue(type).toString(),
QString::number(checkWallpaperVisible),
QString::number(m_settings->checkWallpaperVisible()),
// Fixes issue 84 media key overlay
" --disable-features=HardwareMediaKeyHandling"
};
@ -145,10 +146,9 @@ void ScreenPlayWallpaper::close()
return;
}
if(m_connection->close()){
if (m_connection->close()) {
m_isExiting = true;
}
}
/*!
\brief Prints the exit code if != 0.
@ -175,7 +175,7 @@ void ScreenPlayWallpaper::processError(QProcess::ProcessError error)
*/
bool ScreenPlayWallpaper::setWallpaperValue(const QString& key, const QString& value, const bool save)
{
if(m_isExiting)
if (m_isExiting)
return false;
if (!m_connection) {
@ -249,7 +249,7 @@ void ScreenPlayWallpaper::replace(
const bool checkWallpaperVisible)
{
if(m_isExiting)
if (m_isExiting)
return;
if (!m_connection) {

View File

@ -44,6 +44,7 @@
#include "globalvariables.h"
#include "projectsettingslistmodel.h"
#include "sdkconnection.h"
#include "settings.h"
#include "util.h"
namespace ScreenPlay {
@ -78,10 +79,12 @@ public:
const QString& absolutePath,
const QString& previewImage,
const QString& file,
const float volume, const float playbackRate,
const float volume,
const float playbackRate,
const FillMode::FillMode fillMode,
const InstalledType::InstalledType type, const QJsonObject& properties,
const bool checkWallpaperVisible,
const InstalledType::InstalledType type,
const QJsonObject& properties,
const std::shared_ptr<Settings>& settings,
QObject* parent = nullptr);
bool start();
@ -124,6 +127,7 @@ signals:
void volumeChanged(float volume);
void isLoopingChanged(bool isLooping);
void playbackRateChanged(float playbackRate);
void messageKDECloseWallpaper();
void requestSave();
void requestClose(const QString& appID);
@ -241,6 +245,7 @@ public slots:
private:
const std::shared_ptr<GlobalVariables> m_globalVariables;
std::unique_ptr<SDKConnection> m_connection;
const std::shared_ptr<Settings> m_settings;
ProjectSettingsListModel m_projectSettingsListModel;
QVector<int> m_screenNumber;

View File

@ -108,7 +108,7 @@ bool ScreenPlay::SDKConnection::sendMessage(const QByteArray& message)
*/
bool ScreenPlay::SDKConnection::close()
{
if (!m_socket){
if (!m_socket) {
qWarning() << "Cannot close invalid socket.";
return false;
}

View File

@ -34,10 +34,14 @@ set(HEADER
add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADER})
qt_add_qml_module(${PROJECT_NAME}
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/SysInfo
URI ${PROJECT_NAME}
VERSION 1.0)
qt_add_qml_module(
${PROJECT_NAME}
OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/bin/SysInfo
URI
${PROJECT_NAME}
VERSION
1.0)
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)

View File

@ -12,8 +12,10 @@ find_package(
set(SOURCES # cmake-format: sortable
src/util.cpp src/contenttypes.cpp inc/public/ScreenPlayUtil/httpfileserver.cpp)
set(HEADER # cmake-format: sortable
inc/public/ScreenPlayUtil/util.h inc/public/ScreenPlayUtil/httpfileserver.h inc/public/ScreenPlayUtil/contenttypes.h inc/public/ScreenPlayUtil/projectfile.h)
set(HEADER
# cmake-format: sortable
inc/public/ScreenPlayUtil/util.h inc/public/ScreenPlayUtil/httpfileserver.h inc/public/ScreenPlayUtil/contenttypes.h
inc/public/ScreenPlayUtil/projectfile.h)
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADER})

View File

@ -68,6 +68,11 @@ target_link_libraries(
Qt6::WebEngineCore
Qt6::WebEngineQuick)
if(UNIX AND NOT APPLE)
include(CopyRecursive)
copy_recursive(${CMAKE_CURRENT_SOURCE_DIR}/kde/ScreenPlay ${CMAKE_BINARY_DIR}/bin/kde/ScreenPlay "*")
endif()
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)
target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Cocoa")

View File

@ -6,6 +6,8 @@ Will not work because KDE uses the kpluginindex.json (that is actually a bz2 fil
#### Installation
```
sudo apt install qml-module-qt-websockets qtwebengine5-*
plasmapkg2 --install ScreenPlay
```
@ -21,3 +23,6 @@ Because Wallpaper and Widgets are already a different application we can extend
1. Open Desktop Settings
- Select Wallpaper type ScreenPlay
```
plasmapkg2 --upgrade ScreenPlay ; kquitapp5 plasmashell; kstart5 plasmashell
```

View File

@ -0,0 +1,74 @@
import QtQuick 2.15
Rectangle {
anchors.fill: parent
color: "black"
Rectangle {
id: toBeCreated
anchors.fill: parent
color: "black"
opacity: 0
Text {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
anchors.centerIn: parent
text: qsTr("Please start ScreenPlay before launching the wallpaper")
color: "White"
font.pixelSize: 50
}
OpacityAnimator on opacity{
id: createAnimation
from: 0;
to: 1;
duration: 1000
onRunningChanged: {
if(!running){
toBeDeleted.opacity = 1
toBeCreated.opacity = 0
destroyAnimation.start()
}
}
}
Component.onCompleted: {
createAnimation.start()
}
}
Rectangle {
opacity: 0
id: toBeDeleted
anchors.fill: parent
color: "black"
Text {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
anchors.centerIn: parent
text: qsTr("Please start ScreenPlay before launching the wallpaper")
color: "White"
font.pixelSize: 50
}
OpacityAnimator on opacity{
id: destroyAnimation
from: 1;
to: 0;
duration: 1000
running: false
onRunningChanged: {
if(!running){
toBeDeleted.opacity = 0
toBeCreated.opacity = 0
createAnimation.start()
}
}
}
}
}

View File

@ -0,0 +1,92 @@
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtWebSockets 1.1
import QtWebEngine 1.8
import QtMultimedia 5.12
import Qt.labs.settings 1.1
Rectangle {
id: root
color: "black"
anchors.fill: parent
property string fullContentPath
property real volume: 1
property string fillMode: "Cover"
property string type
property string projectSourceFileAbsolute
property bool loops: true
function stop(){
player1.stop()
player2.stop()
videoOutput1.visible = false
videoOutput2.visible = false
root.enabled = false
}
function play(){
root.enabled = true
videoOutput2.visible = false
videoOutput1.visible = true
//if(wallpaper.configuration.DualPlayback){
player2.source = root.projectSourceFileAbsolute
player2.play()
player2.pause()
//}
player1.play()
}
MediaPlayer {
id: player1
volume: root.volume
source: root.projectSourceFileAbsolute
onStopped: {
if(!root.enabled)
return
videoOutput1.visible = false
videoOutput2.visible = true
if(player2.source !== root.projectSourceFileAbsolute){
player2.source = root.projectSourceFileAbsolute
}
player1.play()
player1.pause()
player2.play()
}
}
MediaPlayer {
id: player2
volume: root.volume
onStopped: {
if(!root.enabled)
return
videoOutput2.visible = false
videoOutput1.visible = true
player2.play()
player2.pause()
player1.play()
}
}
VideoOutput {
id: videoOutput1
fillMode: VideoOutput.PreserveAspectCrop
anchors.fill: parent
source: player1
}
VideoOutput {
id: videoOutput2
fillMode: VideoOutput.PreserveAspectCrop
anchors.fill: parent
source: player2
}
}

View File

@ -0,0 +1,42 @@
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtWebSockets 1.1
import QtWebEngine 1.8
import QtMultimedia 5.12
Rectangle {
id: container
anchors.fill: parent
Loader {
id: wp
anchors.fill: parent
source: "Wallpaper.qml"
property bool connected: false
Timer {
id: connectTimer
interval: 1000
running: true
repeat: true
onTriggered: {
if(!wp.connected){
console.log("not connected")
wp.source = ""
wp.source = "Wallpaper.qml"
} else {
console.log("connected")
screensaver.visible = false
connectTimer.stop()
}
}
}
}
Loader {
anchors.fill: parent
id: screensaver
source: "WaitingForScreenplay.qml"
}
}

View File

@ -1,13 +1,14 @@
import QtQuick
import QtQuick.Controls as QQC
import QtQuick.Window
import Qt5Compat.GraphicalEffects
import QtQuick 2.11
import QtQuick.Controls 2.4 as QQC
import QtQuick.Window 2.0
import QtGraphicalEffects 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.wallpapers.image 2.0 as Wallpaper
import org.kde.kcm 1.1 as KCM
import org.kde.kirigami 2.4 as Kirigami
import org.kde.newstuff 1.1 as NewStuff
Column {
id: root

View File

@ -1,100 +1,115 @@
import QtQuick
import Qt5Compat.GraphicalEffects
import QtQuick.Window
import Qt.WebSockets 1.15
import QtWebEngine
import QtQuick 2.0
import QtQuick.Controls 2.12
import QtWebSockets 1.1
import QtWebEngine 1.8
import QtMultimedia 5.12
import Qt.labs.settings 1.1
Rectangle {
id: root
id:root
color:"orange"
property bool connected: false
property string fullContentPath
property real volume: 1
property string fillMode: "Cover"
property string type
function getSetVideoCommand() {
// TODO 30:
// Currently wont work. Commit anyways til QtCreator and Qt work with js template literals
var src = "";
src += "var videoPlayer = document.getElementById('videoPlayer');";
src += "var videoSource = document.getElementById('videoSource');";
src += "videoSource.src = '" + root.fullContentPath + "';";
src += "videoPlayer.load();";
src += "videoPlayer.volume = " + root.volume + ";";
src += "videoPlayer.setAttribute('style', 'object-fit :" + root.fillMode + ";');";
src += "videoPlayer.play();";
print(src);
return src;
Settings {
id:settings
}
color: "#333333"
Component.onCompleted: {
WebEngine.settings.localContentCanAccessFileUrls = true;
WebEngine.settings.localContentCanAccessRemoteUrls = true;
WebEngine.settings.allowRunningInsecureContent = true;
WebEngine.settings.accelerated2dCanvasEnabled = true;
WebEngine.settings.javascriptCanOpenWindows = false;
WebEngine.settings.showScrollBars = false;
WebEngine.settings.playbackRequiresUserGesture = false;
WebEngine.settings.focusOnNavigationEnabled = true;
wallpaper.projectSourceFileAbsolute = settings.value("SP_projectSourceFileAbsolute","NULL")
// if(root.projectSourceFileAbsolute === "NULL")
// return
wallpaper.type = settings.value("SP_type")
wallpaper.fillMode = settings.value("SP_fillMode")
wallpaper.volume = settings.value("SP_volume")
wallpaper.play()
}
Wallpaper {
id:wallpaper
anchors.fill: parent
// visible: root.connected
onFullContentPathChanged: settings.setValue("SP_fullContentPath",fullContentPath)
onVolumeChanged: settings.setValue("SP_volume",volume)
onFillModeChanged: settings.setValue("SP_fillMode",fillMode)
onTypeChanged: settings.setValue("SP_type",type)
onProjectSourceFileAbsoluteChanged: settings.setValue("SP_projectSourceFileAbsolute",projectSourceFileAbsolute)
onLoopsChanged: settings.setValue("SP_loops",loops)
}
Timer {
id:reconnectTimer
interval: 1000
running: true
repeat: true
onTriggered: {
if (socket.status === WebSocket.Open)
return
socket.active = false
socket.active = true
reconnectTimer.retryCounter += 1
}
property int retryCounter: 0
}
WebSocket {
id: socket
url: "ws://127.0.0.1:16395"
active: true
onStatusChanged: {
if (socket.status === WebSocket.Error)
messageBox.text = "Error: " + socket.errorString;
else if (socket.status === WebSocket.Open)
socket.sendTextMessage("Hello World");
else if (socket.status === WebSocket.Closed)
messageBox.text += "Socket closed";
if (socket.status === WebSocket.Open)
socket.sendTextMessage("Hello World from QML wallpaper")
}
onTextMessageReceived: {
var obj = JSON.parse(message);
onTextMessageReceived: (message)=> {
var obj = JSON.parse(message)
root.connected = true
txtCommand.text = obj.command
if (obj.command === "replace") {
root.type = obj.type;
root.fillMode = obj.fillMode;
root.volume = obj.volume;
root.fullContentPath = obj.absolutePath + "/" + obj.file;
webView.setVideo();
socket.sendTextMessage("replace")
wallpaper.type = obj.type
wallpaper.fillMode = obj.fillMode
wallpaper.volume = obj.volume
wallpaper.projectSourceFileAbsolute = "file://" + obj.absolutePath + "/" + obj.file
print("got: " + root.projectSourceFileAbsolute)
wallpaper.play()
return;
}
if(obj.command === "quit"){
wallpaper.stop()
}
}
}
WebEngineView {
id: webView
function setVideo() {
webView.runJavaScript(root.getSetVideoCommand());
// WaitingForScreenplay {
// anchors.fill: parent
// visible: !root.connected
// }
Column {
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
margins: 60
}
anchors.fill: parent
opacity: loadProgress === 100 ? 1 : 0
onLoadProgressChanged: {
if (loadProgress === 100)
setVideo();
}
}
Rectangle {
id: infoWrapper
width: 300
height: 200
opacity: 0
anchors.centerIn: parent
Text {
id: messageBox
text: qsTr("text")
anchors.centerIn: parent
id:txtCommand
color: "white"
}
Text {
color: "white"
text:wallpaper.type + wallpaper.projectSourceFileAbsolute
}
Text {
color: "white"
text:"Actitve: " +socket.active +" status: "+ socket.status + " reconnectTimer.retryCounter : "+ reconnectTimer.retryCounter
}
}
}
}

View File

@ -3,6 +3,7 @@ Encoding=UTF-8
Name=ScreenPlay
Keywords=ScreenPlay
Icon=preferences-desktop-wallpaper
Version=0.15.0
Type=Service

View File

@ -46,24 +46,9 @@ LinuxWindow::LinuxWindow(
setHeight(m_window.height());
m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
m_window.rootContext()->setContextProperty("window", this);
//m_window.rootContext()->setContextProperty("desktopProperties", &m_windowsDesktopProperties);
// Instead of setting "renderType: Text.NativeRendering" every time
// we can set it here once :)
qmlRegisterSingletonInstance<LinuxWindow>("ScreenPlayWallpaper", 1, 0, "Wallpaper", this);
m_window.setTextRenderType(QQuickWindow::TextRenderType::NativeTextRendering);
m_window.setSource(QUrl("qrc:/mainWindow.qml"));
// WARNING: Setting Window flags must be called *here*!
Qt::WindowFlags flags = m_window.flags();
m_window.setFlags(flags | Qt::FramelessWindowHint | Qt::Desktop);
m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView);
m_window.rootContext()->setContextProperty("window", this);
// Instead of setting "renderType: Text.NativeRendering" every time
// we can set it here once :)
m_window.setTextRenderType(QQuickWindow::TextRenderType::NativeTextRendering);
m_window.setSource(QUrl("qrc:/Wallpaper.qml"));
m_window.setSource(QUrl("qrc:/ScreenPlayWallpaper/qml/Wallpaper.qml"));
}
void LinuxWindow::setupWallpaperForOneScreen(int activeScreen)

View File

@ -320,7 +320,7 @@ void WinWindow::setupWallpaperForAllScreens()
m_window.setHeight(rect.height());
m_window.setWidth(rect.width());
m_window.setY(offsetY);
m_window.setX(offsetX+1920);
m_window.setX(offsetX + 1920);
qInfo() << m_window.geometry();
}

View File

@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 20)
find_package(
Qt6
COMPONENTS Quick QML Widgets Gui
COMPONENTS Quick Widgets Gui
REQUIRED)
set(SOURCES
@ -58,10 +58,13 @@ qt_add_qml_module(
${PROJECT_NAME}
OUTPUT_DIRECTORY
${WORKSHOP_PLUGIN_DIR}
URI "Workshop"
SOURCES ${SOURCES} ${HEADER}
VERSION 1.0)
URI
"Workshop"
SOURCES
${SOURCES}
${HEADER}
VERSION
1.0)
if(${SCREENPLAY_STEAM})
if(APPLE)
@ -71,8 +74,8 @@ if(${SCREENPLAY_STEAM})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/steam_appid.txt ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/ COPYONLY)
configure_file(${STEAM_BIN} ${WORKSHOP_PLUGIN_DIR} COPYONLY)
set_target_properties(${PROJECT_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/Workshop)
set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/Workshop)
else()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/steam_appid.txt ${CMAKE_BINARY_DIR}/bin/steam_appid.txt COPYONLY)
configure_file(${STEAM_BIN} ${CMAKE_BINARY_DIR}/bin/ COPYONLY)

View File

@ -49,9 +49,7 @@ set(HEADER
public/steam/steamnetworkingtypes.h
public/steam/steamps3params.h
public/steam/steamtypes.h
public/steam/steamuniverse.h
)
public/steam/steamuniverse.h)
if(${SCREENPLAY_STEAM})
add_library(${PROJECT_NAME} STATIC ${HEADER})
@ -59,8 +57,8 @@ if(${SCREENPLAY_STEAM})
target_link_libraries(${PROJECT_NAME})
endif()
# We allaways need the generated enums as a workaround to register these enums in app.cpp.
# Registering in the ScreenPlayWorkshop plugin does not work for some reason.
# We allaways need the generated enums as a workaround to register these enums in app.cpp. Registering in the ScreenPlayWorkshop plugin does
# not work for some reason.
add_library(SteamSDKQtEnums STATIC public/steam/steam_qt_enums_generated.h)
target_include_directories(SteamSDKQtEnums PUBLIC public/)
target_link_libraries(SteamSDKQtEnums PRIVATE Qt6::Core)

View File

@ -88,7 +88,7 @@ void InstalledListModel::append(const QJsonObject& obj, const QString& folderNam
void InstalledListModel::loadInstalledContent()
{
if(m_loadContentFutureWatcher.isRunning())
if (m_loadContentFutureWatcher.isRunning())
return;
m_loadContentFuture = QtConcurrent::run([this]() {

11
Tools/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
project(Tools LANGUAGES CXX)
file(GLOB PYTHON *.py)
set(FILES # cmake-format: sortable
Installer/package.xml Installer/installscript.qs)
add_custom_target(
${PROJECT_NAME}
SOURCES ${FILES} ${PYTHON}
COMMENT "Dummy target to list these files in the IDE")

View File

@ -0,0 +1,14 @@
function Component()
{
// Install to @RootDir@ instead of @HomeDir@ on Windows
if (installer.value("os") === "win") {
var homeDir = installer.value("HomeDir");
var targetDir = installer.value("TargetDir").replace(homeDir, "@RootDir@");
installer.setValue("TargetDir", targetDir);
}
// do not show component selection page
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
// no startmenu entry so no need to ask where to create it
installer.setDefaultPageVisible(QInstaller.StartMenuSelection, false);
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<Package>
<DisplayName>Register a file extension</DisplayName>
<Description>Register a randomly generated file extension to open with notepad.exe</Description>
<Version>1.0.0-1</Version>
<ReleaseDate>2020-01-01</ReleaseDate>
<Default>true</Default>
<Script>installscript.qs</Script>
</Package>

View File

@ -40,16 +40,27 @@ parser.add_argument('-sign', action="store", dest="sign_build",
help="Enable if you want to sign the apps. This is macos only for now.")
parser.add_argument('-steam', action="store", dest="steam_build",
help="Enable if you want to build the Steam workshop plugin.")
parser.add_argument('-tests', action="store", dest="build_tests",
help="Build tests.")
parser.add_argument('-installer', action="store", dest="create_installer",
help="Create a installer.")
args = parser.parse_args()
if not args.build_type:
print("Build type argument is missing (release,debug). Example: python build.py -t release -steam=True")
sys.exit(1)
qt_version = "6.2.1"
qt_version = "6.2.2"
steam_build = "OFF"
build_tests = "OFF"
create_installer = "OFF"
if args.steam_build:
steam_build = "ON"
if args.build_tests:
build_tests = "ON"
if args.create_installer:
create_installer = "ON"
print("Starting build with type %s. Qt Version: %s" %
(args.build_type, qt_version))
@ -79,7 +90,7 @@ elif platform == "darwin":
deploy_command = "{prefix_path}/bin/macdeployqt {app}.app -qmldir=../../{app}/qml -executable={app}.app/Contents/MacOS/{app}"
cmake_target_triplet = "x64-osx"
elif platform == "linux":
deploy_command = "cqtdeployer -qmldir ../../{app}/qml -bin {app}"
deploy_command = "cqtdeployer -qmlDir ../../{app}/qml -bin {app}"
cmake_prefix_path = "~/Qt/" + qt_version + "/gcc_64"
cmake_target_triplet = "x64-linux"
@ -98,7 +109,6 @@ if os.path.isdir(build_folder):
print("Remove previous build folder: " + build_folder)
shutil.rmtree(build_folder)
os.mkdir(build_folder)
os.chdir(build_folder)
@ -107,8 +117,9 @@ cmake_configure_command = """cmake ../
-DCMAKE_BUILD_TYPE={type}
-DCMAKE_TOOLCHAIN_FILE={toolchain}
-DVCPKG_TARGET_TRIPLET={triplet}
-DTESTS_ENABLED=OFF
-DSCREENPLAY_STEAM={steam}
-DSCREENPLAY_TESTS={tests}
-DSCREENPLAY_CREATE_INSTALLER={installer}
-G "CodeBlocks - Ninja"
-B.
""".format(
@ -116,7 +127,10 @@ cmake_configure_command = """cmake ../
prefix_path=cmake_prefix_path,
triplet=cmake_target_triplet,
toolchain=cmake_toolchain_file,
steam=steam_build).replace("\n", "")
steam=steam_build,
tests = build_tests,
installer= create_installer
).replace("\n", "")
execute(cmake_configure_command)
execute("cmake --build . --target all")
@ -184,3 +198,7 @@ for filename in os.listdir(os.getcwd()):
full_file_path = os.path.join(os.getcwd(), filename)
print("Remove: %s" % full_file_path)
os.remove(full_file_path)
if args.create_installer:
os.chdir("..")
execute("cpack")

View File

@ -31,7 +31,7 @@ if __name__ == "__main__":
vcpkg_path = os.path.join(project_source_parent_path, "ScreenPlay-vcpkg")
print("vcpkg_path: ", vcpkg_path)
vcpkg_version = "9172179c513aa84308e48b8dd0e3df90acec7204" # Master 25.06.2021
vcpkg_version = "5ddd7f0" # Master 02.12.2021
print("Build vcpkg ", vcpkg_version)
execute("git fetch", vcpkg_path)
execute("git checkout {}".format(vcpkg_version), vcpkg_path)
@ -41,7 +41,6 @@ if __name__ == "__main__":
"curl",
"sentry-native",
"doctest",
"benchmark",
"cpp-httplib"
]