Files
suaveplan/packages/ui/react/react-audio/src/provider/provider-bus-registry.md
2026-05-27 23:47:53 +01:00

2.3 KiB

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

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

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.