#!/bin/bash
#set -n		# read but do not execute commands (check on syntax errors)
#
# File: /usr/local/bin/makeslideshow
#
# Create a video slideshow from a set of images.
#
#    Copyright (C) 2000  Juergen Kaesmann (JK)
#
##############################################################################
# GPL NOTICE
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
##############################################################################
# FIND SAMPLES
#
##############################################################################
# FILTER SAMPLES
#
##############################################################################
# AWK SAMPLES
#
##############################################################################
# SED SAMPLES
#
##############################################################################
# RSYNC OPTIONS
#
##############################################################################
# DIALOG SAMPLES
#
##############################################################################
# REPLACE STRINGS
#
##############################################################################
# EXIT CODES

##############################################################################
# SOURCE FILES
#
. /usr/local/etc/main.conf				# config main
#. $LLIBDIR/libfuncerr-sh				# functions error
. $LLIBDIR/libfuncstd-sh				# functions standard
#. $LLIBDIR/libfuncmath-sh				# functions math
#. $LLIBDIR/libfuncip-sh				# functions IP
#. /usr/local/etc/sample.conf				# config sample

#if [ ! -e ~/.samplerc ]; then				# install config user
#	cp /usr/local/share/ksm-sample/samplerc ~/.samplerc
#	echo "Please configure your ~/.samplerc"
#	exit 1
#fi
#. ~/.samplerc						# config user

##############################################################################
# DECLARATION OF STANDARD CONSTANTS AND VARIABLES
#
readonly package=Multimedia				# package name
readonly package_file=ksm-multimedia			# package file name
readonly vinfopath="/usr/local/share/$package_file"	# path to package dir
readonly version=$(/bin/cat $vinfopath/VERSION)		# package version
readonly release=$(/bin/cat $vinfopath/RELEASE)		# package release
readonly scriptname=$(basename $0)			# name of script
#readonly tempfile=$TEMPDIR/$scriptname.$UID.tmp	# temporary file name
#readonly tempfile=$(mktemp -u $TEMPDIR/$scriptname.$UID.XXXXXX) # temporary file name
#readonly lockfile=$TEMPDIR/lock/$scriptname.$UID.lock	# lock file name
readonly debuglog="/usr/bin/logger -p user.debug -t $scriptname -- DEBUG:"	# log dbg msg
readonly errlog="/usr/bin/logger -p user.err -t $scriptname -- ERROR:"		# log err msg
readonly infolog="/usr/bin/logger -p user.info -t $scriptname -- INFO:"		# log inf msg
cmd=''							# sub command
debug=no						# debug=yes/no
verbose=''						# verbose=yes/''/no
err=${_ERR_OK_}						# error code

##############################################################################
# USER FILL IN AT FIRST RUN

##############################################################################
# SYSTEM

##############################################################################
# USER-CONSTANTS

##############################################################################
# USER-VARIABLES
#
# STRINGS
tempfile=$TEMPDIR/$scriptname.$UID.mp4

#args=''				# all args from cmdline
arg1=''					# 1. arg from cmdline
arg2=''					# 2. arg from cmdline
#opt_o=''				# option -o (yes)
					# option --output (yes)
#opt_i=''				# option -i (arg)
					# option --infile (arg)
#opt_o=''				# option -o (arg)
					# option --outfile (arg)
#opt_p=''				# option -p (arg)
					# option --pages (arg)
opt_e=''				# option -e (arg)
opt_m=''				# option -m (arg)
opt_t=''				# option -t (arg)

# NUMBERS
#p_first=0				# first page
#p_last=0				# last page

# ARRAYS
# Indexed arrays are always zero based string arrays.
# If index starts with 1 and all members are assigned then
# count of members of array = last index of array
#declare -a arr
#maxarr="${#arr[@]}"			# get number of elements in arr
#unset arr[@]				# remove the entire array

##############################################################################
# SIGNAL HANDLING

##############################################################################
# FUNCTIONS
##############################################################################
#
#=============================================================================
function helptext ()
{
# Output helptext
# Uses cat, echo, logger
# Return codes:
# Standard

if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG helptext: $# $@" >&2
	$debuglog helptext: $# $@
fi

cat <<EOT
NAME
$scriptname - Create a video slideshow from a set of images.

SYNOPSIS
$scriptname [options] [outfile]

DESCRIPTION
Ceate a video slideshow from a set of jpeg images. Each image will stay
for 5 (default) seconds on the screen. You may apply a crossfade effect
and music to the video.

Use image names in the format img-000001.jpg in actual dir. The number
should have 6 digits, starting with '1' in uninterrupted increasing
numbers.

All images should have an equal size and equal direction.

The image type should be jpeg with pixel format yuv420p. Gimp f.i.
produces yuvj444p. Therefore it is better to use tools from the netpbm
package for final conversion needs.

The video size and aspect ratio depends on the image size. Framerate is
25 fps. Videocodec is H264, optional audiocodec is AAC. The outfile is
always overwritten.

Sound and amount of images have to calculated so that both should reach
the end in common. If both, length of images and length of sound,
differ then it is best that length of images should be greater, so that
all images are seen. In all cases time of the shortest stream is used.

XFADE EFFECTS
We can use an image change effect with the xfade filter (option -e).
Following effects are implemented:

-   0 = random effect
-   1 = fade
-   2 = wipeleft
-   3 = wiperight
-   4 = wipeup
-   5 = wipedown
-   6 = slideleft
-   7 = slideright
-   8 = slideup
-   9 = slidedown
-  10 = circlecrop
-  11 = rectcrop
-  12 = distance
-  13 = fadeblack
-  14 = fadewhite
-  15 = radial
-  16 = smoothleft
-  17 = smoothright
-  18 = smoothup
-  19 = smoothdown
-  20 = circleopen
-  21 = circleclose
-  22 = vertopen
-  23 = vertclose
-  24 = horzopen
-  25 = horzclose
-  26 = dissolve
-  27 = pixelize
-  28 = diagtl
-  29 = diagtr
-  30 = diagbl
-  31 = diagbr
-  32 = hlslice
-  33 = hrslice
-  34 = vuslice
-  35 = vdslice
-  36 = hblur
-  37 = fadegrays
-  38 = wipetl
-  39 = wipetr
-  40 = wipebl
-  41 = wipebr
-  42 = squeezeh
-  43 = squeezev

ATTENTION
The ffmpeg function is very sensitive to errors in the images. Maybe
that the images (jpg) need to resample manually.

OPTIONS
Gnu style options:

  -h|--help    = Output help, then exit.
  -V|--version = Output version info, then exit.
  -d|--debug   = Turn on DEBUG mode.
  -q|--quiet   = Be quiet.
  -v|--verbose = Be verbose.
  -e ef        = Use image change effect <ef>. From each image there
                 will be at start 1 sec xfade and at end 1 sec xfade.
                 So the clear visible time is <tm> - 2 secs.
  -m mf        = Music file <mf> which accompanies the slideshow.
  -s           = Make slideschow only with the first 2 images. Don't
                 give a music file.
  -t tm        = Time in secs to stay <tm> for each image (def. = 5).
                 If we don't use an effect then
                   summerized length of all images is calculated like:
                   len = cnt x <tm>
                 else If we use an effect (-e) then
                   summerized length of all images is calculated like:
                   len = cnt x (<tm> - 1)
                 If you use an effect (-e) then
                   calculate the clear visible time as follows:
                   time = <tm> - 1 sec start_xfade - 1 sec end_xfade.
                   If f.i. you want each image to stay 5 clear visible
                   seconds without effect then you should set <tm> to 7
  --           = End of options.

ARGUMENTS
Give if needed:

 outfile = The video to create (.mp4).

EXAMPLES
For instance:

  Make a slideshow without effect. Each image should stay vor 5 
  (default) secs:
  $scriptname outfile.mp4

  Make a slideshow without effect. Each image should stay vor 10 secs:
  $scriptname -t 10 outfile.mp4

  Make a slideshow with effect 1. Each image should stay vor 5 clear
  visible secs. Use music file mymusic.mp3:
  $scriptname -e 1 -t 7 -m mymusic.mp3 outfile.mp4

  Make a test slideshow with effect 1. Show the result with ffmplay:
  $scriptname -s -e 1 outfile.mp4

EXIT STATUS
On program exit:

  Code 0 = OK

  See output of 'showerrmsg'.

SEE ALSO
Related manpages:

  showerrmsg(1), ffmpeg(1).

AUTHORS
Juergen Kaesmann <juergen@kaesmann-online.de>
EOT
#  -o|--output  = Output to STDOUT.
#  -i f         = Input from file <f>.
#  --infile=f   = Input from file <f>.
#  -o f         = Output to file <f>.
#  --outfile=f  = Output to file <f>.
#  -p s,e       = Pages s=START e=END.
#  --pages=s,e  = Pages s=START e=END.

#FILES
#Used directories and files:
#
#  Config Global = /usr/local/etc/sample.conf
#  Config User   = ~/.samplerc

return
}

#=============================================================================
function get_random ()
{
# Give a random number in the range of 1 - 43.
# par1 = 
# Uses echo, logger
# Return codes:
# Standard

if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG get_random: $# $@" >&2
	$debuglog get_random: $# $@
fi

local r=0 l=0 ret=0

while [ $r -lt 1 ] || [ $r -gt 43 ]; do
	r=$(echo $RANDOM)
	l=${#r}
	case $l in
	    1)	l=0; r="0$r";;
	    2)	l=0;;
	    3)	l=1;;
	    4)	l=2;;
	    5)	l=3;;
	esac
	r=${r:$l:2}
	if [ ${r:0:1} -eq 0 ]; then
		r=${r:1:1}
	fi
done
Push "$r"
ret=$?

return $ret
}

#=============================================================================
function get_xfade_effect ()
{
# Return the corresponding xfade effect of a number.
# par1 = number of effect.
# Uses echo, logger
# Push the xfade effect name onto stack.
# Return codes:
# Standard

if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG get_xfade_effect: $# $@" >&2
	$debuglog get_xfade_effect: $# $@
fi

local num="$1" ret=0

case $num in
    1)	Push fade; ret=$?;;
    2)	Push wipeleft; ret=$?;;
    3)	Push wiperight; ret=$?;;
    4)	Push wipeup; ret=$?;;
    5)	Push wipedown; ret=$?;;
    6)	Push slideleft; ret=$?;;
    7)	Push slideright; ret=$?;;
    8)	Push slideup; ret=$?;;
    9)	Push slidedown; ret=$?;;
    10)	Push circlecrop; ret=$?;;
    11)	Push rectcrop; ret=$?;;
    12)	Push distance; ret=$?;;
    13)	Push fadeblack; ret=$?;;
    14)	Push fadewhite; ret=$?;;
    15)	Push radial; ret=$?;;
    16)	Push smoothleft; ret=$?;;
    17)	Push smoothright; ret=$?;;
    18)	Push smoothup; ret=$?;;
    19)	Push smoothdown; ret=$?;;
    20)	Push circleopen; ret=$?;;
    21)	Push circleclose; ret=$?;;
    22)	Push vertopen; ret=$?;;
    23)	Push vertclose; ret=$?;;
    24)	Push horzopen; ret=$?;;
    25)	Push horzclose; ret=$?;;
    26)	Push dissolve; ret=$?;;
    27)	Push pixelize; ret=$?;;
    28)	Push diagtl; ret=$?;;
    29)	Push diagtr; ret=$?;;
    30)	Push diagbl; ret=$?;;
    31)	Push diagbr; ret=$?;;
    32)	Push hlslice; ret=$?;;
    33)	Push hrslice; ret=$?;;
    34)	Push vuslice; ret=$?;;
    35)	Push vdslice; ret=$?;;
    36)	Push hblur; ret=$?;;
    37)	Push fadegrays; ret=$?;;
    38)	Push wipetl; ret=$?;;
    39)	Push wipetr; ret=$?;;
    40)	Push wipebl; ret=$?;;
    41)	Push wipebr; ret=$?;;
    42)	Push squeezeh; ret=$?;;
    43)	Push squeezev; ret=$?;;
    *)	echo "${ErrMsg[9]} Option -e $opt_e" >&2; ret=9;;
esac

return $ret
}

#=============================================================================
function short_slideshow ()
{
# Produce a short slideshow with 2 images and show it with ffplay.
# par1 = 
# Uses echo, logger
# Return codes:
# Standard

if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG short_slideshow: $# $@" >&2
	$debuglog short_slideshow: $# $@
fi

local fadename=''
local ret=0

get_xfade_effect "$opt_e"
ret=$?
if [ $ret -eq 0 ]; then
	Pop fadename
	ret=$?
	if [ $ret -eq 0 ]; then
		ffmpeg -hide_banner -y \
		-loop 1 -t 5 -i img-000001.jpg -loop 1 -t 5 -i img-000002.jpg \
		-filter_complex xfade=transition=${fadename}:duration=1:offset=4 \
		-c:v libx264 -r 25 -pix_fmt yuv420p $tempfile

		ffplay -hide_banner -fs $tempfile
		rm -f $tempfile
	fi
fi

return $ret
}

#=============================================================================
function mainproc ()
{
# Sample function.
# par1 = 
# Uses echo, logger
# Return codes:
# Standard

if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG mainproc: $# $@" >&2
	$debuglog mainproc: $# $@
fi

local s='' input='' filter='' fadename='' eff=''
local i=0 j=0 maximg=0 off=0 fd=0 ret=0
#local -a arr
#maxarr="${#arr[@]}"			# get number of elements in arr
#unset arr[@]				# remove the entire array

# man-all ffmpeg:
# pictures should start with 1 in uninterrupted increasing numbers.
# %06d means image number has 6 digits with leading zeroes
# -framerate 1/5 means each image stays for 5 seconds

#ffmpeg -i first.jpg -i second.jpg -filter_complex xfade=transition=fade:duration=1:offset=4 outfile.mp4

if [ -z "$opt_e" ]; then				# without xfade
	if [ -n "$opt_m"]; then				# with audio
		ffmpeg -hide_banner -framerate 1/$opt_t -i img-%06d.jpg -i $opt_m -shortest -c:v libx264 -r 25 -pix_fmt yuv420p -c:a aac -y $arg1
	else						# without audio
		ffmpeg -hide_banner -framerate 1/$opt_t -i img-%06d.jpg -c:v libx264 -r 25 -pix_fmt yuv420p -y $arg1
	fi
	ret=$?
else							# with crossfade
	if [ $opt_e -ge 1 ] && [ $opt_e -le 43 ]; then
		get_xfade_effect "$opt_e"
		ret=$?
		if [ $ret -eq 0 ]; then
			Pop fadename
			ret=$?
		fi
	fi

	maximg=0
	off=0
	fd=0
	j=0
	i=1
	if [ -n "$opt_m" ]; then			# with audio
		for s in img-*.jpg; do
			let maximg++
			input+=" -loop 1 -t $opt_t -i $s"
		done
		let maximg--
		let opt_t--

		for s in img-*.jpg; do
			if [ $ret -eq 0 ] && [ $i -le $maximg ]; then
				if [ $opt_e -eq 0 ]; then # get random effect
					get_random
					ret=$?
					if [ $ret -eq 0 ]; then
						Pop eff
						ret=$?
						get_xfade_effect "$eff"
						ret=$?
						if [ $ret -eq 0 ]; then
							Pop fadename
							ret=$?
						fi
					fi
				fi
				off=$[$i*$opt_t]
				if [ $i -eq 1 ]; then
					filter="[0][$i]xfade=transition=${fadename}:duration=1:offset=${off}[f$j];"
				else
					fd=$[$j-1]
					filter+="[f$fd][$i]xfade=transition=${fadename}:duration=1:offset=${off}[f$j];"
				fi
			fi
			let i++
			let j++
		done
		filter=${filter%[*}

		if [ $ret -eq 0 ]; then
			ffmpeg -hide_banner -y \
			$input \
			-filter_complex $filter \
			-i $opt_m -shortest -c:v libx264 -c:a aac -r 25 -pix_fmt yuv420p $arg1
		fi
	else						# without audio
		for s in *.jpg; do
			let maximg++
			input+=" -loop 1 -t $opt_t -i $s"
		done
		let maximg--
		let opt_t--

		for s in *.jpg; do
			if [ $ret -eq 0 ] && [ $i -le $maximg ]; then
				if [ $opt_e -eq 0 ]; then # get random effect
					get_random
					ret=$?
					if [ $ret -eq 0 ]; then
						Pop eff
						ret=$?
						get_xfade_effect "$eff"
						ret=$?
						if [ $ret -eq 0 ]; then
							Pop fadename
							ret=$?
						fi
					fi
				fi
				off=$[$i*$opt_t]
				if [ $i -eq 1 ]; then
					filter="[0][$i]xfade=transition=${fadename}:duration=1:offset=${off}[f$j];"
				else
					fd=$[$j-1]
					filter+="[f$fd][$i]xfade=transition=${fadename}:duration=1:offset=${off}[f$j];"
				fi
			fi
			let i++
			let j++
		done
		filter=${filter%[*}

		if [ $ret -eq 0 ]; then
			ffmpeg -hide_banner -y \
			$input \
			-filter_complex $filter \
			-c:v libx264 -r 25 -pix_fmt yuv420p $arg1
		fi
	fi
	ret=$?
fi

return $ret
}

##############################################################################
# GET OPTIONS
##############################################################################
# Give 2 strings and all cmdline_args to func Get Opt
# (POSIX_options Gnu_long_options cmdline_args):
# Get Opt 'hVdqvi:m:' 'help version debug quiet verbose infile= myval=' $@
#
# A ':' after a POSIX option means this option needs an arg.
# A '=' after a Gnu long option means this option needs an arg.
#
# All cmd/options have to be initialised to ''!
#
# Options are divided in 2 classes:
#   a) cmds (mutually exclusive). All cmds are given to var 'cmd'.
#   b) options (as many as you like). Each option is given to it's own var.
# As a general rule: If cmds/options are given multiple then last given wins.
#
# Options can take 1 argument (no whitespace in arg). If you want to give more
# than 1 arg or want to use multiple strings as 1 arg then concatenate them
# together with a delimiter like ',' or ';' or '.'
# Use a delimiter which will not be part of the arg:
# sampleprog -m val1,val2
# sampleprog --myval=val1,val2
# It's at the programmers responsibility to do meaningfull things with the
# content of the options.
#
# While err = 0 then look for a next option.
# When Get Opt finishes then all options are removed from cmdline.
#
if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG Parse Commandline: $# $@" >&2
	$debuglog Parse Commandline: $# $@
fi
#
err=0
while [ "$err" -eq 0 ]; do
	GetOpt 'hVdqve:m:st:' 'help version debug quiet verbose' $@
	err=$?
	#echo "DEBUG GET OPTIONS: err=${err}  _OPTNAME_=${_OPTNAME_}  _OPTVAL_=${_OPTVAL_}  _OPTPOS_=${_OPTPOS_}  _OPTIDX_=${_OPTIDX_}" >&2
	if [ $err -eq 0 ]; then
		case "$_OPTNAME_" in
		    h|help)	cmd="-h";;
		    V|version)	cmd="-V";;
		    s)		cmd="-${_OPTNAME_}";;
		    d|debug)	debug=yes;;
		    q|quiet)	verbose=no;;
		    v|verbose)	verbose=yes;;
		    e)		opt_e="${_OPTVAL_}";;
		    m)		opt_m="${_OPTVAL_}";;
		    t)		opt_t="${_OPTVAL_}";;
#		    o|output)	opt_o=yes;;
#		    i|infile)	opt_i="${_OPTVAL_}";;
#		    outfile)	opt_outfile="${_OPTVAL_}";;
#		    p|pages)	opt_p="${_OPTVAL_}";;
		    --)		break;;
		    :)	if [ "$verbose" != no ]; then
				echo "${ErrMsg[8]} -${_OPTVAL_}" >&2
			else
				$errlog ${ErrMsg[8]} -${_OPTVAL_}
			fi; exit 8;;
		    ?)	if [ "$verbose" != no ]; then
				echo "${ErrMsg[4]} -${_OPTVAL_}" >&2
			else
				$errlog ${ErrMsg[4]} -${_OPTVAL_}
			fi; exit 4;;
		    *)	if [ "$verbose" != no ]; then
				echo "${ErrMsg[99]} _OPTNAME_=${_OPTNAME_} _OPTVAL_=${_OPTVAL_}" >&2
			else
				$errlog ${ErrMsg[99]} _OPTNAME_=${_OPTNAME_} _OPTVAL_=${_OPTVAL_}
			fi; exit 99;;
		esac
	fi
done
err=0
shift ${_OPTIDX_}				# rm all opts from cmdline
# Uncomment if giving a cmd is mandatory
#if [ -z "$cmd" ]; then					# error no cmd given
#	if [ "$verbose" != no ]; then
#		echo "${ErrMsg[7]}" >&2
#	else
#		$errlog ${ErrMsg[7]}
#	fi
#	exit 7
#fi

##############################################################################
# CHECK LINK NAMES

##############################################################################
# CHECK OPTIONS
#
#-----------------------------------------------------------------------------
# check not allowed option for sub commands
#case "$cmd" in
#    -l|-p)						# for these cmds
#	if [ -n "$opt_z" ]; then			# option -z not allowed
#		Show_Err ${_ERR_OPT_NOT_ALLOWED_} "-z"
#		exit ${_ERR_OPT_NOT_ALLOWED_}
#	fi
#	;;
#    *)							# for all other cmds
#	:
#	;;
#esac
#
#-----------------------------------------------------------------------------
# check allowed option for sub commands
#if [ -n "$opt_z" ]; then
#	case "$cmd" in
#	    -l|-p)					# for these cmds
#		:					# option -z allowed
#		;;
#	    *)						# for all other cmds
#		Show_Err ${_ERR_OPT_NOT_ALLOWED_} "-z"
#		exit ${_ERR_OPT_NOT_ALLOWED_}
#		;;
#	esac
#fi
#
#-----------------------------------------------------------------------------
# check needed option for sub commands
case "$cmd" in
    -s)							# for these cmds
	if [ -z "$opt_e" ]; then			# option -e needed
		Show_Err "Missing option -e"
		exit 1
	fi
	;;
    *)							# for all other cmds
	:
	;;
esac
#
#-----------------------------------------------------------------------------
# check options which are mutually exclusive
#if [ -n "$opt_x" ] && [ -n "$opt_y" ]; then		# don't give both opts
#		Show_Err ${_ERR_OPT_NOT_ALLOWED_} "-x and -y given"
#		exit ${_ERR_OPT_NOT_ALLOWED_}
#fi
#
#-----------------------------------------------------------------------------
# check option which needs another option
#if [ -n "$opt_x" ]; then			# opt_x given
#	if [ -z "$opt_y" ]; then		# error - opt_x needs opt_y
#		Show_Err ${_ERR_GENERAL_} "-x needs -y"
#		exit ${_ERR_GENERAL_}
#	fi
#fi
#
#-----------------------------------------------------------------------------
# check options which needs to give at least one of them
#case "$cmd" in
#    '')
#	if [ -z "$opt_x" ] && [ -z "$opt_y" ]; then	# no option given
#		Show_Err ${_ERR_GENERAL_} "give -x and/or -y"
#		exit ${_ERR_GENERAL_}
#	fi
#esac
#
#-----------------------------------------------------------------------------
# check arguments of option -x
#if [ -n "$opt_x" ]; then
#	case "$opt_x" in
#	    A|B|C)	:
#		;;
#	    *)	Show_Err 1 "Wrong argument for option -x"
#		exit ${_ERR_GENERAL_}
#		;;
#	esac
#fi
#-----------------------------------------------------------------------------
# get values from arg of option -p to vars p_first p_last
#if [ -n "$opt_p" ]; then
#	p_first="${opt_p%,*}"
#	p_last="${opt_p#*,}"
#fi

##############################################################################
# CHECK VERSION

##############################################################################
# CHECK ARGUMENTS
#
case "$cmd" in
    '')
	if [ "$#" -eq 1 ]; then				# parameter count ok
		arg1="$1"
		shift
		#args="$@"
		#shift $#
	else						# error in param count
		if [ "$verbose" != no ]; then
			echo "${ErrMsg[2]}" >&2
		else
			$errlog ${ErrMsg[2]}
		fi
		exit 2
	fi
	;;
    *)
	if [ "$#" -ne 0 ]; then				# error in param count
		if [ "$verbose" != no ]; then
			echo "${ErrMsg[2]}" >&2
		else
			$errlog ${ErrMsg[2]}
		fi
		exit 2
	fi
	;;
esac

##############################################################################
# LOCK

##############################################################################
# MAINPROGRAM
##############################################################################
#
if [ "$debug" == "yes" ]; then				# DEBUG
	echo "DEBUG Main: $# $@" >&2
	$debuglog Main: $# $@
fi

if [ -z "$opt_t" ]; then
	opt_t=5
fi

# Check what to do (sub commands, options and args are removed from cmdline)
case "$cmd" in
    '')							# no cmd given
	mainproc
	err=$?
	;;
    -s)
	short_slideshow
	;;
    -h)
	helptext
	err=0
	;;
    -V)
	echo "${scriptname}: (${package}) $package_file ${version}-${release}"
	exit 0
	;;
    *)							# other cmds = error
	if [ "$verbose" != no ]; then
		echo "${ErrMsg[6]}" >&2
	else
		$errlog ${ErrMsg[6]}
	fi
	err=6
	;;
esac

#rm -f $lockfile

exit $err
