Signatur
Beschreibung
Das Ereignis statechange gehört zur Web MIDI API. Es wird an einem MIDIPort, also einem MIDIInput oder MIDIOutput, ausgelöst, sobald sich einer von zwei Werten ändert: port.connection ("open", "closed", "pending") oder port.state ("connected", "disconnected"). Das passiert zum Beispiel, wenn du port.open() oder port.close() aufrufst oder wenn jemand ein USB-MIDI-Gerät einsteckt oder abzieht.
Der Handler bekommt ein MIDIConnectionEvent. Dessen Eigenschaft event.port zeigt auf den Port, der sich geändert hat. Du kannst das Ereignis mit addEventListener("statechange", handler) abonnieren oder über die Eigenschaft port.onstatechange setzen.
Das gleiche Ereignis wird auch am MIDIAccess-Objekt ausgelöst, und zwar für alle Ports. Willst du einen einzelnen Port überwachen, etwa den gerade gewählten Controller, hängst du den Listener direkt an den Port. Für eine allgemeine Geräteliste mit Hot-Plug-Erkennung eignet sich MIDIAccess.onstatechange besser.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "statechange". |
|
| $handler Pflicht | (event: MIDIConnectionEvent) => void | Die Rückruffunktion. Über event.port erreichst du den betroffenen MIDIPort, dort kannst du state und connection abfragen. |
|
| $options | boolean | AddEventListenerOptions | false | Die üblichen Optionen wie once, signal oder capture. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler erhält ein MIDIConnectionEvent.Beispiele
Zustand eines Eingangsports protokollieren
const access = await navigator.requestMIDIAccess();
const [input] = access.inputs.values();
if (input) {
input.addEventListener('statechange', (event) => {
const { name, state, connection } = event.port;
console.log(`${name}: state=${state}, connection=${connection}`);
});
// Das Öffnen löst ein statechange aus (connection: closed -> open)
await input.open();
}
Handler über onstatechange setzen und wieder entfernen
const access = await navigator.requestMIDIAccess();
const output = [...access.outputs.values()][0];
const onChange = (event) => {
if (event.port.state === 'disconnected') {
console.warn(`Ausgang "${event.port.name}" wurde getrennt`);
}
};
// Variante 1: on-Property (ersetzt einen vorhandenen Handler)
output.onstatechange = onChange;
// Variante 2: addEventListener / removeEventListener
output.onstatechange = null;
output.addEventListener('statechange', onChange);
// Später aufräumen, z. B. beim Wechsel des Ausgabegeräts
output.removeEventListener('statechange', onChange);
Gewählten Controller überwachen und Oberfläche aktualisieren
const statusEl = document.querySelector('#midi-status');
const access = await navigator.requestMIDIAccess();
const controller = [...access.inputs.values()]
.find((p) => p.name.includes('Launchpad'));
const updateStatus = ({ port }) => {
statusEl.textContent = port.state === 'connected'
? `Verbunden (${port.connection})`
: 'Gerät getrennt – bitte wieder einstecken';
};
if (controller) {
controller.addEventListener('statechange', updateStatus);
// Mit einem Nachrichten-Handler wird der Port implizit geöffnet
controller.onmidimessage = (e) => console.log(e.data);
}
// Wichtig · Fallstricke
- Zwei Zustände: Das Ereignis kommt nicht nur beim Öffnen oder Schließen (
connection), sondern auch beim Ein- und Abstecken (state). Prüfe im Handler immer beide Eigenschaften. - Doppelte Ereignisse: Jede Änderung wird zusätzlich an
MIDIAccessgemeldet. Wenn du an beiden Stellen lauschst, wird deine Logik unter Umständen doppelt ausgeführt. - Implizites Öffnen: Wenn du
onmidimessagesetzt odersend()aufrufst, wird der Port automatisch geöffnet. Auch das löst einstatechangeaus. - Getrennte Geräte: Ein abgezogenes Gerät kann
state="disconnected"und gleichzeitigconnection="pending"haben. Wird es wieder eingesteckt, öffnet der Browser den Port erneut. - Kompatibilität und Sicherheit: Die Web MIDI API gibt es nur in sicheren Kontexten (HTTPS). Sie erfordert eine Nutzerfreigabe über
navigator.requestMIDIAccess(), für SysEx-Nachrichten eine zusätzliche Freigabe. Chromium-Browser unterstützen sie. Firefox unterstützt sie ab Version 108, dort ist eine Seitenberechtigung nötig. Safari unterstützt die API nicht. Prüfe deshalb vorher mit'requestMIDIAccess' in navigator.