mirror of
https://github.com/radio95-rnt/RadioPlayer.git
synced 2026-07-29 15:29:14 +02:00
ping?
This commit is contained in:
+23
-21
@@ -20,20 +20,21 @@ from . import Track, PlayerModule, Path, BaseIMCModule
|
||||
MAIN_PATH_DIR = Path("/home/user/mixes")
|
||||
|
||||
async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: multiprocessing.Queue, ws_q: multiprocessing.Queue):
|
||||
await websocket.send(json.dumps({"event": "time", "data": time.monotonic()}))
|
||||
try:
|
||||
initial = {
|
||||
"track": json.loads(shared_data.get("track", "{}")),
|
||||
"dirs": {"files": [i.name for i in list(MAIN_PATH_DIR.iterdir()) if i.is_file()], "dirs": [i.name for i in list(MAIN_PATH_DIR.iterdir()) if i.is_dir()], "base": str(MAIN_PATH_DIR)},
|
||||
}
|
||||
except Exception: initial = {"track": {}, "dirs": {}}
|
||||
await websocket.send(json.dumps({"event": "state", "data": initial}))
|
||||
await websocket.send(json.dumps({"event": "playlist", "data": json.loads(shared_data.get("playlist", "[]"))}))
|
||||
await websocket.send(json.dumps({"event": "rds", "data": json.loads(shared_data.get("rds", "{}"))}))
|
||||
await websocket.send(json.dumps({"event": "state", "data": initial, "time": time.monotonic()}))
|
||||
await websocket.send(json.dumps({"event": "playlist", "data": json.loads(shared_data.get("playlist", "[]")), "time": time.monotonic()}))
|
||||
await websocket.send(json.dumps({"event": "rds", "data": json.loads(shared_data.get("rds", "{}")), "time": time.monotonic()}))
|
||||
|
||||
async for raw in websocket:
|
||||
try: msg: dict = json.loads(raw)
|
||||
except Exception:
|
||||
await websocket.send(json.dumps({"error": "invalid json"}))
|
||||
await websocket.send(json.dumps({"error": "invalid json", "time": time.monotonic()}))
|
||||
continue
|
||||
|
||||
async def get_imc(name, data):
|
||||
@@ -48,7 +49,7 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult
|
||||
action = msg.get("action")
|
||||
if action == "skip":
|
||||
imc_q.put({"name": "procman", "data": {"op": 2}})
|
||||
await websocket.send(json.dumps({"event": "skip"}))
|
||||
await websocket.send(json.dumps({"event": "skip", "time": time.monotonic()}))
|
||||
elif action == "add_to_toplay":
|
||||
songs = msg.get("songs")
|
||||
at_top = msg.get("top", False)
|
||||
@@ -61,21 +62,21 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult
|
||||
await asyncio.get_event_loop().run_in_executor(None, ws_q.put, {"data": result, "event": "toplay"})
|
||||
elif action == "get_toplay":
|
||||
result = await get_imc("activemod", {"action": "get_toplay"})
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504}))
|
||||
else: await websocket.send(json.dumps({"data": result, "event": "toplay"}))
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504, "time": time.monotonic()}))
|
||||
else: await websocket.send(json.dumps({"data": result, "event": "toplay", "time": time.monotonic()}))
|
||||
elif action == "clear_toplay":
|
||||
result = await get_imc("activemod", {"action": "clear_toplay"})
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504}))
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504, "time": time.monotonic()}))
|
||||
else:
|
||||
await asyncio.get_event_loop().run_in_executor(None, ws_q.put, {"data": result, "event": "toplay"})
|
||||
elif action == "skipc" or action == "skipi":
|
||||
result = await get_imc("activemod", msg)
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504}))
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504, "time": time.monotonic()}))
|
||||
else:
|
||||
await asyncio.get_event_loop().run_in_executor(None, ws_q.put, {"data": result, "event": action})
|
||||
elif action == "jingle":
|
||||
result = await get_imc("jingle", msg.get("top", False))
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504}))
|
||||
if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504, "time": time.monotonic()}))
|
||||
else:
|
||||
await websocket.send(json.dumps(result))
|
||||
result = await get_imc("activemod", {"action": "get_toplay"})
|
||||
@@ -87,23 +88,23 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult
|
||||
dir = Path(MAIN_PATH_DIR, what).resolve()
|
||||
payload = {"files": [i.name for i in list(dir.iterdir()) if i.is_file()], "base": str(dir), "dir": dir.name}
|
||||
except Exception: payload = {}
|
||||
await websocket.send(json.dumps({"event": "request_dir", "data": payload}))
|
||||
await websocket.send(json.dumps({"event": "request_dir", "data": payload, "time": time.monotonic()}))
|
||||
elif action == "fsdb_add":
|
||||
name: str | None = msg.get("name")
|
||||
try:
|
||||
if not name: raise Exception("name not defined")
|
||||
path = Path(MAIN_PATH_DIR, ".playlist", msg.get("playlist", ""), name)
|
||||
path.touch(exist_ok=True)
|
||||
await websocket.send(json.dumps({"event": "fsdb_add", "ok": True}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_add", "error": str(e)}))
|
||||
await websocket.send(json.dumps({"event": "fsdb_add", "ok": True, "time": time.monotonic()}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_add", "error": str(e), "time": time.monotonic()}))
|
||||
elif action == "fsdb_add_dir":
|
||||
name: str | None = msg.get("name")
|
||||
try:
|
||||
if not name: raise Exception("name not defined")
|
||||
path = Path(MAIN_PATH_DIR, ".playlist", msg.get("playlist", ""), name)
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
await websocket.send(json.dumps({"event": "fsdb_add_dir", "ok_dir": True}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_add_dir", "error": str(e)}))
|
||||
await websocket.send(json.dumps({"event": "fsdb_add_dir", "ok_dir": True, "time": time.monotonic()}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_add_dir", "error": str(e), "time": time.monotonic()}))
|
||||
elif action == "fsdb_remove":
|
||||
name: str | None = msg.get("name")
|
||||
try:
|
||||
@@ -111,8 +112,8 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult
|
||||
path = Path(MAIN_PATH_DIR, ".playlist", msg.get("playlist", ""), name)
|
||||
if path.is_dir(): shutil.rmtree(path)
|
||||
else: path.unlink(missing_ok=True)
|
||||
await websocket.send(json.dumps({"event": "fsdb_remove", "ok": True}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_remove", "error": str(e)}))
|
||||
await websocket.send(json.dumps({"event": "fsdb_remove", "ok": True, "time": time.monotonic()}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_remove", "error": str(e), "time": time.monotonic()}))
|
||||
elif action == "fsdb_list":
|
||||
try:
|
||||
p = Path(MAIN_PATH_DIR, ".playlist", msg.get("playlist", ""))
|
||||
@@ -120,15 +121,16 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult
|
||||
"files": [i.name for i in p.iterdir() if i.is_file()],
|
||||
"dirs": [i.name for i in p.iterdir() if i.is_dir()]
|
||||
}
|
||||
await websocket.send(json.dumps({"event": "fsdb_list", "data": payload}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_list", "data": {}, "error": str(e)}))
|
||||
else: await websocket.send(json.dumps({"event": "error", "error": "unknown action"}))
|
||||
await websocket.send(json.dumps({"event": "fsdb_list", "data": payload, "time": time.monotonic()}))
|
||||
except Exception as e: await websocket.send(json.dumps({"event": "fsdb_list", "data": {}, "error": str(e), "time": time.monotonic()}))
|
||||
else: await websocket.send(json.dumps({"event": "error", "error": "unknown action", "time": time.monotonic()}))
|
||||
|
||||
async def broadcast_worker(ws_q: multiprocessing.Queue, clients: set):
|
||||
loop = asyncio.get_event_loop()
|
||||
while True:
|
||||
msg = await loop.run_in_executor(None, ws_q.get)
|
||||
msg: dict = await loop.run_in_executor(None, ws_q.get)
|
||||
if msg is None: break
|
||||
msg["time"] = time.monotonic()
|
||||
payload = json.dumps(msg)
|
||||
if clients:
|
||||
coros = []
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>FSDB Editor</title>
|
||||
<style>
|
||||
body {
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="theme-color" content="#0b1220">
|
||||
<link rel="preconnect" href="/ws">
|
||||
<title>Radio95 Track Monitor</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" integrity="sha512-2SwdPD6INVrV/lHTZbO2nodKhrnDdJK9/kg2XD1r9uGqPo1cUbujc+IYdlYdEErWNu69gVcYgdxlmVmzTWnetw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<style>
|
||||
@@ -257,6 +259,7 @@
|
||||
<div class="footer small">
|
||||
<div><i class="fa-solid fa-server"></i> <span id="server-status">connecting...</span></div>
|
||||
<div><i class="fa-solid fa-user"></i> <span id="user-count">-</span></div>
|
||||
<div><i class="fa fa-arrows-h"></i> <span id="ping-status">-</span>ms</div>
|
||||
<div class="small" id="keybinds">
|
||||
<span><kbd>S</kbd> skip</span>
|
||||
<span><kbd>N</kbd> +skip</span>
|
||||
|
||||
+10
-4
@@ -17,6 +17,7 @@ let skippedIndices = [];
|
||||
let lastElapsed = 0;
|
||||
let lastUpdateTime = 0;
|
||||
let currentRealTotal = 1;
|
||||
let timeOffset = 0;
|
||||
|
||||
function toggleSection(id) {
|
||||
document.getElementById(id).classList.toggle("collapsed");
|
||||
@@ -90,10 +91,17 @@ function wsSend(obj) {
|
||||
ws.send(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
// ─── Message Handling ────────────────────────────────────────────────────────
|
||||
|
||||
function handleMessage(msg) {
|
||||
if(msg.time && timeOffset != 0) {
|
||||
const now = performance.now() / 1000;
|
||||
const lag = now - (msg.time + offset);
|
||||
document.getElementById("ping-status").textContent = lag;
|
||||
}
|
||||
switch (msg.event) {
|
||||
case "time": {
|
||||
const localNow = performance.now() / 1000;
|
||||
timeOffset = localNow - msg.data;
|
||||
}
|
||||
case "state": {
|
||||
const d = msg.data || {};
|
||||
if (d.dirs) updateDirs(d.dirs);
|
||||
@@ -144,8 +152,6 @@ function renderAll() {
|
||||
renderPlaylist();
|
||||
}
|
||||
|
||||
// ─── Track State ─────────────────────────────────────────────────────────────
|
||||
|
||||
function trackLabel(track, index) {
|
||||
const prefix = track.official ? "(official) " : "(unofficial) ";
|
||||
return prefix + track.path.replace(basePath, "").slice(1);
|
||||
|
||||
Reference in New Issue
Block a user