streamer-widgets/app/state.py

65 lines
1.6 KiB
Python

from __future__ import annotations
import asyncio
from dataclasses import dataclass, asdict
from typing import Any, Dict, Optional, Set
@dataclass
class NowPlaying:
title: str = ""
album: str = ""
artist: str = ""
playing: bool = False
source_app: str = ""
art_url: str = "/art/album.png"
has_art: bool = False
updated_unix: int = 0
def to_dict(self) -> Dict[str, Any]:
return asdict(self)
class AppState:
"""
Shared state + websocket client tracking.
"""
def __init__(self) -> None:
self.now_playing: NowPlaying = NowPlaying()
self._ws_clients: Set[Any] = set()
self._lock = asyncio.Lock()
async def set_now_playing(self, np: NowPlaying) -> None:
async with self._lock:
self.now_playing = np
async def get_now_playing(self) -> NowPlaying:
async with self._lock:
return self.now_playing
async def register_ws(self, ws: Any) -> None:
async with self._lock:
self._ws_clients.add(ws)
async def unregister_ws(self, ws: Any) -> None:
async with self._lock:
self._ws_clients.discard(ws)
async def broadcast(self, message: Dict[str, Any]) -> None:
async with self._lock:
clients = list(self._ws_clients)
dead: list[Any] = []
for ws in clients:
try:
await ws.send_json(message)
except Exception:
dead.append(ws)
if dead:
async with self._lock:
for ws in dead:
self._ws_clients.discard(ws)