X-Git-Url: https://git.draconx.ca/gitweb/mpdhacks.git/blobdiff_plain/9913010f15f1fb7a3f331e655592fa6fc2807a12..HEAD:/mpdthumb.sh diff --git a/mpdthumb.sh b/mpdthumb.sh index f41c5f6..e87f837 100755 --- a/mpdthumb.sh +++ b/mpdthumb.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright © 2019-2020 Nick Bowler +# Copyright © 2019-2022 Nick Bowler # # Generate thumbnails for cover art retrieved from MPD. # @@ -36,8 +36,8 @@ fi print_version () { cat <<'EOF' -mpdthumb.sh 0.8 -Copyright © 2020 Nick Bowler +mpdthumb.sh 0.9 +Copyright © 2021 Nick Bowler License GPLv3+: GNU General Public License version 3 or any later version. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. @@ -64,18 +64,34 @@ the same order of the associated files specified on the command line. If a given file has no cover art, then a blank line is printed. Options: - --size=[W][xH] Specify the dimensions (in pixels) of a bounding rectangle - into which the image will be scaled to fit. One (but not - both) of the dimensions may be omitted to indicate no limit - in that direction. The default size is x128. - --small Equivalent to --size=56 - --version Print a version message and then exit. - --help Print this message and then exit. + --size=[W][xH] Specify the dimensions (in pixels) of a bounding + rectangle into which the image will be scaled to fit. + One (but not both) of the dimensions may be omitted + to indicate no limit in that direction. The default + size is x128. + --small Equivalent to --size=56 + --binarylimit[=ARG] + If ARG is omitted or 'yes', force the use of the + binarylimit command to reduce the amount of data + transferred in the hot cache case. If ARG is 'no', + then the old "large offset" method is used which is + incompatible with newer MPD servers. The default is + 'auto', which queries the server to determine the + appropriate method. + --no-binarylimit Equivalent to --binarylimit=no + --embedded Attempt to retrieve embedded covers using readpicture. + This requires (and implies) --binarylimit. + --no-embedded Use only album-level covers. This is the default. + --version Print a version message and then exit. + --help Print this message and then exit. Report bugs to . EOF } +opt_binarylimit=auto +opt_embedded=no + size=x128 lastarg= dashdash= @@ -86,6 +102,11 @@ for arg; do fi case $dashdash$arg in + --binarylimit=*) opt_binarylimit=${arg#--*=} ;; + --no-binarylimit) opt_binarylimit=no ;; + --binarylimit) opt_binarylimit=yes ;; + --embedded) opt_embedded=yes ;; + --no-embedded) opt_embedded=no ;; --size=*) size=${arg#--size=} ;; --small) size=56 ;; --size) lastarg=$arg ;; @@ -118,29 +139,91 @@ tmp=`mktemp` exec 5>"$tmp" 6<"$tmp" rm -f "$tmp" -for arg; do - arg=${arg%/*}/ - shift; set x "$@" "$arg"; shift +# --embedded implies --binarylimit +case $opt_embedded in +yes) use_embedded=true ;; +*) use_embedded=false ;; +esac +$use_embedded && opt_binarylimit=yes + +# Test for binarylimit command in MPD server. We want to minimize data +# transfer in order to make cache hits as fast as possible. +# +# On older servers we can set a ridiculously large offset which causes the +# server to send no data, but this is rejected by new servers. On new servers +# we can limit the data transferred explicitly, but not less than 64 bytes +# for some reason (probably not a big problem). + +use_binarylimit=true +case $opt_binarylimit in +auto) $MPDEXEC binarylimit 64 2>/dev/null || use_binarylimit=false ;; +no) use_binarylimit=false ;; +yes) :;; +*) + print_usage 'invalid --binarylimit argument; must be yes, no or auto' 1>&2 + exit 1 +esac - printf '%s\n' "$arg" | sed '/[ \\"'\'']/ { +if $use_binarylimit; then + printf 'binarylimit 64\n' >&3 + binarylimit_offset=0 +else + binarylimit_offset=2147483647 +fi + +for file; do + case $file in + */*) dir=${file%/*}/ ;; + *) dir=/ ;; + esac + + if $use_embedded; then + shift; set x "$@" "$file" "$dir"; shift + else + file= + fi + + printf '%s\n' "$dir" ${file:+"$file"} | sed -n '/[ \\"'\'']/ { s/[\\"]/\\&/g s/.*/"&"/ } - s/.*/albumart & 2147483647/' >&3; + s/.*/albumart & '"$binarylimit_offset"'/ + 1h + 2s/^albumart/readpicture/p + $ { + g + p + }' >&3; done -<&4 $MPDEXEC --ignore-errors >&5 2>&1 || exit +valid= +<&4 $MPDEXEC --verbose --ignore-errors >&5 2>&1 || exit while read a b <&6; do case $a in - size:) :;; - ACK) echo; shift || exit; continue ;; + readpicture|albumart) + prevn=$# file=$1 mode=$a; shift || exit; continue + ;; + size:) + if test x"$mode/$valid" = x"albumart/readpicture$prevn"; then + # readpicture result was OK, skip over albumart result + continue + fi + valid=$mode$# + ;; + ACK) + case $b in + *'{binarylimit}'*|*'{readpicture}'*) + printf '%s: %s\n' "$argv0" "$a $b" 1>&2; exit 1 ;; + esac + test x"$valid" = x"readpicture$prevn" || echo + continue + ;; *) continue ;; esac # We combine the filename and the size to compute the cache key and # hope this suffices to detect stale entries. Unfortunately MPD does # not currently give us the modified date which would be more useful... - file=$1; shift || exit cache_id=`printf 'MPD:%s:%s' "$file" "$b" | md5sum` cache_id=${cache_id:+${cache_id%% *}_$size.png} @@ -154,7 +237,7 @@ EOF fi # Not cached, retrieve the entire image - $MPDEXEC --binary --download albumart "$file" >&3 || exit + $MPDEXEC --binary --download "$mode" "$file" >&3 || exit <&4 $CONVERT -scale "$size" - "$THUMBNAILDIR/tmp.$cache_id" || { rc=$? rm -f "$THUMBNAILDIR/tmp.$cache_id"; exit $rc; } mv -f "$THUMBNAILDIR/tmp.$cache_id" "$THUMBNAILDIR/$cache_id"