#!/bin/dash
#150503 step: see https://github.com/step-/nathans-wallpaper/

#|set +x
#|echo     " >&2
#|---------- set_bg $(date)"
#|set -x

[ -z "$USRDIR" ] && USRDIR="$HOME/.config/wallpaper"

# Require rox
if ! pidof ROX-Filer >/dev/null 2>&1; then
  echo "no rox" >&2
  exit 101
fi
# Fatdog64 - PINBOARD_FILE is set in /usr/sbin/fatdog-drive-icon*.sh
PINBOARD_FILE=$HOME/.config/rox.sourceforge.net/ROX-Filer/PuppyPin

# We assume that rox is already running for $USER. If not, on its first
# invocation for $USER rox will
# 1) complain that it can't find dir ~/.icons to set link ~/.icons/ROX
# 2) daemonize and keep gtkdialog's parent process active after gtkdialog has closed.
# Note that Wallpaper Setter AppRun actually tests for a running ROX-Filer process.

# Determine the path to this application.
if ! [ -e "$APPDIR" ]; then # don't do this if APPDIR is preset.
  APPDIR=${0%/*}; APPDIR=`cd "$APPDIR";pwd`
fi

DEBUG=${DEBUG:-} # unset to disable debug trace to stderr; set verbosity (integer) 1-3
CACHEROOT=${CACHEROOT:-$HOME/.cache/wallpaper}

# Emit pathname of current wallpaper preview file
get_current_preview()
{
  local PREVIEWIMG=/tmp/$USER-current_wallpaper_selection.jpg
  local prw="$(readlink -e "${PREVIEWIMG}")" # keep readlink !
  [ -n "${prw}" ] && echo -n "${prw}"
}

set +f
mkdir -p "$USRDIR" "$CACHEROOT"
if [ "$1" = "-clear" ];then
 [ "${DEBUG}" ] && set -x
 x=${PINBOARD_FILE%/*}
 y=$USRDIR
 [ -e $x/pb_default -a $PINBOARD_FILE -ot $x/pb_default ] && z=$x/pb_default || z=$PINBOARD_FILE
 grep -v '<backdrop' $z > $y/pb &&
 mv -f $y/pb $x/pb_default &&
 # Caveat: rox -p "pb_default" creates "pb_pb_default"
 # while   rox -p "/.../pb_default" updates "/.../pb_default"
 rox -p "$x/pb_default" # full path
 # remove cached copies of the actual background wallpaper
 if read x < $y/bg_img; then
  x=${x##*/}
  [ "[none]" != "$x" ] && rm -f "$CACHEROOT"/.[0-9][0-9][0-9]/"$x"
 fi
 # remove cached copies of the current preview wallpaper
 x=$(get_current_preview)
 if [ -n "$x" ]; then
   x=${x##*/}; x=${x%.jpg}
   rm -f "$CACHEROOT"/.[0-9][0-9][0-9]/"$x" "$CACHEROOT"/.[0-9][0-9][0-9]/"$x.jpg";
   # remove current preview image (file or link)
   rm -f "$CACHEROOT/.preview/$x.jpg" "$CACHEROOT/.preview/$x.jpg.jpg"
 fi

 echo "[none]" > $y/bg_img
 [ "${DEBUG}" ] && set +x
 exit
fi

# $1 ::= [mode':']image-file-path; mode ::= 'Centre'|'Scale'|'Fit'|'Tile'|'Stretch'|'Distort'
MODE=${1%:*}; ifp=${1#*:}; [ "${MODE}" = "${ifp}" ] && MODE=

# accept non-empty image file only
if ! [ -s "${ifp}" ]; then # -z=!-n < -f < -s
  echo -n "$0: "
  ls -l "$ifp" # print 'not found/empty' message
  exit 1
fi >&2

if [ -z "${MODE}" ]; then
  [ ! -s "$USRDIR/backgroundmode" ] &&
    echo Centre > "$USRDIR/backgroundmode" # sensible catchall
  read MODE < "$USRDIR/backgroundmode"
fi
# convert MODE to UK-spelling infinitive verb for rox --RPC
case $MODE in
 Scale*) MODE=Scale  ;;
 Fit*) MODE=Fit  ;;
 Stretch*) MODE=Stretch ;;
 Distort*) MODE=Distort ;; # NOT RPC - renamed later
 Tile*) MODE=Tile ;;
 Center*|Centre*|*) MODE=Centre ;; # sensible catchall
esac

# Windows BMP support
bmptojpg () # $1-bmp-image-path
{
  local name out
  name=${1##*/}; name=${name%.*}
  out="$CACHEROOT/${name}.jpg"
  # Convert BMP $1 to JPG $out. Notice that we don't overwrite an
  # existing, non-empty $out.  So if $out already exists before we get
  # called we will wrongly return it as the converted $out.  Since the
  # latter case is very unlikely we ignore it.
  [ ! -s "${out}" ] && bmptopnm "$1" | pnmtojpeg -quality=85 > "${out}"
  [ -s "${out}" ] && echo -n "${out}" # signal success
}

#20150503 ROX-Filer can't convert BMP, so we do it here
case ${ifp} in *.bmp|*.BMP) NEWIMAGE=$(bmptojpg "${ifp}");; *) NEWIMAGE= ;; esac
# NEWIMAGE is non-null iff conversion succeeded

#w482 BK now have script that truncates an image vertically so that it has the right dimensions
#for a widescreen...
#140101 background_reshape has changed...
[ -z "${NEWIMAGE}" ] && NEWIMAGE="${ifp}"
if [ "$MODE" = "Stretch" ]; then
 #truncated image is created, in a sub-directory of $CACHEROOT, ex: /usr/share/backgrounds/.177/image.jpg
 # where "177" is the screen aspect ratio, as a percentage.
 [ "${DEBUG}" ] && echo >&2 "========== set_bg calls ${APPDIR}/background_reshape" "${NEWIMAGE}"
 DEBUG=${DEBUG} \
 SCALE_FILTER=${SCALE_FILTER} \
 "${APPDIR}/background_reshape" "${NEWIMAGE}"
 RETVAL=$?
 if [ $RETVAL -eq 10 -o $RETVAL -eq 11 ];then # legacy compatibility
  read NEWIMAGE < /tmp/$USER-qwallpaper_reshaped
 else
  exit 1 # exit without changing background on reshaping error
 fi
fi

set_pinboard() # $1-pinboard-file-full-path
# Rox provides a method to set the backdrop of the active pinboard, but no
# method to find out which is the active pinboard, or to set the backdrop of a
# given pinboard file.  If there is no active pinboard when the SetBackDrop RPC
# method is called rox display an error dialog, "No active pinboard...Using the
# 'Default' pinboard", which causes a second pinboard ('Default') to come into
# existence. Clicking the desktop switches between the Puppy pinboard and the
# Default pinboard, which is quite confusing and unexpected.  Therefore, before
# calling SetBackDrop we test that $1 is already the active pinboard. If it is
# we don't want to set it again, because it takes rox noticeable time and
# screen-flicker to redraw the pinboard when it is being set.
{
  local t

  # Variable LIVE is set if Wallpaper AppRun's gtkdialog is running and is my
  # ancestor. Assume it set the pinboard.
  [ -n "$LIVE" ] && return

  # Variable ACTIVE_SLIDESHOW_INT is set if wallslide is running and is my
  # ancestor. Gtkdialog could not be running. If wallslide called me at least
  # once before, then I already set the pinboard.
  if [ -n "$ACTIVE_SLIDESHOW_INT" ]; then
    # running time of wallslide > slideshow update interval
    t=$(ps -p "`pgrep wallslide`" --no-headers -o etimes 2>/dev/null)
    [ -n "$t" ] &&
      [ "$t" -gt $((2 * $ACTIVE_SLIDESHOW_INT - 1)) ] &&
      return
  fi
  # set -- $(date +%s; stat -c "%Z" "$PINBOARD_FILE")
  # echo $(($1 - $2 <= 15)) # modified less than 16 s ago

  # We couldn't find any evidence that the pinboard file is already set.
  rox -p "$PINBOARD_FILE"
}
# Tell rox to use a new background image.
# Note this will also write to $PINBOARD_FILE.
# If ROX-Filer doesn't like the file type of $NEWIMAGE it will delete
# $NEWIMAGE and show 'removing the backdrop' in a dialog box.
set_pinboard "$PINBOARD_FILE" # full path
: rox RPC "SetBackDrop('$MODE:$NEWIMAGE')"
# "Distort" MODE is actually a placeholder for the native,
# unproportional "Stretch" mode.  NEWIMAGE is unconverted for Distort,
# and converted for Stretch.
[ $MODE = Distort ] && mode=Stretch || mode=$MODE
rox --RPC << EOF
<env:Envelope xmlns:env="http://www.w3.org/2001/12/soap-envelope">
 <env:Body xmlns="http://rox.sourceforge.net/SOAP/ROX-Filer">
  <SetBackdrop>
   <Filename><![CDATA[${NEWIMAGE}]]></Filename>
   <Style>$mode</Style>
  </SetBackdrop>
 </env:Body>
</env:Envelope>
EOF

# Save NEWIMAGE and MODE states
echo "$NEWIMAGE" > "$USRDIR/bg_img"
echo $MODE > "$USRDIR/backgroundmode"

# We can't know for sure if rox RPC did actually change the wallpaper.
exit

###END###
