Documentation for controlling and preserving Bose SoundTouch devices
The Bose SoundTouch Go client provides comprehensive source selection functionality through the POST /select endpoint. This feature allows you to switch between different audio sources like Spotify, Bluetooth, AUX input, and various streaming services.
✅ Complete - All source selection functionality implemented and tested
SelectSource()Purpose: Select an audio source for playback
Request Format:
<ContentItem source="SPOTIFY" sourceAccount="user_account">
<itemName>Spotify</itemName>
</ContentItem>
Response: HTTP 200 OK (no body) on success
Supported Sources:
SPOTIFY - Spotify streaming serviceBLUETOOTH - Bluetooth audio inputAUX - Auxiliary input (3.5mm jack)TUNEIN - TuneIn internet radioPANDORA - Pandora streaming serviceAMAZON - Amazon MusicIHEARTRADIO - iHeartRadio streamingSTORED_MUSIC - Local/network stored musicAIRPLAY - Apple AirPlay (device dependent)RADIO_BROWSER - RadioBrowser internet radio directoryimport "github.com/gesellix/bose-soundtouch/pkg/client"
// Create client
config := client.ClientConfig{
Host: "192.168.1.100",
Port: 8090,
}
c := client.NewClient(config)
// Select a source
err := c.SelectSource("SPOTIFY", "your_spotify_account")
if err != nil {
fmt.Printf("Failed to select source: %v\n", err)
}
For popular sources, use the convenience methods:
// Select Spotify
err := c.SelectSpotify("your_account")
// Select Bluetooth
err := c.SelectBluetooth()
// Select AUX input
err := c.SelectAux()
// Select TuneIn
err := c.SelectTuneIn("tunein_account")
// Select Pandora
err := c.SelectPandora("pandora_account")
First get available sources, then select from them:
// Get available sources
sources, err := c.GetSources()
if err != nil {
return fmt.Errorf("failed to get sources: %w", err)
}
// Find and select a ready Spotify source
spotifySources := sources.GetReadySpotifySources()
if len(spotifySources) > 0 {
err := c.SelectSourceFromItem(&spotifySources[0])
if err != nil {
return fmt.Errorf("failed to select Spotify: %w", err)
}
}
// Or use helper methods
if sources.HasBluetooth() {
err := c.SelectBluetooth()
if err != nil {
return fmt.Errorf("failed to select Bluetooth: %w", err)
}
}
err := c.SelectSource("INVALID_SOURCE", "")
if err != nil {
// Check for API errors
if apiErr, ok := err.(*models.APIError); ok {
fmt.Printf("API Error: %s (code: %d)\n", apiErr.Message, apiErr.Code)
} else {
fmt.Printf("General error: %v\n", err)
}
}
# Select source using generic method
soundtouch-cli -host 192.168.1.100 -select-source SPOTIFY -source-account "your_account"
# Select source with convenience flags
soundtouch-cli -host 192.168.1.100 -spotify -source-account "your_account"
soundtouch-cli -host 192.168.1.100 -bluetooth
soundtouch-cli -host 192.168.1.100 -aux
# Check available sources first
soundtouch-cli -host 192.168.1.100 -sources
# Select Spotify with account
soundtouch-cli -host 192.168.1.100 -spotify -source-account "your_account"
# Select TuneIn
soundtouch-cli -host 192.168.1.100 -select-source TUNEIN
# Select AUX input
soundtouch-cli -host 192.168.1.100 -aux
| Flag | Description | Example |
|---|---|---|
-select-source <source> |
Select audio source | -select-source SPOTIFY |
-source-account <account> |
Account for streaming services | -source-account "user123" |
-spotify |
Select Spotify source | -spotify -source-account "user" |
-bluetooth |
Select Bluetooth source | -bluetooth |
-aux |
Select AUX input | -aux |
Use the sources endpoint to discover available accounts:
soundtouch-cli -host 192.168.1.100 -sources
This shows account names for each source:
Ready Sources:
• user+spotify@example.com (user) [Remote, Multiroom, Streaming]
In this example:
user+spotify@example.comuser (often works better)func selectBestAvailableSource(client *client.Client) error {
sources, err := client.GetSources()
if err != nil {
return err
}
// Prefer Spotify if available
if sources.HasSpotify() {
spotifySources := sources.GetReadySpotifySources()
return client.SelectSourceFromItem(&spotifySources[0])
}
// Fall back to TuneIn
if sources.HasSource("TUNEIN") {
tuneInSources := sources.GetSourcesByType("TUNEIN")
for _, src := range tuneInSources {
if src.Status.IsReady() {
return client.SelectSourceFromItem(&src)
}
}
}
// Last resort: AUX if available
if sources.HasAux() {
return client.SelectAux()
}
return fmt.Errorf("no suitable sources available")
}
type SourceConfig struct {
PreferredSources []string
Accounts map[string]string
}
func selectWithConfig(client *client.Client, config SourceConfig) error {
sources, err := client.GetSources()
if err != nil {
return err
}
for _, preferred := range config.PreferredSources {
if sources.HasSource(preferred) {
account := config.Accounts[preferred]
return client.SelectSource(preferred, account)
}
}
return fmt.Errorf("none of the preferred sources are available")
}
| Code | Name | Description | Solution |
|---|---|---|---|
| 1005 | UNKNOWN_SOURCE_ERROR | Invalid or unavailable source | Check available sources first |
| 1006 | SOURCE_UNAVAILABLE | Source temporarily unavailable | Try again later |
| 1007 | ACCOUNT_ERROR | Invalid account for source | Check account name format |
soundtouch-cli -host <ip> -sources
Run all source selection tests:
go test ./pkg/client -v -run ".*SelectSource.*"
Test with real hardware:
SOUNDTOUCH_TEST_HOST=192.168.1.100 go test ./pkg/client -v -run ".*Integration.*"
# Test discovery and source selection
soundtouch-cli -discover
soundtouch-cli -host <discovered-ip> -sources
soundtouch-cli -host <discovered-ip> -spotify -source-account "account"
soundtouch-cli -host <discovered-ip> -nowplaying # Verify selection
Source selection typically completes in:
The implementation follows the official SoundTouch API:
ContentItem XML structuresource and sourceAccount attributesitemName for better UXImplementation Date: 2026-01-09
Status: ✅ Complete and tested
Real Device Validation: SoundTouch 10, SoundTouch 20