Signatur
Beschreibung
Mit close() gibt eine Web-Anwendung einen zuvor geöffneten MIDIPort (also einen MIDIInput oder MIDIOutput) wieder frei. Die Methode gibt ein Promise zurück, das mit dem Port selbst erfüllt wird, sobald er geschlossen ist. Danach steht die Eigenschaft connection auf "closed".
Ob ein Port offen ist, hängt nicht nur von open() ab. Er wird auch implizit geöffnet, wenn man einen onmidimessage-Handler an einen Eingang hängt oder send() auf einem Ausgang aufruft. close() ist also der ausdrückliche Weg, das Gerät wieder freizugeben. Das ist zum Beispiel sinnvoll, wenn der Nutzer ein anderes Gerät auswählt, eine Ansicht verlassen wird oder andere Programme exklusiven Zugriff auf das Gerät brauchen. Bei manchen Betriebssystemtreibern (etwa unter Windows) kann nämlich immer nur ein Programm denselben Port nutzen.
Beim Schließen feuert ein statechange-Ereignis, und zwar sowohl am Port als auch am zugehörigen MIDIAccess-Objekt. Ist der Port bereits geschlossen, wird das Promise sofort erfüllt, ohne dass ein Fehler auftritt.
Rückgabewert
Promise, das mit dem geschlossenen MIDIPort erfüllt wird, sobald der Port geschlossen ist (port.connection === "closed").Beispiele
Eingang öffnen und wieder schließen
const access = await navigator.requestMIDIAccess();
const [input] = access.inputs.values();
if (input) {
await input.open();
console.log(input.name, input.connection); // "open"
const port = await input.close();
console.log(port.name, port.connection); // "closed"
}
Gerätewechsel: alten Eingang freigeben
let currentInput = null;
const handleMessage = ({ data }) => {
const [status, note, velocity] = data;
console.log(`Status ${status}, Note ${note}, Velocity ${velocity}`);
};
const selectInput = async (access, id) => {
if (currentInput) {
// Handler entfernen und den Port ausdrücklich schließen
currentInput.onmidimessage = null;
await currentInput.close();
}
currentInput = access.inputs.get(id) ?? null;
if (currentInput) {
currentInput.onmidimessage = handleMessage; // öffnet den Port implizit
}
};
const access = await navigator.requestMIDIAccess();
const ids = [...access.inputs.keys()];
if (ids.length) await selectInput(access, ids[0]);
Beim Schließen auf statechange reagieren
const access = await navigator.requestMIDIAccess();
access.addEventListener("statechange", ({ port }) => {
console.log(`${port.type} "${port.name}": state=${port.state}, connection=${port.connection}`);
});
const [output] = access.outputs.values();
if (output) {
output.send([0x90, 60, 100]); // Note On, öffnet implizit
output.send([0x80, 60, 0], performance.now() + 500); // Note Off in 500 ms
setTimeout(() => output.close(), 1000); // danach Port freigeben
}
Alle Ports beim Verlassen der Seite schließen
const access = await navigator.requestMIDIAccess();
const closeAll = () =>
Promise.all([
...[...access.inputs.values()].map((p) => p.close()),
...[...access.outputs.values()].map((p) => p.close()),
]);
window.addEventListener("pagehide", () => {
closeAll();
});
// Wichtig · Fallstricke
- Implizites Wiederöffnen: Ruft man nach
close()erneutsend()auf oder setzt einenonmidimessage-Handler, wird der Port automatisch wieder geöffnet. Wer den Port wirklich freigeben will, sollte vorher die Handler entfernen (onmidimessage = nullbzw.removeEventListener). - Geplante Nachrichten: Mit Zeitstempel geplante
send()-Nachrichten können beim Schließen verloren gehen. Bei Bedarf vorherMIDIOutput.clear()aufrufen oder abwarten, bis alle Nachrichten gesendet sind. Sonst droht eine „hängende“ Note ohne Note Off. close()trennt nicht die physische Verbindung.statebleibt"connected", nurconnectionwird zu"closed".- Kompatibilität: Die Web MIDI API gibt es nur in Chromium-Browsern und in Firefox (ab 108, dort mit Freigabe über ein Site-Permission-Add-on). Safari unterstützt sie nicht. Sie setzt einen sicheren Kontext (HTTPS) und die Zustimmung des Nutzers voraus. Vorher mit
"requestMIDIAccess" in navigatorprüfen.