diff --git a/docs/source/about/app_examples.rst b/docs/source/about/app_examples.rst index 30c99070..531a647e 100644 --- a/docs/source/about/app_examples.rst +++ b/docs/source/about/app_examples.rst @@ -125,35 +125,35 @@ Linux Changing Resolution and Refresh Rate (Linux - X11) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+----------------------+--------------------------------------------------------------+ -| **Field** | **Value** | -+----------------------+--------------------------------------------------------------+ -| Command Preparations | Do: ``xrandr --output HDMI-1 --mode 1920x1080 --rate 60`` | -| +--------------------------------------------------------------+ -| | Undo: ``xrandr --output HDMI-1 --mode 3840×2160 --rate 120`` | -+----------------------+--------------------------------------------------------------+ ++----------------------+---------------------------------------------------------------------------------------------------------------------------------------+ +| **Field** | **Value** | ++----------------------+---------------------------------------------------------------------------------------------------------------------------------------+ +| Command Preparations | Do: ``sh -c "xrandr --output HDMI-1 --mode \"${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}\" --range ${SUNSHINE_CLIENT_FPS}"`` | +| +---------------------------------------------------------------------------------------------------------------------------------------+ +| | Undo: ``xrandr --output HDMI-1 --mode 3840x2160 --rate 120`` | ++----------------------+---------------------------------------------------------------------------------------------------------------------------------------+ Changing Resolution and Refresh Rate (Linux - Wayland) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+----------------------+-------------------------------------------------------------+ -| **Field** | **Value** | -+----------------------+-------------------------------------------------------------+ -| Command Preparations | Do: ``wlr-xrandr --output HDMI-1 --mode 1920x1080@60Hz`` | -| +-------------------------------------------------------------+ -| | Undo: ``wlr-xrandr --output HDMI-1 --mode 3840×2160@120Hz`` | -+----------------------+-------------------------------------------------------------+ ++----------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| **Field** | **Value** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| Command Preparations | Do: ``sh -c "wlr-xrandr --output HDMI-1 --mode \"${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}Hz\""`` | +| +-------------------------------------------------------------------------------------------------------------------------------------+ +| | Undo: ``wlr-xrandr --output HDMI-1 --mode 3840x2160@120Hz`` | ++----------------------+-------------------------------------------------------------------------------------------------------------------------------------+ Changing Resolution and Refresh Rate (Linux - KDE Plasma - Wayland and X11) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -+----------------------+-------------------------------------------------------------+ -| **Field** | **Value** | -+----------------------+-------------------------------------------------------------+ -| Command Preparations | Do: ``kscreen-doctor output.HDMI-A-1.mode.1920x1080@60`` | -| +-------------------------------------------------------------+ -| | Undo: ``kscreen-doctor output.HDMI-A-1.mode.3840×2160@120`` | -+----------------------+-------------------------------------------------------------+ ++----------------------+----------------------------------------------------------------------------------------------------------------------------------+ +| **Field** | **Value** | ++----------------------+----------------------------------------------------------------------------------------------------------------------------------+ +| Command Preparations | Do: ``sh -c "kscreen-doctor output.HDMI-A-1.mode.${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}@${SUNSHINE_CLIENT_FPS}"`` | +| +----------------------------------------------------------------------------------------------------------------------------------+ +| | Undo: ``kscreen-doctor output.HDMI-A-1.mode.3840x2160@120`` | ++----------------------+----------------------------------------------------------------------------------------------------------------------------------+ Flatpak ^^^^^^^ @@ -188,17 +188,13 @@ Changing Resolution and Refresh Rate (Windows) .. Note:: This example uses the `QRes` tool to change the resolution and refresh rate. This tool can be downloaded from their `SourceForge repository `_. -+----------------------+----------------------------------------------------+ -| **Field** | **Value** | -+----------------------+----------------------------------------------------+ -| Command Preparations | Do: ``FullPath\qres.exe /x:1920 /y:1080 /r:60`` | -| +----------------------------------------------------+ -| | Undo: ``FullPath\qres.exe /x:3840 /y:2160 /r:120`` | -+----------------------+----------------------------------------------------+ - -.. Tip:: You can change your host resolution to match the client resolution automatically using the - `Nonary/ResolutionAutomation `_ project. - ++----------------------+------------------------------------------------------------------------------------------------------------------+ +| **Field** | **Value** | ++----------------------+------------------------------------------------------------------------------------------------------------------+ +| Command Preparations | Do: ``cmd /C FullPath\qres.exe /x:%SUNSHINE_CLIENT_WIDTH% /y:%SUNSHINE_CLIENT_WIDTH% /r:%SUNSHINE_CLIENT_FPS%`` | +| +------------------------------------------------------------------------------------------------------------------+ +| | Undo: ``cmd /C FullPath\qres.exe /x:3840 /y:2160 /r:120`` | ++----------------------+------------------------------------------------------------------------------------------------------------------+ Elevating Commands (Windows) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/nvhttp.cpp b/src/nvhttp.cpp index dfa0b9fe..b23a087c 100644 --- a/src/nvhttp.cpp +++ b/src/nvhttp.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // local includes #include "config.h" @@ -267,12 +268,32 @@ namespace nvhttp { launch_session.host_audio = host_audio; launch_session.gcm_key = util::from_hex(get_arg(args, "rikey"), true); + std::stringstream mode = std::stringstream(get_arg(args, "mode")); + // Split mode by the char "x", to populate width/height/fps + int x = 0; + std::string segment; + while (std::getline(mode, segment, 'x')) { + if (x == 0) launch_session.width = atoi(segment.c_str()); + if (x == 1) launch_session.height = atoi(segment.c_str()); + if (x == 2) launch_session.fps = atoi(segment.c_str()); + x++; + } + launch_session.unique_id = (get_arg(args, "uniqueid")); + launch_session.uuid = (get_arg(args, "uuid")); + launch_session.appid = util::from_view(get_arg(args, "appid")); + launch_session.enable_sops = util::from_view(get_arg(args, "sops")); + launch_session.surround_info = util::from_view(get_arg(args, "surroundAudioInfo")); + launch_session.gcmap = util::from_view(get_arg(args, "gcmap")); + launch_session.enable_hdr = 0; + if (args.find("enableHdr"s) != std::end(args)) { + launch_session.enable_hdr = util::from_view(get_arg(args, "enableHdr")); + } uint32_t prepend_iv = util::endian::big(util::from_view(get_arg(args, "rikeyid"))); auto prepend_iv_p = (uint8_t *) &prepend_iv; auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv)); std::fill(next, std::end(launch_session.iv), 0); - + BOOST_LOG(error) << launch_session.width << " h: " << launch_session.height << " fps: " << launch_session.fps; return launch_session; } @@ -757,8 +778,11 @@ namespace nvhttp { } } + host_audio = util::from_view(get_arg(args, "localAudioPlayMode")); + auto launch_session = make_launch_session(host_audio, args); + if (appid > 0) { - auto err = proc::proc.execute(appid); + auto err = proc::proc.execute(appid, launch_session); if (err) { tree.put("root..status_code", err); tree.put("root..status_message", "Failed to start the specified application"); @@ -768,8 +792,7 @@ namespace nvhttp { } } - host_audio = util::from_view(get_arg(args, "localAudioPlayMode")); - rtsp_stream::launch_session_raise(make_launch_session(host_audio, args)); + rtsp_stream::launch_session_raise(launch_session); tree.put("root..status_code", 200); tree.put("root.sessionUrl0", "rtsp://"s + request->local_endpoint().address().to_string() + ':' + std::to_string(map_port(rtsp_stream::RTSP_SETUP_PORT))); diff --git a/src/process.cpp b/src/process.cpp index 1a0f8e53..83ada346 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -1,6 +1,6 @@ /** * @file src/process.cpp - * @brief todo + * @brief Handles the startup and shutdown of the apps started by a streaming Session. */ #define BOOST_BIND_GLOBAL_PLACEHOLDERS @@ -101,7 +101,7 @@ namespace proc { } int - proc_t::execute(int app_id) { + proc_t::execute(int app_id, rtsp_stream::launch_session_t launch_session) { // Ensure starting from a clean slate terminate(); @@ -120,6 +120,29 @@ namespace proc { _app_prep_begin = std::begin(_app.prep_cmds); _app_prep_it = _app_prep_begin; + // Add Stream-specific environment variables + _env["SUNSHINE_APP_ID"] = std::to_string(_app_id); + _env["SUNSHINE_APP_NAME"] = _app.name; + _env["SUNSHINE_CLIENT_WIDTH"] = std::to_string(launch_session.width); + _env["SUNSHINE_CLIENT_HEIGHT"] = std::to_string(launch_session.height); + _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); + _env["SUNSHINE_CLIENT_HOST_AUDIO"] = launch_session.host_audio ? "true" : "false"; + _env["SUNSHINE_CLIENT_ENABLE_SOPS"] = launch_session.enable_sops ? "true" : "false"; + int channelCount = launch_session.surround_info & (65535); + switch (channelCount) { + case 2: + _env["SUNSHINE_CLIENT_AUDIO_CONFIGURATION"] = "2.0"; + break; + case 6: + _env["SUNSHINE_CLIENT_AUDIO_CONFIGURATION"] = "5.1"; + break; + case 8: + _env["SUNSHINE_CLIENT_AUDIO_CONFIGURATION"] = "7.1"; + break; + } + if (!_app.output.empty() && _app.output != "null"sv) { #ifdef _WIN32 // fopen() interprets the filename as an ANSI string on Windows, so we must convert it diff --git a/src/process.h b/src/process.h index 038e86f0..25aa1714 100644 --- a/src/process.h +++ b/src/process.h @@ -15,6 +15,7 @@ #include "config.h" #include "platform/common.h" +#include "rtsp.h" #include "utility.h" namespace proc { @@ -65,7 +66,7 @@ namespace proc { _apps(std::move(apps)) {} int - execute(int app_id); + execute(int app_id, rtsp_stream::launch_session_t launch_session); /** * @return _app_id if a process is running, otherwise returns 0 diff --git a/src/rtsp.h b/src/rtsp.h index 2b0355fd..58834f1e 100644 --- a/src/rtsp.h +++ b/src/rtsp.h @@ -17,6 +17,16 @@ namespace rtsp_stream { crypto::aes_t iv; bool host_audio; + std::string unique_id; + std::string uuid; + int width; + int height; + int fps; + int gcmap; + int appid; + int surround_info; + bool enable_hdr; + bool enable_sops; }; void diff --git a/src_assets/common/assets/web/apps.html b/src_assets/common/assets/web/apps.html index 54a3bebf..760a0007 100644 --- a/src_assets/common/assets/web/apps.html +++ b/src_assets/common/assets/web/apps.html @@ -302,6 +302,26 @@ must be a PNG file. If not set, Sunshine will send default box image. +
+
About Environment Variables: All commands get these environment variables by default:
+ + + + + + + + + + + + +
Var Name
SUNSHINE_APP_IDApp ID
SUNSHINE_APP_NAMEApp Name
SUNSHINE_CLIENT_WIDTHThe Width requested by the client
SUNSHINE_CLIENT_HEIGHTThe Height requested by the client
SUNSHINE_CLIENT_FPSThe FPS requested by the client
SUNSHINE_CLIENT_HDR(true/false) if HDR is enabled by the client
SUNSHINE_CLIENT_GCMAP(int) the requested gamepad mask, in a bitset/bitfield format
SUNSHINE_CLIENT_HOST_AUDIO(true/false) if the client has requested host audio
SUNSHINE_CLIENT_ENABLE_SOPS(true/false) if the client has requested the option to optimize the game for optimal streaming
SUNSHINE_CLIENT_AUDIO_CONFIGURATIONThe Audio Configuration requested by the client (2.0/5.1/7.1)
+
Example - QRes for Resolution Automation:
cmd /C <qres path>\QRes.exe /X:%SUNSHINE_CLIENT_WIDTH% /Y:%SUNSHINE_CLIENT_HEIGHT%
+
Example - Xrandr for Resolution Automation:
sh -c "xrandr --output HDMI-1 --mode \"${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT}\" --range 60"
+
Example - displayplacer for Resolution Automation:
sh -c "displayplacer "id: res:${SUNSHINE_CLIENT_WIDTH}x${SUNSHINE_CLIENT_HEIGHT} hz:60 scaling:on origin:(0,0) degree:0""
+ +