//! PipeWire control, split into three modules: //! //! - `graph` - live graph control (link/unlink ports, break feedback //! rings, node/port/link introspection) via `pipewire-rs`, //! using only numeric object ids and this program's own //! ASCII node names. //! - `loopback` - creates/destroys the two chained loopback stages and the //! self-monitor loopback, built on top of `graph`. //! - `text` - byte-safe text matching (`pactl` subprocess output) for //! anything that has to match against human-authored, //! possibly-multibyte device names/descriptions. //! //! Module *lifecycle* (spawning/loading the loopback stages and the //! self-monitor) can't go through `graph`: `pw_context_load_module` loads a //! module into the *calling process's own* context, which then has to keep //! running its main loop forever for the module's nodes to keep producing //! audio - that's what `pw-loopback` itself is. A one-shot CLI invocation //! can't be that persistent host, so the two chained stages stay //! `pw-loopback` subprocesses (tracked by pid), and the self-monitor stays a //! `pactl load-module`/`unload-module` call. Everything downstream of //! that - linking, unlinking, ring-breaking, liveness - is native //! `pipewire-rs` via `graph`. pub mod graph; pub mod loopback; pub mod text; pub use graph::PwGraph;