"""What the panel sees as a "display": one receiver, whatever protocol it speaks.""" from __future__ import annotations import time from dataclasses import dataclass, field CAST, AIRPLAY, DLNA = "cast", "airplay", "dlna" KIND_LABEL = {CAST: "Google Cast", AIRPLAY: "AirPlay", DLNA: "DLNA"} @dataclass class Device: id: str kind: str name: str host: str port: int model: str = "" manufacturer: str = "" # Protocol-specific handles: cast_info for Cast, control URLs for DLNA, # the mDNS TXT record for AirPlay. extra: dict = field(default_factory=dict) seen: float = field(default_factory=time.time) # Live status, filled in by the backend that owns the device. status: str = "" # "" | idle | busy | casting | connecting | error app: str = "" # what it is showing now ("Netflix", "Backdrop", …) volume: float = -1.0 # -1 when unknown muted: bool = False error: str = "" @property def video(self) -> bool: """Can it show a picture? Speaker groups and speakers cannot.""" if self.kind == CAST: return self.extra.get("cast_type") in (None, "cast", "group") and not self.audio_only return True @property def audio_only(self) -> bool: if self.kind == CAST: return self.extra.get("cast_type") in ("audio", "group") return False def to_json(self) -> dict: return { "id": self.id, "kind": self.kind, "kindLabel": KIND_LABEL.get(self.kind, self.kind), "name": self.name, "model": self.model, "host": self.host, "port": self.port, "status": self.status, "app": self.app, "volume": self.volume, "muted": self.muted, "audioOnly": self.audio_only, "error": self.error, }