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

@@ -127,6 +127,7 @@
{% include 'modals/audio-template.html' %}
{% include 'modals/test-audio-template.html' %}
{% include 'modals/value-source-editor.html' %}
{% include 'modals/test-value-source.html' %}
{% include 'partials/tutorial-overlay.html' %}
{% include 'partials/image-lightbox.html' %}

View File

@@ -0,0 +1,27 @@
<!-- Test Value Source Modal -->
<div id="test-value-source-modal" class="modal" role="dialog" aria-modal="true" aria-labelledby="test-value-source-modal-title">
<div class="modal-content">
<div class="modal-header">
<h2 id="test-value-source-modal-title" data-i18n="value_source.test.title">Test Value Source</h2>
<button class="modal-close-btn" onclick="closeTestValueSourceModal()" title="Close" data-i18n-aria-label="aria.close">&#x2715;</button>
</div>
<div class="modal-body">
<canvas id="vs-test-canvas" class="vs-test-canvas"></canvas>
<div class="vs-test-stats">
<span class="vs-test-stat vs-test-stat-current">
<span class="vs-test-stat-label" data-i18n="value_source.test.current">Current</span>
<span class="vs-test-stat-value vs-test-value-large" id="vs-test-current">---</span>
</span>
<span class="vs-test-stat">
<span class="vs-test-stat-label" data-i18n="value_source.test.min">Min</span>
<span class="vs-test-stat-value" id="vs-test-min">---</span>
</span>
<span class="vs-test-stat">
<span class="vs-test-stat-label" data-i18n="value_source.test.max">Max</span>
<span class="vs-test-stat-value" id="vs-test-max">---</span>
</span>
</div>
<div id="vs-test-status" class="vs-test-status" data-i18n="value_source.test.connecting">Connecting...</div>
</div>
</div>
</div>

View File

@@ -123,13 +123,25 @@
</select>
</div>
<div class="form-group">
<div class="label-row">
<label for="value-source-auto-gain" data-i18n="value_source.auto_gain">Auto Gain:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="value_source.auto_gain.hint">Automatically normalize audio levels so output uses the full range, regardless of input volume</small>
<label class="toggle-label">
<input type="checkbox" id="value-source-auto-gain">
<span data-i18n="value_source.auto_gain.enable">Enable auto-gain</span>
</label>
</div>
<div class="form-group">
<div class="label-row">
<label for="value-source-sensitivity"><span data-i18n="value_source.sensitivity">Sensitivity:</span> <span id="value-source-sensitivity-display">1.0</span></label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="value_source.sensitivity.hint">Gain multiplier for the audio signal (higher = more reactive)</small>
<input type="range" id="value-source-sensitivity" min="0.1" max="5" step="0.1" value="1.0"
<input type="range" id="value-source-sensitivity" min="0.1" max="20" step="0.1" value="1.0"
oninput="document.getElementById('value-source-sensitivity-display').textContent = this.value">
</div>