init
This commit is contained in:
64
windows_py_client/synctv_client/sync_client.py
Normal file
64
windows_py_client/synctv_client/sync_client.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
from collections.abc import Callable
|
||||
|
||||
import websocket
|
||||
|
||||
|
||||
class SyncClient:
|
||||
def __init__(
|
||||
self,
|
||||
on_event: Callable[[str, dict], None],
|
||||
on_error: Callable[[str], None],
|
||||
) -> None:
|
||||
self.on_event = on_event
|
||||
self.on_error = on_error
|
||||
self.ws: websocket.WebSocketApp | None = None
|
||||
self.thread: threading.Thread | None = None
|
||||
|
||||
def connect(self, server_base_url: str, room_code: str, device_id: str) -> None:
|
||||
self.close()
|
||||
ws_base = (
|
||||
server_base_url.rstrip("/")
|
||||
.replace("https://", "wss://")
|
||||
.replace("http://", "ws://")
|
||||
)
|
||||
url = f"{ws_base}/ws?roomCode={room_code}&deviceId={device_id}"
|
||||
self.ws = websocket.WebSocketApp(
|
||||
url,
|
||||
on_message=self._on_message,
|
||||
on_error=lambda _ws, err: self.on_error(str(err)),
|
||||
on_close=lambda _ws, _code, reason: self.on_error(f"websocket closed: {reason}"),
|
||||
)
|
||||
self.thread = threading.Thread(target=self.ws.run_forever, daemon=True)
|
||||
self.thread.start()
|
||||
|
||||
def close(self) -> None:
|
||||
if self.ws:
|
||||
self.ws.close()
|
||||
self.ws = None
|
||||
|
||||
def set_source(self, payload: dict) -> None:
|
||||
self._send("setSource", payload)
|
||||
|
||||
def play(self, position_ms: int) -> None:
|
||||
self._send("play", {"positionMs": position_ms})
|
||||
|
||||
def pause(self, position_ms: int) -> None:
|
||||
self._send("pause", {"positionMs": position_ms})
|
||||
|
||||
def seek(self, position_ms: int) -> None:
|
||||
self._send("seek", {"state": "playing", "positionMs": position_ms})
|
||||
|
||||
def sync_to_live(self) -> None:
|
||||
self._send("syncToLive", {"state": "playing", "positionMs": 0, "targetLatencyMs": 3000})
|
||||
|
||||
def _send(self, event_type: str, payload: dict) -> None:
|
||||
if self.ws:
|
||||
self.ws.send(json.dumps({"type": event_type, "payload": payload}))
|
||||
|
||||
def _on_message(self, _ws: websocket.WebSocketApp, message: str) -> None:
|
||||
data = json.loads(message)
|
||||
self.on_event(data.get("type", ""), data.get("payload") or {})
|
||||
Reference in New Issue
Block a user