Add value source test modal, auto-gain, brightness always-show, shared value streams

- Add real-time value source test: WebSocket endpoint streams get_value() at
  ~20Hz, frontend renders scrolling time-series chart with min/max/current stats
- Add auto-gain for audio value sources: rolling peak normalization with slow
  decay, sensitivity range increased to 0.1-20.0
- Always show brightness overlay on LED preview when brightness source is set
- Refactor ValueStreamManager to shared ref-counted streams (value streams
  produce scalars, not LED-count-dependent, so sharing is correct)
- Simplify acquire/release API: remove consumer_id parameter since streams
  are no longer consumer-dependent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 15:48:45 +03:00
parent a164abe774
commit 88b3ecd5e1
18 changed files with 477 additions and 56 deletions

View File

@@ -45,6 +45,7 @@ class ValueSource:
"mode": None,
"sensitivity": None,
"smoothing": None,
"auto_gain": None,
"schedule": None,
"picture_source_id": None,
"scene_behavior": None,
@@ -93,6 +94,7 @@ class ValueSource:
smoothing=float(data.get("smoothing") or 0.3),
min_value=float(data.get("min_value") or 0.0),
max_value=float(data["max_value"]) if data.get("max_value") is not None else 1.0,
auto_gain=bool(data.get("auto_gain", False)),
)
if source_type == "adaptive_time":
@@ -171,10 +173,11 @@ class AudioValueSource(ValueSource):
audio_source_id: str = "" # references an audio source (mono or multichannel)
mode: str = "rms" # rms | peak | beat
sensitivity: float = 1.0 # gain multiplier (0.15.0)
sensitivity: float = 1.0 # gain multiplier (0.120.0)
smoothing: float = 0.3 # temporal smoothing (0.01.0)
min_value: float = 0.0 # minimum output (0.01.0)
max_value: float = 1.0 # maximum output (0.01.0)
auto_gain: bool = False # auto-normalize audio levels to full range
def to_dict(self) -> dict:
d = super().to_dict()
@@ -184,6 +187,7 @@ class AudioValueSource(ValueSource):
d["smoothing"] = self.smoothing
d["min_value"] = self.min_value
d["max_value"] = self.max_value
d["auto_gain"] = self.auto_gain
return d