RP400 EndPoint – RAAT, NAA, and UPnP/DLNA Functionality Without RoPieee

I previously posted the steps to create a Raspberry Pi 400 endpoint for use with Roon’s RAAT protocol and HQPlayer’s NAA protocol (see here). The OS was Ubuntu 25.10 Desktop. The solution did not include RoPieee (2026.01) because of its instability on the RP400.

The present post provides steps to add UPnP/DLNA functionality to the RP400. This is desirable when the audio stream is directed from a variety of sources, for example the JPlay app on iOS, or the BubbleUPnP app on Android.

My particular use case is as follows: I select a track from the Qobuz Android app, which sends the track selection to the BubbleUPnP Android app, which tells a BubbleUPnP server to pull the stream from the cloud, transcode it, and then send the stream to a UPnP endpoint for final transmission to the DAC.

UPnP/DLNA endpoint functionality requires the installation of additional packages. I tried the following two free options:

  1. MPD with upmpdcli integration (fully featured suite, easy to install and use headless)
  2. gmediarender-resurrect (light, moderately easy to install, not for headless operation)

There is some online chatter suggesting that these two options differ sonically (for example, see here). I have not tested for sonic differences myself. However, I believe SQ differences may be possible, given obvious sonic differences between streaming protocols and their various implementations in general (for example, see here). Let’s avoid the “bits are bits” debate for now, and proceed with installation steps.

Option #1: MPD with upmpdcli integration (my preferred option)

To install MPD with upmpdcli, type the following commands into Ubuntu terminal:

sudo apt-get update

sudo apt-get install mpd -y

sudo add-apt-repository ppa:jean-francois-dockes/upnpp1

sudo apt-get update

sudo apt-get install upmpdcli -y

The next step is to revise the default settings for MPD and upmpdcli. MPD and upmpdcli packages install their default configuration files at /etc/mpd.conf and /etc/upmpdcli.conf respectively.

For mpd.conf, use the Ubuntu text editor to make the following edits:

  • All commented settings (denoted with “#”) should be uncommented, except as indicated in these instructions.
  • Leave #pid_file and #password commented. (This is to enable root user access for convenience.)
  • The database and input settings can also be left commented.
  • For the audio outputs, various examples are provided. I used the ALSA example by uncommenting all ALSA settings. Change the name (I used “RP400-MPD”), and change device to “hw:1,0”. All other output examples (e.g. OSS output, etc.) can remain commented.
  • The setting for user should be changed from “mpd” to “root”. (This is to enable root user access for convenience.)

For upmpdcli.conf, use the Ubuntu text editor to make the following edits:

  • uncomment friendlyname, and changed its default value to the corresponding ALSA value in mpd.conf (I used “RP400-MPD”).
  • uncomment #upnpav = 1
  • uncomment #mpdhost = localhost
  • uncomment #mpdport = 6600

EDIT: To resolve a warning discussed subsequently in this thread, use the Ubuntu text editor to edit /usr/lib/systemd/system/mpd.service, and add the following line under [Service]:

Environment=“MPDCONF=/etc/mpd.conf”

Now go back to Ubuntu terminal, and enter the following commands:

sudo systemctl restart mpd

sudo systemctl restart upmpdcli

sudo systemctl enable mpd

sudo systemctl enable upmpdcli

The last step is to check the service status for MPD and upmpdcli, to ensure no significant errors. Type the following into Ubuntu terminal:

sudo systemctl status mpd

sudo systemctl status upmpdcli

NOTE: If you did not revise mpd.service as indicated above, you may get the following warning in the MPD status:

Mpd.service: Referenced but unset environment variable evaluates to an empty string: MPDCONF.

As far as I can tell, this warning does not affect UPnP/DLNA streaming. If you get additional warnings or errors, go back into the two configuration files and review the above instructions.

Assuming no errors were returned, the RP400 is now a headless UPnP/DLNA endpoint. This solution was tested with the JPlay iOS controller and BubbleUPnP, and it works alongside HQPlayer NAA capabilities. I have not tested this solution alongside Roon Bridge capabilities, as my free trial of Roon has ended. However, I have no reason to doubt that the RP400 continues to function as Roon Bridge without issue.

Option #2: gmediarender-resurrect

I could only get gmediarender working as a non-root user, which means user login is required. This additional step is contrary to the objective of headless operation. For this reason, I prefer the above Option #1.

If headless operation is not important to you, here are the steps to install and configure gmediarender on Ubuntu 25.10 Desktop.

Enter the following into Ubuntu terminal:

sudo apt-get update && sudo apt-get install -y autoconf automake libtool git libupnp-dev libgstreamer1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-alsa alsa-utils

cd /tmp

git clone https://github.###com/hzeller/gmrender-resurrect.git NOTE: “###” has been inserted to avoid auto-replacement of the plaintext URL with the title of the website. This command should therefore be entered with “###” omitted from the URL.

cd gmrender-resurrect

./autogen.sh

./configure

make

sudo make install

Then, with Ubuntu text editor, create /etc/systemd/system/gmediarender.service with the following contents:

[Unit]
Description=GMediaRender UPnP/DLNA Renderer
After=network.target sound.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/gmediarender --friendly-name “RP400-UPnP” --daemon --gstout-audiosink=alsasink --gstout-audiodevice=hw:1,0
Restart=always
Group=audio

[Install]
WantedBy=multi-user.target

Now go back into Ubuntu terminal and type the following commands:

sudo systemctl daemon-reload

sudo systemctl start gmediarender.service

sudo systemctl enable gmediarender.service

If you would like to see the status of gmediarender, type the following into Ubuntu terminal:

sudo systemctl status gmediarender.service

Assuming no errors, installation and configuration are now complete. If desired, the source files can be removed with the following commands in Ubuntu terminal:

cd /tmp && sudo rm -rf gmrender-resurrect

Unfortunately, this solution does not load gmediarender as a service on startup. There is a permissions issue as root user, which for some reason requires a non-root user to login. However, once logged in, the non-root user can start gmediarender with the following command typed into Ubuntu terminal (or placed in an executable script):

/usr/local/bin/gmediarender --friendly-name “RP400-UPnP” --daemon --gstout-audiosink=alsasink --gstout-audiodevice=hw:1,0

The RP400 is now a UPnP/DLNA endpoint. This solution was tested with the JPlay iOS controller and BubbleUPnP, and it works alongside HQPlayer NAA capabilities. I have not tested this solution alongside Roon Bridge capabilities, as my free trial of Roon has ended. However, I have no reason to doubt that the RP400 continues to function as Roon Bridge without issue.

If anyone figures out how to load gmediarender as a systemd service on startup without login, please post your solution. A startup script with automated user login may be possible. However, I was unable to get past the requirement for user credentials (even for user accounts that do not require a password). There’s probably a solution, but the relative simplicity of using MPD with upmpdcli integration (Option #1 above) has made that my preferred solution.

Probaby as easy as adding this to the systemctl service file.

Environment="MPDCONF="

Your feedback resolved the error - thanks! However, since $MDPCONF is referenced in ExecStart (within the service file), the best practice is probably to reference the path of mpd.conf.

To reproduce the fix, use the text editor to edit /usr/lib/systemd/system/mpd.service, and add the following line under [Service]:

Environment=“MPDCONF=/etc/mpd.conf”

Then enter the following commands in Ubuntu terminal:

sudo rm /etc/systemd/system/multi-user.target.wants/mpd.service
sudo systemctl daemon-reload
sudo systemctl restart mpd
sudo systemctl enable mpd
sudo systemctl status mpd

There should now be no errors while starting mpd.service. I’ll update the above instructions accordingly.

It was a warning, not an error. :slight_smile:

All the line I suggested does is set (declare) the environment variable; the warning was telling you that it was unset. It still has no value when the service starts.

Moreover, you did not need to disable or stop the service to edit the file. Simple use systemctl daemon-reload and then restart the service.

Fair enough - the alert was a warning rather than an error. But why would the default service file include $MPDCONF without declaring its value? Perhaps an oversight in the MPD build?

Regarding disabling and stopping the service before daemon-reload, it looks like you read an older version of my last post before it was edited. At that time, I was trying to resolve the following new error upon enabling the MPD service:

Failed to enable unit: file ‘/etc/systemd/system/multi-user.target.wants/mpd.service’ already exists"

Instead of seeing a symbolic link at this location, MPD was seeing an actual file with the same name. I thought that starting/stopping the service might remove the file, but it didn’t. I eventually just removed the file manually with a “sudo rm” command. The service could thereafter be enabled without issue.

I don’t believe a subsequent user will run into this problem if they edit the service file right after install, before enabling and starting the service for the first time. (Just to be clear, I’m talking about mpd.service located at the path provided in my last post, not mpd.service from the path in the error message quoted in the present post.)

I’ve revised the original post as appropriate. Many thanks for your help to resolve the MPDCONF warning!

The default service file didn’t include the declaration, which is why there was a warning. This is a recent addition to systemctl.