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
+57
View File
@@ -1,7 +1,9 @@
package main
import (
"encoding/base64"
"fmt"
"net/url"
"strings"
"github.com/gesellix/bose-soundtouch/pkg/models"
@@ -251,6 +253,61 @@ func selectLocalInternetRadio(c *cli.Context) error {
return nil
}
// selectCustomRadio handles selecting custom radio stream via soundtouch-service
func selectCustomRadio(c *cli.Context) error {
clientConfig := GetClientConfig(c)
client, err := CreateSoundTouchClient(clientConfig)
if err != nil {
return err
}
streamURL := c.String("url")
itemName := c.String("name")
containerArt := c.String("artwork")
serviceURL := c.String("service-url")
encodedURL := base64.URLEncoding.EncodeToString([]byte(streamURL))
location := fmt.Sprintf("%s/bmx/custom/v1/playback/%s", serviceURL, encodedURL)
params := url.Values{}
if itemName != "" {
params.Add("name", itemName)
}
if containerArt != "" {
params.Add("imageUrl", containerArt)
}
if len(params) > 0 {
location += "?" + params.Encode()
}
// Check LOCAL_INTERNET_RADIO availability
checker := NewServiceAvailabilityChecker(client)
if !checker.CheckSourceAvailable("LOCAL_INTERNET_RADIO", "select custom radio") {
return fmt.Errorf("LOCAL_INTERNET_RADIO is not available")
}
PrintDeviceHeader("Selecting custom radio stream", clientConfig.Host, clientConfig.Port)
if itemName != "" {
fmt.Printf(" Station: %s\n", itemName)
}
fmt.Printf(" URL: %s\n", streamURL)
fmt.Printf(" Proxy: %s\n", location)
err = client.SelectLocalInternetRadio(location, "", itemName, containerArt)
if err != nil {
return fmt.Errorf("failed to select custom radio: %w", err)
}
PrintSuccess("Custom radio stream selected")
return nil
}
// selectLocalMusic handles selecting LOCAL_MUSIC source
func selectLocalMusic(c *cli.Context) error {
clientConfig := GetClientConfig(c)