Friday 5 October 2012

Auto-rip CDs on headless server using udev and abcde

I have a lot of CDs, at least 500. Some of them have over the last few years made their way in FLAC form to the hard disk of my main PC, but now this collection is on the server, I'd like to add the rest of the CDs to the digital library and finally store them out of the way. I wanted a way for the server to do the work of ripping the CDs without any user intervention apart from putting a CD in the drive and taking it out again.

Linux's udev system provides a way for programs to be triggered on hardware events, such as a CD being inserted. In Fedora, udev rules files can be added to /etc/udev/rules.d/ and they will be magically picked up and used.

I wrote a rules file that looked like this:
/etc/udev/rules.d/99-autoripcd.rules

SUBSYSTEM=="block", KERNEL=="sr0", ENV{ID_CDROM_MEDIA_CD}=="1", RUN+="/usr/bin/cdautoinsert" 

Simply, this looks in sysfs's /sys/block/sr0/ for a CD (instead of a DVD) to be inserted, and runs the commmand given by RUN+. This is a shell script which runs the useful cd ripper, abcde. Here is the script:
/usr/bin/cdautoinsert

#/bin/bash

PATH=/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin /bin/abcde -NVP | tee /var/log/abcde-auto.log &

exit

The key to getting this working (and which took some googling to work out) is to pass a PATH to whatever commands you run in the script. This is because udev runs commands (as root) without much of an environment, and abcde was failing to find cdparanoia and the other tools it relies on. The other useful thing to know is to make sure commands are run with & to make the shell detach those processes, otherwise udev will hang until the job is complete, which is about 5 minutes for a typical cd.

I edited /etc/abcde.conf to give abcde defaults that work for me, including:
INTERACTIVE=n     (the -N switch on abcde's command line also does this)
ACTIONS=cddb,read,encode,tag,move,clean
OUTPUTTYPE=flac
OUTPUTFORMAT='${ARTISTFILE}/${ALBUMFILE}/${ARTISTFILE}-${ALBUMFILE}-${TRACKNUM}.${TRACKFILE}' (this fits with the directory structure of my music collection)
EJECTCD=y


When writing your own udev rules, the udevadm tool is handy.
udevadm monitor will show udev events as they happen (so you can see which subsystem to look at)
udevadm info --name=/dev/sr0 --query=all will list everything udev knows about the CD drive

11 comments:

  1. what happens if there is more than one entry in the cddb?

    ReplyDelete
    Replies
    1. It seems to just take the first complete match, which hasn't caused any problems so far. If there's a CD that I think won't be in the CDDB then I rip it manually.

      Delete
  2. When I try to run /usr/bin/cdautoinsert on cmd line to test it, the data from cdparanioa is spat out to stdout (in the console) rather than being passed to flac, any ideas?

    ReplyDelete
    Replies
    1. What happens when you run abcde from a shell, passing the same options? If you get the same thing, it might be to do with your environment - check for dot files and environment variables that cdparanioa might be using which aren't present in the environment that udev spawns the script in.

      It might also be something to do with abcde itself - have a look through the /usr/bin/abcde script and see if anything jumps out at you. FWIW, I'm using abcde-2.4.2-4.fc17.

      My abcde.conf has the following lines changed from the default:

      PADTRACKS=y
      INTERACTIVE=n
      METAFLACOPTS=""
      ACTIONS=cddb,read,encode,tag,move,clean
      CDROM=/dev/cdrom
      OUTPUTDIR=/export/media/music/
      WAVOUTPUTDIR=/tank/temp/
      OUTPUTTYPE=flac
      OUTPUTFORMAT='${ARTISTFILE}/${ALBUMFILE}/${TRACKNUM}-${TRACKFILE}'
      VAOUTPUTFORMAT='Various Artists/${ALBUMFILE}/${ALBUMFILE}-${TRACKNUM}-${ARTISTFILE}-${TRACKFILE}'
      EJECTCD=y

      Does the script run fine when triggered by udev ie does it autorip a cd successfully?

      Delete
  3. Hi, thanks for your help.
    My abcde version is 2.5.3, I see the issue I am having has been reported on abcde's issue tracker.

    I was running the script on the cmd line to glean some info as it was not auto ripping when inserted, though I think this is a separate issue. The cd drive is connected via USB-PATA adaptor. At present udevadm-monitor does not report anything when the CD is inserted.

    I do not seem to have any other cdparanoia etc config files laying around.

    my abcde.conf is pretty much the same but for revised output paths, i'm writing the results to an NFS mount, but tried with a local path in case that was causing some issue.


    When its running the following appears in output of ps -aef f

    root 20630 16106 5 09:25 pts/0 S+ 0:00 | \_ /bin/bash /usr/bin/abcde -NVP
    root 21017 20630 0 09:25 pts/0 S+ 0:00 | \_ /bin/bash /usr/bin/abcde -NVP
    root 21026 21017 0 09:25 pts/0 S+ 0:00 | | \_ /bin/bash /usr/bin/abcde -NVP
    root 21051 21026 16 09:25 pts/0 SN+ 0:01 | | | \_ cdparanoia -d /dev/sr0 01 -
    root 21027 21017 0 09:25 pts/0 S+ 0:00 | | \_ /bin/bash /usr/bin/abcde -NVP
    root 21045 21027 0 09:25 pts/0 SN+ 0:00 | | \_ flac -f -o /tmp//abcde.d20a4411/track01.flac -
    root 21018 20630 0 09:25 pts/0 S+ 0:00 | \_ /bin/bash /usr/bin/abcde -NVP


    Would you mine posting what yours looks like?

    ReplyDelete
    Replies
    1. If i run

      cdparanoia -d /dev/sr0 01 - | flac -f -o /tmp/track01.flac -


      it works as expected so I think this must be some bug in abcde not setting up the pipe correctly. Ill try the older version later.

      Thanks

      Dan

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. OK, found out it is better to use devmon to run programs when you want to run programs on hardware events

      Delete
  5. Hi, couple of quick questions.
    How does this react if you accidentally put a CD in that has already been ripped?

    If I were to leave the udev rule in place, what would happen if I inserted an non audio CD?
    I guess I'd want to leave the rule in place to deal with future CD purchases.

    ReplyDelete
  6. Hi JC ... I'm having a heck of a time getting udev to run my script ..... the abcde script works fine, I just can't get the inserted cd to trigger it ...
    do i need the rule in /etc/udev or usr/lib/udev .... here's my rule (i'm running a usb cdrom on sr0 )

    SUBSYSTEM=="block", KERNEL=="sr0", ENV{ID_CDROM_MEDIA_CD}=="1", RUN+="/usr/bin/cdautoinsert"


    ReplyDelete
  7. The issue with udev is that several events can occur for a single CD insertion, which can manifest itself in multiple instances of ABCDE running.

    ReplyDelete