My ultimate guide to the Raspberry pi audio server I wanted — Audio CD
Part 6 — Audio CD
To be honest I don’t use CD anymore, I gave up my collection years ago. I don’t even have a player anymore except for my desktop optical drive. However I still get some from time to time when buying records, so I wanted to add a CD player to my setup. I bought an external 2.0 USB DVD writer, plugged it to the Pi and started digging.
I ended up with a solution very similar to what I did with USB sticks:
- a udev rule to detect audio cd insertion, whichs starts
- a systemd service triggering
- a bash script to autoplay CD through MPD
/etc/udev/rules.d/99-local.conf
KERNEL==”sr0", SUBSYSTEM==”block”, ACTION==”change”, ENV{ID_CDROM_MEDIA_TRACK_COUNT_AUDIO}==”[0–9]*”, MODE=”0664", RUN+=”/bin/systemctl start cd-mount.service”
KERNEL==”sr0", SUBSYSTEM==”block”, ACTION==”change”, ENV{DISK_EJECT_REQUEST}==”1", RUN+=”/bin/systemctl stop cd-mount.service”
/dev/sr0 and block specify the optical drive, but not the CD in it, so we watch for change and expect env var ID_CDROM_MEDIA_TRACK_COUNT_AUDIO to exist and be a number, then we start our systemd service
/etc/systemd/system/cd-mount.service
[Unit]
Description=Play Audio CD[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/bin/mpc-cd.sh add
ExecStop=/usr/local/bin/mpc-cd.sh remove
I tried at first to trigger the script directly from udev, but I had timeout issues that systemd solved.
I decided to use the MPD USB service instead of the satellite one, only because I thought it made more sense to use the one already dedicated to removable devices. Both would work, you only need to add these lines to your mpd.conf file :
input {
plugin “cdio_paranoia”
}
And restart MPD.
$ sudo systemctl restart mpdusb
Audio cd have no file system, which makes them impossible to mount as we did with USB sticks, but they are referred as cdda:// in MPD. In the script, we’ll read the number of tracks on the CD and then add them one by one to MPD queue. We could add only cdda:// but then we’d have only one track for the whole CD.
eject needs to be installed to manage the optical drive speed. Script first set it at max (mine is 24x) for fast initialization, and then lower it to 12x for playing. This way you can listen to your CD without being disturbed by the drive’s noise, which can be really excessive.
/usr/local/bin/mpc-cd.sh
#!/bin/bashACTION=”$1"
if [[ -z ${ACTION} ]]; then
exit 1
fiDEV=”/dev/sr0”
MPC=”/usr/bin/mpc -p 6610"do_mount() {
NUM_TRACK=$(/sbin/udevadm info --query=property ${DEV} | /bin/grep ID_CDROM_MEDIA_TRACK_COUNT_AUDIO | /usr/bin/awk -F= ‘{ print $2 }’)
/bin/echo “cd with ${NUM_TRACK} tracks detected”
/bin/echo “setting speed to max”
MAX_SPEED=$(/usr/bin/eject -X)
/usr/bin/eject -x ${MAX_SPEED} /bin/echo “clearing mpd queue”
${MPC} clear
for i in $(/usr/bin/seq 1 ${NUM_TRACK}); do
${MPC} add cdda:///${i}
done /bin/echo “setting speed to x12 for playing”
/usr/bin/eject -x 12
${MPC} play
}do_unmount() {
${MPC} -f "%position% %file%" playlist | /bin/grep cdda:// | /usr/bin/awk '{ print $1 }' | ${MPC} del
}case “${ACTION}” in
add)
do_mount
;;
remove)
do_unmount
;;
esac
This way, when a CD (or a USB key) is inserted it’s played automatically, and takes over whatever was playing before on this MPD instance. Pulseaudio, bluetooth and MPD/DLNA will still play and need to be stopped/paused manually. Playback can also be managed through M.A.L.P.
However, unlike USB sticks, CD aren’t temporarily added to MPD database. So if it’s removed from queue, it can’t be accessed unless inserting the CD again. That’s really not a big deal in my opinion. What annoys me more is that I don’t have tracks tags in M.A.L.P. I know it’s possible to get them either from a CDDB server or by reading the CD metadata (which is actually really slow), but I don’t know how to feed them to MPD. It might be doable with gvfs from what I read, but I’ll settle for that for now.
It’s obviously possible to rip the audio CD to files tagged automatically and add this to MPD queue, but that’s not what I want since that would be too slow (10–20 minutes) before playing.