THEORETICAL SET-UP:
The Raspberry Pi plays music from a USB memory, reading input from the Arduino Nano.
WHAT ACTUALLY HAPPENS:
The Raspberry Pi does absolutely nothing useful. Software for this does not exist.
So, first, the software running on the Nano is extended to supply key press information and allow showing stuff on the LCD via USB. The protocol is line-based and :-separated; just stuff like ">SHOW_TEXT:Foobar\r\n", "<KEYPRESS:14\r\n".
Then we are left with the mountain of stuff the Pi should do, but doesn't.
What is needed is a media player that supports our custom Arduino-based UI over a USB serial port. It also has to be able to automatically mount and scan USB devices.
Well, I made one. It's called the OVER POWERED TRACK SWITCH.
The main issue was finding a combination of a programming language and a library that would support all media formats with minimal effort, and not crash all the time.
Gstreamer? Maybe. Gstreamer and Python? It's stable, right? Right?
...I tried, it's not. You only have to add time.sleep(1) to the simplest python-gstreamer example and it all comes crashing down with a segmentation fault, no less! And I know, it doesn't even make any sense. I guess you're not supposed to do that, but at the instant I get a segmentation fault from Python, I throw gasoline on my laptop, light it on fire and buy a new one.
So with the (imaginary) new laptop, I removed Python and Gstreamer from my entire world view and stumbled upon libmpv. I tried some Python bindings because I'm stupid, and none of them worked. I wasn't surprised by any amount though, and just started a C++11 project. From there on, everything was relatively straight forward compared to whatever the hell I tried until then.
OVER POWERED TRACK SWITCH |
It organizes all media into albums, which are simply directories on the original media; subdirectories are flattened into the album list after their parent directories. (Or maybe before? I don't remember. Anyway...)
The main user interaction is switching to the next or previous track, or the next or previous album. There are a few repeat and a shuffle modes, a pause function, and a jump-to-random-album function. The current album, track, position, play mode and shuffle order is saved on disk and operation continues automatically when restarted.
OPTS also has a powerful search function that can't be used from the head unit front panel due to the obvious lack of a keyboard, but it is very handy when used in a terminal.
On our Raspberry Pi, we set up OPTS to be run as root as soon as possible at boot as a systemd service. It then mounts, scans and plays any USB media when inserted and... well, then we have a functioning music player.
The software running on the Nano is included in a subdirectory under OPTS, and OPTS is able to check the version and automatically upload a new firmware binary to the Nano.
In addition to that, I created a script that checks the USB media for a specific subdirectory and if it exists, it stops OPTS, copies the new version onto the root file system, builds it and starts it again. This allows me to update OPTS without connecting the Pi into any networks or anything.
I additionally set up OPTS to take input from tty11 and an additional systemd unit to chvt 11 after OPTS has started, so that I can just plug in a USB keyboard and blindly input OPTS commands to eg. search for a track. It's handy.
OPTS is released under the MIT license on Github: https://github.com/celeron55/opts
"This is not the head unit you are looking for" |