]> git.draconx.ca Git - mpdhacks.git/blob - mpdthumb.sh
mpdthumb: Add --help and --version options.
[mpdhacks.git] / mpdthumb.sh
1 #!/bin/sh
2 #
3 # Copyright © 2019-2020 Nick Bowler
4 #
5 # Generate thumbnails for cover art retrieved from MPD.
6 #
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.
10
11 : "${XDG_CACHE_HOME=$HOME/.cache}"
12 : "${THUMBNAILDIR=$XDG_CACHE_HOME/mpdthumb}"
13
14 # Try to find mpdexec...
15 argv0=$0
16 case $argv0 in
17 /*) self=$argv0 ;;
18 */*) self=$PWD/${argv0#./} ;;
19 *) self=`command -v $argv0` ;;
20 esac
21 owndir=${self%/*}
22
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}"
27 else
28   : "${MPDEXEC=mpdexec}"
29 fi
30
31 if command -v gm >/dev/null; then
32   : "${CONVERT=gm convert}"
33 else
34   : "${CONVERT=convert}"
35 fi
36
37 print_version () {
38   cat <<'EOF'
39 mpdthumb.sh 0.8
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.
44 EOF
45 }
46
47 print_usage () {
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"
51 }
52
53 print_help () {
54   print_usage
55   cat <<EOF
56 This is "mpdthumb": a tool to retrieve cover art thumbnails from MPD.
57
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.
61
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.
65
66 Options:
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.
74
75 Report bugs to <nbowler@draconx.ca>.
76 EOF
77 }
78
79 size=x128
80 lastarg=
81 dashdash=
82 for arg; do
83   if test ${lastarg:+y}; then
84     arg=$lastarg=$arg
85     lastarg=
86   fi
87
88   case $dashdash$arg in
89   --size=*) size=${arg#--size=} ;;
90   --small) size=56 ;;
91   --size) lastarg=$arg ;;
92   --version) print_version; exit ;;
93   --help) print_help; exit ;;
94   --) dashdash=: ;;
95   -*) print_usage 'unrecognized argument: %s\n' "$arg" 1>&2; exit 1 ;;
96   *) set x "$@" "$arg"; shift
97   esac
98
99   shift
100 done
101
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
105   exit 1
106 fi
107
108 case $# in 0)
109   print_usage 'at least one filename is required\n' 1>&2
110   exit 1
111 esac
112
113 tmp=`mktemp`
114 exec 3>"$tmp" 4<"$tmp"
115 rm -f "$tmp"
116
117 tmp=`mktemp`
118 exec 5>"$tmp" 6<"$tmp"
119 rm -f "$tmp"
120
121 for arg; do
122   arg=${arg%/*}/
123   shift; set x "$@" "$arg"; shift
124
125   printf '%s\n' "$arg" | sed '/[        \\"'\'']/ {
126     s/[\\"]/\\&/g
127     s/.*/"&"/
128   }
129   s/.*/albumart & 2147483647/' >&3;
130 done
131
132 <&4 $MPDEXEC --ignore-errors >&5 2>&1 || exit
133 while read a b <&6; do
134   case $a in
135   size:) :;;
136   ACK) echo; shift || exit; continue ;;
137   *) continue ;;
138   esac
139
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}
146
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
152 EOF
153       mv -f "$THUMBNAILDIR/CACHEDIR.TAG~" "$THUMBNAILDIR/CACHEDIR.TAG"
154     fi
155
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"
161   fi
162
163   printf '%s\n' "$THUMBNAILDIR/$cache_id"
164 done