A Multi-Room audio controller with interactive and non-interactive modes, multi-language support, and automatic network scanning for BlueOS and Sonos devices.
- ๐ Automatic Network Scanning - Finds all BluOS and Sonos players on your network
- ๐ Multi-Language Support - English, German, and Swahili
- ๐ฎ Two Control Modes - Interactive TUI and CLI command mode
- ๐ฑ Multiple Player Support - Control different players easily
- ๐ต Full Playback Control - Play, pause, stop, volume, and preset management
- ๐ Player Grouping - Group BluOS players for synchronized playback
- ๐ Consistent Player Ordering - Players always appear in the same order (sorted by IP)
# Clone the repository
git clone <repository-url>
cd bluesoundplayer
# Build for your platform
cd src
go build -o ../bluesoundplayer *.go# Using Makefile
make all # Build for all platforms
make linux # Linux AMD64
make windows # Windows AMD64
make raspberry # All Raspberry Pi variants
make apple # macOS (Intel and Apple Silicon)
# Or using build script
./build_execs.shStart without any flags to enter the interactive mode:
./bluesoundplayerThe app will:
- Scan your network for all players
- Let you select a player interactively
- Display a live interface with status, presets, and commands
Use the -c flag for single command execution:
./bluesoundplayer -c [options] [command]Important: Most command-line options require the -c flag to enable CLI mode!
These flags work directly without -c:
| Flag | Description | Example |
|---|---|---|
-list |
List all available players | ./bluesoundplayer -list |
-help |
Show help message | ./bluesoundplayer -help |
-status |
Show status of first player | ./bluesoundplayer -status |
-presets |
Show presets of first player | ./bluesoundplayer -presets |
Note: -status and -presets operate on the first discovered player (lowest IP address).
Choose which player to control:
| Flag | Description | Example |
|---|---|---|
-ip <address> |
Select by IP address | -c -ip 192.168.1.100 |
-player <N> |
Select by index (1-N) | -c -player 2 |
-type <type> |
Filter by device type | -c -type bluos |
Player Selection Priority:
- If
-ipis specified โ Uses that specific player - If
-playeris specified โ Uses player at that index - If neither โ Uses first player found (sorted by IP)
Device Types:
bluos- BluOS devices (Bluesound, NAD, etc.)sonos- Sonos devices
| Flag | Description | Example |
|---|---|---|
-cmd play |
Start/resume playback | -c -ip 192.168.1.100 -cmd play |
-cmd pause |
Pause playback | -c -player 1 -cmd pause |
-cmd stop |
Stop playback | -c -ip 192.168.1.100 -cmd stop |
-cmd next |
Skip to next track | -c -player 2 -cmd next |
-cmd prev |
Previous track | -c -ip 192.168.1.100 -cmd prev |
| Flag | Description | Example |
|---|---|---|
-preset <ID> |
Play specific preset | -c -ip 192.168.1.100 -preset 3 |
-volume <0-100> |
Set volume level | -c -player 1 -volume 50 |
| Flag | Description | Requires -c |
|---|---|---|
-cmd status |
Show player status | Yes |
-cmd presets |
List presets | Yes |
-cmd list |
List all players | Yes |
-status |
Show first player status | No |
-presets |
Show first player presets | No |
-list |
List all players | No |
# List all players on network (sorted by IP)
./bluesoundplayer -list
# List only BluOS devices
./bluesoundplayer -c -type bluos -list
# List only Sonos devices
./bluesoundplayer -c -type sonos -list
# Quick status check of first player
./bluesoundplayer -status
# Detailed status of specific player
./bluesoundplayer -c -ip 192.168.1.100 -cmd status
# Show presets of second player
./bluesoundplayer -c -player 2 -cmd presets# Play preset 5 on first player
./bluesoundplayer -c -preset 5
# Play preset on specific player by IP
./bluesoundplayer -c -ip 192.168.1.100 -preset 3
# Play preset on second player from list
./bluesoundplayer -c -player 2 -preset 1
# Resume playback on specific player
./bluesoundplayer -c -ip 192.168.1.100 -cmd play
# Pause all Sonos devices (using scripting)
for ip in $(./bluesoundplayer -c -type sonos -list | grep "IP:" | awk '{print $2}'); do
./bluesoundplayer -c -ip $ip -cmd pause
done
# Skip to next track
./bluesoundplayer -c -ip 192.168.1.100 -cmd next# Set volume to 50% on specific player
./bluesoundplayer -c -ip 192.168.1.100 -volume 50
# Set volume on second player from list
./bluesoundplayer -c -player 2 -volume 75
# Set volume and show updated status
./bluesoundplayer -c -ip 192.168.1.100 -volume 40 && \
./bluesoundplayer -c -ip 192.168.1.100 -cmd status
# Quiet mode for all BluOS devices
./bluesoundplayer -c -type bluos -volume 20# Morning routine: Start radio at comfortable volume
./bluesoundplayer -c -ip 192.168.1.100 -volume 30
./bluesoundplayer -c -ip 192.168.1.100 -preset 1
# Evening: Fade to quiet and stop
./bluesoundplayer -c -ip 192.168.1.100 -volume 10
sleep 60
./bluesoundplayer -c -ip 192.168.1.100 -cmd stop
# Party mode: Start same preset on all players
PRESET=3
for ip in $(./bluesoundplayer -list | grep "IP:" | awk '{print $2}'); do
./bluesoundplayer -c -ip $ip -preset $PRESET
doneโ Wrong:
# Forgot -c flag with command options
./bluesoundplayer -ip 192.168.1.100 -cmd playError: "Command-line options provided without enabling CLI mode"
โ Correct:
# Use -c flag for CLI mode
./bluesoundplayer -c -ip 192.168.1.100 -cmd playโ Wrong:
# Using player index from old scan
./bluesoundplayer -list # Player 2 is Kitchen
# ... time passes, players turn on/off ...
./bluesoundplayer -c -player 2 # Might be different now!โ Correct:
# Always use IP address for specific player
./bluesoundplayer -c -ip 192.168.1.101 -cmd playโ Wrong:
# Trying to use -type in interactive mode
./bluesoundplayer -type bluos
# Still shows all devicesโ Correct:
# Use -type with -c and commands
./bluesoundplayer -c -type bluos -list
# Or just use interactive without filters
./bluesoundplayerOnce in interactive mode, use these commands:
| Command | Description |
|---|---|
play <id> |
Play preset by ID |
play |
Start/resume playback |
pause |
Pause playback |
stop |
Stop playback |
next |
Skip to next track |
prev |
Go to previous track |
vol <0-100> |
Set volume level |
status |
Refresh status |
presets |
Refresh presets list |
output <id> |
Switch to different player |
group <id1+id2> |
Group players (BluOS only) |
ungroup |
Ungroup all players |
lang <en|de|sw> |
Change language |
debug |
Show API diagnostics |
help |
Show help |
quit / exit |
Exit program |
๐ต Multi-Room Audio Controller
======================================================================
๐ Scanning network for audio players...
โ
Found: Kitchen (Node 2i) at 192.168.1.100 [BluOS]
โ
Found: Living Room (Play:3) at 192.168.1.101 [Sonos]
๐ฑ Available Players:
[1] Kitchen (Bluesound Node 2i) - 192.168.1.100 [BluOS]
[2] Living Room (Sonos Play:3) - 192.168.1.101 [Sonos]
Select a player (1-2): 1
โ
Connected to: Kitchen (192.168.1.100)
๐ต Multi-Room Audio Controller - Interactive Mode
======================================================================
๐ Current Player: Kitchen [BluOS]
๐ฑ Available Players:
[1] Kitchen (192.168.1.100) [BluOS] โ
[2] Living Room (192.168.1.101) [Sonos]
๐ Status: stop | Volume: 50%
๐ต No song playing
๐ Available Presets/Favorites:
[1] Spotify Daily Mix
[2] Radio Paradise
[3] Classical WQXR
๐ฎ Available Commands:
play <id> | play | pause | stop | next | prev | vol <0-100>
output <id> | group <id1+id2> | ungroup | lang <en|de|sw> | quit
======================================================================
Command> play 2
โ
Playing preset 2
๐ Status: stream | Volume: 50%
๐ต World Music - Radio Paradise
Command> vol 35
๐ Volume set to 35%
Command> output 2
๐ Switched to player 2: Living Room
Command> quit
๐ Goodbye!
Switch languages in interactive mode:
| Command | Language | UI Example |
|---|---|---|
lang en |
๐บ๐ธ English | "โ Connected to: Living Room" |
lang de |
๐ฉ๐ช Deutsch | "โ Verbunden mit: Wohnzimmer" |
lang sw |
๐น๐ฟ Kiswahili | "โ Imeunganishwa na: Sebule" |
# /etc/crontab - Morning radio weekdays at 7 AM
0 7 * * 1-5 pi /home/pi/bluesoundplayer -c -ip 192.168.1.100 -preset 1 -volume 30
# Stop music at midnight
0 0 * * * pi /home/pi/bluesoundplayer -c -ip 192.168.1.100 -cmd stop
# Volume down every 5 minutes from 22:00 to 23:00
*/5 22 * * * pi /home/pi/bluesoundplayer -c -ip 192.168.1.100 -volume 20
55 22 * * * pi /home/pi/bluesoundplayer -c -ip 192.168.1.100 -volume 10
0 23 * * * pi /home/pi/bluesoundplayer -c -ip 192.168.1.100 -cmd stop#!/bin/bash
# morning-radio.sh - Start morning radio routine
PLAYER_IP="192.168.1.100"
RADIO_PRESET=3
VOLUME=40
echo "Starting morning radio..."
/home/pi/bluesoundplayer -c -ip $PLAYER_IP -volume $VOLUME
/home/pi/bluesoundplayer -c -ip $PLAYER_IP -preset $RADIO_PRESET
echo "โ Radio started at volume $VOLUME%"#!/bin/bash
# goodnight.sh - Fade out and stop all players
echo "Starting goodnight routine..."
# Get all player IPs
PLAYERS=$(/home/pi/bluesoundplayer -list | grep "IP:" | awk '{print $2}')
# Fade to 20%
for IP in $PLAYERS; do
/home/pi/bluesoundplayer -c -ip $IP -volume 20
done
sleep 30
# Fade to 10%
for IP in $PLAYERS; do
/home/pi/bluesoundplayer -c -ip $IP -volume 10
done
sleep 30
# Stop all
for IP in $PLAYERS; do
/home/pi/bluesoundplayer -c -ip $IP -cmd stop
echo "โ Stopped player: $IP"
done
echo "Goodnight!"# configuration.yaml
shell_command:
play_radio: "/usr/local/bin/bluesoundplayer -c -ip 192.168.1.100 -preset 3"
stop_music: "/usr/local/bin/bluesoundplayer -c -ip 192.168.1.100 -cmd stop"
set_volume: "/usr/local/bin/bluesoundplayer -c -ip 192.168.1.100 -volume {{ volume }}"
# automations.yaml
- alias: "Morning Music"
trigger:
platform: time
at: "07:00:00"
condition:
condition: state
entity_id: binary_sensor.workday
state: 'on'
action:
service: shell_command.play_radio
- alias: "Volume Down at Night"
trigger:
platform: time
at: "22:00:00"
action:
service: shell_command.set_volume
data:
volume: 20[
{
"id": "morning_radio",
"type": "exec",
"command": "/usr/local/bin/bluesoundplayer -c -ip 192.168.1.100 -preset 1 -volume 30",
"name": "Morning Radio"
},
{
"id": "stop_music",
"type": "exec",
"command": "/usr/local/bin/bluesoundplayer -c -ip 192.168.1.100 -cmd stop",
"name": "Stop Music"
}
]# Build for all platforms
make all
# Build for specific platforms
make linux # Linux AMD64
make windows # Windows AMD64
make raspberry # All Raspberry Pi variants
make apple # macOS (Intel and Apple Silicon)
# Individual targets
make rpi-armv6 # Raspberry Pi 1/Zero/Zero W
make rpi-armv7 # Raspberry Pi 2/3/4/Zero 2 W
make rpi-arm64 # Raspberry Pi 4/5 (64-bit)
make apple-arm64 # Apple Silicon (M1/M2/M3/M4)
make apple-amd64 # Intel Macs
# Utility commands
make clean # Clean build artifacts
make test # Test if project builds
make run # Run locally for development
make list # List built executables
make fmt # Format Go code# Build all platforms
./build_execs.sh
# Executables will be in release/ directory
ls release/# Check network connectivity
ping 192.168.1.100
# Verify players are on same network
ip addr show
# Test BluOS player manually
curl http://192.168.1.100:11000/SyncStatus
# Test Sonos player manually
curl http://192.168.1.101:1400/xml/device_description.xml
# Check firewall settings
sudo ufw statusProblem: Player indices change between scans
Solution: Always use IP addresses for scripts:
# โ
Good - Uses stable IP
./bluesoundplayer -c -ip 192.168.1.100 -preset 3
# โ Bad - Index might change
./bluesoundplayer -c -player 2 -preset 3# Make executable
chmod +x bluesoundplayer
# Install system-wide
sudo cp bluesoundplayer /usr/local/bin/
# Check permissions
ls -la /usr/local/bin/bluesoundplayer# Test connectivity in interactive mode
./bluesoundplayer
Command> debug
# Check API endpoints via CLI
./bluesoundplayer -c -ip 192.168.1.100 -cmd status
# Verbose network scan
./bluesoundplayer -listBluOS Devices (Port 11000):
- Bluesound (Node, Powernode, Pulse, Vault, etc.)
- NAD (C 658, C 368, M10, etc.)
- DALI
- And other BluOS-compatible devices
Sonos Devices (Port 1400):
- All Sonos speakers and components
- Uses SOAP/UPnP protocol
BluOS:
- Protocol: HTTP REST API
- Port: 11000
- Format: XML responses
- Examples:
/Status,/Presets,/Play,/Volume?level=50
Sonos:
- Protocol: SOAP/UPnP
- Port: 1400
- Services: AVTransport, RenderingControl, ContentDirectory
- Scans all network interfaces automatically
- Checks each IP in subnet (x.x.x.1-254)
- Results sorted by IP address for consistency
- Deduplicates players found on multiple interfaces
This project is open source. Check the LICENSE file for details.
Contributions are welcome! Please feel free to submit:
- Bug reports
- Feature requests
- Pull requests
- Documentation improvements
- BluOS API documentation
- Sonos UPnP/SOAP protocol specifications
- Go community for excellent networking libraries