There are a lot of posts on how to get this up and running so rather than traipse through 100s of posts to piece it all together I’ll pull together here. It took a while to nut out some of the finer points so I hope this helps.
There are appear to be two differing methods of using Roon with older streamers.
- Get a Rpi and Allo DAC or some derivation and use that as the end point.
- Use a method that creates an endpoint the bridges the Roon Raat protocol to something that the older streamers understand like uPnP.
This post discusses option 2
There are 2 methods I know of to implement the bridge, Software only and a hardware version. A company called “small green computer” sells a Sonore uPnP bridge/sonic transporter which acts as the bridge. I have never used these.
The second method is a piece of open source software that I have used with great success called lms-to-uPnP. It is usually used as a plugin to the Logitech Media Server (LMS) - but we will not be installing it in LMS as a plugin. We will install it manually on its own so our Roon server can see it.
Pros and Cons (in no particular order)
- Its opensource and freely available and actively maintained.
- Lots of OSs and CPU architectures are supported including Linux Windows MacOS and NASs.
- Allows grouping (but not proper syncing of new and old devices)
- No meta data shows up on my ND5XS ( I prefer the Roon interface anyway)
- I have all DSP off so volume does not work for me on the Naim( I use the NAC 102 remote for volume)
- It requires a NAS/Rpi/Server or something on 24/7 to act as a bridge. ( I use the same Linux box that the Roon server is installed on)
- I don’t know if there’s an impact on SQ compared to the Sonare uPnP bridge. (but expect it to be be better than the Rpi/DAC route)
- Nothing to compile or build - downloading the zip file gets you all the binaries for all OSs
- It uses very low resources (I have it configured for passthrough mode)
- Cannot use the LMS GUI to install.
What does it do and how does it work?
I’m not entirely sure, I’m no expert on how it actually works, but I think the lms-to-uPnP searches the network using mDNS and finds all uPnP servers. It then advertises each uPnP device back to Roon as a squeezebox.
The uPnP spec also allows the uPnP devices to advertise their specifications, like sample rates, file formats etc. The lms-to-uPnP does a pretty good job of translating this back to the Roon in pass through mode, and this means that when I play a song at 384khz, the Roon server automatically re-samples/converts it to 192khz (which is the limit of the ND5XS). Manual changes can be made in a config.xml file if needed. I need to to experiment with sending WAV vs PCM (raw), not sure what they do!
In the config file, parameter values listed first have higher priority.
How to Run it?
- Ensure LMS compatibility is turned on in the Roon interface
- Put the application on a LOCAL disk where you have read/write access
- Choose the correct binary for your OS and CPU (choose the “static” version for the least problems)
- launch it with “squeeze2upnplms-??? -i config.xml” on the command line, and wait 30s till it exits.
- Launch it again just without any flags and hopefully your devices will appear in Roon.
- Go and edit the config.xml file if needed.
- Once happy create a start script so it comes up on reboot.
- Ensure the “-Z” flag is used in your start script otherwise the lms-to-uPnP bridge will slowly consume all your RAM (since its waiting for input) the Z flag puts into daemon/background service.
- There are a couple of “modes”, I use “pass through” mode and have not tried any others. I’m keen to hear from anyone that has?
- In the doc folder there is a great userguide.htm and it explains all the settings.
- Make sure the parameter in the config.xml called roon_mode is set to 1 as per the file below.
Some helpful files
INSTALL\Bin\config.xml (you cannot copy this file and expect it to work as your UUIDs will be different!).
The top section is a general section which holds all the defaults. Copying a parameter to a device section and editing it overrides the default. the below file works, but is not necessary optimised, I’d be keen to hear back form others that have managed to improve it.
<?xml version="1.0"?> <squeeze2upnp> <common> <streambuf_size>524288</streambuf_size> <output_size>4194304</output_size> <stream_length>-3</stream_length> <enabled>1</enabled> <roon_mode>1</roon_mode> <codecs>aac,ogg,flc,alc,aif,pcm,mp3</codecs> <mode>thru</mode> <raw_audio_format>wav,raw,aif</raw_audio_format> <sample_rate>48000</sample_rate> <L24_format>1</L24_format> <flac_header>1</flac_header> <forced_mimetypes></forced_mimetypes> <seek_after_pause>0</seek_after_pause> <send_icy>1</send_icy> <volume_on_play>1</volume_on_play> <volume_feedback>1</volume_feedback> <send_metadata>1</send_metadata> <send_coverart>1</send_coverart> <max_volume>100</max_volume> <accept_nexturi>1</accept_nexturi> <min_gapless>10</min_gapless> <auto_play>0</auto_play> <server>?</server> <resample_options></resample_options> </common> <upnp_socket>?</upnp_socket> <slimproto_log>info</slimproto_log> <slimmain_log>warn</slimmain_log> <stream_log>warn</stream_log> <output_log>info</output_log> <decode_log>warn</decode_log> <main_log>info</main_log> <upnp_log>info</upnp_log> <util_log>warn</util_log> <log_limit>-1</log_limit> <device> <udn>uuid:67a91540-097a-d74a-d66d-2bcf116dfe06</udn> <name>Kodi (kodi)</name> <friendly_name>Kodi (kodi)</friendly_name> <mac>bb:bb:2a:39:56:53</mac> <enabled>1</enabled> </device> <device> <udn>uuid:5F9EC1B3-ED59-79BB-4530-0011F68C99A2</udn> <name>naim lounge</name> <friendly_name>naim lounge</friendly_name> <mac>bb:bb:01:a9:ba:03</mac> <enabled>1</enabled> <sample_rate>192000</sample_rate> <send_coverart>0</send_coverart> <volume_on_play>-1</volume_on_play> </device> </squeeze2upnp>
Start Script for Linux
[Unit] Description=LMS upnp Bridge After=network-online.target Wants=network-online.target [Service] ExecStart=/opt/squeezeupnpbridge/Bin/squeeze2upnp-x86-64 -Z -x /opt/squeezeupnpbridge/Bin/config.xml Restart=on-failure RestartSec=30 [Install] WantedBy=multi-user.target