X-Git-Url: https://git.draconx.ca/gitweb/mpdhacks.git/blobdiff_plain/614746d84dbada7c6f55c1d824e485d876f1018f..44faac243210fd4ab72702a9acc2ff6cf7743d55:/mpdthumb.sh diff --git a/mpdthumb.sh b/mpdthumb.sh index c48e398..4faf7a6 100755 --- a/mpdthumb.sh +++ b/mpdthumb.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright © 2019 Nick Bowler +# Copyright © 2019-2021 Nick Bowler # # Generate thumbnails for cover art retrieved from MPD. # @@ -12,10 +12,11 @@ : "${THUMBNAILDIR=$XDG_CACHE_HOME/mpdthumb}" # Try to find mpdexec... -case $0 in -/*) self=$0 ;; -*/*) self=$PWD/${0#./} ;; -*) self=`command -v $0` ;; +argv0=$0 +case $argv0 in +/*) self=$argv0 ;; +*/*) self=$PWD/${argv0#./} ;; +*) self=`command -v $argv0` ;; esac owndir=${self%/*} @@ -33,8 +34,65 @@ else : "${CONVERT=convert}" fi -size=x128 +print_version () { + cat <<'EOF' +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. +EOF +} + +print_usage () { + test $# -eq 0 || { printf '%s: ' "$argv0"; printf "$@"; } + printf 'Usage: %s [options] file [file ...]\n' "$argv0" + test $# -eq 0 || printf 'Try %s --help for more information.\n' "$argv0" +} + +print_help () { + print_usage + cat <. +EOF +} +opt_binarylimit=auto +opt_embedded=no + +size=x128 lastarg= dashdash= for arg; do @@ -44,11 +102,18 @@ 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 ;; + --version) print_version; exit ;; + --help) print_help; exit ;; --) dashdash=: ;; - -*) printf '%s: unrecognized argument: %s\n' "$0" "$arg" 1>&2; exit 1 ;; + -*) print_usage 'unrecognized argument: %s\n' "$arg" 1>&2; exit 1 ;; *) set x "$@" "$arg"; shift esac @@ -57,12 +122,12 @@ done w=${size%x*} h=${size#*x} if expr "$w$h" : '[0-9][0-9]*$' >/dev/null; then :; else - printf '%s: invalid --size setting: %s\n' "$0" "$size" 1>&2 + print_usage 'invalid --size setting: %s\n' "$size" 1>&2 exit 1 fi case $# in 0) - printf 'usage: %s [options] file [file ...]\n' "$0" 1>&2 + print_usage 'at least one filename is required\n' 1>&2 exit 1 esac @@ -74,29 +139,87 @@ 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 + +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' "$arg" | sed '/[ \\"]/ { + 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:) + 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} @@ -110,7 +233,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"