Signatur
Beschreibung
Das Ereignis statechange des MIDIAccess-Objekts feuert immer dann, wenn sich an einem MIDI-Port etwas ändert: Ein Gerät wird angeschlossen oder abgezogen, oder ein Port wechselt zwischen den connection-Zuständen "open", "closed" und "pending". Der Handler bekommt ein MIDIConnectionEvent, dessen Eigenschaft port auf den betroffenen MIDIInput bzw. MIDIOutput verweist.
Einsatzgebiet sind vor allem Hot-Plug-Szenarien: Web-Synthesizer, DAWs im Browser oder Controller-Editoren sollen ihre Geräteliste aktuell halten und neu angeschlossene Keyboards automatisch verbinden, ohne dass jemand die Seite neu laden muss. Registrieren lässt sich der Handler per addEventListener("statechange", handler) oder über die Eigenschaft midiAccess.onstatechange.
Wichtig: Das Ereignis feuert zusätzlich auch auf dem einzelnen MIDIPort, und zwar dort vor dem MIDIAccess. Auf MIDIAccess hört man, wenn man alle Ports zentral überwachen will. Ein bestimmtes Gerät beobachtet man besser direkt am Port.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Ereignistyp, hier immer "statechange". |
|
| $handler Pflicht | (event: MIDIConnectionEvent) => void | Callback, der ein MIDIConnectionEvent bekommt. event.port ist der betroffene MIDIPort mit den Eigenschaften id, name, manufacturer, type ("input"/"output"), state ("connected"/"disconnected") und connection. |
|
| $options | boolean | AddEventListenerOptions | false | Übliche Listener-Optionen wie once oder signal (z. B. ein AbortSignal, um den Listener später zu entfernen). |
Beispiele
An- und Abstecken von Geräten protokollieren
const access = await navigator.requestMIDIAccess();
access.addEventListener("statechange", (event) => {
const { port } = event;
console.log(`${port.type} "${port.name}" (${port.manufacturer}): ${port.state}, ${port.connection}`);
});
Neue Eingänge automatisch verbinden (Hot-Plug)
const handleMessage = (msg) => {
const [status, note, velocity] = msg.data;
if ((status & 0xf0) === 0x90 && velocity > 0) {
console.log(`Note an: ${note}, Anschlagstärke ${velocity}`);
}
};
const access = await navigator.requestMIDIAccess();
// bereits vorhandene Eingänge verbinden
access.inputs.forEach((input) => { input.onmidimessage = handleMessage; });
// später angeschlossene Eingänge ebenfalls verbinden
access.onstatechange = ({ port }) => {
if (port.type === "input" && port.state === "connected" && !port.onmidimessage) {
port.onmidimessage = handleMessage; // öffnet den Port implizit
}
};
Geräteliste in der UI aktuell halten und Listener entfernen
const controller = new AbortController();
const access = await navigator.requestMIDIAccess();
const renderDevices = () => {
const names = [...access.inputs.values()]
.filter((p) => p.state === "connected")
.map((p) => p.name);
document.querySelector("#devices").textContent = names.join(", ") || "Keine Geräte";
};
renderDevices();
access.addEventListener("statechange", renderDevices, { signal: controller.signal });
// Überwachung beenden, z. B. beim Verlassen der Ansicht
document.querySelector("#stop").addEventListener("click", () => controller.abort());
// Wichtig · Fallstricke
- Mehrfache Ereignisse: Ein einziges An- oder Abstecken kann mehrere
statechange-Ereignisse auslösen, etwa einmal für diestate-Änderung und einmal für dieconnection-Änderung beim Öffnen des Ports. Außerdem hat ein Gerät oft einen Eingang und einen Ausgang. Handler sollten deshalb idempotent sein, also z. B. prüfen, ob schon einonmidimessagegesetzt ist. - Nicht nur neue Geräte: Das Ereignis feuert auch, wenn eine Seite selbst einen Port per
open()/close()öffnet oder schließt. Setzt manonmidimessage, öffnet das den Port implizit und löst dadurch ebenfalls ein Ereignis aus. - Abgezogene Geräte bleiben mit
state === "disconnected"in den Mapsinputs/outputssichtbar, solange sie offen waren. Beim Rendern also nachstatefiltern. - Sichere Umgebung und Berechtigung: Web MIDI gibt es nur in sicheren Kontexten (HTTPS).
requestMIDIAccess()fragt die Nutzerin oder den Nutzer um Erlaubnis. Mit{ sysex: true }ist die Freigabe strenger, und die Permissions-Policymidikann den Zugriff in iframes sperren. - Browser-Kompatibilität: Unterstützt von Chromium-Browsern und Firefox ab Version 108 (dort nur mit Site-Permission-Add-on). Safari unterstützt Web MIDI nicht. Vorher mit
"requestMIDIAccess" in navigatorprüfen.