115 lines
3.7 KiB
Markdown
115 lines
3.7 KiB
Markdown
# rpi-sendspin
|
|
|
|
A [sendspin](https://github.com/Sendspin/sendspin-go) client and server with native PipeWire node selection.
|
|
Audio is routed through `pw-cat`, so any PipeWire source or sink can be targeted by name — no ALSA/PulseAudio compatibility layer needed.
|
|
|
|
## Requirements
|
|
|
|
- Go 1.22+
|
|
- PipeWire with `pw-cat` and `pw-dump` in `$PATH`
|
|
- `libopus` and `libopusfile` (for the sendspin dependency)
|
|
|
|
**Build host** (dev packages, only needed to compile):
|
|
```bash
|
|
# Arch
|
|
sudo pacman -S pipewire opus opusfile
|
|
|
|
# Debian/Ubuntu
|
|
sudo apt install libopus-dev libopusfile-dev libasound2-dev
|
|
```
|
|
|
|
**Raspberry Pi** (runtime only, no dev packages needed):
|
|
```bash
|
|
sudo apt install libopus0 libopusfile0 libasound2 pipewire
|
|
```
|
|
|
|
## Build
|
|
|
|
```bash
|
|
make # builds bin/sendspin-client and bin/sendspin-server (native)
|
|
make rpi # cross-compiles for RPi via Docker → bin/*-armhf and bin/*-arm64
|
|
make clean
|
|
```
|
|
|
|
`make rpi` requires Docker. It builds a Debian image with ARM cross-compilers and the ARM versions of libopus/libasound, then copies the four binaries into `bin/`. No toolchain installation needed on the host.
|
|
|
|
## Usage
|
|
|
|
### Server
|
|
|
|
Captures audio from a PipeWire source node and streams it to connected clients.
|
|
|
|
```bash
|
|
# List available capture sources
|
|
./bin/sendspin-server --list-sources
|
|
|
|
# Stream from a specific source
|
|
./bin/sendspin-server --source alsa_input.usb-JBL_Quantum810-00.pro-input-0
|
|
|
|
# Options
|
|
./bin/sendspin-server --help
|
|
-source string PipeWire source node name
|
|
-port int listen port (default 8927)
|
|
-name string server name (default "Sendspin Server")
|
|
-rate int capture sample rate (default 48000)
|
|
-channels int capture channels (default 2)
|
|
```
|
|
|
|
### Client
|
|
|
|
Connects to a sendspin server and plays audio on a PipeWire sink.
|
|
|
|
```bash
|
|
# List available playback sinks
|
|
./bin/sendspin-client --list-devices
|
|
|
|
# Play on a specific sink (omit --device to use the system default)
|
|
./bin/sendspin-client --server rpi.local:8927 --device alsa_output.usb-JBL_Quantum810-00.pro-output-0
|
|
|
|
# Options
|
|
./bin/sendspin-client --help
|
|
-server string server address (default "localhost:8927")
|
|
-device string PipeWire sink node name (default: system default)
|
|
-name string player name (default: hostname)
|
|
-volume int initial volume 0-100 (default 80)
|
|
```
|
|
|
|
## Running as a systemd user service
|
|
|
|
Example unit files are in [dist/systemd/](dist/systemd/). Both run as a **user** service so they have access to the PipeWire session without any special privileges.
|
|
|
|
```bash
|
|
# 1. Copy the binary
|
|
install -Dm755 bin/sendspin-client-arm64 ~/.local/bin/sendspin-client
|
|
|
|
# 2. Edit the unit file — set --server, --device, --name to your values
|
|
cp dist/systemd/sendspin-client.service ~/.config/systemd/user/
|
|
|
|
# 3. Enable and start
|
|
systemctl --user daemon-reload
|
|
systemctl --user enable --now sendspin-client
|
|
|
|
# Logs
|
|
journalctl --user -u sendspin-client -f
|
|
```
|
|
|
|
The unit files use `%H` (hostname) for `--name` and `%h` (home dir) for the binary path. Replace the placeholder `--device` / `--source` values — use `--list-devices` / `--list-sources` to find the right node name first.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
PipeWire source node
|
|
│
|
|
pw-cat --capture
|
|
│ int32 PCM
|
|
sendspin server ──── network ──── sendspin client
|
|
│ int32 PCM
|
|
pw-cat --playback
|
|
│
|
|
PipeWire sink node
|
|
```
|
|
|
|
`internal/pipewire/source.go` wraps `pw-cat --capture` as an `AudioSource`.
|
|
`internal/pipewire/output.go` wraps `pw-cat --playback` as an `Output`.
|
|
`internal/pipewire/nodes.go` parses `pw-dump` JSON to enumerate nodes.
|