Add an Apply button to the Web UI when running as a Win32 Service (#700)

This commit is contained in:
Cameron Gutman
2023-01-05 13:26:54 -06:00
committed by GitHub
parent 5980e520b9
commit 65574a02d4
7 changed files with 153 additions and 10 deletions

View File

@@ -494,6 +494,7 @@ void getConfig(resp_https_t response, req_https_t request) {
outputTree.put("status", "true"); outputTree.put("status", "true");
outputTree.put("platform", SUNSHINE_PLATFORM); 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())); 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) { void savePassword(resp_https_t response, req_https_t request) {
if(!config::sunshine.username.empty() && !authenticate(response, request)) return; if(!config::sunshine.username.empty() && !authenticate(response, request)) return;
@@ -678,6 +710,7 @@ void start() {
server.resource["^/api/apps$"]["POST"] = saveApp; server.resource["^/api/apps$"]["POST"] = saveApp;
server.resource["^/api/config$"]["GET"] = getConfig; server.resource["^/api/config$"]["GET"] = getConfig;
server.resource["^/api/config$"]["POST"] = saveConfig; server.resource["^/api/config$"]["POST"] = saveConfig;
server.resource["^/api/restart$"]["POST"] = restart;
server.resource["^/api/password$"]["POST"] = savePassword; server.resource["^/api/password$"]["POST"] = savePassword;
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp; server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
server.resource["^/api/clients/unpair$"]["POST"] = unpairAll; server.resource["^/api/clients/unpair$"]["POST"] = unpairAll;

View File

@@ -318,6 +318,9 @@ void adjust_thread_priority(thread_priority_e priority);
void streaming_will_start(); void streaming_will_start();
void streaming_will_stop(); void streaming_will_stop();
bool restart_supported();
bool restart();
input_t input(); input_t input();
void move_mouse(input_t &input, int deltaX, int deltaY); 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); void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y);

View File

@@ -165,6 +165,16 @@ void streaming_will_stop() {
// Nothing to do // Nothing to do
} }
bool restart_supported() {
// Restart not supported yet
return false;
}
bool restart() {
// Restart not supported yet
return false;
}
namespace source { namespace source {
enum source_e : std::size_t { enum source_e : std::size_t {
#ifdef SUNSHINE_BUILD_CUDA #ifdef SUNSHINE_BUILD_CUDA

View File

@@ -143,6 +143,16 @@ void streaming_will_stop() {
// Nothing to do // Nothing to do
} }
bool restart_supported() {
// Restart not supported yet
return false;
}
bool restart() {
// Restart not supported yet
return false;
}
} // namespace platf } // namespace platf
namespace dyn { namespace dyn {

View File

@@ -1,3 +1,4 @@
#include <csignal>
#include <filesystem> #include <filesystem>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@@ -522,4 +523,16 @@ void streaming_will_stop() {
DwmEnableMMCSS(false); 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 } // namespace platf

View File

@@ -765,11 +765,18 @@
</div> </div>
</div> </div>
</div> </div>
<div class="alert alert-success my-4" v-if="success"> <div class="alert alert-success my-4" v-if="saved && restart_supported">
<b>Success!</b> Restart Sunshine to apply changes <b>Success!</b> Click 'Apply' to restart Sunshine and apply changes. This will terminate any running sessions.
</div>
<div class="alert alert-success my-4" v-if="saved && !restart_supported">
<b>Success!</b> Restart Sunshine to apply changes.
</div>
<div class="alert alert-success my-4" v-if="restarted">
<b>Success!</b> Sunshine is restarting to apply changes.
</div> </div>
<div class="mb-3 buttons"> <div class="mb-3 buttons">
<button class="btn btn-primary" @click="save">Save</button> <button class="btn btn-primary" @click="save">Save</button>
<button class="btn btn-success" @click="apply" v-if="saved && restart_supported && !restarted">Apply</button>
</div> </div>
</div> </div>
@@ -779,7 +786,9 @@
data() { data() {
return { return {
platform: "", platform: "",
success: false, restart_supported: false,
saved: false,
restarted: false,
config: null, config: null,
fps: [], fps: [],
resolutions: [], resolutions: [],
@@ -836,6 +845,7 @@
.then((r) => { .then((r) => {
this.config = r; this.config = r;
this.platform = this.config.platform; this.platform = this.config.platform;
this.restart_supported = (this.config.restart_supported === "true");
var app = document.getElementById("app"); var app = document.getElementById("app");
if (this.platform == "windows") { if (this.platform == "windows") {
@@ -856,6 +866,7 @@
delete this.config.status; delete this.config.status;
delete this.config.platform; delete this.config.platform;
delete this.config.restart_supported;
//Populate default values if not present in config //Populate default values if not present in config
this.config.key_rightalt_to_key_win = this.config.key_rightalt_to_key_win =
this.config.key_rightalt_to_key_win || "disabled"; this.config.key_rightalt_to_key_win || "disabled";
@@ -895,8 +906,7 @@
}); });
}, },
methods: { methods: {
save() { serialize() {
this.success = false;
let nl = this.config === "windows" ? "\r\n" : "\n"; let nl = this.config === "windows" ? "\r\n" : "\n";
this.config.resolutions = this.config.resolutions =
"[" + "[" +
@@ -906,12 +916,31 @@
nl + nl +
"]"; "]";
this.config.fps = JSON.stringify(this.fps); this.config.fps = JSON.stringify(this.fps);
},
save() {
this.saved = this.restarted = false;
this.serialize();
fetch("/api/config", { fetch("/api/config", {
method: "POST", method: "POST",
body: JSON.stringify(this.config), body: JSON.stringify(this.config),
}).then((r) => { }).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;
});
}
}); });
}, },
}, },

View File

@@ -7,10 +7,10 @@
<br /> <br />
<p> <p>
If Moonlight complains about an app currently running, force closing the If Moonlight complains about an app currently running, force closing the
app should fix the issue app should fix the issue.
</p> </p>
<div class="alert alert-success" v-if="closeAppStatus === true"> <div class="alert alert-success" v-if="closeAppStatus === true">
Application Closed Successfuly! Application Closed Successfully!
</div> </div>
<div class="alert alert-danger" v-if="closeAppStatus === false"> <div class="alert alert-danger" v-if="closeAppStatus === false">
Error while closing Appplication Error while closing Appplication
@@ -22,6 +22,28 @@
</div> </div>
</div> </div>
</div> </div>
<!--Restart Sunshine-->
<div class="card p-2 my-4" v-if="restartSupported">
<div class="card-body">
<h2>Restart Sunshine</h2>
<br />
<p>
If Sunshine isn't working properly, you can try restarting it.
This will terminate any running sessions.
</p>
<div class="alert alert-success" v-if="restartStatus === true">
Sunshine is restarting
</div>
<div class="alert alert-danger" v-if="restartStatus === false">
Error restarting Sunshine
</div>
<div>
<button class="btn btn-warning" :disabled="restartPressed" @click="restart">
Restart Sunshine
</button>
</div>
</div>
</div>
<!--Unpair all Clients--> <!--Unpair all Clients-->
<div class="card p-2 my-4"> <div class="card p-2 my-4">
<div class="card-body"> <div class="card-body">
@@ -68,6 +90,9 @@
closeAppStatus: null, closeAppStatus: null,
unpairAllPressed: false, unpairAllPressed: false,
unpairAllStatus: null, unpairAllStatus: null,
restartSupported: false,
restartPressed: false,
restartStatus: null,
logs: 'Loading...', logs: 'Loading...',
logFilter: null, logFilter: null,
logInterval: null, logInterval: null,
@@ -86,6 +111,11 @@
this.refreshLogs(); this.refreshLogs();
}, 5000); }, 5000);
this.refreshLogs(); this.refreshLogs();
fetch("/api/config")
.then((r) => r.json())
.then((r) => {
this.restartSupported = (r.restart_supported === "true");
});
}, },
beforeDestroy(){ beforeDestroy(){
clearInterval(this.logInterval); clearInterval(this.logInterval);
@@ -124,7 +154,22 @@
}, },
copyLogs(){ copyLogs(){
navigator.clipboard.writeText(this.actualLogs); 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);
});
},
}, },
}); });
</script> </script>