From 0435f990eb6737495ecb0e2a356661d1a91235c2 Mon Sep 17 00:00:00 2001 From: Tobias Gesellchen Date: Tue, 9 Jun 2026 22:24:14 +0200 Subject: [PATCH] docs(dlna): add Music Library guide; mark /listMediaServers implemented New guide docs/content/docs/guides/dlna-music-library.md: how to browse a DLNA/UPnP media server and play it on a SoundTouch via native STORED_MUSIC (discover -> register -> browse -> play), with CLI examples (RFC-5737 IPs + placeholder UDNs) and the player Library tab (BETA), plus gotchas and format limits. Flips GET /listMediaServers from unimplemented to implemented in UNIMPLEMENTED-ENDPOINTS.md (client.ListMediaServers + models.ListMediaServersResponse). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../docs/appendix/UNIMPLEMENTED-ENDPOINTS.md | 23 +- .../content/docs/guides/dlna-music-library.md | 198 ++++++++++++++++++ 2 files changed, 211 insertions(+), 10 deletions(-) create mode 100644 docs/content/docs/guides/dlna-music-library.md diff --git a/docs/content/docs/appendix/UNIMPLEMENTED-ENDPOINTS.md b/docs/content/docs/appendix/UNIMPLEMENTED-ENDPOINTS.md index 5aced22..e0230aa 100644 --- a/docs/content/docs/appendix/UNIMPLEMENTED-ENDPOINTS.md +++ b/docs/content/docs/appendix/UNIMPLEMENTED-ENDPOINTS.md @@ -19,14 +19,15 @@ responses and community testing. > **Reconciliation note (June 2026).** Verified against `pkg/client`. Since the > last update these are **now implemented** and have been re-marked below: > `setMusicServiceAccount` / `removeMusicServiceAccount` (`SetMusicServiceAccount`, -> `RemoveMusicServiceAccount`) and the full stereo-pair group set +> `RemoveMusicServiceAccount`), the full stereo-pair group set > `getGroup` / `addGroup` / `removeGroup` / `updateGroup` -> (`GetGroup`, `AddGroup`, `RemoveGroup`, `UpdateGroup`). The priority-matrix -> counts further down are historical and have not all been recomputed; trust the -> per-endpoint ✅ markers over the section totals. Endpoints still listed as -> candidates (e.g. `/search`, `/standby`, `/powerManagement`, `/bluetoothInfo`, -> `/language`, `/listMediaServers`) were confirmed absent from `pkg/client` -> (some appear only in test fixtures). +> (`GetGroup`, `AddGroup`, `RemoveGroup`, `UpdateGroup`), and +> `listMediaServers` (`ListMediaServers`, with app-side SSDP in `pkg/discovery`). +> The priority-matrix counts further down are historical and have not all been +> recomputed; trust the per-endpoint ✅ markers over the section totals. +> Endpoints still listed as candidates (e.g. `/search`, `/standby`, +> `/powerManagement`, `/bluetoothInfo`, `/language`) were confirmed absent from +> `pkg/client` (some appear only in test fixtures). --- @@ -294,8 +295,10 @@ Rates currently playing media (Pandora only). -#### GET /listMediaServers 🔥 **CRITICAL** -Returns detected UPnP/DLNA media servers. +#### ~~GET /listMediaServers~~ ✅ **IMPLEMENTED** +~~Returns detected UPnP/DLNA media servers.~~ + +**Implementation Status:** ✅ Complete - Available in `pkg/client/client.go` as `ListMediaServers()`; response model in `pkg/models/mediaservers.go` as `ListMediaServersResponse`. The CLI exposes this via `soundtouch-cli library servers --via-speaker`. App-side SSDP discovery (without `--via-speaker`) is in `pkg/discovery`. **Response Example:** ```xml @@ -1016,7 +1019,7 @@ func TestDeviceCompatibility(t *testing.T) { 1. **Power Management**: `standby`, `powerManagement`, `lowPowerStandby` 2. **Notifications**: `speaker`, `playNotification` 3. **Network Management**: `performWirelessSiteSurvey`, `addWirelessProfile` -4. **System Info**: ~~`serviceAvailability`~~ (✅ implemented), `listMediaServers`, `language` +4. **System Info**: ~~`serviceAvailability`~~ (✅ implemented), ~~`listMediaServers`~~ (✅ implemented), `language` ### Phase 3: Advanced Features (3 weeks) 1. **Bluetooth**: `enterBluetoothPairing`, `clearBluetoothPaired` diff --git a/docs/content/docs/guides/dlna-music-library.md b/docs/content/docs/guides/dlna-music-library.md new file mode 100644 index 0000000..58c0cd7 --- /dev/null +++ b/docs/content/docs/guides/dlna-music-library.md @@ -0,0 +1,198 @@ +--- +title: "Playing Music from a DLNA / NAS Library" +--- +This guide explains how to browse a DLNA/UPnP media server on your LAN (NAS, +FRITZ!Box, minidlna, Plex, etc.) and play its tracks on a SoundTouch speaker +using the speaker's native `STORED_MUSIC` source. + +--- + +## How it works + +The **speaker is the DLNA control point**, not AfterTouch. The flow is: + +1. AfterTouch (or the CLI) discovers DLNA servers on the LAN via SSDP. +2. You register a server on the speaker with `setMusicServiceAccount`. This + creates a `STORED_MUSIC` source entry on the speaker. +3. You browse the library through the speaker's `/navigate` endpoint. The + speaker contacts the media server's ContentDirectory service and returns its + own browse tokens (e.g. `4:cont2:150:0:0:` for folders, or a track token + ending in `TRACK`). +4. You select a track or folder using `/select` with a `STORED_MUSIC` + `ContentItem`. The speaker fetches the audio directly from the media server. + AfterTouch does not proxy the audio stream. + +> **Why use the speaker's browse tokens instead of raw DLNA object IDs?** +> The speaker's `/select` endpoint only accepts the tokens it produces via +> `/navigate`. Raw DLNA ContentDirectory object IDs (like `"64"`) are not +> accepted for playback. + +--- + +## Prerequisites + +- A DLNA/UPnP media server running on the same LAN as the speaker (e.g. NAS + with minidlna, FRITZ!Box media server, Plex with DLNA enabled). +- The speaker and the media server must be on the same network segment so the + speaker can reach the server directly for streaming. +- `soundtouch-cli` installed and able to reach the speaker (test with + `soundtouch-cli --host 192.0.2.10 info`). + +--- + +## Step 1: Discover servers on the LAN + +Run an SSDP sweep from the machine where the CLI runs: + +```bash +soundtouch-cli library servers +``` + +Sample output: + +``` +Found 1 DLNA media server(s): + + Name: My Music Library + Vendor: minidlna / MiniDLNA 1.3.3 + UDN: uuid:00000000-0000-0000-0000-000000000000 + CDS: http://192.0.2.20:8200/ctl/ContentDir +``` + +Note the **UDN** (the `uuid:...` string). You will need it in the next steps. + +Alternatively, ask a specific speaker for its own DLNA list (the speaker runs +its own independent UPnP sweep): + +```bash +soundtouch-cli --host 192.0.2.10 library servers --via-speaker +``` + +> The speaker's list and the app-side list may differ. The speaker reports only +> servers it has seen on its UPnP sweep, which can lag behind or miss servers +> that appear after the speaker boots. + +--- + +## Step 2: Register the server on the speaker + +The `STORED_MUSIC` source account is the bare UUID from the UDN with a `/0` +suffix appended. If the UDN from discovery is +`uuid:00000000-0000-0000-0000-000000000000`, the account string is +`00000000-0000-0000-0000-000000000000/0` (drop the `uuid:` prefix). + +```bash +soundtouch-cli --host 192.0.2.10 account add-nas \ + --user 00000000-0000-0000-0000-000000000000/0 \ + --name "My Music Library" +``` + +Verify the source is visible: + +```bash +soundtouch-cli --host 192.0.2.10 source list +``` + +The output should include a `STORED_MUSIC` entry with your display name and +status `READY`. If the status is `UNAVAILABLE`, wait 10-20 seconds and check +again; the speaker needs a moment to connect to the media server. + +--- + +## Step 3: Browse the library + +Get the top-level containers: + +```bash +soundtouch-cli --host 192.0.2.10 browse stored-music \ + --source-account 00000000-0000-0000-0000-000000000000/0 +``` + +Drill into a folder using a location token returned from the previous step: + +```bash +soundtouch-cli --host 192.0.2.10 browse container \ + --source STORED_MUSIC \ + --source-account 00000000-0000-0000-0000-000000000000/0 \ + --location "4:cont2:150:0:0:" \ + --type dir +``` + +Repeat with `--type dir` for sub-folders, or `--type track` for track +containers. The `Location` values shown in browse output are the tokens to +pass to the next `browse container` or `library play` call. + +--- + +## Step 4: Play a track + +Pass the location token from a browse result to `library play`: + +```bash +soundtouch-cli --host 192.0.2.10 library play \ + --source-account 00000000-0000-0000-0000-000000000000/0 \ + --location "5:audio5:part13:3171:5 TRACK" \ + --name "Track Title" +``` + +The `--name` flag sets the display name shown on the speaker's display and in +the web UI. It is optional but recommended for clarity. + +The CLI checks that the `STORED_MUSIC` source is in `READY` state before +sending the play command. If it is not ready, it prints the `account add-nas` +command you need to run first. + +--- + +## Player UI (BETA) + +The soundtouch-player "Library" tab provides a browser-based interface for the +same workflow: + +1. Open the player at `http://:8000`. +2. Go to the **Library** tab. +3. Select the target speaker from the device list. +4. Click **Find servers** to run an SSDP sweep. +5. Click **Add** next to a server to register it on the speaker. +6. Open the server to browse folders and tracks. +7. Click a track to play it on the speaker. + +> **BETA notice:** DLNA behavior varies across server implementations. Some +> servers expose non-standard browse trees or restrict access by IP. If a +> server appears in discovery but does not load in the library browser, check +> that the media server allows UPnP browsing from the speaker's IP address. + +--- + +## Removing a server + +```bash +soundtouch-cli --host 192.0.2.10 account remove-nas \ + --user 00000000-0000-0000-0000-000000000000/0 +``` + +--- + +## Gotchas and limitations + +**No password needed for STORED_MUSIC.** The registration only requires the +server UDN. The `--user` flag takes the bare UUID plus `/0`; no `--password` +flag is accepted or needed. + +**Source becomes UNAVAILABLE after a speaker reboot.** The speaker re-runs its +UPnP sweep on startup. Until it rediscovers the media server (usually within +30 seconds), the `STORED_MUSIC` source shows as `UNAVAILABLE`. Wait for it to +return to `READY` before browsing or playing. + +**`uuid:` prefix in UDN.** Discovery output may show the full UDN as +`uuid:00000000-0000-0000-0000-000000000000`. Drop the `uuid:` prefix when +passing it to `--user`; the account string is just the UUID plus `/0`. + +**Format support.** The SoundTouch firmware decodes MP3 and AAC streams. HLS +(`.m3u8`) playlists and formats the firmware cannot decode (e.g. FLAC, ALAC, +OGG) will not play. If a track starts and immediately stops, the audio format +is likely unsupported. + +**Do not re-register a READY source.** Calling `account add-nas` on a source +that is already `READY` can flip it to `UNAVAILABLE`. Check `source list` +first.