-
-
+
+
+
NAM
+
No Model Loaded
+
โ€”
+
+
+
+
+
+
+
Vol @@ -224,6 +260,44 @@ body{display:flex;flex-direction:column;max-height:100vh;user-select:none;-webki
๐Ÿ”„ Channel ModeDual Mono
๐Ÿ”— Routing4CM
+
๐ŸŽš Audio Interface
+
๐Ÿ”Œ Input Device
+
+
+ ๐Ÿ”ด CH 1 โ€” Input 1/L + +
+
+ Instrument: + +
+
Output: Main L/R (Scarlett 1+2)
+
+
+
+ ๐ŸŸข CH 2 โ€” Input 2/R + +
+
+ Instrument: + +
+
Output: Main L/R (Scarlett 1+2)
+
+
Dual Mono: each channel has independent presets. Same instrument = shared presets.
+
Bluetooth
๐Ÿ”ต Statusโ€”
๐ŸŽ› MIDIOff
@@ -332,6 +406,59 @@ function cycleInstrument(){ localStorage.setItem('pedalCurrentChannel',currentChannel); toast(currentChannel); } + +// Loading overlay +function showLoading(msg){ + let el=document.getElementById('loadingOverlay'); + if(!el){ + el=document.createElement('div');el.id='loadingOverlay';el.className='loading-overlay'; + el.innerHTML='
'; + document.body.appendChild(el); + } + el.querySelector('.load-msg').textContent=msg||'Loading...'; + el.style.display='flex'; +} +function hideLoading(){ + const el=document.getElementById('loadingOverlay'); + if(el)el.style.display='none'; +} + +// Audio Interface helpers +async function loadAudioDevices(){ + const sel=document.getElementById('audioInputDevice'); + if(!sel)return; + const devs=await API.listAudioDevices(); + sel.innerHTML=(devs||[]).map(d=>'').join('')||''; +} +function setChInstrument(idx,val){ + const arr=JSON.parse(localStorage.getItem('chInstruments')||'["guitar","bass"]'); + arr[idx]=val; + localStorage.setItem('chInstruments',JSON.stringify(arr)); + API.saveSettings({['ch'+(idx+1)+'_instrument']:val}).catch(()=>{}); +} +function toggleChPower(idx){ + const btn=document.getElementById('ch'+(idx+1)+'Power'); + const on=btn.textContent==='โšก'; + btn.textContent=on?'โญ•':'โšก'; + btn.style.background=on?'rgba(160,160,188,.1)':'rgba(58,184,122,.2)'; + btn.style.borderColor=on?'rgba(160,160,188,.2)':'rgba(58,184,122,.4)'; + 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)=>{ + const el=document.getElementById(id); + if(el)el.value=arr[i]||(i===0?'guitar':'bass'); + }); +} function toast(msg,t){const e=$('#toast');e.textContent=msg;e.classList.add('show');clearTimeout(e._h);e._h=setTimeout(()=>e.classList.remove('show'),t||2000);} // โ•โ•โ• Overlay Controller โ•โ•โ• @@ -372,7 +499,7 @@ async function loadState(){ if(s.bypass){fs.className='footswitch off';fs.textContent='MUTE';} else{fs.className='footswitch on';fs.textContent='BYpass';} document.getElementById('cpuLabel').textContent=(s.cpu_percent!=null?s.cpu_percent:'โ€”')+'%'; - renderFxBlocks(); + renderNamHero(); const tb=document.getElementById('tabTuner'); if(s.tuner_enabled){tb.querySelector('.tab-label').textContent='Tuning';tb.classList.add('active');} else{tb.querySelector('.tab-label').textContent='Tuner';tb.classList.remove('active');} @@ -381,20 +508,79 @@ async function loadState(){ // โ•โ•โ• FX Blocks โ•โ•โ• const BLOCK_COLORS={nam_amp:'#E8A030',ir:'#4090E0',gate:'#50D090',compressor:'#E0E060',eq:'#A080E0',reverb:'#60C0E0',delay:'#80D0A0',distortion:'#E06060'}; -function renderFxBlocks(){ - const strip=document.getElementById('fxStrip'); +const FX_ICONS={nam_amp:'๐ŸŽ›',nam:'๐ŸŽ›',overdrive:'โšก',distortion:'๐Ÿ’ฅ',delay:'โณ',reverb:'๐ŸŒŠ',chorus:'๐ŸŒ€',compressor:'๐Ÿ“ˆ',eq:'๐Ÿ“Š',cabinet:'๐Ÿ“ฆ',ir:'๐Ÿ“ฆ',volume:'๐Ÿ”Š',gate:'๐Ÿšช',tremolo:'ใ€ฐ๏ธ',phaser:'๐ŸŒ€',flanger:'๐ŸŒŠ',boost:'๐Ÿš€',pitch:'๐ŸŽต',filter:'๐Ÿ”€'}; +const FX_COLORS={nam_amp:'#E0A040',nam:'#E0A040',overdrive:'#E8A030',distortion:'#E04040',delay:'#3090E0',reverb:'#40B0A0',chorus:'#50C080',compressor:'#D09040',eq:'#7080D0',cabinet:'#D07090',ir:'#D07090',volume:'#8888A0',gate:'#80A0C0',tremolo:'#C080D0',phaser:'#40B0D0',flanger:'#60A0E0',boost:'#E8A030',pitch:'#B080D0',filter:'#80C0A0'}; + +function renderNamHero(){ + const hero=document.getElementById('namHero'); + const nameEl=document.getElementById('namName'); + const detailEl=document.getElementById('namDetail'); + const ledEl=document.getElementById('namLed'); + const badgeEl=document.getElementById('namBadge'); const blocks=state.blocks||[]; - const addBtn=document.getElementById('btnAddBlock'); - strip.innerHTML=''; - strip.appendChild(addBtn); - blocks.forEach((b,i)=>{ - const div=document.createElement('div'); + const namBlock=blocks.find(b=>b.fx_type==='nam_amp'||b.fx_type==='nam'); + if(namBlock){ + hero.className='nam-hero'; + hero.style.borderColor=FX_COLORS[namBlock.fx_type]||'var(--border)'; + badgeEl.textContent=(namBlock.fx_type||'NAM').toUpperCase(); + badgeEl.style.background=(FX_COLORS[namBlock.fx_type]||'#E0A040')+'22'; + badgeEl.style.color=FX_COLORS[namBlock.fx_type]||'#E0A040'; + nameEl.textContent=namBlock.name||namBlock.nam_model_name||'NAM Model'; + const enabled=namBlock.enabled!==false; + ledEl.className='nam-led '+(enabled?'on':'off'); + ledEl.style.background=enabled?'var(--green)':'var(--red)'; + const detailParts=[]; + if(namBlock.nam_model_name)detailParts.push(namBlock.nam_model_name); + detailParts.push(enabled?'ON':'OFF'); + if(state.nam_loaded)detailParts.push('loaded'); + detailEl.textContent=detailParts.join(' ยท ')||'โ€”'; + }else{ + hero.className='nam-hero empty'; + hero.style.borderColor=''; + nameEl.textContent='No NAM Model'; + detailEl.textContent='Tap to add amp block'; + ledEl.className='nam-led off'; + badgeEl.textContent='NAM'; + badgeEl.style=''; + } + renderPedals(); +} +function renderPedals(){ + const row=document.getElementById('pedalRow'); + const addBtn=document.getElementById('btnAddPedal'); + row.innerHTML=''; + row.appendChild(addBtn); + const nonNam=(state.blocks||[]).filter(b=>b.fx_type!=='nam_amp'&&b.fx_type!=='nam'); + if(nonNam.length===0){ + const empty=document.createElement('div'); + empty.style.cssText='flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:9px;color:var(--text3);padding:0 8px;min-height:76px'; + empty.textContent='No FX pedals โ€” tap + to add'; + row.insertBefore(empty,addBtn); + } + (state.blocks||[]).forEach((b,i)=>{ + if(b.fx_type==='nam_amp'||b.fx_type==='nam')return; // NAM shown in hero const en=b.enabled!==false&&!b.bypass; - div.className='fx-block '+(en?'on':'off'); - div.innerHTML='
'+(b.fx_type||'fx')+'
'+(b.name||b.fx_type||'Block')+'
'+[...Array(4)].map((_,j)=>'
').join('')+'
'; - strip.insertBefore(div,addBtn); + const type=b.fx_type||'fx'; + const name=b.name||b.fx_type||'Block'; + const color=FX_COLORS[type]||'#E8A030'; + const icon=FX_ICONS[type]||'๐ŸŽ›'; + const pedal=document.createElement('div'); + pedal.className='pedal '+(en?'on':'off'); + pedal.style.borderColor=en?color:'var(--border)'; + pedal.innerHTML='
'+icon+'
'+name+'
'; + pedal.onclick=()=>{toggleBlock(i);}; + row.insertBefore(pedal,addBtn); }); } +async function toggleBlock(idx){ + const blocks=state.blocks||[]; + const b=blocks[idx]; + if(!b)return; + const newEn=!(b.enabled!==false); + await API.toggleBlock(currentChannel,b.block_id||idx,newEn).catch(()=>{}); + loadState(); +} +function showAddBlock(){openOverlay('Downloads');} // โ•โ•โ• Presets โ•โ•โ• async function loadPresets(){ @@ -481,7 +667,14 @@ async function loadAudioProfiles(){ const d=document.createElement('div'); d.className='ap-card'+(p.key===cp?' active':''); d.innerHTML='
'+p.key.replace(/_/g,' ')+'
'+p.period+'fr / '+p.rate+'Hz
'+((p.key===cp)?'
โ— Active
':''); - d.onclick=()=>{API.setAudioProfile(p.key).then(()=>{toast('Profile: '+p.key);loadAudioProfiles();}).catch(e=>toast(e.message));}; + d.onclick=async()=>{ + d.classList.add('loading'); + try{ + await API.setAudioProfile(p.key); + toast('Profile: '+p.key); + loadAudioProfiles(); + }catch(e){toast(e.message);d.classList.remove('loading');} + }; grid.appendChild(d); }); document.getElementById('audioProfileLabel').textContent=cp; @@ -606,6 +799,7 @@ function init(){ openOverlay('Settings'); await loadAudioProfiles();await loadBtStatus();await loadBtMidi();await loadHotspotStatus(); await loadNetworkInfo();await loadSystemInfo();await doWifiScan(); + loadAudioDevices();loadChInstrumentState(); }; // Close all overlays