]> git.draconx.ca Git - mpdhacks.git/commitdiff
mpdthumb: Fix compatibility with newer MPD versions.
authorNick Bowler <nbowler@draconx.ca>
Thu, 22 Jul 2021 03:46:50 +0000 (23:46 -0400)
committerNick Bowler <nbowler@draconx.ca>
Thu, 22 Jul 2021 04:10:40 +0000 (00:10 -0400)
It seems that recent MPD servers have made backward-incompatible changes
to the albumart command.

Specifically, the cache check currently sends an absurdly huge offset to
avoid downloading a pointless and unnecessary multi-KB blob for every
image it is querying.  While this worked well with older servers, new
servers now reject such commands with an error instead of returning
useful information.

Fortunately, newer servers also implement the "binarylimit" command to
reduce the amount of data transferred.  For some reason we can't ask the
server to send less than 64 bytes but whatever, it is probably good
enough.

So work around the problem by testing whether the server supports
binarylimit, and use the new method if it does.  Otherwise use the
old method.  Command-line options are provided to force the behaviour
one way or the other (which avoids the extra round trip to the server).

mpdthumb.sh

index f41c5f6f18cf95b19d85e8608d1c6b94d5b55553..4ff4249042917920cdc9940b55086338e2500e7e 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright © 2019-2020 Nick Bowler
+# Copyright © 2019-2021 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,30 @@ 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
+  --version         Print a version message and then exit.
+  --help            Print this message and then exit.
 
 Report bugs to <nbowler@draconx.ca>.
 EOF
 }
 
+opt_binarylimit=auto
+
 size=x128
 lastarg=
 dashdash=
@@ -86,6 +98,9 @@ for arg; do
   fi
 
   case $dashdash$arg in
+  --binarylimit=*) opt_binarylimit=${arg#--*=} ;;
+  --no-binarylimit) opt_binarylimit=no ;;
+  --binarylimit) opt_binarylimit=yes ;;
   --size=*) size=${arg#--size=} ;;
   --small) size=56 ;;
   --size) lastarg=$arg ;;
@@ -118,6 +133,31 @@ tmp=`mktemp`
 exec 5>"$tmp" 6<"$tmp"
 rm -f "$tmp"
 
+# 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 arg; do
   arg=${arg%/*}/
   shift; set x "$@" "$arg"; shift
@@ -126,14 +166,19 @@ for arg; do
     s/[\\"]/\\&/g
     s/.*/"&"/
   }
-  s/.*/albumart & 2147483647/' >&3;
+  s/.*/albumart & '"$binarylimit_offset"'/' >&3;
 done
 
 <&4 $MPDEXEC --ignore-errors >&5 2>&1 || exit
 while read a b <&6; do
   case $a in
   size:) :;;
-  ACK) echo; shift || exit; continue ;;
+  ACK)
+    case $b in
+    *binarylimit*) printf '%s: %s\n' "$argv0" "$a $b" 1>&2; exit 1 ;;
+    esac
+
+    echo; shift || exit; continue ;;
   *) continue ;;
   esac