diff --git a/src/confighttp.cpp b/src/confighttp.cpp index e58f53ae..79997435 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -494,6 +494,7 @@ void getConfig(resp_https_t response, req_https_t request) { outputTree.put("status", "true"); outputTree.put("platform", SUNSHINE_PLATFORM); + outputTree.put("restart_supported", platf::restart_supported()); auto vars = config::parse_config(read_file(config::sunshine.config_file.c_str())); @@ -537,6 +538,37 @@ void saveConfig(resp_https_t response, req_https_t request) { } } +void restart(resp_https_t response, req_https_t request) { + if(!authenticate(response, request)) return; + + print_req(request); + + std::stringstream ss; + std::stringstream configStream; + ss << request->content.rdbuf(); + pt::ptree outputTree; + auto g = util::fail_guard([&]() { + std::ostringstream data; + + pt::write_json(data, outputTree); + response->write(data.str()); + }); + + if(!platf::restart_supported()) { + outputTree.put("status", false); + outputTree.put("error", "Restart is not currently supported on this platform"); + return; + } + + if(!platf::restart()) { + outputTree.put("status", false); + outputTree.put("error", "Restart failed"); + return; + } + + outputTree.put("status", true); +} + void savePassword(resp_https_t response, req_https_t request) { if(!config::sunshine.username.empty() && !authenticate(response, request)) return; @@ -678,6 +710,7 @@ void start() { server.resource["^/api/apps$"]["POST"] = saveApp; server.resource["^/api/config$"]["GET"] = getConfig; server.resource["^/api/config$"]["POST"] = saveConfig; + server.resource["^/api/restart$"]["POST"] = restart; server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; diff --git a/src/platform/common.h b/src/platform/common.h index 732b56bb..fe074c5b 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -318,6 +318,9 @@ void adjust_thread_priority(thread_priority_e priority); void streaming_will_start(); void streaming_will_stop(); +bool restart_supported(); +bool restart(); + input_t input(); void move_mouse(input_t &input, int deltaX, int deltaY); void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y); diff --git a/src/platform/linux/misc.cpp b/src/platform/linux/misc.cpp index 1a4c30d6..35e68b96 100644 --- a/src/platform/linux/misc.cpp +++ b/src/platform/linux/misc.cpp @@ -165,6 +165,16 @@ void streaming_will_stop() { // Nothing to do } +bool restart_supported() { + // Restart not supported yet + return false; +} + +bool restart() { + // Restart not supported yet + return false; +} + namespace source { enum source_e : std::size_t { #ifdef SUNSHINE_BUILD_CUDA diff --git a/src/platform/macos/misc.cpp b/src/platform/macos/misc.cpp index 0bfef608..eb99de78 100644 --- a/src/platform/macos/misc.cpp +++ b/src/platform/macos/misc.cpp @@ -143,6 +143,16 @@ void streaming_will_stop() { // Nothing to do } +bool restart_supported() { + // Restart not supported yet + return false; +} + +bool restart() { + // Restart not supported yet + return false; +} + } // namespace platf namespace dyn { diff --git a/src/platform/windows/misc.cpp b/src/platform/windows/misc.cpp index 4f9d211c..88e714d3 100644 --- a/src/platform/windows/misc.cpp +++ b/src/platform/windows/misc.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -522,4 +523,16 @@ void streaming_will_stop() { DwmEnableMMCSS(false); } +bool restart_supported() { + // Restart is supported if we're running from the service + return (GetConsoleWindow() == NULL); +} + +bool restart() { + // Raise SIGINT to trigger the graceful exit logic. The service will + // restart us in a few seconds. + std::raise(SIGINT); + return true; +} + } // namespace platf \ No newline at end of file diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index bb961c62..096233dc 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -765,11 +765,18 @@ -
- Success! Restart Sunshine to apply changes +
+ Success! Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions. +
+
+ Success! Restart Sunshine to apply changes. +
+
+ Success! Sunshine is restarting to apply changes.
+
@@ -779,7 +786,9 @@ data() { return { platform: "", - success: false, + restart_supported: false, + saved: false, + restarted: false, config: null, fps: [], resolutions: [], @@ -836,6 +845,7 @@ .then((r) => { this.config = r; this.platform = this.config.platform; + this.restart_supported = (this.config.restart_supported === "true"); var app = document.getElementById("app"); if (this.platform == "windows") { @@ -856,6 +866,7 @@ delete this.config.status; delete this.config.platform; + delete this.config.restart_supported; //Populate default values if not present in config this.config.key_rightalt_to_key_win = this.config.key_rightalt_to_key_win || "disabled"; @@ -895,8 +906,7 @@ }); }, methods: { - save() { - this.success = false; + serialize() { let nl = this.config === "windows" ? "\r\n" : "\n"; this.config.resolutions = "[" + @@ -906,12 +916,31 @@ nl + "]"; this.config.fps = JSON.stringify(this.fps); - + }, + save() { + this.saved = this.restarted = false; + this.serialize(); fetch("/api/config", { method: "POST", body: JSON.stringify(this.config), }).then((r) => { - if (r.status == 200) this.success = true; + if (r.status == 200) this.saved = true; + }); + }, + apply() { + this.saved = this.restarted = false; + this.serialize(); + fetch("/api/config", { + method: "POST", + body: JSON.stringify(this.config), + }).then((r) => { + if (r.status == 200) { + fetch("/api/restart", { + method: "POST", + }).then((r) => { + if (r.status == 200) this.restarted = true; + }); + } }); }, }, diff --git a/src_assets/common/assets/web/troubleshooting.html b/src_assets/common/assets/web/troubleshooting.html index 513319d0..f517348e 100644 --- a/src_assets/common/assets/web/troubleshooting.html +++ b/src_assets/common/assets/web/troubleshooting.html @@ -7,10 +7,10 @@

If Moonlight complains about an app currently running, force closing the - app should fix the issue + app should fix the issue.

- Application Closed Successfuly! + Application Closed Successfully!
Error while closing Appplication @@ -22,6 +22,28 @@
+ +
+
+

Restart Sunshine

+
+

+ If Sunshine isn't working properly, you can try restarting it. + This will terminate any running sessions. +

+
+ Sunshine is restarting +
+
+ Error restarting Sunshine +
+
+ +
+
+
@@ -68,6 +90,9 @@ closeAppStatus: null, unpairAllPressed: false, unpairAllStatus: null, + restartSupported: false, + restartPressed: false, + restartStatus: null, logs: 'Loading...', logFilter: null, logInterval: null, @@ -86,6 +111,11 @@ this.refreshLogs(); }, 5000); this.refreshLogs(); + fetch("/api/config") + .then((r) => r.json()) + .then((r) => { + this.restartSupported = (r.restart_supported === "true"); + }); }, beforeDestroy(){ clearInterval(this.logInterval); @@ -124,7 +154,22 @@ }, copyLogs(){ navigator.clipboard.writeText(this.actualLogs); - } + }, + restart() { + this.restartPressed = true; + fetch("/api/restart", { + method: "POST", + }).then((r) => { + this.restartPressed = false; + + // We won't get a response in the success case + this.restartStatus = r.status.toString() !== "false"; + + setTimeout(() => { + this.restartStatus = null; + }, 5000); + }); + }, }, });