#!/usr/bin/env bash # Desktop notification with cover art on song change. Run by ncmpcpp's # execute_on_song_change, so it only fires while ncmpcpp is open. # # mopidy: Mopidy-MPD has no albumart command, so the cover comes from the # Subsonic server behind Mopidy-Subidy. url and username are read from # mopidy.conf, the password from the untracked secrets.conf. # Usage: song-notify [subidy:song:] (defaults to the current song) set -u conf=~/.config/mopidy/mopidy.conf secrets=~/.config/mopidy/secrets.conf cache=${XDG_CACHE_HOME:-$HOME/.cache}/ncmpcpp/covers fmt='%file%\t%artist%\t%title%\t%album%' if [ $# -gt 0 ]; then line=$(mpc -f "$fmt" playlist 2>/dev/null | awk -F'\t' -v u="$1" '$1 == u { print; exit }') else line=$(mpc -f "$fmt" current 2>/dev/null) fi IFS=$'\t' read -r uri artist title album <<<"$line" [ -n "$uri" ] || exit 0 # Value of key in [subidy] of an ini file. ini() { awk -F' *= *' -v k="$2" ' /^\[/ { s = ($0 == "[subidy]") } s && $1 == k { print $2; exit }' "$1" } cover= id=${uri#subidy:song:} if [ "$id" != "$uri" ] && [ -r "$secrets" ]; then url=$(ini "$conf" url) user=$(ini "$conf" username) pass=$(ini "$secrets" password) salt=$(head -c 8 /dev/urandom | od -An -tx1 | tr -d ' \n') token=$(printf '%s%s' "$pass" "$salt" | md5sum | cut -d' ' -f1) auth="u=$user&t=$token&s=$salt&v=1.16.1&c=ncmpcpp" art=$(curl -fsS --max-time 5 "$url/rest/getSong.view?$auth&f=json&id=$id" | jq -r '."subsonic-response".song.coverArt // empty') if [ -n "$art" ]; then cover=$cache/${art////_} if [ ! -s "$cover" ]; then mkdir -p "$cache" curl -fsS --max-time 10 -o "$cover" \ "$url/rest/getCoverArt.view?$auth&id=$art&size=256" || cover= fi fi fi notify-send -a ncmpcpp ${cover:+-i "$cover"} \ -h string:x-canonical-private-synchronous:ncmpcpp \ "${title:-$uri}" "${artist:-}${album:+ — $album}"