Start · Sprachen · JavaScript · Referenz · MIDIPort.close()

MIDIPort.close()

Methode

Schließt den MIDI-Port. Danach kann die Anwendung nicht mehr auf das verbundene MIDI-Gerät zugreifen; der Port wechselt in den Zustand <code>connection: "closed"</code>.

seit JavaScript Web MIDI API — Chrome 43+, Edge 79+, Firefox 108+, Kategorie: webapi

Signatur

MIDIPort.prototype.close()

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

Typ
Promise<MIDIPort>
Beschreibung
Ein 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"
}
USB MIDI Keyboard open USB MIDI Keyboard 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
}
output "Synth": state=connected, connection=open output "Synth": state=connected, connection=closed

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() erneut send() auf oder setzt einen onmidimessage-Handler, wird der Port automatisch wieder geöffnet. Wer den Port wirklich freigeben will, sollte vorher die Handler entfernen (onmidimessage = null bzw. removeEventListener).
  • Geplante Nachrichten: Mit Zeitstempel geplante send()-Nachrichten können beim Schließen verloren gehen. Bei Bedarf vorher MIDIOutput.clear() aufrufen oder abwarten, bis alle Nachrichten gesendet sind. Sonst droht eine „hängende“ Note ohne Note Off.
  • close() trennt nicht die physische Verbindung. state bleibt "connected", nur connection wird 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 navigator prüfen.