ControlBooth
The unsandboxed companion to AntennaHead. It runs user-defined process pipelines — tool piped into tool via stdin/stdout — and delivers the resulting PCM audio to AntennaHead over UDP for streaming.
Why a separate app
AntennaHead is sandboxed and ships only fixed, known-good pipelines.
Arbitrary command-line tools — unsigned Homebrew binaries included
— can't run inside that sandbox. ControlBooth
(ENABLE_APP_SANDBOX = NO) is where that freedom lives, so
AntennaHead stays locked down.
Pipeline editor
Chain executables left to right; each stage's stdout feeds the next stage's stdin. A structured argument editor with a helper catalog and validation keeps stages well-formed.
Automatic delivery
ControlBooth appends PCMUDPSender --exit-with-parent as the final stage, sending raw S16LE PCM to AntennaHead (default port 6019), which forwards it to LiveAudioServer.
Example: HD Radio
nrsc5 → sox for HD Radio, or any decoder chain you can express on a command line — without the manual terminal juggling.
Shared internals
Uses the same PipelineHelpers runner, SharedLogging viewer, and AirPlayReceiver as AntennaHead.
Devices hub
ControlBooth also owns the embedded AirPlay receiver and the cross-app Devices page.
Ducking & mixing
Sidechain ducking (PCMMixer --duck-input) lets announcements or a live mix drop the main audio underneath them.
Recovering a wedged RTL-SDR
An RTL-SDR that stops delivering samples (“PLL not locked”, a read that never returns) only recovers when it loses power. ControlBooth can switch a USB hub port off and on with uhubctl: choose the port in Commands › USB Tree… (the tree shows every hub and RTL-SDR, with ports that can be switched selectable and the rest dimmed), then let the dsd-neo scanner do it automatically when it gets no signal, or trigger it by hand from Commands › Power Cycle USB Hub… or AntennaHead’s Now Playing page.
Per-port power switching
The hub whose port is cycled must support per-port power switching (PPPS). uhubctl marks such a hub ppps; a hub marked ganged switches all its ports together and isn’t offered.
The hub above the dongles
The RTL-SDRs’ own hub can be any hub, even a ganged one. The switchable hub is the one above it: choose the port that feeds the dongles’ hub, and everything below that port loses power for a few seconds.
It has to really cut power
Some hubs advertise PPPS but only drop the data lines, which doesn’t un-wedge a dongle. Try Power Cycle Now… and watch the dongles go away and return. Self-powered hubs are much more likely to work than bus-powered ones; a Mac’s built-in ports and most unpowered travel hubs can’t switch power. uhubctl keeps a list of hubs known to work.
uhubctl
Not bundled: install it with MacPorts (sudo port install uhubctl) or Homebrew (brew install uhubctl). It ran without sudo on macOS here; if cycling fails for lack of permission, uhubctl needs to run as root. A USB 3 hub has a USB 2 and a USB 3 side, and uhubctl cycles both.
ControlBooth checks the hub’s location and USB ID, and the device on the port, before every cycle, and refuses — asking you to choose again — if the USB layout has changed. This feature is new and not in v0.3.1-alpha.
Screen recordings
ControlBooth is a native SwiftUI app (no browser UI), so these are desktop captures.
rtl_fm_localradio → sox → PCMJitterBuffer), then pressing Play to send it to AntennaHead.Get it
ControlBooth checks out as a sibling of AntennaHead — use the antennahead-workspace bootstrap for the local-package layout.
github.com/
Latest release: v0.3.1-alpha (pre-release) — direct download (.zip, signed & notarized)