A music thing for my parents

A while back my parents said: we’ve got a telly in the dining room now. Could we play music through it so we can put songs on while we’re doing things around the house?

Sure, I said.

Dad Music TV

For parents everywhere

So, we have a set of constraints. We need to find or build a thing which can play music through a telly, and which they can put new music on without my help. I’m sure there are devices out there which can do this, but I thought it might be fun to build something. And I set the biggest constraint of all on the device, which is this: it is not connected to the network. Wifi is annoying to configure, and on the Raspberry Pi it basically requires a powered hub.1 No ethernet network connection while it’s running. Non-negotiable requirement.

Therefore, there are two complexities here: how do you get music onto this thing? And how do you control it?

My thought was: we’ll base this on a Raspberry Pi, because they’re nice and standard and you can buy nice looking cases for them. That way, it needs only two wires: power, and HDMI into the telly, and that’s it. How you put music on it is: you unplug it, put the SD card into a computer, copy music onto the SD card, then put the card back in the Pi and turn it on. Ta daaah; easy.2 This requires something on the Pi which knows how to play music, and knows how to look at a folder of mp3s and index them. Sounds like a job for mpd!

And indeed that works. We create a folder named MUSIC at the root of the Pi’s SD card3, and stick a file named .hidden in the root to ensure that only the MUSIC folder shows up. Now, when my dad puts the SD card into his machine, it’ll pop up a file browser window which only shows the MUSIC folder. Winner. Configure mpd on the Pi to treat /MUSIC as its music root directory, and that all works; whenever the Pi starts up, mpd reindexes all the music in the folder, and you can’t add music without taking out the SD card which means that you have to restart the Pi. Now we can put music on the device and there’s a daemon which knows how to play it. Step 1: done.

It should really show something on the screen while it’s playing, though, shouldn’t it? So, a trivial little Python script which (a) uses SDL to (b) display things on the framebuffer while (c) being an mpd client, so when mpd does anything, the screen display changes. This is pretty easy stuff, thanks to an Adafruit writeup about using the framebuffer on the Pi.

The main screen

Now, how do we control it? It has no network. There is a thing named HDMI-CEC which allows a TV to pass commands down an HDMI cable to a connected device. This would be the obvious way to do it, and the Pi supports it; just have the TV’s remote control buttons for left/right/up/down/whatever get sent to the Pi, which then reacts to them appropriately.

Sadly, their telly doesn’t do CEC. So that’s that idea kiboshed. Shame; this would have been a good way to do it.

So, next step. Bluetooth it is! For that, we need a bluetooth USB dongle for the Pi. I have two, but one of them I couldn’t get to work. The one that does work names itself in lsusb as 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode). So now what we need is some way to control mpd on the Pi over Bluetooth. Well… Bluetooth supports what it calls “RFCOMM” connections, which basically are a socket, like telnet, but which goes over Bluetooth. So what if we make a little “proxy” server which listens on a Bluetooth socket and connects to mpds socket API? So when someone connects over Bluetooth to it, they can act just like they’re connected to mpd normally because they send an mpd command to the Bluetooth socket, the little proxy sends it on to mpd, mpd responds, and the proxy sends the output back? That way, all you need is an mpd client where you can switch out its “use a socket to connect” code with “use a Bluetooth socket to connect” code and Robert’s your mother’s brother. And indeed, that works; another relatively trivial bit of Python code to just open the two sockets and shuffle data between them.

Now we need an mpd client which can connect over Bluetooth. Both my parents have Android phones, so that’s the obvious place to have the client. I don’t like Java, so taking an existing open source Android mpd client and altering it is sadly not on the cards. One way to do this would be something like Cordova/PhoneGap, but nobody seems to have written a Cordova mpd app which makes socket connections itself, sadly.4 So, time to write a relatively noddy mpd client for Android. The ideal here is Kivy; it’s Python, it does all the GUI stuff, and they have both good documentation and the “buildozer” utility for packaging a Kivy app for Android. This also has the advantage that, because it’s in Python and I understand it, I can write the client with a switchable socket back-end, so on Android it uses Bluetooth, and on my desktop it uses an ordinary socket to connect over the network, so I can test the client in a nice convenient environment. I can also have the client connect to mpd running on my actual computer, so I can use other mpd clients to confirm that it does what it’s trying to do, that the screen display thing changes when it’s supposed to, and so on: this makes testing really, really easy because I don’t have to push any of it to the Pi or the Android phone while I’m working on it or to test it out. Having a test environment like this makes life much nicer.

The Android client

And, indeed, all of this works! It’s not quite finished yet, but all of this stuff hangs together. I’m quietly pleased with the amount of different stuff that had to come together for this project; Raspbian on a Raspberry Pi, mpd and its pretty-good API, creating Bluetooth server sockets with PyBluez on the Pi, proxying between two sockets, rendering a screen with SDL to the framebuffer, supervisord to ensure that all the server-side stuff gets run and keeps running and reports errors, building apps with Kivy, Android packaging for Kivy, using PyJnius from Python to use the underlying Android Java API, Bluetooth clients… I knew about all of this stuff at a high level, but there’s something satisfying about pulling it all together into a working product.

Code is at github.com/stuartlangridge/dadmusictv for both the Pi server and the Android client if you’re very keen to look at it. I’ve written down instructions, but they’re really for me as reference if I’m honest; setting this up yourself will require some jiggery-pokery, I don’t doubt. Nonetheless, this was a fun project to do. Easter hacking time 2015: 10 marks out of 10.

  1. you will say, no it doesn’t. and I will not believe you. and I’ve tried. A wifi dongle plugged into a powered hub which is then plugged into the Pi works always. A dongle plugged directly into the Pi works sometimes. At best. No network.
  2. actually, that’s probably easier than faffing about copying it over the network, to be honest; no passwords, no hassle, no dodgy wifi
  3. it’s running Raspbian, obviously; there is now a build of proper Ubuntu (not snappy) for the Pi 2, but Raspbian is fine here and at this level Ubuntu and Debian are pretty much identical
  4. there are a million billion mpd clients where the “client” running on the web is actually talking to a server which then in turn connects to mpd, but we can’t do that here because there’s nowhere to run the server, and making a webview use a bluetooth socket rather than a tcp socket sounds really low-level and difficult

More in the discussion (powered by webmentions)

  • Rich Wareham responded at plus.google.com That's genuinely awesome. Not the end product per se but the collection of existing technologies and software. Also I'm particularly interested that K…
  • Stuart Langridge responded at plus.google.com +Rich Wareham yeah, that's what I liked about it -- not that the final product is superb or anything, 'cos it ain't, but the gluing together of many d…
  • Albert Westra responded at likes this. (plus.google.com)
  • Adrian Bradshaw responded at likes this. (plus.google.com)
  • Rich Wareham responded at likes this. (plus.google.com)
  • Matthew Gregg responded at plus.google.com As a project this is cool and awesome, but given the audience(parents), why not something off the shelf, simple and reliable like a Chromecast?
  • Stuart Langridge responded at plus.google.com Because the wifi in their house is unreliable, I don't want to have to put all their music on both of their phones, they don't want to pay a subscript…
  • Matthew Gregg responded at plus.google.com You'd only need reliable wifi in one place, the room with the TV. Also no need to put music on both phones nor a subscription, unless they have more t…
  • Stuart Langridge responded at plus.google.com They really don't get uploading music to the cloud. Sure, I could set that up for them, but then I'm still doing a bunch of setup work, and the wifi n…
  • Adrian Bradshaw responded at plus.google.com Sir, did you really want the github link to be - ??
  • Stuart Langridge responded at plus.google.com +Adrian Bradshaw gnaah. I did the link and the link text the wrong way around! Will fix when at a machine, cheers. Hopefully you were able to find the…
  • Adrian Bradshaw responded at plus.google.com +Stuart Langridge I hope you are not too surprised when I say I was able to work it out
  • Adrian Bradshaw responded at plus.google.com +Stuart Langridge I thought you had maybe invented a new protocol github://
  • Stuart Langridge responded at plus.google.com Fixed it from phone! Woo ssh.
  • Will Cooke responded at likes this. (plus.google.com)
  • Seth Arnold responded at likes this. (plus.google.com)
  • Vincent Beers responded at likes this. (plus.google.com)
  • David Callé responded at likes this. (plus.google.com)
  • Eric Casteleijn responded at likes this. (plus.google.com)
  • Fiona C responded at likes this. (plus.google.com)
  • David Meyer responded at likes this. (plus.google.com)
  • Matt Seng responded at likes this. (plus.google.com)
  • dieGO González responded at plus.google.com Wow, amazing gluing work +Stuart Langridge​​!The *NIX way, each one doing his own job to get the things done!I'm trying to code/get something that cou…
  • James Henstridge responded at plus.google.com So the TV didn't have DLNA support?
  • Stuart Langridge responded at plus.google.com +dieGO González I certainly wouldn't do it with C, but that's because I'm not a C coder. I'd go with whichever language you're most comfortable with;…
  • dieGO González responded at likes this. (plus.google.com)
  • Jan Henkins responded at likes this. (plus.google.com)
  • Matt McGraw responded at likes this. (plus.google.com)
  • James Henstridge responded at plus.google.com When I bought my TV set (I think it is a 2008 model) DLNA was somewhat common in the medium-high end, so I guess I assumed it would have filtered down…
  • Pierre Equoy responded at plus.google.com I loved that! Having a project, finding existing open source bricks and assembling something, it's just all what I love about open source!I learnt abo…
  • Pierre Equoy responded at likes this. (plus.google.com)
  • Stuart Langridge responded at plus.google.com +James Henstridge interesting idea! It's not applicable in this situation -- the tv definitely does not have an Ethernet port -- but I would not have…
  • Stuart Langridge responded at plus.google.com +Pierre Equoy kivy' certainly worth a try, I'd say!
  • James Henstridge responded at plus.google.com +Stuart Langridge: fair enough. I've seen some fairly terrible TV UIs, so I can believe that. The one on my set didn't seem too bad: it was a variat…
  • Pierre Equoy responded at plus.google.com After +James Henstridge comment, I realized there might have another option for your parents, since you already have a Raspberry Pi: OpenElec [1]. It'…
  • Stuart Langridge responded at plus.google.com Huh. Bluetooth remote for XBMC/OpenElec on the Pi. Did not think of that.That might actually be a better option...
  • Stuart Langridge responded at plus.google.com +Pierre Equoy have remembered why I rejected kodi. There are indeed bluetooth remote controls, but they're all just up/down/left/right controllers and…
  • James Henstridge responded at plus.google.com I wonder if there are any apps to make your phone look like a Bluetooth keyboard?
  • James Henstridge responded at plus.google.com That one seems to require you install a special service on the computer you want to control rather than it just emulating a Bluetooth HID keyboard.Thi…
  • Stuart Langridge responded at plus.google.com Yeah, I saw the service, but I'm roughly ok with doing that if need be (probably more ok than rooting my parents' phones :))