Add configurable FPS to test preview and fix composite stream release race

- Add FPS control (1-60, default 20) to test preview modal next to LED count
- Server accepts fps query param, controls frame send interval
- Single Apply icon button (✓) applies both LED count and FPS
- FPS control stays visible for picture sources (LED count hidden)
- Fix composite sub-stream consumer ID collision: use unique instance ID
  to prevent old WebSocket release from killing new connection's streams

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 02:04:09 +03:00
parent e912019873
commit 561229a7fe
9 changed files with 78 additions and 28 deletions

View File

@@ -30,7 +30,9 @@ class CompositeColorStripStream(ColorStripStream):
"""
def __init__(self, source, css_manager, value_stream_manager=None):
import uuid as _uuid
self._source_id: str = source.id
self._instance_id: str = _uuid.uuid4().hex[:8] # unique per instance to avoid release races
self._layers: List[dict] = list(source.layers)
self._led_count: int = source.led_count
self._auto_size: bool = source.led_count == 0
@@ -167,7 +169,7 @@ class CompositeColorStripStream(ColorStripStream):
src_id = layer.get("source_id", "")
if not src_id:
continue
consumer_id = f"{self._source_id}__layer_{i}"
consumer_id = f"{self._source_id}__{self._instance_id}__layer_{i}"
try:
stream = self._css_manager.acquire(src_id, consumer_id)
if hasattr(stream, "configure") and self._led_count > 0: