Files
wled-screen-controller-mixed/server/src/wled_controller/storage/sync_clock.py
alexei.dolgolyov aa1e4a6afc 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>
2026-03-01 21:46:55 +03:00

44 lines
1.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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.110.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"]),
)