diff --git a/editor.html b/editor.html
index d9f4ce4..83ca38a 100644
--- a/editor.html
+++ b/editor.html
@@ -1117,25 +1117,35 @@ async function loadFromDevice() {
/* Device audio (Phase 3): a connected PM_K-1 sends a USB-MIDI note per click; we voice it through
this page's synth, so the device drives sound out the computer's speakers, locked to its clock. */
-let _midiAccess = null, _midiOn = false;
+let _midiAccess = null, _midiOn = false, _midiFlash = 0;
+function _midiInputs() { return _midiAccess ? [..._midiAccess.inputs.values()] : []; }
function onDeviceMidi(e) {
const d = e.data; if (!d || d.length < 3) return;
if ((d[0] & 0xf0) === 0x90 && d[2] > 0) { // Note On
const v = d[2], gain = v >= 110 ? 1.0 : v >= 70 ? 0.6 : 0.25; // accent / normal / ghost
- try { playInstrument(GM_NUM[d[1]] || "beep", audioCtx.currentTime, gain); } catch (_) {}
+ try { ensureAudio(); playInstrument(GM_NUM[d[1]] || "beep", audioCtx.currentTime, gain); } catch (_) {}
+ const b = $("midiBtn"); if (b) { b.style.boxShadow = "0 0 0 2px #2fe07a"; clearTimeout(_midiFlash); _midiFlash = setTimeout(() => b.style.boxShadow = "", 90); }
}
}
-function _bindMidi() { if (_midiAccess) for (const inp of _midiAccess.inputs.values()) inp.onmidimessage = _midiOn ? onDeviceMidi : null; }
-function updateMidiBtn() { const b = $("midiBtn"); if (b) { b.textContent = _midiOn ? "🎹 Device audio: ON" : "🎹 Device audio"; b.classList.toggle("primary", _midiOn); } }
+function _bindMidi() { for (const inp of _midiInputs()) inp.onmidimessage = _midiOn ? onDeviceMidi : null; }
+function updateMidiBtn() {
+ const b = $("midiBtn"); if (!b) return;
+ if (!_midiOn) { b.textContent = "🎹 Device audio"; b.classList.remove("primary"); b.style.boxShadow = ""; return; }
+ const names = _midiInputs().map((i) => i.name || "MIDI");
+ b.textContent = names.length ? "🎹 " + names[0].slice(0, 16) : "🎹 no device"; // shows the connected MIDI device
+ b.classList.add("primary");
+}
async function toggleDeviceAudio() {
if (_midiOn) { _midiOn = false; _bindMidi(); updateMidiBtn(); return; }
if (!navigator.requestMIDIAccess) return alert("Playing the device through this computer needs the Web MIDI API — use Chrome or Edge.");
- try { if (!_midiAccess) { _midiAccess = await navigator.requestMIDIAccess(); _midiAccess.onstatechange = _bindMidi; } }
+ try { if (!_midiAccess) { _midiAccess = await navigator.requestMIDIAccess(); _midiAccess.onstatechange = () => { _bindMidi(); updateMidiBtn(); }; } }
catch (e) { return alert("MIDI access was denied."); }
ensureAudio(); if (audioCtx && audioCtx.state === "suspended") audioCtx.resume();
_midiOn = true; _bindMidi(); updateMidiBtn();
- if (![..._midiAccess.inputs.values()].length)
- alert("No MIDI device detected yet — plug in the PM_K-1 (CircuitPython firmware) and press play on it. (It stays armed; new devices connect automatically.)");
+ const names = _midiInputs().map((i) => i.name || "MIDI");
+ alert(names.length
+ ? "Device audio ON.\nMIDI input(s): " + names.join(", ") + "\nPress play on the device — the button pulses green on each note received."
+ : "Device audio is armed, but NO MIDI input is connected.\nPlug in the PM_K-1 running the CircuitPython firmware — it should appear here as a MIDI device. (New devices connect automatically.)");
}
// Apply a shared link on load. Returns true if it set the metronome state.