feat(player,cli): nudge sources refresh after adding a media server

Adding a DLNA media server (setMusicServiceAccount) can leave the new
STORED_MUSIC source not fully registered on the speaker, so playing a track
fails with INVALID_SOURCE until a power-cycle. AfterTouch's health
diagnostic already recommends the no-reboot fix: a sourcesUpdated
notification makes the speaker re-fetch its account /full and re-register
its source list.

Fire that nudge automatically right after a successful registration, in
both the player (HandleAddLibraryServer) and the CLI (account add-nas), via
the existing client.NotifySourcesUpdated. It is best-effort: registration
already succeeded, so a failed nudge never fails the request (the handler
returns {account, refreshed}, the CLI prints a warning that a power-cycle
may still be needed). The handler resolves the Bose device ID from the
cached DeviceConnection.DeviceInfo, falling back to GetDeviceInfo.

Note: per the diagnostic, a power-cycle is still occasionally required, so
the nudge is an improvement, not a guarantee.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-06-11 20:56:04 +02:00
co-authored by Claude Opus 4.8
parent f010e96699
commit 836e985c58
3 changed files with 124 additions and 6 deletions
+15 -2
View File
@@ -318,7 +318,7 @@ func removePandoraAccount(c *cli.Context) error {
func addStoredMusicAccount(c *cli.Context) error {
clientConfig := GetClientConfig(c)
client, err := CreateSoundTouchClient(clientConfig)
stClient, err := CreateSoundTouchClient(clientConfig)
if err != nil {
return err
}
@@ -340,13 +340,26 @@ func addStoredMusicAccount(c *cli.Context) error {
fmt.Printf(" Display Name: %s\n", displayName)
fmt.Printf(" Type: UPnP/DLNA Media Server\n")
err = client.AddStoredMusicAccount(user, displayName)
err = stClient.AddStoredMusicAccount(user, displayName)
if err != nil {
return fmt.Errorf("failed to add network music library: %w", err)
}
PrintSuccess("Network music library added successfully")
// Send a sourcesUpdated nudge so the speaker re-fetches its account list and
// registers the new source without requiring a power-cycle. This is
// best-effort: a failure here does not abort the command.
if info, infoErr := stClient.GetDeviceInfo(); infoErr == nil && info != nil && info.DeviceID != "" {
if nudgeErr := stClient.NotifySourcesUpdated(info.DeviceID); nudgeErr == nil {
fmt.Println(" Sent a sources refresh to the speaker (no reboot needed).")
} else {
fmt.Println(" Warning: could not send sources refresh; you may need to power-cycle the speaker for the new source to register.")
}
} else {
fmt.Println(" Warning: could not retrieve device ID; you may need to power-cycle the speaker for the new source to register.")
}
// Show next steps
fmt.Printf("\n💡 Next Steps:\n")
fmt.Printf(" • Check available sources: soundtouch-cli --host %s source list\n", clientConfig.Host)