diff --git a/repl/src/useRepl.ts b/repl/src/useRepl.ts index ffa65f18..85261a38 100644 --- a/repl/src/useRepl.ts +++ b/repl/src/useRepl.ts @@ -1,7 +1,6 @@ -import { useCallback, useLayoutEffect, useState, useMemo, useEffect } from 'react'; +import { useCallback, useState, useMemo } from 'react'; import { isNote } from 'tone'; import { evaluate } from './evaluate'; -import { useWebMidi } from './midi'; import type { Pattern } from './types'; import useCycle from './useCycle'; import usePostMessage from './usePostMessage'; @@ -12,7 +11,7 @@ let s4 = () => { .substring(1); }; -function useRepl({ tune, defaultSynth, autolink = true }) { +function useRepl({ tune, defaultSynth, autolink = true, onEvent }: any) { const id = useMemo(() => s4(), []); const [code, setCode] = useState(tune); const [activeCode, setActiveCode] = useState(); @@ -48,30 +47,34 @@ function useRepl({ tune, defaultSynth, autolink = true }) { }; // cycle hook to control scheduling const cycle = useCycle({ - onEvent: useCallback((time, event) => { - try { - if (!event.value?.onTrigger) { - const note = event.value?.value || event.value; - if (!isNote(note)) { - throw new Error('not a note: ' + note); - } - if (defaultSynth) { - defaultSynth.triggerAttackRelease(note, event.duration, time); - } else { - throw new Error('no defaultSynth passed to useRepl.'); - } - /* console.warn('no instrument chosen', event); + onEvent: useCallback( + (time, event) => { + try { + onEvent?.(event); + if (!event.value?.onTrigger) { + const note = event.value?.value || event.value; + if (!isNote(note)) { + throw new Error('not a note: ' + note); + } + if (defaultSynth) { + defaultSynth.triggerAttackRelease(note, event.duration, time); + } else { + throw new Error('no defaultSynth passed to useRepl.'); + } + /* console.warn('no instrument chosen', event); throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ - } else { - const { onTrigger } = event.value; - onTrigger(time, event); + } else { + const { onTrigger } = event.value; + onTrigger(time, event); + } + } catch (err: any) { + console.warn(err); + err.message = 'unplayable event: ' + err?.message; + pushLog(err.message); // not with setError, because then we would have to setError(undefined) on next playable event } - } catch (err: any) { - console.warn(err); - err.message = 'unplayable event: ' + err?.message; - pushLog(err.message); // not with setError, because then we would have to setError(undefined) on next playable event - } - }, []), + }, + [onEvent] + ), onQuery: useCallback( (span) => { try { @@ -146,7 +149,7 @@ function useRepl({ tune, defaultSynth, autolink = true }) { togglePlay, activateCode, activeCode, - pushLog, + pushLog }; }