import { useEffect, useState, type RefObject } from "react"; import clsx from "clsx"; import type { AudioEngine } from "../audio"; import { IconPlay, IconPause } from "./icons"; export function Controls(props: { audio: AudioEngine; /** Attached to the time clock; updated imperatively by the rAF loop. */ clockRef: RefObject; mix: number; onMixChange: (v: number) => void; stereo: boolean; onStereoChange: (v: boolean) => void; /** Whether the roll auto-follows the playhead (toggled off by manual scrolling). */ following: boolean; onToggleFollow: () => void; }) { const { audio, clockRef, mix, onMixChange, stereo, onStereoChange, following, onToggleFollow } = props; // The transport's state isn't React state (and it can auto-stop at the end), // so poll it each frame to keep the toggle button's label in sync. const [playing, setPlaying] = useState(false); useEffect(() => { let raf = 0; const tick = () => { setPlaying(audio.state === "started"); raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, [audio]); return (
0.0s
); }