DiskplayerHD: Using 3.5″ floppy disks to play Local FLAC files

A while ago I read an article by Dino Fizzotti called Diskplayer: Using 3.5″ floppy disks to play albums on Spotify and loved the idea. It involves using a floppy disk drive and a Raspberry Pi, along with a HiFiBerry DAC+ to trigger Spotifyd to play albums from Spotify.

I loved the idea and experimented with it on an old server, and managed to get it working (albeit with no DAC and no stereo to connect it to. I considered it to be a proof of concept that I’d get around to “some day.”

Flash forward about a year and I spotted a Luxman R-1050 receiver on eBay. It’s the amplifier I grew up listening to when I was a kid and in a moment of impulse, I bought it. Once it was properly set up and I was playing some records, I remembered Diskplayer and decided it was time to give it another go. Unfortunately since then I’d abandoned Spotify in favour of using my own library of FLAC files which I’ve been collecting for some years now. I needed to make some changes.

Hardware

My version of Diskplayer consists of the following hardware:

I already had a Pi4 from some earlier experiments, the floppy and disks were grabbed from Amazon, and the DAC2 Pro was purchased from HiFiBerry direct. As with Dino’s original, I was aiming for high-fidelity audio as I’m using 24-bit FLAC rips of CDs, and the onboard audio just wasn’t going to be good enough. The DAC2 Pro is awesome. It feels kinda silly plugging it in to a receiver from 1978, but boy howdy does it ever sound good.

Software

As I’m using local files, there’s quite a bit less going on that in the original. I use:

  • MPlayer
  • Dino’s UDEV rule and a modified version of their script
  • A new script for recording albums to disk
  • Byobu to allow MPlayer to continue running once you disconnect

Detecting a Floppy Disk

udev rule

No need to reinvent the wheel here. As per Dino:

Grab the ID of your USB floppy disk:

$ lsusb
Bus 001 Device 003: ID 0644:0000 TEAC Corp. Floppy

Create a new file at /etc/udev/rules.d/100-floppy-change.rules and paste in the following, substituting the vendor ID and product ID from the lsusb output from before:

ACTION=="change", ATTRS{idVendor}=="03ee", ATTRS{idProduct}=="6901", ENV{DISK_MEDIA_CHANGE}=="1", RUN+="/home/pi/media_change.sh $env{DEVNAME}"

media_change.sh

Again, this one is thanks to Dino but modified by yours truly. If a disk is inserted, it’ll read the diskplayer.contents file and shoot the list of files into MPlayer. If a disk is removed it’ll tell MPlayer to load an mp3 file which is just silence and pause playback.

#!/usr/bin/env bash
exec >> /home/pi/mount.log 2>&1
#export LC_ALL=en_GB.utf-8
#export LANG=en_GB.utf-8

echo "$(date) Start."
echo "$(date) Media change detected on device $1"

device=${1##*/}

lsblk | grep $device

if [ $? -eq 0 ]; then
    echo "$(date) Device exists on machine."
    echo "$(date) Mounting device $1 to /media/floppy."
    /usr/bin/systemd-mount $1 /media/floppy
    echo loadlist /media/floppy/diskplayer.contents >> /home/pi/fifofile
    /usr/bin/systemd-mount --umount /media/floppy
else
    echo "$(date) Device does not exist on machine."
    echo loadfile /home/pi/music/silence.mp3 >> /home/pi/fifofile
    echo pause >> /home/pi/fifofile
fi
echo "$(date) End."

write_media.sh

It’s nowhere near as elegant as Dino’s solution, but it gets the job done. This simple script will look into the specified folder, sort files alphabetically (so it can get the track listing correct for the album) then write them as lines to the disk you’ve inserted. If it’s blank it’ll just go ahead and do it, if there’s already something there it’ll overwrite it with the new album contents. Once it’s done writing it’ll start playing the album.

#!/usr/bin/env bash
echo pause >> /home/pi/fifofile
mount /dev/sda /media/floppy
find "$1" -type f | sort -d > /media/floppy/diskplayer.contents
echo "Writing the following files to disk:"
cat /media/floppy/diskplayer.contents
echo loadlist /media/floppy/diskplayer.contents >> /home/pi/fifofile

Writing an album looks like this:

$ sudo ./write_media.sh /home/pi/music/Nirvana/MTV\ Unplugged\ in\ New\ York\ \(1994\)/
Writing the following files to disk:
/home/pi/music/Nirvana/MTV Unplugged in New York (1994)/Nirvana - MTV Unplugged in New York - 01 - About a Girl.flac
~snip for brevity~
/home/pi/music/Nirvana/MTV Unplugged in New York (1994)/Nirvana - MTV Unplugged in New York - 14 - Where Did You Sleep Last Night.flac

MPlayer

The big change here is using MPlayer to playback local files (or in this case, files which are on a CIFS share on my server. You’ll need to install MPlayer first – it’s widely used, so should be available in your distro of choice and should be something along the lines of:

sudo apt update && sudo apt install mplayer -y

The reason I went with MPlayer, even though it’s primarily used as a video player, is that it’s a real swiss army knife of playback, and it has the one feature that I really need for this to all work correctly – the ability to work in Slave Mode. It’s designed so you can leave the app running and then fire commands into it from the console, or (as used here) you can use a fifofile to act as the command buffer.

To make the fifofile you’ll need to run the following command:

$ mkfifo /home/pi/fifofile

Then launch MPlayer with the following command:

$ mplayer -slave -input file=/home/pi/fifofile -idle -quiet -novideo /home/pi/music/silence.mp3

When you pop in a disk like the one we recorded earlier, you can see MPlayer doing it’s thing like this:

Playing /home/pi/music/Nirvana/MTV Unplugged in New York (1994)/Nirvana - MTV Unplugged in New York - 01 - About a Girl.flac.
libavformat file format detected.
[lavf] stream 0: audio (flac), -aid 0
Clip info:
 TITLE: About A Girl
 ARTIST: Nirvana
 ALBUM: MTV Unplugged In New York
 DATE: 1994
 GENRE: Rock
 track: 01
 ALBUM ARTIST: Nirvana
Load subtitles in /home/pi/music/Nirvana/MTV Unplugged in New York (1994)/
==========================================================================
Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders
AUDIO: 96000 Hz, 2 ch, s32le, 0.0 kbit/0.00% (ratio: 0->768000)
Selected audio codec: [ffflac] afm: ffmpeg (FFmpeg FLAC audio)
==========================================================================
AO: [pulse] Init failed: Connection refused
Failed to initialize audio driver 'pulse'
AO: [alsa] 96000Hz 2ch s32le (4 bytes per sample)
Video: no video
Starting playback...

Byobu

If you haven’t tried it yet, I highly recommend Byobu. It’s a wrapper for screen or tmux which are text-based window managers. I use screen because that’s what I’m familiar with, and it allows me to have multiple sessions open which will persist once I’ve disconnected and will be right there waiting for me when I come back. It should already be installed, so you just need to enable it with

$ byobu-enable

so it launches at boot. Then fire it up for the first time with

$ byobu

you can then fire up mplayer, disconnect your ssh session and there you have it. A completely headless, floppy-powered FLAC playing machine!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s