69 lines
2.3 KiB
Markdown
69 lines
2.3 KiB
Markdown
# `provider/provider-bus-registry`
|
|
|
|
## Purpose
|
|
|
|
`ProviderBusRegistry` is a thin wrapper around
|
|
`DefaultBusRegistry` from `@suaveplan/audio-fx-plugin-base` that adds a
|
|
synchronous `close()` method. The wrapper is owned by
|
|
`<AudioProvider>` and torn down on unmount; closing it force-closes
|
|
every still-active `SidechainPublisher` issued through this registry
|
|
so no buses leak across remounts (especially relevant under React 19
|
|
Strict Mode, which double-invokes effects).
|
|
|
|
## Features
|
|
|
|
- Implements `BusRegistry` so it is a drop-in for the inner default.
|
|
- Tracks every `SidechainPublisher` returned by `publish()` and
|
|
force-closes them on `close()`.
|
|
- Inert after close — late `publish()` calls return a no-op publisher
|
|
rather than throwing.
|
|
- Forwards `get`, `list`, `subscribe` to the inner registry untouched.
|
|
|
|
## Usage: Basic
|
|
|
|
```ts
|
|
import { ProviderBusRegistry } from "@suaveplan/react-audio/provider";
|
|
|
|
const buses = new ProviderBusRegistry();
|
|
const pub = buses.publish("sidechain", 1);
|
|
pub.write([new Float32Array(128)]);
|
|
|
|
buses.close(); // closes pub; subsequent publish() returns a no-op.
|
|
```
|
|
|
|
## Usage: Advanced
|
|
|
|
```ts
|
|
import { ProviderBusRegistry } from "@suaveplan/react-audio/provider";
|
|
|
|
const buses = new ProviderBusRegistry();
|
|
const pub = buses.publish("kick", 1);
|
|
const off = buses.subscribe("kick", (bus) => {
|
|
if (bus === undefined) console.log("bus closed");
|
|
});
|
|
|
|
buses.close();
|
|
off();
|
|
```
|
|
|
|
## API Reference
|
|
|
|
- `new ProviderBusRegistry()` — no constructor arguments.
|
|
- `publish(name, channels): SidechainPublisher` — tracked and
|
|
closed on `close()`.
|
|
- `get(name)`, `list()`, `subscribe(name, listener)` — delegate.
|
|
- `close()` — idempotent; closes all tracked publishers.
|
|
|
|
## Implementation Notes
|
|
|
|
Wrapping rather than subclassing keeps the implementation independent
|
|
of the inner class's private state. The `Set<SidechainPublisher>`
|
|
tracks the *outer* (wrapped) publisher so closing it removes itself
|
|
from the set before delegating to the inner close — this avoids
|
|
double-iteration concerns when `close()` calls each publisher's close
|
|
which would in turn try to mutate the set. Iterating via
|
|
`Array.from(this.active)` snapshots the set so concurrent mutation
|
|
during the close loop is safe. Once closed, `publish()` returns an
|
|
inert publisher whose `write` / `close` are no-ops, allowing late
|
|
consumers to drain without throwing.
|