Add a custom-radio url stream source (#114)

Based on the descriptions at

- https://gist.github.com/rody64/98a59990ff60ea962cac72cbe93edf56
-
https://github.com/thlucas1/homeassistantcomponent_soundtouchplus/discussions/37

Example usage:

```
go run ./cmd/soundtouch-cli --host 192.... source custom-radio --url https://stream.antenne.de/chillout/stream/aacp --service-url http://soundtouch.local:8000
Selecting custom radio stream from 192....:8090...
  URL: https://stream.antenne.de/chillout/stream/aacp
  Proxy: http://soundtouch.local:8000/bmx/custom/v1/playback/aHR0cHM6Ly9zdHJlYW0uYW50ZW5uZS5kZS9jaGlsbG91dC9zdHJlYW0vYWFjcA==
✓ Custom radio stream selected
```

Relates to https://github.com/gesellix/Bose-SoundTouch/issues/94
This commit is contained in:
Tobias Gesellchen
2026-03-16 23:17:50 +01:00
committed by GitHub
parent 565ca33345
commit 8d95e170f6
11 changed files with 267 additions and 62 deletions
+20 -3
View File
@@ -23,6 +23,14 @@ All content selection features from the [SoundTouch WebServices API Wiki](https:
- Automatic defaults for missing parameters
- **Use Cases**: Internet radio streams, proxy-based radio services
#### `SelectLocalInternetRadio(location, ...)` via `soundtouch-service`
- **Purpose**: Select custom radio stream via local `soundtouch-service` proxy
- **Features**:
- Flexible stream URL encoding (Base64 or URL-escaped)
- Dynamic generation of Bose-compatible playback JSON
- Seamless integration with existing `LOCAL_INTERNET_RADIO` source
- **Use Case**: Playing any internet radio URL without external proxy dependencies
#### `SelectLocalMusic(location, sourceAccount, itemName, containerArt string) error`
- **Purpose**: Select LOCAL_MUSIC content from SoundTouch App Media Server
- **Requirements**: SoundTouch App Media Server running on a computer
@@ -47,6 +55,15 @@ soundtouch-cli --host <device> source internet-radio \
--artwork "https://example.com/art.png"
```
#### `soundtouch-cli source custom-radio`
```bash
soundtouch-cli --host <device> source custom-radio \
--url "https://stream.example.com/radio" \
--name "My Station" \
--artwork "https://example.com/art.png" \
--service-url "http://localhost:8080"
```
#### `soundtouch-cli source local-music`
```bash
soundtouch-cli --host <device> source local-music \
@@ -101,7 +118,7 @@ Comprehensive test suites implemented for all new functionality:
### Example Code
Complete working example demonstrating:
- LOCAL_INTERNET_RADIO with streamUrl proxy format
- LOCAL_INTERNET_RADIO with direct streams
- LOCAL_INTERNET_RADIO with direct streams
- LOCAL_MUSIC content selection
- STORED_MUSIC content selection
- Generic ContentItem usage
@@ -152,7 +169,7 @@ All convenience methods create properly structured `ContentItem` objects:
Based on the wiki structure, these related features are also supported:
1. **LOCAL_MUSIC**: ✅ Fully implemented
2. **STORED_MUSIC**: ✅ Fully implemented
2. **STORED_MUSIC**: ✅ Fully implemented
3. **SPOTIFY**: ✅ Previously implemented
4. **TUNEIN**: ✅ Previously implemented
5. **BLUETOOTH**: ✅ Previously implemented
@@ -169,7 +186,7 @@ err := client.SelectLocalInternetRadio(location, "", "My Station", "")
// Direct ContentItem
contentItem := &models.ContentItem{
Source: "LOCAL_INTERNET_RADIO",
Type: "stationurl",
Type: "stationurl",
Location: location,
ItemName: "My Station",
IsPresetable: true,
+12 -2
View File
@@ -394,6 +394,9 @@ soundtouch-cli --host <device> source spotify
soundtouch-cli --host <device> source bluetooth
soundtouch-cli --host <device> source aux
# Custom radio selection (via soundtouch-service)
soundtouch-cli --host <device> source custom-radio --url <STREAM_URL> [--name <NAME>] [--artwork <ARTWORK>] [--service-url <SERVICE_URL>]
# Advanced content selection
soundtouch-cli --host <device> source internet-radio --location <URL> [--name <NAME>]
soundtouch-cli --host <device> source local-music --location <LOCATION> --account <ACCOUNT>
@@ -482,6 +485,7 @@ soundtouch-cli --host 192.168.1.10 source compare
| Command | Description | Requirements |
|---------|-------------|--------------|
| `internet-radio` | Select internet radio stream (LOCAL_INTERNET_RADIO) | Stream URL |
| `custom-radio` | Select custom radio stream via soundtouch-service | Stream URL and service URL |
| `local-music` | Select local music content (LOCAL_MUSIC) | SoundTouch App Media Server |
| `stored-music` | Select stored music content (STORED_MUSIC) | UPnP/DLNA media server |
| `content` | Generic content selection (advanced) | Source and location |
@@ -495,6 +499,12 @@ The `internet-radio` command supports the streamUrl proxy format from the [Sound
soundtouch-cli --host 192.168.1.10 source internet-radio \
--location "http://contentapi.gmuth.de/station.php?name=Antenne%20Chillout&streamUrl=https://stream.antenne.de/chillout/stream/aacp" \
--name "Antenne Chillout"
# Using local soundtouch-service for custom streams
soundtouch-cli --host 192.168.1.10 source custom-radio \
--url "https://stream.antenne.de/chillout/stream/aacp" \
--name "Antenne Chillout" \
--service-url "http://localhost:8080"
```
#### Service Introspection
@@ -1044,7 +1054,7 @@ soundtouch-cli --host 192.168.1.10 speaker beep
**Supported Languages for TTS:**
- `EN` - English (default)
- `DE` - German
- `DE` - German
- `ES` - Spanish
- `FR` - French
- `IT` - Italian
@@ -1085,7 +1095,7 @@ soundtouch-cli --host <device> events subscribe [flags]
**Event Types:**
- `nowPlaying` - Track changes, playback status
- `volume` - Volume and mute changes
- `volume` - Volume and mute changes
- `connection` - Network connectivity status
- `preset` - Preset configuration changes
- `zone` - Multiroom zone changes
+6 -5
View File
@@ -26,10 +26,11 @@ The service consists of several key components:
### BMX Services (Bose Media eXchange)
- **TuneIn Integration**: Direct playback of radio stations and podcasts
- **Custom Streams**: Flexible playback of any internet radio URL via dynamic proxy
- **Service Registry**: Media service discovery and configuration
- **Playback Control**: Stream URL resolution and audio metadata
### Marge Services (Account & Device Management)
### Marge Services (Account & Device Management)
- **Account Management**: User account simulation and device association
- **Preset Synchronization**: Cross-device preset storage and sync
- **Recent Items**: Playback history tracking and management
@@ -57,7 +58,7 @@ go build -o soundtouch-service ./cmd/soundtouch-service
### Docker Support
You can run the SoundTouch service using Docker or Docker Compose.
You can run the SoundTouch service using Docker or Docker Compose.
> **Note for macOS and Windows users**: The `--net host` option is only supported on Linux. On macOS and Windows, service discovery (mDNS, UPnP) will not work automatically within the container. You will need to manually enter your device's IP address in the management UI, and the service will communicate with it directly.
@@ -393,7 +394,7 @@ Migrates device to use local services.
**Query Parameters:**
- `target_url`: Custom service URL (optional)
- `proxy_url`: Proxy URL for fallback (optional)
- `proxy_url`: Proxy URL for fallback (optional)
- `marge`: Set to "original" to proxy Marge requests (optional)
- `stats`: Set to "original" to proxy stats requests (optional)
- `sw_update`: Set to "original" to proxy update requests (optional)
@@ -764,7 +765,7 @@ ls -la data/events/
This service implementation is based on and inspired by several excellent community projects:
### SoundCork
- **Project**: [SoundCork](https://github.com/deborahgu/soundcork)
- **Project**: [SoundCork](https://github.com/deborahgu/soundcork)
- **Authors**: Deborah Gu and contributors
- **Contribution**: The architecture and service emulation approach in this Go implementation is heavily based on SoundCork's pioneering Python implementation. SoundCork provided the foundation for understanding Bose's service architecture and migration strategies.
@@ -809,7 +810,7 @@ soundtouch:
- host: 192.168.1.100
port: 8090
name: "Living Room Speaker"
rest:
- resource: "http://localhost:8000/setup/devices"
scan_interval: 60