PE-1 editor display: match the device (always-elapsed, ramp, device link)
Bring the web editor's display in line with the PM_K-1 device screen: - Elapsed stopwatch is always visible and counts while playing (was gated behind the Timers switch); the switch now governs only the countdown. - Tempo-ramp indicator in the display (↗/↘ amount/everyBars), shown whenever a ramp is active — mirrors the device's ramp arrow. - Header "device" badge that lights green with the port name while a PM_K-1 / PM_X-1 is connected over USB-MIDI, updated live on connect/disconnect. The editor requests MIDI on load (Chrome remembers the grant) so it reflects the link automatically; the badge is also click-to-connect. editor-beta.html (separate live-sync variant) left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8cbd53a2ee
commit
6aeca94222
1 changed files with 22 additions and 7 deletions
29
editor.html
29
editor.html
|
|
@ -253,6 +253,7 @@
|
|||
<div class="row appheader" style="align-items:center; flex-wrap:wrap; gap:6px 14px; margin-bottom:8px">
|
||||
<h1 style="margin:0">PM_E‑1 <span style="font-weight:400; opacity:.75">PolyMeter Editor</span></h1>
|
||||
<div class="appheader-ctrls" style="display:flex; align-items:center; gap:10px">
|
||||
<span id="devBadge" title="USB-MIDI link to a PM_K-1 / PM_X-1 (Chrome/Edge/Firefox). Click to connect." style="cursor:pointer; font-size:12px; padding:3px 9px; border-radius:7px; border:1px solid var(--edge); color:var(--muted); white-space:nowrap">◎ connect device</span>
|
||||
<button id="helpBtn" title="keyboard shortcuts (?)">?</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -267,6 +268,7 @@
|
|||
<div class="big" id="bpmDisplay">120</div>
|
||||
<div class="dtimers" id="dtimers">
|
||||
<span title="elapsed (stopwatch)">⏱ <span id="elapsedVal">0:00</span></span>
|
||||
<span id="rampWrap" class="tval" title="tempo ramp" hidden></span>
|
||||
<span id="countWrap" title="time countdown" hidden>⏳ <span id="countVal" class="tval">0:00</span></span>
|
||||
<span id="barWrap" title="bars remaining in this segment" hidden>▦ <span id="barVal" class="tval">0</span></span>
|
||||
</div>
|
||||
|
|
@ -1201,7 +1203,13 @@ async function _ensureMidi() { // MIDI access WITH SysEx (needed to send/
|
|||
_midiAccess.onstatechange = _wireMidi; _wireMidi();
|
||||
return true;
|
||||
}
|
||||
function _wireMidi() { for (const inp of _midiInputs()) inp.onmidimessage = onDeviceMidi; updateMidiBtn(); }
|
||||
function _wireMidi() { for (const inp of _midiInputs()) inp.onmidimessage = onDeviceMidi; updateMidiBtn(); updateDevBadge(); }
|
||||
function updateDevBadge() { // header badge: lights green while a PM_K-1 / PM_X-1 is connected over USB-MIDI
|
||||
const el = $("devBadge"); if (!el) return;
|
||||
const dev = _midiAccess ? [..._midiOutputs(), ..._midiInputs()].filter(_isDevicePort) : [];
|
||||
if (dev.length) { el.textContent = "● " + (dev[0].name || "device").slice(0, 18); el.style.color = "#2fe07a"; el.style.borderColor = "#2fe07a"; }
|
||||
else { el.textContent = _midiAccess ? "◎ no device" : "◎ connect device"; el.style.color = "var(--muted)"; el.style.borderColor = "var(--edge)"; }
|
||||
}
|
||||
function onDeviceMidi(e) {
|
||||
const d = e.data; if (!d) return;
|
||||
if (d[0] === 0xF0 && d[1] === 0x7D) { // our SysEx reply
|
||||
|
|
@ -1403,9 +1411,9 @@ function tickTimers() {
|
|||
const now = Date.now();
|
||||
const dt = timers.last ? Math.min(now - timers.last, 1000) : 0; // clamp so backgrounded gaps don't jump
|
||||
timers.last = now;
|
||||
if (timersOn && state.running) {
|
||||
timers.elapsedMs += dt;
|
||||
if (timers.totalMs > 0) {
|
||||
if (state.running) {
|
||||
timers.elapsedMs += dt; // elapsed stopwatch always runs while playing (like the device)
|
||||
if (timersOn && timers.totalMs > 0) {
|
||||
const before = timers.remainingMs;
|
||||
timers.remainingMs -= dt;
|
||||
// time countdown hit 0 → auto-advance (smooth). Bar-length segments use the
|
||||
|
|
@ -1420,10 +1428,12 @@ function tickTimers() {
|
|||
renderTimers();
|
||||
}
|
||||
function renderTimers() {
|
||||
$("dtimers").hidden = !timersOn;
|
||||
if (!timersOn) return;
|
||||
$("dtimers").hidden = false; // elapsed + ramp always visible (like the device)
|
||||
$("elapsedVal").textContent = fmtClock(timers.elapsedMs);
|
||||
const off = timers.totalMs <= 0;
|
||||
const rw = $("rampWrap"); // tempo-ramp indicator (matches the device's ramp arrow)
|
||||
if (ramp.on) { rw.hidden = false; rw.textContent = (ramp.amount < 0 ? "↘ " : "↗ ") + (ramp.amount >= 0 ? "+" : "") + ramp.amount + "/" + ramp.everyBars + "b"; }
|
||||
else rw.hidden = true;
|
||||
const off = !timersOn || timers.totalMs <= 0;
|
||||
$("countWrap").hidden = off; // hide time countdown when off
|
||||
if (!off) {
|
||||
const cd = $("countVal");
|
||||
|
|
@ -1576,6 +1586,7 @@ $("saveDeviceBtn").addEventListener("click", () => { $("trayMenu").hidden = true
|
|||
$("loadDeviceBtn").addEventListener("click", () => { $("trayMenu").hidden = true; loadFromDevice(); });
|
||||
$("updateFwBtn").addEventListener("click", () => { $("trayMenu").hidden = true; updateFirmware(); });
|
||||
$("midiBtn").addEventListener("click", toggleDeviceAudio);
|
||||
$("devBadge").addEventListener("click", () => { _ensureMidi().then(updateDevBadge); });
|
||||
$("clearLogBtn").addEventListener("click", () => { $("trayMenu").hidden = true; clearLog(); });
|
||||
$("resetAllBtn").addEventListener("click", () => { $("trayMenu").hidden = true; resetAll(); });
|
||||
$("shareSettingsBtn").addEventListener("click", () => { $("trayMenu").hidden = true; shareSettings(); });
|
||||
|
|
@ -1663,6 +1674,10 @@ updateCtx();
|
|||
refreshFeatureBoxes();
|
||||
$("continueMode").checked = continueMode;
|
||||
$("timersOn").checked = timersOn;
|
||||
// Connect to a PM_K-1 / PM_X-1 over USB-MIDI on load so the header badge reflects the link
|
||||
// (Chrome remembers the grant; first visit prompts once). updateDevBadge runs via _wireMidi.
|
||||
if (navigator.requestMIDIAccess) _ensureMidi().then(updateDevBadge).catch(() => updateDevBadge());
|
||||
else updateDevBadge();
|
||||
requestAnimationFrame(drawLoop);
|
||||
/*@BUILD:include:src/chrome.js@*/
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue