Skip to content

Commit

Permalink
Don't refresh midi ports continually
Browse files Browse the repository at this point in the history
  • Loading branch information
tstirrat committed Sep 1, 2024
1 parent b40bdc2 commit 32aa90e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
36 changes: 17 additions & 19 deletions src/components/SendSysex.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Dropdown } from "primereact/dropdown";
import { useMidiAccess, useMidiPermission } from "../hooks/use_midi";
import { useMidiPermission, useMidiPortNames } from "../hooks/use_midi";
import { Flex } from "./Flex";
import { FormEventHandler, useState } from "react";
import { Button } from "primereact/button";
Expand All @@ -15,31 +15,35 @@ export const SendSysex: React.FC<{ readonly waveform: Waveform }> = ({
waveform,
}) => {
const perm = useMidiPermission();
const midi = useMidiAccess();
const { midi, portNames } = useMidiPortNames();

const [portId, setPortId] = useState<string | undefined>(undefined);
const [portName, setPortName] = useState<string | undefined>(undefined);

const sendSysex: FormEventHandler = (e) => {
e.preventDefault();
e.stopPropagation();

if (!portId) throw new Error("You must select a port");
if (!midi) throw new Error("MIDI is not ready");

const port = midi?.outputs.get(portId);
if (!portName) throw new Error("You must select a port");

if (!port) throw new Error(`Invalid port ${portId}`);
const port = [...midi.outputs.values()].find((o) => o.name === portName);

if (!port) throw new Error(`Port not found ${portName}`);

sendWaveformSysex(port, waveform);
};

if (!perm) return <strong>Error: Permission unavailable</strong>;

if (!midi?.sysexEnabled) return <strong>Error: SysEx not enabled</strong>;

if (!midi) return <strong>Error: No MIDIAccess</strong>;

if (!portId && midi.outputs.size) {
setPortId([...midi.outputs.values()][0].id);
if (!midi.sysexEnabled) return <strong>Error: SysEx not enabled</strong>;

if (!portName && midi.outputs.size) {
const first = [...midi.outputs.values()][0];

if (first.name) setPortName(first.name);
}

return (
Expand All @@ -58,15 +62,9 @@ export const SendSysex: React.FC<{ readonly waveform: Waveform }> = ({
<Dropdown
inputId={id}
name="midiPort"
options={[...midi.outputs.values()]}
optionLabel="name"
optionValue="id"
value={portId}
valueTemplate={(
option: MIDIOutput | undefined,
{ placeholder }
) => <span>{option?.name ?? placeholder}</span>}
onChange={(e) => setPortId(e.value)}
options={portNames}
value={portName}
onChange={(e) => setPortName(e.value)}
placeholder="MIDI Port"
/>
)}
Expand Down
34 changes: 24 additions & 10 deletions src/hooks/use_midi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useEffect, useMemo, useState } from "react";

export function useMidiPermission() {
const [granted, setGranted] = useState<PermissionState | undefined>(
Expand All @@ -20,17 +20,31 @@ export function useMidiPermission() {
return granted;
}

export function useMidiAccess() {
function useMidiAccess() {
const [midi, setMidi] = useState<MIDIAccess | undefined>(undefined);

(async () => {
try {
const midiAccess = await navigator.requestMIDIAccess({ sysex: true });
setMidi(midiAccess);
} catch (e) {
console.error(`Failed to get MIDI access`, e);
}
})();
useEffect(() => {
(async () => {
try {
const midiAccess = await navigator.requestMIDIAccess({ sysex: true });
setMidi(midiAccess);
} catch (e) {
console.error(`Failed to get MIDI access`, e);
}
})();
}, []);

return midi;
}

export function useMidiPortNames() {
const midi = useMidiAccess();

const portNames = useMemo(() => {
if (!midi) return [];

return [...midi.outputs.values()].map((o) => o.name);
}, [midi]);

return { midi, portNames };
}

0 comments on commit 32aa90e

Please sign in to comment.