import { useMemo } from "react"; import type { MidiMessage } from "../../midi-contract/midi-message.types.js"; import { adaptOutput } from "../../port/web-midi-port.js"; import { useMidiContextOrThrow } from "../use-midi-context.js"; import type { PortSelector } from "../use-midi-input/use-midi-input.js"; export interface MidiOutputHandle { readonly id: string; readonly name: string; readonly manufacturer: string | undefined; readonly state: "connected" | "disconnected"; send(bytes: Uint8Array): void; sendMessage(msg: MidiMessage): void; } /** * Returns a typed output handle for the selected Web MIDI output, or * `null` while access is loading / the selector misses. The handle's * `sendMessage` encodes a `MidiMessage` via `encodeMessage` and * forwards the resulting bytes to the underlying `MIDIOutput.send`; * `send(bytes)` is the raw escape-hatch (typically used for SysEx * pass-through). */ export function useMidiOutput(selector: PortSelector): MidiOutputHandle | null { const ctx = useMidiContextOrThrow(); const stateVersion = ctx.stateVersion; return useMemo(() => { void stateVersion; if (ctx.access === null) { return null; } if (selector === "first") { const next = ctx.access.outputs.values().next(); return next.done === true ? null : adaptOutput(next.value); } const target = ctx.access.outputs.get(selector); return target === undefined ? null : adaptOutput(target); }, [ctx.access, stateVersion, selector]); }