As a lot of people with technical interests, I find joy in automating things around the house. In this particular example, it's about my home media setup, which plays audio and video from my local library. The goal is to be able to control the player remotely, through my android phone.
I rarely stream music from cloud services, instead I enjoy my good old
mp3
and flac
files. That makes it a lot more challenging to listen to
my collection from locations other than my desktop PC. Hence I came up with
this solution, which is for the living room but is also relatively
portable which allows me to deploy it elsewhere too.
Occasionally, I also want to view some media on the big TV in the living room, but the content is only on my PC in the other room. I've made sure I can access that content too, and stream it through VLC.
As mentioned, my music collection is simply a whole bunch of files. I manage these files with Winamp, where I create playlists for each album, or sometimes a collection of albums or random tracks.
The goals are fairly straightforward:
Let's start at the music files. These should be available locally on the Raspberry Pi, so I can listen to it without having to depend on a network or remote storage location. This is trivial thanks to Syncthing, which synchronizes files with another location, in this case my desktop PC.
Next, the playback. I've opted to use Music Player Daemon (MPD),
as it best fits my requirements. I've configured it to output to
both the RCA and 3.5mm outputs of the HifiBerry board (through
ALSA).
MPD has an open protocol which allows various clients to be used.
I personally use MPDroid, which is a bit outdated and has some
quirks, but it works well enough. I can fully control playback and
select anything from my library.
Finally, playlists. This was the biggest hurdle, as the playlists
used in Winamp are not compatible with MPD. Without an easy way to
convert them, I did what every software engineer would do in this
situation: Write my own conversion program!
The conversion is relatively simple, from m3u8
to
m3u
. Here's how it works in a couple of steps:
m3u
format.
With that, I've accomplished my goals! I've hooked it up to my media receiver and am able to enjoy all the music from the comfort of my couch!
Accessing storage on the network is fairly trivial. Even when my target machine is running windows, using CIFS to mount the drive is pretty easy. I've also automated it through fstab.
However, being able to browse directories and playing back media using my phone as a remote is a bit more tricky. I've opted to use VLC as it's capable of processing a lot of different media formats. It's also capable of remote control through various means, including HTTP.
Unfortunately the HTTP interface is, in my humble opinion,
quite awful. Especially on mobile it's nigh impossible to
use.
Hence, I created my own interface! With a bit of network routing
trickery using Nginx, it's possible to forward API calls from my
own interface to the HTTP server of VLC, without CORS errors.
There was barely any documentation on the VLC http API as it is
technically only available for internal (within VLC) use. With the
little documentation that was available and some reverse
engineering, I managed to get the most important functions working!
While this system works alright, there are still some flaws. Here is a list of things I would like to improve in the future:
dd
, but this is
rather slow, both in terms of storing and recovering. And it
is not automated, which could result in losing weeks or months
of data depending on the frequency of the manual backup.
rc
interface instead,
using Rust to create a lightweight http server which forwards
commands to the rc
interface. However, that was
practically my first attempt at writing something in Rust,
which turned out to be a bit too complex for the effort I
wanted to put into it at that time.