diff --git a/src/httpcommon.cpp b/src/httpcommon.cpp index 355ab6e9..a67943f3 100644 --- a/src/httpcommon.cpp +++ b/src/httpcommon.cpp @@ -30,7 +30,6 @@ #include "platform/common.h" #include "rtsp.h" #include "utility.h" -#include "uuid.h" namespace http { using namespace std::literals; @@ -43,6 +42,7 @@ namespace http { user_creds_exist(const std::string &file); std::string unique_id; + uuid_util::uuid_t uuid; net::net_e origin_web_ui_allowed; int @@ -51,7 +51,8 @@ namespace http { origin_web_ui_allowed = net::from_enum_string(config::nvhttp.origin_web_ui_allowed); if (clean_slate) { - unique_id = uuid_util::uuid_t::generate().string(); + uuid = uuid_util::uuid_t::generate(); + unique_id = uuid.string(); auto dir = std::filesystem::temp_directory_path() / "Sunshine"sv; config::nvhttp.cert = (dir / ("cert-"s + unique_id)).string(); config::nvhttp.pkey = (dir / ("pkey-"s + unique_id)).string(); diff --git a/src/httpcommon.h b/src/httpcommon.h index 324ada03..31d78380 100644 --- a/src/httpcommon.h +++ b/src/httpcommon.h @@ -6,6 +6,7 @@ #include "network.h" #include "thread_safe.h" +#include "uuid.h" namespace http { @@ -30,6 +31,7 @@ namespace http { url_get_host(const std::string &url); extern std::string unique_id; + extern uuid_util::uuid_t uuid; extern net::net_e origin_web_ui_allowed; } // namespace http diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index b9e4fe9e..38ff4d88 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -238,9 +238,11 @@ namespace nvhttp { auto unique_id_p = tree.get_optional("root.uniqueid"); if (!unique_id_p) { // This file doesn't contain moonlight credentials - http::unique_id = uuid_util::uuid_t::generate().string(); + http::uuid = uuid_util::uuid_t::generate(); + http::unique_id = http::uuid.string(); return; } + http::uuid = uuid_util::uuid_t::parse(*unique_id_p); http::unique_id = std::move(*unique_id_p); auto root = tree.get_child("root"); @@ -335,6 +337,7 @@ namespace nvhttp { launch_session->gcmap = util::from_view(get_arg(args, "gcmap", "0")); launch_session->enable_hdr = util::from_view(get_arg(args, "hdrMode", "0")); launch_session->virtual_display = util::from_view(get_arg(args, "virtualDisplay", "0")); + launch_session->scale_factor = util::from_view(get_arg(args, "scale_factor", "100")); // Encrypted RTSP is enabled with client reported corever >= 1 auto corever = util::from_view(get_arg(args, "corever", "0")); diff --git a/src/platform/windows/virtual_display.cpp b/src/platform/windows/virtual_display.cpp index b596a07e..2a1920f3 100644 --- a/src/platform/windows/virtual_display.cpp +++ b/src/platform/windows/virtual_display.cpp @@ -175,7 +175,6 @@ std::wstring createVirtualDisplay( } memcpy((void*)&guid, (void*)s_client_uid, len); } else { - guid = DEFAULT_DISPLAY_GUID; s_client_uid = "unknown"; } diff --git a/src/process.cpp b/src/process.cpp index 93c2bdc7..0ed9ca4a 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -25,6 +25,7 @@ #include "crypto.h" #include "logging.h" #include "platform/common.h" +#include "httpcommon.h" #include "system_tray.h" #include "utility.h" @@ -157,13 +158,29 @@ namespace proc { _app_prep_begin = std::begin(_app.prep_cmds); _app_prep_it = _app_prep_begin; + uint32_t client_width = launch_session->width; + uint32_t client_height = launch_session->height; + + uint32_t render_width = client_width; + uint32_t render_height = client_height; + + if (launch_session->scale_factor != 100) { + // Chop the last bit to ensure the scaled resolution is even numbered + // Most odd resolution won't work well + render_width *= 100 / launch_session->scale_factor & ~1; + render_height *= 100 / launch_session->scale_factor & ~1; + } + // Add Stream-specific environment variables _env["SUNSHINE_APP_ID"] = std::to_string(_app_id); _env["SUNSHINE_APP_NAME"] = _app.name; _env["SUNSHINE_CLIENT_UID"] = launch_session->unique_id; _env["SUNSHINE_CLIENT_NAME"] = launch_session->device_name; - _env["SUNSHINE_CLIENT_WIDTH"] = std::to_string(launch_session->width); - _env["SUNSHINE_CLIENT_HEIGHT"] = std::to_string(launch_session->height); + _env["SUNSHINE_CLIENT_WIDTH"] = std::to_string(render_width); + _env["SUNSHINE_CLIENT_HEIGHT"] = std::to_string(render_height); + _env["SUNSHINE_CLIENT_RENDER_WIDTH"] = std::to_string(launch_session->width); + _env["SUNSHINE_CLIENT_RENDER_HEIGHT"] = std::to_string(launch_session->height); + _env["SUNSHINE_CLIENT_SCALE_FACTOR"] = std::to_string(launch_session->scale_factor); _env["SUNSHINE_CLIENT_FPS"] = std::to_string(launch_session->fps); _env["SUNSHINE_CLIENT_HDR"] = launch_session->enable_hdr ? "true" : "false"; _env["SUNSHINE_CLIENT_GCMAP"] = std::to_string(launch_session->gcmap); @@ -216,12 +233,14 @@ namespace proc { if (vdisplayDriverInitialized) { std::wstring prevPrimaryDisplayName = VDISPLAY::getPrimaryDisplay(); + launch_session->display_guid = *(GUID*)(void*)&http::uuid; + std::wstring vdisplayName = VDISPLAY::createVirtualDisplay( launch_session->unique_id.c_str(), launch_session->device_name.c_str(), _app.name.c_str(), - launch_session->width, - launch_session->height, + render_width, + render_height, launch_session->fps, launch_session->display_guid ); diff --git a/src/rtsp.h b/src/rtsp.h index deeee5e1..928ee67c 100644 --- a/src/rtsp.h +++ b/src/rtsp.h @@ -34,6 +34,7 @@ namespace rtsp_stream { bool enable_hdr; bool enable_sops; bool virtual_display; + uint32_t scale_factor; std::optional rtsp_cipher; std::string rtsp_url_scheme; diff --git a/src/uuid.h b/src/uuid.h index a7b4db2e..632396ad 100644 --- a/src/uuid.h +++ b/src/uuid.h @@ -5,6 +5,7 @@ #pragma once #include +#include /** * @brief UUID utilities. @@ -40,6 +41,40 @@ namespace uuid_util { return generate(engine); } + static uuid_t + parse(std::string& uuid_str) { + if (uuid_str.length() != 36) { + throw std::invalid_argument("Invalid UUID string length"); + } + + uuid_t uuid; + unsigned int temp16_1; + unsigned int temp32_1, temp32_2; + + // Parse UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + unsigned int data1, data2; + std::sscanf( + uuid_str.c_str(), "%8x-%4x-%4x-%4x-%8x%4x", + &uuid.b32[0], &data1, &data2, &temp16_1, &temp32_1, &temp32_2 + ); + + // Assign parsed values into uuid_t structure + uuid.b16[2] = static_cast(data1); + uuid.b16[3] = static_cast(data2); + + // Manually splitting the last segments into bytes + uuid.b8[8] = (temp16_1 >> 8) & 0xFF; + uuid.b8[9] = temp16_1 & 0xFF; + uuid.b8[10] = (temp32_1 >> 24) & 0xFF; + uuid.b8[11] = (temp32_1 >> 16) & 0xFF; + uuid.b8[12] = (temp32_1 >> 8) & 0xFF; + uuid.b8[13] = temp32_1 & 0xFF; + uuid.b8[14] = (temp32_2 >> 8) & 0xFF; + uuid.b8[15] = temp32_2 & 0xFF; + + return uuid; + } + [[nodiscard]] std::string string() const { std::string result;