3 # Copyright © 2019-2020 Nick Bowler
5 # Generate thumbnails for cover art retrieved from MPD.
7 # License GPLv3+: GNU General Public License version 3 or any later version.
8 # This is free software: you are free to change and redistribute it.
9 # There is NO WARRANTY, to the extent permitted by law.
11 : "${XDG_CACHE_HOME=$HOME/.cache}"
12 : "${THUMBNAILDIR=$XDG_CACHE_HOME/mpdthumb}"
14 # Try to find mpdexec...
18 */*) self=$PWD/${argv0#./} ;;
19 *) self=`command -v $argv0` ;;
23 if command -v "$owndir/mpdexec.pl" >/dev/null; then
24 : "${MPDEXEC=$owndir/mpdexec.pl}"
25 elif command -v mpdexec.pl >/dev/null; then
26 : "${MPDEXEC=mpdexec.pl}"
28 : "${MPDEXEC=mpdexec}"
31 if command -v gm >/dev/null; then
32 : "${CONVERT=gm convert}"
34 : "${CONVERT=convert}"
40 Copyright © 2020 Nick Bowler
41 License GPLv3+: GNU General Public License version 3 or any later version.
42 This is free software: you are free to change and redistribute it.
43 There is NO WARRANTY, to the extent permitted by law.
48 test $# -eq 0 || { printf '%s: ' "$argv0"; printf "$@"; }
49 printf 'Usage: %s [options] file [file ...]\n' "$argv0"
50 test $# -eq 0 || printf 'Try %s --help for more information.\n' "$argv0"
56 This is "mpdthumb": a tool to retrieve cover art thumbnails from MPD.
58 One or more filenames may be specified. The cover art (if any) for each
59 file is retrieved and scaled to the requested size. The thumbnails are
60 cached locally so that subsequent lookups return results very quickly.
62 The filenames of the generated thumbnails are printed one per line in
63 the same order of the associated files specified on the command line.
64 If a given file has no cover art, then a blank line is printed.
67 --size=[W][xH] Specify the dimensions (in pixels) of a bounding rectangle
68 into which the image will be scaled to fit. One (but not
69 both) of the dimensions may be omitted to indicate no limit
70 in that direction. The default size is x128.
71 --small Equivalent to --size=56
72 --version Print a version message and then exit.
73 --help Print this message and then exit.
75 Report bugs to <nbowler@draconx.ca>.
83 if test ${lastarg:+y}; then
89 --size=*) size=${arg#--size=} ;;
91 --size) lastarg=$arg ;;
92 --version) print_version; exit ;;
93 --help) print_help; exit ;;
95 -*) print_usage 'unrecognized argument: %s\n' "$arg" 1>&2; exit 1 ;;
96 *) set x "$@" "$arg"; shift
102 w=${size%x*} h=${size#*x}
103 if expr "$w$h" : '[0-9][0-9]*$' >/dev/null; then :; else
104 print_usage 'invalid --size setting: %s\n' "$size" 1>&2
109 print_usage 'at least one filename is required\n' 1>&2
114 exec 3>"$tmp" 4<"$tmp"
118 exec 5>"$tmp" 6<"$tmp"
123 shift; set x "$@" "$arg"; shift
125 printf '%s\n' "$arg" | sed '/[ \\"'\'']/ {
129 s/.*/albumart & 2147483647/' >&3;
132 <&4 $MPDEXEC --ignore-errors >&5 2>&1 || exit
133 while read a b <&6; do
136 ACK) echo; shift || exit; continue ;;
140 # We combine the filename and the size to compute the cache key and
141 # hope this suffices to detect stale entries. Unfortunately MPD does
142 # not currently give us the modified date which would be more useful...
143 file=$1; shift || exit
144 cache_id=`printf 'MPD:%s:%s' "$file" "$b" | md5sum`
145 cache_id=${cache_id:+${cache_id%% *}_$size.png}
147 if test ! -f "$THUMBNAILDIR/$cache_id"; then
148 if test ! -f "$THUMBNAILDIR/CACHEDIR.TAG"; then
149 mkdir -p "$THUMBNAILDIR"
150 { cat >"$THUMBNAILDIR/CACHEDIR.TAG~" || exit; } <<'EOF'
151 Signature: 8a477f597d28d172789f06886806bc55
153 mv -f "$THUMBNAILDIR/CACHEDIR.TAG~" "$THUMBNAILDIR/CACHEDIR.TAG"
156 # Not cached, retrieve the entire image
157 $MPDEXEC --binary --download albumart "$file" >&3 || exit
158 <&4 $CONVERT -scale "$size" - "$THUMBNAILDIR/tmp.$cache_id" ||
159 { rc=$? rm -f "$THUMBNAILDIR/tmp.$cache_id"; exit $rc; }
160 mv -f "$THUMBNAILDIR/tmp.$cache_id" "$THUMBNAILDIR/$cache_id"
163 printf '%s\n' "$THUMBNAILDIR/$cache_id"