If I believed in New Year resolutions, I suspect I’d have to add one right now: “Don’t overthink things in 2019”. As this short tale will demonstrate, I just narrowly avoided going down a very deep, branching rabbit hole in search of something that was right in front of my nose.
To give you the backstory: I enjoy classic radio programming – mostly plays and serials from the golden age of radio. In fact, it’s pretty much all I listen to. Because of this interest, many years ago I bought a not-very-valuable (and also not working) tombstone radio of roughly 1940s vintage, removed its innards and put a small MP3 player and LM386-based audio amplifier inside it. I jury-rigged the MP3 player so that it would start playing immediately on powerup – just a simple cap to ground on the play button relying on the ASIC’s on-chip pullup resistor to charge the cap back above VIL – and finished off by transplanting in a better loudspeaker than the original.
In this day and age, I can definitely do much better, and since I still have my ancient Raspberry Pi left over from the NAS project, I planned to build something around this. Unfortunately, it looks like I left the original real-vintage radio in New York and it was thrown out in some kind of cleanup festival, so I have to start from scratch.
I began, as I usually do with such projects, at the wrong end – buying the housing. I’ve become a bit of an addict to Goodwill’s online auction site, since the prices there for what is (let’s be honest here) mostly yard sale junk are much more reasonable than eBay and if you happen to locate an item that’s geographically close, shipping can be extremely reasonable. For the thrifty sum of $6.99 (okay, fine, I admit it… $23.10 shipped from Nebraska) I acquired a Thomas Collector’s Edition reproduction radio [with hidden cassette player on the side] from the late 1980s, probably 1988. This picture is taken from the auction itself, as I haven’t received the radio yet. Radiomuseum has a listing for this item which shows you more details. I think I’m going to use the cassette door on this unit as a convenient aperture to mount an external USB port, maybe also an external HDMI port, and if I get fancy, wire the power switch to a GPIO so it can trigger a controlled shutdown.
I downloaded the latest Raspbian Stretch with desktop (the thinner distro, without “recommended software” as I only have an 8GB SD card for this box) and wrote it out with:
dd bs=4M if=2018-11-13-raspbian-stretch.img of=/dev/mmcblk0 status=progress conv=fsync
I also bought an 802.11bgn USB adapter for $10.99 and verified that it works well with Raspbian.
All the wiring and physical components seem clear enough. But what about the software that will actually play the media – and how will I control it? This is where the rabbit hole begins, and here’s how my thought process went.
I started by thinking of methods to adapt the radio’s existing controls to drive a media player – or more likely a specialized frontend that I would have to write myself. I mulled a few possibilities here; for instance, wiring the pots and switches to the inputs of a USB gamepad. However I eventually reached the conclusion that none of this would feasibly provide useful functionality unless I also added a display of some kind to the device, so my better bet was to expose control over WiFi and use my phone as the controller.
On WiFi itself, there are two approaches that I could take, and I considered them both:
- Have the device operate in AP mode and broadcast its own SSID. Advantage: locating the device’s address is easy and I don’t have to remember anything. Also, it will work without tinkering even if I take it someplace else to show off. Disadvantage: Besides the annoyance of having to swap SSIDs on my phone, the device won’t be able to stream off my media server or the Internet.
- Have the device connected to my home WLAN. Advantage: it will have full local network and Internet access. Disadvantage: it won’t work without infrastructure, and anytime I move outside my home network, I won’t be able to access it unless I plug in a display and keyboard and configure it for whatever infrastructure is nearby. Also, I need to either remember its IP address or tinker with the DNS settings in my router to give it a name (or at least, I thought I did).
All things considered, I decided on option 2, but this is where the rabbit hole really started to get crazy. I started sketching out on a napkin how I could write a little C program that either presented its own HTTP interface or ran behind Apache as a CGI binary, which would spawn an external command-line MP3 player like mplayer or vlc (or even control a player like Rhythmbox forcefully). I won’t tell you – but likely you can surmise – how far I got down thinking how such a program might work, and how it might scan and present a list of MP3s, and build playlists, and so on.
After a couple of days of napkin-doodling like this, it occurred to me that there must surely exist a way of remote controlling a media player running on a Linux appliance. (Yes, I realize that probably sounds naive to the average reader, but you need to understand that my attention was very much focused on my original plan; I had picked up my hammer and was looking only for nails). Some Googling turned up mostly people trying to control media players with a gamepad, joystick or IR remote, but I did eventually find out that there are some Android remote control apps for VLC (among others). These apps seem to be adware-infested at best, and for some reason, most of them also require a separate agent running on the target computer. As I don’t care to allow unwanted telemetry of any sort on my networks, this wasn’t really a great solution for me. Fortunately, in the course of reading the setup instructions for this, I learned about the details of VLC’s inbuilt web interface – it’s not just an API, it’s a fully presented human-usable interface. Here’s how you enable it:
- Launch VLC and select Tools – Preferences.
- Under “Show settings” (bottom left corner) select “All”.
- Under “Interface” (you may need to expand it), click “Main interfaces” and check the “Web” checkbox on the right-hand side of the dialog.
- Under “Main interfaces” (again you may need to expand it) select Lua, and enter a password in the “Lua HTTP” – “Password” field. Don’t edit anything else.
- Click “Save” and quit/restart VLC.
- You will now be able to access a very functional remote Web interface at http://ip_address:8080 ! (You’ll be prompted for a username and password – leave the username blank, and enter the password you configured in the step above).
Better yet, it turns out that my router’s DHCP server automatically adds a DNS entry for each IP address lease. So I changed the Raspberry Pi’s hostname to “tombstone”, and now from all my computers and phones, I can see the full remote control interface simply by navigating to “tombstone:8080”:
The web interface seems to only be able to list and play items that are already in VLC’s media library; it doesn’t let you browse the remote device’s filesystem or enter arbitrary stream URLs. Thus, before unplugging the mouse and keyboard, it’s necessary to build the media library (this can apparently only be done locally). Ensure that the playlist is visible (View – Playlist), and in the playlist click “Media Library”. Right-click anywhere in the blank area of the dialog and select “Add Folder…” to add a folder to be scanned for media. At the moment I have a 32GB flash drive attached to the RPi with a few test MP3s in it – once I get all the rest of the hardware, I’ll add more storage and also mount the SMB shares on my media server.
All that remains really is to have VLC autostart on system boot. This wasn’t as easy as I had anticipated – it’s been a while since I used Raspbian, but I was sure that earlier versions had a simple GUI area to add startup programs. Most of the references on the internet for “autostart program on Raspbian” focus on not-so-useful-to-me use cases, like tinkering with systemd (HORROR! *brandishes crucifix*), editing bashrc, or similar. I did eventually find a reference advising to create this file:
~/.config/lxsession/LXDE-pi/autostart
containing the single line
/usr/bin/vlc
(Note that the lxesssion and LXDE-pi directories don’t exist and will have to be created). Obviously this only works if you have the Pi configured to autologin, but since that’s the default – that’s all fine. For reasons I honestly don’t understand, this results in the Pi starting up without a desktop – only VLC loads into the X server. Even once you quit VLC, you don’t get the normal Raspbian desktop. Since this is to be a single-use device, that’s fine.
And there we have it. The last thing I’ll add is that the Dollar Tree currently sells a spherical external amplified speaker with 3.5mm aux in plug, with an internal circuit that’s roughly an LM386 mono amp with a small 8 ohm speaker, which is the ideal match to this application. I’m headed out to buy one tomorrow – and then I simply have to wait for the radio body itself to arrive. Duct tape and hot melt glue (in a software sense) for the win! And I didn’t have to write a single line of code for this project, which is also sort of a win.
PS: The reason the box is labeled “PLUTONIUM” is that it was originally going to be my NAS box and all the static-IP nodes on my home network are named after elements; I’m writing this post on FLUORINE and my media server is HELIUM. I will need to scrape that label off, I guess!