Add sync clock entity for synchronized animation timing
Introduces Synchronization Clocks — shared, controllable time bases that CSS sources can optionally reference for synchronized animation. Backend: - New SyncClock dataclass, JSON store, Pydantic schemas, REST API - Runtime clock with thread-safe pause/resume/reset and speed control - Ref-counted runtime pool with eager creation for API control - clock_id field on all ColorStripSource types - Stream integration: clock time/speed replaces source-local values - Paused clock skips rendering (saves CPU + stops frame pushes) - Included in backup/restore via STORE_MAP Frontend: - Sync Clocks tab in Streams section with cards and controls - Clock dropdown in CSS editor (hidden speed slider when clock set) - Clock crosslink badge on CSS source cards (replaces speed badge) - Targets tab uses DataCache for picture/audio sources and sync clocks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
43
server/src/wled_controller/storage/sync_clock.py
Normal file
43
server/src/wled_controller/storage/sync_clock.py
Normal file
@@ -0,0 +1,43 @@
|
||||
"""Synchronization clock data model.
|
||||
|
||||
A SyncClock provides a shared, controllable time base for animation-based
|
||||
color strip sources. Multiple CSS sources referencing the same clock
|
||||
animate in sync and share speed / pause / resume / reset controls.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class SyncClock:
|
||||
"""Persistent configuration for a synchronization clock."""
|
||||
|
||||
id: str
|
||||
name: str
|
||||
speed: float # animation speed multiplier (0.1–10.0)
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
description: Optional[str] = None
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return {
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"speed": self.speed,
|
||||
"description": self.description,
|
||||
"created_at": self.created_at.isoformat(),
|
||||
"updated_at": self.updated_at.isoformat(),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data: dict) -> "SyncClock":
|
||||
return SyncClock(
|
||||
id=data["id"],
|
||||
name=data["name"],
|
||||
speed=float(data.get("speed", 1.0)),
|
||||
description=data.get("description"),
|
||||
created_at=datetime.fromisoformat(data["created_at"]),
|
||||
updated_at=datetime.fromisoformat(data["updated_at"]),
|
||||
)
|
||||
Reference in New Issue
Block a user