2011-07-07

Rockbox has the ability to generate Audioscrobbler logs for later submission to Last.fm. A custom udev rule can be combined with a command-line Last.fm scrobbler to automate the process of submitting tracks every time the digital audio player is connected to the computer.

notify-send

The udev rule is designed to call a script whenever a Rockbox device is connected:

# /etc/udev/rules.d/80-custom.rules

ACTION=="add", SUBSYSTEM=="block", ATTR{partition}=="1", ATTRS{vendor}=="Rockbox", ATTRS{model}=="Internal Storage", RUN+="/opt/rockbox/upload-scrobbler-log"

Last.fm credentials can be stored in GNOME Keyring and accessed using gkeyring:

gkeyring.py --set \
--name 'http://www.last.fm/' \
--password 'YOUR_PASSWORD_HERE' \
-p 'username_value=YOUR_USERNAME_HERE,origin_url=http://www.last.fm/'

The script will wait for the device to be mounted, retrieve the Last.fm credentials from GNOME Keyring, display a graphical notification using notify-send, call Laspyt to submit the scrobbler log, and then display a report:

#!/usr/bin/env bash

report='/tmp/upload-scrobbler.log'
ubuntu_user='ak'

scrobble() {
echo "Starting at $(date)"

# Identify device
echo "Detected $ID_FS_LABEL at $DEVNAME"

# Wait for mount
echo 'Waiting for mountโ€ฆ'
ttl='20'; while ! grep --quiet "$DEVNAME" /proc/mounts; do
sleep 1s
(( ttl-- )); (( ttl >= 0 )) || ( echo 'Unable to locate mountpoint'; exit 1 )
done

# Identify mountpoint
mountpoint="$(grep -oP '(?<=^'"$DEVNAME"' )\S+' '/proc/mounts')"
echo "Mounted at $mountpoint"

# Identify log file
log="$mountpoint/.scrobbler.log"
count="$(grep --count --invert '^#' "$log")"
echo "Found scrobbler log $log with $count entries"

# Get credentials from keyring
echo 'Getting credentials from keyringโ€ฆ'
credentials="$(sudo -H -u "$ubuntu_user" \
env "$(grep -v '^#' "/home/$ubuntu_user/.dbus/session-bus/$(cat '/var/lib/dbus/machine-id')-0"
)" \
/opt/rockbox/gkeyring.py -p origin_url='http://www.last.fm/' --output 'username_value,secret')"

username="$(echo "$credentials" | awk '{print $1}')"
password="$(echo "$credentials" | awk '{print $2}')"
[[ -n "$username" && -n "$password" ]] || ( echo 'Failed to get credentials'; exit 1 )
echo "Got credentials for $username"

# Upload scrobbler log
export DISPLAY="$(w -s "$ubuntu_user" | grep -m 1 " :" | awk "{print \$3}")"
tz="$(date +%:::z)"
echo "Uploading scrobbler log file with timezone offset $tz..."
sudo -H -u "$ubuntu_user" notify-send --icon 'multimedia-player' \
'Uploading scrobbler log' \
"Submitting $count tracks from $ID_FS_LABEL to Last.fm as $username"
sudo -H -u "$ubuntu_user" \
/opt/rockbox/laspyt.py --file "$log" --timezone "$tz" --clear \
--user "$username" --password "$password" 2>&1 \
| sed 's/\x1B\[[0-9;]*[mK]//g'

# Report
echo 'Done'
sudo -H -u "$ubuntu_user" zenity --text-info \
--title 'Scrobbler log upload' \
--filename "$report"
}

# This script must finish quickly because udev is effectively paused while it is running
scrobble >> "$report" & disown

Details from a run:

zenity

and confirmation on Last.fm:

Last.fm