71 lines
1.8 KiB
Python
71 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
|
|
from app.config.models import InfinityMirrorConfig
|
|
from app.core.types import PreviewFrame
|
|
|
|
|
|
@dataclass
|
|
class OutputResult:
|
|
ok: bool
|
|
message: str = ""
|
|
packets_sent: int = 0
|
|
device_count: int = 0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ControllerMetrics:
|
|
fps: float | None = None
|
|
live_devices: int = 0
|
|
sampled_devices: int = 0
|
|
total_devices: int = 0
|
|
source: str = ""
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class OutputDiagnostics:
|
|
backend_id: str
|
|
backend_name: str
|
|
output_enabled: bool
|
|
worker_running: bool
|
|
target_fps: float
|
|
send_fps: float = 0.0
|
|
last_send_time_ms: float = 0.0
|
|
frames_submitted: int = 0
|
|
frames_sent: int = 0
|
|
stale_frame_drops: int = 0
|
|
send_failures: int = 0
|
|
packets_last_frame: int = 0
|
|
devices_last_frame: int = 0
|
|
packets_sent_total: int = 0
|
|
last_message: str = ""
|
|
send_budget_misses: int = 0
|
|
last_schedule_slip_ms: float = 0.0
|
|
controller_fps: float | None = None
|
|
controller_live_devices: int = 0
|
|
controller_sampled_devices: int = 0
|
|
controller_total_devices: int = 0
|
|
controller_source: str = ""
|
|
|
|
|
|
class OutputBackend(ABC):
|
|
backend_id: str
|
|
display_name: str
|
|
supports_live_output: bool = False
|
|
|
|
def start(self) -> None:
|
|
"""Hook for backends that need to allocate resources."""
|
|
|
|
def stop(self) -> None:
|
|
"""Hook for backends that need to release resources."""
|
|
|
|
def controller_metrics(self, config: InfinityMirrorConfig) -> ControllerMetrics | None:
|
|
"""Optional hook for backends that can report controller-side receive metrics."""
|
|
return None
|
|
|
|
@abstractmethod
|
|
def send_frame(self, config: InfinityMirrorConfig, frame: PreviewFrame) -> OutputResult:
|
|
raise NotImplementedError
|