first commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# use-stream-mixer
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`useStreamMixer` exposes per-peer mixer controls — level, mute, solo, and the per-peer
|
||||
FX slot count — and implements DAW-correct solo semantics on top of the session's track
|
||||
mutators. It is the only hook in chunk C that owns cross-peer behaviour: when any peer
|
||||
is soloed, every non-soloed peer's track-volume is set to 0; when no peer is soloed,
|
||||
every track keeps its last user-set volume (the session is the source of truth for
|
||||
"last set" because the mutations go through `setTrackVolume`).
|
||||
|
||||
Every mutation routes through `session.setTrackVolume`, `session.setTrackMute`, and
|
||||
`session.setTrackSolo` rather than being re-implemented inside the hook — this is the
|
||||
explicit Requirement-6 constraint and the reason the test asserts on
|
||||
`session.calls.setTrackSolo` / `setTrackVolume`.
|
||||
|
||||
## Features
|
||||
|
||||
- DAW solo semantics: any solo activates the per-track ducking pass; clearing the last
|
||||
solo lets non-soloed tracks resume their stored volume.
|
||||
- Pure delegation: zero local volume state — the session owns it.
|
||||
- Stable callbacks via `useCallback`.
|
||||
- Throws `REACT_AUDIO_STREAM.NO_PROVIDER` outside a `<StreamProvider>`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```tsx
|
||||
const { peers, setVolume, setMute, setSolo } = useStreamMixer();
|
||||
return peers.map((p) => (
|
||||
<PeerStrip
|
||||
key={p.id}
|
||||
peer={p}
|
||||
onVolume={(v) => setVolume(p.id, v)}
|
||||
onMute={(m) => setMute(p.id, m)}
|
||||
onSolo={(s) => setSolo(p.id, s)}
|
||||
/>
|
||||
));
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```tsx
|
||||
const { peers, setSolo } = useStreamMixer();
|
||||
const soloExclusive = useCallback((id: string) => {
|
||||
// Solo one peer and clear all others' solos in a single React tick.
|
||||
peers.forEach((p) => p.soloed && p.id !== id && setSolo(p.id, false));
|
||||
setSolo(id, true);
|
||||
}, [peers, setSolo]);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `UseStreamMixerResult` — `{ peers, setVolume, setMute, setSolo }`
|
||||
- `useStreamMixer(): UseStreamMixerResult`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`setSolo` reads the current mixer snapshot from `session.getPeerMixerStates()`,
|
||||
applies the requested solo change in a local copy, computes `anySoloed`, and — when
|
||||
true — issues `setTrackVolume(otherId, 0)` for every non-soloed peer whose current
|
||||
volume is not already 0. The non-zero check avoids redundant mutations that would
|
||||
otherwise show up as extra `calls.setTrackVolume` entries in tests.
|
||||
|
||||
The "restore previous volume on un-solo" arm is delegated to the session: chunk A's
|
||||
session implementation stores the user-set volume independently from the live mixer
|
||||
volume, so when the last solo clears, the session emits a `mixer-changed` event that
|
||||
restores the stored values. The hook does not have to keep its own restore-map, which
|
||||
keeps the React surface stateless.
|
||||
Reference in New Issue
Block a user