Edit, 2013-01-05: See my complete instructions for setting up the Raspberry Pi here.
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.
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.
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 # this installs autoconf autotools-dev m4 (load of output snipped...) $ ./autogen.sh $ ./configure $ make make all-recursive make: Entering directory `/home/pi/gmrender-resurrect' Making all in src make: 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: *** [main.o] Error 1 make: Leaving directory `/home/pi/gmrender-resurrect/src' make: *** [all-recursive] Error 1 make: Leaving directory `/home/pi/gmrender-resurrect' make: *** [all] Error 2 # so 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) # 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: *** [gmediarender] Error 1 # when it links the code together it can't find the basic maths # functions, so 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 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 confifg.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…