sendspin-cli 0.1.5, linked against sendspin-cpp v0.7.2 — --version prints both.
Binaries for Linux (x86-64 and arm64) and macOS (Apple silicon), plus a macOS
installer .pkg. Install steps are on the wiki:
Installation for every
way in, Getting Started on Linux
for the one-command version — or read each archive's own BUILD-INFO.txt. SHA256SUMS
covers the four files above, and the macOS builds are unsigned — read the
macOS install notes
before downloading one.
Native PulseAudio and PipeWire outputs (#27)
-o pulse plays through the PulseAudio server's default sink; -o pipewire lets
the PipeWire graph route the stream. Both take a device after a colon, named
exactly as -l prints it — and the server resolves that name at every stream, so
a sink that appears after startup is picked up by the next track without a restart:
sendspin-cli -o pulse # the server's default sink
sendspin-cli -o pulse:alsa_output.pci-0000_00_1f.3.analog-stereo
sendspin-cli -o pipewire # let the graph route it
sendspin-cli -o pipewire:alsa_output.usb-Topping_D10sOver -o alsa:pulse (ALSA's plugin PCM) this buys enumerable sinks and nodes, a
stream the host mixer shows as sendspin-cli and can route per-application, and
sync feedback that answers for the server's real playout rather than the plugin's
own buffering — and this is a synchronised multi-room player, so that is not
cosmetic.
A working command line changes meaning on this upgrade: -o pulse and
-o pipewire used to fall through to ALSA's plugin PCMs of the same names; the
native backends now claim them. -o alsa:pulse and -o alsa:pipewire are the way
back, on every build with the ALSA backend.
--buffer-ms <ms> (10–2000, default 100) sizes these queues like every other
backend's: the PulseAudio server queue (tlength), the PipeWire ring. The short
tour of -o is under the wiki's
Choosing an output;
the full one is in the
README.
Stream hooks: --hook-start and --hook-stop (#28)
Each runs a shell command when a stream starts and when it stops — the amplifier
relay, the light, the notification. The command goes through /bin/sh -c, so pipes
and && work, and the event's facts arrive in the environment:
sendspin-cli -o hw:1,0 \
--hook-start 'amixer -c 1 set Master unmute' \
--hook-stop 'amixer -c 1 set Master mute'| Variable | Carries |
|---|---|
SENDSPIN_EVENT
| start or stop
|
SENDSPIN_SERVER_ID
| the connected server's id |
SENDSPIN_SERVER_NAME
| its friendly name |
SENDSPIN_SERVER_URL
| the URL this run dialled — set only on an -s run
|
SENDSPIN_CLIENT_ID
| this player's id, when --id chose one
|
SENDSPIN_CLIENT_NAME
| this player's friendly name (-n)
|
A stop event carries the same server facts as the start it pairs with, and an
unknown is left unset rather than exported empty, so [ -n "$SENDSPIN_SERVER_ID" ]
means what it says. The vocabulary is the Python sendspin-cli's, so a hook script
written against one player runs unchanged against the other.
Hooks never block playback; they run one at a time, in event order, with the newest
event superseding one still waiting (#41), and the command text never reaches the
log at any level — a hook command routinely carries a credential (#40). A player
stopped mid-stream runs its stop hook on the way out, so systemctl stop leaves
the amplifier off. The full contract is on the wiki's
Controlling the Player page.
Identity flags: --id, --manufacturer, --product-name (#29)
--id is the stable id a server files this player's volume, group and pairing
under. Without it the id is derived from the network interface MAC — so two
players on one host share it, and each server-side setting lands on whichever
connected last. A dual-mono pair needs its own --id per instance, with its own
--port and --state-dir. --manufacturer and --product-name set what the
server displays for the device.
Pin a format: --audio-format (#31)
--audio-format <codec:rate:depth:channels> — e.g. flac:48000:24:2 — moves a
preferred format to the front of what the device probe derived, which is where a
spec-following server picks. It is a reorder, not a narrowing: everything else the
device takes is still offered behind it, and a pin the device cannot take refuses
to start rather than playing something else (#38). Codecs are flac, opus and
pcm; opus only at 48 kHz / 16-bit.
Also in this release
SENDSPIN_SERVER_URLno longer exports a stale dialled URL when a server dials
in after an outbound attempt dropped or failed: a lost connection clears it,
and a discovery dial exports it only for the server it dialled (#42).- The roadmap records
--interfaceas item 25, gated on a sendspin-cpp bind
address (#39).
Known issues
- A mid-session format change (a queue moving, say, from a 48 kHz track to a
192 kHz one) can leave the stream desynced until a manual pause/play (#30). - Under pipewire-pulse,
-o pulsecan report continuous lost/regained sync with
audible artifacts (#32).-o pipewireon the same host is clean — on PipeWire
hosts, prefer the native-o pipewire.
Both are on the wiki's
Troubleshooting page,
beside the rest of the it-starts-and-makes-no-sound ladder.