A UPnP renderer for the Raspberry Pi

Posted in Posted on 2013-01-01 11:24

A UPnP renderer for the Raspberry Pi

I want to use a Raspberry Pi to play music through the micro Hi-Fi system in my kitchen/dining room. Up to now I have had a San Francisco Android phone velcroed to the kitchen wall running the Subsonic client and accessing the FLAC files on my media server via the excellent Subsonic server software (which transcodes them on the fly to MP3). This has been a good solution for a couple of years now but one problem is that the headphone output of the San Francisco is not very powerful so we have to turn the (small) amp up to max to get a decent volume and sometimes you want it higher.

Attention!

I just tested a Raspberry Pi’s audio output and it is more powerful than the phone’s so it would make a good replacement. A couple of years ago when I set up the phone as a media player, DLNA for sharing/streaming media was not very widespread, but now it’s become quite popular so I’d like to try using that protocol with the Pi. DLNA defines various types of devices, such as “server”, “renderer” and “controller” and they then communicate via Universal Plug and Play (UPnP). I want my media server to be a DLNA server and the Pi to be a “renderer” and all our mobile phones to be the “controllers”.

On the media server I’ve installed minidlna via apt-get and pointed it at my music folder. The server runs as a “minidlna” user and for some reason I had to chown minidlna.minidlna the /var/cache/minidlna folder to get it to work but it seems fine now.

To control the system I’ve installed bubbleupnp on my phone and this means I can stream music from the media server to my phone. What I want to do though is use the phone as a UPnP controller and have it instruct the Pi to play (or “render”) the music through the Hi-Fi’s speakers.

Enter gmrender…

There seems to be a shortage of headless UPnP renderers for linux: I just want a server process that sits there and accepts instructions to play music and plays it - nothing more, nothing graphical. XBMC can be a UPnP renderer I believe but that’s way too heavyweight for what I want to do (even though the Raspbmc project makes it easyish). Google found me gmrender but it’s long abandoned. However, a post on Google+ from Henner Zeller sent me on to the gmrender-resurrect project on GitHub where Henner has taken the old code and added some more features.

However, getting it to install on the Raspberry Pi (with standard Debian wheezy OS) was not completely straightforward…

$ git clone https://github.com/hzeller/gmrender-resurrect.git
$ cd gmrender-resurrect

Looking at what you get, there is an autogen script so I need some more tools…

$ sudo apt-get install automake
(load of output snipped...)

This installs autoconf, autotools-dev, m4. We can now do the normal automake process:

$ ./autogen.sh
$ ./configure
$ make
make all-recursive
make[1]: Entering directory `/home/pi/gmrender-resurrect'
Making all in src
make[2]: Entering directory `/home/pi/gmrender-resurrect/src'
gcc -DHAVE_CONFIG_H -I. -I.. -DPKG_DATADIR="/usr/local/share/gmediarender" -Wall -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wwrite-strings -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
main.c:34:18: fatal error: glib.h: No such file or directory
compilation terminated.
make[2]: *** [main.o] Error 1
make[2]: Leaving directory `/home/pi/gmrender-resurrect/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/pi/gmrender-resurrect'
make: *** [all] Error 2

So looking at the first error, I am missing glib.h, where do I get that?

$ sudo apt-get install apt-file
$ sudo apt-file update
$ apt-file search /glib.h
libghc-glib-doc: /usr/lib/ghc-doc/haddock/glib-0.12.2/glib.haddock
libgirepository1.0-doc: /usr/share/gtk-doc/html/gi/glib.html
libglib2.0-dev: /usr/include/glib-2.0/glib.h
libglib2.0-doc: /usr/share/doc/libglib2.0-doc/glib/glib.html

That gives me the answer.

$ sudo apt-get install libglib2.0-dev
$ rm config.status config.log
$ ./configure
$ make
(output snipped, but fails with:)

gcc -Wall -Wpointer-arith -Wcast-align -Wmissing-prototypes -Wmissing-declarations -Wwrite-strings -o gmediarender main.o upnp.o upnp_control.o upnp_connmgr.o upnp_transport.o upnp_device.o upnp_renderer.o webserver.o output.o output_dummy.o xmldoc.o xmlescape.o -pthread -lgthread-2.0 -lrt -lglib-2.0
upnp_control.o: In function `set_volume_db':
upnp_control.c:(.text+0xc4c): undefined reference to `exp'
upnp_control.o: In function `set_volume':
upnp_control.c:(.text+0xd6c): undefined reference to `exp'
upnp_control.o: In function `upnp_control_init':
upnp_control.c:(.text+0x100c): undefined reference to `log'
collect2: ld returned 1 exit status
make[2]: *** [gmediarender] Error 1

This is saying that when it links the code together it can’t find the basic maths functions (such as “exp” and “log”), so we need to tell it to use the maths lib (why?!)…

$ ./configure LIBS=-lm
$ make
$ sudo make install
$ gmediarenderer --list-outputs
Supported output modules:
dummy Dummy output module (default)

So I have installed it but it’s no use because there is no gstreamer output to play the music.

$ sudo apt-get install gstreamer0.10-alsa
$ sudo apt-get install gstreamer0.10-tools
$ sudo apt-get install libgstreamer0.10-dev

More examination of the config.log file reveals that it also didn’t find the upnp and libxml2 libraries. Why does it just blindly continue?!

$ sudo apt-get install libupnp-dev
$ sudo apt-get install libxml2-dev

$ rm config.status config.log
$ ./configure LIBS=-lm
checking for GLIB... yes
checking for GST... yes
checking for LIBUPNP... yes
checking for LIBXML... yes
$ make clean
$ make
$ sudo make install
$ gmediarender --list-outputs
Supported output modules:
gst GStreamer multimedia framework (default)
dummy Dummy output module
$ gmediarender -f Raspberry
Using output module: gst (GStreamer multimedia framework)
Registering support for 'audio/x-raw-int'
Registering support for 'audio/x-iec958'
gmediarender: output_gstreamer.c:482: output_gstreamer_init:
Assertion `player_ != ((void *)0)' failed.
Aborted

What’s going on? More bits of gstreamer needed?

$ sudo apt-get install gstreamer0.10-ffmpeg
$ gmediarender -f Raspberry
Using output module: gst (GStreamer multimedia framework)
...followed by 100 or so media types it can now render...
gmediarender: output_gstreamer.c:482: output_gstreamer_init:
Assertion `player_ != ((void *)0)' failed.
Aborted

More needed?

$ sudo apt-get install gstreamer0.10-plugins-base
$ sudo apt-get install gstreamer0.10-plugins-good
$ gmediarender -f Raspberry

And it runs!

At this point, the Pi appears in Bubbleupnp’s “devices” list as a “renderer”. If I select it and then choose a song from the media server and press play all sorts of log messages appear on the Pi’s console. Unfortunately I tried playing a FLAC file and the sound quality is terrible! Playing an MP3 file doesn’t work - it says I have a missing plugin so I had a look (type sudo apt-get install gstreamer and press tab) and saw another one that looked to do with MP3s:

$ sudo apt-get install gstreamer0.10-fluendo-mp3

Now I can play an MP3 file and it also sounds terrible…

I copied an MP3 across onto the Pi from the media server (using scp) and tried playing it with mpg123 and it sounds fine. So what is the problem with the gstreamer rendering?

$ gst-launch-0.10 playbin uri=file:///tmp/song.mp3

This command produces the same rubbish output as via gmrender (as expected), so the problem is in gstreamer. I’ll post this and do some more investigation…

Comments

Comments powered by Disqus