Signatur
Beschreibung
MIDIConnectionEvent ist das Ereignisobjekt, das die Web MIDI API beim statechange-Ereignis liefert. Es wird ausgelöst, wenn sich der Zustand eines MIDI-Ports ändert, also wenn ein Gerät angeschlossen oder abgezogen wird (state: "connected"/"disconnected") oder wenn ein Port geöffnet bzw. geschlossen wird (connection: "open"/"closed"/"pending").
Die Schnittstelle erbt von Event und fügt nur eine Eigenschaft hinzu: port, eine schreibgeschützte Referenz auf den betroffenen MIDIInput oder MIDIOutput. Über event.port.name, event.port.manufacturer, event.port.type, event.port.state und event.port.connection lassen sich alle relevanten Informationen auslesen.
Einsatzgebiet ist vor allem Hotplug-Unterstützung: Eine Musik- oder Controller-Anwendung kann damit Gerätelisten live aktualisieren, neu angeschlossene Keyboards automatisch verwenden oder die Oberfläche bei getrennten Geräten anpassen. Das Ereignis lauscht man am besten global über MIDIAccess; zusätzlich feuert es auch am einzelnen MIDIPort.
Einen eigenen MIDIConnectionEvent kann man über den Konstruktor new MIDIConnectionEvent(type, options) erzeugen, etwa für Tests. Im Normalbetrieb erzeugt ihn aber der Browser.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Konstruktor-Parameter: Name des Ereignisses, in der Praxis "statechange". |
|
| $options | { port?: MIDIPort, bubbles?: boolean, cancelable?: boolean, composed?: boolean } | {} | Konstruktor-Parameter: Optionen wie bei Event, dazu port – der betroffene MIDIPort (Standard: null). |
Rückgabewert
port (MIDIPort, schreibgeschützt) verweist auf den Port, dessen Zustand sich geändert hat.Beispiele
Geräte-Anschluss und -Trennung global überwachen
const access = await navigator.requestMIDIAccess();
access.addEventListener('statechange', (event) => {
const { name, type, state, connection } = event.port;
console.log(`${type} "${name}": ${state} / ${connection}`);
});
Neu angeschlossene Eingänge automatisch verwenden (on-Property)
const handleMessage = ({ data }) => {
const [status, note, velocity] = data;
console.log('MIDI:', status, note, velocity);
};
const access = await navigator.requestMIDIAccess();
// Bereits vorhandene Eingänge anbinden
access.inputs.forEach((input) => { input.onmidimessage = handleMessage; });
// Hotplug: neue Eingänge anbinden
access.onstatechange = (event) => {
const port = event.port;
if (port.type === 'input' && port.state === 'connected') {
port.onmidimessage = handleMessage; // öffnet den Port implizit
}
};
Geräteliste in der Oberfläche aktualisieren und Listener entfernen
const list = document.querySelector('#midi-devices');
const access = await navigator.requestMIDIAccess();
const render = () => {
list.replaceChildren(
...[...access.inputs.values(), ...access.outputs.values()].map((port) => {
const li = document.createElement('li');
li.textContent = `${port.type}: ${port.name} (${port.state})`;
return li;
})
);
};
const onStateChange = (event) => {
if (event instanceof MIDIConnectionEvent) render();
};
access.addEventListener('statechange', onStateChange);
render();
// Später, z. B. beim Verlassen der Ansicht:
// access.removeEventListener('statechange', onStateChange);
Ereignis für Tests selbst erzeugen
const access = await navigator.requestMIDIAccess();
const [firstInput] = access.inputs.values();
const fake = new MIDIConnectionEvent('statechange', { port: firstInput ?? null });
console.log(fake.type, fake.port?.name ?? 'kein Port');
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-Browser und Firefox (ab 108) unterstützen die Web MIDI API, Safari nicht. Vorher mit
'requestMIDIAccess' in navigatorprüfen. - Sicherer Kontext & Berechtigung: Die API funktioniert nur über HTTPS (bzw. localhost) und erfordert eine Nutzerfreigabe. Firefox verlangt zusätzlich ein Site-Permission-Add-on. In iframes ist die Permissions-Policy
midinötig. - Mehrfaches Feuern: Beim Öffnen eines Ports feuert
statechangeebenfalls (Änderung vonconnection), nicht nur beim An- und Abstecken. Deshalb immerport.stateundport.connectionauswerten, statt jedes Ereignis als „neues Gerät“ zu behandeln. - Das Setzen von
onmidimessageöffnet einen Eingang implizit und löst dadurch ein weiteresstatechangeaus. Wer das nicht beachtet, riskiert Endlosschleifen oder doppelte Listener. - Ein getrenntes Gerät bleibt unter Umständen mit
state === \"disconnected\"inaccess.inputs/outputsstehen. Beim Anzeigen also nach Zustand filtern.