Auto-rip Music CDs

Published: Monday, Feb 7, 2022
Last modified: Wednesday, Jun 8, 2022 (0fbd635)

Awhile back I found a stack of audio CDs I wished to digitize. It’s a bit of work to do the following steps quickly and while doing other more cerebral work:

  1. Open the disc tray
  2. Insert the disc
  3. Wait a few seconds for the disc to be detected by the OS
  4. Kick off abcde to rip the CD.
  5. Repeat ad infinitum.

The solution is to streamline the workflow:

  1. Open the disc tray (first time only)
  2. Insert the disc
  3. Wait until abcde is finished and ejects the CD, repeat from step #2.

Much simpler. This requires only one human action, whereas the above requires a bit of fumbling with telling the workstation to do the work. Read on to learn how to set this up for your own ‘ripping fun’.

§Tell udev to do something when the CD drive is ejected or inserted

Add this to your udev rules. On my box it is located at /etc/udev/rules.d/90-ripper.rules.

SUBSYSTEM=="block", KERNEL=="sr*", ACTION=="change", RUN+="/usr/local/sbin/rip-music-cd"

Next run udevadm control --reload to ask udev to look for new rules off disk.

§The script that udev runs

Create this script at /usr/local/sbin/rip-music-cd and make it executable (i.e. chmod 755 /usr/local/sbin/rip-music-cd).

#!/usr/bin/env bash
set -eu -o pipefail

ripuser=winston

if [[ -f /root/dont-rip ]]; then
    msg='/root/dont-rip exists, exiting.'
    echo "$msg"
    sudo -u "$ripuser" -i sh -c 'cat >> ~/ripper.log' <<<"$msg"
    exit 1
fi

sleep 5

# https://superuser.com/a/1367091/302931
python - <<EOF
"""detect_tray reads status of the CDROM_DRIVE.
Statuses:
1 = no disk in tray
2 = tray open
3 = reading tray
4 = disk in tray
"""

import fcntl
import os
import sys

CDROM_DRIVE = '/dev/sr0'

fd = os.open(CDROM_DRIVE, os.O_RDONLY | os.O_NONBLOCK)
rv = fcntl.ioctl(fd, 0x5326)
os.close(fd)
sys.exit(rv != 4)
EOF

# Not reached when the ioctl retval is not equal to 4 (disk in tray).

sudo -u "$ripuser" -i bash -c \
     'env INTERACTIVE=no abcde -B -G -x -d /dev/sr0 &>> ~/ripper.log'

Let’s break this script down.

You’ll also note this appears to log to a ripper.log file. Find this in your homedirectory of the $ripuser.

There are three settings uncommented in my abcde config file. I recommend settings all of these to some value:

OUTPUTDIR=/mnt/stuff/rips
WAVOUTPUTDIR=/tmp
OUTPUTTYPE=flac

§Conclusion

Lug a stack of discs to your workstation, and get cracking - they won’t rip themselves!

Run this as your $ripuser user to monitor activity and progress:

tail -f ~/ripper.log

§Sources