From 19ac61a11b3c909f6aa82c6a2aa76a2dae8507f6 Mon Sep 17 00:00:00 2001 From: Mikhail Nevskiy Date: Wed, 22 Apr 2026 21:30:26 +0300 Subject: [PATCH 1/5] docs(plugins): add DLNA Receiver plugin page Adds a new documentation page for the DLNA Receiver plugin, which exposes Music Assistant as a UPnP/DLNA MediaRenderer so external apps can cast audio to any MA player. - New page: src/content/docs/plugins/dlna-receiver.md - Sidebar entry added to astro.config.mjs under Plugins Related PR: music-assistant/server#3611 --- astro.config.mjs | 1 + src/content/docs/plugins/dlna-receiver.md | 80 +++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/content/docs/plugins/dlna-receiver.md diff --git a/astro.config.mjs b/astro.config.mjs index 30eed47a2..10d03fcdf 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -254,6 +254,7 @@ export default defineConfig({ items: [ { label: 'AirPlay Receiver Plugin', slug: 'plugins/airplay-receiver' }, { label: 'Ariacast Receiver Plugin', slug: 'plugins/ariacast-receiver' }, + { label: 'DLNA Receiver Plugin', slug: 'plugins/dlna-receiver' }, { label: 'Home Assistant Plugin', slug: 'ha-plugin' }, { label: 'LastFM Scrobbler', slug: 'plugins/lastfm_scrobble' }, { label: 'Listenbrainz Scrobbler', slug: 'plugins/listenbrainz_scrobble' }, diff --git a/src/content/docs/plugins/dlna-receiver.md b/src/content/docs/plugins/dlna-receiver.md new file mode 100644 index 000000000..566b481f9 --- /dev/null +++ b/src/content/docs/plugins/dlna-receiver.md @@ -0,0 +1,80 @@ +--- +title: "DLNA Receiver Plugin" +description: Features and Notes for the DLNA Receiver Plugin +--- + +# DLNA Receiver + +Music Assistant can act as a [UPnP/DLNA MediaRenderer](https://openconnectivity.org/developer/specifications/upnp-resources/upnp/) on the local network, so that external DLNA-aware apps can discover it over SSDP and cast audio to any MA player. Contributed and maintained by [TrudenBoy](https://github.com/TrudenBoy). + +External apps send a stream URL via the standard DLNA protocol (`SetAVTransportURI` / `Play`) and Music Assistant proxies the audio through its streaming pipeline to the selected target player — DLNA speakers, AirPlay receivers, Chromecast, Yandex Station, Squeezebox, etc. + +> [!CAUTION] +> This is an unofficial implementation of the UPnP/DLNA MediaRenderer server side and is not certified by the UPnP Forum / Open Connectivity Foundation. + +> [!WARNING] +> SSDP relies on IPv4 multicast on `239.255.255.250:1900`. When running Music Assistant in Docker, `network_mode: host` is required — bridge networking will prevent control points from discovering the renderer. + +> [!NOTE] +> Full plugin documentation: **[trudenboy.github.io/ma-provider-dlna-receiver](https://trudenboy.github.io/ma-provider-dlna-receiver/)** + + +## Features + +| | | +|:-----------------------|:---------------------:| +| Exposes MA players as DLNA MediaRenderers | Yes | +| Device type | `urn:schemas-upnp-org:device:MediaRenderer:1` | +| Multi-player mode (one renderer per MA player) | Yes | +| Stable device identity across restarts | Yes (UUID5-derived UDN) | +| Multiple plugin instances | No | +| UPnP eventing (GENA SUBSCRIBE/NOTIFY) | Yes | + +### Supported UPnP services and actions + +| UPnP service | Supported actions | +|---|---| +| `AVTransport:1` | `SetAVTransportURI`, `Play`, `Pause`, `Stop`, `Seek`, `GetTransportInfo`, `GetPositionInfo`, `GetMediaInfo` | +| `RenderingControl:1` | `GetVolume`, `SetVolume`, `GetMute`, `SetMute` | +| `ConnectionManager:1` | `GetProtocolInfo`, `GetCurrentConnectionIDs`, `GetCurrentConnectionInfo` | + +### Tested DLNA control points + +- [BubbleUPnP](https://bubblesoftapps.com/bubbleupnp/) (Android) +- [mconnect Player](https://www.mconnect.cc/) (iOS / Android) +- [foobar2000](https://www.foobar2000.org/) with UPnP/DLNA Renderer, Server, Control Point component +- [Kodi](https://kodi.tv/) (as UPnP control point) +- [Qobuz](https://www.qobuz.com/) (Android — "Cast to" menu) + +## Configuration + +The plugin is single-instance. After adding it in Music Assistant, configure the following settings: + +### Settings + +- **Friendly name prefix** — prefix shown to DLNA control points on the network. In multi-player mode the MA player name is appended automatically (e.g. `Music Assistant — Kitchen`). Default: `Music Assistant`. +- **Target players** — how MA players are exposed on the network: + - *empty* — a single unbound renderer is advertised; playback can be routed to any player via the MA UI after receiving the stream. + - *comma-separated player IDs* — one dedicated renderer per listed player (e.g. `kitchen,living_room`). + - `*` — automatically create one renderer per MA player, including players that come online after startup. +- **Bind IP address** — IP address on which the UPnP HTTP server and SSDP listener bind. Leave empty to auto-detect the primary interface. +- **HTTP base port** — base TCP port for the UPnP HTTP servers. In multi-player mode each additional renderer uses the next port (e.g. `8298`, `8299`, `8300`, …). Default: `8298`. + +### Multi-player mode + +In multi-player mode every MA player is advertised as its own DLNA device with: + +- a unique friendly name (``); +- a stable UDN derived from the MA player ID via UUID5, so BubbleUPnP / mconnect bookmarks survive restarts; +- its own HTTP port for the UPnP description and SOAP control endpoints. + +Control points see them as independent devices — e.g. *Music Assistant — Kitchen*, *Music Assistant — Living Room*, *Music Assistant — Yandex Station*. + +## Known Issues / Notes + +- Docker: `network_mode: host` is required for SSDP multicast. Without it, SSDP `NOTIFY` / `M-SEARCH` packets cannot leave the container and control points will not discover any renderer. +- Only `http://` and `https://` stream URLs are accepted. `SetAVTransportURI` requests with `file://`, `ftp://` or other schemes, or URIs resolving to loopback / private addresses via redirects, are rejected with SOAP fault `716 (Illegal MIME-Type)` to protect against SSRF. +- MA's audio pipeline may introduce a small delay between the control point's `Play` command and audio output on the target player, depending on the player's buffering. +- The SCPD (service description XML) documents ship as minimal stubs — a handful of strict control points that parse the full state variable table may flag warnings, but all tested apps above work correctly. +- DIDL-Lite metadata from control points is parsed for title / artist / album / artwork / duration and displayed in the MA UI. Input is size-bounded and DOCTYPE/ENTITY declarations are rejected to guard against XML-expansion DoS. +- The renderer participates in SSDP `M-SEARCH` and advertises `alive` / `byebye` on start / stop. If renderers linger in a control point after MA is killed with `SIGKILL`, wait up to 30 minutes (SSDP cache timeout) or re-open the control point to force re-discovery. From c0d6c9137d1dc8a0c4f61670b9c14954ae1aad4d Mon Sep 17 00:00:00 2001 From: Mikhail Nevskiy Date: Tue, 28 Apr 2026 09:18:22 +0300 Subject: [PATCH 2/5] docs(dlna-receiver): trim to user-facing content Address review feedback on PR #626: - Remove external docs link and UPnP-internals (SCPD, GENA, UDN/UUID5, SOAP fault codes, DIDL-Lite XEE). - Replace features/services tables with concise user-focused bullets. - Simplify settings descriptions and Docker note. --- src/content/docs/plugins/dlna-receiver.md | 77 ++++++----------------- 1 file changed, 18 insertions(+), 59 deletions(-) diff --git a/src/content/docs/plugins/dlna-receiver.md b/src/content/docs/plugins/dlna-receiver.md index 566b481f9..550744153 100644 --- a/src/content/docs/plugins/dlna-receiver.md +++ b/src/content/docs/plugins/dlna-receiver.md @@ -5,46 +5,17 @@ description: Features and Notes for the DLNA Receiver Plugin # DLNA Receiver -Music Assistant can act as a [UPnP/DLNA MediaRenderer](https://openconnectivity.org/developer/specifications/upnp-resources/upnp/) on the local network, so that external DLNA-aware apps can discover it over SSDP and cast audio to any MA player. Contributed and maintained by [TrudenBoy](https://github.com/TrudenBoy). - -External apps send a stream URL via the standard DLNA protocol (`SetAVTransportURI` / `Play`) and Music Assistant proxies the audio through its streaming pipeline to the selected target player — DLNA speakers, AirPlay receivers, Chromecast, Yandex Station, Squeezebox, etc. - -> [!CAUTION] -> This is an unofficial implementation of the UPnP/DLNA MediaRenderer server side and is not certified by the UPnP Forum / Open Connectivity Foundation. - -> [!WARNING] -> SSDP relies on IPv4 multicast on `239.255.255.250:1900`. When running Music Assistant in Docker, `network_mode: host` is required — bridge networking will prevent control points from discovering the renderer. - -> [!NOTE] -> Full plugin documentation: **[trudenboy.github.io/ma-provider-dlna-receiver](https://trudenboy.github.io/ma-provider-dlna-receiver/)** +Music Assistant can act as a UPnP/DLNA MediaRenderer on the local network. External DLNA-aware apps discover it on the network and can cast audio to any MA player. +Once an external app sends a stream URL via the standard DLNA protocol, Music Assistant proxies the audio through its streaming pipeline to the selected target player — DLNA speakers, AirPlay receivers, Chromecast, Yandex Station, Squeezebox, etc. ## Features -| | | -|:-----------------------|:---------------------:| -| Exposes MA players as DLNA MediaRenderers | Yes | -| Device type | `urn:schemas-upnp-org:device:MediaRenderer:1` | -| Multi-player mode (one renderer per MA player) | Yes | -| Stable device identity across restarts | Yes (UUID5-derived UDN) | -| Multiple plugin instances | No | -| UPnP eventing (GENA SUBSCRIBE/NOTIFY) | Yes | - -### Supported UPnP services and actions - -| UPnP service | Supported actions | -|---|---| -| `AVTransport:1` | `SetAVTransportURI`, `Play`, `Pause`, `Stop`, `Seek`, `GetTransportInfo`, `GetPositionInfo`, `GetMediaInfo` | -| `RenderingControl:1` | `GetVolume`, `SetVolume`, `GetMute`, `SetMute` | -| `ConnectionManager:1` | `GetProtocolInfo`, `GetCurrentConnectionIDs`, `GetCurrentConnectionInfo` | - -### Tested DLNA control points - -- [BubbleUPnP](https://bubblesoftapps.com/bubbleupnp/) (Android) -- [mconnect Player](https://www.mconnect.cc/) (iOS / Android) -- [foobar2000](https://www.foobar2000.org/) with UPnP/DLNA Renderer, Server, Control Point component -- [Kodi](https://kodi.tv/) (as UPnP control point) -- [Qobuz](https://www.qobuz.com/) (Android — "Cast to" menu) +- Exposes Music Assistant players as DLNA MediaRenderers on the local network +- Works as either a single virtual renderer or one renderer per MA player +- Renderer names and identity persist across MA restarts, so DLNA apps remember their bookmarks +- Reports playback progress and volume back to the controlling app +- Tested with [BubbleUPnP](https://bubblesoftapps.com/bubbleupnp/) ## Configuration @@ -52,29 +23,17 @@ The plugin is single-instance. After adding it in Music Assistant, configure the ### Settings -- **Friendly name prefix** — prefix shown to DLNA control points on the network. In multi-player mode the MA player name is appended automatically (e.g. `Music Assistant — Kitchen`). Default: `Music Assistant`. -- **Target players** — how MA players are exposed on the network: - - *empty* — a single unbound renderer is advertised; playback can be routed to any player via the MA UI after receiving the stream. - - *comma-separated player IDs* — one dedicated renderer per listed player (e.g. `kitchen,living_room`). - - `*` — automatically create one renderer per MA player, including players that come online after startup. -- **Bind IP address** — IP address on which the UPnP HTTP server and SSDP listener bind. Leave empty to auto-detect the primary interface. -- **HTTP base port** — base TCP port for the UPnP HTTP servers. In multi-player mode each additional renderer uses the next port (e.g. `8298`, `8299`, `8300`, …). Default: `8298`. - -### Multi-player mode - -In multi-player mode every MA player is advertised as its own DLNA device with: - -- a unique friendly name (``); -- a stable UDN derived from the MA player ID via UUID5, so BubbleUPnP / mconnect bookmarks survive restarts; -- its own HTTP port for the UPnP description and SOAP control endpoints. - -Control points see them as independent devices — e.g. *Music Assistant — Kitchen*, *Music Assistant — Living Room*, *Music Assistant — Yandex Station*. +- **Friendly name prefix** — name shown to DLNA apps on the network. When multiple players are exposed, the MA player name is appended automatically (e.g. `Music Assistant — Kitchen`). Default: `Music Assistant`. +- **Target players** — controls which Music Assistant players appear as DLNA devices: + - *empty* — a single virtual renderer is advertised; you can route the incoming stream to any player from the MA UI after it starts. + - *comma-separated player IDs* — one DLNA device per listed player (e.g. `kitchen,living_room`). + - `*` — automatically expose every MA player, including ones that come online later. +- **Bind IP address** — IP address the plugin listens on. Leave empty to auto-detect. +- **HTTP base port** — TCP port used by the plugin. When multiple players are exposed, the next ports are used as well (e.g. `8298`, `8299`, `8300`, …). Default: `8298`. ## Known Issues / Notes -- Docker: `network_mode: host` is required for SSDP multicast. Without it, SSDP `NOTIFY` / `M-SEARCH` packets cannot leave the container and control points will not discover any renderer. -- Only `http://` and `https://` stream URLs are accepted. `SetAVTransportURI` requests with `file://`, `ftp://` or other schemes, or URIs resolving to loopback / private addresses via redirects, are rejected with SOAP fault `716 (Illegal MIME-Type)` to protect against SSRF. -- MA's audio pipeline may introduce a small delay between the control point's `Play` command and audio output on the target player, depending on the player's buffering. -- The SCPD (service description XML) documents ship as minimal stubs — a handful of strict control points that parse the full state variable table may flag warnings, but all tested apps above work correctly. -- DIDL-Lite metadata from control points is parsed for title / artist / album / artwork / duration and displayed in the MA UI. Input is size-bounded and DOCTYPE/ENTITY declarations are rejected to guard against XML-expansion DoS. -- The renderer participates in SSDP `M-SEARCH` and advertises `alive` / `byebye` on start / stop. If renderers linger in a control point after MA is killed with `SIGKILL`, wait up to 30 minutes (SSDP cache timeout) or re-open the control point to force re-discovery. +- To listen to the plugin audio, navigate to the desired player's NOW PLAYING view and then in the menu in the top right, select Source, and choose the desired DLNA Receiver. +- **Docker:** `network_mode: host` is required. Bridge networking blocks DLNA discovery and control points will not see any renderer. +- A small delay between *Play* in the controlling app and audio on the target player is normal — it depends on the target player's buffering. +- For security, only `http://` and `https://` stream URLs are accepted. Other schemes and URLs that resolve to private or loopback addresses are rejected. From 26f8fad72fd601c48e1511b0ff9b05f34207853a Mon Sep 17 00:00:00 2001 From: Mikhail Nevskiy <139659391+trudenboy@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:28:58 +0300 Subject: [PATCH 3/5] Update src/content/docs/plugins/dlna-receiver.md Co-authored-by: OzGav --- src/content/docs/plugins/dlna-receiver.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/plugins/dlna-receiver.md b/src/content/docs/plugins/dlna-receiver.md index 550744153..4a720bc1e 100644 --- a/src/content/docs/plugins/dlna-receiver.md +++ b/src/content/docs/plugins/dlna-receiver.md @@ -19,7 +19,7 @@ Once an external app sends a stream URL via the standard DLNA protocol, Music As ## Configuration -The plugin is single-instance. After adding it in Music Assistant, configure the following settings: +The plugin is single-instance. After adding it to Music Assistant, configure the following: ### Settings From adf718d1f584fa02a1b0bd499be2ca558d14ddcc Mon Sep 17 00:00:00 2001 From: Mikhail Nevskiy <139659391+trudenboy@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:31:40 +0300 Subject: [PATCH 4/5] Update dlna-receiver.md --- src/content/docs/plugins/dlna-receiver.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/content/docs/plugins/dlna-receiver.md b/src/content/docs/plugins/dlna-receiver.md index 4a720bc1e..a67cbbe0d 100644 --- a/src/content/docs/plugins/dlna-receiver.md +++ b/src/content/docs/plugins/dlna-receiver.md @@ -13,13 +13,11 @@ Once an external app sends a stream URL via the standard DLNA protocol, Music As - Exposes Music Assistant players as DLNA MediaRenderers on the local network - Works as either a single virtual renderer or one renderer per MA player -- Renderer names and identity persist across MA restarts, so DLNA apps remember their bookmarks - Reports playback progress and volume back to the controlling app -- Tested with [BubbleUPnP](https://bubblesoftapps.com/bubbleupnp/) ## Configuration -The plugin is single-instance. After adding it to Music Assistant, configure the following: +After adding it to Music Assistant, configure the following: ### Settings From b53dd93c01bf9639c3685ea1d721237ac1cc3771 Mon Sep 17 00:00:00 2001 From: Mikhail Nevskiy <139659391+trudenboy@users.noreply.github.com> Date: Tue, 28 Apr 2026 17:33:21 +0300 Subject: [PATCH 5/5] Update known issues for DLNA Receiver plugin Added note about Docker network mode requirement for DLNA. --- src/content/docs/plugins/dlna-receiver.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/plugins/dlna-receiver.md b/src/content/docs/plugins/dlna-receiver.md index a67cbbe0d..268400116 100644 --- a/src/content/docs/plugins/dlna-receiver.md +++ b/src/content/docs/plugins/dlna-receiver.md @@ -32,6 +32,5 @@ After adding it to Music Assistant, configure the following: ## Known Issues / Notes - To listen to the plugin audio, navigate to the desired player's NOW PLAYING view and then in the menu in the top right, select Source, and choose the desired DLNA Receiver. -- **Docker:** `network_mode: host` is required. Bridge networking blocks DLNA discovery and control points will not see any renderer. - A small delay between *Play* in the controlling app and audio on the target player is normal — it depends on the target player's buffering. - For security, only `http://` and `https://` stream URLs are accepted. Other schemes and URLs that resolve to private or loopback addresses are rejected.