ae0a5cb160
Lint & Test / test (push) Failing after 29s
New audio source type that filters a parent source to a specific frequency band (bass 20-250Hz, mid 250-4kHz, treble 4k-20kHz, or custom range). Supports chaining with frequency range intersection and cycle detection. Band filtering applied in both CSS audio streams and test WebSocket.
140 lines
9.5 KiB
HTML
140 lines
9.5 KiB
HTML
<!-- Audio Source Editor Modal -->
|
||
<div id="audio-source-modal" class="modal" role="dialog" aria-modal="true" aria-labelledby="audio-source-modal-title">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h2 id="audio-source-modal-title" data-i18n="audio_source.add">Add Audio Source</h2>
|
||
<button class="modal-close-btn" onclick="closeAudioSourceModal()" data-i18n-aria-label="aria.close">✕</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="audio-source-form" onsubmit="return false;">
|
||
<input type="hidden" id="audio-source-id">
|
||
|
||
<div id="audio-source-error" class="error-message" style="display: none;"></div>
|
||
|
||
<!-- Name -->
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-name" data-i18n="audio_source.name">Name:</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="audio_source.name.hint">A descriptive name for this audio source</small>
|
||
<input type="text" id="audio-source-name" data-i18n-placeholder="audio_source.name.placeholder" placeholder="System Audio" required>
|
||
<div id="audio-source-tags-container"></div>
|
||
</div>
|
||
|
||
<!-- Type (hidden — determined by which add button was clicked) -->
|
||
<input type="hidden" id="audio-source-type" value="multichannel">
|
||
|
||
<!-- Multichannel fields -->
|
||
<div id="audio-source-multichannel-section">
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-audio-template" data-i18n="audio_source.audio_template">Audio Template:</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="audio_source.audio_template.hint">Audio capture template that defines which engine and settings to use for this device</small>
|
||
<select id="audio-source-audio-template">
|
||
<!-- populated dynamically -->
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-device" data-i18n="audio_source.device">Audio Device:</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="audio_source.device.hint">Audio input source. Loopback devices capture system audio output; input devices capture microphone or line-in.</small>
|
||
<div class="select-with-action">
|
||
<select id="audio-source-device">
|
||
<!-- populated dynamically -->
|
||
</select>
|
||
<button type="button" class="btn btn-secondary btn-sm" id="audio-source-refresh-devices" onclick="refreshAudioDevices()" data-i18n-title="audio_source.refresh_devices" title="Refresh devices">↻</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Mono fields -->
|
||
<div id="audio-source-mono-section" style="display:none">
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-parent" data-i18n="audio_source.parent">Parent Source:</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="audio_source.parent.hint">Multichannel source to extract a channel from</small>
|
||
<select id="audio-source-parent">
|
||
<!-- populated dynamically with multichannel sources -->
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-channel" data-i18n="audio_source.channel">Channel:</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="audio_source.channel.hint">Which audio channel to extract from the multichannel source</small>
|
||
<select id="audio-source-channel">
|
||
<option value="mono" data-i18n="audio_source.channel.mono">Mono (L+R mix)</option>
|
||
<option value="left" data-i18n="audio_source.channel.left">Left</option>
|
||
<option value="right" data-i18n="audio_source.channel.right">Right</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Band Extract fields -->
|
||
<div id="audio-source-band-extract-section" style="display:none">
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-band-parent" data-i18n="audio_source.band_parent">Parent Audio Source:</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="audio_source.band_parent.hint">Audio source to extract the frequency band from</small>
|
||
<select id="audio-source-band-parent">
|
||
<!-- populated dynamically with all audio sources -->
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-band" data-i18n="audio_source.band">Frequency Band:</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="audio_source.band.hint">Select a frequency band preset or custom range</small>
|
||
<select id="audio-source-band" onchange="onBandPresetChange()">
|
||
<option value="bass" data-i18n="audio_source.band.bass">Bass (20–250 Hz)</option>
|
||
<option value="mid" data-i18n="audio_source.band.mid">Mid (250–4000 Hz)</option>
|
||
<option value="treble" data-i18n="audio_source.band.treble">Treble (4000–20000 Hz)</option>
|
||
<option value="custom" data-i18n="audio_source.band.custom">Custom Range</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div id="audio-source-custom-freq" style="display:none">
|
||
<div class="form-group">
|
||
<label for="audio-source-freq-low" data-i18n="audio_source.freq_low">Low Frequency (Hz):</label>
|
||
<input type="number" id="audio-source-freq-low" min="20" max="20000" value="20" step="1">
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="audio-source-freq-high" data-i18n="audio_source.freq_high">High Frequency (Hz):</label>
|
||
<input type="number" id="audio-source-freq-high" min="20" max="20000" value="20000" step="1">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Description -->
|
||
<div class="form-group">
|
||
<div class="label-row">
|
||
<label for="audio-source-description" data-i18n="audio_source.description">Description (optional):</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="audio_source.description.hint">Optional notes about this audio source</small>
|
||
<input type="text" id="audio-source-description" data-i18n-placeholder="audio_source.description.placeholder" placeholder="Describe this audio source...">
|
||
</div>
|
||
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-icon btn-secondary" onclick="closeAudioSourceModal()" title="Cancel" data-i18n-title="settings.button.cancel" data-i18n-aria-label="aria.cancel">✕</button>
|
||
<button class="btn btn-icon btn-primary" onclick="saveAudioSource()" title="Save" data-i18n-title="settings.button.save" data-i18n-aria-label="aria.save">✓</button>
|
||
</div>
|
||
</div>
|
||
</div>
|