Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
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<MidiOutputHandle | null>(() => {
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]);
}