feat: add VU meter to status bar
Shows input (green) and output (amber) level bars in the status bar, updated every 2s from /api/state. Scales factor 300x to make small signals visible, capped at 100%.
This commit is contained in:
@@ -18,6 +18,12 @@ body{display:flex;flex-direction:column;max-height:100vh;user-select:none;-webki
|
|||||||
.status-channel{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--amber);padding:2px 6px;border-radius:4px;background:rgba(232,160,48,.12);white-space:nowrap}
|
.status-channel{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--amber);padding:2px 6px;border-radius:4px;background:rgba(232,160,48,.12);white-space:nowrap}
|
||||||
.status-preset{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:600;min-width:0}
|
.status-preset{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;font-weight:600;min-width:0}
|
||||||
.status-vol{font-size:10px;font-weight:700;color:var(--amber);white-space:nowrap;font-variant-numeric:tabular-nums}
|
.status-vol{font-size:10px;font-weight:700;color:var(--amber);white-space:nowrap;font-variant-numeric:tabular-nums}
|
||||||
|
.vu-pair{display:flex;align-items:center;gap:2px;margin-left:4px;flex-shrink:0}
|
||||||
|
.vu-track{width:28px;height:5px;background:rgba(255,255,255,.08);border-radius:3px;position:relative;overflow:hidden}
|
||||||
|
.vu-fill{position:absolute;top:0;left:0;height:100%;border-radius:3px;transition:width .04s linear}
|
||||||
|
.vu-fill.in{background:var(--green)}
|
||||||
|
.vu-fill.out{background:var(--amber)}
|
||||||
|
.vu-lbl{font-size:6px;color:var(--text-dim);letter-spacing:.03em;line-height:1;width:10px;text-align:right}
|
||||||
.status-btn{width:40px;height:40px;border:none;background:transparent;color:var(--text-dim);font-size:16px;border-radius:6px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:all .15s}
|
.status-btn{width:40px;height:40px;border:none;background:transparent;color:var(--text-dim);font-size:16px;border-radius:6px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:all .15s}
|
||||||
.status-btn:active{background:var(--border);color:var(--amber)}
|
.status-btn:active{background:var(--border);color:var(--amber)}
|
||||||
|
|
||||||
@@ -166,6 +172,8 @@ body{display:flex;flex-direction:column;max-height:100vh;user-select:none;-webki
|
|||||||
<div class="status-channel" id="statusChannel" onclick="cycleInstrument()" style="cursor:pointer">Guitar</div>
|
<div class="status-channel" id="statusChannel" onclick="cycleInstrument()" style="cursor:pointer">Guitar</div>
|
||||||
<div class="status-preset" id="statusPreset">—</div>
|
<div class="status-preset" id="statusPreset">—</div>
|
||||||
<div class="status-vol" id="statusVolPct">80%</div>
|
<div class="status-vol" id="statusVolPct">80%</div>
|
||||||
|
<div class="vu-pair"><span class="vu-lbl">I</span><div class="vu-track"><div class="vu-fill in" id="vuIn" style="width:0%"></div></div></div>
|
||||||
|
<div class="vu-pair"><span class="vu-lbl">O</span><div class="vu-track"><div class="vu-fill out" id="vuOut" style="width:0%"></div></div></div>
|
||||||
<button class="status-btn" id="btnChannel" onclick="cycleInstrument()">🎛</button>
|
<button class="status-btn" id="btnChannel" onclick="cycleInstrument()">🎛</button>
|
||||||
<button class="status-btn" id="btnSettings">⚙</button>
|
<button class="status-btn" id="btnSettings">⚙</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -649,6 +657,10 @@ async function loadState(){
|
|||||||
if(s.bypass){fs.className='footswitch off';fs.textContent='MUTE';}
|
if(s.bypass){fs.className='footswitch off';fs.textContent='MUTE';}
|
||||||
else{fs.className='footswitch on';fs.textContent='BYpass';}
|
else{fs.className='footswitch on';fs.textContent='BYpass';}
|
||||||
document.getElementById('cpuLabel').textContent=(s.cpu_percent!=null?s.cpu_percent:'—')+'%';
|
document.getElementById('cpuLabel').textContent=(s.cpu_percent!=null?s.cpu_percent:'—')+'%';
|
||||||
|
const vi=Math.min(100,Math.round((s.input_level||0)*300));
|
||||||
|
const vo=Math.min(100,Math.round((s.output_level||0)*300));
|
||||||
|
document.getElementById('vuIn').style.width=vi+'%';
|
||||||
|
document.getElementById('vuOut').style.width=vo+'%';
|
||||||
renderNamHero();
|
renderNamHero();
|
||||||
const tb=document.getElementById('tabTuner');
|
const tb=document.getElementById('tabTuner');
|
||||||
if(s.tuner_enabled){tb.querySelector('.tab-label').textContent='Tuning';tb.classList.add('active');}
|
if(s.tuner_enabled){tb.querySelector('.tab-label').textContent='Tuning';tb.classList.add('active');}
|
||||||
|
|||||||
Reference in New Issue
Block a user