Skip to content

Commit 504c1ab

Browse files
committed
websocket for steamvr shutdown
1 parent c663926 commit 504c1ab

File tree

5 files changed

+115
-14
lines changed

5 files changed

+115
-14
lines changed

sidecar/main.cpp

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
//clang-format off
22
#define CROW_MAIN
33
#define CROW_LOG_LEVEL 0
4+
#define CROW_ENFORCE_WS_SPEC
45
#include "crow_all.h"
56

67
//clang-format on
78

89
#include <windows.h>
910

10-
#include <iomanip>
1111
#include <iostream>
1212
#include <string>
13+
#include <unordered_set>
1314

1415
#include "json.hpp"
1516
#include "openvr.h"
@@ -231,6 +232,22 @@ std::string GetOpenVRErrorAsString(vr::EVRInitError err) {
231232
}
232233
}
233234

235+
crow::SimpleApp app;
236+
std::mutex connectionMutex;
237+
std::unordered_set<crow::websocket::connection*> connections;
238+
239+
std::atomic<bool> isRunning = true;
240+
241+
void close() {
242+
for (auto u : connections) u->send_text("shutdown");
243+
244+
app.stop();
245+
246+
vr::VR_Shutdown();
247+
248+
isRunning = false;
249+
}
250+
234251
int main() {
235252
vr::EVRInitError initErr = InitOpenVR();
236253
if (initErr != vr::EVRInitError::VRInitError_None) {
@@ -240,8 +257,6 @@ int main() {
240257

241258
std::cout << "initialised" << std::endl;
242259

243-
crow::SimpleApp app;
244-
245260
CROW_ROUTE(app, "/settings/get").methods(crow::HTTPMethod::Post)([](const crow::request& req) {
246261
auto json = nlohmann::json::parse(req.body, nullptr, true, true);
247262

@@ -268,5 +283,41 @@ int main() {
268283

269284
CROW_ROUTE(app, "/")([]() { return "Pong"; });
270285

271-
app.port(18080).multithreaded().run();
286+
CROW_ROUTE(app, "/ws")
287+
.websocket()
288+
.onaccept([&](const crow::request&) { return true; })
289+
.onopen([&](crow::websocket::connection& conn) {
290+
std::cout << "user connected" << std::endl;
291+
std::lock_guard<std::mutex> _(connectionMutex);
292+
connections.insert(&conn);
293+
})
294+
.onclose([&](crow::websocket::connection& conn, const std::string& reason) {
295+
CROW_LOG_INFO << "websocket connection closed: " << reason;
296+
std::lock_guard<std::mutex> _(connectionMutex);
297+
connections.erase(&conn);
298+
})
299+
.onmessage([&](crow::websocket::connection& /*conn*/, const std::string& data, bool is_binary) {
300+
std::lock_guard<std::mutex> _(connectionMutex);
301+
if (data == "shutdown") close();
302+
});
303+
304+
std::thread serverThread = std::thread([&]() { app.port(18080).multithreaded().run(); });
305+
306+
while (isRunning) {
307+
vr::VREvent_t event;
308+
while (vr::VRSystem()->PollNextEvent(&event, sizeof event)) {
309+
switch (event.eventType) {
310+
case vr::VREvent_Quit:
311+
vr::VRSystem()->AcknowledgeQuit_Exiting();
312+
std::cout << "shutdown" << std::endl;
313+
close();
314+
break;
315+
}
316+
}
317+
318+
Sleep(100);
319+
}
320+
321+
std::cout << "closing program" << std::endl;
322+
return 0;
272323
}

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ tauri-build = { version = "1.0.0-beta.3" }
1515
[dependencies]
1616
serde_json = "1.0"
1717
serde = { version = "1.0", features = [ "derive" ] }
18-
tauri = { version = "1.0.0-beta.8", features = ["fs-read-dir", "fs-read-text-file", "fs-write-file", "http-all", "shell-execute", "shell-open"] }
18+
tauri = { version = "1.0.0-beta.8", features = ["fs-read-dir", "fs-read-text-file", "fs-write-file", "http-all", "shell-execute", "shell-open", "window-all"] }
1919

2020
[features]
2121
default = [ "custom-protocol" ]

src-tauri/tauri.conf.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
"http": {
6565
"all": true,
6666
"request": true
67+
},
68+
"window": {
69+
"all": true
6770
}
6871
},
6972
"windows": [

src/pages/_layout.svelte

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
import {onMount} from "svelte";
1717
import Suspense from "../components/Suspense.svelte";
1818
import OrangeButton from "../components/Input/Button/OrangeButton.svelte";
19+
import {SidecarWebsocket} from "../utils/http";
20+
import {process} from "@tauri-apps/api";
21+
import {appWindow} from '@tauri-apps/api/window';
22+
1923
2024
const _urls = [
2125
["./index", "Configuration"],
@@ -73,18 +77,44 @@
7377
active: !!$isActive(path),
7478
}));
7579
80+
let isClosing = false;
81+
const closeApp = () => {
82+
if (isClosing) return;
83+
isClosing = true;
84+
ToastStore.addToast(ToastStore.severity.WARNING, "SteamVR closed! Closing app...");
85+
86+
setTimeout(() => {
87+
appWindow.close();
88+
process.exit();
89+
}, 1000);
90+
}
91+
7692
const init = async () => {
7793
try {
7894
$state.sidecar.loading = true;
7995
if ($state.sidecar.process) $state.sidecar.process.kill();
8096
8197
await awaitSidecarInit((child) => $state.sidecar.process = child);
82-
$state.sidecar.success = true;
98+
99+
const sidecarWebsocket = new SidecarWebsocket(() => {
100+
$state.sidecar.success = true;
101+
$state.sidecar.loading = false;
102+
}, (event) => {
103+
console.log(event.data);
104+
if (event.data === 'shutdown') closeApp();
105+
}, (event) => {
106+
closeApp();
107+
});
108+
109+
await appWindow.listen('tauri://close-requested', ({event, payload}) => {
110+
sidecarWebsocket.send('shutdown');
111+
})
112+
113+
83114
} catch (e) {
84115
console.error(e);
85116
$state.sidecar.success = false;
86117
ToastStore.addToast(ToastStore.severity.ERROR, e);
87-
} finally {
88118
$state.sidecar.loading = false;
89119
}
90120
}

src/utils/http.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import {http} from "@tauri-apps/api";
2-
import {awaitSidecarInit} from "./sidecar";
2+
import {process} from "@tauri-apps/api";
3+
import ToastStore from "../stores/toast";
34

4-
const basePath = "http://localhost:18080/";
5+
const port = 18080;
56

67
export const makeHTTPRequest = async (url, method = "POST", body, retry = true) => {
78
try {
8-
const response = await http.fetch(basePath + url, {
9+
const response = await http.fetch("http://localhost:" + port + "/" + url, {
910
method: 'POST',
1011
body: {
1112
type: 'Json',
@@ -17,15 +18,31 @@ export const makeHTTPRequest = async (url, method = "POST", body, retry = true)
1718

1819
console.error(response);
1920

20-
throw new Error(response.data ?? 'An unknown error occurred');
21+
throw new Error(response.data ? response.data : "An unknown error occurred");
2122
} catch (e) {
22-
//The server has closed, retry connection
23+
//The server has closed
2324
if (typeof e === 'string' && e.includes('(os error 10061)') && retry) {
24-
await awaitSidecarInit();
25+
ToastStore.addToast(ToastStore.severity.WARNING, "Server has closed - closing app.");
2526

26-
return makeHTTPRequest(url, method, body, false);
27+
setTimeout(() => process.exit(), 500);
2728
}
2829
throw e;
2930
}
31+
}
3032

33+
export function SidecarWebsocket(onOpen = () => {
34+
}, onMessage = () => {
35+
}, onClose = () => {
36+
}) {
37+
const socket = new WebSocket('ws://localhost:' + port + "/ws");
38+
39+
socket.addEventListener('open', onOpen);
40+
41+
socket.addEventListener('message', onMessage);
42+
43+
socket.addEventListener('close', onClose);
44+
45+
return {
46+
send: async (data) => socket.send(data)
47+
};
3148
}

0 commit comments

Comments
 (0)