Signatur
Beschreibung
MIDIPort ist die gemeinsame Basisschnittstelle für alle MIDI-Ports, die über navigator.requestMIDIAccess() erreichbar sind. Direkt erzeugt wird sie nie. Du bekommst immer eine konkrete Instanz von MIDIInput (Eingang, z. B. ein Keyboard) oder MIDIOutput (Ausgang, z. B. ein Synthesizer). Diese Instanzen stehen in den Maps MIDIAccess.inputs und MIDIAccess.outputs.
Jeder Port beschreibt sein Gerät mit den schreibgeschützten Eigenschaften id, name, manufacturer, version und type ("input" oder "output"). Dazu kommen zwei Zustände:
state:"connected"oder"disconnected". Sagt, ob das Gerät physisch verfügbar ist.connection:"open","closed"oder"pending". Sagt, ob deine Anwendung den Port gerade benutzt.
Mit den Methoden open() und close() öffnest oder schließt du den Port ausdrücklich. Beide geben ein Promise<MIDIPort> zurück. Ändert sich state oder connection, wird das Ereignis statechange ausgelöst (über addEventListener("statechange", …) oder onstatechange). Das gleiche Ereignis kommt auch am MIDIAccess-Objekt an.
Typische Einsatzfälle: eine Geräteliste in einer Musik-App, Hot-Plugging (Geräte an- und abstecken) und das gezielte Freigeben von Ports, damit andere Programme sie nutzen können.
Rückgabewert
MIDIAccess.inputs und MIDIAccess.outputs.Beispiele
Alle verfügbaren MIDI-Ports auflisten
const listPorts = async () => {
const access = await navigator.requestMIDIAccess();
const ports = [...access.inputs.values(), ...access.outputs.values()];
for (const port of ports) {
console.log(`${port.type}: ${port.name} (${port.manufacturer}) – ${port.state}/${port.connection}`);
}
};
listPorts().catch((err) => console.error('MIDI nicht verfügbar:', err));
Port ausdrücklich öffnen und schließen
const access = await navigator.requestMIDIAccess();
const [output] = access.outputs.values();
if (output) {
await output.open();
console.log(output.connection); // "open"
output.send([0x90, 60, 100]); // Note On, mittleres C
setTimeout(async () => {
output.send([0x80, 60, 0]); // Note Off
await output.close();
console.log(output.connection);
}, 500);
}
Hot-Plugging mit statechange (addEventListener und onstatechange)
const access = await navigator.requestMIDIAccess();
// Global: alle Ports überwachen
access.addEventListener('statechange', (event) => {
const { port } = event; // MIDIPort
console.log(`${port.name} ist jetzt ${port.state} (${port.connection})`);
});
// Einzelnen Port per on-Property überwachen
for (const input of access.inputs.values()) {
input.onstatechange = (e) => {
if (e.port.state === 'disconnected') {
console.warn(`Eingang ${e.port.name} wurde getrennt`);
}
};
}
// Wichtig · Fallstricke
- Kompatibilität: Chromium-Browser und Firefox (ab 108) unterstützen die API, Safari nicht. Die API läuft nur in sicheren Kontexten (HTTPS). Firefox verlangt außerdem ein Site-Permission-Add-on bzw. eine Nutzerbestätigung.
- Berechtigungen:
requestMIDIAccess({ sysex: true })fragt den Nutzer ausdrücklich um Erlaubnis, weil SysEx-Nachrichten Geräte-Firmware verändern können. Frage SysEx nur an, wenn du es wirklich brauchst. Auch eine Permissions Policy (midi) kann den Zugriff in iframes sperren. - Implizites Öffnen: Beim Setzen von
MIDIInput.onmidimessageoder beim Aufruf vonMIDIOutput.send()wird der Port automatisch geöffnet.open()brauchst du nur, wenn du den Port vorher belegen willst. Achtung:addEventListener("midimessage", …)öffnet den Port nicht automatisch. - Exklusiver Zugriff: Unter Windows kann ein Port oft nur von einem Programm gleichzeitig genutzt werden.
open()wird dann mitInvalidAccessErrorabgelehnt. stateundconnectionsind verschiedene Dinge:statebeschreibt die Hardware,connectiondie Nutzung durch deine App. Wird ein offener Port abgesteckt, gehtconnectionauf"pending". Beim erneuten Anstecken wird er automatisch wieder geöffnet.- Eine über Sitzungen stabile
idist nicht garantiert. Zum Wiedererkennen eines Geräts eignet sich die Kombination ausnameundmanufacturer.