Mischiefblog
I make apps for other people

Capturing CD-ROM insert events in Linux

Posted by Chris Jones
On March 24th, 2015 at 20:26

Permalink | Trackback | Links In |

Comments Off on Capturing CD-ROM insert events in Linux
Posted in Tech

I’ve been looking into how to capture CD-ROM (music CD) insert events for . . . reasons. Like I’ve got a big collection of CDs and I’d really like to rip them to FLAC files before jukeboxing the media. Now, I’ve looked into doing this on OS X (using the Disk Arbitration framework — this is relatively easy in Swift and Objective C but a bit harder from Go), and I’ve also considered how to capture the events in DBus on Linux/GNOME systems. However, I’m a stick in the mud when it comes to GNOME and I’ve pulled it off more than one machine because of the GNOME keystore and problems encountered because of that, so I’m reluctant to write anything that requires DBus when there’s a perfectly UI independent solution available: udev.

In short, udev provides a way to query the sysfs device tree, renaming devices on the tree (allowing custom /dev filesystem mounts), and utilities for running rules on device events.

  • Identify the device you’re interested in. Devices may change identifiers so you may need to use additional attributes to identify the physical device. The following example shows part of the output for my virtualized DVD-RW device (Apple SuperDrive on a MacBook Pro, with Mint running in Parallels which shared the DVD-RW).

    $ udevadm info -a -p /sys/block/sr0
     
    Udevadm info starts with the device specified by the devpath and then
    walks up the chain of parent devices. It prints for every device
    found, all possible attributes in the udev rules key format.
    A rule to match, can be composed by the attributes of the device
    and the attributes from one single parent device.
     
      looking at device '/devices/pci0000:00/0000:00:1f.2/ata4/host3/target3:0:0/3:0:0:0/block/sr0':
        KERNEL=="sr0"
        SUBSYSTEM=="block"
        DRIVER==""
        ATTR{ro}=="0"
        ATTR{size}=="3047424"
        ATTR{stat}==" 25 0 148 0 0 0 0 0 0 0 0"
        ATTR{range}=="1"
        ATTR{discard_alignment}=="0"
        ATTR{events}=="media_change eject_request"
        ATTR{ext_range}=="1"
        ATTR{events_poll_msecs}=="2000"
        ATTR{alignment_offset}=="0"
        ATTR{inflight}==" 0 0"
        ATTR{removable}=="1"
        ATTR{capability}=="119"
        ATTR{events_async}==""
     
  • For this example, I’ll assume that sr- is going to be consistent. The ATTRibutes aren’t specific enough for me to pick out a device — likely because of virtualization — although the parent device does indicate an identifiable source (ATTRS{model}==”Virtual DVD-ROM “). I created a rule to be invoked on /dev/sr0 changes.

    $ cat /etc/udev/rules.d/z21_persistent-local.rules
    KERNEL=="sr0", RUN+="/home/chris/callback.sh"

    This invokes a simple script that appends a message to a file when it’s invoked.
  • After creating the persistent-local.rules file, I reloaded the udev rules:

    $ sudo udevadm control --reload-rules

    This has implications for any application I write to automatically capture mounted CDs: I need to run the setup as root to insert the rule, and also provide a script to cleanly remove this rule later.
  • With iTunes grabbing the CD, I needed to (a) dismiss iTunes on insertion and (b) tell Parallels to make the disc available to Mint (as a Hardware option). When this was done, my rule was executed. Watch /var/log/syslog for any execution errors.
  • The callback.sh script was executed as root.

Comments are closed.