#!/bin/ksh
#
# Use a background changer to rotate images

#chbg="habak -mS -hi "
chbg="hsetroot -full "
#	What binary to use to change the background. Note that it is expected
#	that this will take a directory as a parameter and use a random image
#	from within that directory.
identify="gm identify "
conjure="gm conjure "
convert="gm convert "
#       Paths to ImageMagick tools ... or more precisely GraphicsMagic tools.
scriptname=$(basename $0)
#	Used to kill off other copies of this script.
dir="~/lib/backgrounds/"
#	Directory which is the base for which set of background images
#	to play.
delay=300
#	How many seconds to delay between changing backgrounds.
set -A images
#	Set this up as an array
set -A horizontals
set -A verticals
#	Setup two arrays to add images to depending on whether they're horizontal or
#	vertical orientation.

# usage
#
# Do the usual thing

function usage {
  cat <<END
set-random-background choice

A continuous running process to set the background to a random image chosen
from the contents of a directory specified by you ... the first parameter
of this script is appended to $dir to make a directory.

This allows for a choice of directories full of background images to choose
from.
END
}

# expandtilde
#
# Probably unnecessary function to replace the ~ in a string and replace it with
# the contents of $HOME

function expandtilde {
  echo $1 | grep "~" > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    # The string does contain a ~ so replace it 
    regex=$(echo "s:~:$HOME:")
    # Note that we use ":" as a regexp separator.
    echo $(echo $1 | sed -e "$regex")
  else 
    echo $1
  fi	
}

# webcollage
#
# Try and run webcollage (from xscreensaver).

function webcollage {
    exec /usr/lib/xscreensaver/webcollage -root
}

# killold
#
# Try and kill any old running processes

function killold {
  if [[ -f $pidfile ]]
  then
    # We may have something running
    oldpid=$(cat $pidfile)
    ps -p $oldpid > /dev/null 2>&1
    if [[ "$?" == 0 ]]
    then 
      kill $oldpid
      # This is a rough method for killing the old copy of this script; which could kill random
      # processes, so we should have a better method, but it's better than the old method.
    fi
  fi
}

# orientimages
#
# Given a directory, iterate through the files picking out the images and adding them
# to either the 'vertical' array if they're of portrait orientation or the 'horizontal'
# array if not. Uses ImageMagick to do the magic

function orientimages {
    typeset var dir
    dir=$1
    for file in $(ls $dir)
    do
	id=$($identify $dir/$file 2> /dev/null)
	if [[ "$?" = 0 ]]
	then
            # It's an image so treat it as such.
	    size=$(echo $id | awk '{print $3}')
	    xsize=$(echo $size | awk -Fx '{print $1}')
	    ysize=$(echo $size | awk -Fx '{print $2}')
	    if [[ "$xsize" -gt "$ysize" ]]
	    then
		horizontals+=("$dir/$file")
	    else
		verticals+=("$dir/$file")
	    fi
	fi
    done
}

# makecanvas
#
# Make a blank image background to draw on later. It shouldn't matter too much about the details of
# this, as we don't expect to see any of it.

function makecanvas {
    if [[ ! -f "$dir/canvas.png" ]]
    then
	geometry=$(echo $fullsize | sed -e "s/ /x/")
	$convert -size "$geometry" xc:wheat $dir/canvas.png
	if [[ "$?" != 0 ]]
	then
	    echo Could not create the canvas file: $dir/canvas.png for some reason
	fi
    fi
    # We don't create the canvas if it's already there
}

# makebackground
#
# Create a background image ($dir/background.png) using an MSL script. Which does basically :-
# for each region :-
#   - pick a random image whose orientation matches that of the region
#   - adds the relevant MSL to the command file to resize that image to the size of the region.
#

function makebackground {
    cat > "$dir/makebackground.msl" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
    <group>
EOF
    count=0
    for region in $regions
    do
	count=$(expr $count + 1)
	xsize=$(echo $region | awk -Fx '{print $1}')
	ysize=$(echo $region | sed -e "s/^.*x//" | awk -F+ '{print $1}')
	resize=$(echo $region | awk -F+ '{print $1}')
	if [[ "$xsize" -gt "$ysize" ]]
	then
	    image="${horizontals[$[${RANDOM}%${#horizontals[*]}]]}"
	else
	    image="${verticals[$[${RANDOM}%${#verticals[*]}]]}"
	fi
	cat >> "$dir/makebackground.msl" <<EOF
        <image id="$count">
            <read filename="$image"/>
            <resize geometry="$resize!"/>
        </image>
EOF
    done
    cat >> "$dir/makebackground.msl" <<EOF
        <image>
            <read filename="$dir/canvas.png"/>
EOF
    #            <resize geometry="$fullsize"/>
    # Removed the 'resize' above as it probably isn't necessary
    count2=0
    for region in $regions
    do
	count2=$(expr $count2 + 1)
	cat >> "$dir/makebackground.msl" <<EOF
            <composite image="$count2" geometry="$region" />
EOF
    done
    cat >> "$dir/makebackground.msl" <<EOF
        </image>
        <write filename="$dir/background.png"/>
    </group>
EOF
    # Now we've built the command file, do it :-
    $conjure "$dir/makebackground.msl"
}

pidfile="/var/tmp/${scriptname}.$(whoami)"
# A fixed name for storing the PID in ... so we can kill off the previous
# script easily!
killold

echo $$ > $pidfile

choice=$1
#  Just give it a sensible name
if [[ -z "$choice" ]]
then
  usage
  exit 1
fi
dir=$(expandtilde $dir)
#  Get this expansion out of the way - "~" isn't a native filepath thing but interpreted by the shell and not always.

routput=$(xrandr)
#	Get the output of xrandr
if [[ "$?" != 0 ]]
then
  echo Failed to get the output of xrandr. This script requires that.
  exit 1
fi

fullsize=$(echo $routput | awk '/^Screen 0:/ {print $8, $10}' | sed -e 's/,//')
regions=$(echo $routput | awk --lint '{for (i = 1; i <= NF; i++) {if ($i ~ /connected/) {print $(i+1)}}}')
#   Identify the overall size, and the regions within the overall size. This doesn't
#   deal with multiple screens though. And has only been tested with two regions.
makecanvas
#   Make a blank canvas to draw onto.

#echo Size: $fullsize, regions: $regions

case $choice in 
  "webcollage")
	# Special case #1 .. run webcollage
	webcollage
	;;
  *)
	# The default case ...
	#	The first parameter is the sub-directory from which the
	#	images are selected. This is assumed to be a way of selecting
	#	between different types of images - "my photos", "pics of
	#	cats", etc.
	if [ ! -d "$dir/$choice" ]
	then
	  echo $dir/$choice is not a directory.
	  if [ ! -d "$dir/default" ]
	  then
	    exit 1
	  else
	    choice="default"
	    echo Choosing a default directory $dir/$choice instead.
	  fi
	fi
        # Above tries to ensure we have a sensible directory (hopefully
	# containing interesting background images) to work with ...
        orientimages $dir/$choice
        #   Build the two arrays with the images - horizontal and vertical

	while true
	do
	    makebackground
	    if [ -f "$dir/background.png" ]
	    then
		$chbg "$dir/background.png"
		sleep $delay
		rm "$dir/background.png"
	    else
		echo No background to draw
		exit 1
	    fi
	done


        #  randelement=$[${RANDOM}%${#images[*]}]
        #  # That inscrutable bit of shell noise picks a random element out of the array.
	#  $chbg $dir/$choice/${images[$randelement]}
	#  sleep $delay
	        # And now keep changing the background!
esac
