diff --git a/src/web/server.py b/src/web/server.py index 218dbb1..ed96818 100644 --- a/src/web/server.py +++ b/src/web/server.py @@ -1353,6 +1353,8 @@ class WebServer: "rate": profile["rate"], "jack_running": True, "xrun_count": xruns, + "input_device": self.deps.audio_system.config.input_device, + "output_device": self.deps.audio_system.config.output_device, } @app.post("/api/audio/profile") diff --git a/src/web/ui-v2-dist/index.html b/src/web/ui-v2-dist/index.html index 03be420..a1f7f9b 100644 --- a/src/web/ui-v2-dist/index.html +++ b/src/web/ui-v2-dist/index.html @@ -283,7 +283,8 @@ body{display:flex;flex-direction:column;max-height:100vh;user-select:none;-webki
🔗 Routing4CM
🎚 Audio Interface
-
🔌 Input Device
+
🔌 Input Device
+
🔊 Output Device
🔴 CH 1 — Input 1/L @@ -450,10 +451,36 @@ function hideLoading(){ // Audio Interface helpers async function loadAudioDevices(){ - const sel=document.getElementById('audioInputDevice'); - if(!sel)return; + const inSel=document.getElementById('audioInputDevice'); + const outSel=document.getElementById('audioOutputDevice'); + if(!inSel||!outSel)return; const devs=await API.listAudioDevices(); - sel.innerHTML=(devs||[]).map(d=>'').join('')||''; + const opts=(devs||[]).map(d=>{ + const id='hw:'+d.card+','+d.device; + return ''; + }).join('')||''; + inSel.innerHTML=opts; + outSel.innerHTML=opts; + // Load current input/output from audio profile + try{ + const p=await API.getAudioProfile(); + if(p.input_device)inSel.value=p.input_device; + if(p.output_device)outSel.value=p.output_device; + }catch(e){} +} +async function setAudioInputDevice(id){ + if(!id)return; + showLoading('Switching input...'); + await API.saveSettings({input_device:id}).catch(()=>{}); + hideLoading(); + toast('Input: '+id); +} +async function setAudioOutputDevice(id){ + if(!id)return; + showLoading('Switching output...'); + await API.saveSettings({output_device:id}).catch(()=>{}); + hideLoading(); + toast('Output: '+id); } function setChInstrument(idx,val){ const arr=JSON.parse(localStorage.getItem('chInstruments')||'["guitar","bass"]'); @@ -470,13 +497,7 @@ function toggleChPower(idx){ btn.style.color=on?'var(--text3)':'var(--green)'; API.bypassToggle(channels[idx]||'guitar').catch(()=>{}); } -async function setAudioDevice(devId){ - if(!devId)return; - showLoading('Switching audio device...'); - await API.saveSettings({input_device:devId,output_device:devId}).catch(()=>{}); - hideLoading(); - toast('Device: '+devId); -} + function loadChInstrumentState(){ const arr=JSON.parse(localStorage.getItem('chInstruments')||'["guitar","bass"]'); ['ch1Instrument','ch2Instrument'].forEach((id,i)=>{ @@ -818,7 +839,7 @@ function init(){ btn.onclick=()=>{ const view=btn.dataset.view; if(view==='main'){document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));btn.classList.add('active');} - else if(view==='settings'){openOverlay('Settings');loadNetworkInfo();loadSystemInfo();loadAudioParams();loadHotspotStatus();loadBtStatus();loadBtMidi();return;} + else if(view==='settings'){openOverlay('Settings');loadNetworkInfo();loadSystemInfo();loadAudioParams();loadAudioDevices();loadHotspotStatus();loadBtStatus();loadBtMidi();return;} else if(view==='presets'){openOverlay('Presets');loadPresets();} else if(view==='snapshots'){openOverlay('Snapshots');loadSnapshots();} else if(view==='downloads')openOverlay('Downloads'); @@ -831,6 +852,7 @@ function init(){ loadNetworkInfo(); loadSystemInfo(); loadAudioParams(); + loadAudioDevices(); loadHotspotStatus(); loadBtStatus(); loadBtMidi();