From f04ecec2acd165e6dd5692fed21d0667bbf3ac52 Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Sat, 13 Jun 2020 15:05:22 +0200 Subject: Proton directory discovery Use search paths to find proton wine and the app directory, so that we can support steam installations in multiple locations and 3rd party proton installations. --- proto-wine/ftnoir_protocol_wine.cpp | 8 ++-- proto-wine/ftnoir_protocol_wine.h | 5 ++- proto-wine/ftnoir_protocol_wine_dialog.cpp | 26 +++++++++--- proto-wine/proton.cpp | 68 ++++++++++++++++++++---------- 4 files changed, 72 insertions(+), 35 deletions(-) diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index aabaa30c..63308e9f 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -70,11 +70,11 @@ module_status wine::initialize() if (s.proton_appid == 0) return error(tr("Must specify application id for Proton (Steam Play)")); - QProcessEnvironment make_steam_environ(const QString& proton_version, int appid); - QString proton_path(const QString& proton_version); + QProcessEnvironment make_steam_environ(const QString& proton_path, int appid); + QString proton_path(const QString& proton_path); - wine_path = proton_path(s.proton_version); - env = make_steam_environ(s.proton_version, s.proton_appid); + wine_path = proton_path(s.proton_path().toString()); + env = make_steam_environ(s.proton_path().toString(), s.proton_appid); } else { diff --git a/proto-wine/ftnoir_protocol_wine.h b/proto-wine/ftnoir_protocol_wine.h index 0e48e5b5..fc537b60 100644 --- a/proto-wine/ftnoir_protocol_wine.h +++ b/proto-wine/ftnoir_protocol_wine.h @@ -12,6 +12,7 @@ using namespace options; #include #include #include +#include #include @@ -24,8 +25,8 @@ struct settings : opts esync{b, "esync", true}; value proton_appid{b, "proton-appid", 0}; - value proton_version{b, "proton-version", {} }, - wineprefix{b, "wineprefix", "~/.wine"}; + value proton_path{b, "proton-version", {} }; + value wineprefix{b, "wineprefix", "~/.wine"}; value protocol{b, "protocol", 2}; }; diff --git a/proto-wine/ftnoir_protocol_wine_dialog.cpp b/proto-wine/ftnoir_protocol_wine_dialog.cpp index b590ee94..76ccfdb5 100644 --- a/proto-wine/ftnoir_protocol_wine_dialog.cpp +++ b/proto-wine/ftnoir_protocol_wine_dialog.cpp @@ -1,19 +1,32 @@ #include "ftnoir_protocol_wine.h" #include +#include + #include "api/plugin-api.hpp" -static const char* proton_versions[] = { - "5.0", "4.11", "4.2", "3.16", "3.7", +static const char* proton_paths[] = { + "/.steam/steam/steamapps/common", + "/.steam/root/compatibilitytools.d", + "/.local/share/Steam/steamapps/common", }; +static const QStringList proton_filter = { "Proton*" }; + FTControls::FTControls() { ui.setupUi(this); - for (const char* version : proton_versions) - ui.proton_version->addItem(version, QVariant{version}); - - tie_setting(s.proton_version, ui.proton_version); + for (const char* path : proton_paths) { + QDir dir(QDir::homePath() + path); + dir.setFilter(QDir::Dirs); + dir.setNameFilters(proton_filter); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + ui.proton_version->addItem(fileInfo.fileName(), QVariant{fileInfo.filePath()}); + } + } + tie_setting(s.proton_path, ui.proton_version); tie_setting(s.variant_wine, ui.variant_wine); tie_setting(s.variant_proton, ui.variant_proton); tie_setting(s.esync, ui.esync); @@ -37,4 +50,3 @@ void FTControls::doCancel() s.b->reload(); close(); } - diff --git a/proto-wine/proton.cpp b/proto-wine/proton.cpp index 15306d26..e8d69fd9 100644 --- a/proto-wine/proton.cpp +++ b/proto-wine/proton.cpp @@ -7,55 +7,79 @@ #ifndef OTR_WINE_NO_WRAPPER +#include #include #include #include +#include +#include -QProcessEnvironment make_steam_environ(const QString& proton_version, int appid) + +static const char* steam_paths[] = { + "/.steam/steam/steamapps/compatdata", + "/.local/share/Steam/steamapps/compatdata", +}; + +static const char* runtime_paths[] = { + "/.local/share/Steam/ubuntu12_32/steam-runtime", + "/.steam/ubuntu12_32/steam-runtime", +}; + + +QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) { auto ret = QProcessEnvironment::systemEnvironment(); QString home = qgetenv("HOME"); + QString runtime_path; + + for (const char* path : runtime_paths) { + QDir dir(QDir::homePath() + path); + if (dir.exists()) + runtime_path = dir.absolutePath(); + } auto expand = [&](QString x) { x.replace("HOME", home); - x.replace("PROTON", proton_version); + x.replace("PROTON_PATH", proton_path); + x.replace("RUNTIME_PATH", runtime_path); return x; }; QString path = expand( - ":HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/bin" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/bin" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/usr/bin" + ":PROTON_PATH/dist/bin" ); path += ':'; path += qgetenv("PATH"); ret.insert("PATH", path); QString library_path = expand( - ":HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/lib" - ":HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/lib64" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/pinned_libs_32" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/pinned_libs_64" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/lib/i386-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/lib" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/usr/lib/i386-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/i386/usr/lib" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/lib/x86_64-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/lib" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/usr/lib/x86_64-linux-gnu" - ":HOME/.local/share/Steam/ubuntu12_32/steam-runtime/amd64/usr/lib" + ":PROTON_PATH/dist/lib" + ":PROTON_PATH/dist/lib64" + ":RUNTIME_PATH/pinned_libs_32" + ":RUNTIME_PATH/pinned_libs_64" + ":RUNTIME_PATH/i386/lib/i386-linux-gnu" + ":RUNTIME_PATH/i386/lib" + ":RUNTIME_PATH/i386/usr/lib/i386-linux-gnu" + ":RUNTIME_PATH/i386/usr/lib" + ":RUNTIME_PATH/amd64/lib/x86_64-linux-gnu" + ":RUNTIME_PATH/amd64/lib" + ":RUNTIME_PATH/amd64/usr/lib/x86_64-linux-gnu" + ":RUNTIME_PATH/amd64/usr/lib" ); library_path += ':'; library_path += qgetenv("LD_LIBRARY_PATH"); ret.insert("LD_LIBRARY_PATH", library_path); - ret.insert("WINEPREFIX", expand("HOME/.local/share/Steam/steamapps/compatdata/%1/pfx").arg(appid)); + + for (const char* path : steam_paths) { + QDir dir(QDir::homePath() + path + expand("/%1/pfx").arg(appid)); + if (dir.exists()) + ret.insert("WINEPREFIX", dir.absolutePath()); + } return ret; } -QString proton_path(const QString& proton_version) +QString proton_path(const QString& proton_path) { - QString wine_path = "HOME/.local/share/Steam/steamapps/common/Proton PROTON/dist/bin/wine"; - wine_path.replace("HOME", qgetenv("HOME")); - wine_path.replace("PROTON", proton_version); + QString wine_path = proton_path + "/dist/bin/wine"; return wine_path; } -- cgit v1.2.3 From e00575681938da48c3dc41a798a7211ae6ca4b87 Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Sun, 14 Jun 2020 06:54:54 +0200 Subject: Remove prefx and sort includes --- proto-wine/ftnoir_protocol_wine.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto-wine/ftnoir_protocol_wine.h b/proto-wine/ftnoir_protocol_wine.h index fc537b60..f7346be9 100644 --- a/proto-wine/ftnoir_protocol_wine.h +++ b/proto-wine/ftnoir_protocol_wine.h @@ -9,10 +9,10 @@ #include "options/options.hpp" using namespace options; -#include -#include #include -#include +#include +#include +#include #include -- cgit v1.2.3 From dc66734ae4d5c95aff3a365c499504e758bc343b Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Sun, 14 Jun 2020 07:00:05 +0200 Subject: Simplify proton dirfilter --- proto-wine/ftnoir_protocol_wine_dialog.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/proto-wine/ftnoir_protocol_wine_dialog.cpp b/proto-wine/ftnoir_protocol_wine_dialog.cpp index 76ccfdb5..a954a752 100644 --- a/proto-wine/ftnoir_protocol_wine_dialog.cpp +++ b/proto-wine/ftnoir_protocol_wine_dialog.cpp @@ -10,8 +10,6 @@ static const char* proton_paths[] = { "/.local/share/Steam/steamapps/common", }; -static const QStringList proton_filter = { "Proton*" }; - FTControls::FTControls() { ui.setupUi(this); @@ -19,7 +17,7 @@ FTControls::FTControls() for (const char* path : proton_paths) { QDir dir(QDir::homePath() + path); dir.setFilter(QDir::Dirs); - dir.setNameFilters(proton_filter); + dir.setNameFilters({ "Proton*" }); QFileInfoList list = dir.entryInfoList(); for (int i = 0; i < list.size(); ++i) { QFileInfo fileInfo = list.at(i); -- cgit v1.2.3 From beac0c60e8188cb593ac82df2c0773576b493c93 Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Sun, 14 Jun 2020 07:00:40 +0200 Subject: Remove unnecessary variable assignment --- proto-wine/proton.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/proto-wine/proton.cpp b/proto-wine/proton.cpp index e8d69fd9..f2b0269e 100644 --- a/proto-wine/proton.cpp +++ b/proto-wine/proton.cpp @@ -79,8 +79,7 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) QString proton_path(const QString& proton_path) { - QString wine_path = proton_path + "/dist/bin/wine"; - return wine_path; + return proton_path + "/dist/bin/wine"; } #endif -- cgit v1.2.3 From 8444c609936606a361dd2681a6e2356e0d5ee81c Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Sun, 14 Jun 2020 09:07:27 +0200 Subject: Implement error handling --- proto-wine/ftnoir_protocol_wine.cpp | 11 ++++++++--- proto-wine/proton.cpp | 39 ++++++++++++++++++++++--------------- proto-wine/proton.h | 23 ++++++++++++++++++++++ 3 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 proto-wine/proton.h diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index 63308e9f..7052ea41 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -1,4 +1,5 @@ #include "ftnoir_protocol_wine.h" +#include "proton.h" #ifndef OTR_WINE_NO_WRAPPER # include "csv/csv.h" #endif @@ -74,9 +75,13 @@ module_status wine::initialize() QString proton_path(const QString& proton_path); wine_path = proton_path(s.proton_path().toString()); - env = make_steam_environ(s.proton_path().toString(), s.proton_appid); + try { + env = make_steam_environ(s.proton_path().toString(), s.proton_appid); + } catch(const ProtonException &e) { + return error(e.getMessage()); + } } - else + { QString wineprefix = "~/.wine"; if (!s.wineprefix->isEmpty()) @@ -85,7 +90,7 @@ module_status wine::initialize() wineprefix = qgetenv("HOME") + wineprefix.mid(1); if (wineprefix[0] != '/') - error(tr("Wine prefix must be an absolute path (given '%1')").arg(wineprefix)); + return error(tr("Wine prefix must be an absolute path (given '%1')").arg(wineprefix)); env.insert("WINEPREFIX", wineprefix); } diff --git a/proto-wine/proton.cpp b/proto-wine/proton.cpp index f2b0269e..b1eb8b9e 100644 --- a/proto-wine/proton.cpp +++ b/proto-wine/proton.cpp @@ -7,12 +7,13 @@ #ifndef OTR_WINE_NO_WRAPPER +#include "proton.h" + #include -#include -#include -#include #include #include +#include +#include static const char* steam_paths[] = { @@ -30,7 +31,14 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) { auto ret = QProcessEnvironment::systemEnvironment(); QString home = qgetenv("HOME"); - QString runtime_path; + QString runtime_path, app_wineprefix; + + auto expand = [&](QString x) { + x.replace("HOME", home); + x.replace("PROTON_PATH", proton_path); + x.replace("RUNTIME_PATH", runtime_path); + return x; + }; for (const char* path : runtime_paths) { QDir dir(QDir::homePath() + path); @@ -38,12 +46,16 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) runtime_path = dir.absolutePath(); } - auto expand = [&](QString x) { - x.replace("HOME", home); - x.replace("PROTON_PATH", proton_path); - x.replace("RUNTIME_PATH", runtime_path); - return x; - }; + if (runtime_path.isEmpty()) + ProtonException(QString("Couldn't find a Steam runtime.")).raise(); + + for (const char* path : steam_paths) { + QDir dir(QDir::homePath() + path + expand("/%1/pfx").arg(appid)); + if (dir.exists()) + app_wineprefix = dir.absolutePath(); + } + if (app_wineprefix.isEmpty()) + ProtonException(QString("Couldn't find a Wineprefix for AppId %1").arg(appid)).raise(); QString path = expand( ":PROTON_PATH/dist/bin" @@ -67,12 +79,7 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) ); library_path += ':'; library_path += qgetenv("LD_LIBRARY_PATH"); ret.insert("LD_LIBRARY_PATH", library_path); - - for (const char* path : steam_paths) { - QDir dir(QDir::homePath() + path + expand("/%1/pfx").arg(appid)); - if (dir.exists()) - ret.insert("WINEPREFIX", dir.absolutePath()); - } + ret.insert("WINEPREFIX", app_wineprefix); return ret; } diff --git a/proto-wine/proton.h b/proto-wine/proton.h new file mode 100644 index 00000000..08179c3d --- /dev/null +++ b/proto-wine/proton.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +class ProtonException : public QException +{ +public: + ProtonException(const QString& message) + : message(message) {} + + virtual ~ProtonException() + {} + + void raise() const { throw *this; } + ProtonException *clone() const { return new ProtonException(*this); } + + QString getMessage() const { + return message; + } +private: + QString message; +}; -- cgit v1.2.3 From 342dbc9724c451ce8fc96bb5437030b8c1875fee Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Wed, 17 Jun 2020 08:00:32 +0200 Subject: Replace exception handling with error return value --- proto-wine/ftnoir_protocol_wine.cpp | 14 +++++++------- proto-wine/proton.cpp | 20 ++++++++++---------- proto-wine/proton.h | 23 ----------------------- 3 files changed, 17 insertions(+), 40 deletions(-) delete mode 100644 proto-wine/proton.h diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index 7052ea41..a9de7557 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -1,5 +1,4 @@ #include "ftnoir_protocol_wine.h" -#include "proton.h" #ifndef OTR_WINE_NO_WRAPPER # include "csv/csv.h" #endif @@ -71,15 +70,16 @@ module_status wine::initialize() if (s.proton_appid == 0) return error(tr("Must specify application id for Proton (Steam Play)")); - QProcessEnvironment make_steam_environ(const QString& proton_path, int appid); + std::tuple make_steam_environ(const QString& proton_path, int appid); QString proton_path(const QString& proton_path); wine_path = proton_path(s.proton_path().toString()); - try { - env = make_steam_environ(s.proton_path().toString(), s.proton_appid); - } catch(const ProtonException &e) { - return error(e.getMessage()); - } + qDebug() << s.proton_path().toString(); + auto [proton_env, error_string, success] = make_steam_environ(s.proton_path().toString(), s.proton_appid); + env = proton_env; + + if (!success) + return error(error_string); } { diff --git a/proto-wine/proton.cpp b/proto-wine/proton.cpp index b1eb8b9e..5ecd1f93 100644 --- a/proto-wine/proton.cpp +++ b/proto-wine/proton.cpp @@ -7,8 +7,6 @@ #ifndef OTR_WINE_NO_WRAPPER -#include "proton.h" - #include #include #include @@ -27,9 +25,11 @@ static const char* runtime_paths[] = { }; -QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) +std::tuple make_steam_environ(const QString& proton_path, int appid) { - auto ret = QProcessEnvironment::systemEnvironment(); + using ret = std::tuple; + auto env = QProcessEnvironment::systemEnvironment(); + QString error = ""; QString home = qgetenv("HOME"); QString runtime_path, app_wineprefix; @@ -47,7 +47,7 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) } if (runtime_path.isEmpty()) - ProtonException(QString("Couldn't find a Steam runtime.")).raise(); + error = QString("Couldn't find a Steam runtime."); for (const char* path : steam_paths) { QDir dir(QDir::homePath() + path + expand("/%1/pfx").arg(appid)); @@ -55,13 +55,13 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) app_wineprefix = dir.absolutePath(); } if (app_wineprefix.isEmpty()) - ProtonException(QString("Couldn't find a Wineprefix for AppId %1").arg(appid)).raise(); + error = QString("Couldn't find a Wineprefix for AppId %1").arg(appid); QString path = expand( ":PROTON_PATH/dist/bin" ); path += ':'; path += qgetenv("PATH"); - ret.insert("PATH", path); + env.insert("PATH", path); QString library_path = expand( ":PROTON_PATH/dist/lib" @@ -78,10 +78,10 @@ QProcessEnvironment make_steam_environ(const QString& proton_path, int appid) ":RUNTIME_PATH/amd64/usr/lib" ); library_path += ':'; library_path += qgetenv("LD_LIBRARY_PATH"); - ret.insert("LD_LIBRARY_PATH", library_path); - ret.insert("WINEPREFIX", app_wineprefix); + env.insert("LD_LIBRARY_PATH", library_path); + env.insert("WINEPREFIX", app_wineprefix); - return ret; + return ret(env, error, error.isEmpty()); } QString proton_path(const QString& proton_path) diff --git a/proto-wine/proton.h b/proto-wine/proton.h deleted file mode 100644 index 08179c3d..00000000 --- a/proto-wine/proton.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -class ProtonException : public QException -{ -public: - ProtonException(const QString& message) - : message(message) {} - - virtual ~ProtonException() - {} - - void raise() const { throw *this; } - ProtonException *clone() const { return new ProtonException(*this); } - - QString getMessage() const { - return message; - } -private: - QString message; -}; -- cgit v1.2.3 From 5e3cd6fbe898c6452e61b4edb8d78d4d158fc254 Mon Sep 17 00:00:00 2001 From: Russell Sim Date: Wed, 17 Jun 2020 08:02:28 +0200 Subject: Remove qDebug statement --- proto-wine/ftnoir_protocol_wine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/proto-wine/ftnoir_protocol_wine.cpp b/proto-wine/ftnoir_protocol_wine.cpp index a9de7557..6652eb48 100644 --- a/proto-wine/ftnoir_protocol_wine.cpp +++ b/proto-wine/ftnoir_protocol_wine.cpp @@ -74,7 +74,6 @@ module_status wine::initialize() QString proton_path(const QString& proton_path); wine_path = proton_path(s.proton_path().toString()); - qDebug() << s.proton_path().toString(); auto [proton_env, error_string, success] = make_steam_environ(s.proton_path().toString(), s.proton_appid); env = proton_env; -- cgit v1.2.3