1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-22 10:42:29 +01:00

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	ScreenPlay/CMakeLists.txt
#	ScreenPlay/app.cpp
#	ScreenPlay/main.cpp
#	ScreenPlayWallpaper/CMakeLists.txt
This commit is contained in:
Elias Steurer 2021-06-25 12:31:55 +02:00
commit b70ba77714
34 changed files with 523 additions and 188 deletions

View File

@ -12,7 +12,7 @@ set(CMAKE_CXX_STANDARD 20)
if(WIN32)
set(VCPKG_ARCH "x64-windows")
elseif(UNIX)
elseif(UNIX AND NOT APPLE)
set(VCPKG_ARCH "x64-linux")
elseif(APPLE)
set(VCPKG_ARCH "x64-osx")
@ -78,3 +78,13 @@ add_subdirectory(ScreenPlayUtil)
if(WIN32)
add_subdirectory(ScreenPlaySysInfo)
endif()
#if(APPLE)
#add_custom_target(CopyDependencies DEPENDS ScreenPlay)
#add_custom_command(TARGET CopyDependencies POST_BUILD
# COMMAND "ScreenPlayWallpaper" -E copy_directory
# "$<TARGET_FILE:ScreenPlayWallpaper>"
# "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/$<TARGET_FILE_NAME:ScreenPlayWallpaper>/"
# COMMENT "Copying into ScreenPlay.app bundle")
#endif()

View File

@ -6,12 +6,12 @@ set(CMAKE_AUTOMOC ON)
find_package(
QT NAMES Qt6 Qt5
COMPONENTS Quick Widgets Gui LinguistTools WebSockets WebEngine QuickCompiler
COMPONENTS Quick Widgets Gui LinguistTools Svg WebSockets WebEngine QuickCompiler
REQUIRED)
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Quick Widgets Gui LinguistTools WebSockets WebEngine QuickCompiler
COMPONENTS Quick Widgets Gui LinguistTools Svg WebSockets WebEngine QuickCompiler
REQUIRED)
message(STATUS "[PROJECT] QT_VERSION_MAJOR = ${QT_VERSION_MAJOR}")
@ -20,9 +20,11 @@ find_package(OpenSSL REQUIRED)
find_package(benchmark CONFIG REQUIRED)
find_package(doctest CONFIG REQUIRED)
if(WIN32)
find_package(sentry CONFIG REQUIRED)
endif()
# CURL must be included before sentry
# because sentry needs the module
# and does not include it itself on macos...
find_package(CURL CONFIG REQUIRED)
find_package(sentry CONFIG REQUIRED)
set(src
main.cpp
@ -74,28 +76,17 @@ set(l10n
translations/ScreenPlay_vi.ts)
set_source_files_properties(${l10n} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/translations")
qt_add_translation(qmFiles ${l10n})
qt5_add_translation(qmFiles ${l10n})
qt5_add_big_resources(fonts fonts.qrc)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
qt_add_resources(qml qml.qrc Resources.qrc)
qt5_add_resources(qml qml.qrc assets.qrc)
else()
qtquick_compiler_add_resources(qml qml.qrc Resources.qrc)
qtquick_compiler_add_resources(qml qml.qrc assets.qrc)
endif()
add_executable(${PROJECT_NAME} ${src} ${headers} ${resources} ${qml})
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE true)
endif()
if(WIN32)
# Icon
target_sources(${PROJECT_NAME} PRIVATE ScreenPlay.rc)
# Disable console window on Windows
# https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows
set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE true)
endif()
add_executable(${PROJECT_NAME} ${src} ${headers} ${resources} ${qml} ${fonts})
target_compile_definitions(${PROJECT_NAME} PRIVATE "GIT_VERSION=${GIT_VERSION}")
@ -107,25 +98,65 @@ target_link_libraries(
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::WebSockets
Qt${QT_VERSION_MAJOR}::WebEngine
Qt${QT_VERSION_MAJOR}::Svg
ScreenPlaySDK
ScreenPlayUtil
benchmark::benchmark
benchmark::benchmark_main
doctest::doctest)
doctest::doctest
sentry::sentry)
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE sentry::sentry)
endif()
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/assets/fonts)
configure_file(assets/fonts/NotoSansCJKkr-Regular.otf ${CMAKE_BINARY_DIR}/bin/assets/fonts COPYONLY)
# Icon
target_sources(${PROJECT_NAME} PRIVATE ScreenPlay.rc)
# Copy ffmpeg. If the ffmpeg files are missing, start the install_dependencies_XXX for your system!
if(WIN32)
# Disable console window on Windows
# https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows
set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE true)
# Copy ffmpeg. If the ffmpeg files are missing, start the install_dependencies_XXX for your system!
file(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/../Common/ffmpeg/*")
foreach(filename ${files})
configure_file(${filename} ${CMAKE_BINARY_DIR}/bin/ COPYONLY)
endforeach()
configure_file(${VCPKG_INSTALLED_PATH}/tools/sentry-native/crashpad_handler.exe ${CMAKE_BINARY_DIR}/bin/ COPYONLY)
endif()
if(APPLE)
# Creates a ScreenPlay.app
set_target_properties(${PROJECT_NAME} PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}
MACOSX_BUNDLE TRUE
MACOSX_RPATH TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
MACOSX_FRAMEWORK_IDENTIFIER screen-play.app
XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@loader_path/Libraries"
RESOURCE "${RESOURCE_FILES}"
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE
XCODE_ATTRIBUTE_EXECUTABLE_NAME ${PROJECT_NAME}
)
# Needed for the Steam Workshop qml plugin
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/Workshop)
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/../Common/ffmpeg/ffmpeg
${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/ )
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/../Common/ffmpeg/ffprobe
${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/ )
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${VCPKG_INSTALLED_PATH}/tools/sentry-native/crashpad_handler
${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/ )
endif()

24
ScreenPlay/Info.plist Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>app.screen-play</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleDisplayName</key>
<string>ScreenPlay</string>
</dict>
</plist>

View File

@ -56,7 +56,7 @@ App::App()
QGuiApplication::setWindowIcon(QIcon(":/assets/icons/app.ico"));
QGuiApplication::setOrganizationName("ScreenPlay");
QGuiApplication::setOrganizationDomain("https://screen-play.app");
QGuiApplication::setOrganizationDomain("screen-play.app");
QGuiApplication::setApplicationName("ScreenPlay");
QGuiApplication::setApplicationVersion("0.13.3");
QGuiApplication::setQuitOnLastWindowClosed(false);
@ -74,9 +74,7 @@ App::App()
QFontDatabase::addApplicationFont(":/assets/fonts/NotoSans-Medium.ttf");
QFontDatabase::addApplicationFont(":/assets/fonts/NotoSans-Light.ttf");
if (-1 == QFontDatabase::addApplicationFont(QGuiApplication::applicationDirPath() + "/assets/fonts/NotoSansCJKkr-Regular.otf")) {
qWarning() << "Could not load korean font from: " << QGuiApplication::applicationDirPath() + "/assets/fonts/NotoSansCJKkr-Regular.otf";
}
QFontDatabase::addApplicationFont(":/assets/fonts/NotoSansCJKkr-Regular.otf");
QQuickWindow::setTextRenderType(QQuickWindow::TextRenderType::NativeTextRendering);
@ -158,7 +156,6 @@ void App::init()
// Only create anonymousTelemetry if user did not disallow!
if (m_settings->anonymousTelemetry()) {
#ifdef Q_OS_WIN
sentry_options_t* options = sentry_options_new();
sentry_options_set_dsn(options, "https://425ea0b77def4f91a5a9decc01b36ff4@o428218.ingest.sentry.io/5373419");
QString environment = QGuiApplication::applicationVersion() + "";
@ -167,11 +164,12 @@ void App::init()
const QString appPath = QGuiApplication::applicationDirPath();
sentry_options_set_handler_path(options, QString(appPath + "/crashpad_handler.exe").toStdString().c_str());
sentry_options_set_database_path(options, appPath.toStdString().c_str());
sentry_options_set_handler_path(options, QString(QGuiApplication::applicationDirPath() + "/crashpad_handler" + ScreenPlayUtil::executableBinEnding()).toStdString().c_str());
sentry_options_set_database_path(options, QGuiApplication::applicationDirPath().toStdString().c_str());
const int sentryInitStatus = sentry_init(options);
if (sentryInitStatus != 0) {
qWarning() << "Unable to inti sentry crashhandler with statuscode: " << sentryInitStatus;
}
#endif
}
m_create = make_unique<Create>(m_globalVariables);

View File

@ -48,6 +48,7 @@
#include <QtGlobal>
#include <QtQml>
#include <QtWebEngine>
#include <QtSvg>
#include "src/create.h"
#include "src/globalvariables.h"
@ -61,10 +62,7 @@
#include "src/wizards.h"
#include <memory>
#ifdef Q_OS_WIN
#include <sentry.h>
#endif
class ScreenPlayWorkshopPlugin;

View File

@ -1,16 +1,6 @@
<RCC>
<qresource prefix="/">
<file>assets/WorkshopPreview.html</file>
<file>assets/fonts/LibreBaskerville-Italic.ttf</file>
<file>assets/fonts/NotoSans-Light.ttf</file>
<file>assets/fonts/NotoSans-Medium.ttf</file>
<file>assets/fonts/NotoSans-Regular.ttf</file>
<file>assets/fonts/NotoSans-Thin.ttf</file>
<file>assets/fonts/Roboto-Light.ttf</file>
<file>assets/fonts/Roboto-Regular.ttf</file>
<file>assets/fonts/Roboto-Thin.ttf</file>
<file>assets/fonts/RobotoMono-Light.ttf</file>
<file>assets/fonts/RobotoMono-Thin.ttf</file>
<file>assets/icons/app.ico</file>
<file>assets/icons/brand_github.svg</file>
<file>assets/icons/brand_gitlab.svg</file>
@ -139,5 +129,6 @@
<file>assets/icons/icon_sort-down-solid.svg</file>
<file>assets/icons/brand_reddit.svg</file>
<file>assets/icons/steam_default_avatar.png</file>
<file>assets/macos/app.screenplay.plist</file>
</qresource>
</RCC>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>app.screenplay</string>
<key>ProgramArguments</key>
<array>
<string>{{SCREENPLAY_PATH}}</string>
<string>-silent</string>
</array>
<key>ProcessType</key>
<string>Interactive</string>
<key>RunAtLoad</key>
<{{SCREENPLAY_AUTOSTART}}/>
<key>KeepAlive</key>
<false/>
</dict>
</plist>

15
ScreenPlay/fonts.qrc Normal file
View File

@ -0,0 +1,15 @@
<RCC>
<qresource prefix="/">
<file>assets/fonts/LibreBaskerville-Italic.ttf</file>
<file>assets/fonts/NotoSans-Light.ttf</file>
<file>assets/fonts/NotoSans-Medium.ttf</file>
<file>assets/fonts/NotoSans-Regular.ttf</file>
<file>assets/fonts/NotoSans-Thin.ttf</file>
<file>assets/fonts/NotoSansCJKkr-Regular.otf</file>
<file>assets/fonts/Roboto-Light.ttf</file>
<file>assets/fonts/Roboto-Regular.ttf</file>
<file>assets/fonts/Roboto-Thin.ttf</file>
<file>assets/fonts/RobotoMono-Light.ttf</file>
<file>assets/fonts/RobotoMono-Thin.ttf</file>
</qresource>
</RCC>

View File

@ -37,9 +37,7 @@
#include <QCommandLineParser>
#include <QDebug>
#include <QtWebEngine/QtWebEngine>
#ifdef Q_OS_WIN
#include <sentry.h>
#endif
#define DOCTEST_CONFIG_IMPLEMENT
#define DOCTEST_CONFIG_SUPER_FAST_ASSERTS
#include <doctest/doctest.h>
@ -68,13 +66,9 @@ int main(int argc, char* argv[])
if (app.m_isAnotherScreenPlayInstanceRunning) {
return 0;
} else {
app.init();
const int status = qtGuiApp.exec();
#ifdef Q_OS_WIN
sentry_shutdown();
#endif
return status;
}
}

View File

@ -33,14 +33,19 @@ CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& ex
: QObject(parent)
, m_quality(quality)
{
m_videoPath = videoPath;
m_exportPath = exportPath;
m_codec = codec;
m_process = std::make_unique<QProcess>(this);
m_ffprobeExecutable = QApplication::applicationDirPath() + "/ffprobe" + ScreenPlayUtil::executableBinEnding();
m_ffmpegExecutable = QApplication::applicationDirPath() + "/ffmpeg" + ScreenPlayUtil::executableBinEnding();
m_ffprobeExecutable = QApplication::applicationDirPath() + "/ffprobe" + ScreenPlayUtil::executableEnding();
m_ffmpegExecutable = QApplication::applicationDirPath() + "/ffmpeg" + ScreenPlayUtil::executableEnding();
if (!QFileInfo::exists(m_ffprobeExecutable)) {
qFatal("FFPROBE executable not found!");
}
if (!QFileInfo::exists(m_ffmpegExecutable)) {
qFatal("FFMPEG executable not found!");
}
}
/*!
@ -58,7 +63,7 @@ CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& ex
void CreateImportVideo::process()
{
qInfo() << "createWallpaperInfo()";
qInfo() << "createWallpaperInfo()" << m_videoPath << m_exportPath << m_codec << m_ffmpegExecutable << m_ffprobeExecutable;
if (!createWallpaperInfo() || QThread::currentThread()->isInterruptionRequested()) {
emit abortAndCleanup();
return;
@ -264,7 +269,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj)
QJsonObject videoStream;
for (const auto stream : arrayStream) {
for (const auto& stream : arrayStream) {
QString codec_type = stream.toObject().value("codec_type").toString();
if (codec_type == "video") {
videoStream = stream.toObject();
@ -747,19 +752,42 @@ QString CreateImportVideo::waitForFinished(
const Executable executable)
{
m_process = std::make_unique<QProcess>();
QObject::connect(m_process.get(), &QProcess::errorOccurred, [=](QProcess::ProcessError error) {
qDebug() << "error enum val = " << error << m_process->errorString();
emit createWallpaperStateChanged(ImportVideoState::AnalyseVideoError);
m_process->terminate();
if (!m_process->waitForFinished(1000)) {
m_process->kill();
}
});
if (executable == Executable::FFMPEG) {
m_process->setProgram(m_ffmpegExecutable);
} else {
m_process->setProgram(m_ffprobeExecutable);
}
#ifdef Q_OS_OSX
QProcess changeChmod;
changeChmod.setProgram("chmod");
changeChmod.setArguments({ "+x", m_process->program() });
changeChmod.start();
if (!changeChmod.waitForFinished()) {
qCritical() << "Unable to change permission " << m_process->program() << " to be exectuable";
}
#endif
m_process->setProcessChannelMode(processChannelMode);
m_process->setArguments(args);
m_process->setWorkingDirectory(QApplication::applicationDirPath());
m_process->start();
while (!m_process->waitForFinished(100)) //Wake up every 10ms and check if we must exit
qInfo() << m_process->workingDirectory() << m_process->program() << m_process->arguments();
while (!m_process->waitForFinished(10)) //Wake up every 10ms and check if we must exit
{
if (QThread::currentThread()->isInterruptionRequested()) {
qDebug() << "Interrupt thread";
qInfo() << "Interrupt thread";
m_process->terminate();
if (!m_process->waitForFinished(1000)) {
m_process->kill();

View File

@ -381,6 +381,7 @@ void ScreenPlayManager::newConnection()
for (int i = 0; i < m_screenPlayWallpapers.size(); ++i) {
if (m_screenPlayWallpapers.at(i)->appID() == matchingConnection->appID()) {
qInfo() << "Matching Wallpaper found!";
m_screenPlayWallpapers.at(i)->setSDKConnection(std::move(matchingConnection));
return;
}
@ -388,6 +389,7 @@ void ScreenPlayManager::newConnection()
for (int i = 0; i < m_screenPlayWidgets.size(); ++i) {
if (m_screenPlayWidgets.at(i)->appID() == matchingConnection->appID()) {
qInfo() << "Matching Widget found!";
m_screenPlayWidgets.at(i)->setSDKConnection(std::move(matchingConnection));
return;
}

View File

@ -15,8 +15,9 @@ namespace ScreenPlay {
*/
ScreenPlayWallpaper::~ScreenPlayWallpaper()
{
qInfo() << "Remove wallpaper " << m_appID;
m_connection->close();
qInfo() << "Remove wallpaper " << m_appID;
}
/*!
@ -106,6 +107,7 @@ bool ScreenPlayWallpaper::start()
const bool success = m_process.startDetached();
qInfo() << "Starting ScreenPlayWallpaper detached: " << (success ? "success" : "failed!");
if (!success) {
qInfo() << m_process.program() << m_appArgumentsList;
emit error(QString("Could not start Wallpaper: " + m_process.errorString()));
}
return success;

View File

@ -50,9 +50,10 @@ ScreenPlayWidget::ScreenPlayWidget(
QVariant::fromValue(m_type).toString(),
QString::number(m_position.x()),
QString::number(m_position.y()),
};
};
}
bool ScreenPlayWidget::start()
{
m_process.setArguments(m_appArgumentsList);
@ -65,6 +66,7 @@ bool ScreenPlayWidget::start()
qInfo() << "Starting ScreenPlayWidget detached: " << (success ? "success" : "failed!");
if (!success) {
emit error(QString("Could not start Widget: " + m_process.errorString()));
return false;
}
return success;
}

View File

@ -69,11 +69,11 @@ public:
const QString& absolutePath,
const QString& previewImage, const QJsonObject& properties,
const InstalledType::InstalledType type);
~ScreenPlayWidget();
bool start();
ScreenPlayWidget() { }
~ScreenPlayWidget();
QString previewImage() const { return m_previewImage; }
QPoint position() const { return m_position; }

View File

@ -1,6 +1,7 @@
#include "settings.h"
#include "ScreenPlayUtil/util.h"
#include <QFileInfo>
namespace ScreenPlay {
@ -39,6 +40,16 @@ Settings::Settings(const std::shared_ptr<GlobalVariables>& globalVariables,
: QObject(parent)
, m_globalVariables { globalVariables }
{
#ifdef Q_OS_WIN
setDesktopEnvironment(DesktopEnvironment::Windows);
#endif
#ifdef Q_OS_OSX
setDesktopEnvironment(DesktopEnvironment::OSX);
#endif
#ifdef Q_OS_LINUX
// We only support KDE for now
setDesktopEnvironment(DesktopEnvironment::KDE);
#endif
qRegisterMetaType<Settings::Language>("Settings::Language");
qRegisterMetaType<Settings::Theme>("Settings::Theme");
@ -47,15 +58,15 @@ Settings::Settings(const std::shared_ptr<GlobalVariables>& globalVariables,
qmlRegisterUncreatableType<Settings>("Settings", 1, 0, "Settings", "Error only for enums");
if (!m_qSettings.contains("Autostart")) {
#ifdef Q_OS_WIN
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
if (!m_qSettings.value("Autostart").toBool()) {
if (!settings.contains("ScreenPlay")) {
if (desktopEnvironment() == DesktopEnvironment::Windows) {
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
if (!m_qSettings.value("Autostart").toBool()) {
if (!settings.contains("ScreenPlay")) {
}
}
settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent");
settings.sync();
}
settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent");
settings.sync();
#endif
m_qSettings.setValue("Autostart", true);
m_qSettings.sync();
} else {
@ -87,54 +98,10 @@ Settings::Settings(const std::shared_ptr<GlobalVariables>& globalVariables,
writeJsonFileFromResource("profiles");
}
//If empty use steam workshop location
if (QString(m_qSettings.value("ScreenPlayContentPath").toString()).isEmpty()) {
/*
* ! We must use this (ugly) method, because to stay FOSS we cannot call the steamAPI here !
*
* We start with the assumption that when we go up 2 folder.
* So that there must be at least a common folder:
* Windows example:
* From -> C:\Program Files (x86)\Steam\steamapps\common\ScreenPlay
* To -> C:\Program Files (x86)\Steam\steamapps\
* Dest.-> C:\Program Files (x86)\Steam\steamapps\workshop\content\672870
*
* When we reach the folder it _can_ contain a workshop folder when the user
* previously installed any workshop content. If the folder does not exsist we
* need to create it by hand. Normally Steam will create this folder but we need to
* set it here at this point so that the QFileSystemWatcher in InstalledListModel does
* not generate warnings.
*/
QDir dir;
QString path = QApplication::instance()->applicationDirPath() + "/../../workshop/content/672870";
if (!dir.mkpath(path)) {
qWarning() << "Could not create steam workshop path for path: " << path;
} else {
m_globalVariables->setLocalStoragePath(QUrl::fromUserInput(path));
m_qSettings.setValue("ScreenPlayContentPath", dir.cleanPath(path));
m_qSettings.sync();
}
} else {
m_globalVariables->setLocalStoragePath(QUrl::fromUserInput(m_qSettings.value("ScreenPlayContentPath").toString()));
}
initInstalledPath();
setupWidgetAndWindowPaths();
setGitBuildHash(COMPILE_INFO);
#ifdef Q_OS_WIN
setDesktopEnvironment(DesktopEnvironment::Windows);
#endif
#ifdef Q_OS_OSX
setDesktopEnvironment(DesktopEnvironment::OSX);
#endif
#ifdef Q_OS_LINUX
// We only support KDE for now
setDesktopEnvironment(DesktopEnvironment::KDE);
#endif
}
/*!
@ -173,16 +140,28 @@ void Settings::writeJsonFileFromResource(const QString& filename)
void Settings::setupWidgetAndWindowPaths()
{
QDir workingDir(QGuiApplication::applicationDirPath());
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX)
m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + ScreenPlayUtil::executableEnding()));
m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + ScreenPlayUtil::executableEnding()));
#ifdef Q_OS_WIN
m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + ScreenPlayUtil::executableBinEnding()));
m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + ScreenPlayUtil::executableBinEnding()));
#endif
#if defined(Q_OS_OSX)
m_globalVariables->setWidgetExecutablePath(QUrl::fromUserInput(workingDir.path() + "ScreenPlayWidget.app/Contents/MacOS/ScreenPlayWidget").toLocalFile());
m_globalVariables->setWallpaperExecutablePath(QUrl::fromUserInput(workingDir.path() + "ScreenPlayWallpaper.app/Contents/MacOS/ScreenPlayWallpaper").toLocalFile());
#ifdef Q_OS_OSX
workingDir.cdUp();
workingDir.cdUp();
workingDir.cdUp();
m_globalVariables->setWidgetExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlayWidget.app/Contents/MacOS/ScreenPlayWidget").toLocalFile());
m_globalVariables->setWallpaperExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlayWallpaper.app/Contents/MacOS/ScreenPlayWallpaper").toLocalFile());
#endif
if (!QFileInfo::exists(m_globalVariables->widgetExecutablePath().toString())) {
qFatal("widget executable not found!");
}
if (!QFileInfo::exists(m_globalVariables->wallpaperExecutablePath().toString())) {
qFatal("wallpaper executable not found!");
}
}
/*!
@ -200,6 +179,53 @@ void Settings::restoreDefault(const QString& appConfigLocation, const QString& s
writeJsonFileFromResource(settingsFileType);
}
void Settings::initInstalledPath()
{
//If empty use steam workshop location
qInfo() << m_qSettings.value("ScreenPlayContentPath").toString();
if (QString(m_qSettings.value("ScreenPlayContentPath").toString()).isEmpty()) {
/*
* ! We must use this (ugly) method, because to stay FOSS we cannot call the steamAPI here !
*
* We start with the assumption that when we go up 2 folder.
* So that there must be at least a common folder:
* Windows example:
* From -> C:\Program Files (x86)\Steam\steamapps\common\ScreenPlay
* To -> C:\Program Files (x86)\Steam\steamapps\
* Dest.-> C:\Program Files (x86)\Steam\steamapps\workshop\content\672870
*
* When we reach the folder it _can_ contain a workshop folder when the user
* previously installed any workshop content. If the folder does not exsist we
* need to create it by hand. Normally Steam will create this folder but we need to
* set it here at this point so that the QFileSystemWatcher in InstalledListModel does
* not generate warnings.
*/
QDir dir;
QString appBasePath = QApplication::instance()->applicationDirPath();
if (desktopEnvironment() == DesktopEnvironment::OSX) {
appBasePath += "/../../..";
}
QString path = appBasePath + "/../../workshop/content/672870";
qInfo() << path;
if (!dir.mkpath(path)) {
qWarning() << "Could not create steam workshop path for path: " << path;
}
if (QDir(path).exists()) {
m_globalVariables->setLocalStoragePath(QUrl::fromUserInput(path));
m_qSettings.setValue("ScreenPlayContentPath", dir.cleanPath(path));
m_qSettings.sync();
} else {
qWarning() << "The following path could not be resolved to search for workshop content: " << path;
}
} else {
m_globalVariables->setLocalStoragePath(QUrl::fromUserInput(m_qSettings.value("ScreenPlayContentPath").toString()));
}
}
/*!
\brief Checks if there is already a saved language. If not we try to use the system langauge.
If we do not support the system language we use english.

View File

@ -39,6 +39,7 @@
#include <QDir>
#include <QFile>
#include <QFontDatabase>
#include <QIODevice>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
@ -185,19 +186,48 @@ public slots:
void setAutostart(bool autostart)
{
if (m_autostart == autostart)
return;
if (desktopEnvironment() == DesktopEnvironment::Windows) {
#ifdef Q_OS_WIN
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
if (autostart) {
settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent");
settings.sync();
} else {
settings.remove("ScreenPlay");
QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat);
if (autostart) {
settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent");
settings.sync();
} else {
settings.remove("ScreenPlay");
}
}
#endif
if (desktopEnvironment() == DesktopEnvironment::OSX) {
const QString plistFileName = "app.screenplay.plist";
QFile defaultPListFile(":/assets/macos/" + plistFileName);
defaultPListFile.open(QIODevice::ReadOnly);
QString settingsPlistContent = defaultPListFile.readAll();
if(!settingsPlistContent.contains("{{SCREENPLAY_PATH}}")){
qCritical() << "Unable to load plist settings template from qrc to set autostart!";
}
QDir workingDir(QGuiApplication::applicationDirPath());
workingDir.cdUp();
workingDir.cdUp();
workingDir.cdUp();
const QString screenPlayPath = QUrl::fromUserInput(workingDir.path() + "/ScreenPlay.app/Contents/MacOS/ScreenPlay").toLocalFile();
settingsPlistContent.replace("{{SCREENPLAY_PATH}}", screenPlayPath);
settingsPlistContent.replace("{{SCREENPLAY_AUTOSTART}}", autostart ? "true":"false");
const QString homePath = QDir::homePath();
QFile settingsPlist(homePath + "/Library/LaunchAgents/" + plistFileName);
if (settingsPlist.exists()) {
if(!settingsPlist.remove()){
qCritical() << "Unable to remove: " << settingsPlist;
}
}
settingsPlist.open(QIODevice::WriteOnly | QIODevice::Truncate);
QTextStream out(&settingsPlist);
out.setCodec("UTF-8");
out << settingsPlistContent;
settingsPlist.flush();
settingsPlist.close();
}
setqSetting("Autostart", autostart);
m_autostart = autostart;
@ -371,6 +401,7 @@ public slots:
private:
void restoreDefault(const QString& appConfigLocation, const QString& settingsFileType);
void initInstalledPath();
private:
QSettings m_qSettings;

View File

@ -221,7 +221,6 @@ void Util::logToGui(QtMsgType type, const QMessageLogContext& context, const QSt
if (utilPointer != nullptr)
utilPointer->appendDebugMessages(log);
#ifdef Q_OS_WIN
sentry_value_t crumb
= sentry_value_new_breadcrumb("default", qUtf8Printable(msg));
@ -239,7 +238,6 @@ void Util::logToGui(QtMsgType type, const QMessageLogContext& context, const QSt
sentry_value_set_by_key(crumb, "data", location);
sentry_add_breadcrumb(crumb);
#endif
}
/*!

View File

@ -149,6 +149,7 @@ void ScreenPlaySDK::readyRead()
void ScreenPlaySDK::error(QLocalSocket::LocalSocketError socketError)
{
Q_UNUSED(socketError)
emit sdkDisconnected();
}

View File

@ -43,8 +43,18 @@ file(MAKE_DIRECTORY ${DESTDIR})
configure_file(qmldir ${DESTDIR} COPYONLY)
# Copies ScreenPlayShader.* into qt qml plugins folder
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:ScreenPlayShader> ${DESTDIR}/$<TARGET_FILE_NAME:ScreenPlayShader>)
if(APPLE)
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD
COMMENT "Copying into ScreenPlay.app bundle"
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/bin/$<TARGET_FILE_NAME:${PROJECT_NAME}>
${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/$<TARGET_FILE_NAME:${PROJECT_NAME}>)
else()
# Copies ScreenPlayShader.* into qt qml plugins folder
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:ScreenPlayShader>
${DESTDIR}/$<TARGET_FILE_NAME:ScreenPlayShader>)
endif()

View File

@ -56,7 +56,8 @@ bool copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, con
QString toString(const QStringList& list);
QString toLocal(const QString& url);
QString generateRandomString(quint32 length = 32);
QString executableEnding();
QString executableAppEnding();
QString executableBinEnding();
QStringList getAvailableWallpaper();
QStringList getAvailableWidgets();
QStringList getAvailableTypes();

View File

@ -114,13 +114,26 @@ QString generateRandomString(quint32 length)
/*!
\brief Return .exe on windows otherwise empty string.
*/
QString executableEnding()
QString executableBinEnding()
{
#ifdef Q_OS_WIN
return ".exe";
#else
return "";
#endif
return "";
}
/*!
\brief Return .exe on windows, .app on osx otherwise empty string.
*/
QString executableAppEnding()
{
#ifdef Q_OS_WIN
return ".exe";
#endif
#ifdef Q_OS_OSX
return ".app";
#endif
return "";
}
/*!

View File

@ -41,8 +41,13 @@ if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE shcore.lib)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Quick Qt5::Gui Qt5::Widgets Qt5::Core Qt5::WebEngine ScreenPlaySDK ScreenPlayUtil)
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE true)
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")
endif()
@ -56,3 +61,4 @@ target_link_libraries(
shcore.lib
ScreenPlaySDK
ScreenPlayUtil)

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>app.screen-play.wallpaper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleDisplayName</key>
<string>ScreenPlayWallpaper</string>
<key>NSUIElement</key>
<string>1</string>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>

View File

@ -136,8 +136,10 @@ Rectangle {
source: {
if (Qt.platform.os === "windows")
return Qt.resolvedUrl("file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath);
else
return ""
}
Component.onCompleted: {
if (Qt.platform.os !== "windows") {
root.canFadeByWallpaperFillMode = false;
@ -308,7 +310,12 @@ Rectangle {
}
Text {
text: "imgCover.source " + Qt.resolvedUrl("file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath)
text: {
if (Qt.platform.os === "windows")
return "imgCover.source " + Qt.resolvedUrl("file:///" + Wallpaper.windowsDesktopProperties.wallpaperPath)
else
return ""
}
font.pointSize: 14
}

View File

@ -38,7 +38,7 @@ int main(int argc, char* argv[])
#elif defined(Q_OS_LINUX)
LinuxWindow window({ 0 }, "test", "appid", "1", "fill", false);
#elif defined(Q_OS_OSX)
MacWindow window({ 0 }, "test", "appid", "1", "fill");
MacWindow window({ 0 }, "test", "appID=test", "1", "fill","videoWallpaper", true, true);
#endif
return app.exec();
}
@ -89,12 +89,14 @@ int main(int argc, char* argv[])
checkWallpaperVisible);
#elif defined(Q_OS_OSX)
MacWindow window(
activeScreensList.value(),
projectPath,
appID,
fillmode,
volume,
checkWallpaperVisible);
activeScreensList.value(),
projectFilePath,
appID,
volume,
fillmode,
type,
checkWallpaperVisible,
debugMode);
#endif
return app.exec();

View File

@ -32,6 +32,7 @@ BaseWindow::BaseWindow(
, m_debugMode(debugMode)
, m_sdk(std::make_unique<ScreenPlaySDK>(appID, type))
{
qInfo() << "parent";
QApplication::instance()->installEventFilter(this);
qRegisterMetaType<ScreenPlay::InstalledType::InstalledType>();

View File

@ -2,46 +2,56 @@
MacWindow::MacWindow(
const QVector<int>& activeScreensList,
const QString& projectPath,
const QString& id,
const QString& projectFilePath,
const QString& appID,
const QString& volume,
const QString& fillmode)
: BaseWindow(projectPath, activeScreensList, false)
const QString& fillmode,
const QString& type,
const bool checkWallpaperVisible,
const bool debugMode)
: BaseWindow(
activeScreensList,
projectFilePath,
type,
checkWallpaperVisible,
appID,
debugMode)
{
setAppID(id);
connect(sdk(), &ScreenPlaySDK::sdkDisconnected, this, &MacWindow::destroyThis);
connect(sdk(), &ScreenPlaySDK::incommingMessage, this, &MacWindow::messageReceived);
connect(sdk(), &ScreenPlaySDK::replaceWallpaper, this, &MacWindow::replaceWallpaper);
bool ok = false;
float volumeParsed = volume.toFloat(&ok);
if (!ok) {
qFatal("Could not parse volume");
}
setVolume(volumeParsed);
setFillMode(fillmode);
// Ether for one Screen or for all
if ((QApplication::screens().length() == activeScreensList.length()) && (activeScreensList.length() != 1)) {
//setupWallpaperForAllScreens();
} else if (activeScreensList.length() == 1) {
//setupWallpaperForOneScreen(activeScreensList.at(0));
auto* screen = QGuiApplication::screens().at(0);
m_window.setWidth(screen->geometry().width());
m_window.setHeight(screen->geometry().height());
auto* screen = QGuiApplication::screens().at(activeScreensList.at(0));
m_window.setGeometry(screen->geometry());
} else if (activeScreensList.length() > 1) {
//setupWallpaperForMultipleScreens(activeScreensList);
}
qmlRegisterSingletonInstance<MacWindow>("ScreenPlayWallpaper", 1, 0, "Wallpaper", this);
// 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"));
MacIntegration* macIntegration = new MacIntegration(this);
macIntegration->SetBackgroundLevel(&m_window);
sdk()->start();
}
void MacWindow::setVisible(bool show)

View File

@ -51,12 +51,14 @@
class MacWindow : public BaseWindow {
Q_OBJECT
public:
explicit MacWindow(
const QVector<int>& activeScreensList,
const QString& projectPath,
const QString& id,
explicit MacWindow(const QVector<int>& activeScreensList,
const QString& projectFilePath,
const QString& appID,
const QString& volume,
const QString& fillmode);
const QString& fillmode,
const QString& type,
const bool checkWallpaperVisible,
const bool debugMode);
signals:

View File

@ -31,7 +31,10 @@ if(WIN32)
endif()
if(APPLE)
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE true)
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Quick Qt${QT_VERSION_MAJOR}::Gui Qt${QT_VERSION_MAJOR}::Widgets

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>app.screen-play.widget</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleDisplayName</key>
<string>ScreenPlayWidget</string>
<key>NSUIElement</key>
<string>1</string>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>

View File

@ -50,6 +50,7 @@
#include <QWindow>
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickWindow>
#include <QFileSystemWatcher>
#ifdef Q_OS_WIN
#include <QFileSystemWatcher>

15
Tools/Readme.md Normal file
View File

@ -0,0 +1,15 @@
## Tools
This folder contains serveral python tools to help with development:
#### setup.py
- Installs third party dependencies for all platforms
#### build.py
- Build ScreenPlay locally
#### clang_format.py
- Invokers clang-format for all .cpp and .h files
#### qdoc.py
- Builds documentation for all projects into Docs/html
#### download_ffmpeg.py
- Donwload ffmpeg for macos only for now
#### qml_format.py
- Calls qmlformat for all qml files

36
Tools/download_ffmpeg.py Normal file
View File

@ -0,0 +1,36 @@
import zipfile
from urllib.request import urlopen
import os
def download_and_extract(file_base_path, name):
print("Download: ", name)
download_server_base_url = 'https://evermeet.cx/ffmpeg/'
filedata = urlopen(download_server_base_url + name)
datatowrite = filedata.read()
path_and_filename = os.path.join(file_base_path, name)
print("Save tmp file: ", path_and_filename)
with open(path_and_filename, 'wb') as f:
f.write(datatowrite)
extraction_path = os.path.join(file_base_path, "../Common/ffmpeg")
print("Extract to:", extraction_path)
with zipfile.ZipFile(path_and_filename,"r") as zip_ref:
zip_ref.extractall(extraction_path)
print("Delete tmp file: ", path_and_filename)
os.remove(path_and_filename)
ffmpeg_7zip_name = 'ffmpeg-4.4.zip'
ffprobe_7zip_name = 'ffprobe-4.4.zip'
current_path = os.path.join(os.path.abspath(os.getcwd()),"")
extraction_path = os.path.abspath(os.path.join(current_path, "../Common/ffmpeg"))
if not os.path.exists(extraction_path):
os.makedirs(extraction_path)
download_and_extract(current_path, ffmpeg_7zip_name)
download_and_extract(current_path, ffprobe_7zip_name)

View File

@ -30,7 +30,7 @@ if __name__ == "__main__":
vcpkg_path = os.path.join(project_source_parent_path, "ScreenPlay-vcpkg")
print("vcpkg_path: ", vcpkg_path)
vcpkg_version = "5568f11" # https://github.com/microsoft/vcpkg/releases/tag/2021.05.12
vcpkg_version = "680b27d15f4d62bc6181fd33dc5259482b0890b1" # Master 10.06.2021
print("Build vcpkg ", vcpkg_version)
execute("git fetch", vcpkg_path)
execute("git checkout {}".format(vcpkg_version), vcpkg_path)
@ -39,7 +39,6 @@ if __name__ == "__main__":
"openssl-unix",
"sentry-native",
"doctest",
"benchmark",
]
vcpkg_triplet = ""
@ -53,18 +52,21 @@ if __name__ == "__main__":
vcpkg_triplet = "x64-windows"
elif sys.platform == "darwin":
vcpkg_packages_list.append("infoware[opencl]")
execute("bootstrap-vcpkg.sh", vcpkg_path, False)
execute("chmod +x vcpkg", vcpkg_path)
vcpkg_triplet = "x64-linux"
elif sys.platform == "linux":
vcpkg_packages_list.append("infoware[opencl]")
execute("bootstrap-vcpkg.sh", vcpkg_path, False)
vcpkg_packages_list.append("curl") # Hidden dependency from sentry
execute("chmod +x bootstrap-vcpkg.sh", vcpkg_path)
execute("./bootstrap-vcpkg.sh", vcpkg_path, False)
execute("chmod +x vcpkg", vcpkg_path)
vcpkg_triplet = "x64-osx"
elif sys.platform == "linux":
vcpkg_packages_list.append("infoware[opencl]")
execute("chmod +x bootstrap-vcpkg.sh", vcpkg_path)
execute("./bootstrap-vcpkg.sh", vcpkg_path, False)
execute("chmod +x vcpkg", vcpkg_path)
vcpkg_triplet = "x64-linux"
vcpkg_packages = " ".join(vcpkg_packages_list)
execute("vcpkg{} update".format(executable_file_suffix), vcpkg_path, False)
execute("vcpkg{} upgrade --no-dry-run".format(executable_file_suffix),
execute("./vcpkg{} update".format(executable_file_suffix), vcpkg_path, False)
execute("./vcpkg{} upgrade --no-dry-run".format(executable_file_suffix),
vcpkg_path, False)
execute("vcpkg{} install {} --triplet {} --recurse".format(executable_file_suffix,
execute("./vcpkg{} install {} --triplet {} --recurse".format(executable_file_suffix,
vcpkg_packages, vcpkg_triplet), vcpkg_path, False)