"""In-memory state controller'а.""" from __future__ import annotations import asyncio from dataclasses import dataclass, field from .overlays import Overlay @dataclass class InstanceState: name: str active_layout: str overlays: dict[str, Overlay] = field(default_factory=dict) audio_output_enabled: bool = True # Future: fps_out, dropped_frames, motion_cameras, last_event_ts @dataclass class ControllerState: instances: dict[str, InstanceState] = field(default_factory=dict) _lock: asyncio.Lock = field(default_factory=asyncio.Lock) async def set_layout(self, instance: str, layout: str) -> None: async with self._lock: st = self.instances.get(instance) if st is None: st = InstanceState(name=instance, active_layout=layout) self.instances[instance] = st else: st.active_layout = layout async def get_layout(self, instance: str) -> str | None: async with self._lock: st = self.instances.get(instance) return st.active_layout if st else None # ─── Overlay state ────────────────────────────────────────────── async def add_overlay(self, instance: str, overlay: Overlay) -> str: async with self._lock: st = self.instances.get(instance) if st is None: raise KeyError(f"unknown instance '{instance}'") st.overlays[overlay.id] = overlay return overlay.id async def remove_overlay(self, instance: str, overlay_id: str) -> bool: async with self._lock: st = self.instances.get(instance) if st is None or overlay_id not in st.overlays: return False del st.overlays[overlay_id] return True async def update_overlay(self, instance: str, overlay: Overlay) -> bool: async with self._lock: st = self.instances.get(instance) if st is None or overlay.id not in st.overlays: return False st.overlays[overlay.id] = overlay return True async def get_overlays(self, instance: str) -> list[Overlay]: async with self._lock: st = self.instances.get(instance) return list(st.overlays.values()) if st else [] # ─── Audio output mute ────────────────────────────────────────── async def set_audio_output_enabled(self, instance: str, enabled: bool) -> None: async with self._lock: st = self.instances.get(instance) if st is not None: st.audio_output_enabled = enabled async def get_audio_output_enabled(self, instance: str) -> bool: async with self._lock: st = self.instances.get(instance) return st.audio_output_enabled if st else True async def clear_overlays(self, instance: str) -> int: async with self._lock: st = self.instances.get(instance) if st is None: return 0 n = len(st.overlays) st.overlays.clear() return n