#!/usr/bin/env bash
ME="[todisc]:"
. tovid-init 2>/dev/null ||
{ echo -e "===============================================================\n"
echo -e "'tovid-init' not found.  Was tovid improperly installed?"
echo -e "Or are you trying to run the script directly?"
echo -e "Please run todisc as:\ntovid disc OPTIONS"
exit 1 ; }
# todisc
# Part of the tovid suite
# =======================
# A bash script for generating a DVD
# with many styles of animated and static menus,
# from a collection of MPEG video files.
#
# Project homepage: http://tovid.wikia.com
#
# Copyright (C) 2005-2015
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA. Or see:
#
#     http://www.gnu.org/licenses/gpl.txt

# Mostly written by Robert Sohn:
#     <grepper@gmail.com>
#     grepper on irc.freenode.net

SCRIPT_NAME=`cat << EOF

--------------------------------
tovid disc
Generate a DVD file-system with optional menus, from a list of multimedia files.
Menus can be moving or static thumbnails, or text.  Encoding done automatically.

Version $TOVID_VERSION
$TOVID_HOME_PAGE
--------------------------------

EOF`

USAGE=`cat << EOF
Usage:
    tovid disc [OPTIONS] \\\\
      -files File1.mpg File2.avi ... \\\\
      -titles "Title 1" "Title 2" ... \\\\
      -menu-title "Tovid Demo" \\\\
      -out OUT_DIRECTORY

You can also do slideshows using -slides IMAGES rather than -files VIDEOS
General Options:
    -no-ask, -no-warn, -keep-files, -jobs, -grid, -no-confirm-backup
Other quick examples:
Create 'text menu' DVD filesystem:
    tovid disc -text-menu -files ... -titles .. -out OUT_DIRECTORY
Create DVD filesystem with no menu, encoding with ffmpeg and prompt for burn:
    tovid disc -files *.mp4 -ffmpeg -no-menu -burn -out OUT_DIRECTORY
Create DVD compatible mpeg2 files using makempg (and ffmpeg) and then quit:
    tovid disc -encode-only -ffmpeg -quality 8 -files *.avi (no -out required)
See the tovid manual page ('man tovid') for additional documentation.

EOF`
# check that needed todisc deps are installed
assert_dep "$todisc_deps"
assert_dep strings "'strings' is part of binutils.  In most distros the package
is called binutils. http://www.gnu.org/software/binutils/ ."
SCRIPT_START_TIME=`date +%s`

# check if symlink in /tmp exists and use time stamped link if so
WORK_DIR="/tmp/todisc-work"
LOG_FILE=$(readlink -f todisc.log)
OUT_DIRECTORY=""
TV_STANDARD=ntsc
PIXEL_AR="10:11"
MENU_LEN=( 20 )
USER_MENU_LEN=false
USER_SUBMENU_LEN=false
SUBMENU_LEN=(10)
MAX_MENU_LEN=""
TARGET=dvd
FRAME_RATE=29.970 # for bc. mjpegtools and transcode convert this to 30000/1001
ff_frame_rate="30000/1001" # ffmpeg needs to be explicitly told exact framerate
VIDSIZE=720x480
VF_SCALE=${VIDSIZE%x*}:${VIDSIZE#*x}
MENU_TITLE="My Video Collection"
STATIC=false
SUB_MENU=false
ANI_SUB_MENU=false
TITLE_CLR="#EAEAEA"
SM_TITLE_CLR="#EAEAEA"
THUMB_BG_CLR=white
TITLES_CLR=""
BUTTON_STYLE="line"
MIST_COLOUR=white
MIST_OPACITY=60
M_TITLE_STROKE=""
SUBMENU_STROKE="none"
BG_AUDIO=""
BG_PIC=""
BG_VIDEO=""
SHOWCASE=false
SUBMENU_AUDIO=false
SM_AUDIO_FADE=:
SM_FADE=1
AUDIO_FADE=:
OPACITY=100
MENU_FADE=false
FIRST_PIC=0
TRANSPARENT=false
PREVIEW=:
PAUSE_TIME=10
USER_LOOP=false
MIST=false
FEATHER=false
THUMB_BLUR=1
SC_BLUR=1
SUB_MENU_FEATHER=false
IMG_FMT="png"
SM_IMG_FMT="png"  # submenu image format
KEEP_FILES=false
THUMB_SHAPE=""
SEEK_VAL=2
USER_SEEK_VAL=false
FADE=1
CHAPTERS=( 6 )
TOVID_OPTS=()
CHAIN_VIDEOS=false
NOASK=false
SC_FRAMESTYLE="none"
THUMB_FRAME_SIZE="3x3"
THUMB_FRAME_CLR='#444744'
SHOWCASE_FRAME_SIZE=4x4
SHOWCASE_FRAME_CLR='#6E6E6E'
SHOWCASE_VIDEO=""
THREExONE=false
FOURxONE=false
PLAYALL=false
AUTHOR_PLAYALL=false # needed for VMGM playall logic
THUMBS_3D=false
SHOWCASE_3D=false
RAISE=""
CURVE_UPDATE=""
SUBTITLES=false
USER_BSTYLE=false
SHOWCASE_SEEK_VAL=2
BG_SEEK=2
BG_AUDIO_SEEK=2
USER_BG_AUDIO_SEEK=false
USER_SM_AUDIO_SEEK=false
SC_THUMB=:
TEXTMENU=false
SC_TITLE_ALIGN="center"
EDGE_JUSTIFY=false
ALIGN_OVERRIDE=false
MULTILINE_TITLE=false
SAFE_AREA=50 # undocumented: you can set this from CLI with -showcase-safe-area
SAFE_OFFSET=0 # we only add this offset if center title align, to keep onscreen
ASPECT_RATIO=4:3
AR=1.333
ASPECT_ARG=all
WIDE_SCREEN=false
WIDESCREEN="nopanscan"
GROUP_ARR=""
GROUPING=false
TEXT_YSTART=$SAFE_AREA
BUTTON_GRAVITY=north
XGEO=0
YGEO=45
USER_GRAVITY=false
USER_SPLIT=false
TITLE_GRAVITY=south
SPACER=15
SELECT_CLR="#DE7F7C"
HLIGHT_CLR="#266CAE"
USER_SC_GEO=false
USER_SAFE_AREA=false
USER_TITLE_GEO=false
SPACER=""
SE_YCORNER=0
WARN=true
ROTATE_THUMBS=false
DO_TITLESETS=false
AUTHOR=:
ts_start=0
args=( "$@" )
VMGM_ONLY=false
TITLESET_MODE=false
TSET_NUM=1
MENU_NUM=1
INTRO=""
QUICK_NAV=false
SKIP_VMGM_MENU=false
VMGM_MENU=:
# recursing titlesets need to set logic for returning to root menu (playall)
VMGM_PLAYALL=false
MONTAGE_MENU=:
NO_TOP_MENU=false
DO_MENU=:
DO_STATS=:
DO_FRAME=:
DO_BUTTONS=:
SWITCHED_MENUS=false
SWITCHED_MODE=false
SWITCHED=false
TSET_MODE=false
TSET_TOT=1
NONAME=false
DO_INTRO=false
USE_MPLAYER_4AUDIO=false
MENU_AUDIOLEN=""
USER_AUDIOLENGTH=false
BURN=false
EJECT=''
BURN_PROG="makedvd"
BURN_DEVICE="/dev/dvdrw"
QUICK_MENU=false
BG_CLR='#101010'
SUBMENU_BG_CLR='#101010'
QM_PREVIEW=false
USER_CHAPTERS=false
QUICKMENU_IS_SHOWCASE=false
QUICKMENU_IS_BACKGROUND=false
CAROUSEL_IS_BG=false
CAROUSEL_IS_SHOWCASE=false
RESIZE_BG=false
DO_CAROUSEL=false
is_carousel=false
UNDERCOLOUR="000000"
SLIDE_FADE=false
SINGLE_SLIDESHOW=false
MK_CAROUSEL_MODE=false
MTG_GEO="+12+6"
VIDEOS_ARE_CHAPTERS=false
CONFIRM_BACKUP=:
USE_FEATHER_MASK=false
DO_BINNING=:
BINMAX=640
USE_FFMPEG=:
USE_DVD_SLIDESHOW=false
SLIDE_BLUR_OPT="0x0.4"
USERS_BACKGROUND=false
SFRAME_CLR="#EAEAEA"
EFFECT="crossfade"
num_bgpics=0
num_scpics=0
TRANSITION_TO_MENU=false
DEBUG=false
pngpipe="-quality 01 png:-"
ani_pics=0
use_vhooks=false
use_overlay_filter=false
JUSTIFY="center"
CONTRAST_CLR='gray'
NOMENU=false
ENCODE_ONLY=false
SC_AR=133
THUMB_COLUMNS=""
FAST_SEEK=false # ffmpeg: default:decode during seek (more accurate but slower)
USER_THUMBS=false # is user providing images for the menu link thumbs ?
FRAME_SAFE=false # (-static) if true take the best of 9 frames. default 1 frame
USE_V_TITLES_DECO=false
USE_M_TITLE_DECO=false
PIPE_FORMAT=""
IMG_DEPTH="-depth 8" # when converting to png: ppmtoy4m needs 8 bit
AUDIO_EXT="ac3"
SAMPLERATE="48000"
AUDIO_OPTS="-ab 224k -ar $SAMPLERATE -acodec $AUDIO_EXT"
MPLEX_FORMAT="8"
FROM_GUI=false # needed to disable tput (colour output) in GUI
TOVID_PREFIX=$(tovid -prefix)
use_transcode=:
yuv_correct="yuvcorrect -T NO_HEADER"

##############################################################################
#                                 Functions                                  #
##############################################################################

# Y-echo: print to two places at once (stdout and logfile)
# Output is preceded by the script name that produced it
# Args: $@ == any text string
# If no args are given, print a separator bar
# If empty string is the arg, print a newline
# Use yecho if you want output to go to the logfile
yecho()
{
    # arg supplied but empty (""): just print a newline
    if [[  "${1+defined}" && -z $1 ]]; then
        printf "\n"
        [[ -e "$LOG_FILE" ]] && printf "\n" >> "$LOG_FILE"
    # no arg supplied at all, just 'yecho': print \n[todisc]:\n
    elif test $# -eq 0; then
        printf "\n%s\n\n" "$SEPARATOR"
        # If logfile exists, copy output to it (with pretty formatting)
        test -e "$LOG_FILE" && \
        printf "%s\n%s %s\n%s\n" "$ME" "$ME" "$SEPARATOR" "$ME" >> "$LOG_FILE"
    else
        sed "s/    */ /g;s/^ *//" <<< "$@" | fold -bs
        test -e "$LOG_FILE" && \
            printf "%s %s\n" "$ME" "$@" | sed "s/    */ /g;s/^ *//" |
            fold -bs >> "$LOG_FILE"
    fi
}

# Print script name, usage notes, and optional error message, then exit.
# Args: $@ == text string(s) containing error message and help
usage_error()
{
    MESSAGE=( "$@" )
    printf "%s\n%s\n%s\n\n" "$USAGE" "$SEPARATOR" "***"
    for ((i=0; i<$#; i++)) ; do printf "%s" "${MESSAGE[i]}"; done |format_output
    printf "\n\n%s\n" "***"
    ! $KEEP_FILES && rm -rf "$REAL_WORK_DIR" "$WORK_DIR"
    if $SWITCHED_MODE ||$SWITCHED_MENUS ||$TITLESET_MODE ||$DO_TITLESETS; then
        killall_instances
    fi
    exit 1
}

# Usage: continue_in [SECONDS]
continue_in()
{
    local count LAST
    yecho ""
    (($1)) && LAST=$1 || LAST=5
    for ((i=LAST; i>=0; i--)); do
        ((i==0)) && count='' || count="continuing in $i seconds ..."
        spin $count
        ((i>0)) && sleep 1
    done
}

info_message()
{
    local MESSAGE=$(sed "s/    */ /g;s/^ *//" <<< "$@" | fold -w 60 -bs)
    printgreen "*** Note: ***"
    print2log "$MESSAGE"
    while read -r line; do
        printf "%s\n" "$line"
    done <<< "$MESSAGE"
    printgreen "*************"
}

# print to log, formated with leading/trailing spaces removed
# and prefixed with the script name. [todisc]:
# with no args it just prints [todisc]:, with "" as arg it prints newline
print2log()
{
    local MESSAGE=$(sed "s/    */ /g;s/^ *//" <<< "$@" | fold -w 60 -bs)
    # if "" passed in as arg (ie. defined but empty, print a blank line
    if [[  "${1+defined}" && -z $1 ]]; then
        printf "\n" >> "$LOG_FILE"
    # otherwise print  [todisc]: $line for each line of input
    else
        while read -r line; do
            printf "%s %s\n" "$ME" "$line" >> "$LOG_FILE"
        done <<< "$MESSAGE"
        printf "\n" >> "$LOG_FILE"
    fi
}

# pipe stdout to log prefixed by "[name]:", and ending in newline. 2 opt args
# arg 1:  [name to prefix each line of output]
# arg 2: [fold] fold lines appropriately. Usually you don't fold program stdout.
# uses stdbuf (coreutils) if present so stdin is line buffered
pipe2log()
{
    if [[ $1 ]]; then
        name="[$1]: "
    else
        name="[${0##*/}]: "
    fi
    if [[ $2 && $2 = format ]]; then
        cols=$(( 79 - $(wc -c <<< $name) ))
        ((cols)) || cols=60
        format="fold -w $cols -bs"
    else
        format="cat"
    fi
    $std_buf tr "\015" "\012" < /dev/stdin | $std_buf tr -d "\033" | $format | \
    while read line; do
        printf "%s %s\n" "$name" "$line"
    done >> "$LOG_FILE"
    printf "\n" >> "$LOG_FILE"
}

printgreen()
{
    $FROM_GUI || tput setaf 2
    printf "%s\n" "$@" | sed "s/    */ /g;s/^ *//"
    print2log "$@"
    $FROM_GUI || tput sgr0
    printf ""
}

printred()
{
    $FROM_GUI || tput setaf 1
    printf "%s\n" "$@" | sed "s/    */ /g;s/^ *//"
    print2log "$@"
    $FROM_GUI || tput sgr0
    printf ""
}

titlesafe_error()
{
    (($1 > SAFE_AREA)) && preposition='off the' || preposition='from'
    yecho ""
    printred "***** WARNING *****"
    yecho "video title is $1 pixels $preposition screen edge"
    yecho "Part of the title may not be visible on your tv screen"
    yecho "Perhaps use a smaller -titles-fontsize, or shorten \"${TITLES[i]}\""
    # no need to test $SHOWCASE: default montage will never be offscreen
    if [[ -z $SHOWCASE_FILE && ! $SC_TITLE_ALIGN = east ]]; then
        yecho \
        "You may also use '-showcase-titles-align east' since you are not
        using a -showcase FILE."
    elif ((NUM_FILES >= SPLIT)); then # two columns
        : # insert message here for east offscreen stuff #fixme
    fi
    yecho "****************************"
    $WARN && continue_in 5
}

format_output()
{
    sed "s/    */ /g;s/^ *//"|fold -bs
}

get_font()
{
    # If there is a filename extension, find the absolute path
    if grep -q '\...*$' <<< "$1"; then
        readlink -f "$1"
    # Otherwise, use the literal name
    else
        echo "$1"
    fi
    # TODO: Check for font availability?
}

# get the length of a stream
# usage: stream_length STREAM [type, duration]
# type is either video or audio, duration is the max length to test
# last 2 args are optional: defaults 'video' and the whole stream.
stream_length()
{
	local end=""
    local stream_type=video
    local ff_opts="-an -vcodec copy"
    [[ -n $2 ]] && stream_type=$2
    [[ -n $3 ]] && end="-t $3"
    sed_var="{s/^.*time= *\([^ ]*\).*/\1/p;}"
    stream_name=$stream_type
    if [[ $stream_type = 'audio' ]]; then
        ff_opts="-vn -acodec copy"
    # workaround for avconv which is broken atm wrt getting m2v framerate right
    # overload stream_type to have another meaning, 
    elif [[ $stream_type = 'm2v' ]]; then
        sed_var="{s/^.*frame= *\([^ ]*\).*/\1/p;}"
        stream_name=video
    fi
    print2log "Using $FFmpeg to get accurate $stream_name length of $1"
    local len=$($FFmpeg -i "$1" $end $ff_opts -f null -y /dev/null 2>&1 |
    sed -n "$sed_var" | tail -n 1)
    # sed -n 's/^.*time= *\([^ ]*\).*/\1/p' | tail -n 1)
    if [[ $stream_type = 'm2v' ]]; then
        bc_math "$len / $FRAME_RATE"
    else
        unformat_time $len # no need for echo, prints to stdout
    fi
}

cleanup()
{
    #TODO make a kill_pid function to avoid repetition below
    # and/or consider just using pkill
    echo >&2
    echo "Cleaning up..." >&2
    pids2kill="$impids $smpids $bgfade_pids $title_pids $tcode_pids $encpids"
    for pidfile in "$WORK_DIR/tcode*.pid"; do
        if [[ -s $pidfile ]]; then
            if kill -0 $(<$pidfile) 2> /dev/null; then
                kill $(<$pidfile) 2> /dev/null
                sleep .3
            fi
            if kill -0 $(<$pidfile) 2> /dev/null; then
                kill -9 $(<$pidfile) 2> /dev/null
            fi
        fi
    done
    for PID in $impids $smpids; do
        if kill -0 $PID  2> /dev/null; then
            children=$(pgrep -P $PID)
                for child in $children; do
                    if kill -0 $child 2>/dev/null; then
                        kill $child 2>/dev/null
                        sleep .3
                    fi
                    if kill -0 $child 2>/dev/null; then
                        kill -9 $child 2>/dev/null
                    fi
                done
        fi
    done
    for PID in $pids2kill; do
        if kill -0 $PID  2> /dev/null; then
            kill $PID  2> /dev/null
            sleep .3
        fi
        if kill -0 $PID  2> /dev/null; then
            kill -9 $PID  2> /dev/null
        fi
    done
    if $KEEP_FILES; then
        echo "Keeping temporary files in $REAL_WORK_DIR" >&2
        [[ -n $SUPPORT_VIDEOS ]] && yecho "Keeping ${SUPPORT_VIDEOS[@]}" && \
            yecho "This sliced video will not work if todisc is run with
             different seeks so should be deleted manually"
    else
        if [[ -d $REAL_WORK_DIR ]]; then
            [[ -n $SUPPORT_VIDEOS ]] && yecho \
            "Removing "${SUPPORT_VIDEOS[@]}"" >&2 && \
            rm -f "${SUPPORT_VIDEOS[@]}" >&2
            #echo -n "Removing $REAL_WORK_DIR ..." >&2
            rm -rf "$REAL_WORK_DIR" >&2
        fi
    fi
    #yecho "Removing the symlink in /tmp" >&2 | tee -a "$LOG_FILE"
    rm -f "$WORK_DIR" >&2
}
# exit from all recursive todisc calls
killall_instances()
{
    for P in $TODISC_PIDS ; do
        kill $P
    done
}

# ******************************************************************************
# Print out a runtime error specified as an argument, and exit
# ******************************************************************************
runtime_error()
{
    echo
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    yecho "todisc encountered an error:"
    yecho "    $@"
    echo
    echo "See above message, and also you can check the contents of 
    $LOG_FILE to see what went wrong." |format_output
    echo "See the tovid website ($TOVID_HOME_PAGE) for further help options."
    echo "Latest fixes for ffmpeg api changes go in svn tovid."
    echo "So you should try that if you get ${FFmpeg##*/} errors in the log."
    echo "See subversion section: http://tovid.wikia.com/wiki/Installing_tovid"
    echo "Sorry for the inconvenience!"
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    cleanup
    if $SWITCHED || $TITLESET_MODE || $DO_TITLESETS; then
        killall_instances
    fi
    exit 1
}

running_total()
{
    LC_ALL="C" awk -v offset=$offset '{
    for (i=1; i<=NF; i++) if (s=s+$i) printf("%s ",s);printf ("\n")}'
}

awk_total()
{
    LC_ALL="C" awk '{for (i=1; i<=NF; i++) s=s+$i}; END{print s}'
}

# format seconds to 00:00:00.000 format
format_seconds()
{
    LC_ALL="C"  awk '{
    hr=($1/3600); hd=(sprintf("%02d", hr))
    mr=((hr-hd)*60); md=(sprintf("%02d", mr))
    s=((mr-md)*60); sd=(sprintf("%02d", s))
    t=(sprintf("%02d:%02d:%06.3f" ,hd,md,s)); print t}' <<< $1
}

# generic function for using bc for floating point math
# usage: bc_math "expression" [int]
bc_math()
{
    local val=$1
    #val=${val//$'\n'/}
    OLC_ALL=$LC_ALL
    LC_ALL=C
    bc_out=$( ${bC} <<< "scale=3;$val" 2>/dev/null)
    if [[ -n $2 && $2 = "int" ]]; then
        echo ${bc_out%.*}
    else
        printf  "%.03f" $bc_out
    fi
    LC_ALL=$OLC_ALL
}

confirm_preview()
{
    confirm_msg="type 'yes' to continue, or press <ENTER> to exit: "
    yecho ""
    if $SWITCHED || $TITLESET_MODE || $VMGM_ONLY; then
        echo "If doing titlesets or switched menus and you wish to exit "
        echo "without seeing more previews, then type: 'exit', else you will "
        echo "continue on with other previews even if you don't type 'yes'."
        echo
        confirm_msg="Type yes to continue, press <ENTER> to abort but see "
        confirm_msg="$confirm_msg other previews, or type 'exit' to quit."
    fi
    echo -e "If you are happy with the preview, \n$confirm_msg"
    read input
    echo
    if [ ! -z "$input" -a "$input" = "yes" ]; then
        yecho "Preview OK, continuing."
        yecho ""
    else
        yecho "Preview not OK, exiting."
        #echo -n "Deleting symlink in /tmp . . . "
        echo "Cleaning up..."
        rm -f "$WORK_DIR"
        if $KEEP_FILES; then
            echo "Keeping temporary files in $REAL_WORK_DIR"
        else
            #echo -n "Deleting "$REAL_WORK_DIR" . . . "
            rm -fr "$REAL_WORK_DIR"
        fi
        yecho ""
        echo
        echo "Some configuration options to try, if things look bad:"
        echo "Color:"
        echo "    -title-color"
        echo "    -titles-color"
        echo "Fonts:"
        echo "    -menu-font and -menu-fontsize"
        echo "    -titles-font and -titles-fontsize"
        echo "If your titles are not clear enough or look washed out,"
        echo "try a larger font, or setting -title-stroke and -titles-stroke"
        echo "to a contrasting color.  Or set the strokes to the same color"
        echo "as your titles.  For black frames look at the -seek option."
        echo "For corrupt or gray frames try using the -frame-safe option, or "
        echo "use your own images for thumbnail buttons with -user-thumbs."
        echo "For other fine-tuning options, see 'man tovid'."
        echo
        [ ! -z "$input" -a "$input" = "exit" ] && killall_instances
        exit 0
    fi
}

# Display (echo) a spinner with a message
SP=0
spin()
{
    SPIN_CHARS=".oOo"
    SPINNER="${SPIN_CHARS:SP++%${#SPIN_CHARS}:1}"
    echo -ne "\r$(printf %60s)" # print spaces to overwrite previous line
    echo -ne "\r$@ "
}

get_framed_pics()
{
mplayer -ss $MPLAYER_SEEK_VAL -vo $VOUT -noconsolecontrols \
-vf ${EXPAND}rectangle=${FRAME_SIZE/x*}:${FRAME_SIZE/*x},rectangle=$(( \
${FRAME_SIZE/x*} - D )):$(( ${FRAME_SIZE/*x} - D)),rectangle=$(( \
${FRAME_SIZE/x*} - $((D * 2)) )):$(( ${FRAME_SIZE/*x} - \
$((D * 2)) )),rectangle=$(( ${FRAME_SIZE/x*} - $((D * 3)) )):$(( \
${FRAME_SIZE/*x} - $((D * 3)) )) \
-nosound -zoom -x ${FRAME_SIZE/x*} -y ${FRAME_SIZE/*x}  -frames $FRAMES "$1"
}

stat_logfile()
{
    stat -L -c "%Y" "$LOG_FILE"
}

get_line_count()
{
awk 'END{print NR}' "$LOG_FILE"
}
 
# unused
get_ffmpeg_version()
{
local test_version=$1
ff_ver=$($FFmpeg -version 2>&1 | awk '{ gsub(",", ""); if(NR == 1) print $3 }')
(( ${ff_ver:2:1} == test_version )) 2>/dev/null
} 

is_video()
{
file -biL "$1" |grep -qw video || return 1
}

check_filetype()
{
    fstats=$(file -L "$1" | awk '{ $1 = ""; print }')
    if [[ $fstats =~ "image" || $fstats =~ "bitmap" ]]; then
        file_type="image"
        CONVRT=:
        if [[ $fstats = *JPEG* || $fstats = *PNG || $fstats = *PPM* ]]; then
            CONVRT=false
        fi
    elif is_video "$1"; then
        file_type=video
    else
        file_type=unknown
    fi
}

get_stats()
{
    unset IN_STATS FILES_IN
    this_set=$1
    if [[ $this_set = "group" ]]; then
        unset TOT IN_STATS FILES_IN
        TOT=${#grouping[@]} # || TOT=${#IN_FILES[@]}
        IN_STATS=( "${group_idvid_stats[@]}" )
        FILES_IN=( "${grouping[@]}" )
    else
        TOT=${#IN_FILES[@]}
        IN_STATS=( "${idvid_stats[@]}" )
        FILES_IN=( "${IN_FILES[@]}" )
    fi
    for ((i=0; i<TOT; i++)); do
        VCODEC="$(awk -F= '/ID_VIDEO_FORMAT/ {print $2}' <<< "${IN_STATS[i]}")"
        V_BR="$(awk -F= '/ID_VIDEO_BITRATE/ {print $2}'  <<< "${IN_STATS[i]}")"
        ACODEC="$(awk -F= '/ID_AUDIO_CODEC/ {print $2}'  <<< "${IN_STATS[i]}")"
        A_BR="$(awk -F= '/ID_AUDIO_BITRATE/ {print $2}'  <<< "${IN_STATS[i]}")"
        if [ -z "$A_BR" ]; then
            A_BR="No audio found"
        fi
        V_LENGTH=${VID_LEN[i]}
        [[ $this_set = "group" ]] && V_LENGTH=${GROUP_VID_LEN[i]}
        FPS="$(awk -F= '/ID_VIDEO_FPS/ {print $2}' <<< "${IN_STATS[i]}")"
        yecho ""
        if [[ $this_set = "group" ]] && ((i == 0)); then
            print2log ""; print2log ". . . Grouped file stats . . ."
        yecho ""
        fi
        [[ $this_set = "group" ]] && print2log "Stats for \
        $(readlink -f "${FILES_IN[i]}")" || \
        print2log "Stats for" "${FILES_IN[i]}"
        echo -e  \
        " video codec:   " \
        "$VCODEC" "\n" \
        "video bitrate: " "$V_BR" "bits per second" "\n" \
        "framerate:     " "$FPS" "fps" "\n" \
        "audio codec:   " \
        "$ACODEC" "\n" \
        "audio bitrate: " \
        "$A_BR" "bits per second" "\n" \
        "video length:  " \
        "$V_LENGTH" "seconds" |pipe2log
    done
    
}
test_compliance()
{
    file_in="$1"
    if idvid -isformat ${TV_STANDARD}-${TARGET} "$file_in" >/dev/null; then
        :
    else
        return 1
    fi
}


check_compliance()
{
    # slide mpg's go in $WORK_DIR, and are moved to BASEDIR later if recursing
    # for video files: files are named $IN_FILE.enc.mpg
    unset FILES_TO_ENCODE ENC_IN_FILES CHECK_IN_FILES
    # get user's config options for makempg from the tovid.ini file
    makempg_ini_opts=$(tovid mpg | awk '/Read options/{getline;print}')
    group_set=false
    if $ENCODE_ONLY; then
        # encoding all files as -encode-only was used
        CHECK_IN_FILES=()
        FILES_TO_ENCODE=( "${IN_FILES[@]}" )
    elif [[ $1 = "group" ]]; then
        group_set=:
        unset x a
        CHECK_IN_FILES=( "${grouping[@]}" )
    else
        CHECK_IN_FILES=( "${IN_FILES[@]}" )
    fi
    TEMP_FILE="$WORK_DIR/temp.mpg"
    stime=$(date +%s)
    for ((i=0; i<${#CHECK_IN_FILES[@]}; i++)); do
        # save slideshow temporary files in $WORK_DIR
        IN_FILE=${CHECK_IN_FILES[i]}
        if $group_set; then
            is_image=${grp_file_is_image[i]}
            # replace the symlink with actual mpeg
            OUTFILE="$WORK_DIR/${CHECK_IN_FILES[i]##*/}"
        else
            is_image=${file_is_image[i]}
            # replace the symlink with actual mpeg
            OUTFILE="$WORK_DIR/${TSET_NUM}-$((i+1)).mpg"
        fi

        print2log "Checking compliance of file $((i+1))"
        # if file tested as an image when we were verifying input files
        if [[ $is_image = "yes" ]]; then
            $group_set && grp_use_image2mpeg2[i]="yes" ||
            use_image2mpeg2[i]="yes"
            FILES_TO_ENCODE[i]=$IN_FILE
            NO_PROMPT_FILES[i]=$IN_FILE
            ENC_IN_FILES=("${ENC_IN_FILES[@]}" "$WORK_DIR/${OUTFILE##*/}")
            # for titlesets we need to move all encoded mpegs to $BASEDIR
        # do not reencode animated slideshow m2v's made by MK_CAROUSEL_MODE
        elif ! $group_set && [[ ${CAROUSEL[i]} = "carousel" ]]; then
            ENC_IN_FILES=("${ENC_IN_FILES[@]}" "$IN_FILE")
        # test files with idvid script
        elif test_compliance "$IN_FILE" && [[ ${TOVID_OPTS[@]} != *-force* ]] ; then
            ENC_IN_FILES=("${ENC_IN_FILES[@]}" "$IN_FILE")
        # Video needs to be re-encoded; use a .enc filename in ENC_IN_FILES
        else
            FILES_TO_ENCODE[i]=$IN_FILE
            ENC_IN_FILES=("${ENC_IN_FILES[@]}" "${IN_FILE}.enc.mpg")
        fi
    done
    echo
    $DEBUG && etime=$(date +%s) && get_elapsed "compliance check"
    if test "${#FILES_TO_ENCODE[@]}" -gt 0; then
        TGT_CAPS=$(tr a-z A-Z <<< "$TARGET")
        TV_STND_CAPS=$(tr a-z A-Z <<< "$TV_STANDARD")
        print2log "Encode input files"
        if ! $SINGLE_SLIDESHOW; then
            if $ENCODE_ONLY; then
                yecho "Encoding the following files to \
                $TV_STND_CAPS $TGT_CAPS format:"
            else
                yecho "Some of the -files you provided are not \
                $TV_STND_CAPS $TGT_CAPS-compliant:"
            fi
            print2log ""
        fi
        if test ${#FILES_TO_ENCODE[@]} -lt 12 && ! $SINGLE_SLIDESHOW; then
            printgreen '-------------'
            for i in "${FILES_TO_ENCODE[@]}"; do
                this_file=$(readlink -f "$i")
                test -n "$this_file" && yecho " $this_file"
            done
            printgreen '-------------'
        fi
        # this ugly list of OR's are cases we want automatic encoding
        # all switched runs except the 1st, if -no-ask, if single slideshow
        # or if all input files are images
        if { $SWITCHED && [[ $MENU_NUM -ne 2 ]] ; } \
         || $NOASK || [[ ${TOVID_OPTS[@]} = *-noask* ]] || $ENCODE_ONLY || \
         [[ ${#NO_PROMPT_FILES[@]} = ${#FILES_TO_ENCODE[@]} ]]; then
            echo "Encoding files to $TV_STND_CAPS $TGT_CAPS-compliant format."
            ENCODE="yes"
        else
            yecho ""
            yecho "I can encode them for you, but it may take a long time."
            yecho "Encoding will ensure that your disc is fully compliant;"
            yecho "you may skip this, but your disc may not be playable."
            yecho "Please type 'yes' if you want the files to be encoded:"
            read ENCODE
            if [[ $ENCODE = "yes" ]]; then
                ! $SINGLE_SLIDESHOW && yecho \
                "Converting files to $TGT_CAPS format"
            fi
        fi
        if [[ $ENCODE = 'yes' ]]; then
            for i in "${!FILES_TO_ENCODE[@]}"; do
                IN=$(readlink -f "${FILES_TO_ENCODE[i]}")
                if $group_set; then
                    is_image=${grp_file_is_image[i]}
                    # we will replace the symlink with actual mpeg
                    OUTFILE="$WORK_DIR/${CHECK_IN_FILES[i]##*/}"
                else
                    is_image=${file_is_image[i]}
                    # we will replace the symlink with actual mpeg
                    OUTFILE="$WORK_DIR/${TSET_NUM}-$((i+1)).mpg"
                fi
                if $group_set; then
                    convert_image=${grp_use_image2mpeg2[i]}
                else
                    convert_image=${use_image2mpeg2[i]}
                fi

                if [[ $convert_image = "yes" ]]; then
                    # group: test if $OUTFILE is symlink (ie. not encoded yet)
                    # files: test if $OUTFILE doesn't exist
                    if [[ -L $OUTFILE || ! -e $OUTFILE ]]; then
                        spin "Processing" "${IN##*/}"
                        image2mpeg2 "$IN" "$TEMP_FILE"
                        # replace the symlink in $WORK_DIR
                        rm -f "$WORK_DIR/${OUTFILE##*/}"
                        mv "$TEMP_FILE" "$WORK_DIR/${OUTFILE##*/}"
                    fi
                    # AUDIO_FADE=false # do not fade silence FIXME ???
                else # not an image file - outfile goes beside infile
                    #THIS_FILE=$(readlink -f "${FILES_TO_ENCODE[i]}")
                    if [[ -e "$IN.enc.mpg" ]]; then
                        if ! grep -w -- -overwrite <<< \
                          "$makempg_ini_opts ${script_args[@]}"; then
                            : #FIXME echo to terminal what makempg would do ?
                        fi
                    fi
                    yecho "Converting $IN"
                    echo
                    continue_in 3
                    TOVID_WORKING_DIR=$WORKING_DIR makempg $NO_ASK \
                    -$TV_STANDARD -$TARGET -in "$IN" -out "${IN}.enc" \
                    "${TOVID_OPTS[@]}"
                    wait
                    if [[ -e "${IN}.enc.mpg" ]]; then
                        ! $ENCODE_ONLY && yecho "Using ${IN}.enc.mpg for this DVD"
                    else
                        runtime_error "There appears to be a problem creating \
                        the DVD compatible mpeg.  See $LOG_FILE for details"
                    fi
                    # for grouped files replace symlink in $WORK_DIR
                    $group_set && [[ -L "${FILES_TO_ENCODE[i]}" ]] && \
                    ln -sf "${IN}.enc.mpg" "${FILES_TO_ENCODE[i]}"
                fi
                wait
                # See if output file exists
                if [[ $convert_image = "yes" ]]; then
                    test_file="$WORK_DIR/${OUTFILE##*/}"
                else
                    test_file="${IN}.enc.mpg"
                fi
                if ! test -f "$test_file"; then
                    KEEP_FILES=:
                    runtime_error "Could not encode file: $IN"
                fi
                #yecho ""
            done

            # Replace IN_FILES with ENC_IN_FILES (with .enc extension)
            # for grouped files the mpeg already replaced the group symlink
            ! $group_set && IN_FILES=("${ENC_IN_FILES[@]}")
        else
            if $ENCODE_ONLY; then
                info_message "Not re-encoding."
            else
                info_message "Not re-encoding. I will proceed with menu generation, but
                your authored disc will not be fully $TGT_CAPS-compliant."
            fi
        fi
    fi
}

# check bgvideo and showcase VIDEO for compliance
tovid_reencode()
{
    VIDEO_IN="$1"
    VIDEO_IN_SEEK="$2"
    video_type=$3
    yecho ""
    yecho "$VIDEO_IN is not compliant - re-encoding \
      $( ${bC} <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null)
        second slice to DVD compliant file"
    yecho "This is not strictly necessary and will reduce quality, but it may"
    yecho "help with sync problems if using the same file for audio and video."
    yecho "Do you want to continue encoding this file?, type 'yes' to do so"
    if ! $NOASK; then
        read response
        if [ ! -z "$response" -a "$response" = "yes" ]; then
            :
        else
            return
        fi
    fi
    yecho ""
    yecho "Converting files to $TGT_CAPS format with 'makempg'"
    continue_in 5
    makempg $NO_ASK -in "$VIDEO_IN" \
    -slice 0-$( ${bC} <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null) \
    -${TV_STANDARD} -${TARGET} -in "$VIDEO_IN" \
    -out "${VIDEO_IN}.enc" "${TOVID_OPTS[@]}"
    # See if output file exists
    if ! test -f "${VIDEO_IN}.enc.mpg"; then
        runtime_error "Could not encode file: $VIDEO_IN"
    else
        [[ $video_type = showcase ]] && SHOWCASE_VIDEO="${VIDEO_IN}.enc.mpg"
        [[ $video_type = background ]] && BG_VIDEO="${VIDEO_IN}.enc.mpg"
    fi
    SUPPORT_VIDEOS=( "${SUPPORT_VIDEOS[@]}" "${VIDEO_IN}.enc.mpg" )
    yecho ""
}

mk_workdir()
{
    REAL_WORK_DIR=$(tempdir "$WORKING_DIR/todisc-work")
    sleep .5 # avoid race condition
    WORK_DIR=$(tempdir /tmp/todisc-work nocreate)
    # tempdir() made a unique name with nocreate, now make it a symlink
    ln -sf "$REAL_WORK_DIR" "$WORK_DIR"
}


get_group_chapters()
{
    FORMAT=false
    index=$1
    [[ -n $2 && $2 = "format" ]] && FORMAT=:
    $USER_CHAPTERS && FORMAT=false
    unset chapt_len_array x len remainder y e grp_chapters array
    remainder=0
    chapter_length=$( bc_math "${GROUP_TOT_LEN[index]} / ${CHAPTERS[index]}")
    GROUP_VIDEO_LENGTHS=( ${GROUP_VID_LENGTHS[index]} )
    if $USER_CHAPTERS; then
        unset grp_arb_chts y
        grp_arb_chts=( ${group_arbitrary_chapters[index]} )

        for y in ${!grp_arb_chts[@]}; do
            unset GC
            (( y == 0 )) && chpts0="chapters=\"${grp_arb_chts[y]}\""
            gc=( ${grp_arb_chts[y]//,/ } )
            # allow passing 00:00:00 for grouped chapters
            ((${#gc[@]} == 1 )) && [[ $gc = 00:00:00* ]] && gc=( 00:00:01 )

            for g in ${gc[@]}; do GC="$GC $(unformat_time $g)"; done
            grp_chapters[y]=$GC
            if [[ ${grp_arb_chts[y]} = 0 ]]; then
                chpts[y]=""
            else
                chpts[y]=chapters=\"${grp_arb_chts[y]}\"
            fi
        done
    else
        for len in ${GROUP_VIDEO_LENGTHS[@]}; do
            adjusted_length=$( ${bC} <<< "scale=3; $len + $remainder" 2>/dev/null)
            num_chapters=$( bc_math "$adjusted_length / $chapter_length" int )
            if (( num_chapters > 0)); then
                chapt_len_array=( $( for ((t=0; t<num_chapters; t++)); do
                echo $chapter_length; done) )
                chapt_len_array=($(bc_math "$chapter_length - $remainder") \
                ${chapt_len_array[@]})
                unset chapt_len_array[${#chapt_len_array[@]}-1]
                chapter_points=$( running_total <<< ${chapt_len_array[@]} )
                # remove trailing space
                chapter_points=$(sed 's/[ \t]*$//' <<< $chapter_points)
                remainder=$( ${bC} <<< "$adjusted_length % $chapter_length" \
                2>/dev/null)
                (( ${nochapt[index]} )) && local group_chapters[x++]=0 ||
                local group_chapters[x++]=$chapter_points
            else
                (( ${nochapt[index]} )) && local group_chapters[x++]=0 ||
                local group_chapters[x++]=""
                remainder=$adjusted_length
            fi
        unset chapt_len_array
        done
        # remove last chapter as this makes one for the end of the video
        # ignore if we are doing -chapters 0 for this video ( no chapters )
        if ! ((${nochapt[index]})); then
            for id in ${!group_chapters[@]}; do
                for s in ${group_chapters[id]}; do
                    let p=p+1
                    (( p < ${CHAPTERS[index]})) && substr="$substr $s"
                done
                group_chapters[id]=$substr
                unset substr
            done
        fi

        unset remainder
        for d in ${!group_chapters[@]}; do
            for number in ${group_chapters[d]}; do
                new_element="$new_element $(format_seconds $number),"
                grp_chapters[d]="${grp_chapters[d]} $number"
                grp_chapters[d]=$(sed 's/[ \t]*$//' <<< ${grp_chapters[d]})
            done
            local array[d]=$new_element
            unset new_element
        done

    fi
    if $FORMAT; then
        for e in ${!array[@]}; do
            points=$(for f in ${array[e]// /}; do echo -n $f;done)
            if [[ -z ${array[e]} ]]; then
                [[ -n ${chapts[e]} ]] && unset chpts[e]
            else
                chpts[e]=chapters=\"${points%,}\"
            fi
            [[ -n ${array[e]} ]] && chpts[e]=${chpts[e]#,}
            if ((e == 0)); then
                if [[ -z "$points" ]]; then
                    chpts0="chapters=\"00:00:00\""
                else
                    chpts0="chapters=\"00:00:00,${points%,}\""
                fi
            fi
            #chpts=${chpts[@]#,} # I have no idea why this worked with this here
        done
    fi
}

get_image_dim()
{
    identify -ping "$1" | awk '{print $3}'
}

get_button_geo()
{
    GEOx=${MENU_BUTTON_SIZE/x*}
    GEOy=${MENU_BUTTON_SIZE/*x}
    GEOx=$((GEOx - 3))
    GEOy=$((GEOy - 3))
    GEO="$GEOx,$GEOy"
}

# this function takes a 4:3 image and gives a new height to make it 16:9
get_177_ht()
{
    image_width=$1
    bc_math "($image_width * 9)/16" int
}

get_ntsc_ht()
{
    img_width=$1
    bc_math "(2 * $img_width)/3" int
}

get_pal_ht()
{
    img_width=$1
    bc_math "(4 * $img_width)/5" int
}
image2mpeg2()
{
    IN_IMAGE="$1"
    OUT_MPEG="$2"
    # need to set VIDSIZE here as pal VIDSIZE assignment is later in script
    [ $TV_STANDARD = "pal" ] && VIDSIZE=720x576
    VF_SCALE=${VIDSIZE%x*}:${VIDSIZE#*x}
    # remove symlinks, as otherwise we overwrite symlink target
    IMAGE_ENC_CMD=($FFmpeg -f image2 $LOOP \
    -i "$IN_IMAGE" -f s16le -ar 48000 -i /dev/zero -t $alength \
    -ar $SAMPLERATE -ac 2 -ab 224k -target ${TV_STANDARD}-${TARGET} \
    $VF scale=${VF_SCALE},${ASPECT} -y -vframes $vlength  "$OUT_MPEG")
    print2log ""
    print2log "Running ${IMAGE_ENC_CMD[@]}"
    print2log ""
    "${IMAGE_ENC_CMD[@]}" 2>&1 | pipe2log fmpeg
}

switched_menu_mode()
#call todisc recursively to make multiple menus for -switched-menus option
{
    $TITLESET_MODE && IS_TITLESET="-is_titleset"
    for ((i=1; i<${#FILES[@]}; i++)); do
        yecho
        yecho "Working on switched menu $((i+1))"
        $WARN && yecho && sleep 5
        yecho "Running todisc "$@" -switched-mode $IS_TITLESET \
        -basedir "$BASEDIR" -menu_num $((i+1)) -showcase "${FILES[i]}""
        todisc "$@" -switched-mode $IS_TITLESET -basedir "$WORK_DIR" \
        -menu_num $((i+1)) -todisc_pids "$TODISC_PIDS" -showcase "${FILES[i]}"
        yecho
    done
        yecho
        yecho "Working on switched menu 1"
        yecho
}
carousel_menu_mode()
# call todisc recursively to make animated slideshow menu
{
    mk_carousel()
    {
        unset menulen
        c=$1 # carousel index ( 0 based )
        ! $CONFIRM_BACKUP && NO_CONFIRM_BACKUP="-no-confirm-backup"
        if [[ $sstype = "submenu" ]]; then
            menulen="-menu-length ${SUBMENU_LEN[c]}"
            mixrange=${SM_MIX_RANGE[c]}
        else
            $USER_MENU_LEN && menulen="-menu-length ${MENU_LEN[c]}"
            mixrange=${MIX_RANGE[c]}
        fi
        if [[ -n $mixrange ]]; then
            if (($mixrange<${#IN_SLIDES[@]})); then
                mix_range="-menu-slide-total $mixrange"
            else
                unset mix_range
            fi
        else
            unset mix_range
        fi
        MC_CMD=(todisc -slides "${IN_SLIDES[@]}" $mix_range \
        $NO_CONFIRM_BACKUP ${encopt[@]} $sld_tranition $background_carousel \
        $showcase_carousel -out "$OUT_DIRECTORY" -carousel_menu_mode -basedir \
        "$WORK_DIR" $menulen -carousel_num $((c+1)) -todisc_pids "$TODISC_PIDS")
        yecho ""
        yecho "Running ${MC_CMD[@]}"
        "${MC_CMD[@]}"
    }

    [[ -n $1 ]]  && local sstype=$1 || local sstype=""
    $SLIDE_FADE && sld_tranition="-slide-transition $EFFECT"
    #! grep -q -- -noask <<< "$TOVID_OPTS" && \
    [[ ${TOVID_OPTS[@]} != *-noask* ]] && \
     encopt=("${TOVID_OPTS[@]}" -noask)
    if $CAROUSEL_IS_BG && [[ $sstype != "submenu" ]]; then
        local background_carousel="-background-slideshow"
        IN_SLIDES=( "$WORK_DIR"/${TSET_NUM}-slide_grp*.mpg )
        mk_carousel 0
    elif $CAROUSEL_IS_SHOWCASE && [[ $sstype != "submenu" ]]; then
        local showcase_carousel="-showcase-slideshow"
        IN_SLIDES=( "$WORK_DIR"/${TSET_NUM}-slide_grp*.mpg )
        mk_carousel 0
    else
        for i in ${!FILES[@]}; do
            if ${SLIDESHOW[i]}; then
                unset IN_SLIDES sl
                for sld in "$WORK_DIR"/${TSET_NUM}-slide_grp-$((i+1))-*.mpg; do
                    IN_SLIDES[sl++]=$sld
                done
                yecho
                yecho "Working on carousel menu $((i+1))"
                yecho
                mk_carousel $i
            fi
        done
    fi

}
# used by titleset_mode()
get_genopts()
{
    unset GEN_OPTS
    i=0
    while [[ $@ ]]; do
        case "$1" in
            "-titleset")
                shift
                while [[ $@ && $1 != "-end-titleset" ]]; do
                    tsetopt="$tsetopt $1"
                    shift
                done
                tsetopts=( "${tsetopts[@]}" "$tsetopt" )
                unset tsetopt
                ;;
            "-vmgm")
                shift
                while [[ $@ && $1 != "-end-vmgm" ]]; do
                    vmgmopts="$vmgmopts $1"
                    shift
                done
                ;;
            "-group")
                shift
                get_listargs "$@"
                ;;
            *)
                GEN_OPTS[i++]="$1"
                ;;
        esac
        shift
    done
}
# used by get_titleset_opts() within titleset_mode()
get_title_count()
{
    unset y titles
    while [[ $@ ]]; do
        case "$1" in
            "-vmgm")
                while [[ $@ && $1 != "-end-vmgm" ]]; do
                    shift
                done
                ;;
            "-files" )
                shift
                get_listargs "$@"
                fls=( "${fls[@]}" "${#ARGS_ARRAY[@]}")
                ;;
            "-slides" )
                fls=( "${fls[@]}" 1)
                ;;
        esac
        shift
    done
    NUM_TITLES=( "${NUM_TITLES[@]}" $(awk_total <<< "${fls[@]}") )
    unset fls
}
get_menu_titles()
{
    unset y titles
    while [[ $@ ]]; do
        case "$1" in
            "-vmgm")
                while [[ $@ && $1 != "-end-vmgm" ]]; do
                    shift
                done
                ;;
            "-menu-title" )
                shift
                menutitles=("${menutitles[@]}" "$1")
                ;;
            "-titles" )
                shift
                get_listargs "$@"
                OIFS=$IFS
                IFS=""
                vmgmtitles=( "${vmgmtitles[@]}" "${ARGS_ARRAY[@]}" )
                IFS=$OIFS
                ;;
        esac
        shift
    done
}
# used by titleset_mode()
get_titleset_opts()
{
    while test $# -gt 0; do
        case "$1" in
            "-titleset" )
                unset x TSET_OPTS
                shift
                # Hackish list-parsing
                while test $# -gt 0 && test "$1" != "-end-titleset"; do
                    TSET_OPTS[x++]=$1
                    shift
                done
                get_title_count "${TSET_OPTS[@]}"
                ;;
        esac
        shift
    done
}

titleset_mode()
# call todisc recursively in order to allow titlesets
{
    get_titleset_opts "${args[@]}"
    get_menu_titles "${args[@]}"
    ALLTITLES=( ${NUM_TITLES[@]} )
    # get the number of files in each titleset
    num_titles=${NUM_TITLES[@]}
    MENUTITLES=( "${menutitles[@]}" )
    # some vars for vmgm menu, depending on presence of -static or -quick-nav
    # how many titlesets do we have ?
    for i in "$@"; do [[ $i == -end-titleset ]] && ((tscount++)); done
    VMGM_PAUSE=$PAUSE_TIME
    grep -q  -- -static  <<< "${VMGM_OPTS[@]}" && VMGM_PAUSE="inf"
    for i in ${!VMGM_OPTS[@]}; do
        if [[ ${VMGM_OPTS[i]} = '-loop' ]]; then
            loop_val=${VMGM_OPTS[i+1]}
            test_is_number $loop_val && VMGM_PAUSE=$loop_val
        fi
    done
    # let titlesets know if there is a root menu playall
    get_genopts "${args[@]}" # DEBUG not sure why this was a bad idea before
    if grep -q -- -playall <<< "${VMGM_OPTS[@]} ${GEN_OPTS[@]}"; then
        vmgm_playall="-vmgm_playall"
        VMGM_PLAYALL=:
    fi
    unset vmgmopts tsetopts GEN_OPTS
    DVDAUTHOR_XML="$BASEDIR/dvdauthor.xml"
    VMGM_PRE="        if ( g5 eq 0 ) g5=1;"
    VMGM_PRE="$VMGM_PRE\n        if ( g6 eq 0 ) g6=1; button = g6 * 1024;"
    # switch is now singular (-switched-menu) OR plural (-switched-menus)
    egrep -q -- "-switched-menu" <<< "${args[@]}" && \
    VMGM_PRE="$VMGM_PRE\n        if (g1 eq 0) g1=1;"
    $DO_INTRO && INTRO_PRE="        if (g2==1) jump cell 2; "
    $SKIP_VMGM_MENU && VMGM_PRE="$VMGM_PRE\n        if ( g3 eq 0 )  g3=1 ;"
    # make dvdauthor.xml
(
    cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<dvdauthor dest="$OUT_DIR" jumppad="0">
  <vmgm>
    <menus>
      <video format="$TV_STANDARD" aspect="4:3"/>
      <pgc entry="title">
        <pre>
$(echo -e "$VMGM_PRE")
$(if $QUICK_NAV || $SKIP_VMGM_MENU; then
        for ((i=1; i<=${#TITLESET_OPTS[@]}; i++)); do
            echo -e "        if ( g3 eq $i ) jump titleset $i menu;"
        done
fi)
$(if $VMGM_PLAYALL; then
        # g8 tests if a video finished playing, if not do not jump to next
        echo -e "        if (g8==0) g7=0;"
        echo -e "        if (g8==1) { "
        # for a vmgm playall g7 for jumping between titlesets after last video
        for ((i=1; i<=${#TITLESET_OPTS[@]}; i++)); do
            echo -e "          if ( g7 eq $i ) jump titleset $i menu;"
        done
        echo "        }"
        [[ -n $INTRO_PRE ]] && echo "$INTRO_PRE"
fi)
        </pre>
        <post>
$( [[ -n $INTRO ]]  && echo -e "        g2=1; jump vmgm menu entry title;")
        jump cell 1;
        </post>
$(for ((i=1; i<=${#TITLESET_OPTS[@]}; i++)); do
    echo \
    "        <button name=\"$i\">g1=1; g5=1; g6=$i; jump titleset $i menu;</button>"
done)
$(if $VMGM_PLAYALL; then # VMGM playall needs a playall button entry
    pall=$((${#TITLESET_OPTS[@]} + 1))
    # set g8=1 for vmgm playall button even though it means vid finished
    echo -n \
    "        <button name=\"$pall\">g4=1; g7=1; g8=1; jump titleset 1 menu entry root;"
    echo "</button>"
fi)
$(if $QUICK_NAV; then
    echo -e "        <button name=\"ActionLeft\">"
    echo -e "        g5=${ALLTITLES[tscount-1]}; g3=$tscount; button=1024;"
    echo -e "        jump vmgm menu entry title;</button>"
    echo -e "        <button name=\"ActionRight\">"
    echo -e "        g5=1; g3=1; button=1024;"
    echo -e "        jump vmgm menu entry title;</button>"
fi)
        $INTRO
        <vob file="$BASEDIR/VMGM.mpg" pause="$VMGM_PAUSE"/>
      </pgc>
    </menus>
  </vmgm>
EOF
) |sed '/^ *$/d' >> "$DVDAUTHOR_XML"
    get_genopts "${args[@]}"

    #################### test for incompatible options #######################
    # this unfortunate block helps user by testing for incompatible options
    # within titlesets, exiting BEFORE having done previous titlesets
    general_options="-no-vmgm -skip-vmgm -out -quick-nav -burn -device
    -speed -eject -no-confirm-backup"
    GREP="egrep -w -q --"
    for opt in $general_options; do
        if $GREP $opt <<< "${tsetopts[@]} ${vmgmopts[@]}" \
                       && ! $GREP $opt <<< "${GEN_OPTS[@]}"; then
            usage_error "$opt is a general option and goes outside of
            '-titleset ... -end-titleset' and '-vmgm ... -end-vmgm' areas"
        fi
    done
    if $GREP -no-vmgm <<< "${GEN_OPTS[@]}" && \
       ! $GREP -quick-nav <<< "${GEN_OPTS[@]}"; then
        usage_error "You can not use -no-vmgm if doing titlesets
             unless using -quick-nav."
    fi
    for t in ${!tsetopts[@]}; do
        options="${tsetopts[t]} ${GEN_OPTS[@]}"
        if $GREP -videos-are-chapters <<< "$options"; then
            if $GREP -playall  <<< "$options"; then
                usage_error \
                 "-videos-are-chapters can not be used with -playall"
            elif $GREP '-group|-slides' <<< "$options"; then
                usage_error "-videos-are-chapters can not be used with
                 grouped videos (-group) or slideshows (-slides)"
            fi
        fi
        # making a static slideshow is incompatible with -quick-menu
        if $GREP -quick-menu <<< "$options" \
         && $GREP -slides <<< "$options" \
         && $GREP -static <<< "$options"; then
            usage_error "A -quick-menu slideshow must be animated.
            If you ARE wanting a static menu, remove the '-quick-menu' option"
        fi
        # warning to backup images if doing slideshow
        if $GREP -slides <<< "$options"; then
            $CONFIRM_BACKUP && confirm_backup
        fi
        # -quick-menu incompatible with -menu-fade
        if $GREP -quick-menu <<< "$options" \
         && $GREP -menu-fade <<< "$options"; then
            usage_error "-quick-menu is incompatible with -menu-fade"
        fi
    done
    unset vmgmtitles
    get_menu_titles "${VMGM_OPTS[@]}"
    if [[ -n ${VMGM_OPTS[@]} ]] && ((${#vmgmtitles[@]} != tscount)); then
        usage_error "Number of titleset titles must equal the number
         of titlesets. ( -vmgm ... -titles 'Title 1' 'Title 2' -end-vmgm )"
    fi
    ################### end titleset options testing #########################

    if [[ -z ${VMGM_OPTS[@]} ]]; then
        #yecho
        yecho "You have not supplied -vmgm OPTIONS -end-vmgm"
        yecho "At a minumum you should have: \
        '-vmgm -titles "Title one" "Title two" -end-vmgm'"
        yecho "One title for each titleset you are making."
        yecho "Any other appropriate todisc options for the vmgm menu \
        can be specified as well."
        if  [[ ${#MENUTITLES[@]} -eq $tscount ]]; then
            yecho "Since -menu-title was supplied for each titleset: \
            these titleset titles will be used:"
            for t in "${MENUTITLES[@]}"; do echo "\"$t\""; done
            VMGM_OPTS=(-titles "${MENUTITLES[@]}")
        else
            VMGM_OPTS[0]="-titles"
            for ((menu=1; menu<=tscount; menu++)); do
                VMGM_OPTS[menu]="Titleset $menu"
            done
        fi
        yecho "Making a generic vmgm menu for you - \
        you may wish to cancell out and change this."
        yecho ""
        $VMGM_MENU && $WARN && continue_in 15
    else
        unset vmgmtitles
        get_menu_titles "${VMGM_OPTS[@]}"
        if ((${#vmgmtitles[@]} != 0)) && ((${#vmgmtitles[@]} != tscount)); then
            usage_error "Number of titleset titles must equal the number
            of titlesets."
        fi
    fi
    ################### end titleset options testing #########################
    # VMGM menu
    print2log "Making a VMGM menu"
    vmgm_menu_cmd=(todisc "${GEN_OPTS[@]}" -basedir "$WORK_DIR" -vmgm_only \
    -textmenu -todisc_pids "$TODISC_PIDS" $NO_CONFIRM_BACKUP \
    -title_count "$num_titles" $vmgm_playall  "${VMGM_OPTS[@]}")
    print2log "Running: ${vmgm_menu_cmd[@]}"
    INITIALDIR="$BASEDIR"
    if ! "${vmgm_menu_cmd[@]}" ; then cleanup && exit 1; fi
    # TITLESET menus
   # TODO move to function to avoid duplication - generalize for -vmgm too
    while test $# -gt 0; do
        DO_SHIFT=:
        case "$1" in
            "-titleset" )
                let tset=tset+1
                shift
                unset x TITLESET_OPTS
                # Hackish list-parsing
                while test $# -gt 0 && test "$1" != "-end-titleset"; do
                    TITLESET_OPTS[x++]="$1"
                    shift
                done
                titleset_cmd=( todisc -titleset-mode -basedir "$WORK_DIR" \
                -title_count "$num_titles" -tset_num ${tscount}-${tset} \
                "${GEN_OPTS[@]}" $NO_CONFIRM_BACKUP "${TITLESET_OPTS[@]}" \
                $vmgm_playall )
                yecho
                yecho "Working on the menu for titleset number $tset"
                yecho
                $WARN && continue_in 5
                print2log "Running: ${titleset_cmd[@]}"
                if ! "${titleset_cmd[@]}"; then cleanup && exit 1; fi
                yecho
                ;;
        esac
        $DO_SHIFT && shift
    done
    echo -e "</dvdauthor>" >> "$DVDAUTHOR_XML"
    yecho "Running dvdauthor to create final DVD structure"
    dvdauthor -x "$DVDAUTHOR_XML" 2>&1 | pipe2log dvdauthor
    if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
        dvdauthor_error
    fi
    thanks_goodbye
    cleanup

}

parse_rotateargs()
{
    unset x ARGS_ARRAY
    # Hackish list-parsing
    while test $# -gt 0 && egrep -q '^[-+]?[[:digit:]]{1,2}+$' <<< "$1"; do
        ARGS_ARRAY[x++]="$1"
        shift
    done
    # Do not skip past the next argument
    if test $# -gt 0 && test x"${1:0:1}" = x"-";then
        DO_SHIFT=false
    fi
}

burn_disc()
{
    BURN_TGT="$OUT_DIR"
    BURN_TGT_STR="DVD directory"
    BURN_CMD=(tovid dvd -burn -device "$BURN_DEVICE" $EJECT  \
    $BURN_SPEED \"$BURN_TGT\")
    yecho
    echo "You have indicated you want to burn the $BURN_TGT_STR"
    echo "Would you like to burn the ${BURN_TGT_STR/ *} now ?"
    echo -n "Type 'yes' to continue: "
    read input
    echo
    if [ ! -z "$input" -a "$input" = "yes" ]; then
        echo "Proceeding to burn, continuing."
        echo
        # probably could do redirection using exec and such, but this is simple
        $BURN_PROG -device "$BURN_DEVICE" \
        $BURN_SPEED "$BURN_TGT" | tee  "$WORK_DIR/makedvd.log"
        pipe_status=${PIPESTATUS[0]}
        pipe2log makedvd < "$WORK_DIR/makedvd.log"
        if ((pipe_status==0)); then
            echo "Your ${BURN_TGT_STR/ *} should be ready"
        else
            echo "There was a problem burning the ${BURN_TGT_STR/ *}"
            echo "Please see makedvd output above, and "$LOG_FILE" for details"
            echo "When the problem is solved, try again with the command:"
            echo "${BURN_CMD[@]}"
        fi
    else
        echo "Not burning now - please see the parting message from todisc"
        echo "for instructions on using ${BURN_PROG}, or see 'man tovid'"
    fi
}

thanks_goodbye()
{
    SCRIPT_TIME=$(format_seconds $SECONDS)
    goodbye=`cat << EOF

    $SEPARATOR
    todisc took $SCRIPT_TIME to finish on
    $CPU_MODEL $CPU_SPEED mhz
    $SEPARATOR

    Your new DVD should be in $OUT_DIR
    You can preview them in gxine with this command:
        $(printf "%s\t" "gxine \"dvd:/$OUT_DIR\"")
    Or in vlc with this command:
        $(printf "%s\t" "vlc \"$OUT_DIR\"")
    If you are satisfied with the results, you can burn a disc with:
        $(printf "%s\t" "tovid dvd -burn \"$OUT_DIR\"")
    
    Thanks for using tovid!
EOF`
    echo
    sed 's/^    //g' <<< "$goodbye" | tee -a "$LOG_FILE"
}

# usage mk_return_button (mk_play_button) COLOUR1 COLOUR2 outbutton
# ex. for menu button ( not spumux ):
# mk_return_button "#C6C6C6" black "$WORK_DIR/Main.png"
mk_return_button()
{

    colr1="$1"
    colr2="$2"
    local auth_type=$3
    outbutton="$4"
    if [[ $auth_type = "spu" ]]; then
        clr1="none"
    elif [[ $auth_type = "default" ]]; then
        clr1="$colr1"
    fi

    mk_rtn_cmd=(convert +antialias -size 100x80 xc:none \
    -strokewidth 1 -stroke "$colr2" -fill "$clr1" \
    -draw 'rectangle 0,0 70,62' \
    -fill "$colr2" -stroke none \
    -draw "polyline 40,10 40,50 10,30 40,10" \
    -draw "polyline 60,10 60,50 30,30 60,10" \
    -fill "$colr2" -draw "rectangle 6,10 10,50" \
    -resize 30% -trim +repage "$outbutton")
    print2log "Running ${mk_rtn_cmd[@]}"
    "${mk_rtn_cmd[@]}"
    mogrify -channel A -threshold 50% "$outbutton"
    rtn_btn_dim=$(get_image_dim "$outbutton")
    rtn_btn_width=$(awk -Fx '{print $1}' <<< $rtn_btn_dim )
    rtn_btn_height=$(awk -Fx '{print $2}' <<< $rtn_btn_dim )
}
mk_play_button()
{
    colr1="$1"
    colr2="$2"
    local auth_type=$3
    outbutton="$4"
    if [[ $auth_type = "spu" ]]; then
        clr1="none"
    elif [[ $auth_type = "default" ]]; then
        clr1="$colr1"
    fi
    #-fill "$colr2" -draw "line 40,10 40,50"  \
    # -fill "$colr2" -draw "rectangle 36,10 40,50" \
    mk_play_cmd=(convert +antialias -size 100x80 xc:none  \
    -strokewidth 2 -stroke "$colr2" -fill "$clr1" \
    -draw 'rectangle 22,0 92,62' \
    -fill "$colr2" -stroke none \
    -draw "polyline 40,10 40,50 80,30 40,10" \
    -resize 30% -trim +repage "$outbutton")
     print2log "Running ${mk_play_cmd[@]}"
    "${mk_play_cmd[@]}"
    play_btn_dim=$(get_image_dim "$outbutton")
    play_btn_width=$(awk -Fx '{print $1}' <<< $play_btn_dim )
    play_btn_height=$(awk -Fx '{print $2}' <<< $play_btn_dim )
    mogrify -channel A -threshold 50% "$outbutton"
}

check_menufile()
{
    yecho ""
    if test -f "$MENU_FILE"; then
        echo "Menu file $MENU_FILE created"
        echo
    else
        runtime_error "Menu file $MENU_FILE not found.  \
        Spumux seems to have had problems"
    fi
}

quick_menu()
{
    funct_arg=$1
    # is it a preview or main run of menu creation
    if [[ -n $funct_arg && $funct_arg = "preview" ]]; then
        QM_MENU_TIME=2 && QM_PREVIEW=:
    else
        QM_MENU_TIME=${MENU_LEN[MENU_NUM-1]} && QM_PREVIEW=false
    fi
    # test for filters presense in ffmpeg
    # ffmpeg has really poor support for scripts so we can't do something
    # sane like grep for ^movie or ^crop.
    # using these ugly repeated grep calls because they are easier to
    # understand/maintain than an awk command.
    if ! ((filter_test_completed)); then
        filters=$($FFmpeg -filters 2>/dev/null)
        if grep  -w 'movie'  <<< "$filters" | grep -q -v 'amovie' &&
          grep -w 'crop' <<< "$filters" | grep -q -v 'cropdetect'; then
            print2log "libavfilter movie filter present, using for -quick-menu"
            use_overlay_filter=:
        else
            # exit if missing a needed video filter
            runtime_error \
              "Missing ${FFmpeg##*/} filters
              (movie or crop) -quick-menu impossible."
        fi
    fi

    # ensure the filter test is only run once
    filter_test_completed=1
    if $QUICKMENU_IS_SHOWCASE; then
        if ! $NOASK; then
            yecho ""
            yecho "resizing and padding showcase file: $SHOWCASE_VIDEO"
        fi
        local VF_PADX=$SC_X
        local VF_PADY=$SC_Y
        QM_FRAMESIZE=$SHOWCASE_SIZE
        outdir="$WORK_DIR/showcase"
        if $SWITCHED; then
            qm_seek="-ss ${SEEK_VAL[MENU_NUM-1]}"
        else
            qm_seek="-ss $SHOWCASE_SEEK_VAL"
        fi
    elif $QUICKMENU_IS_BACKGROUND; then
        QM_FRAMESIZE=$VIDSIZE
        outdir="$WORK_DIR/bg"
        qm_seek="-ss $BG_SEEK"
    fi
    if $FAST_SEEK; then
        qm_pre_seek=$qm_seek && unset qm_post_seek
    else
        qm_post_seek=$qm_seek && unset qm_pre_seek
    fi

    $QM_PREVIEW && ! $NOASK && yecho "Creating a quick-menu preview image"
    # pad/resize if needed, use overlay filter to add menu graphics
    # framing (if showcase) by ntsc-safe black bg
    if ! $QM_PREVIEW; then
        yecho ""
        yecho "Using $FFmpeg to add titles and background"
    fi
    if $use_overlay_filter; then
        local qw=${QM_FRAMESIZE%x*}
        local qh=${QM_FRAMESIZE#*x}
        # vhook uses the next var for scaling, but overlay does not
        unset QM_FRAMESIZE
        local overlay="$WORK_DIR/quick_menu_bg.png"
        local PADDING="$VF scale=${qw}:${qh},pad=$VF_SCALE:${VF_PADX}:${VF_PADY}"
        overlay_filter="movie=$overlay [wm];[in][wm] overlay=0:0 [wm2]"
        ffmpeg_filter=($VF "$overlay_filter; [wm2] setdar=4:3 [out]")
    fi
    # no padding needed for background video, just resizing
    $QUICKMENU_IS_BACKGROUND && PADDING=""
    # create fifo
    yuvout="$WORK_DIR/out.yuv"
    rm -f  "$yuvout"  && mkfifo "$yuvout"
    # run the commands to make the final menu m2v video
    PAD_CMD=($FFmpeg -async 1 $qm_pre_seek \
    -i "$QUICK_MENU_FILE" $qm_post_seek -t "$QM_MENU_TIME" \
    -an $PADDING -r $ff_frame_rate \
    $PAD_CLR -f yuv4mpegpipe -vcodec rawvideo -y "$yuvout")
    # removed-s $VIDSIZE from following cmd, don't think it needs it
    # check if I need to add a scale filter, perhaps comma sep at end.
    # http://forum.videohelp.com/threads/338494-Multiple-filter-problem-with-ffmpeg-help-please
    QUICKMENU_CMD=($FFmpeg -f yuv4mpegpipe \
    -i "$yuvout" -an -f mpeg2video -r $ff_frame_rate \
    $VB 7000k -maxrate 8000k -bufsize 224KiB \
    "${ffmpeg_filter[@]}" -y "$WORK_DIR/intro.m2v")
    echo "Running ${PAD_CMD[@]}" > "${LOG_FILE}-1.tmp"
    "${PAD_CMD[@]}" < /dev/null  >> "${LOG_FILE}-1.tmp" 2>&1 &
    echo "Running ${QUICKMENU_CMD[@]}" > "${LOG_FILE}-2.tmp"
    "${QUICKMENU_CMD[@]}" < /dev/null  >> "${LOG_FILE}-2.tmp" 2>&1 &
    ffmpeg_pid=$!
    if ! $QM_PREVIEW; then
        while ps -p $ffmpeg_pid >/dev/null; do
            sleep 1
            [[ -s "$WORK_DIR/intro.m2v" ]] && txt="Writing" || txt="Seeking"
            spin $txt $SPINNER
        done
    fi
    wait
    ! $QM_PREVIEW && yecho ""
    # remove control characters and seeking lines
    [[ -e ${LOG_FILE}-1.tmp ]] && \
      cat "${LOG_FILE}-1.tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
    [[ -e ${LOG_FILE}-2.tmp ]] && \
      cat "${LOG_FILE}-2.tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
    if [[ ! -s "$WORK_DIR/intro.m2v" ]]; then
        runtime_error "There was a problem creating the menu video $funct_arg"
    fi
    rm -f "${LOG_FILE}*.tmp"
    ! $QM_PREVIEW && yecho ""
    # create preview images if called for, taking largest of 10 images
    if $QM_PREVIEW; then
        FFMPEG_CMD=($FFmpeg -i "$WORK_DIR/intro.m2v" -an -vframes 10 \
        -f image2 -y "$outdir"/%06d.$IMG_FMT)
        print2log "Running ${FFMPEG_CMD[@]}"
        "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
        # take the largest image (best quality?) of a 10 frame sampling
        largest_img=$(get_largest 6 10 "$outdir" )
        mv "$largest_img" "$PREVIEW_IMG"
        print2log "Removing temporary preview files"
        rm -f "$WORK_DIR/intro.m2v"
        rm -f "$WORK_DIR"/showcase/*.$IMG_FMT "$WORK_DIR"/bg/*.$IMG_FMT
    fi
    $QM_PREVIEW && yecho ""
}

# 3x1 and 4x1 tile only for default arrangement
tile_warning()
{
    info_message "-tile-3x1 and -tile-4x1 are not showcase options.  Disabling"
    $WARN && continue_in 5
}
dvdauthor_error()
{
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    yecho "todisc encountered an error:"
    yecho "There was a problem creating the DVD structure"
    yecho "Saving files in "$WORK_DIR" so you can examine the situtaion"
    yecho "You can edit "$WORK_DIR/dvdauthor.xml" and rerun: "
    yecho "dvdauthor -x dvdauthor.xml from inside $REAL_WORK_DIR"
    yecho "Remove the symlink in /tmp when you are done"
    echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
    exit 1
}

confirm_backup()
{
    yecho
    yecho "Slideshows are an experimental (but well tested) feature.  Todisc is
    unlikely to overwrite your personal files, but you should take precautions
    and backup your images/files, as you would with any beta software."
    yecho "You can disable the check by using '-no-confirm-backup'"
    echo
    yecho "If and when you have backed up your images, type 'yes' to continue"
    read input
    echo
    if [ ! -z "$input" -a "$input" = "yes" ]; then
        CONFIRM_BACKUP=false
        NO_CONFIRM_BACKUP="-no-confirm-backup"
        yecho "Continuing..."
        yecho
    else
        yecho "Exiting..."
        yecho
        cleanup
        exit 0
    fi
}

make_dummy()
{
    convert  -resize $VIDSIZE! xc:"#101010" "$WORK_DIR/dummy.jpg"
    [[ $TV_STANDARD = "ntsc" ]] && local len=30 || local len=25
    ENC_CMD1=(jpeg2yuv -v 1 -f $FRAME_RATE -I p -n 1 -l $len \
    -L 1 -b1 -j "$WORK_DIR/dummy.jpg")
    ENC_CMD2=($FFmpeg -f yuv4mpegpipe -i - -an -r $ff_frame_rate \
    $FFMPEG_OPTS -vf scale=${VF_SCALE},${ASPECT} -y "$WORK_DIR/dummy.m2v")
    print2log "Running: ${ENC_CMD1[@]} | ${ENC_CMD2[@]}"
    ${ENC_CMD1[@]} 2>> "${LOG_FILE}.tmp"  |
    ${ENC_CMD2[@]} 2>&1 |pipe2log ${FFmpeg##*/}
    [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log jpeg2yuv
    rm -f "${LOG_FILE}.tmp"
    ! [[ -s "$WORK_DIR/dummy.m2v" ]] && \
      runtime_error "There was a problem creating a dummy vmgm video"
    local VMGM_TIME=1 # use one second as dummy.m2v or either 30 or 25 frames
    BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero -t $VMGM_TIME \
    $AUDIO_OPTS -y "$WORK_DIR/dummy.$AUDIO_EXT")
    print2log "Creating silent audio stream."
    print2log "${BGAUDIO_CMD[@]}"
    "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
    ! [[ -s "$WORK_DIR/dummy.$AUDIO_EXT" ]] &&  runtime_error \
    "There was a problem creating audio for the dummy vmgm menu"

    MPLEX_CMD=(mplex -V -f $MPLEX_FORMAT -o  "$BASEDIR/dummy.mpg" \
     "$WORK_DIR/dummy.$AUDIO_EXT"  "$WORK_DIR/dummy.m2v")
    print2log "Running: ${MPLEX_CMD[@]}"
    "${MPLEX_CMD[@]}" 2>&1 |pipe2log mplex
    ((${PIPESTATUS[0]} != 0)) && runtime_error \
    "There was a problem muxing the audio and video with mplex"
}
verify_infiles()
{
    # OUTFILE is $WORK_DIR/(basename of file without extension)
    verify_type=$1
    if [[ $verify_type = "infiles" ]]; then
        in_files=( "${IN_FILES[@]}" )
    else
        for f in ${!grouping[@]}; do
                in_files[f]=$(readlink -f "${grouping[f]}")
        done
    fi
    for ((i=0; i<${#in_files[@]}; i++)); do
        CROP_CMD=()
        IN_FILE="${in_files[i]}"
        if test -s "$IN_FILE"; then
            check_filetype "$IN_FILE"
            if [[ $file_type = "image" ]]; then
                IMG_STATS=( $(identify -ping -format "%z %w %h" "$IN_FILE") )
                DEPTH=${IMG_STATS[0]}
                IMG_WIDTH=${IMG_STATS[1]}
                IMG_HEIGHT=${IMG_STATS[2]}
                IMG_AR=$(bc_math "$IMG_WIDTH / $IMG_HEIGHT")
                if [[ $ASPECT_RATIO = "4:3" ]]; then
                    NEWSIZE=640x480
                else
                    NEWSIZE=640x360
                fi
                if [[ ${IMG_AR:0:4} != ${AR:0:4} ]]; then
                    CROP_CMD=(-resize  ${NEWSIZE}\> -size $NEWSIZE \
                    xc:'#101010' +swap -gravity center -composite)
                    PAD_IMG="yes"
                else
                    CROP_CMD=(-resize 640x480\!)
                fi
                OUTBASE=${IN_FILE##*/} # basename of file
                OUTFILE=${OUTBASE%.*} # basename of file less extention
                OUTFILE_GRP=${grouping[i]##*/} # basename of link
                OUTFILE_GRP=${OUTFILE_GRP%.*} # basename of link less extension
                OUTFILE_GRP=$(cut -f3-4 -d- <<< "$OUTFILE_GRP")
                OUTFILE_GRP=$(cut -f 1 -d. <<< "$OUTFILE_GRP") # group number
                if [[ $verify_type = "group" ]]; then
                    OUTFILE="$WORK_DIR/${TSET_NUM}-${OUTFILE_GRP}-${OUTFILE}"
                else
                    OUTFILE="$WORK_DIR/${TSET_NUM}-${i}-${OUTFILE}"
                fi
                OUTPNG="${OUTFILE}.png"
                # ffmpeg image2 can't handle 16 bit depth - convert it
                # also convert if not PNG or JPEG or wrong aspect ratio
                # test IN_FILES for preview - group files tested later
                if [[ $DEPTH = 16 || $PAD_IMG = "yes" ]] || $CONVRT ; then
                    print2log "Converting $IN_FILE to proper image format"
                    IMG_CMD=(convert "$IN_FILE" -depth 8 "${CROP_CMD[@]}" \
                    -quality 01 "$OUTPNG")
                    print2log "${IMG_CMD[@]}"
                    "${IMG_CMD[@]}" 2>&1| pipe2log imagemagick
                    # replace IN_FILES[i] OR group symlink
                    if [[ $verify_type = "infiles" ]]; then
                        IN_FILES[i]=$OUTPNG
                    else # this symlink gets replaced with the mpeg later
                        if [[ -L ${grouping[i]} ]]; then
                            png_out="${grouping[i]##*/}"
                            ln -sf "$OUTPNG" "$WORK_DIR/$png_out"
                            # replace saved link to original file too
                            ln -sf "$OUTPNG" \
                            "$WORK_DIR/${png_out/group/slide_grp}"
                        fi
                    fi
                fi
                if [[ $verify_type = "infiles" ]]; then
                    if [[ "$SC_FRAMESTYLE" = "glass" ]]; then
                        # make mpeg with ffmpeg now since OUTFILE is a link
                        image2mpeg2 "${IN_FILES[i]}" \
                        "$WORK_DIR/${OUTFILE##*/}.mpg"
                        # replace IN_FILE link with actual new file
                        IN_FILES[i]=$WORK_DIR/${OUTFILE##*/}.mpg
                    else
                        file_is_image[i]="yes" # encode to mpeg later
                    fi
                else
                    grp_file_is_image[i]="yes"
                fi
                spin checking "${IN_FILE##*/}"
            elif is_video "$IN_FILE"; then
                checkfile="${IN_FILE##*/}"
                spin checking "$checkfile"
            else
                usage_error "Sorry, $IN_FILE is not a supported file type"
            fi
        else
            usage_error "Sorry, $IN_FILE does not exist or is empty"
        fi
    done
    echo
}

# contrasting 'undercolor' for -background from given font colour
# usage: get_contrasting_colour COLOUR (rgb , named, or hex syntax)
get_contrasting_color()
{
    ucolor=$(convert -size 20x20 xc:$1 -fx 1-intensity -threshold 50% \
    -depth 8 txt:- 2>/dev/null |  awk '{ field = $NF }; END{ print field }')
    if [[ -z $ucolor ]]; then
        CONTRAST_CLR="none"
    else
        if [[ $ucolor = "black" ]]; then
            CONTRAST_CLR="#101010"
        else
            CONTRAST_CLR="gray"
        fi
    fi
}

# get safe NTSC colour
get_safe_colour()
{
    unset SAFE_CLR
    if [[ $1 ]]; then
        case $1 in
            '#ffffff'|'#FFFFFF'|white) SAFE_CLR='#EAEAEA' && \
              SUB_CLRS+=( "${1}:${SAFE_CLR}" );;
            '#000000'|black) SAFE_CLR='#101010' && \
              SUB_CLRS+=( "${1}:${SAFE_CLR}" );;
            '#FF0000'|'#ff0000'|red) SAFE_CLR='#EB2D2D' && \
              SUB_CLRS+=( "${1}:${SAFE_CLR}" );;
            '#FFFF00'|'#ffff00'|yellow) SAFE_CLR='#EBEB2D' && \
              SUB_CLRS+=( "${1}:${SAFE_CLR}" );;
            '#0000FF'|'#0000ff'|blue) SAFE_CLR='#2D2DEB' && \
              SUB_CLRS+=( "${1}:${SAFE_CLR}" );;
            *) return 1
        esac
    fi
}

# see http://www.imagemagick.org/Usage/photos/#binning
# the function is modified from a script by Walter Dnes with thanks
get_binning_cmd()
{
    ind=$1
    inpic="$2"; outpic="$WORK_DIR/${ind}.ppm"
    dimensions=$(identify -ping -format %wx%h "$inpic")
    x=${dimensions/x*}
    y=${dimensions/*x}
    # only do binning resize if doing 'full screen' and image width is > 1440
    # and user did not ask specifically not to
    if { ((x>1440)) || ((y>1440)) ; } && \
     $DO_BINNING && (( ${CAROUSEL_SIZE/x*} > 400 )); then
        for bin_size in 1 2 3 4 5 6 7 8; do
            newx=$(( x / bin_size ))
            # ppmtoy4m needs a multiple of 2 (hopefully doesn't affect binning)
            newx=$(( (newx / 2) * 2 ))
            ((newx<=BINMAX)) && break
        done
    else
        return 0
    fi

    checkx=$(( newx * bin_size ))
    (( checkx != x )) && crop_flag="YES"

    newy=$(( y / bin_size ))
    newy=$(( (newy / 2) * 2 )) # must be multiple of 2 for ppmtoy4m
    checky=$(( newy * bin_size ))
    (( checky != y )) && crop_flag="YES"

    [[ -n $crop_flag ]] && crop_args="-crop ${checkx}x${checky}+0+0 +repage"
    unset PPM_ENC_CMD
    BINNING_CMD=(convert "$inpic" $crop_args -depth 8 \
    -filter box -resize ${newx}x${newy} ${SLIDE_BLUR[p]} "$outpic")
}

# make dvd-slideshow config file if using -use-dvd-slideshow
mk_dvd_slideshow_conf()
{
    if $SLIDE_FADE; then
        [[ $EFFECT = "fade" ]] && fadein=fadein:1 && fadeout=fadeout:1
        [[ $EFFECT = "crossfade" ]] && crossfade=crossfade:1
    fi
    (
    cat <<EOF
    fadein:1
    $(for i in ${!MIX_IN[@]}; do
        echo $fadein
        echo ${MIX_IN[i]}:$MIX_SLIDE_LEN
        if (( i < (${#MIX_IN[@]} - 1) )); then
            [[ $EFFECT = "crossfade" ]] && echo $crossfade
            echo $fadeout
        fi
    done)
    fadeout:1
EOF
    ) | sed '/^$/d;s/^[ \t]*//' > "$WORK_DIR/dvd-slideshow.conf"
}

transition_slide()
{
    local fade_type=$1
    local value
    index=$2
    outppm="$WORK_DIR/animenu/$(printf %06d%s $index .ppm)"
    if [[ $fade_type = "crossfade" ]]; then
        value=$( ${bC} -l <<< "scale=2; ($fade_slide + 1) * $fade_incr") >&2
        fade_cmd=(composite -blend $value -depth 8 "$overlay_ppm" \
        "$base_ppm" "$outppm")
    elif [[ $fade_type = "fadein" ]]; then
        value=$( ${bC} -l <<< "scale=2; $fade_slide * $fade_incr") >&2
        fade_cmd=(composite -depth 8 "$base_ppm" "$WORK_DIR/black.ppm" \
        -blend ${value}% "$outppm")
    elif [[ $fade_type = "fadeout" ]]; then
        value=$( ${bC} -l <<< "scale=2;100 - (($fade_slide + 1) * $fade_incr)") >&2
        (( $( ${bC} <<< "$value < 0") == 1 )) && value=0
        fade_cmd=(composite -depth 8 "$base_ppm" "$WORK_DIR/black.ppm" \
        -blend ${value}% "$outppm")
    fi
     "${fade_cmd[@]}" >/dev/null
}

# this function does a loop with transition_slide() ... combine them into 1 ?
do_transitions()
{
    local fade_type=$1
    fade_slide=0
    for ((i=0; i<=fade_frames; i++)); do
        transition_slide $fade_type $i &
        transition_pids="$transition_pids $!"
        ((num_procs++))
        if ((num_procs == max_procs || i == fade_frames-1)); then
            wait $transition_pids 2>/dev/null
            unset transition_pids num_procs
        fi
        let fade_slide=fade_slide+1
    done
    if [[ $fade_type = "fadeout" ]] && ((f == ${#MIX_IN[@]}-1)); then
        for p in {0..12}; do
            cp "$WORK_DIR/black.ppm" \
            "$WORK_DIR/animenu/$(printf %06d%s $((p +i)) .ppm)" >&2
        done
    fi
}

# border and/or frame slides
border_and_frame()
{
    SLIDE_IN="$1"
    SLIDE_OUT="$2"
    convert  -size 640x480 "$SLIDE_IN" -mattecolor $SFRAME_CLR \
    -thumbnail ${tmbnail_size}\> $SLIDE_FRAME $SLD_BG +swap -gravity center \
    -composite "$SLIDE_OUT"
}

mk_polaroid_stack()
{
    local stackfiles=( "$@" )
    local CONVERT="convert -quality 01 -depth 8"
    local TSIZE=120x80
    local CANVAS_SIZE=640x480
    local rand_xmax=400
    local rand_ymax=200
    local rand_xoffset=80
    local rans_yoffset=50

    # this assignment not used in script, just for standalone demo purposes

    for i in ${!stackfiles[@]}; do

        # Use a 'random' angle
        local angle=$((RANDOM %45 +1))
        local angle=$(( (angle / 2) * 2 ))
        # use a 'random' direction of rotation
        #local rand_dir=$((RANDOM %2))
        #((rand_dir==0)) && randir="" || randir='-'
        rand_dir=""
        # thumbnail to 120x80 or 80x80 # TODO get working for pal
        $CONVERT "${stackfiles[i]}" -background none -thumbnail ${TSIZE}! \
        -bordercolor '#EAEAEA' -shave 5x5 +repage -border 4x4 \
        -bordercolor grey60 -border 1 \
        -rotate ${randir}${angle}  \
        -background  black  \( +clone -shadow 60x4+4+4 \) +swap \
        +repage -background none -flatten \
        "$WORK_DIR/tnail${i%.*}.png"
        stack_files[i]=$WORK_DIR/tnail${i%.*}.png

        # Composite the polaroid over the canvas

        # get 'random' coordinates
        local rand_xloc=$((RANDOM %rand_xmax + rand_xoffset))
        local rand_yloc=$((RANDOM %rand_ymax + rans_yoffset))
        local rand_loc="+${rand_xloc}+${rand_yloc}"
        local img_page[i]="-page $rand_loc"
    done
    for i in ${!stack_files[@]}; do
        local \
        image_page=( "${image_page[@]}" ${img_page[i]} "${stack_files[i]}" )
    done
    $CONVERT -background none -size $CANVAS_SIZE xc:none \
    "${image_page[@]}" -mosaic -trim +repage "$WORK_DIR/polaroid_stack.png"
}

get_elapsed()
{
    echo -e "\nIt took $(format_seconds $((etime-stime)) ) for the $1\n"
}

# Usage: check_maskshape SHAPE.  Returns 1 if SHAPE not found.
check_maskshape()
{
    SHAPE="$1"
    ! egrep -q -w \
    'oval|vignette|plectrum|flare|arch|spiral|blob|star|normal' \
    <<< "$SHAPE"  && \
    ! test -f "$TOVID_PREFIX/masks/${SHAPE}.png" && \
    ! test -f "$HOME/.tovid/masks/$SHAPE.png"
    (($? == 0)) && return 1 || return 0
}

# make an image mask for feathered shapes
# usage: make_mask SHAPE thumb|showcase
make_mask()
{
    local shape="$1"
    local mask_type="$2"
    if [[ $mask_type == "thumb" ]]; then
        local BLUR_CMD=( "${THUMB_BLUR_CMD[@]}" )
    else
        local BLUR_CMD=( "${SC_BLUR_CMD[@]}" )
    fi
    MASK="$WORK_DIR/${shape}_${mask_type}_mask.png"

    case "$shape" in
      "normal")
        convert -size $THUMB_SIZE xc:black -fill white \
        -draw "Rectangle $MASK_DIM" \
        +matte -compose CopyOpacity miff:- |
        convert - -bordercolor none -border 8x8 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "oval")
        convert -size $THUMB_SIZE xc:black -fill white \
        -draw "RoundRectangle $DIMY1,$DIMY1 $DIMY2,$DIMX2, $DIMY3,$DIMX3" \
        +matte -compose CopyOpacity miff:- |
        convert - -bordercolor none -border 6x6 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "vignette")
        convert -size 200x200 xc:white -background black -vignette 0x8 miff:- |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "flare")
        # with thanks to Fred Weinhaus for his starburst script and
        # Anthony Thyssen who did the original investigation of the technique
        # http://www.imagemagick.org/Usage/advanced/#radial_flares
        # test if imagemagick has -distort polar
        if ! convert -list distort | grep -q -w Polar; then
            usage_error "Your imagemagick version is too old to support the
              \"-distort polar\" technique used with the 'flare' thumb
              shape.  Upgrade your imagemagick to version 6.3.5-1 or
              newer, or use a different thumb shape."
        fi
        convert -size 200x1 xc: -seed 100 +noise Random -channel G -separate \
        +channel +level-colors black,white -size 200x199 xc:black -append \
        -motion-blur 66x65535-90 \( -size 200x132  gradient:white-black \
        -evaluate cos .5 -negate -evaluate pow 1.5 \) -compose screen \
        -composite -distort Polar -1 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert \( -size 200x200 xc:black \) \( - -level 0,100%  \) \
        -geometry +0+0 -composite miff:- |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "plectrum")
        convert -size 200x200 xc:none -fill white \
        -draw 'circle 100,100 150,150' miff:- |
        convert -background none -wave -50x456 - miff:- |
        convert - -bordercolor none -border 3x3 -trim +repage miff:- |
        convert - -bordercolor none -border 18x18 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "arch")
        convert -size 200x200 xc:none -fill white \
        -draw 'circle 25,30 10,30' -draw 'circle 25,170 10,170' \
        -draw 'circle 175,30 160,30' -draw 'circle 175,170 160,170' \
        -draw 'rectangle 25,15 180,185' -draw 'rectangle 10,25 190,175' miff:- |
        convert -background none -wave -50x456 - miff:- |
        convert - -bordercolor none -border 3x3 -trim +repage miff:- |
        convert - -bordercolor none -border 18x18 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "spiral")
        convert -size 200x200 xc:none -fill white \
        -draw 'circle 65,100 100,150' -draw 'circle 135,100 100,150' \
        -draw 'rectangle 60,38 140,162'  miff:-  |
        convert -background none -wave -80x188 - miff:- |
        convert -background none -swirl 1440 - miff:- |
        convert - -bordercolor none -border 3x3 -trim +repage miff:- |
        convert - -bordercolor none -border 18x18 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "star")
        convert -size 290x200 xc:none -fill white \
        -draw  "polygon 75,37.5  89.5,80.5 134.5,80.5 98.5,107.5 111.5,150.5 \
        75,125    38.5,150.5   51.5,107.5 15.5,80.5    60.5,80.5" miff:- |
        convert - -trim +repage miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      "blob")
        convert -size 100x60 xc:none -fill white \
        -draw "circle 41,39 44,57 circle 59,39 56,57 circle 50,21 50,3" miff:- |
        convert - -trim +repage -bordercolor none -border 10x10 miff:- |
        ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
        convert - -resize $THUMB_SIZE! $MASK
        ;;
      *)
        if test -f "$HOME/.tovid/masks/$shape.png"; then
            convert "$HOME/.tovid/masks/$shape.png" \
            -bordercolor none -border 3x3 -trim +repage miff:- |
            convert - -bordercolor none -border 18x18 miff:- |
            ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
            convert - -resize $THUMB_SIZE! $MASK

        elif test -f "$TOVID_PREFIX/masks/$shape.png"; then
            convert "$TOVID_PREFIX/masks/$shape.png" \
            -bordercolor none -border 3x3 -trim +repage miff:- |
            convert - -bordercolor none -border 18x18 miff:- |
            ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} | ${BLUR_CMD[@]} |
            convert - -resize $THUMB_SIZE! $MASK
        fi
        ;;
    esac
}

# wait for file to appear
# name and timeout are optional: defaults to basename of FILE and 12 secs 
# usage: wait_for file [name] [timeout]
wait_for()
{
    local check_file=$1
    local filename=${check_file##*/}
    # default timeout of 10 seconds
    local timeout=${3:-10}
    timeout=$((timeout * 10))
    local name=${2:-$filename}
    x=0
    while ((x<timeout)); do
        if test -e "$check_file"; then
            return
        fi
        # print a message after 2 seconds: will only run when there is a problem
        if ((x==20)); then
            echo Waiting $(( (timeout / 10) - 2)) seconds for $name to appear ...
        fi
        sleep .1
        ((x++))
    done
    unset x
    return 1
}

# HACK: transcode produces some scary output when run from python
print_tcode_info()
{
    echo -e "\n****\n$ME You can probably ignore 'critical' 'errors' from \
    transcode shown below if it shows transcode finishing the last image. \
    These harmless 'broken pipe' messages from transcode appear to be a \
    subtle bug in transcode when running it (or a script) from python. \
    \n****\n" | sed "s/    */ /g;s/^ *//" | pipe2log todisc format
}

# get the largest PNG (1st match sequentially if more than one are same size)
# images must be padded numbers as in 000001.png
#args: width [6] (pad width), last [10] (last img to test), img_dir [pwd] (dir)
# call without args to test from ./000000.png to ./000010.png
get_largest()
{
    unset c largest result
    local width=${1:-6}
    local last=${2:-10}
    local img_dir=${3:-$PWD}

    for num in $(seq 0 $last); do
        local img=$(printf %0${width}d $num)
        if [[ -e $img_dir/${img}.$IMG_FMT ]]; then
            c=$( du "$img_dir/${img}.$IMG_FMT" | cut -f1 )
            ((c > largest)) && largest=$c && result="$img_dir/${img}.$IMG_FMT"
        fi
    done
    echo $result
}

# tip from Steven M. Schultz
# https://www.mail-archive.com/mjpeg-users@lists.sourceforge.net/msg03511.html
# an alternative to yuvcorrect -T NO_HEADER
remove_header()
{
read junk
cat
return 0
}

##############################################################################
#                          	 End of Functions                                #
##############################################################################


trap 'cleanup; exit 13' TERM INT HUP

# ***********************************
# EXECUTION BEGINS HERE
# ***********************************

###############################################################################
#       Process arguments to the script, set up VARS and WORK_DIR             #
###############################################################################

# if -prefix is passed, show the prefix and exit
[[ ${args[0]} == '-prefix' ]] && echo $TOVID_PREFIX && exit 0

egrep -q 'titleset-mode|switched-mode|menu-only|carousel_menu_mode' <<< "$@" \
 && NONAME=:
! $NONAME && echo $"$SCRIPT_NAME"

while test $# -gt 0; do
    DO_SHIFT=:
    case "$1" in
        "-files" | "-slides" )
            unset sshows inc_files unset grp
            if [[ $1 = '-files' ]]; then
                incoming_vids=:; incoming_slides=false
            else
                incoming_vids=false; incoming_slides=:
            fi
            for i in ${args[@]}; do
                [[ $i = -slides  ]] && ((sshows++))
                [[ $i = -files ]] && ((inc_files++))
            done
            ((sshows==1)) && ((inc_files<1)) && SINGLE_SLIDESHOW=:
            shift
            get_listargs "$@"
            if $incoming_vids || [[ $sshows -eq 1 && $inc_files -lt 1 ]]; then
                for f in  ${!ARGS_ARRAY[@]}; do
                    FILENAMES[f]=${ARGS_ARRAY[f]}
                    filenames[f]=$(readlink -f "${ARGS_ARRAY[f]}")
                    if [[ ! -e ${filenames[f]} ]]; then
                        usage_error "${filenames[f]} does not exist"
                    fi
                done
                if $incoming_slides; then
                    SLIDESHOW=( ${SLIDESHOW[@]} : ) # is this a slideshow ?
                else
                    for f in ${!ARGS_ARRAY[@]}; do
                        SLIDESHOW=( "${SLIDESHOW[@]}" false )
                    done
                fi
                FILES=( "${FILES[@]}" "${filenames[@]}" )
            else
                ((num_slideshows++))
                ! $GROUPING && mk_workdir
                unset group groupkey grp x
                for ((i=0; i<${#ARGS_ARRAY[@]}; i++)); do
                    grp[x++]=$(readlink -f "${ARGS_ARRAY[i]}")
                    if [[ ! -e "${ARGS_ARRAY[i]}" ]]; then
                        usage_error "${ARGS_ARRAY[i]} does not exist"
                    fi
                done
                unset x
                [[ -z ${FILES[@]} ]] && ss_index=0 || ss_index=${#FILES[@]}
                SLIDESHOW[ss_index]=: # is this a slideshow ?
                FILES[ss_index]=$(readlink -f "${ARGS_ARRAY[0]}")
                GROUP_IN_FILES=( "${GROUP_IN_FILES[@]}" "${grp[@]}" )
                groupkey=${#FILES[@]}
                GROUP_ARR[groupkey-1]=${#grp[@]}
                ((groupkeys++))
                # create symlinks to ease substitution later
                for c in ${!grp[@]}; do
                    ln -s "${grp[c]}" \
                     "$WORK_DIR/${TSET_NUM}-group-$((groupkey))-$((c+1)).mpg"
                    # keep track of original images as above is overwritten
                    ln -s "${grp[c]}" \
                     "$WORK_DIR/${TSET_NUM}-slide_grp-$((groupkey))-$((c+1)).mpg"
                done
                GROUPING=:
            fi
            ;;
        "-titleset" )
            shift
            unset x ARGS_ARRAY
            while test $# -gt 0 && test "$1" != "-end-titleset"; do shift ; done
            if test $# -gt 0 && test x"${1:0:1}" = x"-";then DO_SHIFT=false; fi
            TITLESET_OPTS[y++]=${ARGS_ARRAY[@]}
            DO_TITLESETS=:
            ;;
       "-vmgm" )
            shift
            unset x ARGS_ARRAY
            # Hackish list-parsing
            while test $# -gt 0 && test "$1" != "-end-vmgm"; do
                ARGS_ARRAY[x++]="$1"
                shift
            done
            # Do not skip past the next argument
            if test $# -gt 0 && test x"${1:0:1}" = x"-";then
                DO_SHIFT=false
            fi
            VMGM_OPTS=( "${ARGS_ARRAY[@]}" )
            ;;
        "-group" )
            shift
            ! $GROUPING && mk_workdir
            get_listargs "$@"
            unset group groupkey grp x
            for ((i=1; i<${#ARGS_ARRAY[@]}; i++)); do
                grp[x++]=$(readlink -f "${ARGS_ARRAY[i]}")
            done
            GROUP_IN_FILES=( "${GROUP_IN_FILES[@]}" "${grp[@]}" )
            ((${ARGS_ARRAY[0]})) 2>/dev/null || usage_error "Arguments to \
            -group must be preceeded by a positive integer.  See 'man tovid'"
            groupkey=$(( ${ARGS_ARRAY[0]} - 1))
            GROUP_ARR[groupkey]=${#grp[@]}
            # temporary till I finish submenu groups TODO
            is_vidgroup[groupkey]=1
            # create symlinks to ease substitution later
            for c in ${!grp[@]}; do
                ln -s "${grp[c]}" \
                $WORK_DIR/${TSET_NUM}-group-$((groupkey+1))-$((c+1)).mpg
            done
            GROUPING=:
            ;;
        "-titles" )
            shift
            get_listargs "$@"
            OIFS=$IFS
            IFS=""
            TITLES=( "${TITLES[@]}" "${ARGS_ARRAY[@]}" )
            IFS=$OIFS
            ;;
        "-chapter-titles" )
            shift
            get_listargs "$@"
            OIFS=$IFS
            IFS=""
            for c in ${!ARGS_ARRAY[@]}; do
                CHAPTER_TITLES=("${CHAPTER_TITLES[@]}" "${ARGS_ARRAY[c]}")
            done
            IFS=$OIFS
            ;;
        "-slideshow-menu-thumbs" )
            shift
            get_listargs "$@"
            for f in  ${!ARGS_ARRAY[@]}; do
                SLIDESHOW_MENU_THUMBS[f]=$(readlink -f "${ARGS_ARRAY[f]}")
            done
            ;;
        "-submenu-titles" )
            shift
            get_listargs "$@"
            OIFS=$IFS;IFS=""
            SM_TITLES=( "${ARGS_ARRAY[@]}" )
            IFS=$OIFS
            ;;
        "-nomenu" | "-no-menu" )
            NOMENU=:
            ;;
        "-encode-only" )
            ENCODE_ONLY=:
            NOMENU=:
            ;;
        "-out" )
            shift
            OUT_DIRECTORY="$1"
            OUT_DIRECTORY=${OUT_DIRECTORY%/}
            ;;
        "-no-ask" | "-noask" )
            NOASK=:
            ;;
        "-no-warn" | "-nowarn" )
            WARN=false
            ;;
        "-debug" )
            DEBUG=:
            KEEP_FILES=:
            ;;
        "-grid" )
            GRID=1
            ;;
        "-keep-files" )
            KEEP_FILES=:
            ;;
        "-svcd" )
            usage_error \
            "Todisc does only DVD's now.  Use the tovid, makemenu, makexml
            and makevcd scripts instead (simple menus)."
            ;;
        "-ntsc" )
            TV_STANDARD="ntsc"
            ;;
        "-pal" )
            TV_STANDARD="pal"
            PIXEL_AR="59:54"
            ;;
        "-aspect" )
            unset ASPECT ASPECT_ARG
            shift
            ASPECT_ARG=$1
            if [[ ${#ASPECT_ARG[@]} -gt 0 ]]; then
            ASPECT_RATIO=$ASPECT_ARG
            [[ $ASPECT_RATIO = "16:9" ]] && AR=177 || AR=133
            # below used by dvdauthor, not ffmpeg
            V_ASPECT="aspect=\"$ASPECT_RATIO\""
            fi
            ;;
        "-widescreen" )
            shift
            get_listargs "$@"
            wsarg=${ARGS_ARRAY[0]}
            [[ -n $wsarg ]] &&  WIDESCREEN=$wsarg || WIDESCREEN="nopanscan"
            WIDE_SCREEN=:
            ;;
        "-safe-area" | "-showcase-safe-area" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            shift
            SAFE_AREA="$1"
            USER_SAFE_AREA=:
            ;;
        "-align" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            shift
            BUTTON_GRAVITY=$1
            BUTTON_GRAVITY=$(tr A-Z a-z <<< $BUTTON_GRAVITY) # West => west
            [[ $BUTTON_GRAVITY = "centre" ]] && BUTTON_GRAVITY="center"
            USER_GRAVITY=:
            ;;
        # Menu control options
        "-menu-length" )
            shift
            unset MENU_LEN
            get_listargs "$@"
            MENU_LEN=${ARGS_ARRAY[@]}
            MENU_LEN=( ${MENU_LEN//,/ } )
            USER_MENU_LEN=:
            ;;
        "-submenu-length" )
            shift
            get_listargs "$@"
            SUBMENU_LEN=${ARGS_ARRAY[@]}
            SUBMENU_LEN=( ${SUBMENU_LEN//,/ } )
            USER_SUBMENU_LEN=:
            ;;
        "-static" )
            STATIC=:
            ;;
        "-animated" )
            STATIC=false
            ;;
        "-menu-fade" )
            shift
            get_listargs "$@"
            if [[ -n ${ARGS_ARRAY[0]} ]]; then
                if [[ ${ARGS_ARRAY[0]} = *:* ]]; then
                    transition_time=$(unformat_time ${ARGS_ARRAY[0]})
                else
                    transition_time=${ARGS_ARRAY[0]}
                fi
                if test_is_number $transition_time ; then
                    TRANSITION_TO_MENU_LEN=$transition_time
                else
                    usage_error "the argument for --menu-fade must be in
                    in seconds or HH:MM:SS format"
                fi
            else
                # use the default menu-fade
                TRANSITION_TO_MENU_LEN=1
            fi
            MENU_FADE=:
            AUDIO_FADE=:
            ;;
        "-transition-to-menu" )
            TRANSITION_TO_MENU=:
            MENU_FADE=:
            AUDIO_FADE=:
            ;;
        "-tile-3x1" | "-tile3x1" )
            THREExONE=:
            tile_arg="$1"
            ;;
        "-tile-4x1" | "-tile4x1" )
            FOURxONE=:
            tile_arg="$1"
            ;;
        "-thumb-columns") # same as -tile-4x1 and -tile-3x1
            tile_arg="$1"
            shift
            THUMB_COLUMNS=$1
            if [[ $THUMB_COLUMNS == 4 ]]; then
                FOURxONE=:
            elif [[ $THUMB_COLUMNS == 3 ]]; then
                THREExONE=:
            else
                usage_error "-thumb-columns uses only '3' or '4' as an argument"
            fi
            ;;
        "-loop" )
            unset pause_time
            shift
            #get_listargs "$@"
                unset x ARGS_ARRAY
            # if begins with '-' only -1 is a valid option, else stop
            while test $# -gt 0 && [[ ${1:0:2} != -[a-zA-Z2-9] ]]; do
                ARGS_ARRAY[x++]="$1"
                shift
            done
            # Do not skip past the next argument
            if test $# -gt 0 && test x"${1:0:1}" = x"-";then
                DO_SHIFT=false
            fi

            pause_time=${ARGS_ARRAY[0]}
            if [[ -n $pause_time ]]; then
                PAUSE_TIME=$pause_time
                ((PAUSE_TIME==-1)) && PAUSE_TIME='inf' # gui uses -1 for 'inf'
            else
                usage_error "-loop requires a numeric argument"
            fi
            USER_LOOP=:
            ;;
        "-video-pause" | "-slide-pause" )
            shift
            svcd_pause=$1
            get_listargs "$@"
            [[ -n "${ARGS_ARRAY[@]}" ]] && VPAUSE=( "${ARGS_ARRAY[@]}" )
            ;;
        "-group-video-pause" )
            shift
            get_listargs "$@"
            GRP_VPAUSE=( "${ARGS_ARRAY[@]}" )
            ;;
        "-slide-menu-mix" ) # removed
            shift
            usage_error "-slide-menu-mix has been changed - see manpage"
            ;;
        "-slideshow" ) # removed
            shift
            usage_error "Use -slides now instead of -slideshow"
            ;;
        "-slide-fade" ) # removed
            shift
            usage_error "Use -slide-transition fade|crossfade \
            now instead of -slide-fade"
            ;;
        "-menu-slide-total" )
            shift
            get_listargs "$@"
            MIX_RANGE=${ARGS_ARRAY[@]}
            MIX_RANGE=( ${MIX_RANGE//,/ } )
            ;;
        "-submenu-slide-total" )
            shift
            get_listargs "$@"
            SM_MIX_RANGE=${ARGS_ARRAY[@]}
            SM_MIX_RANGE=( ${SM_MIX_RANGE//,/ } )
            ;;
        "-slide-transition" )
            shift
            EFFECT=$1
            if ! egrep -q -w 'fade|crossfade'  <<< "$EFFECT"; then
                usage_error "The -slide-transition argument must be 'fade' \
                or 'crossfade' (default if option unused: 'crossfade')"
            fi
            SLIDE_FADE=:
            ;;
        "-background-slideshow" | "-bg-slideshow" )
            CAROUSEL_IS_BG=:
            SHOWCASE=:
            IMG_FMT="png"
            BG_SEEK=0
            ;;
        "-showcase-slideshow" )
            CAROUSEL_IS_SHOWCASE=:
            SHOWCASE=:
            IMG_FMT="png"
            SHOWCASE_SEEK_VAL=0
            ;;
        "-use-dvd-slideshow" )
            shift
            get_listargs "$@"
            if [[ -n ${ARGS_ARRAY[@]} ]]; then
                SLIDESHOW_CONF=$(readlink -f "${ARGS_ARRAY[0]}")
            fi
            USE_DVD_SLIDESHOW=:
            ;;
        "-jobs" )
            shift
            ! test_is_number $1 && \
            usage_error "-jobs requires a numerical argument (integer)"
            JOBS=$1
            max_procs=$JOBS
            ;;
        "-nr" )
            shift
            get_listargs "$@"
            if [[ ${ARGS_ARRAY[0]} ]]; then
                test_is_number ${ARGS_ARRAY[0]} && NR_AMT=${ARGS_ARRAY[0]}
            else
                usage_error "The argument to -nr must be an integer"
            fi
            NR="-nr"
            ;;
        "-slide-blur" )
            shift
            get_listargs "$@"
            if ((${#ARGS_ARRAY[@]} <= 1)); then
                if [[ -n ${ARGS_ARRAY[0]} ]]; then
                    SLIDE_BLUR_OPT=${ARGS_ARRAY[0]}
                else
                    SLIDE_BLUR_OPT=0x0.2
                fi
            else
                for f in ${!ARGS_ARRAY[@]}; do
                    SLIDE_BLUR_OPT[f]=${ARGS_ARRAY[f]}
                done
            fi
            ;;
        "-slides-to-blur" )
            shift
            get_listargs "$@"
            for f in ${!ARGS_ARRAY[@]}; do
                BLURFILES[f]=${ARGS_ARRAY[f]##*/}
            done
            ;;
        "-slides-to-bin" )
            shift
            get_listargs "$@"
            for f in ${!ARGS_ARRAY[@]}; do
                FILES2BIN[f]=${ARGS_ARRAY[f]##*/}
            done
            ;;
        "-slide-border" )
            shift
            get_listargs "$@"
            if [[ -n ${ARGS_ARRAY[0]} ]]; then
                if test_is_number ${ARGS_ARRAY[0]}; then
                    SBORDER_ARG=${ARGS_ARRAY[0]%%.*}
                else
                    usage_error \
                    "-slide-border takes a single integer as an argument"
                fi
            else # no argument given - set default at 100
                SBORDER_ARG=100
            fi
            ;;
        "-slide-frame" )
            shift
            get_listargs "$@"
            if [[ -n ${ARGS_ARRAY[0]} ]]; then
                if test_is_number ${ARGS_ARRAY[0]}; then
                    SFRAME_ARG=${ARGS_ARRAY[0]%%.*}
                else
                    usage_error \
                    "-slide-border takes a single integer as an argument"
                fi
            else # use default value
                SFRAME_ARG=12
            fi
            SLIDE_FRAME="-frame"
            ;;
        "-slide-frame-color" | "-slide-frame-colour" )
            opt=$1
            shift
            [[ -n $1 ]] && SFRAME_CLR="$1" ||
             usage_error "$opt takes an argument - the ${opt/*-} for the frame"
            ;;
        "-chain-videos" )
            shift
            get_listargs "$@"
            chains_in=${ARGS_ARRAY[@]}
            post_play=${chains_in//,/ }
            CHAIN_VIDEOS=:
            ;;
        "-playall" )
            PLAYALL=:
            ;;
        "-background" )
            shift
            BACKGROUND=$(readlink -f "$1")
            USERS_BACKGROUND=:
            ! [[ -e "$BACKGROUND" ]] && \
            usage_error "background \"$BACKGROUND\" does not exist"
            ;;
        "-submenu-background" )
            shift
            get_listargs "$@"
            for f in  ${!ARGS_ARRAY[@]}; do
                SM_BACKGROUND[f]=$(readlink -f "${ARGS_ARRAY[f]}")
                ! [[ -e ${SM_BACKGROUND[f]} ]] && usage_error \
                "submenu background \"${SM_BACKGROUND[f]}\" does not exist"
            done
            ;;
        "-intro" )
            shift
            DO_INTRO=:
            INTRO_CLIP=$(readlink -f "$1")
            ! [[ -e "$INTRO_CLIP" ]] && \
            usage_error "intro clip \"$INTRO_CLIP\" does not exist"
            ;;
        "-showcase" )
            shift
            get_listargs "$@"
            unset f
            for f in  ${!ARGS_ARRAY[@]}; do
                SHOWCASE_FILE[f]=$(readlink -f "${ARGS_ARRAY[f]}")
            done
            SHOWCASE=:
            IMG_FMT="png"
            ;;
        "-textmenu" | "-text-menu" )
            shift
            get_listargs "$@"
            arg=${ARGS_ARRAY[0]}
            [[ -n $arg && $arg = 0 ]] && usage_error "Using '0' as an arg for -textmenu not allowed -
            use -align east (northeast, southeast) for 1 right-aligned column"
            [[ -n $arg ]] && SPLIT=$arg && USER_SPLIT=:
            TEXTMENU=:
            ;;
        "-edge-justify")
            EDGE_JUSTIFY=:
            ;;
        "-text-start" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            shift
            TEXT_YSTART=$1
            ;;
        "-showcase-titles-align" )
            shift
            SC_TITLE_ALIGN="$1"
            SC_TITLE_ALIGN=$(tr A-Z a-z <<< $SC_TITLE_ALIGN) # West => west
            [[ SC_TITLE_ALIGN = "centre" ]] && SC_TITLE_ALIGN="center"
            ;;
        "-titles-gap" | "-title-gap" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            shift
            SPACER=$1
            ;;
        "-rotate" )
            shift
            ROTATE_DEGREES="$1"
            if test_is_number $ROTATE_DEGREES; then
                ROTATE="-rotate $ROTATE_DEGREES"
            else
                usage_error "Argument to -rotate must be a number"
            fi
            IMG_FMT="png"
            ;;
        "-wave" )
            shift
            get_listargs "$@"
            wave=${ARGS_ARRAY[0]}
            if [[ -n $wave ]]; then
                if [[ $wave = "default" ]]; then
                    WAVE="-wave -20x556"
                else
                    WAVE="-wave $wave"
                fi
            else
                # a hack to address a current lack in metagui for todiscgui
                WAVE="-wave -20x556"
            fi
            ;;
        "-showcase-framestyle" )
            shift
            SC_FRAMESTYLE="$1"
            ;;
        "-thumb-shape" )
            shift
            THUMB_SHAPE="$1"
            FEATHER=:
            IMG_FMT="png"
            ;;
        "-showcase-shape" )
            shift
            SHOWCASE_SHAPE="$1"
            ;;
        "-button-style" )
            shift
            BUTTON_STYLE="$1"
            USER_BSTYLE=:
            ;;
        "-3d-thumbs" | "-3dthumbs" )
            THUMBS_3D=:
            RAISE="-raise 8x8"
            ;;
        "-3d-showcase" | "-3dshowcase" )
            SHOWCASE_3D=:
            SC_RAISE="-raise 8x8"
            ;;
        "-thumb-frame-colour" | "-thumb-frame-color" )
            shift
            THUMB_FRAME_CLR="$1"
            ;;
        "-thumb-frame-size" )
            shift
            tfsize="$1"
            if test_is_number "$tfsize"; then
                THUMB_FRAME_SIZE="${tfsize}x${tfsize}"
                USER_THUMB_FRAME_SIZE=1
            else
                usage_error "-thumb-frame-size requires an integer as argument"
            fi
            ;;
        "-showcase-frame-colour" | "-showcase-frame-color" )
            shift
            SHOWCASE_FRAME_CLR="$1"
            ;;
        "-showcase-frame-size" )
            shift
            sfsize="$1"
            if test_is_number "$sfsize"; then
                SHOWCASE_FRAME_SIZE="${sfsize}x${sfsize}"
                USER_SHOWCASE_FRAME_SIZE=1
            else
                usage_error "-showcase-frame-size requires an integer as argument"
            fi
            ;;
        "-thumb-blur" | "-blur" )
            shift
            if ! test_is_number "$BLUR"; then
                usage_error "-blur requires an integer as argument"
            fi
            THUMB_BLUR="$1"
            (( ${THUMB_BLUR%.*} >= 2 )) && THUMB_BLUR=2
            USER_BLUR=1
            ;;
        "-showcase-blur" )
            shift
            if ! test_is_number "$SC_BLUR"; then
                usage_error "-showcase-blur requires an integer as argument"
            fi
            SC_BLUR="$1"
            (( ${SC_BLUR%.*} >= 2 )) && SC_BLUR=2
            SC_USER_BLUR=1
            ;;
        "-menu-title-colour" | "-menu-title-color" | \
        "-title-colour" | "-title-color" )
            shift
            TITLE_CLR="$1"
            ;;
        "-submenu-font" )
            shift
            SM_TITLE_FONT="$1"
            ;;
        "-submenu-fontsize" )
            shift
            SUBMENU_FONTSIZE="$1"
            ;;
        "-submenu-title-colour" | "-submenu-title-color" )
            shift
            SM_TITLE_CLR="$1"
            ;;
        "-menu-title-stroke" | "-title-stroke" )
            shift
            M_TITLE_STROKE="$1"
            ;;
        "-titles-stroke" )
            shift
            V_TITLES_STROKE="$1"
            ;;
        "-submenu-stroke" )
            shift
            SUBMENU_STROKE="$1"
            ;;
        "-titles-opacity" )
            shift
            test_is_number $1 && TITLES_OPACITY="$1"
            ;;
        "-menu-title-opacity" | "-title-opacity" )
            shift
            test_is_number $1 && TITLE_OPACITY="$1"
            ;;
        "-submenu-title-opacity" )
            shift
            test_is_number $1 && SM_TITLE_OPACITY="$1"
            ;;
        "-chapter-title-opacity" )
            shift
            test_is_number $1 && CHAPTER_TITLES_OPACITY="$1"
            ;;
        "-chapter-stroke" )
            shift
            CHAPTER_STROKE="$1"
            ;;
        "-chapter-color" | "-chapter-colour" )
            shift
            CHAPTER_CLR="$1"
            ;;
        "-titles-colour" | "-titles-color" )
            shift
            TITLES_CLR="$1"
            ;;
        "-highlight-colour" | "-highlight-color" )
            shift
            HLIGHT_CLR="$1"
            ;;
        "-select-colour" | "-select-color" )
            shift
            SELECT_CLR="$1"
            ;;
        "-menu-title-font-deco" | "-title-font-deco" | \
        "-menu-title-fontdeco" | "-title-fontdeco")
            shift
            USE_M_TITLE_DECO=:
            M_TITLE_FONT_DECO=($1)
            ;;
        "-titles-font-deco" | "-titles-fontdeco" )
            shift
            USE_V_TITLES_DECO=:
            V_TITLES_FONT_DECO=($1)
            ;;
        -thumb-text-col* | "-thumb-font" | "-thumb-fontsize" ) # removed
            usage_error \
            "The $1 option now renamed.  Try: -titles-${1##*-} or check manual"
            ;;
        *-stroke-col* ) # removed
            usage_error \
            "The $1 option now renamed.  Try: ${1%-*} or check manual"
            ;;
        "-text-mist" )
            MIST=:
            ;;
        "-text-mist-opacity" )
            shift
            MIST_OPACITY="$1"
            ;;
        "-text-mist-colour" |"-text-mist-color" )
            shift
            MIST_COLOUR="$1"
            ;;
        "-thumb-mist-colour" |"-thumb-mist-color" )
            usage_error "$1 has been removed.  Use ${1%-*} [COLOR]"
            ;;
        "-thumb-mist" )
            unset thumb_bg_colour
            shift
            get_listargs "$@"
            thumb_bg_colour=${ARGS_ARRAY[0]}
            if [[ -n $thumb_bg_colour ]]; then
                THUMB_BG_CLR=$thumb_bg_colour
            else
                THUMB_BG_CLR="#FFFFFF" # default colour without args
            fi
            USE_FEATHER_MASK=:
            ;;
        "-opacity" )
            shift
            TRANSPARENT=:
            OPACITY="$1"
            ;;
        "-chapters" )
            unset CHAPTERS
            shift
            get_listargs "$@"
            CHAPTERS=${ARGS_ARRAY[@]}
            # user can pass HH:MM:SS chapters, else, remove possible comma sep
            ! [[ "$CHAPTERS" = *:* ]] && CHAPTERS=( ${CHAPTERS//,/ } )
            # a way to tell later if user passed HH:MM:SS chapters
            if [[ "$CHAPTERS" = *:* ]]; then
                [[ "$CHAPTERS" = *+* ]] && grouped_user_chapters=( $CHAPTERS )
                # make array, remove everything after and including 1st '+',
                CHAPTERS=( $CHAPTERS )
                #CHAPTERS=( ${CHAPTERS[@]%%+*} ) # in case of grouped chapters
                USER_CHAPTERS=: # user passed HH:MM:SS chapters
            fi
            ;;
        "-subtitle-lang" )
            shift
            SUBTITLES=:
            get_listargs "$@"
            SUBS=${ARGS_ARRAY[@]}
            SUBS_ARRAY=( ${SUBS//,/ } )
            ;;
        "-audio-channel" )
            shift
            get_listargs "$@"
            AUDIO_CHANNEL=${ARGS_ARRAY[@]}
            AUDIO_CHANNEL=( ${AUDIO_CHANNEL//,/ } )
            ;;
        "-audio-lang" )
            o=$1
            shift
            get_listargs "$@"
            LANGS=${ARGS_ARRAY[@]}
            LANGS=( ${LANGS//,/ } )
            for i in ${LANGS[@]}; do
                test_is_number "$i" && \
                usage_error "$o is for language codes now:
                perhaps you wanted '-audio-channel' ?"
            done
            ;;
        "-bgaudio" | "-bg-audio" )
            shift
            if [[ $1 = "none" ]]; then
                BG_AUDIO="none" # for switched menus
            else
                BG_AUDIO=$(readlink -f "$1")
                if [[ ! -e "$BG_AUDIO" ]]; then
                    usage_error "background audio \"$BG_AUDIO\" does not exist"
                fi
            fi
            ;;
        "-menu-audio-fade" )
            shift
            FADE="$1"
            AUDIO_FADE=:
            ;;
        "-submenu-audio" )
            shift
            get_listargs "$@"
            for i in ${!ARGS_ARRAY[@]}; do
                if [[ ${ARGS_ARRAY[i]} = "none" ]]; then
                    SM_AUDIO=( "${SM_AUDIO[@]}" "${ARGS_ARRAY[i]}" )
                else
                    if [[ ! -e "${ARGS_ARRAY[i]}" ]]; then
                        usage_error "audio file \"${ARGS_ARRAY[i]}\" not found"
                    else
                        SM_AUDIO=( "${SM_AUDIO[@]}" \
                        "$(readlink -f "${ARGS_ARRAY[i]}")" )
                    fi
                fi
            done
            SUBMENU_AUDIO=:
            ;;
        "-submenu-audio-fade" )
            shift
            SM_FADE="$1"
            ;;
        "-submenu-audio-length" ) # removed
            usage_error "The $1 option has been removed. Use -submenu-length to
            set the length of submenu audio for a static submenu. (yes now
            submenu lengths can be set)"
            ;;
        "-submenus" )
            SUB_MENU=:
            ;;
        "-ani-submenus" )
            ANI_SUB_MENU=:
            SUB_MENU=:
            ;;
        "-menu-title" )
            shift
            MENU_TITLE="$1"
            ;;
        "-menu-title-font" | "-title-font" | "-menu-font" )
            shift
            MENU_FONT=$(get_font "$1")
            ;;
        "-menu-title-fontsize" | "-title-fontsize" | "-menu-fontsize" )
            shift
            MENU_FONTSIZE="$1"
            ;;
        "-titles-font" )
            shift
            TITLES_FONT=$(get_font "$1")
            ;;
        "-titles-fontsize" )
            shift
            TITLES_FONTSIZE="$1"
            ;;
        "-chapter-font" )
            shift
            CHAPT_FONT=$(get_font "$1")
            ;;
        "-chapter-fontsize" )
            shift
            get_listargs "$@"
            CHAPT_FONTSIZE=( ${ARGS_ARRAY[@]} )
            ;;
        "-seek" )
            shift
            unset SEEK_VAL
            get_listargs "$@"
            SEEK_VAL=${ARGS_ARRAY[@]}
            SEEK_VAL=( ${SEEK_VAL//,/ } )
            USER_SEEK_VAL=:
            ;;
        "-showcase-seek" )
            shift
            SHOWCASE_SEEK_VAL="$1"
            ;;
        "-bg-video-seek" | "-bgvideo-seek" )
            shift
            BG_SEEK="$1"
            ;;
        "-bg-audio-seek" | "-bgaudio-seek" )
            shift
            BG_AUDIO_SEEK="$1"
            USER_BG_AUDIO_SEEK=:
            ;;
        "-showcase-geo" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            shift
            USER_SC_GEO=:
            SHOWCASE_GEO=$1
            ! grep -q "+[0-9]*+[0-9]*" <<< $SHOWCASE_GEO && usage_error \
            "-showcase-geo argument must be the position geometry in form +X+Y"
            ;;
        "-submenu-audio-seek" ) # not implemented yet
            shift
            get_listargs "$@"
            SM_AUDIO_SEEK=( ${ARGS_ARRAY[@]} )
            USER_SM_AUDIO_SEEK=:
            ;;
        "-menu-title-geo" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            USER_TITLE_GEO=:
            shift
            TITLE_GRAVITY=$1
            # centre => center ... no other direction has re in it :)
            TITLE_GRAVITY=${TITLE_GRAVITY/re/er}
            ;;
        "-menu-title-offset" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            USER_TITLE_GEO=:
            shift
            xpr='([-+][0-9]+)([-+][0-9]+)'
            [[ $1 =~ $xpr ]]
            [[ -n ${BASH_REMATCH[1]} ]] && title_xoffset=${BASH_REMATCH[1]}
            [[ -n ${BASH_REMATCH[2]} ]] && title_yoffset=${BASH_REMATCH[2]}
            ;;
        "-outlinewidth" )
            ADV_OPT=( "${ADV_OPT[@]}" "$1" )
            shift
            OUTLINEWIDTH="\"$1\""
            ;;
        "-rotate-thumbs" )
            shift
            parse_rotateargs "$@"
            ROTATE_ARRAY=( "${ARGS_ARRAY[@]}" )
            IMG_FMT="png"
            ROTATE_THUMBS=:
            ;;
        "-tovidopts" | "-tovid-opts" )
            usage_error "The -tovidopts option no longer exists.  Now just use
            the tovid options directly on the command line."
            ;;
        "-titleset-mode" ) # internal use only
            AUTHOR=false
            TITLESET_MODE=:
            ;;
        "-switched-mode" ) # internal use only
            SWITCHED_MODE=:
            TEXTMENU=:
            SC_TITLE_ALIGN="west"
            SHOWCASE=:
            ;;
        "-vmgm_only" ) # internal use only
            VMGM_ONLY=:
            ;;
        "-basedir" ) # internal use only
            shift
            BASEDIR="$1"
            ;;
        "-tset_num" ) # internal use only
            shift
            TSET_NUMS="$1"
            TSET_NUM=${TSET_NUMS/*-}
            TSET_TOT=${TSET_NUMS/-*}
            ;;
        "-vmgm_playall" ) # internal use only
            VMGM_PLAYALL=:
            ;;
        "-todisc_pids" ) # internal use only
            shift
            TODISC_PIDS="$TODISC_PIDS $1"
            ;;
        "-menu_num" ) # internal use only
            shift
            MENU_NUM="$1"
            ;;
        "-carousel_num" ) # internal use only
            shift
            CAROUSEL_NUM="$1"
            ;;
        "-title_count" ) # internal use only
            shift
            ALLTITLES=( $1 )
            ;;
        "-quick-nav" )
            QUICK_NAV=:
            ;;
        "-switched-menus" | "-switched-menu" )
            SWITCHED_MENUS=:
            TEXTMENU=:
            SHOWCASE=:
            SC_TITLE_ALIGN="west"
            ;;
        "-skip-vmgm" )
            SKIP_VMGM_MENU=:
            ;;
        "-no-vmgm-menu" | "-no-vmgm" )
            VMGM_MENU=false
            ;;
        "-no-top-menu" )
            usage_error "Option removed - no SVCD output available now"
            ;;
        "-videos-are-chapters" )
            VIDEOS_ARE_CHAPTERS=:
            ;;
        "-is_titleset" ) #FIXME - this is useless
            TSET_MODE=:
            ;;
        "-carousel_menu_mode" ) # internal use only
            MK_CAROUSEL_MODE=:
            ;;
        "-no-confirm-backup" )
            CONFIRM_BACKUP=false
            ;;
        "-burn" )
            BURN=:
            ;;
        "-device" )
            shift
            BURN_DEVICE="$1"
            ;;
        "-speed" )
            shift
            SPEED="$1"
            BURN_SPEED="-speed $SPEED"
            ;;
        "-eject" )
            EJECT="-eject"
            ;;
        "-quick-menu" )
            QUICK_MENU=:
            ;;
        "-bg-colour" | "-bg-color" )
            shift
            BG_CLR="$1"
            ;;
        "-submenu-bg-colour" | "-submenu-bg-color" )
            shift
            SUBMENU_BG_CLR="$1"
            ;;
        "-fast-seek" )
            FAST_SEEK=:
            ;;
        "-frame-safe" )
            FRAME_SAFE=:
            ;;
        "-user-thumbs" )
            shift
            get_listargs "$@"
            for f in  ${!ARGS_ARRAY[@]}; do
                USER_PICS[f]=$(readlink -f "${ARGS_ARRAY[f]}")
                ! [[ -e ${USER_PICS[f]} ]] && usage_error \
                "Your supplied thumb \"${USER_PICS[f]}\" does not exist"
            done
            USER_THUMBS=:
            ;;
        "-from-gui" )
            FROM_GUI=:
            ;;
        "-config" | "-ntscfilm" | "-dvd-vcd" | "-half-dvd" | "-kvcd" | \
        "-kvcdx3" | "-kvcdx3a" | "-kdvd" | "-bdvd" | "-704" | "-normalize" | \
        "-amplitude" | "-overwrite" | "-panavision" | "-force" | "-fps" | \
        "-vbitrate" | "-quality" | "-safe" | "-crop" | "-filters" | \
        "-abitrate" | "-priority" | "-deinterlace" | "-progressive" | \
        "-interlaced" | "-interlaced_bf" | "-type" | "-fit" | "-discsize" | \
        "-parallel" | "-mkvsub" | "-autosubs" | "-subtitles" | "-update" | \
        "-mplayeropts" | "-audiotrack" | "-downmix" | "-ffmpeg" | "-avconv" | \
        "-nofifo" | "-from-gui" | "-noask" | "-slice" | "-async" | "-quiet" | \
        "-fake" | "-keepfiles" )
            # remove this warning for tovid 0.33 TODO
            if [[ $1 = "-subtitles" ]]; then
                if (( ${#2} == 2 )); then
                    usage_error "todisc's '-subtitles' option has been changed
                    to '-subtitle-lang', so it doesn't conflict with a tovid
                    option by the same name"
                elif [[ ! -e $2 ]]; then
                    usage_error " subtitle file $2 does not exist"
                else
                    TOVID_OPTS+=( "$1" "$(readlink -f "$2")" )
                fi
            elif [[ $1 == "-config" ]]; then
                if [[ ! -e $2 ]]; then
                    usage_error "config file $2 does not exist"
                else
                    TOVID_OPTS+=( "$1" "$(readlink -f "$2")" )
                fi
            elif [[ $1 == '-mplayeropts' ]]; then
                # -mplayeropts can start with a '-' so just get entire string.
                # TODO allow using -mplayeropts for each video, use "" for none
                # [[  "${2+defined}" && -z $2 ]] ... MPLAYER_OPTS+=("")
                TOVID_OPTS+=("$1" "$2")
                shift
            else
                TOVID_OPTS+=( "$1" )
                shift
                get_listargs "$@"
                TOVID_OPTS+=( "${ARGS_ARRAY[@]}" )
            fi
            ;;
        -car* )
            usage_error "$1: No such option.  Please see 'man tovid' ?"
            ;;
    esac
    $DO_SHIFT && shift
done

##############################################################################
#                      Sanity checks and preliminaries                       #
##############################################################################

# get script pid so we can kill the parent if doing recursive todisc's
TODISC_PIDS="$TODISC_PIDS $$"
    ########################################################################
    ### Setup and error checks (Critical 1st, Warnings after log created ###
    ########################################################################

# make sure dvd-slideshow is installed if user passed -use-dvd-slideshow
$USE_DVD_SLIDESHOW && assert_dep dvd-slideshow \
"The program dvd-slideshow was not found - you can get it from
dvd-slideshow.sourceforge.net.  Note: if you do not use
-use-dvd-slideshow, todisc will create the slideshow video for you. "
assert_dep pgrep "You need the pgrep program to use todisc"
if $USE_DVD_SLIDESHOW; then
    if $STATIC && $ANI_SUBMENUS ||
     ((sshows>1 || inc_files>=1)); then
        usage_error "Sorry you can only use the dvd-slideshow program with
        single slideshows"
    fi
fi
# make sure user has backed up personal image files
((sshows>=1)) && $CONFIRM_BACKUP && confirm_backup
# link WORK_DIR to /tmp for easy solution to spaces, illegal chars bugs
! $GROUPING && mk_workdir
# set some other vars now that depended on *WORK_DIR being set
SPUMUX_XML="$WORK_DIR/spumux.xml"
DVDAUTHOR_XML="$WORK_DIR/dvdauthor.xml"
PREVIEW_IMG="$WORK_DIR/preview.$IMG_FMT"

# check for multiple cpus if -jobs not passed already
#TODO always wait for either 1 or 2 processes - no need for if block later
if [[ -z $JOBS ]]; then
    max_procs=$cpu_count # cpu_count is sourced from tovid-init
fi

if $BURN; then
    if [[ ! -b $(readlink -f $BURN_DEVICE) ]]; then
        usage_error \
        "$BURN_DEVICE is not a valid block device file or link to a block device.
        Are you sure your burner is \"${BURN_DEVICE}\"? Specify your burner with
        -device /path/to/burner."
    fi
fi

# Make sure equal, nonzero number of titles and files were provided

if ! $VMGM_ONLY && ! $DO_TITLESETS; then
    ((num_slideshows>0)) && ss_err="  A slideshow counts as one file.
     Please give one title for each slideshow. "
    if [[ ${#FILES[@]} -eq 0 ]]; then
        usage_error "Please provide at least one file."
    elif [[ -n ${TITLES[@]} ]] && [[ ${#FILES[@]} -ne ${#TITLES[@]} ]]; then
        if $SINGLE_SLIDESHOW; then
            ERR="Please do not pass '-titles' if doing a single slideshow"
        else
            ERR="Please give the same number of titles as files.
        You gave ${#FILES[@]} files and ${#TITLES[@]} titles.$ss_err"
        fi
        usage_error "$ERR"
    fi
fi
# for switched menus the 1st menu (MN) made is the 2nd, not the 1st
{ $SWITCHED_MODE || $SWITCHED_MENUS ; } && MN=2 || MN=1

if $DO_TITLESETS && ! $VMGM_MENU && ! $QUICK_NAV; then
    usage_error \
    "You can not use -no-vmgm if doing titlesets unless using -quick-nav"
fi
# some things the vmgm menu does not support
if $VMGM_ONLY; then
    SUB_MENU=false
    ANI_SUB_MENU=false
#    QUICK_MENU=false
    SM_TITLES=""
fi
# flesh out options needed for -quick-menu,-textmenu.  Check slideshow opts
if $QUICK_MENU; then
    if $MENU_FADE; then
        usage_error "-quick-menu is incompatible with -menu-fade"
    fi
    SC_TITLE_ALIGN="west"
    SHOWCASE=:
fi
# usage error on mispellings for *align* options
case $BUTTON_GRAVITY in
  north|south|east|west|northwest|northeast|southwest|southeast|center)
    :
    ;;
  *)
    usage_error "$BUTTON_GRAVITY is an incorrect argument for '-align'"
    ;;
esac
case $SC_TITLE_ALIGN in
  west|east|center)
    :
    ;;
  *)
    usage_error "$SC_TITLE_ALIGN is an incorrect argument for \
      '-showcase-titles-align'"
    ;;
esac
if $TEXTMENU; then
    SHOWCASE=:
    IMG_FMT="png"
    # default -align for textmenu is northwest, not north
    ! $USER_GRAVITY && BUTTON_GRAVITY="northwest"
elif $SHOWCASE; then
    ! $USER_GRAVITY && BUTTON_GRAVITY="northwest" # with thumbs, use defaults
fi
# incompatible slideshow options with -switched-menus
if { $CAROUSEL_IS_BG || $CAROUSEL_IS_SHOWCASE ; } && $SWITCHED_MENUS; then
    $CAROUSEL_IS_BG && OPT="-background-slideshow" || OPT="-showcase-slideshow"
    info_message "$OPT uses slides from ALL slideshows, so its use with \
     -switched-menus makes no sense.  Removing this option for you."
    CAROUSEL_IS_SHOWCASE=false; CAROUSEL_IS_BG=false
    $WARN && continue_in 5
fi
# slideshows are animated by default like rest of todisc
if ((sshows>=1)); then
    if $STATIC && \
     { ! $CAROUSEL_IS_SHOWCASE && ! $CAROUSEL_IS_BG ; }; then
        :
    else
        DO_CAROUSEL=:
        is_carousel=:
        SLIDE_FADE=:
    fi
fi

# you can not use submenus with slideshows
if ((num_slideshows>0)) && $SUB_MENU; then
    usage_error "You can not use submenus with slideshows.  If you have
    a mixed menu of videos and slideshows, but want submenus for the videos,
    you will have to put the videos in a separate titleset instead."
fi
    

#if $DO_CAROUSEL && $SHOWCASE && ! { $SWITCHED_MODE || $SWITCHED_MENUS ; } && \
# ! $CAROUSEL_IS_BG && ! $CAROUSEL_IS_SHOWCASE && ((sshows<=1)); then
#    yecho
#    usage_error "You are using an animated slideshow but not making a background or
#    showcase slideshow, so -textmenu or -showcase makes no sense."
#fi

if [[ -n "$SM_TITLES" ]]; then
    if test ${#SM_TITLES[@]} -ne ${#TITLES[@]}; then
    usage_error "Please give the same number of submenu titles as titles.
    You gave ${#SM_TITLES[@]} submenu titles and ${#TITLES[@]} titles"
    fi
fi
# titlesets use BASEDIR which is the WORK_DIR of the calling todisc
# BASEDIR is supplied by the calling todisc with -basedir
: ${BASEDIR:="$WORK_DIR"}

# Make sure -out was provided and it is valid
if test -n "$OUT_DIRECTORY"; then
    # for BSD readlink
    if [[ ! -d "$OUT_DIRECTORY" ]]; then
        mkdir "$OUT_DIRECTORY" || usage_error "Can not make $OUT_DIRECTORY"
	bsdoutdir=1
    fi
    OUT_DIR=$(readlink -f "$OUT_DIRECTORY")
    ((bsdoutdir)) && rmdir "$OUT_DIRECTORY"
    if [[ ! -d ${OUT_DIR%/*} ]]; then
        OUT_PATH=$(readlink -m "$OUT_DIRECTORY")
        usage_error "The -out path ${OUT_PATH%/*}/ does not exist"
    fi
    if egrep -q '<|>|&' <<< "$OUT_DIR"; then
        usage_error "Sorry, dvdauthor will not let you use a -out name \
        with '>', '<' or '&' in it.  Please choose another directory or \
        name for -out  You used: $OUT_DIR"
    elif test $(wc -l <<< "$(echo -e "$OUT_DIR")") -gt 1; then
        usage_error "Dvdauthor does not allow multiline directory names.
        Please change the directory you gave as an -out argument."
    fi
else
    ! $ENCODE_ONLY && usage_error "Please provide an output name with -out"
fi
### dvdauthor stuff
# for xml, if -intro was used
$DO_INTRO && INTRO="<vob file=\"$INTRO_CLIP\"/>"
# strangely we need to export this even if we specify <video format=ntsc|pal...>
export VIDEO_FORMAT=$TV_STANDARD

# switched menus need more than one video file
if $SWITCHED_MENUS && [[ ${#FILES[@]} -eq 1 ]]; then
    usage_error "You can not use switched menus with only one file"
fi

# don't make submenus on each recursive call in switched mode
if $SWITCHED_MODE; then
    ANI_SUB_MENU=false && SUB_MENU=false
fi
# disable submenus for some options
if $SUB_MENU && $SINGLE_SLIDESHOW; then
    usage_error "Sorry, no submenu for a single slideshow"
fi

if $VMGM_ONLY; then SWITCHED_MODE=false && SWITCHED_MENUS=false; fi
# -no-vmgm requires -skip-vmgm:  pass -no-vmgm-menu to subshells via NO_VMGM
if ! $VMGM_MENU; then
    SKIP_VMGM_MENU=:
    NO_VMGM="-no-vmgm-menu"
fi
if [ ${#MENU_LEN[@]} -eq 1 ]; then
    for ((i=0; i<${#FILES[@]}; i++)); do
        MENU_LEN[i]=${MENU_LEN[0]}
    done
fi
# initialize MENU_AUDIOLEN now that options have been read
[[ -n $BG_AUDIO ]] && MENU_AUDIOLEN=${MENU_LEN[MENU_NUM-1]}

# ffmpeg noise reduction
if [[ -n $NR ]]; then
    [[ -z $NR_AMT ]] && NR_AMT=200
    NR="$NR $NR_AMT"
fi

# assign values for slides
# blurs
if [[ -n ${BLURFILES[@]} ]]; then
    for i in ${!BLURFILES[@]}; do
        if [[ -z ${SLIDE_BLUR_OPT[i]} ]]; then
            SLIDE_BLUR_OPT[i]=${SLIDE_BLUR_OPT[0]}
        fi
    done
fi
# frames
if [[ -n $SLIDE_FRAME ]]; then # we are framing slides
    SFRAME=${SFRAME_ARG}x${SFRAME_ARG}
    SLIDE_FRAME="$SLIDE_FRAME $SFRAME"
fi
# now that frame-sizes and frame colours have been read in, set some vars

SHOWCASE_FRAME="-bordercolor  $SHOWCASE_FRAME_CLR -compose Copy"
SHOWCASE_FRAME="$SHOWCASE_FRAME -border $SHOWCASE_FRAME_SIZE"
# no frame with -3d-showcase
$SHOWCASE_3D && unset SHOWCASE_FRAME
# allow -showcase-frame-size (otherwise unused for 3D showcase) to set -raise
((USER_SHOWCASE_FRAME_SIZE)) && SC_RAISE="-raise $SHOWCASE_FRAME_SIZE"
THUMB_FRAME="-shave $THUMB_FRAME_SIZE +repage -border $THUMB_FRAME_SIZE"
# no frame with 3D thumbs which use '-raise'
$THUMBS_3D && unset THUMB_FRAME
# allow -thumb-frame-size (otherwise unused for 3D thumbs) to set -raise
((USER_THUMB_FRAME_SIZE)) && RAISE="-raise $THUMB_FRAME_SIZE"

# centre aligned titles under showcase thumbs need extra safe room
if [[ $SC_TITLE_ALIGN = center ]]; then
    SAFE_OFFSET=36
    $USER_SAFE_AREA && SAFE_OFFSET=$((86-SAFE_AREA))
fi

# honour -noask for functions and called scripts that use them
$NOASK && NO_ASK="-noask"

#####################################
#           backend checks          #
####################################

# transcode is needed for making animated submenu, else we can use just ffmpeg
hash transcode 2>/dev/null || use_transcode=false
# todisc should run if mjpegtools not installed, assumes -ffmpeg for 'tovid mpg'
hash yuvcorrect 2>/dev/null || yuv_correct=remove_header
#$ANI_SUB_MENU && assert_dep transcode "transcode is required for making
#  animated submenus"
if $use_transcode; then
    # transcode version >= 1.1.0 mandated
    _transcode_version=$(transcode -v 2>&1| awk '{gsub("v", ""); print $2}')
    _baseline_version=1.1.0
    if ! test_version $_transcode_version $_baseline_version; then
        test -f "$LOG_FILE" && rm -f "$LOG_FILE"
        runtime_error \
        "transcode version 1.1.0 or newer required to run this script (todisc).
        If you must use version $_transcode_version use tovid 0.34 or older."
    fi
    # stock debian transcode and probably others missing export_yuv4mpeg module
    if !  ls -1 $( tcmodinfo -p )/export*.so |grep -q yuv4mpeg; then
        test -f "$LOG_FILE" && rm -f "$LOG_FILE"
        _url="http://tovid.wikia.com/wiki/Known_bugs#tovid_is_broken_on_Debian"
        runtime_error \
        "your transcode is missing the yuv4mpeg export module. See $_url"
    fi
fi
# ffmpeg - minimum version: 0.7, which has necessary filters
ffmpeg_help=$($FFmpeg -h full 2>&1)
ff_filters=$($FFmpeg -filters 2>/dev/null | awk 'f;/Filters:/{f=1}')
# if no filters present show a runtime error and exit
[[ "$ff_filters" ]] || \
  runtime_error "Your ${FFmpeg##*/} is too old ! No filter support."
# newer ffmpeg's use setdar= and setsar=
if grep -qw setdar <<< "$ff_filters"; then
    ASPECT="setdar=4:3"  # for menu.  Always 4:3 aspect
# somewhat older rev's used aspect=
elif grep -qw ^aspect <<< "$ff_filters"; then
    ASPECT="aspect=4:3"
fi
# check for -loop or -loop_input (-loop from 0.9 onwards)
if grep -q -- '^-loop ' <<< "$ffmpeg_help"; then
    LOOP="-loop 1"
else
    LOOP="-loop_input"
fi
# switch form video filters: -vf or -vfilters
# "-vf" was "-vfilters" briefly, check
if grep -qw -- -vf <<< "$ffmpeg_help"; then
    VF="-vf"
# somewhat older is "-vfilters"
elif grep -qw -- -vfilters <<< "$ffmpeg_help"; then
    VF="-vfilters"
else # this should not run as we would have exited checking for -filters above
    runtime_error "Your ffmpeg is too old: missing video filters"
fi

# ffmpeg will not allow setting -pix_fmt before the -i if  > 0.8.x
make_dummy
if $FFmpeg -pix_fmt yuv420p -t 0.13 -i "$WORK_DIR/dummy.mpg" \
                    -f null -y /dev/null >/dev/null 2>&1; then
    PIPE_FORMAT="-pix_fmt yuv420p -f yuv4mpegpipe"
else
    PIPE_FORMAT="-f yuv4mpegpipe"
fi
# -acodec, -vcodec, -b and -ab now use per stream options (-b:v)
if $FFmpeg -i "$WORK_DIR/dummy.mpg" -t 0.13 \
  -b:v 500k -f null -y /dev/null >/dev/null 2>&1; then
    VB=-b:v
    AB=-b:a
    CA=-c:a
else
    VB=-b
    AB=-ab
    CA=-acodec
fi
rm -f "$WORK_DIR/dummy.mpg"

#####################################
#         end backend checks        #
#####################################

# set some vars for switched menus so we know where we are
$SWITCHED_MODE && SWITCHED_MENUS=false
{ $SWITCHED_MODE || $SWITCHED_MENUS ; } && SWITCHED=:
# check if user passed a usable thumb or showcase shape
if [[ -n $THUMB_SHAPE ]]; then
    if ! check_maskshape $THUMB_SHAPE; then
        usage_error "Please supply a usable thumb shape with
        -thumb-shape option. You gave \"$THUMB_SHAPE\""
    fi

fi
# -user-thumbs is only compatible with static thumbs (-static)
if $USER_THUMBS && ! $STATIC; then
    if $SWITCHED_MENUS; then
        usage_error "If doing switched menus -user-thumbs can only be used
                    with a static menu (-static)"
    else
        usage_error "-user-thumbs option is for static buttons only (-static)"
    fi
fi

# check for legal -button-style option
case $BUTTON_STYLE in
  line|text|text-rect|rect)
    :
    ;;
  *)
    usage_error "\"$BUTTON_STYLE\" is not a -button-style arg"
    ;;
esac
# transparent border around text so rect spumux outline can fit
if [[ $BUTTON_STYLE = "text-rect" ]]; then
    TEXT_BORDER="-bordercolor Transparent -border 8x8"
fi

# If output directory already exists, print a message and exit
if test -e "$OUT_DIR"; then
    echo "Cleaning up created dirs"
    yecho
    echo "A file or directory named \"$OUT_DIR\" already exists."
    echo "Please use a different -out name, "
    echo "or (re)move the existing file or directory."
    rm -rf "$REAL_WORK_DIR"
    rm -f "$WORK_DIR"
    exit 1
fi
# Remove any existing log file, and print headers, unless recursing
if ! $SWITCHED_MODE && ! $TITLESET_MODE && \
! $MK_CAROUSEL_MODE && ! $VMGM_ONLY; then
    test -f "$LOG_FILE" && rm -f "$LOG_FILE"
    echo
    # script details for the log file
    PATTERN=$(for ((i=1; i<=79; i++)); do echo -n \*; done)
    printf "%s\n%s\n%s\n\n\n" "$PATTERN" \
    "todisc from the tovid suite ($TOVID_VERSION) - log for `date`" \
    "$PATTERN" >> "$LOG_FILE"
    script_args=( ${0##*/} "${args[@]}" )
    #for i in "${script_args[@]}"; do printf "%s %s\n" "$ME" "$i"; done
    # do some locale debugging
    printf "\n%s%s\n" "$ME" "You are using the following locale settings:" >> "$LOG_FILE"
    locale_env=( $(locale) )
    for v in "${locale_env[@]}"; do printf "%s %s\n" "$ME" "$v"; done >> "$LOG_FILE"
    printf "\n\n" >> "$LOG_FILE"
fi
# put command line into log for debugging - changes with recursive todisc calls
_args=( todisc "${args[@]}" )
for i in "${_args[@]}"; do printf "%s %s\n" "$ME" "$i"; done >> "$LOG_FILE"
print2log ""
    ##########################################################################
    ########## More setup, and non-critical info + warning messages ##########     
    ##########################################################################

# information about -titles option in case user doesn't know
if [[ ${#TITLES[@]} -eq 0 ]]; then
    if [[ $MENU_NUM = $MN ]] && ! $NOMENU \
     && ! $SINGLE_SLIDESHOW && ! $DO_TITLESETS && $MONTAGE_MENU; then
        info_message "You did not provide any titles with -titles. Using the \
          basename of each file provided (minus the extension)."
        ((sshows < 1)) && $WARN && continue_in 5
    fi
    for i in ${!FILES[@]}; do
        title=${FILES[i]##*/}
        TITLES[i]=" ${title%%.*} "
    done
    unset title
fi
if ! $SINGLE_SLIDESHOW; then
    for i in ${!FILES[@]}; do
        if [[ ! ${TITLES[i]} && $BUTTON_STYLE != "rect" ]]; then
            notitles=1
        fi
    done
    if ((notitles)); then
        $USER_BSTYLE && notit_mess="You can not use \"$BUTTON_STYLE\" button 
        style with no titles. " || notit_mess="You have no titles. "
        info_message "$notit_mess Setting button style to 'rect' style for you"
        BUTTON_STYLE=rect
        TITLES_CLR=none
        V_TITLES_STROKE=none
        $WARN && continue_in 5
    fi
fi
if ! $TITLESET_MODE && ! $DO_TITLESETS && $QUICK_NAV && ! $VMGM_ONLY; then
    QUICK_NAV=false
    info_message "No -quick-nav unless doing titlesets ... disabling this option"
    $WARN && continue_in 5
fi
# Warn if thumb labels have more than 16 characters
if ! $SHOWCASE && ! $ENCODE_ONLY && ! $NOMENU; then
    for ((i=0; i<${#TITLES[@]}; i++)); do
        val=${#TITLES[i]}
        [ -z "$MAX_CHARS" ] || ((val > MAX_CHARS)) && MAX_CHARS=$val && key=$i
    done
    if [[ ${#TITLES[@]} -gt 6 \
    && $MAX_CHARS -gt 16 ]] && ! $SINGLE_SLIDESHOW; then
        info_message "WARNING! Some titles are longer than 16 characters; \
        they may be chopped off."
        $WARN && continue_in 5
        #echo "\"${TITLES[key]}\" is too long; please use a shorter title."
        #exit 1
    fi
fi
# warn about change in -thumb-mist option
if $FEATHER && ! $USE_FEATHER_MASK; then
    info_message "Note: feathered thumb shapes no longer have mist background
        by default.  Use -thumb-mist [COLOR] to get the old behavior"
    $WARN && continue_in 5
fi
#
# sanity checks for button style ( -button-style ) for menu buttons
#
# use a suitable button style
if ! $SINGLE_SLIDESHOW; then
    for ((i=0; i<${#FILES[@]}; i++)); do
        if test $(wc -l <<< "$(echo -e "${TITLES[i]}")") -gt 1; then
            MULTILINE_TITLE=:
        fi
    done
    # multiline titles not suitable for text buttons
    if $MULTILINE_TITLE && [[ $BUTTON_STYLE = "text" ]]; then
        BUTTON_STYLE="line"
        info_message "'text' button style not suitable for multi-line
        titles, using 'line' style instead"
        $WARN && continue_in 3
    fi

    # remove multiple spaces in video titles for text button style
    if [ "$BUTTON_STYLE" = "text" ]; then
        for ((i=0; i<${#TITLES[@]}; i++)); do
            T=$(sed 's/^[ \t]*//;s/[ \t]*$//' <<< "${TITLES[i]}")
            if grep "  " <<< "$T" >/dev/null; then
                info_message "Sorry, a maximum of one consecutive space is allowed
                in titles for text buttons.  \"${TITLES[i]}\" has more than
                one consecutive space in it.  Removing the extra spaces for you."
                new_title=$("s/^ *//;s/ *$//;s/ \{1,\}/ /g" <<< "${TITLES[i]}")
                TITLES[i]="$new_title"
                $WARN && continue_in 5
            fi
        done
    fi
fi
if { $TEXTMENU || $QUICK_MENU ; } && [[ $BUTTON_STYLE = "rect" ]]; then
    BUTTON_STYLE="line"
    if ((MENU_NUM==2)) || { ! $SWITCHED_MODE && ! $SWITCHED_MENUS ; }; then
        if $USER_BSTYLE; then
            info_message "Using button style '$BUTTON_STYLE' instead of 'rect'
            for textmenu menu"
            $WARN && continue_in 3
        fi
    fi
fi
if [[ -n ${ROTATE_ARRAY[@]} ]]; then
    if ! $SHOWCASE; then
         if [[ $BUTTON_STYLE = *rect* ]]; then
            BUTTON_STYLE="line"
            if $USER_BSTYLE; then
                info_message "'*rect' button styles with rotated thumbs don't
                play well with spumux buttons. Setting button style to
                'line'.  You may also use 'text' style.
                Quit now if you wish to exit and examine your options"
                $WARN && continue_in 10
            fi
        fi
    fi
fi
#
# end of button-style checks
#
if [[ -n $SHOWCASE_SHAPE ]]; then
    # if -wave also (incompatible), disable -showcase-shape and give warning
    if [[ -n $WAVE ]]; then
        info_message "-showcase-shape incompatible with -wave, \
          disabling -showcase-shape for you"
        SHOWCASE_SHAPE=""
        $WARN && continue_in 3
    else
        ! check_maskshape $SHOWCASE_SHAPE && \
        usage_error "Please supply a usable showcase shape with
        -showcase-shape option.  You gave \"$SHOWCASE_SHAPE\""
    fi
fi

# allow multiline titles in submenu
if [[ -n "$SM_TITLES" ]]; then
    for i in ${!SM_TITLES[@]}; do
        if [[ $(echo -e "${SM_TITLES[i]}" |wc -l) -gt 1 ]]; then
            SM_TITLES[i]="$(echo -e  "${SM_TITLES[i]}")"
        fi
    done
fi
# copy symlinks for -group hack
if $GROUPING && $TITLESET_MODE; then
    find "$WORK_DIR"/  -name \*group\*.mpg -exec cp -P {} "$BASEDIR" \;
fi
# carousel's are made BEFORE switched menus - so don't do them in switched mode
$SWITCHED_MODE && DO_CAROUSEL=false

# save value of default chapters
! $USER_CHAPTERS && (( ${#CHAPTERS[@]} == 1 )) && default_chapters=${CHAPTERS[0]}

# see if imagemagick supports -vignette for the oval shape
if [[ $THUMB_SHAPE == "vignette" || $SHOWCASE_SHAPE == "vignette" ]]; then
    if ! convert -help 2>&1 | egrep -q -- "-vignette"; then
        [[ $THUMB_SHAPE == "vignette" ]] && THUMB_SHAPE="oval"
        [[ $SHOWCASE_SHAPE == "vignette" ]] && SHOWCASE_SHAPE="oval"
        ! ((USER_BLUR)) && BLUR=3
        ! ((SC_USER_BLUR)) && SC_BLUR=3
        info_message \
          "Note: -vignette option not available in your imagemagick version.
          You should upgrade it.  Using 'oval' mask shape instead which is
          similar.  Setting the blur to 3 unless you used '-blur' (thumbs) or
          '-showcase-blur' (showcase file)"
        $WARN && continue_in 5
    fi
fi
# see if advanced options were used and give warning if so
if [[ -n "${ADV_OPT[@]}" ]] && ! $SWITCHED_MODE; then
    yecho ""
    printgreen "*** Note: ***"
    yecho "You have used the following advanced options:"
    yecho "${ADV_OPT[@]}" | format_output
    yecho "With these options it is possible to create a menu where things "
    yecho "overlap or are offscreen, or that has other problems, "
    yecho "so please check it with the preview."
    printgreen "***************"
    yecho ""
    $WARN && continue_in 7
fi

# check aspect ratios of infiles so thumbs are in aspect without -aspect passed
# this is done before makempg converts non-compliant files so it is really only
# useful to get a preview
if ((inc_files && MENU_NUM == 1)) && [[ ! "$V_ASPECT" ]] \
      && ! $VMGM_ONLY && ! $ENCODE_ONLY; then
    yecho "Determining aspect ratio of videos for the preview."
    yecho ""
    yecho "If SURE of ratios skip this step with '-aspect ASPECT' \
    (but it is best if you always run it first to check)."
    #$WARN && continue_in 3
    echo
    cur_aspect=""
    for ((i=0; i<${#FILES[@]}; i++)); do
        curfile=${FILES[i]}
        ! $SINGLE_SLIDESHOW && print2log "Checking aspect ratios: ${FILES[i]##*/}"
        # check if image, then check aspect ratio of image if so
        check_filetype "$curfile"
        if [[ $file_type = 'image' ]]; then
            stat=133
        elif [[ $file_type = 'video' ]]; then
            stat=$(idvid -terse -fast "${FILES[i]}" 2>/dev/null |
              awk -F= '/V_ASPECT_WIDTH=/ {print $2}' 2>/dev/null)
        else
            usage_error "Sorry could not identify file ${FILES[i]}"
        fi
        #if [[ $(file -L "$curfile"  | awk '{ $1 = ""; print }') =~ image ]]; then
        #    stat=133
        #elif mencoder -quiet -oac pcm -ovc copy \
        #    -frames 0 -o /dev/null "${FILES[i]}" &>/dev/null; then
                # it is a video, check aspect ratio
        #        stat=$(idvid -terse -fast "${FILES[i]}" 2>/dev/null |
        #          awk -F= '/V_ASPECT_WIDTH=/ {print $2}' 2>/dev/null)
        #else
        #    usage_error "Sorry could not identify file ${FILES[i]}"
        #fi
        # exit from the loop 
        # save list of files without reported aspect ratio for a warning
        { [[ $stat = 0 ]] || ! test_is_number $stat; } &&  warn_files[i]=${FILES[i]}
        stats[i]=${stat:-0}
        # round up to 177 or down to 133 in the same way as makempg does for
        # padding, so we know what aspect it will be after conversion
        if (( ${stats[i]} > 153 )); then
            ar_stats[i]=177
            # exit with usage error if videos are 16:9 and a slideshow is included
            if ((sshows >=1)); then
                usage_error \
                "Slides are encoded using 4:3 aspect ratio.  You can not mix \
                16:9 videos with a slideshow in the same titleset"
            fi
        else
            ar_stats[i]=133
        fi
        #if [[ -n $cur_aspect ]] && [[ ${ar_stats[i]} != $cur_aspect ]]; then
        #    # if we have a value for cur_aspect and it differs from new value 
        #    if [[ ${ar_stats[i]} != $cur_aspect ]]; then
                # we may have this already if the value was 0, but no harm done
        #        warn_files[i]=${FILES[i]}
        #    fi
        #fi
        cur_aspect=${ar_stats[i]}
        # unset stat so we can test it again
        unset stat 
    done
    # count the most frequent occurence in ar_stats of 133 or 177.
    # They should all be the same!, but user can still continue if he wants
    ws=$(grep 177 <<< "$(printf '%s\n' ${ar_stats[@]})" |wc -l)
    lb=$(grep 133 <<< "$(printf '%s\n' ${ar_stats[@]})" |wc -l)
    ((ws > lb)) && ar=177 || ar=133
    # set the global var for aspect ratio
    { [[ $ar = 177 ]] && ASPECT_RATIO=16:9; } || ASPECT_RATIO=4:3
    
    # warn about files that have a differing aspect ratio
    for i in ${!ar_stats[@]}; do
        if ! grep -q $ar <<< ${ar_stats[i]}; then
            warn_files[i]=${FILES[i]}
        fi
    done
    if [[ -n ${warn_files[@]} ]]; then
        yecho
        printred "*** CRITICAL WARNING ***"
        yecho "The following files differ from the $ASPECT_RATIO aspect ratio
        we are using, even if they are to be re-encoded by makempg here."
        echo
        printf "\"%s\"\n" ${warn_files[@]}
        echo
        yecho "You can not mix different aspect ratios in the same menu. 
        They need to be put in a separate titleset. You may want to quit 
        at the preview and re-examine the situation."
        printred "*************"
        yecho
        yecho "Press <ENTER> to continue"
        read input
    fi
    print2log ""
    print2log "Videos in this titleset will be done using aspect of $ASPECT_RATIO."
fi

################################################
#        recursive magic for titlesets,        #
# switched menus, and animated slideshow menus #
################################################

# if doing titlesets, call todisc recursively,
# collect parts and author.  Then exit
if $DO_TITLESETS; then
    titleset_mode "${args[@]}"
    yecho Goodbye
    exit
fi
# if -animated slideshow, AND  multiple slideshow or slideshow AND video(s)
# call todisc recursively for each ${FILES[@]},
# collect each concatenated carousel m2v, and exit
if { ((sshows>=1)) && ((inc_files >=1)) ; } || ((sshows>1)); then
    if $DO_CAROUSEL && ! $MK_CAROUSEL_MODE; then
        # call todisc recursively, collect slideshow.m2v and exit
        ! $CONFIRM_BACKUP && NO_CONFIRM_BACKUP="-no-confirm-backup"
        if ! carousel_menu_mode menu; then
            yecho '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
            yecho 'todisc encountered an error'
            cleanup && killall_instances
            exit 13
        fi
        if $CAROUSEL_IS_BG; then
            mv "$WORK_DIR/carousel-1.m2v" "$WORK_DIR/carousel-00.m2v"
            BACKGROUND="$WORK_DIR/carousel-00.m2v"
            BG_SEEK=0
        elif $CAROUSEL_IS_SHOWCASE; then
            mv "$WORK_DIR/carousel-1.m2v" "$WORK_DIR/carousel-00.m2v"
            SHOWCASE_FILE="$WORK_DIR/carousel-00.m2v"
            SHOWCASE_SEEK=0
        else
            for f in ${!FILES[@]}; do
                if ! ${SLIDESHOW[f]}; then
                    # set seek and chapter value if user only passed one value
                    [[ -z ${SEEK_VAL[f]} ]] && SEEK_VAL[f]=${SEEK_VAL[0]}
                    [[ -z ${CHAPTERS[f]} ]] && CHAPTERS[f]=$default_chapters
                elif ${SLIDESHOW[f]} && \
                 [[ -e $WORK_DIR/carousel-$((f+1)).m2v ]]; then
                    cp -v  "$WORK_DIR/carousel-$((f+1)).m2v" \
                    "$WORK_DIR/${TSET_NUM}-$((f+1)).mpg"
                    # use CAROUSEL array to id a do_not_overwrite symlink
                    CAROUSEL[f]="carousel"
                    if $SWITCHED; then
                        FILES[f]=$WORK_DIR/carousel-$((f+1)).m2v
                    else
                        FILES[f]=$WORK_DIR/${TSET_NUM}-$((f+1)).mpg
                    fi
                    SEEK_VAL[f]=0
                    CHAPTERS[f]=0
                fi
            done
        fi
        DO_CAROUSEL=false
    fi
fi
# if doing switched menus, call todisc recursively for each
# ${FILES[@]} and collect each intro.mpg
if $SWITCHED_MENUS; then
        switched_menu_mode "${args[@]}"
fi

######################################
#       end recursive calls          #
######################################


# if -slideshow-menu-thumbs passed, change with approprite FILE
if [[ -n ${SLIDESHOW_MENU_THUMBS[@]} ]]; then
    unset sld
    ((sshows < 1)) && \
     usage_error "You must be doing a slideshow to use -slideshow-menu-thumbs"
    for f in ${!FILES[@]}; do
        if ${SLIDESHOW[f]}; then # if this file is part of a slideshow...
            FILES[f]=${SLIDESHOW_MENU_THUMBS[sld++]} # replace it
        fi
    done
fi

# set some vars for the last run of switched menus (non-recursive )
$SWITCHED_MENUS && SHOWCASE_FILE=${FILES[0]}

print2log "Creating work directories"

# create an array of grouped files.
if $GROUPING; then
unset grp
for ((i=1; i<=${#FILES[@]}; i++)); do
    if [[ -n ${GROUP_ARR[i-1]} ]]; then
        for ((j=1; j<=${GROUP_ARR[i-1]}; j++)); do
            if [[ -e $WORK_DIR/${TSET_NUM}-group-${i}-${j}.mpg ]]; then
                grouping[grp++]=$WORK_DIR/${TSET_NUM}-group-${i}-${j}.mpg
            fi
        done
    fi
done
fi

## if no bg supplied, use template.png so we can add a frame (-quick-menu only)
# near-black background causes ffmpeg's movie/overlay filter to act weirdly
if [[ $BG_CLR = '#101010' || $BG_CLR = black ]] && [[ -z $BACKGROUND ]] && $QUICK_MENU; then
    SUB_CLRS+=("$BG_CLR:'#000030' ('black' bg for quick menu is problematic)")
    BG_CLR='#000030'
    #BG_CLR='#101028'
fi

# check that NTSC menu uses safe colours
if [[ $TV_STANDARD = "ntsc" ]]; then
    get_safe_colour $SFRAME_CLR && FRAME_CLR=$SAFE_CLR
    get_safe_colour $TITLE_CLR && TITLE_CLR=$SAFE_CLR
    get_safe_colour $SM_TITLE_CLR && SM_TITLE_CLR=$SAFE_CLR
    get_safe_colour $M_TITLE_STROKE && M_TITLE_STROKE=$SAFE_CLR
    get_safe_colour $SUBMENU_STROKE && SUBMENU_STROKE=$SAFE_CLR
    get_safe_colour $CHAPTER_STROKE && CHAPTER_STROKE=$SAFE_CLR
    get_safe_colour $TITLES_CLR && TITLES_CLR=$SAFE_CLR
    get_safe_colour $HLIGHT_CLR && HLIGHT_CLR=$SAFE_CLR
    get_safe_colour $SELECT_CLR && SELECT_CLR=$SAFE_CLR
    get_safe_colour $BG_CLR && BG_CLR=$SAFE_CLR
    get_safe_colour $V_TITLES_STROKE && V_TITLES_STROKE=$SAFE_CLR
    get_safe_colour $SUBMENU_BG_CLR && SUBMENU_BG_CLR=$SAFE_CLR
    get_safe_colour $THUMB_FRAME_CLR && THUMB_FRAME_CLR=$SAFE_CLR
    echo
    if [[ -n ${SUB_CLRS[@]} ]]; then
        printgreen "*** Note: ***"
        echo "Some of the colors you passed in are not NTSC color safe. "
        echo "The following substitutions were made for you:"
        for i in ${!SUB_CLRS[@]}; do
            echo "${SUB_CLRS[i]/:*} ===>  ${SUB_CLRS[i]/*:}"
        done
        printgreen "*************"
        echo
        $WARN && continue_in 5
    fi
fi

if [[ -z $BACKGROUND ]]; then
    BACKGROUND="$WORK_DIR/bg.$IMG_FMT"
    convert  -size $VIDSIZE! xc:$BG_CLR -depth 8 "$BACKGROUND"
fi
# check file type of background file and assign to BG_VIDEO or BG_IMAGE
if [[ -n $BACKGROUND ]]; then
    check_filetype "$BACKGROUND"
    if [[ $file_type = "image" ]]; then
        BG_PIC="$BACKGROUND"
    elif [[ $file_type = "video" ]]; then
        BG_VIDEO="$BACKGROUND"
    else
        usage_error "Sorry, can not identify "$BACKGROUND""
    fi
fi
if [[ -n ${SM_BACKGROUND[@]} ]]; then
    for smbg in ${!SM_BACKGROUND[@]}; do
        check_filetype "${SM_BACKGROUND[smbg]}"
        if [[ $file_type != "image" ]]; then
            usage_error "-submenu-background takes image files only"
        fi
    done
fi

# if $SHOWCASE, find out if using SHOWCASE_VIDEO or SHOWCASE_IMG or ! SC_THUMB
if $SHOWCASE; then
    if [[ -n ${SHOWCASE_FILE[@]} ]]; then
        check_filetype "${SHOWCASE_FILE[@]}"
        if [[ $file_type = "image" ]]; then
            SHOWCASE_IMG=${SHOWCASE_FILE[@]}
        elif [[ $file_type = "video" ]]; then
            SHOWCASE_VIDEO=${SHOWCASE_FILE[@]}
        else
            usage_error "Can not identify showcase file: "${SHOWCASE_FILE[@]}""
        fi
    else
        SC_THUMB=false
        SHOWCASE_IMG="dummy"
    fi
fi
# find out the aspect ratio of the showcase file
if [[ -n $SHOWCASE_VIDEO ]]; then
    SC_AR=$( idvid -fast -terse "$SHOWCASE_VIDEO" 2>> $LOG_FILE |
    awk -F= '/V_ASPECT_WIDTH/ {print $2}' 2>/dev/null)
elif [[ -n $SHOWCASE_IMG && $SHOWCASE_IMG != "dummy" ]]; then
    SC_AR=$(identify -ping -format %wx%h "$SHOWCASE_IMG")
    SC_AR=$( bc_math "(${SC_AR/x*} / ${SC_AR/*x}) * 100" int )
fi

# now the showcase image is id'ed, we can find out what kind of quick menu
if $QUICK_MENU; then
    if [[ -n $SHOWCASE_VIDEO ]]; then
        QUICK_MENU_FILE="$SHOWCASE_VIDEO"
        QUICKMENU_IS_SHOWCASE=:
    elif [[ -n $BG_VIDEO ]]; then
        QUICK_MENU_FILE="$BG_VIDEO"
        QUICKMENU_IS_BACKGROUND=:
    fi
fi
if $QUICK_MENU && ! $QUICKMENU_IS_SHOWCASE && ! $QUICKMENU_IS_BACKGROUND; then
    if ! $SWITCHED; then
        yecho
        if { $DO_TITLESETS || $TITLESET_MODE ; }; then
            yech=yecho
        else
            yech=usage_error
        fi
        if $is_carousel; then
            $yech "animated slideshows with quick-menu need either
            -background-slideshow  or -showcase-slideshow"
        else
            $yech "-quick-menu needs a -showcase VIDEO or a -background VIDEO"
        fi
        yecho "Disabling -quick-menu for you as it is not needed"
        yecho "It might be better to Ctrl-c now to exit and examine the situation
        as you are now making a showcase style menu"
        yecho
        QUICK_MENU=false
        # -quick-menu really messes up single slideshow
        if $SINGLE_SLIDESHOW; then
            BUTTON_STYLE="rect"
            SHOWCASE=false
        fi
        $WARN && continue_in 10
    fi
fi
$QUICKMENU_IS_BACKGROUND && SHOWCASE_IMG=""
# some checks for -quick-menu
if $QUICK_MENU; then
# quick-menu needs TEXTMENU=: , and does its own showcase and bg with ffmpeg
    TEXTMENU=:
    SC_THUMB=false
    STATIC=:
fi
if [[ $SC_FRAMESTYLE = "glass" ]] && [[ -z $SHOWCASE_IMG && -z $SHOWCASE_VIDEO ]]; then
    yecho
    yecho "You must use a -showcase option for '-showcase-framestyle'. Either "
    yecho "-showcase IMAGE, -showcase VIDEO, -showcase mix, or '-showcase'"
    yecho "Disabling this option for you - please exit now"
    yecho "if you wish to reexamine the situation"
    yecho
    SC_FRAMESTYLE="none"
fi
if [[ $SC_FRAMESTYLE = "glass" ]] && $QUICK_MENU; then
    yecho
    yecho "You can not use 'glass' frame style with -quick-menu, \
    disabling this option"
    yecho
    SC_FRAMESTYLE="none"
fi
# allow user to only specify one audio file for all submenus
if [ ${#SM_AUDIO[@]} -eq 1 ]; then
    if ((sshows>1)); then
        for i in ${!FILES[@]}; do
            SM_AUDIO[i]=${SM_AUDIO[0]}
        done
        unset SM_AUDIO_FILE
    else
        SM_AUDIO_FILE=${SM_AUDIO[0]}
    fi
fi
# if more than one audio file for submenu make sure they equal video #
if [[ ${SM_AUDIO[@]} && \
${#FILES[@]} -ne ${#SM_AUDIO[@]} &&  ${#SM_AUDIO[@]} -ne 1 ]]; then
    usage_error "Please give the same number of submenu audios as videos.
    You gave ${#FILES[@]} video files and ${#SM_AUDIO[@]} audio files"
fi
# Get absolute pathnames of all files
if ! $VMGM_ONLY; then
    for i in "${FILES[@]}"; do
        IN_FILES=("${IN_FILES[@]}" "$(readlink -f "$i")")
        spin "Adding: ${i##*/}"
    done
    echo
fi

$VMGM_ONLY && V_TOTAL=$(( ${#TITLES[@]} - 1 )) || V_TOTAL=${#IN_FILES[@]}
$VMGM_ONLY && NUM_FILES=$(( ${#TITLES[@]} - 1 )) || NUM_FILES=$((V_TOTAL - 1))
# slide mix sets MONTAGE_MENU to false
$DO_CAROUSEL && MONTAGE_MENU=false

# switch title position when appropriate so it doesn't get covered up
! $USER_TITLE_GEO && [[ $BUTTON_GRAVITY = south* ]] && TITLE_GRAVITY="north"
# not sure why YGEO is 45, probably from when -align didn't affect montage
#if [[ $BUTTON_GRAVITY = *east || $BUTTON_GRAVITY = *west ]]; then
if ! $SHOWCASE; then # XGEO/YGEO for montage style only
    # montage adds spacing to edge of montage so subtract it.  This is a
    # HACK, it would have been better to -trim +repage but I don't feel
    # like testing each of the myrid combos to make sure it works okay
    safe_area=$(( SAFE_AREA - 12 ))
    case $BUTTON_GRAVITY in
      northeast|southeast|northwest|southwest)
        if $USER_GRAVITY; then
            XGEO=$safe_area && YGEO=$safe_area
        else
            XGEO=45 && YGEO=45
        fi
        ;;
      east|west)
        # move to REAL center if -align centers the montage vertically
        YGEO=0 && XGEO=$SAFE_AREA
        ;;
      center)
        YGEO=0 && XGEO=0
        ;;
    esac 
else # for showcase, move Y position to true north or south at safe area edge
    :
    #[[ $BUTTON_GRAVITY = north* ]] && TEXT_YSTART=$SAFE_AREA
    #[[ $BUTTON_GRAVITY = south* ]] && TEXT_YSTART=$(( ${VIDSIZE/*x} - SAFE_AREA))
fi
    
! $SHOWCASE && \
[[ $BUTTON_GRAVITY = "center" ]] && ! $USER_TITLE_GEO && TITLE_GRAVITY="north"

# make an array of possible vars for dvdauthor post calls
if $CHAIN_VIDEOS; then
    if [ -z "$post_play" ]; then
        for ((i=0; i<NUM_FILES; i++)); do
                POST_PLAY[i]=chain
            done
    else
        for j in $post_play; do
            if [[ $j = *-* ]]; then
                for ((i=${j/-*}; i<=${j/*-}; i++)); do
                    POST_PLAY[i-1]=chain
                done
            elif [[ $j != *[^0-9]* ]]; then
                POST_PLAY[j-1]=chain
            fi
        done
    fi
    echo
    for ((n=0; n<=NUM_FILES; n++)); do
        if [ "${POST_PLAY[n]}" = "chain" ]; then
            if [ $n -lt $NUM_FILES ]; then
                echo "video $((n+1)) will be chained with video $((n+2))"
            else
                echo "video $((n+1)) will be chained with video 1"
            fi
        fi
    done
    echo
fi
# make array, remove everything after and including 1st '+',
#CHAPTERS=( ${CHAPTERS%%+*} ) # in case of grouped chapters
# allow user to pass HH:MM:SS chapters
$USER_CHAPTERS && CHAPT_ARRAY=( ${CHAPTERS[@]} )
if $USER_CHAPTERS; then
    C=( ${CHAPTERS[@]} )
    if ((${#C[@]} == 1)) && ((${#C[@]} != ${#FILES[@]})); then
        for i in ${!FILES[@]}; do
            CHAPT_ARRAY[i]=${C[0]}
        done
    else
        CHAPT_ARRAY=( ${CHAPTERS[@]} )
    fi
fi


# if arbitrary grouped chapters passed, make an array of them
if $GROUPING && $USER_CHAPTERS; then
    for i in ${!IN_FILES[@]}; do
        if [[ -n ${GROUP_ARR[i]} ]]; then
            group_arbitrary_chapters[i]=${grouped_user_chapters[i]//+/ }
        else
            group_arbitrary_chapters[i]=""
        fi
    done
fi
# if treating each video as a chapter, use 1 chapter.  No playall allowed here
if $VIDEOS_ARE_CHAPTERS; then
    if [[ -n ${grouping[@]} ]]; then
        usage_error "-videos-are-chapters can not be used with -group"
    elif $SUB_MENU; then
        usage_error "-videos-are-chapters can not be used with submenus"
    elif $USER_CHAPTERS; then
        usage_error "HH:MM:SS chapters incompatible with -videos-are-chapters"
    else
         CHAPTERS=1 && PLAYALL=false
    fi
fi
# allow specifying one # of chapters for all videos if not given in HH:MM:SS
if [[ ${#CHAPTERS[@]} -eq 1 && -z ${CHAPT_ARRAY[@]} ]]; then
    for ((i=0; i<=NUM_FILES; i++)); do
        CHAPTERS[i]=${CHAPTERS[0]}
    done
fi
# make sure if -video-pause is given it equals the # of videos
if [[ -n ${VPAUSE[@]} && ${#VPAUSE[@]} -ne 1 ]]; then
    if [[ ${#VPAUSE[@]} -ne ${#IN_FILES[@]} ]]; then
        usage_error "# of -video-pause args must equal 1 or the # of videos"
    fi
fi
# make sure if -group-video-pause is given it equals the # of videos
if [[ -n ${GRP_VPAUSE[@]} && ${#GRP_VPAUSE[@]} -ne 1 ]]; then
    if [[ ${#GRP_VPAUSE[@]} -ne ${#grouping[@]} ]]; then
        usage_error "# of -video-pause args must equal 1 or the # of videos"
    fi
fi
# allow specifying one # for -video-pause
if [[ -n ${VPAUSE[@]} && ${#VPAUSE[@]} -eq 1 ]]; then
    for ((i=0; i<=NUM_FILES; i++)); do
        VPAUSE[i]=${VPAUSE[0]}
    done
fi
# allow specifying one # for -group-video-pause
if [[ -n ${GRP_VPAUSE[@]} && ${#GRP_VPAUSE[@]} -eq 1 ]]; then
for i in ${!grouping[@]}; do
    GRP_VPAUSE[i]=${GRP_VPAUSE[0]}
done
fi
# check # of -submenu-length args, and allow specifying 1 value for all videos
if $SUB_MENU \
&& ((${#SUBMENU_LEN[@]} != 1 && ${#SUBMENU_LEN[@]} != ${#IN_FILES[@]} )); then
usage_error "Give 1 submenu length for each video, or just 1 value for all"
fi
if $SUB_MENU && (( ${#SUBMENU_LEN[@]} == 1 )); then
if ! $DO_CAROUSEL; then
    for i in ${!IN_FILES[@]}; do
        SUBMENU_LEN[i]=${SUBMENU_LEN[0]}
    done
fi
fi

# use user passed -submenu-length for static submenus with audio
if $SUB_MENU && ! $ANI_SUB_MENU; then
if ! $DO_CAROUSEL; then
    for i in ${!IN_FILES[@]}; do
        if $USER_SUBMENU_LEN; then
            SUBMENU_AUDIOLEN[i]=${SUBMENU_LEN[i]}
        fi
    done
fi
fi


# if more than one value for CHAPTERS, make sure they equal video #
if $SUB_MENU &&  [[ ${#FILES[@]} -ne ${#CHAPTERS[@]} ]]; then
$USER_CHAPTERS && string="chapter point string" || string="chapter"
usage_error "Please give the same number of ${string}s as videos.
You gave ${#FILES[@]} video files and ${#CHAPTERS[@]} ${string}(s)"
fi
# get normal CHAPTERS VAR,i.e.: 'how many chapters'
# Check if 1st is 00:00:00 and all chapters have HH:MM:SS format
if $USER_CHAPTERS; then
    if [[ ${#FILES[@]} -ne ${#CHAPTERS[@]} ]]; then
        usage_error "Please give the same number of chapter point strings as
        videos when using HH:MM:SS form chapters.  You gave ${#FILES[@]}
        videos but only ${#CHAPTERS[@]} chapter point strings."
    fi
    for i in ${!CHAPT_ARRAY[@]}; do
        unset newchapts
        [[ ${CHAPTERS[i]} != *:* ]] && usage_error \
        "for HH:MM:SS style chapters all video chapters must have this format"
        if [[ ${CHAPT_ARRAY[i]:0:8} != 00:00:00 ]];then
            usage_error \
            "The first chapter must be 00:00:00. ${IN_FILES[i]} \
            used ${CHAPT_ARRAY[i]}"
        fi
        # remove + sign and commas, count the number of chapters left
        str=$(sed 's/+/ /g;s/,/ /g' <<< ${CHAPTERS[i]})
        for substr in $str; do [[ $substr != 0 ]] && newchapts+=($substr); done
        CHAPTERS[i]=${#newchapts[@]}
    done
fi
# do not let user use -chapters 0 (-chapters 5 0 6)
for ((i=0; i<${#CHAPTERS[@]}; i++)); do
    if ((${CHAPTERS[i]} == 0)) && ! ${SLIDESHOW[i]}; then
        if ! $USER_CHAPTERS; then
            [[ -z ${GROUP_ARR[i]} ]] && usage_error \
            "-chapters 0 is only for grouped videos (each video is a chapter)"
            CHAPTERS[i]=$(( ${GROUP_ARR[i]} + 1 )) && nochapt[i]=1
        fi
    fi
done

# if using chapter titles, they must equal the combined total for all files
if [[ -n ${CHAPTER_TITLES[@]} ]]; then
    total_chapters=$(awk_total <<< "${CHAPTERS[@]}")
    if (( ${#CHAPTER_TITLES[@]} !=  $total_chapters )); then
        usage_error "If using chapter titles you must supply a title for each
        chapter in each video.  You gave ${#CHAPTER_TITLES[@]} titles but
        have a total of $total_chapters chapters."
    fi
fi
# find out longest chapter value (number of chapters)
if $SUB_MENU; then
    for ((i=0; i<${#CHAPTERS[@]}; i++)); do
        chapt_val=${CHAPTERS[i]}
        [ -z "$MAX_CHAPTERS" ] || ((chapt_val > MAX_CHAPTERS)) \
        && MAX_CHAPTERS=$chapt_val && max_chapt_key=$i
        [ -z "$MIN_CHAPTERS" ]  || ((chapt_val < MIN_VAL)) \
        && MIN_CHAPTERS=$chapt_val && min_chapt_key=$i
    done
    if ((MAX_CHAPTERS > 35)); then
        usage_error "Sorry, maximum 35 chapters for submenus (DVD button limit)"
    fi
fi

# allow using todisc for just encoding mpegs, then exiting
if $ENCODE_ONLY; then
    check_compliance
    if (( ${#FILES_TO_ENCODE[@]} > 1 )); then
        for f in "${FILES_TO_ENCODE[@]}"; do
            [[ -s "$f" ]] && arr+=("${f}.enc.mpg")
        done
        #((${#arr[@]} > 0)) && printf "%s\n%s.enc.mpg" \
        if ((${#arr[@]} > 0)); then
            printf "\n%s\n" "Here are your encoded files:"
            printgreen '-------------'
            printf "%s\n" "${arr[@]}"
            printgreen '-------------'
        fi
    fi
    cleanup
    exit 0
fi
# a quick way to allow user to make a dvd with no menus
if $NOMENU; then
    cd "$WORK_DIR"
    yecho
    yecho "Making a DVD with no menus"
    yecho "Identifying video files"
    check_compliance
    # link files in $WORK_DIR so an array with "$file $chapters" will work
    for i in "${!IN_FILES[@]}"; do
        ln -s "${IN_FILES[i]}" "$WORK_DIR/$(printf %03d%s%s $i .mpg)"
        idvid_stats[i]=$(idvid -terse "${IN_FILES[i]}" 2>/dev/null)
        # run stream_length to get the length if using arbitrary chapters
        if $USER_CHAPTERS; then
            chapter_points[i]=${CHAPT_ARRAY[i]}
        else
            if $VIDEOS_ARE_CHAPTERS; then
                : # we don't need file length or chapters if not making chapters
            else
                yecho "Getting video lengths"
                VID_LEN[i]=$(stream_length  "${IN_FILES[i]}" )
                chapter_points[i]=$(make_chapters ${VID_LEN[i]} ${CHAPTERS[i]} )
            fi
        fi
    done
    get_stats files
    IN_FILES=( $WORK_DIR/*.mpg )
    lastvid=${#IN_FILES[@]}
    nomenu_cmd=(dvdauthor -o )
    nomenu_cmd+=("$OUT_DIR")
    $VIDEOS_ARE_CHAPTERS && nomenu_cmd+=( -t ) # only want 1 "-t" if 1 pgc
    for i in ${!IN_FILES[@]}; do
        curvid=$((i+1)) # zero based array, we want for ex. file 1 not file 0
        # -videos-are-chapters needs no chapter points, else make them and jump
        if ! $VIDEOS_ARE_CHAPTERS; then
            yecho
            echo -e "Chapters for ${IN_FILES[i]}\n${chapter_points[i]}"
            nomenu_cmd+=(-t)
            nomenu_cmd+=(-c ${chapter_points[i]})
            if ((i != lastvid-1)); then # no jump on last video
                nomenu_cmd+=(-i "post=jump title $((curvid+1)) ;")
            fi
            nomenu_cmd+=( -f )
        fi
        nomenu_cmd+=("${IN_FILES[i]}")
    done
    print2log "Running: ${nomenu_cmd[@]} -o $OUT_DIR"
    "${nomenu_cmd[@]}" -o "$OUT_DIR" 2>&1| pipe2log
    dvdauthor -o "$OUT_DIR" -T 2>&1 |pipe2log
    thanks_goodbye
    $BURN && burn_disc
    cleanup
    exit 0
fi

# make sure -user-thumbs matches the number of videos
if  $USER_THUMBS && ((${#USER_PICS[@]} != ${#IN_FILES[@]})); then
    usage_error "The number of images supplied with \"-user-thumbs\"
    must match the number of videos"
fi
# pass -frame-safe and ffmpeg/transcode will output only 9 images for static
$FRAME_SAFE && V_FRAMES=9 || V_FRAMES=1
# -frame-safe is incompatible with -user-thumbs
if $USER_THUMBS && $FRAME_SAFE; then
    FRAME_SAFE=false
    echo "-frame-safe and -user-thumbs incompatible, disabling -frame-safe"
    $WARN && continue_in 5
fi
    
print2log "Creating pics directories..."
for ((i=0; i<=NUM_FILES; i++)); do
    mkdir -p "$REAL_WORK_DIR/pics/$i"
done
print2log "${#FILES[@]} pics directories created"
# textmenu is static unless there is an animated background or showcase video
if $TEXTMENU && [[ -z $SHOWCASE_VIDEO && -z $BG_VIDEO ]]; then STATIC=:; fi


{ $MENU_FADE || test -n "$BG_VIDEO" ; } && mkdir -v "$REAL_WORK_DIR/bg"
mkdir "$REAL_WORK_DIR/animenu"
if $ANI_SUB_MENU; then
    for ((i=0; i<MAX_CHAPTERS; i++)); do
        mkdir "$REAL_WORK_DIR/animenu/$i"
    done
fi
if $SUB_MENU && ! $ANI_SUB_MENU; then
    mkdir "$REAL_WORK_DIR/submenu"
fi
if [[ -n "$SHOWCASE_VIDEO" ]]; then
    mkdir "$REAL_WORK_DIR/showcase"
fi

# if more than one value for AUDIO_CHANNEL, make sure they equal video #
if [[ -n $AUDIO_CHANNEL ]] && \
[[ ${#FILES[@]} -ne ${#AUDIO_CHANNEL[@]} && ${#AUDIO_CHANNEL[@]} -ne 1 ]]; then
    usage_error "Please give the same number of audio channels as videos.  \
    You gave ${#FILES[@]} videos and ${#AUDIO_CHANNEL[@]} audio channel values"
fi
# make sure number of -rotate-thumbs arguments equals number of videos
if $ROTATE_THUMBS; then
    if  [[ ${#FILES[@]} -ne ${#ROTATE_ARRAY[@]} ]]; then
        usage_error "Please give the same number of thumb rotate values \
        as videos.  You gave  ${#FILES[@]} video files and \
        ${#ROTATE_ARRAY[@]} thumb rotate values."
    fi
fi

# if Fading menu, and no BG IMAGE OR VIDEO, fade thumbs right in after title
if $MENU_FADE; then
    # some vars for when we source todisc-fade-routine
    [[ -z "$BG_PIC" && -z "$BG_VIDEO" ]] &&  THUMBS_FADEIN_STARTTIME=2.5
    TITLE_FADEIN_STARTTIME=${TRANSITION_TO_MENU_LEN:-1}
    THUMBS_FADEIN_STARTTIME=$(bc_math "$TITLE_FADEIN_STARTTIME + 2.5")
    # if user did not pass in -loop value, set pause to 'inf'
    if $USER_LOOP && [[ $PAUSE_TIME = "inf" ]]; then
        TITLE_FADEOUT_ENDTIME=${MENU_LEN[MENU_NUM-1]}
        TITLE_FADEOUT_STARTTIME=${MENU_LEN[MENU_NUM-1]}
        THUMBS_FADEOUT_ENDTIME=${MENU_LEN[MENU_NUM-1]}
        THUMBS_FADEOUT_STARTTIME=${MENU_LEN[MENU_NUM-1]}
        BG_FADEOUT_STARTTIME=${MENU_LEN[MENU_NUM-1]}
    fi
fi

# if only one seek value, then use for all videos
if [ ${#SEEK_VAL[@]} -eq 1 ]; then
    for ((i=0; i<=NUM_FILES; i++)); do
        SEEK_VAL[i]=${SEEK_VAL[0]}
        SEEK[i]="-ss ${SEEK_VAL[i]}" # create seek value for each video
    done
fi
# if only one chapters fontsize, then use for all videos
if ((${#CHAPT_FONTSIZE[@]} == 1 )); then
    for ((i=0; i<=NUM_FILES; i++)); do
        CHAPT_FONTSIZE[i]=${CHAPT_FONTSIZE[0]}
    done
fi
# make sure if more than one chapter fontsize, they equal the number of videos
if ! $VMGM_ONLY && [[ -n $CHAPT_FONTSIZE ]] \
&& ((${#FILES[@]} != ${#CHAPT_FONTSIZE[@]})); then
    usage_error "Please give the same number of seek times as videos,
    or just use one value.  You gave ${#FILES[@]} video files
    and ${#CHAPT_FONTSIZE[@]} seek times"
fi
# allow -seek to have HH:MM:SS format passed
for ((i=0; i<=NUM_FILES; i++)); do
    if [[ "${SEEK_VAL[i]}" = *:* ]]; then
        SEEK_VAL[i]=$(unformat_time ${SEEK_VAL[i]})
    fi
done
# make sure if more than one seek value, they equal the number of video
if ! $VMGM_ONLY &&  ((${#FILES[@]} != ${#SEEK_VAL[@]})); then
    usage_error "Please give the same number of seek times as videos, or \
    just use one value.  You gave ${#FILES[@]} video files and \
    ${#SEEK_VAL[@]} seek times"
fi
# if more than 1 -menu-length value passed, total must be same as videos total
if ! $VMGM_ONLY &&  ((${#FILES[@]} != ${#MENU_LEN[@]})); then
    usage_error "Please give the same number of -menu-length times as
    videos, or just use one value.  You gave ${#FILES[@]} video files
    and ${#MENU_LEN[@]} -menu-length times"
fi
# set a maximum # of videos
if $SHOWCASE && ! $MK_CAROUSEL_MODE; then
    $TEXTMENU && file_max=26 || file_max=10
    test  ${#FILES[@]} -gt $file_max && usage_error \
     "Sorry, a maximum of $file_max titles is allowed for this style
    You gave ${#FILES[@]} videos as input"
else
    if test ${#FILES[@]} -gt 36; then
        ! $SINGLE_SLIDESHOW && usage_error \
         "Sorry, a maximum of 36 videos (thumbs) is supported
         You gave ${#FILES[@]} files as input.  Please use titlesets
         for this many files.  Alternatively you may use '-group' to group
        some of them under a single button"
    fi
fi

if ! $VMGM_ONLY; then
    # two values for length of video(frames) and audio(secs) for slides
    # SVCD mpegs are minumum length of 4 seconds, DVD can be just single frame
    # this is a hack since makexml is broken for svcd stills
    vlength=4
    alength=$(bc_math "4 / $FRAME_RATE") # 0.16 or 0.133
    # float < 1  must begin with 0
    [[ -n ${alength/*.} && -z ${alength/.*} ]] && alength=0${alength}
    echo "Verifying that input files are video or image files"
    verify_infiles infiles
    if [[ ${#file_is_image[@]} -eq ${#FILES[@]} && $inc_files -gt 0 ]]; then
        usage_error "Please use -slides IMAGES, not -files IMAGES
        for a slideshow"
    fi
    if $GROUPING; then
        echo
        echo "Verifying that grouped input files are video or image files"
        verify_infiles group
    fi
fi
# some vars for slide mix
# this is only called when todisc running recursively to make ani slideshows
# DO_CAROUSEL is set to false when the self recursion is complete
# this happens earlier in the script.
if $DO_CAROUSEL; then
    if [[ -n ${GROUP_ARR[@]} ]] && ! $MK_CAROUSEL_MODE; then
        #*slide_grp*.mpg are symlinks to the original images we have kept intact
        mixgroup=( "$WORK_DIR"/${TSET_NUM}-slide_grp-*.mpg )
        for g in ${!mixgroup[@]}; do
            MIXFILES[g]=$(readlink -f "${mixgroup[g]}")
            MIXLINKS[g]=${mixgroup[g]}
            # remove original link we can keep track of what is already encoded
            rm -f "${MIXLINKS[g]}"
        done
    else
        MIXFILES=( "${IN_FILES[@]}" )
    fi
    for n in ${!BLURFILES[@]}; do
        for i in ${!MIXFILES[@]}; do
            if [[ ${MIXFILES[i]##*/} = ${BLURFILES[n]##*/} ]]; then
                blur_files[i]=${MIXFILES[i]}
                SLIDE_BLUR_AMT[i]=${SLIDE_BLUR_OPT[n]}
            fi
        done
    done
   # randomize order to produce the final 'mix'
    for f in "${!MIXFILES[@]}"; do
        a=$RANDOM
        while [[ ${shuffled[a]} ]]; do
            a=$RANDOM
        done
        shuffled[a]=${MIXFILES[f]}
        if [[ ${SLIDE_BLUR_AMT[f]} ]]; then
            SHUFFLED_SLIDE_BLUR[a]="-blur ${SLIDE_BLUR_AMT[f]}"
        else
            SHUFFLED_SLIDE_BLUR[a]="none"
        fi
    done
    # remove holes in the array and reassign to MIXFILES
    MIXFILES=( "${shuffled[@]}" )
    SLIDE_BLUR=( "${SHUFFLED_SLIDE_BLUR[@]}" )
    unset r
    for s in ${!SLIDE_BLUR[@]}; do
        [[ ${SLIDE_BLUR[s]} = "none" ]] && unset SLIDE_BLUR[s]
    done
fi
[[ -n $MIX_RANGE ]] && MIXRANGE=$MIX_RANGE
#[[ -n $SM_MIX_RANGE ]] && MIXRANGE=$SM_MIX_RANGE
if [[ -n $MIXRANGE ]] && ((MIXRANGE<${#MIXFILES[@]})); then
    last_ind=$MIXRANGE
    for ((i=0; i<MIXRANGE; i++)); do
        #[[ -n ${SLIDE_BLUR[i]} ]] &&
        if $DO_CAROUSEL; then
            MIX_IN=( "${MIX_IN[@]}" "${MIXFILES[i]}" )
        else
            # read in in reverse order so 1st slide is composited last
            MIX_IN=( "${MIX_IN[@]}" "${IN_FILES[--last_ind]}" )
        fi
    done
else
    if $DO_CAROUSEL; then
        MIX_IN=( "${MIXFILES[@]}" )
    else
        last_ind=${#IN_FILES[@]}
        for i in ${!IN_FILES[@]}; do
            MIX_IN[i]=${IN_FILES[--last_ind]}
        done
        #MIX_IN=( "${IN_FILES[@]}" )
    fi
fi
# All files must be images for slide mix.
# if all are images, then we are doing a slideshow.
if $SINGLE_SLIDESHOW; then
    # if -static was not passed we have already set DO_CAROUSEL to :
    # So here we set STATIC to : as ani slideshow has its own code
    DO_FRAME=false; DO_BUTTONS=false; STATIC=:; DO_STATS=false
    CAROUSEL_IS_SHOWCASE=false
    CAROUSEL_IS_BG=false
    [[ $MENU_TITLE = "My Video Collection" ]] && \
    MENU_TITLE="My Slideshow"
fi
# don't print stats when slideshows are being done
((sshows>=1)) && DO_STATS=false

# no playall for single slideshow, and it has its own menu block, not DO_MENU
if $SINGLE_SLIDESHOW ; then
    PLAYALL=false
    ! $MONTAGE_MENU && DO_MENU=false
fi

# for slides or short files, seeking/fading will not work: set them to 0
# if user has not set a value from the command line
for i in ${!IN_FILES[@]}; do
    SHORTFILE=false
    if [[ ${file_is_image[i]} = "yes" ]]; then
        SHORTFILE=:
    else
        FRAME_CK=$(stream_length "${IN_FILES[i]}" video 90)
        [[ $( ${bC} -l <<< "$FRAME_CK < 2") -eq 1 ]] && SHORTFILE=:
    fi
    if $SHORTFILE; then
        ! $USER_SEEK_VAL && SEEK_VAL[i]=0
        ! $USER_CHAPTERS && CHAPTERS[i]=1
    fi
done
if [[ $FADE -eq 0 ]]; then # in case user thinks he needs to specify 0 for fade
    AUDIO_FADE=false
elif [[ $SM_FADE -eq 0 ]]; then
    SM_AUDIO_FADE=false
fi


##############################################################################
# Font defaults
##############################################################################

if $DO_MENU; then
    # Menu title font size
    test $TARGET = "dvd" && : ${MENU_FONTSIZE:="30"}
    # Thumbnail title font size
    # if not -titles-fontsize N passed, use default, based on the following:
    if test -z "$TITLES_FONTSIZE"; then
        if test "$NUM_FILES" -lt 2; then
            TITLES_FONTSIZE=20
        elif  test "$NUM_FILES" -eq 2; then
            TITLES_FONTSIZE=18
        elif  test "$NUM_FILES" -ge 3; then
            TITLES_FONTSIZE=16
        fi
    fi
    if test -z $CHAPT_FONTSIZE; then
        for c in ${!IN_FILES[@]}; do
            ((${CHAPTERS[c]} <= 2)) && CHAPT_FONTSIZE[c]=20
            ((${CHAPTERS[c]} == 2)) && CHAPT_FONTSIZE[c]=18
            ((${CHAPTERS[c]} >= 2)) && CHAPT_FONTSIZE[c]=16
        done
    fi
    test -z $SUBMENU_FONTSIZE && SUBMENU_FONTSIZE=$MENU_FONTSIZE

    # See if "Helvetica" or "helvetica" are available as default fonts
    if convert -size 50x20 xc:none -font Helvetica -gravity Center \
    -draw "text 0,0 'test'" "$WORK_DIR/font.png"; then
        DEFAULT_FONT="Helvetica"
    elif convert -size 200x100 xc:none -font helvetica -gravity Center \
    -draw "text 0,0 'test'" "$WORK_DIR/font.png"; then
        DEFAULT_FONT="helvetica"
    fi
    # If user did not specify fonts, use default
    test -z "$MENU_FONT" && MENU_FONT=$DEFAULT_FONT
    test -z "$TITLES_FONT" && TITLES_FONT=$DEFAULT_FONT
    test -z "$CHAPT_FONT" && CHAPT_FONT="$TITLES_FONT"
    test -z "$SM_TITLE_FONT" && SM_TITLE_FONT="$MENU_FONT"
    rm -f "$WORK_DIR/font.png"

    # Some user feedback
    if ! $SINGLE_SLIDESHOW; then
        #yecho ""
        yecho ""
        printgreen "-------------"
        if $VMGM_ONLY; then
            yecho "Disc title: \"$MENU_TITLE\""
        else
            yecho "Menu title: \"$MENU_TITLE\""
        fi
        yecho "  (adjust with -menu-title)"
        yecho "Including the following files:"
        # do not echo all of long or multiline titles AND files
        for ((i=0; i<${#TITLES[@]}; i++)); do
            if [[ ${#TITLES[i]} -gt 35 || \
            $(echo -e "${TITLES[i]}" |wc -l) -gt 1 ]]; then
                TITLE[i]=$(sed 's/^  *//'<<<${TITLES[i]//\\n/ }) # no spaces or \n
                TITLE[i]=${TITLE[i]:0:35} # cut down to 35 characters maximum
                if [ ${#TITLES[i]} -gt 35 ]; then
                    echo "  \"${TITLE[i]}...\" (${IN_FILES[i]})" # "..."
                else
                    echo "  \"${TITLE[i]}\" (${IN_FILES[i]})"
                fi
            else # echo titles "as is"
                echo "  \"${TITLES[i]}\" (${IN_FILES[i]})"
            fi
            # FIXME move this before the aspect ratio check for IN_FILES if possible
            if [[ $(echo -e "${TITLES[i]}" |wc -l) -gt 1 ]]; then
                # if there is a multiline title we need to align to right of thumbs
                $SHOWCASE && ! [[ $SC_TITLE_ALIGN = "east" ]] && \
                  align_warning="\"${TITLE[i]}\" is more than one line: \
                   - setting '-showcase-titles-align east'"
                ALIGN_OVERRIDE=:
                if [[ ! $SC_TITLE_ALIGN = east ]]; then
                    WARN_RE_ALIGN_EAST=1
                fi
            fi
        done
        yecho "Current font settings: "
        yecho "  -menu-font $MENU_FONT"
        yecho "  -menu-fontsize $MENU_FONTSIZE"
        yecho "  -titles-font $TITLES_FONT"
        yecho "  -titles-fontsize $TITLES_FONTSIZE"
        if ! $VMGM_ONLY; then
            yecho "Current menu settings: "
            if  ! $STATIC; then
                yecho "  -menu-length ${MENU_LEN[MENU_NUM-1]} seconds"
            fi
            if $ANI_SUB_MENU; then
                if $USER_SUBMENU_LEN; then
                    for i in ${!SUBMENU_LEN[@]}; do
                        sml=${SUBMENU_LEN[i]}
                        yecho "Video $((i+1)):  -submenu-length $sml seconds"
                    done
                else
                        yecho "  -submenu-length $SUBMENU_LEN seconds"
                fi
                if $SUBMENU_AUDIO; then
                    yecho "  -submenu-audio-fade $SM_FADE second(s)"
                fi
            fi
                for ((i=0; i<=NUM_FILES; i++)); do
                    echo -n "Video $((i+1)):"
                    echo -n "  -seek ${SEEK_VAL[i]} second(s)"
                    echo "  -chapters ${CHAPTERS[i]}"
                done
            if [ ! $STATIC ]; then
                yecho "  -menu-audio-fade $FADE second(s)"
            fi
            #yecho ""
            printgreen "-------------"
            yecho ""
        fi
    fi
    if ((WARN_RE_ALIGN_EAST)); then 
        #info_message "Multiline titles must be aligned east. \
        #Setting \"-align east\" for you"
        info_message "$align_warning"
        SC_TITLE_ALIGN=east
        $WARN && continue_in 3
    fi
fi
# TODO: Merge these globals with the ones up top
# only the 1st 6 are mergable - keeping them here for debugging this beast :)
# 9 /row  
NTSC_1333_DVD=(420x280 288x192 192x128 192x128 186x124 186x124 132x88 132x88 \
132x88 120x80 120x80 120x80 96x64 96x64 96x64 96x64 96x64 96x64 \
96x64 96x64 84x56 84x56 84x56 84x56 84x56 84x56 84x56 \
84x56 84x56 84x56 60x40 60x40 60x40 60x40 60x40 60x40 \
60x40 60x40 60x40 60x40 60x40 60x40 60x40 60x40 60x40
60x40 60x40 60x40 60x40)
# *_1777_DVD is for 16:9 videos displayed in proper res on a 4:3 menu
NTSC_1777_DVD=(420x210 288x144 240x120 240x120 186x98 186x98 180x90 180x90 \
180x90 132x66 132x66 132x66 132x66 132x66 132x66 132x66 100x50 100x50 \
100x50 100x50 100x50 100x50 100x50 100x50 100x50 88x44 88x44 \
88x44 88x44 88x44 80x40 80x40 80x40 80x40 80x40 80x40)
PAL_1333_DVD=(420x336 280x224 190x152 190x152 190x152 190x152 130x104 130x104 \
130x104 130x104 130x104 130x104 100x80 100x80 100x80 100x80 100x80 100x80 \
100x80 100x80 90x72 90x72 90x72 90x72 90x72 90x72 90x72 \
90x72 90x72 90x72 60x48 60x48 60x48 60x48 60x48 60x48)
PAL_1777_DVD=(420x252 280x168 240x144 240x144 190x114 190x114 190x114 190x114 \
190x114 130x78 130x78 130x78 130x78 130x78 130x78 130x78 100x60 100x60
100x60 100x60 100x60 100x60 100x60 100x60 100x60 90x54 90x54 90x54 90x54 90x54
80x48 80x48 80x48 80x48 80x48 80x48)
# 15 per row
TILE_1333=(1x1 2x1 2x2 2x2 3x2 3x2 3x3 3x3 3x3 4x3 4x3 4x3 4x4 4x4 4x4 \
4x4 5x4 5x4 5x4 5x4 5x5 5x5 5x5 5x5 5x5 6x5 6x5 6x5 6x5 6x5 \
6x6 6x6 6x6 6x6 6x6 6x6)
TILE_1777=(1x1 2x1 2x2 2x2 3x2 3x2 3x3 3x3 3x3 4x3 4x3 4x3 4x4 4x4 4x4 \
4x4 5x4 5x4 5x4 5x4 5x5 5x5 5x5 5x5 5x5 5x6 5x6 5x6 5x6 5x6 \
6x6 6x6 6x6 6x6 6x6 6x6)
SC_THUMB_Y_ARRAY=("166" "110 240" "75 175 275" "68 148 228 308" \
"68 131 194 257 320" "75 175 275 75 175 275" "68 148 228 308 68 148 228" \
"68 148 228 308 68 148 228 308" "68 131 194 257 320 68 131 194 257" \
"68 131 194 257 320 68 131 194 257 320")
SC_TITLES_Y_ARRAY=("144" "88 218" "54 154 254" \
"50 130 210 290" "49 112 175 238 301" "54 154 254 54 154 254" \
"50 130 210 290 50 130 210" "50 130 210 290 50 130 210 290" \
"49 112 175 238 301 49 112 175 238" \
"49 112 175 238 301 49 112 175 238 301")
SC_THUMB_X_ARRAY=("86" "86 86" "86 86 86" "86 86 86 86" \
"86 86 86 86 86" "86 86 86 538 538 538" "86 86 86 86 554 554 554" \
"86 86 86 86 554 554 554 554" "86 86 86 86 86 574 574 574 574" \
"86 86 86 86 86 574 574 574 574 574")
SC_THUMB_X_ARRAY=( ${SC_THUMB_X_ARRAY[NUM_FILES]} )
SC_THUMB_Y_ARRAY=( ${SC_THUMB_Y_ARRAY[NUM_FILES]} )
SC_TITLES_X_ARRAY=( ${SC_THUMB_X_ARRAY[@]} )
SC_TITLES_Y_ARRAY=( ${SC_TITLES_Y_ARRAY[NUM_FILES]} ) # not used by textmenu
if $TEXTMENU ; then
    # next line useless as it will always be overwritten for large # of titles
    ! $USER_SPLIT && SPLIT=13 # max text only titles in one column (-textmenu)
    if [[ $NUM_FILES -gt 12 ]] && ! $USER_SPLIT; then
        SPLIT=$((V_TOTAL / 2))
        (( (SPLIT * 2) != V_TOTAL)) && ((SPLIT++))
    fi
fi

if $SHOWCASE && ! $TEXTMENU; then
    # TODO? allow user to specify the SPLIT?
    ((NUM_FILES < 5)) && SPLIT=$((NUM_FILES+1)) # col 1 always >= col 2
    ((NUM_FILES == 5)) && SPLIT=3
    ((NUM_FILES >= 6)) && SPLIT=4
    ((NUM_FILES >= 8)) && SPLIT=5
    # -align *east or *west disallowed for 2 column showcase thumbs
    if ((NUM_FILES >= SPLIT)); then
        case $BUTTON_GRAVITY in
          *east|*west)
                butgrav=$BUTTON_GRAVITY
                # northeast or northwest
                if [[ $BUTTON_GRAVITY = north* ]]; then
                    BUTTON_GRAVITY=north && USER_GRAVITY=false
                # southeast or southwest
                elif [[ $BUTTON_GRAVITY = south* ]]; then
                    BUTTON_GRAVITY=south && USER_GRAVITY=false
                else # east or west
                    BUTTON_GRAVITY=north
                fi
                info_message "You can not use \"-align $butgrav\" with 2 \
                column -showcase, only \"north\", \"south\", \"center\". \
                Changing to \"-align ${BUTTON_GRAVITY}\", please check preview."
                $WARN && continue_in 10
            ;;
        esac
    # central alignment disallowed for 1 column showcase
    else
        if [[ $SHOWCASE_FILE ]]; then
            case $BUTTON_GRAVITY in
              center|north|south)
                [[ $BUTTON_GRAVITY = center ]] && but_grav="" || \
                  but_grav=$BUTTON_GRAVITY
                info_message "You can not use a central -align option as in \
                'north', 'center', or 'south' when using a showcase image and \
                a single column of titles.
                Setting '-align ${but_grav}west' for you, please check it with the preview."
                BUTTON_GRAVITY=${but_grav}west && USER_GRAVITY=false
                $WARN && continue_in 5
                ;;
              *east)
                #BUTTON_GRAVITY="northwest"
                bgrav=$BUTTON_GRAVITY
                BUTTON_GRAVITY=${BUTTON_GRAVITY/east/west} # could be west/nw/sw
                info_message "You can not use -align $bgrav when using a showcase image. \
                Setting -align $BUTTON_GRAVITY"
                $WARN && continue_in 3
            esac
        fi
    fi
fi


FFMPEG_OPTS="-b 7000k  -maxrate 8000k -bufsize 224KiB"
SS_FFMOPTS="-b 8000k -maxrate 9000k -bufsize 224KiB"
SHOWCASE_SIZE=384x256
if [ $TV_STANDARD = "ntsc" ]; then
    if [[ $ASPECT_RATIO = "4:3" ]]; then
        GEO_ARRAY=("${NTSC_1333_DVD[@]}")
        TILE_ARRAY=("${TILE_1333[@]}")
    else
        GEO_ARRAY=("${NTSC_1777_DVD[@]}")
        TILE_ARRAY=("${TILE_1777[@]}")
    fi
    VIDSIZE="720x480"
    FRAME_RATE=29.970
    ff_frame_rate="30000/1001"
    if [[ $SC_AR = 133 ]]; then
        SHOWCASE_SIZE=384x256
        SM_SHOWCASE_SIZE=288x192
    elif [[ $SC_AR = 177 ]]; then
        SHOWCASE_SIZE=384x192
        SM_SHOWCASE_SIZE=288x144
    fi
elif [ $TV_STANDARD = "pal" ]; then
    VIDSIZE="720x576"
    TILE_ARRAY=("${TILE_1333[@]}")
    FRAME_RATE=25
    ff_frame_rate="25/1"
    if [[ $SC_AR = 133 ]]; then
        SHOWCASE_SIZE=380x304
        SM_SHOWCASE_SIZE=290x232
    elif [[ $SC_AR = 177 ]]; then
        SHOWCASE_SIZE=384x230
        SM_SHOWCASE_SIZE=290x174
    fi
    if [[ $ASPECT_RATIO = "4:3" ]]; then
        GEO_ARRAY=("${PAL_1333_DVD[@]}") #TODO make sizes array for pal
    else
        GEO_ARRAY=("${PAL_1777_DVD[@]}")
    fi
fi
# set a variable for vfilter scaling based on above sizes VFSCALE
VF_SCALE=${VIDSIZE%x*}:${VIDSIZE#*x}
if [[ $TV_STANDARD = "ntsc" ]]; then
    YUV_FR=30000:1001
else
    YUV_FR=25:1
fi
THUMB_SIZE=${GEO_ARRAY[NUM_FILES]}
if $SHOWCASE; then
    if [ -z ${BLUR/.*} ]; then
        BLUR=0.${BLUR/*.}
    fi
    if (( ${BLUR/.*} > 2 )) && [[ -n $THUMB_SHAPE ]]; then
        BLUR=2.0
        if ! $TEXTMENU; then
            yecho
            yecho "Reducing thumb blur to 2.0 because you are using -showcase"
            yecho
            $WARN && continue_in 3
        fi
    fi
    if [ $V_TOTAL -lt 3 ]; then
        THUMB_SIZE=${GEO_ARRAY[10]}
    elif [ $V_TOTAL -eq 3 ]; then
        THUMB_SIZE=${GEO_ARRAY[13]}
    elif [ $V_TOTAL -eq 4 ]; then
        THUMB_SIZE=${GEO_ARRAY[23]}
    elif [ $V_TOTAL -eq 5 ]; then
        THUMB_SIZE=${GEO_ARRAY[30]}
    elif [ $V_TOTAL -eq 6 ]; then
        THUMB_SIZE=${GEO_ARRAY[13]}
    elif [[ $V_TOTAL -ge 7 && $V_TOTAL -le 8 ]]; then
        THUMB_SIZE=${GEO_ARRAY[23]}
    elif [[ $V_TOTAL -ge 9 && $V_TOTAL -le 10 ]]; then
        THUMB_SIZE=${GEO_ARRAY[30]}
    fi
fi

#create seek value for each video
for ((i=0; i<=NUM_FILES; i++)); do
    # translate SEEK_VAL into frames for transcode
    SEEK_FRAMES[i]=$(bc_math "${SEEK_VAL[i]} * $FRAME_RATE" int)
done

# some choices needed for different -align -showcase-titles and alignments
if $SHOWCASE && ! $TEXTMENU; then
    JUSTIFY="west"
    
    if ((V_TOTAL <= 5)); then
        # FIXME move this before the aspect ratio check for IN_FILES if possible
        # smaller to allow for titles
        AUTOORDER="rows"       # spumux var
        [[ $SC_TITLE_ALIGN = "east" ]] && SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
        case $BUTTON_GRAVITY in
          south|north|center)
            SC_TITLE_ALIGN="center" # moves titles to left a bit for room
            SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
            ;;
        esac
    else
        SHOWCASE_SIZE=$SM_SHOWCASE_SIZE  # smaller showcase thumb because we have 2 rows
        AUTOORDER="columns"
        if [[ $SHOWCASE_FILE ]] && \
        [[ "$SC_TITLE_ALIGN" = "east" ]]; then
            info_message "Sorry, no room for showcase thumb with 2 columns and \
            \"-showcase-titles-align east\" (or multiline titles). Change the \
            option, remove the showcase image/video, or use -textmenu.  Or \
            use -bgimage or -bgvideo instead of a thumb. Changed for you to: \
            \"-showcase-titles-align center\". Continuing on to the preview ..."
            SC_TITLE_ALIGN=center
            $WARN && continue_in 15
        fi
    fi
elif ! $SHOWCASE && ! $TEXTMENU; then
    AUTOORDER="rows"
elif $TEXTMENU; then
    AUTOORDER="columns"
fi

# set size of animated slideshow menu images
if $CAROUSEL_IS_BG; then
    CAROUSEL_SIZE=$VIDSIZE
else
    # use SHOWCASE_SIZE instead of THUMBSIZE for better quality,
    # even though for video thumbs it gets resized later
    CAROUSEL_SIZE=$SHOWCASE_SIZE
fi
$SINGLE_SLIDESHOW && ! $MK_CAROUSEL_MODE && CAROUSEL_SIZE=$VIDSIZE

# textmenu does not use -showcase-titles-align, unset this to aid block parsing
$TEXTMENU && unset SC_TITLE_ALIGN
#  -align east uses text-rect
if [[ $BUTTON_STYLE = "text-rect" ]] \
 && ! [[ $SC_TITLE_ALIGN = "east" ]] && $SHOWCASE && ! $TEXTMENU; then
    info_message "text-rect buttons need to be aligned east of thumbs by using: 
     '-showcase-titles-align east'.  Setting this option for you.
    Ctrl-c now to exit if you wish to reconsider"
    SC_TITLE_ALIGN="east"
    $WARN && continue_in 10
fi

# Do everything in $WORK_DIR
yecho "Changing to ${REAL_WORK_DIR} - $WORK_DIR will be the symlink."
yecho ""
$WARN && sleep 1
cd "$WORK_DIR"

# default of no blur if using 3D thumbs or flare shape
if $THUMBS_3D; then
    BLUR=0.1
fi
if ! ((USER_BLUR)) && [[ $THUMB_SHAPE == "flare" ]]; then
    BLUR=0.1
fi
if ! ((SC_USER_BLUR)) && [[ $SHOWCASE_SHAPE == "flare" ]]; then
    SC_BLUR=0.1
fi
# no 3d thumbs for flare shape
if $THUMBS_3D || $SHOWCASE_3D && \
  [[ $THUMB_SHAPE == "flare" || $SHOWCASE_SHAPE == "flare" ]]; then
    info_message "There is no 3d thumbs available for the 'flare' shape. "
    "Disabling this option for you"
    $WARN && continue_in 3
fi

$FOURxONE && $SHOWCASE && FOURxONE=false && tile_warning
$THREExONE && $SHOWCASE && THREExONE=false && tile_warning
# allow specifically setting the geometry for 3 videos to 1x3 page
if $THREExONE || $FOURxONE; then
    if $THREExONE && [ $V_TOTAL -eq 3 ]; then
        TILE_ARRAY[2]=3x1
        [[ $ASPECT_RATIO = "16:9" ]] && THUMB_SIZE=${GEO_ARRAY[4]}
    elif $FOURxONE && [[ $V_TOTAL -eq 4 ]]; then
        TILE_ARRAY[3]=4x1
        if  [[ $ASPECT_RATIO = "16:9" ]]; then
            THUMB_SIZE=${GEO_ARRAY[9]}
        else
            THUMB_SIZE=${GEO_ARRAY[6]}
        fi
    else
        info_message "Warning: Incorrect number of videos for ${tile_arg}:
        this option will be ignored"
        $WARN && continue_in 3
    fi
fi
# south* aligned with nav buttons may be a problem, unless aligned southwest
if { $DO_TITLESETS || $TITLESET_MODE; } && $VMGM_MENU  || $PLAYALL; then
    bydir=${BUTTON_GRAVITY/south}
    if [[ $BUTTON_GRAVITY = south* && $bydir != west ]]; then
        if $TEXTMENU; then
            # textmenu will cover the nav button if southeast aligned
            # (center and southwest should be okay).Move to "east" (higher up).
            if [[ $bydir = east ]]; then
                BUTTON_GRAVITY=east
                info_message "Changing -align option to 'east' to make room \
                for navigation button(s) like playall '>'."
                $WARN && continue_in 5
            fi
        else
            info_message "You are using -align ${BUTTON_GRAVITY}, but need \
            room for navigation buttons like playall '>'.  Please \
            check the preview and adjust your commands if necessary."
            $WARN && continue_in 7
        fi
    fi
fi

# do not use frame for showcase-framestyle glass
if [[ "$SC_FRAMESTYLE" = "glass" && -n "$SHOWCASE_VIDEO" ]] ; then
    unset SHOWCASE_FRAME
fi
# unset the showcase frame if the frame size is 0
(( ${SHOWCASE_FRAME_SIZE/x*} )) || unset SHOWCASE_FRAME

if $SHOWCASE; then
    THUMB_BG_CLR="none"   # mist backgrounds look a bit funny with showcase
fi
# easier to have non transparent showcase use the transparent block
if $SHOWCASE && ! $TRANSPARENT; then TRANSPARENT=:; fi
# spumux and dvdauthor vars
TITLES_VID_TAG="<video format=\"$TV_STANDARD\""
$WIDE_SCREEN && TITLES_VID_TAG=" $TITLES_VID_TAG widescreen=\"$WIDESCREEN\""
[[ -n "$V_ASPECT" ]] && TITLES_VID_TAG="$TITLES_VID_TAG $V_ASPECT"
TITLES_VID_TAG="$TITLES_VID_TAG />"
START="00:00:00.0"
$PLAYALL && TITLESET_PRE="g4=0;"
$ITLESET_MODE && TITLESET_PRE="$TITLESET_PRE g2=1;"

if [[ -n $AUDIO_CHANNEL ]]; then
    # if only one -audio-channel value, then use for all videos
        for ((i=0; i<=NUM_FILES; i++)); do
            if [ ${#AUDIO_CHANNEL[@]} -eq 1 ]; then
                AUDIO_PRE[i]="audio=${AUDIO_CHANNEL[0]};"
            else
                AUDIO_PRE[i]="audio=${AUDIO_CHANNEL[i]};"
            fi
        done
    for ((i=0; i<=NUM_FILES; i++)); do # create audio tag for dvdauthor
        VOB_PRE[i]="        <pre> ${AUDIO_PRE[i]} </pre>"
    done
fi

MAIN_POST="        <post> jump cell 1; </post>"
if $MENU_FADE; then
    . todisc-fade-routine
    END_TIME=$(format_seconds $THUMBS_FADEOUT_ENDTIME)
    if [[ $PAUSE_TIME != "inf" ]]; then
        END=" end=\"$END_TIME\""
    fi
    START=$(format_seconds $THUMBS_FADEIN_STARTTIME)
    POST="<post> jump cell 1; </post>"

    # only do imagemagick operations on frames we will actually see
    FIRST_PIC=$THUMBS_FADEIN_STARTFRAME # 1st image to use IM on
    LAST_PIC=$THUMBS_FADEOUT_ENDFRAME
fi
# remember that static menus can have animated background or showcase video
if $STATIC && ! $MENU_FADE && [[ -z $BG_VIDEO && -z $SHOWCASE_VIDEO ]] ; then
    if ! $USER_LOOP; then
        VMGM_PAUSE="inf"
    else
        VMGM_PAUSE=$PAUSE_TIME
    fi
else
    VMGM_PAUSE=$PAUSE_TIME
fi
# pausing a -menu-fade gives a period of unselectable thumbs: use pause of 0
if $MENU_FADE && ! $USER_LOOP && [[ $VMGM_PAUSE != "inf" ]]; then
    VMGM_PAUSE=0
fi
# loop slideshows with fades by default, unless user passed -loop VALUE
$DO_CAROUSEL && $SLIDE_FADE && ! $USER_LOOP && VMGM_PAUSE=0
if [ "$PAUSE_TIME" = "inf" ]; then
    unset MAIN_POST
fi
###############################################################################
#     generate title_txt png, and template.png needed for all operations       #
###############################################################################

if [ -z "$BG_PIC" ]; then
    echo
    echo "Creating a black background"
    BG_PIC="$WORK_DIR/pics/template.$IMG_FMT"
    $QUICK_MENU && template_colour="none" || template_colour=$BG_CLR
    convert  -resize $VIDSIZE! xc:$template_colour "$BG_PIC"
else
    convert -resize $VIDSIZE! "$BG_PIC" "$WORK_DIR/pics/template.$IMG_FMT"
fi
if $MENU_FADE; then
    cp "$WORK_DIR/pics/template.$IMG_FMT" "$WORK_DIR/pics/template.bk.$IMG_FMT"
fi

if $MENU_FADE || $FEATHER; then
    convert -depth 8 -size $VIDSIZE xc:"#101010" "$WORK_DIR/black.ppm"
fi
# now that we have a background we can do the polaroid stack if called for
if $SINGLE_SLIDESHOW && ! $DO_CAROUSEL && ! $MK_CAROUSEL_MODE; then
    echo -e "\nMaking a 'polaroid stack' of your images for the main menu"
    mk_polaroid_stack "${MIX_IN[@]}" &
    polaroid_pid=$!
    while ps -p $polaroid_pid >/dev/null; do
        sleep .5
        spin $SPINNER
    done
    echo

    # FFMPEG_OPTS="-b 7000k  -maxrate 8000k -bufsize 224KiB -aspect 4:3"
   #MENU_N=$(bc_math "$FRAME_RATE * ${MENU_LEN[MENU_NUM-1]}" int)
    #ffmpeg -f image2 -loop_input -t $MENU_LEN -i "$WORK_DIR/image_stack.png" \
    #-an -r $ff_frame_rate -s $VIDSIZE $FFMPEG_OPTS \
    #-f mpeg2video -y "$WORK_DIR/intro.m2v"
fi
# values to use for the blur mask
DIMY=$(cut -f1 -dx <<< $THUMB_SIZE)
DIMX=$(cut -f2 -dx <<< $THUMB_SIZE)
DIMY1=$((DIMY / 20))
DIMX1=$((DIMX / 20))
DIMY2=$((DIMY - DIMY1))
DIMX2=$((DIMX - DIMY1))
DIMY3=$(($DIMY2 / 2))
DIMX3=$(($DIMX2 / 2))
DIMY4=$((DIMY / 2))
DIMX4=$((DIMX / 2))
DIMY5=$((DIMY / 3))
DIMX5=$((DIMX4 / 3))
THUMB_BLUR_CMD=(convert - -blur 0x$THUMB_BLUR -channel RGBA +matte miff:-)
SC_BLUR_CMD=(convert - -blur 0x$SC_BLUR -channel RGBA +matte miff:-)
if $THUMBS_3D && $SHOWCASE && \
    [[ $THUMB_SHAPE == "normal" || $SHOWCASE_SHAPE == "normal" ]]; then
    MASK_DIM="0,0 $DIMY,$DIMX"
    THUMB_BLUR_CMD=(convert - miff:-)
    SC_BLUR_CMD=(convert - miff:-)
else
    MASK_DIM="$DIMY1,$DIMY1 $DIMY2,$DIMX2"
fi

if [[ -n "$THUMB_SHAPE" ]] && $USE_FEATHER_MASK; then
    # make a mask for the mist if called for
    convert -size $THUMB_SIZE xc:none -fill  "$THUMB_BG_CLR" -stroke none \
    -draw "rectangle $DIMY1,$DIMY1 $DIMY2,$DIMX2" "$WORK_DIR/feather_orig.png"
    convert "$WORK_DIR/feather_orig.png" -channel RGBA \
    -blur 0x60 "$WORK_DIR/feather_mask2.png"
fi
[[ -z "$TITLES_CLR" ]] && TITLES_CLR='#EAEAEA'
# set submenu font colours to defaults if not passed in
[[ -z $CHAPTER_STROKE ]] && CHAPTER_STROKE="$SUBMENU_STROKE"
[[ -z $CHAPTER_CLR ]] && CHAPTER_CLR="$TITLES_CLR"

if $DO_MENU; then
    # make thumb-shape mask - showcase mask made later after its size is set
    if [[ -n $THUMB_SHAPE ]]; then
        make_mask $THUMB_SHAPE thumb
        THUMB_MASK="$MASK"
    fi
    
    # make a menu title image
    print2log "Creating a menu title image"
    if $USE_M_TITLE_DECO; then
        # using -title-stroke does a plain 'makemenu' style font with no shadow
        # but using font outline like makemenu does
        M_TITLE_CMD=(convert -size 620x100 xc:none -font "$MENU_FONT" \
        -pointsize $MENU_FONTSIZE -fill "$TITLE_CLR" -gravity center \
        "${M_TITLE_FONT_DECO[@]}" -annotate +0+0 "$MENU_TITLE")
        #-stroke none -annotate +0+0 "$MENU_TITLE")
    else
        # with no -title-stroke passed, make a font shadow for contrast
        # but no font outline (it will be a shadow on one side only
        M_TITLE_STROKE=${M_TITLE_STROKE:-black}
        M_TITLE_CMD=(convert -size 620x300 xc:none -gravity \
        $JUSTIFY -font "$MENU_FONT" -pointsize $MENU_FONTSIZE \
        -fill none  -stroke "$M_TITLE_STROKE" -strokewidth 1 \
        -annotate +0+0 "$MENU_TITLE" \
        -fill $TITLE_CLR  -stroke none \
        -annotate +1+1 "$MENU_TITLE")
    fi
    TRIM_CMD="-trim +repage -blur 0x0.3"
    M_TITLE_CMD0=(composite -blend 0x${TITLE_OPACITY}  null: - -matte)
    M_TITLE_CMD1=(convert - $TRIM_CMD  "$WORK_DIR/title_txt.png")

    if [[ -n $TITLE_OPACITY ]]; then
        "${M_TITLE_CMD[@]}" miff:- | "${M_TITLE_CMD0[@]}" miff:- |
        "${M_TITLE_CMD1[@]}" >> "$LOG_FILE" 2>&1
    else
        "${M_TITLE_CMD[@]}" miff:- | "${M_TITLE_CMD1[@]}" >> "$LOG_FILE" 2>&1
    fi
fi
# this is really part of same DO_MENU block above, splitting up for readability
if $DO_MENU; then
    # make video titles
    if ! $SINGLE_SLIDESHOW; then
        for ((i=0; i<=NUM_FILES; i++)); do
            print2log "Working on video title $((i+1)) "
            if $USE_V_TITLES_DECO; then
                # use a font outline makemenu style
                V_TITLES_CMD=(convert -size 620x100 xc:none \
                -font "$TITLES_FONT" -pointsize $TITLES_FONTSIZE \
                -fill "$TITLES_CLR" "${V_TITLES_FONT_DECO[@]}" \
                -gravity center -annotate +0+0 "${TITLES[i]}")
            #    #-stroke none -annotate +0+0 "${TITLES[i]}")
            else
                # default is to use a font shadow only on one side of font
                V_TITLES_STROKE=${V_TITLES_STROKE:-black}
                V_TITLES_CMD=(convert -size 620x300 xc:none -gravity $JUSTIFY \
                -font "$TITLES_FONT" -pointsize $TITLES_FONTSIZE \
                -fill none  -stroke "$V_TITLES_STROKE" -strokewidth 1 \
                -annotate +0+0 "${TITLES[i]}" \
                -fill $TITLES_CLR  -stroke none \
                -annotate +1+1 "${TITLES[i]}")
            fi
            FADE_CMD=(composite -blend 0x${TITLES_OPACITY}  null: - -matte)
            # only repage and border if not 'text button'
            if [[ $BUTTON_STYLE = "text" ]]; then
                TRIM_CMD=(convert - -trim "$WORK_DIR/thumb_title${i}.png")
            else
                TRIM_CMD=(convert - -trim +repage $TEXT_BORDER \
                "$WORK_DIR/thumb_title${i}.png")
            fi
            # make thumb title
            if [[ -n $TITLES_OPACITY ]]; then
                "${V_TITLES_CMD[@]}" miff:- | "${FADE_CMD[@]}" miff:- |
                "${TRIM_CMD[@]}"
            else
                "${V_TITLES_CMD[@]}" miff:- | "${TRIM_CMD[@]}"
            fi
            # save dimensions for later use
            TT_DIM[i]=$(get_image_dim "$WORK_DIR/thumb_title${i}.png")
            # now get offset before repaging, for the spumux button crop later
            if [[ $BUTTON_STYLE = "text" ]]; then
                titles_offset[i]=$(identify -format %O \
                "$WORK_DIR/thumb_title${i}.png")
                titles_dim[i]=$(identify -format %wx%h \
                "$WORK_DIR/thumb_title${i}.png")
                convert "$WORK_DIR/thumb_title${i}.png" +repage \
                "$WORK_DIR/thumb_title${i}.png"
            fi

            # make spumux buttons now if 'text' button style
            if [[ $BUTTON_STYLE = "text" ]]; then
                for btn in ${HLIGHT_CLR/\#} ${SELECT_CLR/\#}; do
                    btncmd=(convert +antialias -background none \
                    -fill none -size 620x300 xc:none -font "$TITLES_FONT" \
                    -pointsize $TITLES_FONTSIZE -gravity $JUSTIFY \
                    -fill "#${btn}" -stroke none \
                    -annotate +1+1 "${TITLES[i]}" \
                    "$WORK_DIR/thumb_title${i}-${btn}.png")
                    "${btncmd[@]}"
                done
                # crop the button to the same size as the thumb_title*.png
                for clr in ${HLIGHT_CLR/\#} ${SELECT_CLR/\#}; do
                    btn="$WORK_DIR/thumb_title${i}-${clr}.png"
                    convert "$btn" +antialias \
                    -crop ${titles_dim[i]}${titles_offset[i]} +repage "$btn"
                done
                # rename textmenu buttons, - they don't need further processing
                if $SHOWCASE; then
                    mv "$WORK_DIR/thumb_title${i}-${HLIGHT_CLR/\#}.png" \
                    "$WORK_DIR/$(printf %06d%s%s ${i} -highlight .png)"
                    mv "$WORK_DIR/thumb_title${i}-${SELECT_CLR/\#}.png" \
                    "$WORK_DIR/$(printf %06d%s%s ${i} -select .png)"
                fi
            fi
            # find out dimension of the thumb title png
            TT_DIM=( ${TT_DIM[@]} $(get_image_dim \
                "$WORK_DIR/thumb_title${i}.png") )
            if ! $SHOWCASE && (( ${TT_DIM[i]/x*} > ${THUMB_SIZE/x*} )); then
                usage_error "The title \"${TITLES[i]}\" is too long to fit
                at your fontsize.  Use a smaller font with -titles-fontsize"
            fi
        done
        yecho ""
    fi
fi
###############################################################################
############ set showcase/textmenu titles and thumb positions array ###########
###############################################################################

# this is really part of same DO_MENU block above, splitting up for readability
if $DO_MENU && $SHOWCASE; then
    # textmenu also uses this block !
    # get widest png in each colum for use later for alignment use
    for ((i=0; i<=NUM_FILES; i++)); do
        unset ts_dim j
        if ((i < SPLIT)); then
            # save widest_title x_dim as well as its array index
            val=${TT_DIM[i]/x*}
            [ -z "$widest_title" ] || ((val > widest_title)) \
              && widest_title=$val && widest_title_index=$i
        else
            val2=${TT_DIM[i]/x*}
            [ -z "$widest_title2" ] || ((val2 > widest_title2)) \
              && widest_title2=$val2 && widest_title2_index=$i
        fi
        # get just X demension to help determine final title pos below
        tt_dim=${TT_DIM[i]/x*}
    done
    # so we can do math on the var without error
    ((widest_title2)) || widest_title2=0

    ######################################################################
    ############### showcase with thumbs only X dimension ################
    ######################################################################

    { $TEXTMENU && LEFT_MAX=$SPLIT ; } || LEFT_MAX=5
    # textmenu doesn't use this block at all
    # TODO check_space=0 # only check if enough space once if $SHOWCASE_FILE
    # some shortened var names for the math in this block
    tt_w=${TT_DIM[i]} # title width
    tt_w=${tt_w/x*}
    t_w=${THUMB_SIZE/x*} # thumb width
    safe_w=$SAFE_AREA # safe area width
    vsize_w=${VIDSIZE/x*} # video size width (720)
    for ((i=0; i<=NUM_FILES; i++)); do
        # get array positions for thumbs and titles.  The titles_xdelta is
        # the amount we subtract later from the thumb position to re-define
        # the arrays when the various -align options are taken into account
        case $SC_TITLE_ALIGN in
          west)
            # only need extra room after 2nd column for long titles
            ovflow=$(( widest_title2 - t_w ))
            if ((i < SPLIT)); then
                SC_THUMB_X_ARRAY[i]=$((${SC_THUMB_X_ARRAY[i]} - SAFE_OFFSET))
            else
                # ovflow=0 is the right edge of thumb, so stop there
                ((ovflow < 0)) && ovflow=0
                # titles are aligned west: try to align east side close to edge
                SC_THUMB_X_ARRAY[i]=$(( vsize_w - t_w  - safe_w - ovflow ))
            fi
            SC_TITLES_X_ARRAY[i]=${SC_THUMB_X_ARRAY[i]}
            titles_xdelta[i]=0 # for using later in -align options
            ;;
          east)
            #if ((i < SPLIT)) && ! $ALIGN_OVERRIDE; then
                #SC_THUMB_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - \
                #SAFE_OFFSET ))
                #SC_TITLES_X_ARRAY[i]=$(( ${SC_TITLES_X_ARRAY[i]} - \
                #SAFE_OFFSET ))
            #fi
            if ((i >= SPLIT)); then
                # 2 cols can't -align east/west/center so no ALIGN_OVERRIDE test
                SC_THUMB_X_ARRAY[i]=$(( ( vsize_w - safe_w) - \
                    $widest_title2 - t_w - 5 ))
                    # titlesafe warnings disabled for now
                    #roffset=$(( ${SC_TITLES_X_ARRAY[i]} + 5 + safe_w ))
                    #if (( roffset + ${TT_DIM[i]/x*} > vsize_w )); then
                    #    titlesafe_error $(( roffset - vsize_w ))
                    #fi
            fi
            SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} + t_w + 5 ))
            SC_TITLES_Y_ARRAY[i]=${SC_THUMB_Y_ARRAY[i]}
            titles_xdelta[i]=$(( ${SC_THUMB_X_ARRAY[i]} - ${SC_TITLES_X_ARRAY[i]} ))
            ;;
          center)
            # make sure the showcase file is not being covered up
            ! [[ $widest_title ]] && widest_title=0
            ! [[ $widest_title2 ]] && widest_title2=0
            #if ((widest_title2)); then
            #    col2_thumb_x=$widest_title2
            #    thumbs_space=$((${THUMB_SIZE/x*} * 2))
            #else
            #    col2_thumb_x=0
            #    thumbs_space=${THUMB_SIZE/x*}
            #fi
            # need to rewrite, checking only the area on sides of the sc thumb
            #if [[ $SHOWCASE_FILE ]]; then #&& ! ((checked_space)); then
            #    safearea=$((SAFE_AREA * 2))
            #    titles_space=$((widest_title + col2_thumb_x))
            #    if $(( (VS - safearea - \
            #      titles_space - thumbs_space - ShowCaseSize) <= 0)); then
            #        : # problem: do something #FIXME run this only once
            #    fi
            #fi
            #checked_space=1
            # check if "title-safe" (not too close to screen edge or offscreen)
            # for showcase with thumbs and center aligned titles only # FIXME?
            # thumb pos + 1/2 (X dim) of thumbsize - 1/2 (X dim) of title size
            f=$(( ${THUMB_SIZE/x*} / 2 ))
            j=$(( ( ${SC_THUMB_X_ARRAY[i]} + f ) - (${TT_DIM[i]/x*} / 2) ))
            if ((widest_title > ${TT_DIM[i]/x*})); then
                offset1=$(( (widest_title - ${TT_DIM[i]/x*}) / 2 ))
                offset2=$((widest_title2 - ${TT_DIM[i]/x*} / 2 ))
            else
                offset1=${TT_DIM[i]/x*}
            fi
            offset_from_safe_edge1=$offset # unused
            tt_x=( ${tt_x[@]} "$j" )
            l=$((j + tt_dim))
            # FIXME this test gives wrong result and is unused right now !
            if ((i < SPLIT)); then
                if (( j < SAFE_AREA + SAFE_OFFSET )); then
                    off_left=$j
                    # titlesafe warnings disabled for now
                    #titlesafe_error $off_left
                fi
            else
                if (( l > vsize_w - SAFE_AREA - SAFE_OFFSET)); then
                    off_right=$(($vsize_w - l))
                    #titlesafe_error $off_right
                fi
            fi
            titles_xdelta[i]=$(( ${SC_THUMB_X_ARRAY[i]} - ${tt_x[i]} ))
            ;;
        esac
        # now that we have the title delta, factor in -align option (E/W/Centre)
        td=${titles_xdelta[i]}
        case $BUTTON_GRAVITY in
          *east) # single column showcase with thumbs only
            # if title is wider than thumb
            #if ((tt_w > t_w)); then
            #    SC_TITLES_X_ARRAY[i]=$(( vsize_w - safe_w - tt_w ))
            # thumb wider, or they are the same
            #else
            #    SC_TITLES_X_ARRAY[i]=$(( vsize_w - safe_w - t_w ))
            #fi
            # titles also aligned east of thumb need to Add the (neg) xdelta
            #if [[ $SC_TITLE_ALIGN = east ]]; then
            #    SC_THUMB_X_ARRAY[i]=$(( vsize_w - safe_w - t_w - (widest_title / 2) + td  ))
            #else
            #    SC_THUMB_X_ARRAY[i]=$(( vsize_w - safe_w - t_w - (widest_title / 2) ))
            #fi
            #SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
            if [[ $SC_TITLE_ALIGN = east ]]; then
                SC_TITLES_X_ARRAY[i]=$(( vsize_w - safe_w - widest_title ))
                SC_THUMB_X_ARRAY[i]=$(( ${SC_TITLES_X_ARRAY[i]} - 5 - t_w ))
            else
                SC_THUMB_X_ARRAY[i]=$(( vsize_w - safe_w - t_w - (widest_title / 2) ))
                SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
            fi
            ;;
          *west)  # single column showcase with thumbs only
            # they are the same, as the west sides are flush (titles_xdelta=0)
            SC_THUMB_X_ARRAY[i]=$((SAFE_AREA + SAFE_OFFSET))
            SC_TITLES_X_ARRAY[i]=$((${SC_THUMB_X_ARRAY[i]} - td))
            ;;
          north|south|center) # either single or 2 column showcase with thumbs
            if ((NUM_FILES >= SPLIT)); then # 2 column showcase (N/S/C only)
                #if ((widest_title2 > t_w)); then
                #    SC_THUMB_X_ARRAY[i]=$((vsize_w - safe_w - t_w + td))
                #fi
                SC_TITLES_X_ARRAY[i]=$((${SC_THUMB_X_ARRAY[i]} - td))
            else # single column showcase (all -align opt should work)
                SC_THUMB_X_ARRAY[i]=$(( (vsize_w / 2) - (t_w / 2) ))
                SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
            fi
            #if ((tt_w > t_w)); then
            #    SC_THUMB_X_ARRAY[i]=$(( (vsize_w / 2) - (t_w / 2) ))
            #    SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
            #else
            #    SC_THUMB_X_ARRAY[i]=$(( (vsize_w / 2) - (t_w / 2) ))
            #    SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
            #fi
            #echo thumb: ${SC_THUMB_X_ARRAY[i]} title: ${SC_TITLES_X_ARRAY[i]}
                ;;
          *)
            # default is to use original arrays.  Subtract titles_xdelta
            SC_TITLES_X_ARRAY[i]=$(( ${SC_THUMB_X_ARRAY[i]} - td ))
            ;;
        esac
    done
    ######################################################################
    ############### showcase with thumbs only Y dimension ################
    ######################################################################

    # bottom edge of last thumb vertically
    SW_CORNER=$(( ${SC_THUMB_Y_ARRAY[SPLIT-1]} + ${THUMB_SIZE/*x} ))
    # TODO add north) so user can align flush with top safearea edge
    # as the default is not 'exactly' north in these terms, but a compromise
    # center aligned titles only can use *west -align options
    case $BUTTON_GRAVITY in
      northwest)
        : # no offset
        ;;
      south*)
        Y_OFFSET=$(( ( ${VIDSIZE/*x} - SAFE_AREA) - SW_CORNER ))
        ;;
      *east|*west|center)
        COL1_HEIGHT=$(( SW_CORNER - ${SC_TITLES_Y_ARRAY[0]} ))
        Y_OFFSET=$(( ( ${VIDSIZE/*x} / 2) - (COL1_HEIGHT / 2) ))
        Y_OFFSET=$(( Y_OFFSET - ${SC_TITLES_Y_ARRAY[0]} ))
        ;;
    esac
    #if [[ $BUTTON_GRAVITY = south* ]]; then
    #    Y_OFFSET=$(( ( ${VIDSIZE/*x} - SAFE_AREA) - SW_CORNER ))
    #elif [[ $BUTTON_GRAVITY = *st* ]] || [[ $BUTTON_GRAVITY = *center* ]]; then
    #    COL1_HEIGHT=$(( SW_CORNER - ${SC_TITLES_Y_ARRAY[0]} ))
    #    Y_OFFSET=$(( ( ${VIDSIZE/*x} / 2) - (COL1_HEIGHT / 2) ))
    #    Y_OFFSET=$(( Y_OFFSET - ${SC_TITLES_Y_ARRAY[0]} ))
    #fi
    for ((i=0; i<=NUM_FILES; i++)); do
        SC_THUMB_Y_ARRAY[i]=$((${SC_THUMB_Y_ARRAY[i]} + Y_OFFSET ))
        SC_TITLES_Y_ARRAY[i]=$((${SC_TITLES_Y_ARRAY[i]} + Y_OFFSET))
    done
    #fi
    # showcase style default: left justification. montages default: center.
    # find out the showcase thumb "-page" array for this arrangement
    for ((i=0; i<=NUM_FILES; i++)); do
        if $TEXTMENU; then
            SCTHUMB_PAGES_ARRAY[i]=+${SC_TITLES_Y_ARRAY[i]}+${SC_TITLES_X_ARRAY[i]}
        else
            SCTHUMB_PAGES_ARRAY[i]=+${SC_THUMB_X_ARRAY[i]}+${SC_THUMB_Y_ARRAY[i]}
        fi
    done
fi

##############################################################################
#################                 textmenu only              #################
##############################################################################

if $DO_MENU && $TEXTMENU; then
    #############            textmenu  Y dimension               #############
    # text-rect is OK with a small space between titles for spumux
    [[ $BUTTON_STYLE = "text-rect" ]] && \
      SPACER=${SPACER:-"10"} || SPACER=${SPACER:-"15"}

    # get array of titles Y positions for textmenu
    offsets1=$(for ((c=0; c<NUM_FILES; c++)); do
    ((c < (LEFT_MAX-1))) && echo $((${TT_DIM[c]#*x} + SPACER)); done)
    if ((NUM_FILES >= SPLIT)); then
        # to line up rows across, use taller of 2 images for space calc.
        if (( ${TT_DIM[c-SPLIT]#*x} > ${TT_DIM[c]#*x} )); then
            tt_yspace=${TT_DIM[c-SPLIT]#*x}
        else
            tt_yspace=${TT_DIM[c]#*x}
        fi
        offsets1=$(for ((c=0; c<NUM_FILES; c++)); do
        ((c < (LEFT_MAX-1))) && echo $((tt_yspace + SPACER)); done)
        offsets2=$(for ((d=0; d<=NUM_FILES; d++)); do
        ((d >= LEFT_MAX)) && echo $((tt_yspace + SPACER)); done)
        [[ $offsets2 ]] && offsets2="$TEXT_YSTART $offsets2"
        tt_ygeos_col2=$(running_total <<< $offsets2)
    fi
    offsets1="$TEXT_YSTART $offsets1"
    tt_ygeos_col1=$(running_total <<< $offsets1)
    tt_ygeos="$tt_ygeos_col1 $tt_ygeos_col2"
    unset SC_TITLES_Y_ARRAY
    SC_TITLES_Y_ARRAY=( $tt_ygeos_col1 $tt_ygeos_col2 )
    # get y position of the last title in 1st column (tt_ygeos_col1)
    endtitle_col1=$(wc -w <<< "$tt_ygeos_col1")
    endtitle_col1_ygeo=${SC_TITLES_Y_ARRAY[endtitle_col1-1]/*x}
    # add y dimension of the last title size to the above y position
    SW_YCORNER=$((${TT_DIM[endtitle_col1-1]/*x} + $endtitle_col1_ygeo))
    avail_space1=$(( ( ${VIDSIZE/*x} - SAFE_AREA ) - $SW_YCORNER ))
    # if there are 2 columns, get same data for column 2
    if [[ -n $tt_ygeos_col2 ]]; then
        endtitle_col2=$NUM_FILES
        endtitle_col2_ygeo=${SC_TITLES_Y_ARRAY[endtitle_col2]/*x}
        endtitle_col2_xgeo=${SC_TITLES_Y_ARRAY[endtitle_col2]/x*}
        SE_YCORNER=$((${TT_DIM[endtitle_col2]/*x}+$endtitle_col2_ygeo))
        avail_space2=$(( ( ${VIDSIZE/*x} - SAFE_AREA ) - SE_YCORNER ))
    fi
    # available space is lowest value of 2 *space* vars ( if 2 columns)
    if [[ -n $tt_ygeos_col2 ]] && ((SE_YCORNER > SW_YCORNER)); then
        avail_space=$avail_space2
        end_title_pos=$SE_YCORNER
    else
        avail_space=$avail_space1
        end_title_pos=$SW_YCORNER
    fi
    # get the height of each column for -align centre
    if [[ $BUTTON_GRAVITY = "center" \
      || $BUTTON_GRAVITY = "east" || $BUTTON_GRAVITY = "west" ]]; then
        WEST_YSPACE=$(( SW_YCORNER - TEXT_YSTART))
        EAST_YSPACE=$((SE_YCORNER - TEXT_YSTART))
        ((WEST_YSPACE > EAST_YSPACE)) && YSPACE=$WEST_YSPACE \
          || YSPACE=$EAST_YSPACE
        CANVAS_Y=$(( ${VIDSIZE/*x} - (SAFE_AREA * 2) ))
        NEW_TEXT_YSTART=$(( ( (CANVAS_Y - YSPACE) / 2) + SAFE_AREA ))
        TEXT_YSTART_OFFSET=$((NEW_TEXT_YSTART - TEXT_YSTART))
    fi
    # add available space to each title position for south alignment
    if [[ $BUTTON_GRAVITY = *south* ]] && ((avail_space > 0)); then
        for ((d=0; d<=NUM_FILES; d++)); do
            SC_TITLES_Y_ARRAY[d]=$(( $avail_space + \
              ${SC_TITLES_Y_ARRAY[d]} ))
        done
    elif  [[ $BUTTON_GRAVITY = "center" \
      || $BUTTON_GRAVITY = "east" || $BUTTON_GRAVITY = "west" ]]; then
        for ((d=0; d<=NUM_FILES; d++)); do
            SC_TITLES_Y_ARRAY[d]=$(($TEXT_YSTART_OFFSET + \
              ${SC_TITLES_Y_ARRAY[d]} ))
        done
    fi
fi
    ########################  textmenu X dimension  ##########################
# this is really part of block above, split up for readability
if $DO_MENU && $TEXTMENU; then
    XSPACE=$(( ${VIDSIZE/x*} - SAFE_AREA ))
    # title Xdim location for ONE column on right side (left justified)
    ljustify_eoffset=$((XSPACE-widest_title))
    # same as above, but for 2nd column when using TWO title columns
    ljustify_eoffset2=$((XSPACE-widest_title2))
    for ((d=0; d<=NUM_FILES; d++)); do
        ([[ "$BUTTON_GRAVITY" = *east* ]] \
          || [[ -n $tt_ygeos_col2 ]]) && \
            rjustify_eoffset=$(( XSPACE - ${TT_DIM[d]/x*} ))
        if ((d < SPLIT)); then
            # default is northwest alignment
            SC_TITLES_X_ARRAY[d]=$SAFE_AREA
            # for centred align add safe area from both sides
            case "$BUTTON_GRAVITY" in
              "center" | "north" | "south")
                SC_TITLES_X_ARRAY[d]=$((( (XSPACE + SAFE_AREA) / 2) - \
                (${TT_DIM[d]/x*} / 2) ))
                ;;
              "northeast"|"southeast"|"east")
                # allow justifying east column to right instead of left
                if $EDGE_JUSTIFY; then
                    SC_TITLES_X_ARRAY[d]=$rjustify_eoffset
                else
                    SC_TITLES_X_ARRAY[d]=$ljustify_eoffset
                fi
                ;;
            esac
        else # could be single column or a 2nd column, aligned east
            if ((d >= LEFT_MAX)); then # therefore this is an east column
                # allow justifying east column to right instead of left
                if $EDGE_JUSTIFY; then
                    SC_TITLES_X_ARRAY[d]=$rjustify_eoffset
                else
                    SC_TITLES_X_ARRAY[d]=$ljustify_eoffset2
                fi
            else
                SC_TITLES_X_ARRAY[d]=$SAFE_AREA
            fi
        fi
    done
    unset MAX_VAL val max_key
    # END textmenu block
fi
if $SHOWCASE; then
    # make -page arrays for thumbs, and for titles
    # use values set in the above block for textmenu
    # and for showcase with thumbs unless doing centre align for titles
    for ((i=0; i<=NUM_FILES; i++)); do
        #if [ "$SC_TITLE_ALIGN" != "center" ]; then
        SC_TITLES_ARR[i]=+${SC_TITLES_X_ARRAY[i]}+${SC_TITLES_Y_ARRAY[i]}
        #else
        #    SC_TITLES_ARR[i]=+${tt_x[i]}+${SC_TITLES_Y_ARRAY[i]}
        #fi

        SHOWCASE_THUMB_PAGES[i]="-page ${SCTHUMB_PAGES_ARRAY[i]}"
        THUMBTITLES_ARRAY[i]="-page ${SC_TITLES_ARR[i]}"
    done
    echo 
fi
# make a button for playall and one for jumping to the vmgm menu, if called for
# or make a 'play' button if doing a montage slideshow menu
pa_ind=$((NUM_FILES+1))
if { $PLAYALL && $DO_MENU ; } || $SINGLE_SLIDESHOW; then
    if { $TITLESET_MODE && $VMGM_MENU ; } && ! $VMGM_ONLY; then
        $SHOWCASE && PLAYALL_BTN_yOFFSET=50 || PLAYALL_BTN_yOFFSET=80
        PLAYALL_BTN_xOFFSET=50
    else
        PLAYALL_BTN_xOFFSET=50 && PLAYALL_BTN_yOFFSET=55
    fi
    PLAYALL_BTN_OFFSETS="+$PLAYALL_BTN_xOFFSET+$PLAYALL_BTN_yOFFSET"
    mk_play_button  "#C6C6C6" '#101010' default  "$WORK_DIR/Playall.png"
    ADD_PLAYALL_BTN=("$WORK_DIR/Playall.png" -gravity SouthEast -geometry \
      "$PLAYALL_BTN_OFFSETS" -composite)
    # make the button for spumux too
    mk_play_button  "$HLIGHT_CLR" "$HLIGHT_CLR" spu \
     "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png"
    mogrify -channel A -threshold 50% \
     "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png"
    mk_play_button   "$SELECT_CLR" "$SELECT_CLR" spu \
     "$WORK_DIR/Playall_${SELECT_CLR/\#}.png"
    mogrify -channel A -threshold 50% \
     "$WORK_DIR/Playall_${SELECT_CLR/\#}.png"
    # coordinates for spumux
    X0=$(( ${VIDSIZE/x*} - PLAYALL_BTN_xOFFSET - play_btn_width))
    Y0=$((${VIDSIZE/*x} - PLAYALL_BTN_yOFFSET - play_btn_height))
    X1=$((X0 + play_btn_width))
    Y1=$((Y0 + play_btn_height))
    # spumux needs the coordinates to be divisible by 2
    ((X0%2 && X0--));  ((Y0%2 && Y0--))
    ((X1%2 && X1--));  ((Y1%2 && Y1--))
    if $SHOWCASE; then
        if $SINGLE_SLIDESHOW; then
            :
        else
            pa_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
            btn_geos[pa_ind]=${pa_geos[@]}
        fi
    fi
    if ! $SHOWCASE && $SINGLE_SLIDESHOW; then
        ss_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
       btn_geos[0]=${ss_geos[@]}
    fi
fi
# make back button for submenus
if $SUB_MENU; then
    mk_return_button "$HLIGHT_CLR" "$HLIGHT_CLR" spu \
    "$WORK_DIR/sm_back_${HLIGHT_CLR/\#}.png"
    mk_return_button  "$SELECT_CLR" "$SELECT_CLR" spu \
     "$WORK_DIR/sm_back_${SELECT_CLR/\#}.png"
    mk_return_button "#C6C6C6" '#101010' default "$WORK_DIR/sm_back.png"
    SM_BK_PNG="$WORK_DIR/sm_back.png"
fi
if $TITLESET_MODE && $VMGM_MENU && ! $VMGM_ONLY; then
    RTN_BTN_yOFFSET=50; RTN_BTN_xOFFSET=50
    RTN_BTN_OFFSETS="+$RTN_BTN_xOFFSET+$RTN_BTN_yOFFSET"
    # put return button on left side for showcase, right side if not showcase
    if $SHOWCASE; then
        RTN_BTN_GRAVITY=SouthWest
        ind=$((NUM_FILES+2))
    else
        RTN_BTN_GRAVITY=SouthEast
    fi
    mk_return_button "#C6C6C6" '#101010' default "$WORK_DIR/Main.png"
    ADD_RTN_BTN=("$WORK_DIR/Main.png" -gravity $RTN_BTN_GRAVITY \
    -geometry "$RTN_BTN_OFFSETS" -composite)
    # make the image for spumux while we at add it
    mk_return_button "$HLIGHT_CLR" "$HLIGHT_CLR" spu \
     "$WORK_DIR/Main_${HLIGHT_CLR/\#}.png"
    mk_return_button  "$SELECT_CLR" "$SELECT_CLR" spu \
     "$WORK_DIR/Main_${SELECT_CLR/\#}.png"
    # coordinates for spumux
    X0=$RTN_BTN_xOFFSET
    if ! $SHOWCASE && $SINGLE_SLIDESHOW; then
        X0=$((${VIDSIZE/x*} - $RTN_BTN_xOFFSET - rtn_btn_width))
    fi
    Y0=$((${VIDSIZE/*x} - RTN_BTN_yOFFSET - rtn_btn_height))
    X1=$((X0 + rtn_btn_width))
    Y1=$((Y0 + rtn_btn_height))
    # spumux needs the coordinates to be divisible by 2
    ((X0%2 && X0--)); ((Y0%2 && Y0--))
    ((X1%2 && X1++)); ((Y1%2 && Y1++))
    # single slideshow has hidden button - no spumux geometries needed
    if $SHOWCASE; then
        if $SINGLE_SLIDESHOW; then
            :
        else # else pass on button geometries for making spumux xml
            rtn_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
            btn_geos[ind]=${rtn_geos[@]}
        fi
    fi
    if ! $SHOWCASE && $SINGLE_SLIDESHOW; then
        if $TITLESET_MODE && $VMGM_MENU; then
            rtn_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
            btn_geos[1]=${rtn_geos[@]}
        fi
    fi
fi

if [[ -n $MENU_TITLE ]] && $DO_MENU; then
    TITLE_TEXT_DIM=$(get_image_dim "$WORK_DIR/title_txt.png")
    TITLE_TEXT_XDIM=${TITLE_TEXT_DIM/x*}
    TITLE_TEXT_YDIM=${TITLE_TEXT_DIM/*x}
fi
if $MIST; then
    echo
    echo "Making a white or colored png for the misted title background"
    echo
    # make a white/coloured png for misted background effect, only for user bg
    # add 10 pixels to width and height compared to title text png
    y=$((TITLE_TEXT_YDIM + 40))
    x=$((TITLE_TEXT_XDIM + 40))
    newX=$((TITLE_TEXT_XDIM + 30))
    newY=$((TITLE_TEXT_YDIM + 30))
    DIM=${x}x${y}
    convert -size $DIM xc:none -fill $MIST_COLOUR -stroke none \
    -draw "rectangle 10,10 $newX,$newY" "$WORK_DIR/white_orig.png"
    convert $WORK_DIR/white_orig.png -channel RGBA -blur 0x4 \
      "$WORK_DIR/white.png"
    unset X Y x y
fi
# offsets for placing title and mist for Y dimension
# place menu title lower if not text mist and -title-geo is not supplied
if $MIST; then
    if [[ $TITLE_GRAVITY = *south* || $TITLE_GRAVITY = *north* ]]; then
        title_yoffset=${title_yoffset:-"+65"}
        mist_yoffset="$(( ${title_yoffset#*[-+]} - 20))"
    else
        title_yoffset=${title_yoffset:-"+0"}
        mist_yoffset="$(( ${title_yoffset#*[-+]} - 0))"
    fi
else
    title_yoffset=${title_yoffset:-"+50"}
fi
[[ ${mist_yoffset:0:1} != [+-] ]] && mist_yoffset=+${mist_yoffset}
# offsets placing title and mist for X dimension
if $MIST; then
    mist_dim=$(get_image_dim "$WORK_DIR/white.png" )
    mist_xdim=${mist_dim/x*}
    mist_xoffset=$(( (mist_xdim - TITLE_TEXT_XDIM) / 2 ))
    case $TITLE_GRAVITY in
      northeast|southeast|east)
        title_xoffset=${title_xoffset:-"+50"}
        mist_xoffset="$(bc_math "${title_xoffset#*[-+]} - $mist_xoffset" int)"
        [[ ${mist_xoffset:0:1} != [+-] ]] && mist_xoffset=+${mist_xoffset}
        ;;
      *)
        title_xoffset=${title_xoffset:-"+0"}
        mist_xoffset=$title_xoffset
        ;;
    esac
else
        # make sure the offset supplied is >= safe_area
        if [[ $TITLE_GRAVITY = east || $TITLE_GRAVITY = west ]]; then
            ((${title_xoffset#*[-+]} < SAFE_AREA)) && title_xoffset=+${SAFE_AREA}
        fi
        title_xoffset=${title_xoffset:-"+0"}
fi
###############################################################################
#      generate a basic preview of the main menu                              #
###############################################################################
# generate images for montage and title and resize them
if [[ -n "$BG_VIDEO" ]] && ! $QUICKMENU_IS_BACKGROUND; then
    echo
    echo "Getting background video images from $BG_VIDEO"
    if $FAST_SEEK; then
        bg_pre_seek="-ss $BG_SEEK" && unset bg_post_seek
    else
        bg_post_seek="-ss $BG_SEEK" && unset bg_pre_seek
    fi
    FFMPEG_CMD=($FFmpeg $bg_pre_seek -i "$BG_VIDEO" $VF scale=$VF_SCALE \
    -an $bg_post_seek -f image2 -vframes 1 -y "$WORK_DIR/pics/template.$IMG_FMT")
    #echo -e "\nRunning: "${FFMPEG_CMD[@]}"\n" | fold -bs >> "$LOG_FILE"
    print2log "Running ${FFMPEG_CMD[@]}"
    SED_VAR="frame="
    "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
    if ((${PIPESTATUS[0]} != 0)); then
        runtime_error "Problem creating images from the video."
    fi
    echo | tee -a "$LOG_FILE"
fi
if $SHOWCASE && { $SC_THUMB || $QUICK_MENU ; }; then
    #if [[ $SC_TITLE_ALIGN = "east" ]] && ! $TEXTMENU; then
    #    TS=${THUMB_SIZE/x*}
    #else
    #    TS=0
    #fi
    if ((V_TOTAL > SPLIT)); then
            SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
    fi
    if $TEXTMENU && [[ -n $tt_ygeos_col2 ]]; then
        SHOWCASE_SIZE=$SM_SHOWCASE_SIZE
    fi
    # make mask for showcase shape, now that the showcase size is set
    if [[ -n $SHOWCASE_SHAPE ]]; then
        MASK="$WORK_DIR/${SHOWCASE_SHAPE}_mask.png"
        make_mask $SHOWCASE_SHAPE showcase
        convert "$MASK" -resize ${SHOWCASE_SIZE}! "$MASK"
        SHOWCASE_MASK="$MASK"
    fi

    if $SHOWCASE_3D && [[ -n $SHOWCASE_SHAPE ]]; then
        CURVE_VARS="5 3 5 1 1"
        unset SC_RAISE # 3D shaped thumbs have no -raise - use command below
        . todisc-fade-routine
        sc_3d_cmd=(convert - -write mpr:1img -fx A  +matte \
        -blur 0x$( LC_ALL="C" bash -c "printf  "%.2f" \
        $(bc_math "6.9 + .${CURVE_ARRAY[i]/.}")" ) -shade \
        $(bc_math "115 + ${CURVE_ARRAY[i]}" int)x30 \
        -normalize mpr:1img \
        -compose Overlay -composite mpr:1img -matte \
        -compose Dst_In -composite)
    else
        sc_3d_cmd=(convert - $SC_RAISE)
    fi
    if [[ -n "$SHOWCASE_VIDEO" ]]; then
        if $SWITCHED && $USER_THUMBS; then
            echo "Using supplied image for showcased thumb"
        else
            ! $QUICK_MENU && \
              yecho "Getting showcase video images from $SHOWCASE_VIDEO"
        fi
        if [[ "$SC_FRAMESTYLE" = "glass" ]]; then
            # some vars for get_framed_pics function
            D=2
            OUTDIR="$WORK_DIR/showcase"
            OUT="$WORK_DIR/showcase_img.png"
            VOUT="png:z=7"; FRAMES=30
            FRAME_SIZE=$SHOWCASE_SIZE
            MPLAYER_SEEK_VAL=$SHOWCASE_SEEK_VAL
            $SWITCHED && MPLAYER_SEEK_VAL=${SEEK_VAL[MENU_NUM-1]}
            yecho "Using mplayer to get framed images from the showcase video"
            get_framed_pics "$SHOWCASE_VIDEO" >> "$LOG_FILE" 2>&1
            largest_img=$(get_largest 8 30 )
            mv "$largest_img" "$OUT"
            rm -f "$WORK_DIR"/00000*.png
            convert "$WORK_DIR/showcase_img.png" \
            -background none $ROTATE $WAVE miff:-|
            convert - -resize $SHOWCASE_SIZE! "$WORK_DIR/showcase_img.png"
        elif [ "$SC_FRAMESTYLE" = "none" ]; then
            if $SWITCHED; then
                FFMPEG_SEEK_VAL=${SEEK_VAL[MENU_NUM-1]}
            else
                FFMPEG_SEEK_VAL=$SHOWCASE_SEEK_VAL
            fi
            if $FAST_SEEK; then
                ffm_pre_seek="-ss $FFMPEG_SEEK_VAL" && unset ffm_post_seek
            else
                ffm_post_seek="-ss $FFMPEG_SEEK_VAL" && unset ffm_pre_seek
            fi
            # if -user-thumbs passed we use the supplied thumb for the menu
            if $SWITCHED && $USER_THUMBS; then
                convert ${USER_PICS[MENU_NUM-1]} -resize $SHOWCASE_SIZE \
                "$WORK_DIR/showcase_img.png"
            else
                FFMPEG_CMD=($FFmpeg $ffm_pre_seek -i "$SHOWCASE_VIDEO" \
                $VF scale=${SHOWCASE_SIZE%x*}:${SHOWCASE_SIZE#*x} -an \
                $ffm_post_seek -f image2 -y -vframes 1 "$WORK_DIR/showcase_img.png")
                print2log "Running: ${FFMPEG_CMD[@]}"
                SED_VAR="frame="
                "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
                if ((${PIPESTATUS[0]} != 0)); then
                    runtime_error "Problem creating images from the video."
                fi
            fi
            # SHOWCASE_FRAME includes size and colour, it is empty if size is 0
            if [[ -n $SHOWCASE_SHAPE ]]; then
                composite -compose CopyOpacity $SHOWCASE_MASK +matte \
                "$WORK_DIR/showcase_img.png" miff:- |
                "${sc_3d_cmd[@]}" miff:- |
                convert - -background none $ROTATE $WAVE \
                -resize $SHOWCASE_SIZE! "$WORK_DIR/showcase_img.png"
            else
                convert "$WORK_DIR/showcase_img.png" $SHOWCASE_FRAME $SC_RAISE miff:- |
                convert -background none $ROTATE $WAVE - miff:-|
                convert -size $SHOWCASE_SIZE - -resize $SHOWCASE_SIZE! \
                 "$WORK_DIR/showcase_img.png"
            fi
        fi
    elif [[ -n "$SHOWCASE_IMG" ]]; then

        if [[ -n $SHOWCASE_SHAPE ]]; then # apply mask and no -raise
            SHAPE_CMD=(composite -compose CopyOpacity $SHOWCASE_MASK +matte \
            "$SHOWCASE_IMG")
        else
            SHAPE_CMD=(convert -size  $SHOWCASE_SIZE "$SHOWCASE_IMG" \
            -resize $SHOWCASE_SIZE! $SHOWCASE_FRAME $SC_RAISE)
            print2log "Running ${SHAPE_CMD[@]}"
        fi
        "${SHAPE_CMD[@]}" miff:- |
        "${sc_3d_cmd[@]}" miff:- |
        convert - -background none -bordercolor Transparent -border 8x8 \
        $ROTATE $WAVE miff:- | convert -size $SHOWCASE_SIZE - -trim +repage \
        -resize $SHOWCASE_SIZE! "$WORK_DIR/showcase_img.png"
    fi
fi
# transcode outputs yuv4mpeg which is piped to ffmpeg to make images (faster)
EXPORT="-y yuv4mpeg,null"
if [ $IMG_FMT = "png" ]; then
    QUALITY="-quality 01"
fi

# create the preview images
if ! $TEXTMENU && ! $SINGLE_SLIDESHOW && $DO_MENU && ! $USER_THUMBS; then
    print2log "Getting images from your video(s) for the preview"
    for ((i=0; i<=NUM_FILES; i++)) ; do
        # fast seek disabled by default
        if $FAST_SEEK; then
            ffm_pre_seek="-ss ${SEEK_VAL[i]}" && unset ffm_post_seek
        else
            ffm_postseek="-ss ${SEEK_VAL[i]}" && unset ffm_pre_seek
        fi
        # don't make titles if all input files are images
        # pass -f image2 to ffmpeg if its an image (not always needed but ...)
        [[ ${file_is_image[i]} = "yes" ]] && fmt="-f image2" || fmt=""
        SV=${SEEK_VAL[i]}; CURFILE="${IN_FILES[i]##*/}"
        spin "[$((i + 1)) of ${#FILES[@]}] Seeking to $SV seconds in $CURFILE"

        FFMPEG_CMD=($FFmpeg $fmt $ffm_pre_seek -i "${IN_FILES[i]}" -an \
        $ffm_postseek -f image2 -vframes $V_FRAMES \
        $VF scale=${THUMB_SIZE%x*}:${THUMB_SIZE#*x} -y $WORK_DIR/pics/$i/%06d.$IMG_FMT)
        CMD=( "${FFMPEG_CMD[@]}" )
        SED_VAR="frame="
        ! [[ "$SC_FRAMESTYLE" = "glass" ]] \
        && print2log "Running: ${CMD[@]}"
        # some vars for get_framed_pics function
        VOUT="png:z=7"; FRAMES=30
        FRAME_SIZE=$THUMB_SIZE
        D=2

        if [ "$SC_FRAMESTYLE" = "glass" ]; then
            MPLAYER_SEEK_VAL=${SEEK_VAL[i]}
            get_framed_pics "${IN_FILES[i]}"  >> "$LOG_FILE" 2>&1
            largest_img=$(get_largest 8 30)
            mv -f $largest_img "$WORK_DIR/pics/$i/$(printf "%06d%s" 0 .$IMG_FMT)"
            rm -f "$WORK_DIR"/000*[0-9].png
        elif [ "$SC_FRAMESTYLE" = "none" ]; then
            "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/} 2>&1
            if ((${PIPESTATUS[0]} != 0)); then
                runtime_error "Problem creating images from the video."
            fi
            
            # get largest image of 9 if static menu and -frame-safe
            if $FRAME_SAFE; then
                largest_img=$(get_largest 6 $V_FRAMES "$WORK_DIR/pics/$i")
                mv -f "$largest_img" "$WORK_DIR/pics/largest.$IMG_FMT"
                rm -f "$WORK_DIR"/pics/$i/*.$IMG_FMT
                mv  "$WORK_DIR/pics/largest.$IMG_FMT" \
                  "$WORK_DIR/pics/$i/000001.$IMG_FMT"
            fi
        fi

        wait
        unset NAVSEEK_CMD rectangle FFMPEG_CMD TRANSCODE_CMD
    done
    echo
fi
# for user supplied thumbs, resize and copy to appropriate directories
if ! $SWITCHED && $USER_THUMBS; then
    for i in ${!USER_PICS[@]}; do
        convert "${USER_PICS[i]}" -resize $THUMB_SIZE \
        "$WORK_DIR/pics/$i/000001.$IMG_FMT"
    done
fi
# overlay menu title and video titles on template
if $MIST; then
    # overlay white.png onto background
    print2log "Overlaying the text mist on the background"
    composite -dissolve $MIST_OPACITY -gravity $TITLE_GRAVITY \
    -geometry ${mist_xoffset}${mist_yoffset} \
    "$WORK_DIR/white.png" "$WORK_DIR/pics/template.png" \
    "$WORK_DIR/pics/template.png"
fi
if $SHOWCASE && $DO_MENU; then
    for ((i=0; i<=NUM_FILES; i++)); do
        sc_thumb_title_cmd=( "${sc_thumb_title_cmd[@]}" \
        "${THUMBTITLES_ARRAY[i]}" "$WORK_DIR/thumb_title${i}.png")
    done
    print2log "Running \
    convert  -size $VIDSIZE -background none $WORK_DIR/pics/template.png \
    ${sc_thumb_title_cmd[@]} -page +210+400 $WORK_DIR/title_txt.png \
    -mosaic $WORK_DIR/pics/template.png"
    convert -size $VIDSIZE -background none "$WORK_DIR/pics/template.png" \
    ${sc_thumb_title_cmd[@]} -mosaic "$WORK_DIR/pics/template.png"
    convert "$WORK_DIR/pics/template.png" "$WORK_DIR/title_txt.png" \
    -gravity $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
    -composite -background none "$WORK_DIR/pics/template.png"
fi
if $PLAYALL || { $TITLESET_MODE && $VMGM_MENU; } || $SINGLE_SLIDESHOW ; then
    convert "$WORK_DIR/pics/template.png" -background none \
    "${ADD_PLAYALL_BTN[@]}" "${ADD_RTN_BTN[@]}" \
    "$WORK_DIR/pics/template.png"
    convert "$WORK_DIR/pics/template.png" "$WORK_DIR/pics/template1.png"
fi

# copy the preview for -quick-menu
if $QUICK_MENU && [[ -s "$WORK_DIR/showcase_img.png" ]]; then
    cp "$WORK_DIR/pics/template.png" "$WORK_DIR/quick_menu_bg.png"
fi

# lets be sure of order by using a loop
for ((i=0; i<=NUM_FILES; i++)); do
    PICS=( "${PICS[@]}" \
    $(find $WORK_DIR/pics/$i/  -maxdepth 1 -name 000\*.$IMG_FMT) )
done
if ! $TEXTMENU && ! $SINGLE_SLIDESHOW && $DO_MENU; then
    # feathered and 3d thumbs get their effect here
    for ((i=0; i<${#PICS[@]}; i++)); do
        [[ -n ${ROTATE_ARRAY[@]} ]] && \
        THUMB_ROTATE="-background none -rotate ${ROTATE_ARRAY[i]}"
        if $THUMBS_3D && [ "$THUMB_SHAPE" != "normal" ]; then
        CURVE_VARS="5 3 5 1 1"
        . todisc-fade-routine
        fi
        PVIEW_CMD=(composite -compose CopyOpacity $THUMB_MASK +matte \
        "${PICS[i]}")
        PVIEW_CMD0=(convert "${PICS[i]}" $RAISE)
        PVIEW_CMD2=(convert - -write mpr:${i}img -fx A  +matte \
        -blur 0x$( LC_ALL="C" bash -c "printf  "%.2f" \
       $(bc_math "6.9 + .${CURVE_ARRAY[i]/.}")" ) -shade \
       $(bc_math "115 + ${CURVE_ARRAY[i]}" int)x30 -normalize mpr:${i}img \
       -compose Overlay -composite mpr:${i}img -matte \
       -compose Dst_In -composite)
        PVIEW_CMD3=(convert -trim +repage - "${PICS[i]}")
        if $FEATHER; then
            if $THUMBS_3D; then
                if $SHOWCASE; then
                    if [ "$THUMB_SHAPE" != "normal" ]; then
                        "${PVIEW_CMD[@]}" miff:- |
                        "${PVIEW_CMD2[@]}" miff:- |
                        "${PVIEW_CMD3[@]}"
                    else # normal thumb shape
                        "${PVIEW_CMD0[@]}" miff:- | "${PVIEW_CMD3[@]}"
                    fi
                else  # not $SHOWCASE
                    if [ "$THUMB_SHAPE" != "normal" ]; then
                        "${PVIEW_CMD[@]}" miff:- |
                        "${PVIEW_CMD2[@]}" "${PICS[i]}"
                    else # normal thumb shape
                        "${PVIEW_CMD0[@]}" miff:- | "${PVIEW_CMD3[@]}"
                    fi
                fi
            else # not 3D
                "${PVIEW_CMD[@]}" miff:- | "${PVIEW_CMD3[@]}"
            fi
        else # not FEATHER
            if $THUMBS_3D; then
                "${PVIEW_CMD0[@]}" miff:- | "${PVIEW_CMD3[@]}"
            fi
        fi
        IM_CMD=(convert -background none -bordercolor $THUMB_FRAME_CLR $THUMB_FRAME \
        $RAISE "${PICS[i]}")
        IM_CMD0=(composite -gravity center -compose DstOver \
        "$WORK_DIR/feather_mask2.png" "${PICS[i]}")
        ! $USE_FEATHER_MASK && IM_CMD0=(convert "${PICS[i]}")
        IM_CMD1=(montage "${PICS[i]}" -geometry +4+4 -compose Copy  \
        -background none)
        IM_CMD2=(convert - -resize $THUMB_SIZE!)
        IM_CMD3=(composite -gravity center -compose DstOver \
        "$WORK_DIR/feather_mask2.png" - )
        ! $USE_FEATHER_MASK && IM_CMD3=(convert -)
        IM_CMD3b=(convert - "$WORK_DIR/thumb_title${i}.png" -gravity south \
        -geometry +0+5 -compose over -composite)
        IM_CMD4=(convert "${PICS[i]}" -background none -bordercolor $THUMB_FRAME_CLR \
        $THUMB_FRAME "$WORK_DIR/thumb_title${i}.png" -gravity south \
        -geometry +0+5 -compose over -composite )
        IM_CMD5=(convert - -bordercolor none $THUMB_FRAME $THUMB_ROTATE -resize ${THUMB_SIZE}! \
        "${PICS[i]}" )
        IM_CMD6=(convert - -bordercolor $THUMB_FRAME_CLR $THUMB_FRAME \
        $THUMB_ROTATE -resize ${THUMB_SIZE}! "${PICS[i]}")
        IM_CMD7=(convert - $THUMB_ROTATE -resize ${THUMB_SIZE}! "${PICS[i]}")

        if $FEATHER; then
            if $SHOWCASE; then
                "${IM_CMD0[@]}" miff:- | "${IM_CMD5[@]}"
            else  # feather, but not showcase
                "${IM_CMD1[@]}" miff:- | "${IM_CMD2[@]}" miff:- |
                "${IM_CMD3[@]}" miff:- | "${IM_CMD3b[@]}" miff:- |
                "${IM_CMD5[@]}"
            fi
        else  # not feather
            if $SHOWCASE; then
                "${IM_CMD[@]}" miff:- | "${IM_CMD6[@]}"
            else # not feather and not showcase
                "${IM_CMD4[@]}" miff:- |  "${IM_CMD7[@]}"
            fi
        fi
    done
fi
##############################################################################
#                 create button layer for spumux                             #
##############################################################################

if $DO_BUTTONS; then
    print2log "Creating the highlight and selection PNGs for the main menu"
    if [ "$BUTTON_STYLE" = "rect" ]; then
        MENU_BUTTON_SIZE=$THUMB_SIZE
        get_button_geo
    (
    cat  <<EOF
rectangle 2,2 $GEO
EOF
)  > "$WORK_DIR/draw_file"
    fi
    if [[ $BUTTON_STYLE = "text-rect" ]]; then
        for ((i=0; i<=NUM_FILES; i++)); do
            MENU_BUTTON_SIZE=${TT_DIM[i]}
            get_button_geo
    (
    cat <<EOF
rectangle 1,1 $GEO
EOF
    )  > "$WORK_DIR/draw_file${i}"
        done
    fi
    if [[ $BUTTON_STYLE = "line" ]]; then
        for ((i=0; i<=NUM_FILES; i++)); do
            twidth=$(convert "$WORK_DIR/thumb_title${i}.png" \
            -trim +repage -format %w info:-)
            tx1=$(( ${TT_DIM[i]/x*} - twidth))
            tx1=$((tx1 / 2))
            tx2=$(( ${TT_DIM[i]/x*} - tx1 ))
            ty=$(( ${TT_DIM[i]/*x} - 5 ))
    (
    cat <<EOF
line ${tx1},${ty} ${tx2},${ty}
EOF
    ) > "$WORK_DIR/draw_file${i}"
        done
    fi

    PNG_IS_DONE=false
    for ((t=0; t<${#TITLES[@]}; t++)); do
        unset BUTTON_CMD6b BUTTON_CMD7b
        if $FEATHER; then FRAME=0; else FRAME=3x3;fi
        [[ -n ${ROTATE_ARRAY[@]} ]] && \
         THUMB_ROTATE="-background none -rotate ${ROTATE_ARRAY[t]}"
        BUTTON_SIZE=$THUMB_SIZE
        BUTTON_CMD=(convert -size $THUMB_SIZE xc:none)
        BUTTON_CMD1=(convert +antialias -size $THUMB_SIZE xc:none \
        -mattecolor none -background none -bordercolor none \
        "$WORK_DIR/thumb_title${t}-${SELECT_CLR/\#}.png" \
        -gravity South -geometry +0+5 -compose over -composite)
        BUTTON_CMD2=(convert +antialias -size $THUMB_SIZE xc:none \
        -mattecolor none -background none -bordercolor none \
        "$WORK_DIR/thumb_title${t}-${HLIGHT_CLR/\#}.png" \
        -gravity South -geometry +0+5 -compose over -composite)
        BUTTON_CMD3=(convert - +antialias -background none \
        $THUMB_ROTATE -resize ${THUMB_SIZE}! )
        BUTTON_CMD4=(convert -size "${THUMB_SIZE}+5+5"  xc:none -fill none \
        +antialias -stroke "$SELECT_CLR" -strokewidth 4 -draw @draw_file \
        $THUMB_ROTATE -resize ${THUMB_SIZE}! \
        "$WORK_DIR/Select${t}.png")
        BUTTON_CMD5=(convert -size "${THUMB_SIZE}+5+5" xc:none -fill none \
        +antialias -stroke "$HLIGHT_CLR" -strokewidth 4 -draw @draw_file \
        $THUMB_ROTATE -resize ${THUMB_SIZE}! \
        "$WORK_DIR/Highlight${t}.png")
        BUTTON_CMD6=(convert -size ${THUMB_SIZE}+5+5 xc:none +antialias \
        -fill none -stroke "$SELECT_CLR" -strokewidth 4 -draw @draw_file \
        $THUMB_ROTATE -resize ${THUMB_SIZE}! \
        "$WORK_DIR/Select${t}.png")
        BUTTON_CMD6b=(convert +antialias \
        -size ${TT_DIM[t]} xc:none -fill none -stroke "$SELECT_CLR" \
        -strokewidth 2 -draw @draw_file${t} \
        "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)")
        BUTTON_CMD7=(convert +antialias -size ${THUMB_SIZE}+5+5 \
        xc:none -fill none -stroke "$HLIGHT_CLR" -strokewidth 4 \
        -draw @draw_file $THUMB_ROTATE -resize ${THUMB_SIZE}! \
        "$WORK_DIR/Highlight${t}.png")
        BUTTON_CMD7b=(convert +antialias \
        -size ${TT_DIM[t]} xc:none -fill none -stroke "$HLIGHT_CLR" \
        -strokewidth 2 -draw @draw_file${t} \
        "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)")

        if [[ $BUTTON_STYLE = "text" ]] && ! $SHOWCASE; then
            if $FEATHER; then
                "${BUTTON_CMD2[@]}" miff:- | "${BUTTON_CMD3[@]}" \
                "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)"
                "${BUTTON_CMD2[@]}" miff:- | "${BUTTON_CMD3[@]}" \
                "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)"
            else
                "${BUTTON_CMD2[@]}" miff:- |
                "${BUTTON_CMD3[@]}" \
                "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)"
                "${BUTTON_CMD2[@]}" miff:- | "${BUTTON_CMD3[@]}" \
                "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)"
            fi
            mogrify -channel A -threshold 50% \
            "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)"
            mogrify -channel A -threshold 50% \
            "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)"

        elif [[ $BUTTON_STYLE = "rect" ]]; then
            if  ! $PNG_IS_DONE; then
                if $SHOWCASE; then
                    "${BUTTON_CMD6[@]}"
                    "${BUTTON_CMD7[@]}"
                else
                    "${BUTTON_CMD4[@]}" #2> /dev/null
                    "${BUTTON_CMD5[@]}" #2> /dev/null
                fi
            fi
        elif [[ $BUTTON_STYLE = "text-rect" ]] \
            || { [[ $BUTTON_STYLE = "line" ]] && ! $SHOWCASE ; }; then
            # "line" style for non showcase can use same code as text-rect
            # showcase "line" style button montage is created later in one shot
            "${BUTTON_CMD6b[@]}"
            "${BUTTON_CMD7b[@]}"
            if ! $SHOWCASE; then
                # 'line' button style goes at the very bottom of the thumb
                [[ $BUTTON_STYLE = "line" ]] && butgeo=+0+0 || butgeo=+0+5

                convert -size $BUTTON_SIZE xc:none "$WORK_DIR/blank.png"
                convert +antialias $WORK_DIR/blank.png \
                "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)" -gravity \
                South -geometry $butgeo -composite $THUMB_ROTATE -resize \
                ${BUTTON_SIZE}! "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)"
                mogrify -channel A -threshold 50% \
                "$WORK_DIR/$(printf %06d%s%s ${t} -select .png)"
                convert +antialias $WORK_DIR/blank.png  \
                "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)" \
                -gravity south -geometry $butgeo -composite $THUMB_ROTATE \
                -resize ${BUTTON_SIZE}! \
                "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)"
                mogrify -channel A -threshold 50% \
                "$WORK_DIR/$(printf %06d%s%s ${t} -highlight .png)"
            fi
        fi
        # do not loop over creating same png
#        [[ -z ${ROTATE_ARRAY[@]} ]] && PNG_IS_DONE=:
    done
    if [ "$BUTTON_STYLE" = "rect" ]; then
        BUTTON_DIM=$(get_image_dim "$WORK_DIR/Highlight0.png")
        for button in Select Highlight; do
            if $SHOWCASE; then
                unset sc_spumux_cmd fake_montage_cmd
                convert -size $BUTTON_DIM xc:none -background none \
                $WORK_DIR/empty-button.png
                fake_montage=( $WORK_DIR/Highlight0.png \
                $(for ((i=0; i<NUM_FILES; i++)); do \
                echo $WORK_DIR/empty-button.png; done))
                for ((i=0; i<=NUM_FILES; i++)); do
                    fake_montage_cmd=( ${fake_montage_cmd[@]} \
                    ${SHOWCASE_THUMB_PAGES[i]} "${fake_montage[i]}")
                    sc_spumux_cmd=( ${sc_spumux_cmd[@]} \
                    ${SHOWCASE_THUMB_PAGES[i]} "$WORK_DIR/${button}${i}.png" )
                    # get button locations for spumux
                    btn_size=$(get_image_dim "$WORK_DIR/${button}${i}.png")
                    # a couple of commented references
                    #${SC_THUMB_X_ARRAY[i]}+${SC_THUMB_Y_ARRAY[i]}
                    #btn_geos[ind]="x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\""
                    X0=${SC_THUMB_X_ARRAY[i]}; X1=$((X0 + ${btn_size/x*}))
                    Y0=${SC_THUMB_Y_ARRAY[i]}; Y1=$((Y0 + ${btn_size/*x}))
                    # spumux needs the coordinates to be divisible by 2
                    ((X0%2 && X0--)); ((Y0%2 && Y0--))
                    ((X1%2 && X1++)); ((Y1%2 && Y1++))
                    button_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
                    btn_geos[i]=${button_geos[@]}
                    unset button_geos
                done
                convert  -size $VIDSIZE xc:none -background none \
                ${fake_montage_cmd[@]} -mosaic "$WORK_DIR/fake_montage.png"
                convert +antialias -size $VIDSIZE xc:none \
                -background none ${sc_spumux_cmd[@]} -mosaic \
                "$WORK_DIR/${button}.png"
            else
                montage -background none \
                $(for ((i=0; i<=NUM_FILES; i++)); do
                echo $WORK_DIR/${button}${i}.png;done) -tile \
                ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
                -bordercolor none -mattecolor transparent miff:- |
                convert +antialias  -size $VIDSIZE xc:none - -gravity \
                $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} -composite \
                "$WORK_DIR/${button}.png"
                convert -size $BUTTON_DIM xc:none -background none \
                $WORK_DIR/empty-button.png
                fake_montage=( $WORK_DIR/Highlight0.png \
                $(for ((i=0; i<NUM_FILES; i++)); do \
                echo $WORK_DIR/empty-button.png; done))
                montage -background none ${fake_montage[@]} \
                -tile ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
                -bordercolor none -mattecolor transparent miff:- | convert \
                -size $VIDSIZE xc:none - -gravity $BUTTON_GRAVITY -geometry \
                +${XGEO}+${YGEO} -composite "$WORK_DIR/fake_montage.png"
            fi
        done
    elif [[ "$BUTTON_STYLE" = *text* ]]; then
        if $SHOWCASE; then
            select_buttons=( ${select_buttons[@]} \
            $(find $WORK_DIR/ -name 00\*select.png |sort) )
            highlight_buttons=( ${highlight_buttons[@]} \
            $(find $WORK_DIR/ -name 00\*highlight.png |sort) )
            for ((i=0; i<=NUM_FILES; i++)); do
                sc_select_cmd=(${sc_select_cmd[@]} \
                ${THUMBTITLES_ARRAY[i]} "${select_buttons[i]}")
                sc_highlight_cmd=(${sc_highlight_cmd[@]} \
                ${THUMBTITLES_ARRAY[i]} "${highlight_buttons[i]}")
            done
            convert +antialias -quality 01 \
            -size $VIDSIZE xc:none -background none \
            ${sc_highlight_cmd[@]} -mosaic "$WORK_DIR/Highlight.png"
            convert +antialias -quality 01 \
            -size $VIDSIZE xc:none -background none \
            ${sc_select_cmd[@]} -mosaic "$WORK_DIR/Select.png"
        else
            select_buttons=( ${select_buttons[@]} \
            $(find $WORK_DIR/ -name 00\*select.png |sort) )
            highlight_buttons=( ${highlight_buttons[@]} \
            $(find $WORK_DIR/ -name 00\*highlight.png |sort) )
            montage -background none \
            ${select_buttons[@]} -tile ${TILE_ARRAY[NUM_FILES]} \
            -geometry ${THUMB_SIZE}${MTG_GEO} -bordercolor none \
            -mattecolor none miff:- |
            convert  +antialias -size $VIDSIZE xc:none \
            - -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} \
            -composite  "$WORK_DIR/Select.png"
            montage -background none \
            ${highlight_buttons[@]} -tile ${TILE_ARRAY[NUM_FILES]} -geometry \
            ${THUMB_SIZE}${MTG_GEO} -bordercolor none -mattecolor none miff:- |
            convert +antialias -size $VIDSIZE xc:none - \
            -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} -composite \
            "$WORK_DIR/Highlight.png"
            BUTTON_DIM=$(get_image_dim "$WORK_DIR/000000-highlight.png")
            convert -size $BUTTON_DIM xc:none -background none \
            $WORK_DIR/empty-button.png
            fake_montage=( $WORK_DIR/000000-highlight.png \
            $(for ((i=0; i<NUM_FILES; i++)); do \
            echo $WORK_DIR/empty-button.png; done))
        fi
        if $SHOWCASE; then
            if [[ $BUTTON_STYLE = *text* ]]; then
                convert +antialias -size $VIDSIZE xc:none \
                -background none ${THUMBTITLES_ARRAY[MENU_NUM-1]} \
                $WORK_DIR/$(printf "%06d%s" $((MENU_NUM-1)) -highlight.png) \
                -mosaic "$WORK_DIR/fake_montage.png"
            fi
        else
            montage -background none ${fake_montage[@]} \
            -tile ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
            -bordercolor none -mattecolor transparent miff:- |
            convert  -size $VIDSIZE xc:none - -gravity $BUTTON_GRAVITY \
            -geometry +${XGEO}+${YGEO} -composite "$WORK_DIR/fake_montage.png"
        fi
    elif $SHOWCASE && [[ "$BUTTON_STYLE" = "line" ]]; then
        for i in ${!TITLES[@]}; do
            XPT1=$( cut -f2 -d+ <<< ${THUMBTITLES_ARRAY[i]} )
            XPT2=$(( XPT1 + ${TT_DIM[i]%%x*} ))
            YPT=$( cut -f3 -d+ <<< ${THUMBTITLES_ARRAY[i]} )
            YPT=$(( YPT + ${TT_DIM[i]##*x} ))
            # Y0,X0,Y0,Y1 is for later, for spumux button geometries
            Y0=$YPT
            X0=$XPT1
            X1=$XPT2
            # for line button just add 2 to Y geo
            Y1=$((Y0+2))
            # make sure coordinates are even
            ((X0%2 && X0--)); ((Y0%2 && Y0--))
            ((X1%2 && X1++)); ((Y1%2 && Y1++))
            button_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
            btn_geos[i]=${button_geos[@]}
            unset button_geos
            echo \
            "line ${XPT1},${YPT} ${XPT2},${YPT}" >> "$WORK_DIR/spumux_drawfile"
            [[ $i -eq $((MENU_NUM-1)) ]] && echo \
            "line ${XPT1},${YPT} ${XPT2},${YPT}" >>"$WORK_DIR/fake_montage.mvg"
        done
        convert +antialias -size $VIDSIZE xc:none -fill none \
        -stroke $SELECT_CLR -strokewidth 2 -draw @spumux_drawfile \
        "$WORK_DIR/Select.png"
        convert +antialias -size $VIDSIZE xc:none -fill none \
        -stroke $HLIGHT_CLR \
        -strokewidth 2 -draw @spumux_drawfile "$WORK_DIR/Highlight.png"
        convert  -size $VIDSIZE xc:none -fill none -stroke $HLIGHT_CLR \
        -strokewidth 2 -draw @fake_montage.mvg "$WORK_DIR/fake_montage.png"
    elif  ! $SHOWCASE && [[ $BUTTON_STYLE = "line" ]]; then
        select_buttons=( ${select_buttons[@]} \
        $(find $WORK_DIR/ -name 00\*select.png |sort) )
        highlight_buttons=( ${highlight_buttons[@]} \
        $(find $WORK_DIR/ -name 00\*highlight.png |sort) )

        montage -background none ${select_buttons[@]} \
        -tile ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
        -bordercolor none -mattecolor none miff:- |
        convert +antialias -size $VIDSIZE xc:none - \
        -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} \
        -composite "$WORK_DIR/Select.png"

        montage -background none ${highlight_buttons[@]} \
        -tile ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
        -bordercolor none -mattecolor none miff:- |
        convert +antialias -size $VIDSIZE xc:none - \
        -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} \
        -composite "$WORK_DIR/Highlight.png"

        BUTTON_DIM=$(get_image_dim "$WORK_DIR/000000-highlight.png")
        convert -size $BUTTON_DIM xc:none -background none \
        $WORK_DIR/empty-button.png
        fake_montage=( $WORK_DIR/000000-highlight.png \
        $(for ((i=0; i<NUM_FILES; i++)); do \
        echo $WORK_DIR/empty-button.png; done))

        montage -background none ${fake_montage[@]} \
        -tile ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
        -bordercolor none -mattecolor transparent miff:- |
        convert  -size $VIDSIZE xc:none - -gravity $BUTTON_GRAVITY \
        -geometry +${XGEO}+${YGEO} -composite "$WORK_DIR/fake_montage.png"
    fi
    if $TITLESET_MODE && ! $VMGM_ONLY && $VMGM_MENU; then
        convert +antialias -gravity $RTN_BTN_GRAVITY \
        -geometry "$RTN_BTN_OFFSETS" "$WORK_DIR/Select.png" \
        "$WORK_DIR/Main_${SELECT_CLR/\#}.png" -composite "$WORK_DIR/Select.png"

        convert +antialias -gravity $RTN_BTN_GRAVITY \
        -geometry "$RTN_BTN_OFFSETS" "$WORK_DIR/Highlight.png" \
        "$WORK_DIR/Main_${HLIGHT_CLR/\#}.png" \
        -composite "$WORK_DIR/Highlight.png"
    fi
    if $PLAYALL; then
        convert +antialias -gravity SouthEast -geometry \
        "$PLAYALL_BTN_OFFSETS" "$WORK_DIR/Select.png" \
        "$WORK_DIR/Playall_${SELECT_CLR/\#}.png" \
        -composite "$WORK_DIR/Select.png"

        convert +antialias -gravity SouthEast -geometry \
        "$PLAYALL_BTN_OFFSETS" "$WORK_DIR/Highlight.png" \
        "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png" \
        -composite "$WORK_DIR/Highlight.png"
    fi

fi
# for dvd slideshow we need just a Select.png unless grouping or MONTAGE_MENU
if $SINGLE_SLIDESHOW; then
    if $TITLESET_MODE && ! $VMGM_ONLY && $VMGM_MENU; then
        convert +antialias -size $VIDSIZE xc:none -fill none  \
        "$WORK_DIR/Main_${SELECT_CLR/\#}.png" -gravity $RTN_BTN_GRAVITY \
        -geometry "$RTN_BTN_OFFSETS" -composite "$WORK_DIR/Select.png"
        convert +antialias -size $VIDSIZE xc:none -fill none \
        "$WORK_DIR/Main_${HLIGHT_CLR/\#}.png" -gravity $RTN_BTN_GRAVITY \
        -geometry "$RTN_BTN_OFFSETS" -composite "$WORK_DIR/Highlight.png"

        convert +antialias -gravity SouthEast -geometry \
        "$PLAYALL_BTN_OFFSETS"  "$WORK_DIR/Select.png" \
        "$WORK_DIR/Playall_${SELECT_CLR/\#}.png" \
        -composite "$WORK_DIR/Select.png"

        convert +antialias -gravity SouthEast -geometry \
        "$PLAYALL_BTN_OFFSETS" "$WORK_DIR/Highlight.png" \
        "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png" \
        -composite "$WORK_DIR/Highlight.png"
    else
        convert +antialias -size $VIDSIZE xc:none -fill none  \
        "$WORK_DIR/Playall_${SELECT_CLR/\#}.png" -gravity SouthEast \
        -geometry "$PLAYALL_BTN_OFFSETS" -composite "$WORK_DIR/Select.png"
        convert +antialias -size $VIDSIZE xc:none -fill none  \
        "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png" -gravity SouthEast \
        -geometry "$PLAYALL_BTN_OFFSETS" -composite "$WORK_DIR/Highlight.png"
    fi
    OUTLINEWIDTH="\"14\"" # needed for text button
fi
# this reduces colours so spumux is happy
for button in Select Highlight; do
    num_colours=$(identify -ping -format %k "$WORK_DIR/${button}.png")
    if ((num_colours > 3)); then
        echo "$button button had $num_colours colors, reducing ..." |
        tee -a "$LOG_FILE"
        mogrify -channel A -threshold 50% "$WORK_DIR/${button}.png"
    fi
    echo
done
# make a draw files for grid preview if -grid was passed
if ((GRID)); then
    # make draw files for grid
    for ((i=20; i<=${VIDSIZE/x*}; i=i+20)); do
        ((i<=${VIDSIZE/*x})) && echo "line 0,${i} ${VIDSIZE/x*},${i}"
        echo "line ${i},0 ${i},${VIDSIZE/*x}"
    done >> "$WORK_DIR/grid1.mvg"

    # make draw files for numbered text
    for ((i=100; i<=600; i=i+100)); do
        ((i<=${VIDSIZE/*x}-40)) && echo text 0,${i} \'$i\'
        echo text ${i},20 \'$i\'
    done >> "$WORK_DIR/grid2.mvg"
fi
if $SHOWCASE && $DO_MENU; then
    if $SC_THUMB; then
        # find out where to put the showcase image/video in the X axis
        sc_size=$(get_image_dim "$WORK_DIR/showcase_img.png")
        sc_width=${sc_size/x*}
        sc_height=${sc_size/*x}
    fi
    $QUICK_MENU && \
    sc_width=${SHOWCASE_SIZE/x*} && sc_height=${SHOWCASE_SIZE/*x}
    if $SC_THUMB || $QUICK_MENU; then
        if [[ "$SC_TITLE_ALIGN" = "center" ]]; then
            if [[ $widest_title -ge ${THUMB_SIZE/x*} ]]; then
                BUTTON_COLUMN1=$(((${THUMB_SIZE/x*} / 2) + (widest_title / 2)))
            else
                BUTTON_COLUMN1=${THUMB_SIZE/x*}
            fi
        elif [[ "$SC_TITLE_ALIGN" = "west" ]]; then
            if [[ $widest_title -ge ${THUMB_SIZE/x*} ]]; then
                BUTTON_COLUMN1=$((widest_title + 5))
            else
                BUTTON_COLUMN1=${THUMB_SIZE/x*}
            fi
        elif [[ "$SC_TITLE_ALIGN" = "east" ]]; then
            BUTTON_COLUMN1=$(( ${THUMB_SIZE/x*} + widest_title ))
        fi
        # work out the general position of the showcase image
        # these will be modified later according to -align options
        # TODO it's already consolidated, now split in 1 vs 2 column if/else
        if $TEXTMENU; then
            # this is the default, *west aligned, for one column textmenu
            BUTTON_COLUMN1=$((widest_title + 5))
            sc_space=$((${VIDSIZE%x*} - \
                ${SC_TITLES_X_ARRAY[0]} - BUTTON_COLUMN1 - SAFE_AREA))
            SC_X=$(( ${SC_TITLES_X_ARRAY[0]} + BUTTON_COLUMN1 \
            + (sc_space / 2) - (sc_width / 2) ))
            if [[ $BUTTON_GRAVITY = *east* ]]; then
                BUTTON_COLUMN1=$widest_title
                sc_space=$((${VIDSIZE%x*} - (SAFE_AREA * 2) - BUTTON_COLUMN1))
                SC_X=$((SAFE_AREA + (sc_space / 2) - (sc_width / 2) ))
            fi
            center_showcase_pos=$(( (${VIDSIZE/x*} / 2) - (sc_width / 2) ))
            # this next block is *east or *west for 2 columns, and N|S|Center
            case $BUTTON_GRAVITY in
              *east|*west)
                # for 2 columns the showcase thumb will always be centered
                [[ -n $tt_ygeos_col2 ]] && SC_X=$center_showcase_pos
                ;;
              north|south|center)
                # for centered 1 column the showcase has no room, so center it
                # these -align args have no effect on 2 column titles position
                SC_X=$center_showcase_pos
                ;;
            esac
        else
            sc_space=$((${VIDSIZE%x*} - \
            ${SC_THUMB_X_ARRAY[0]} - BUTTON_COLUMN1 - SAFE_AREA))
            SC_X=$(( ${SC_THUMB_X_ARRAY[0]} + BUTTON_COLUMN1 \
            + (sc_space / 2) - (sc_width / 2) ))
            if ((V_TOTAL > 5)); then
                # for 2 columns just center the thumb between edges of columns
                inner_edge_col1=$(( ${SC_THUMB_X_ARRAY[0]} + ${THUMB_SIZE/x*} ))
                inner_edge_col2=${SC_THUMB_X_ARRAY[SPLIT]}
                canvas=$(( (inner_edge_col2 - inner_edge_col1) / 2 ))
                canvas=$(( inner_edge_col1 + canvas ))
                SC_X=$(( canvas - (sc_width / 2) ))
            fi
        fi
        # work out the position of the showcase image in the Y axis
        if ! $TEXTMENU; then
            Y1=${SC_THUMB_Y_ARRAY[0]}
            Y2=${SC_THUMB_Y_ARRAY[NUM_FILES]}
            ((NUM_FILES >= LEFT_MAX)) && Y2=${SC_THUMB_Y_ARRAY[SPLIT-1]}
            Y_SPACE=$(( (Y2 - Y1) + ${THUMB_SIZE/*x} ))
            Y_SPACE=$(( Y_SPACE - sc_height ))
            SC_Y=$(( Y_SPACE / 2))
            SC_Y=$(( ${SC_THUMB_Y_ARRAY[0]} + SC_Y ))
        else # TEXTMENU
#            ((NUM_FILES < SPLIT)) && split=$NUM_FILES || split=$((SPLIT - 1))
            # if there is a menu title, move the showcase thumb up or down
            if [[ -n $MENU_TITLE ]] && ! $USER_SC_GEO && ! $USER_TITLE_GEO; then
                [[ $TITLE_GRAVITY = "south" ]] && \
                TITLE_SPACE="- $(( (title_yoffset + TITLE_TEXT_YDIM) / 2))"
                [[ $TITLE_GRAVITY = "north" ]] && \
                TITLE_SPACE="+ $(( (title_yoffset + TITLE_TEXT_YDIM) / 2))"
            fi
            Y_SPACE=${VIDSIZE#*x}
            SC_Y=$(( (Y_SPACE / 2) - (sc_height / 2) $TITLE_SPACE ))

        fi

        # make sure its divisible by 2 for ffmpeg's padding with -quick-menu
        if $QUICK_MENU; then
            SC_Y=$(( (SC_Y /2) * 2 ))
            SC_X=$(( (SC_X / 2) * 2 ))
        fi
        # finally if user passes in a prefered location for showcase, use it
        $USER_SC_GEO && SC_X=$(awk -F+ '{print $2}' <<< $SHOWCASE_GEO)
        $USER_SC_GEO && SC_Y=$(awk -F+ '{print $3}' <<< $SHOWCASE_GEO)

        # make the -page part of the IM command for the showcase image
        SC_IMG_PAGE="-page +$SC_X+$SC_Y"
        SC_IMG_CMD="$SC_IMG_PAGE "$WORK_DIR/showcase_img.png""
    fi
    if ! $SC_THUMB; then unset SC_IMG_CMD ; fi
    if [[ -n "$SHOWCASE_IMG" || -n "$SHOWCASE_VIDEO" ]]; then
        unset sc_cmd
        for ((i=0; i<=NUM_FILES; i++)); do
            sc_cmd=( ${sc_cmd[@]} ${SHOWCASE_THUMB_PAGES[i]} "${PICS[i]}")
        done
        $TEXTMENU && unset sc_cmd
        if $TRANSPARENT; then
            IM_CMD0=(convert  -size $VIDSIZE xc:none -background none \
            ${sc_cmd[@]} $SC_IMG_CMD -mosaic)
            IM_CMD1=(convert -size $VIDSIZE -background none \
            - ${sc_thumb_title_cmd[@]} -mosaic)
            IM_CMD2=(composite -size $VIDSIZE -background none \
            -gravity NorthWest  -dissolve $OPACITY - \
            "$WORK_DIR/pics/template.png" -background none)
            IM_CMD3=(convert - -background none $WORK_DIR/title_txt.png  \
            -gravity $TITLE_GRAVITY -geometry \
            ${title_xoffset}${title_yoffset} -composite "$PREVIEW_IMG" )
            print2log "Running ${IM_CMD0[@]} miff:- | ${IM_CMD1[@]} miff:- | \
            ${IM_CMD2[@]} miff:- | ${IM_CMD3[@]}"
            "${IM_CMD0[@]}" miff:- | "${IM_CMD1[@]}" miff:- |
            "${IM_CMD2[@]}" miff:- | "${IM_CMD3[@]}"
        else
            IM_CMD=(convert  -size $VIDSIZE "$WORK_DIR/pics/template.png" \
            -background none ${sc_cmd[@]} $SC_IMG_CMD \
            -mosaic "$PREVIEW_IMG")
            print2log "Running ${IM_CMD[@]}"
            "${IM_CMD[@]}"
        fi
        unset sc_cmd IM_CMD05 IM_CMD04 IM_CMD03 IM_CMD4
    fi
elif ! $SHOWCASE && ! $SINGLE_SLIDESHOW && $DO_MENU; then # not showcase
    if $TRANSPARENT; then
        IM_CMD1=(montage ${PICS[@]} $MTG_FRM -blur 0x.3 \
        -tile ${TILE_ARRAY[NUM_FILES]} -geometry ${THUMB_SIZE}${MTG_GEO} \
        -background none -bordercolor '#444744' miff:- )
        IM_CMD2=(composite -dissolve $OPACITY \
        -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} - \
        "$WORK_DIR/pics/template.png" -background none miff:- )
        IM_CMD3=(convert - -background none "$WORK_DIR/title_txt.png"  \
        -gravity $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
        -composite "$PREVIEW_IMG")
        print2log "Running ${IM_CMD1[@]} | ${IM_CMD2[@]} | ${IM_CMD3[@]}"
        "${IM_CMD1[@]}" | "${IM_CMD2[@]}" | "${IM_CMD3[@]}"
    else # Not transparent
        IM_CMD1=(montage ${PICS[@]} $MTG_FRM -tile ${TILE_ARRAY[NUM_FILES]} \
        -geometry ${THUMB_SIZE}${MTG_GEO}  -background none \
        -bordercolor "#444744" miff:- )
        IM_CMD2=(convert "$WORK_DIR/pics/template.png" \
        "$WORK_DIR/title_txt.png" -gravity $TITLE_GRAVITY \
        -geometry ${title_xoffset}${title_yoffset} -composite - -gravity \
        $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} -composite "$PREVIEW_IMG")
        print2log "Running ${IM_CMD1[@]} | ${IM_CMD2[@]}"
        "${IM_CMD1[@]}" | "${IM_CMD2[@]}"
    fi
fi
# make a preview for static slideshow menu #FIXME this should use $STATIC
if $SINGLE_SLIDESHOW && ! $DO_CAROUSEL && ! $MK_CAROUSEL_MODE; then
    IM_CMD1=(composite -dissolve $OPACITY -gravity $BUTTON_GRAVITY -geometry \
    +${XGEO}+${YGEO} "$WORK_DIR/polaroid_stack.png" \
    "$WORK_DIR/pics/template.png" -background none miff:- )
    IM_CMD2=(convert - -background none "$WORK_DIR/title_txt.png" \
    -gravity $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
    -composite "${add_playbtn[@]}" "$PREVIEW_IMG" )
    print2log "Running ${IM_CMD1[@]} | ${IM_CMD2[@]}"
    "${IM_CMD1[@]}" | "${IM_CMD2[@]}"
fi
# if there is quickmenu bg, cut out transparent hole for showcase image/video
if $QUICK_MENU; then
    if $QUICKMENU_IS_SHOWCASE && [[ -n "$BACKGROUND" ]]; then
        #[[ -n $SC_MATTECOLOR ]] && SC_MATTECOLOR="-mattecolor $SC_MATTECOLOR"
        # make a blank png for cutting out showcase area (cookie cutter)
        convert -size $SHOWCASE_SIZE xc:black "$WORK_DIR/showcase_blank.png"
        # make a similar framed blank to composite onto the background
        frame_cmd=(convert -size $SHOWCASE_SIZE xc:black \
        $SHOWCASE_FRAME "$WORK_DIR/showcase_frame.png")
        print2log "Running ${frame_cmd[@]}"
        "${frame_cmd[@]}" | pipe2log convert
        # composite the framed blank onto background subtracting the width \
        # of the frame (border) when calculating XxY geometry
        convert "$WORK_DIR/pics/template.png" \
        "$WORK_DIR/showcase_frame.png" -geometry \
        +$((SC_X-${SHOWCASE_FRAME_SIZE/x*}))+$((SC_Y-${SHOWCASE_FRAME_SIZE/x*})) \
        -composite "$WORK_DIR/pics/template.png"
        # add blank to a transparent image the size of the menu video
        convert -size  $VIDSIZE xc:none "$WORK_DIR/showcase_blank.png" \
       -geometry +$SC_X+$SC_Y -composite "$WORK_DIR/cookie_cutter.png"

        # cut out transparent hole in background with this 'cookie cutter'
        convert "$WORK_DIR/cookie_cutter.png" "$WORK_DIR/pics/template.png" \
        -compose Xor -composite -depth 8 -colorspace RGB -type TrueColorMatte \
        "$WORK_DIR/quick_menu_bg.png"
    else
        #cp "$WORK_DIR/pics/template.png" "$WORK_DIR/quick_menu_bg.png"
        convert "$WORK_DIR/pics/template.png" \
        -depth 8 -colorspace RGB -type TrueColorMatte \
        "$WORK_DIR/quick_menu_bg.png"
    fi
fi
$QUICK_MENU && quick_menu preview
if ! $NOASK && $MONTAGE_MENU && $DO_MENU \
 && ! $MK_CAROUSEL_MODE && ! { $VMGM_ONLY && ! $VMGM_MENU ; }; then
    DISPLAY_PREVIEW=:
else
    DISPLAY_PREVIEW=false
fi
if $DISPLAY_PREVIEW; then
    echo "Creating and displaying a preview of the main menu."
    echo "(Press 'q' or ESC in the preview window to close it.)"
fi
# make the fake montage with highlighted 1st button and display it
if $DO_MENU && ! $SINGLE_SLIDESHOW; then
    composite -compose Over "$WORK_DIR/fake_montage.png" \
      "$PREVIEW_IMG" "$PREVIEW_IMG"
fi
if $DISPLAY_PREVIEW; then
    display -title "Preview: (not in aspect) - close window to continue" \
    "$PREVIEW_IMG"
    if ((GRID)); then
        convert "$PREVIEW_IMG" \
         -stroke '#FFF5B270' -strokewidth 1 -draw @grid1.mvg miff:- | convert \
         - -fill none -stroke '#FFFFFF' -strokewidth 1 -draw @grid2.mvg x:
    fi
    confirm_preview
fi
# copy the template back if using $MENU_FADE
if $MENU_FADE; then
    rm "$WORK_DIR/pics/template.png"
    cp "$WORK_DIR/pics/template.bk.png" "$WORK_DIR/pics/template.png"
fi
! $USER_THUMBS && rm -f "${PICS[@]}"
unset PICS IM_CMD1 IM_CMD2 IM_CMD3 IM_CMD4 IM_CMD5


###############################################################################
#   get information about input videos, and some post preview preliminaries   #
###############################################################################

# if -bgvideo selected, but not -bgaudio, offer to use audio from bgvideo
# if "none" is passed for BG_AUDIO it means we are doing switched menus
# in which case we want to skip this step anyway
if ! $NOASK && ! $SWITCHED && [[ -n "$BG_VIDEO" ]]; then
    echo "Getting stats on the background video"
    BGVIDEO_STATS=$(idvid -terse -fast "$BG_VIDEO" 2>/dev/null)
    if [[ -z "$BG_AUDIO" ]]; then
        if grep -q "A_NOAUDIO=:" <<< "$BGVIDEO_STATS"; then
            :
        else
            echo "***** NOTE *****"
            echo "You selected -bgvideo but not -bgaudio"
            echo "To use the audio from "$BG_VIDEO" please type: yes"
            read bgaudio
            if [ ! -z "$bgaudio" -a "$bgaudio" = "yes" ]; then
                BG_AUDIO="$BG_VIDEO"
                echo "Using audio from "$BG_VIDEO""
            else
                echo "No audio selected, will use silence for main menu"
            fi
        fi
    fi
fi

# find out the length of the -bgaudio FILE, if there is one
if [[ -n "$BG_AUDIO" ]]; then
    yecho "Getting length of bg audio"
    $SINGLE_SLIDESHOW && end_pos="" || end_pos=${MENU_LEN[MENU_NUM-1]}
    BG_AUDIOLENGTH=$(stream_length "$BG_AUDIO" audio)

    # make sure user isn't trying to get a longer menu than the audio allows
    if [[ $( ${bC} <<< "${MENU_LEN[MENU_NUM-1]} \
    > $BG_AUDIOLENGTH" 2>/dev/null)  -eq 1 ]]; then
        MENU_AUDIOLEN=$BG_AUDIOLENGTH
    fi
fi
# if static menu and no background audio, ignore MENU_AUDIOLEN
$STATIC && [[ -z "$BG_AUDIO" ]] && ! $SWITCHED && unset MENU_AUDIOLEN
# for slideshow: set length of slides; check menu length is long enough

if $DO_CAROUSEL; then
    # if user passed -bgaudio but did not -(sub)menu-length, use full audio
    if  [[ -n $BG_AUDIO ]] && ! $USER_MENU_LEN; then
        MIX_SLIDE_LEN=$(bc_math "$BG_AUDIOLENGTH / ${#MIX_IN[@]}")
    else # only use MENU_LEN seconds of audio ( default 20 secs unless passed )
         MIX_SLIDE_LEN=$(bc_math "${MENU_LEN[MENU_NUM-1]} / ${#MIX_IN[@]}")
    fi
    # subtract transition time from the slide length
    TT=1 # a constant value atm
    $SLIDE_FADE && MIX_SLIDE_LEN=$(bc_math "$MIX_SLIDE_LEN - $TT")

    if [[ $( ${bC} -l <<< "$MIX_SLIDE_LEN == 0") -eq 1 ]]; then
        # use 2 frames for each still so MIX_SLIDE_LEN is not 0
        MIX_SLIDE_LEN=$( ${bC} -l <<< "scale=3; 2 / $FRAME_RATE")
    elif [[ $( ${bC} -l <<<  "$MIX_SLIDE_LEN < 0") -eq 1 ]]; then
        runtime_error "The menu length is not long enough for an animated menu.
        For slideshows where -bgaudio FILE is supplied, this is determined by:
        1. -menu-length argument if supplied
        2. length of the supplied -bgaudio
        you gave ${#MIX_IN[@]} files

        If -menu-length is not supplied, the length of the menu is the length
        the -bgaudio FILE, or 20 secs if silent background (no -bguaudio FILE)
        (Note: the fade effect duration is 1 second for each slide in the menu"
    fi
    MIX_ALEN=$MIX_SLIDE_LEN
    MIX_VFRAMES=$(bc_math "$MIX_SLIDE_LEN * $FRAME_RATE" int)
fi
# Check input files for compliance; offer to tovid-encode non-compliant files
# run this twice for switched menus for 1st menu made and last
# to make sure files get symlinked properly (Hack)
if [[ $MENU_NUM = [1-2] || -n ${file_is_image[@]}  ]]; then
    if ! $MK_CAROUSEL_MODE; then
        check_compliance
        $GROUPING && check_compliance group
    fi
fi

# this is for getting slide files to BASEDIR
unset MPEGS2MOVE
for i in $WORK_DIR/*slide_grp*.mpg; do
    [[ -e $i ]] && \
    MPEGS2MOVE=( "${MPEGS2MOVE[@]}" "${i/slide_grp/group}")
done
for i in "${!FILES[@]}"; do
    # do not overwrite slideshows if making them
    if $SINGLE_SLIDESHOW \
     || { ${SLIDESHOW[i]} &&  [[ ${CAROUSEL[i]} != "carousel" ]] ; }; then
        MPEGS2MOVE=( "${MPEGS2MOVE[@]}" "$WORK_DIR/${TSET_NUM}-$((i+1)).mpg")
    fi
done
if { $GROUPING || $SINGLE_SLIDESHOW ; } && $TITLESET_MODE; then
    if ! $MK_CAROUSEL_MODE; then
        for i in ${!MPEGS2MOVE[@]}; do
            rm -f "$BASEDIR/${MPEGS2MOVE[i]##*/}"
            cp "${MPEGS2MOVE[i]}" "$BASEDIR"/
        done
    fi
fi

# animated slideshows join the slides and can add audio (-bgaudio)
if $DO_CAROUSEL && ! $USE_DVD_SLIDESHOW; then
    for i in ${!MIX_IN[@]}; do
        this_item=${MIX_IN[i]##*/}
        for f in ${!FILES2BIN[@]}; do
            list_item=${FILES2BIN[f]##*/}
            if [[ $this_item = $list_item ]]; then
                F2BIN[i]="yes"
            fi
        done
    done
    IMGENC_CMD=($FFmpeg -f yuv4mpegpipe -i - $VF scale=${VF_SCALE},${ASPECT} \
    $SS_FFMOPTS -r $ff_frame_rate -bf 2 -y "$WORK_DIR/slideshow.m2v")
    for p in ${!MIX_IN[@]}; do
        if [[ "${F2BIN[p]}" = "yes" ]]; then
            BINNING_CMD=(convert "${MIX_IN[p]}" -depth 8 \
            -resize $CAROUSEL_SIZE "$WORK_DIR/${p}.ppm")
            # BINNING_CMD modified after get_binning_cmd() if imaage>1440 etc
            get_binning_cmd $p "${MIX_IN[p]}"
            spin "Binning slide $((p+1))"
            "${BINNING_CMD[@]}"  >> "$LOG_FILE" 2>&1
            MIX_IN[p]="$WORK_DIR/${p}.ppm"
        fi
        # resize to $CAROUSEL_SIZE

        # do not blur the file twice if already binned and blurred
        [[ ${F2BIN[p]} = "yes" ]] && unset SLIDEBLUR[p]
        if [[ $SBORDER_ARG || $SLIDE_FRAME ]]; then
            tmbnail_size=$(( 640 - SFRAME_ARG - (SBORDER_ARG * 2) ))
            if $USERS_BACKGROUND && [[ -n $BACKGROUND ]]; then
                SLD_BG="$WORK_DIR/slide_bg.ppm"
                convert "$BACKGROUND" -gravity center -crop 640x480+0+0 \
                 +repage -resize 640x480\! "$SLD_BG"
            else
                SLD_BG="xc:#101010"
            fi
            spin "Bordering and framing slide $((p+1))"
            border_and_frame "${MIX_IN[p]}" "$WORK_DIR/${p}.ppm"
            MIX_IN[p]="$WORK_DIR/${p}.ppm"
        fi
        cursize=$(identify -ping -format %wx%h "${MIX_IN[p]}")
        if (( ${cursize/x*} !=  ${CAROUSEL_SIZE/x*} )) \
        || (( ${cursize/*x} !=  ${CAROUSEL_SIZE/*x} )); then
            spin "Resizing slide $((p+1))"
            convert "${MIX_IN[p]}" -depth 8 \
            -resize ${CAROUSEL_SIZE}!  ${SLIDE_BLUR[p]} "$WORK_DIR/${p}.ppm"
            MIX_IN[p]="$WORK_DIR/${p}.ppm"
        fi
    done
    printf "\n\n" | tee -a "$LOG_FILE"
    sstime1=$(date +%s)
    # make a fifo to send raw yuv to, to be encoded by ffmpeg
    mkfifo "$WORK_DIR/ppm.fifo"
    print2log "Running ${IMGENC_CMD[@]}"
    "${IMGENC_CMD[@]}" < "$WORK_DIR/ppm.fifo" 2>&1 | \
      pipe2log ${FFmpeg##*/} &
    #"${IMGENC_CMD[@]}" 2>/dev/null < "$WORK_DIR/ppm.fifo" &
    encpids="$encpids $!"
    #exec 3> "$WORK_DIR/ppm.fifo"

    if [[ $EFFECT = "fade" ]]; then
        [[ $TV_STANDARD = "ntsc" ]] && fade_frames=15 || fade_frames=12
        fade_incr=$( ${bC} -l <<< "scale=2; 100 / $fade_frames") >&2
        convert -size ${CAROUSEL_SIZE}! xc:'#101010' -depth 8 \
        "$WORK_DIR/black.ppm"
    elif [[ $EFFECT = "crossfade" ]]; then
        [[ $TV_STANDARD = "ntsc" ]] && fade_frames=30 || fade_frames=25
        fade_incr=$( ${bC} -l <<< "scale=2; 100 / $fade_frames") >&2
    fi

    TOYUV_FADE_CMD=(ppmtoy4m -v 0 -n $fade_frames -A $PIXEL_AR -F $YUV_FR -I p \
    -S 420mpeg2 -r)
    TOYUV_STILLS_CMD=(ppmtoy4m -n $MIX_VFRAMES -A $PIXEL_AR -F $YUV_FR -I p \
    -S 420mpeg2 -r )
    # transitions
    echo >&2

    for f in ${!MIX_IN[@]}; do
        base_ppm="$WORK_DIR/${f}.ppm"
        if [[ $EFFECT = "crossfade" ]]; then
            if ((f == (${#MIX_IN[@]} - 1) )); then
                overlay_ppm="$WORK_DIR/0.ppm"
            else
                overlay_ppm="$WORK_DIR/$((f+1)).ppm"
            fi
        fi
        # encode fadein frames - keep yuv header
        if [[ $EFFECT = "fade" ]]; then
            spin "Doing fadein for slide $((f+1))" >&2
            # yuvcorrect (remove headers) if we are not on 1st slide fadein
            ((f==0)) && YUVCORRECT="cat"
            do_transitions fadein
            # encode transition frames
            cat "$WORK_DIR"/animenu/*.ppm 2>/dev/null |
            "${TOYUV_FADE_CMD[@]}" 2>/dev/null | $YUVCORRECT 2>/dev/null
            rm -f "$WORK_DIR"/animenu/*.ppm
        fi
        # encode still frames
        # need yuvcorrect if for fade style (remove headers)
        [[ $EFFECT = "fade" ]] && YUVCORRECT="$yuv_correct"
        if [[ $EFFECT = "crossfade" ]]; then
            # encoding 1st slide
            if ((f==0)); then
                YUVCORRECT="cat"
            else # subsequent slides and fades need header removed
                YUVCORRECT="$yuv_correct"
            fi
        fi
        spin "Doing stills for slide $((f+1))" >&2
        "${TOYUV_STILLS_CMD[@]}" "${MIX_IN[f]}" 2>/dev/null |
        $YUVCORRECT 2> /dev/null
        # now we need yuvcorrect for everything
        YUVCORRECT="$yuv_correct"
        # do a transition to the next slide
        [[ $EFFECT = "fade" ]] && fadetype=fadeout || fadetype="crossfade"
        spin "Doing $fadetype for slide $((f+1))" >&2
        if [[ $EFFECT = "crossfade" ]]; then
            do_transitions crossfade
        elif [[ $EFFECT = "fade" ]]; then
            do_transitions fadeout
        fi
        # encode transition frames
        if (($f == (${#MIX_IN[@]} - 1) )); then
            fadein_cmd=(ppmtoy4m -v 0 -n 26 -A $PIXEL_AR -I p -r -S 420mpeg2)
            cat "$WORK_DIR"/animenu/*.ppm 2>/dev/null |
            "${fadein_cmd[@]}" 2>/dev/null |
            $YUVCORRECT 2> /dev/null
        else
            cat "$WORK_DIR"/animenu/*.ppm 2>/dev/null|
            "${TOYUV_FADE_CMD[@]}" 2>/dev/null | $YUVCORRECT 2> /dev/null
        fi
        rm -f "$WORK_DIR"/animenu/*.ppm
        # do crossfade looping to 1st slide if doing crossfade effect
        if (($f == (${#MIX_IN[@]} - 1) )); then
            if [[ $EFFECT = "crossfade" ]]; then
                spin "Looping back to slide 1 with crossfade" >&2
                base_ppm=${MIX_IN[0]}
                do_transitions crossfade
                # encode transition frames
                cat "$WORK_DIR"/animenu/*.ppm 2>/dev/null |
                "${TOYUV_FADE_CMD[@]}" 2>/dev/null | $YUVCORRECT 2> /dev/null
                rm -f "$WORK_DIR"/animenu/*.ppm
            fi
        fi
    done > "$WORK_DIR/ppm.fifo"
    # close the pipe
    #exec 3>&-
    sstime2=$(date +%s)
    enctime=$(( sstime2 - sstime1 ))
    enctime=$(format_seconds $enctime)
    echo
    echo "todisc took $enctime to do the slideshow"
    if $MK_CAROUSEL_MODE; then
        # move the m2v to BASEDIR (basedir of -carousel_menu_mode)
        echo
        mv "$WORK_DIR/slideshow.m2v" "$BASEDIR/carousel-${CAROUSEL_NUM}.m2v"
        cleanup
        exit 0
    fi

    # get length
    bgaudio_time=$(stream_length "$WORK_DIR/slideshow.m2v" m2v)

    if [[ -n $BG_AUDIO ]]; then
        # convert background audio to wav
        BGAUDIO_CMD=($FFmpeg -i "$BG_AUDIO" -t $bgaudio_time -ar 48000 \
         -acodec pcm_s16le -y $WORK_DIR/slideshow.wav)
    else
        # generate silence
        BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero -ar 48000 \
        -ac 2 -t $bgaudio_time -acodec pcm_s16le -y $WORK_DIR/slideshow.wav)
    fi
    echo
    echo "Encoding audio to wav with: ${BGAUDIO_CMD[@]}" | format_output | \
    pipe2log
    echo
    "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
    # fade wav if background audio used and user did not disable fading
    if [[ -n $BG_AUDIO ]] && $AUDIO_FADE; then
        sox "$WORK_DIR/slideshow.wav" "$WORK_DIR/slideshow-faded.wav" \
         fade t $FADE $bgaudio_time $FADE
        rm -f "$WORK_DIR/slideshow.wav"
        mv "$WORK_DIR/slideshow-faded.wav" "$WORK_DIR/slideshow.wav"
    fi

    # convert the wav to target format
    echo "Converting wav to $TARGET format"
    echo
    BGAUDIO_CMD=($FFmpeg -i "$WORK_DIR/slideshow.wav" \
     $AUDIO_OPTS -y "$WORK_DIR/slideshow.ac3")
    print2log "Runnning ${BGAUDIO_CMD[@]}"
    "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
    # multiplex to mpeg-2 ( svcd or dvd )
    MPLEX_CMD=(mplex -V -f $MPLEX_FORMAT -o "$WORK_DIR/slideshow.mpg" \
    "$WORK_DIR/slideshow.$AUDIO_EXT" "$WORK_DIR/slideshow.m2v")
    print2log "Running ${MPLEX_CMD[@]}"
    "${MPLEX_CMD[@]}" 2>&1 | pipe2log mplex
    if [[ -s "$WORK_DIR/slideshow.mpg" ]]; then
        mv "$WORK_DIR/slideshow.mpg" "$WORK_DIR/intro.mpg"
    else
        runtime_error "The joined slideshow file was not created"
    fi

fi

if $DO_CAROUSEL && $USE_DVD_SLIDESHOW; then
    [[ -n $BG_AUDIO ]] && SS_AUDIO=(-a "${BG_AUDIO[@]}" )
    if [[ -n $SLIDESHOW_CONF ]]; then
        cp -v "$SLIDESHOW_CONF" "$WORK_DIR/dvd-slideshow.conf"
    else
        mk_dvd_slideshow_conf "${MIX_IN[@]}"
    fi
    dvd-slideshow $NO_SMP $vid_type -n slideshow -o "$WORK_DIR" \
    "${SS_AUDIO[@]}" -f "$WORK_DIR/dvd-slideshow.conf"
    mv "$WORK_DIR/slideshow.vob" "$WORK_DIR/intro.mpg"
fi
# check bgvideo and showcase VIDEO for compliance ( if present )
if [[ -n $BG_VIDEO && $BG_VIDEO = $BG_AUDIO ]]; then
    # do not reencode animated slideshow made in MK_CAROUSEL_MODE
    if ! [[ $BG_VIDEO = $WORK_DIR/carousel-00.m2v ]]; then
        if ! idvid -isformat \
         ${TV_STANDARD}-${TARGET} "$BG_VIDEO" >/dev/null; then
            ! $NOASK && tovid_reencode "$BG_VIDEO" $BG_SEEK background
        fi
    fi
elif [[ -n $SHOWCASE_VIDEO && $SHOWCASE_VIDEO = $BG_AUDIO ]]; then
    # do not reencode animated slideshow made in MK_CAROUSEL_MODE
    if ! [[ $SHOWCASE_VIDEO = $WORK_DIR/carousel-00.m2v ]]; then
        if ! $SWITCHED && ! $QUICK_MENU; then
            if ! idvid -isformat \
            ${TV_STANDARD}-${TARGET} "$SHOWCASE_VIDEO" >/dev/null; then
                tovid_reencode "$SHOWCASE_VIDEO" $SHOWCASE_SEEK_VAL showcase
            fi
        fi
    fi
fi

# symlink IN_FILES in $WORK_DIR to solve some quoting issues for dvdauthor
if [[ $MENU_NUM -eq 1 ]]; then
    print2log "Symlinking files to $WORK_DIR"
    for i in ${!IN_FILES[@]}; do
        if ! [[ -e $BASEDIR/${TSET_NUM}-$((i+1)).mpg ]]; then
            (cd "$REAL_WORK_DIR" &&  ln -sf "${IN_FILES[i]}" \
             "$BASEDIR/${TSET_NUM}-$((i+1)).mpg")
        fi
    done
fi
$SINGLE_SLIDESHOW && echo "Getting stats on the slides now"
for ((i=0; i<${#IN_FILES[@]}; i++)); do
    if [[ $MENU_NUM -eq 1 ]]; then
        ! $SINGLE_SLIDESHOW && \
          spin "getting stats for the log" $SPINNER #on ${IN_FILES[i]##*/}"
        idvid_stats[i]=$(idvid -terse -accurate "${IN_FILES[i]}" 2> /dev/null)
    fi
    if [ -s  "${IN_FILES[i]}.nav_log" ]; then
        length[i]=$(awk 'END{print NR}' "${IN_FILES[i]}.nav_log")
    fi
done

if $GROUPING &&  [[ $MENU_NUM -eq 1 ]]; then
    print2log ". . . Getting stats on grouped files now . . ."
    for u in ${!grouping[@]}; do
        CUR_VID=$(readlink -f "${grouping[u]}")
        spin "Getting grouped video stats for the log on "${CUR_VID##*/}""
        group_idvid_stats[u]=$(idvid -terse -accurate "$CUR_VID" 2> /dev/null)
        if [ -s "$CUR_VID.nav_log" ]; then
            group_length[u]=$(awk 'END{print NR}' "$CUR_VID.nav_log")
        fi
    done
    echo
fi
#echo -e "\nCheck the stats in todisc.log if you wish"

# get length of videos in a separate loop from other stats
# if we are doing SVCD there will be no nav_seek file
for i in ${!IN_FILES[@]}; do
    # if we have a non empty nav_log get the length from that
    if [ -s "${IN_FILES[i]}".nav_log ]; then
        VID_LEN[i]=$(bc_math "${length[i]} / $FRAME_RATE")
    else # otherwise, we run ffmpeg to get the length
        VID_LEN[i]=$(stream_length  "${IN_FILES[i]}" )
    fi
    if [[ ${VID_LEN[i]%.*} -lt ${SEEK_VAL[i]%.*} ]]; then
        usage_error "A seek of ${SEEK_VAL[i]} seconds is too large for
        ${IN_FILES[i]}. The file is only ${VID_LEN[i]} seconds long"
    fi
    # check if file is long enough for the submenu length
    if $ANI_SUB_MENU; then
        if ((${VID_LEN[i]%.*} < (${SUBMENU_LEN[i]} * ${CHAPTERS[i]}) )); then
            usage_error "${IN_FILES[i]} is not long enough for ${CHAPTERS[i]}
                         animated submenu chapters of ${SUBMENU_LEN[i]} seconds"
        fi
    fi
    # add -force to makevcd if short file
    # wait for input on short files (slides) unless -video-pause passed
    if [[ $( ${bC} -l <<< "${VID_LEN[i]} < 1") -eq 1 ]]; then
        [[ -z ${VPAUSE[i]} ]] && VPAUSE[i]="inf"
        # 1 chapter per short file, (altered below if group short file)
        ! $USER_CHAPTERS && CHAPTERS[i]=1 # each 'slide' is a chapter
    fi
done
# make sure we have the length of grouped files as well
for g in ${!grouping[@]}; do
    # if we have a value for ${group_length[g]}  get the length from that
    if [[ -n "${group_length[g]}" ]]; then
        GROUP_VID_LEN[g]=$(bc_math "${group_length[g]} / $FRAME_RATE")
    else # otherwise, we run stream_length to get the length
        GROUP_VID_LEN[g]=$(stream_length "${grouping[g]}")
    fi
done
if $GROUPING; then
    index=0
    for i in "${!IN_FILES[@]}"; do
        if [[ ${GROUP_ARR[i]} ]]; then
            iter=( $BASEDIR/${TSET_NUM}-group-$((i+1))-*.mpg )
            for ((t=index; t<index+${#iter[@]}; t++)); do
                # get lengths of group videos also in a seperate loop
                # concatenate the group lengths in a string
                GROUP_VID_LENGTHS[i]="${GROUP_VID_LENGTHS[i]} \
                ${GROUP_VID_LEN[t]}"
                # if short file, assume it is a slideshow, and use pause="inf"
                if [[ $( ${bC} -l <<< "${GROUP_VID_LEN[t]} < 1") -eq 1 ]]; then
                    # but only if -group-video-pause was not passed
                    [[ -z ${GRP_VPAUSE[i]} ]] && GRP_VPAUSE[i]="inf"
                    ! $USER_CHAPTERS && CHAPTERS[i]=0 # each slide's a chapter
                fi
            # replacement for comma delimited locales
            done
            index=$((index+${#iter[@]}))
            unset iter
            # a string of the joined grouped lengths and 1st video in the group
            GROUP_VID_LENGTHS[i]="${VID_LEN[i]} ${GROUP_VID_LENGTHS[i]}"
            # total length for the whole group - for chapter creation
            GROUP_TOT_LEN[i]=$(awk_total <<< "${GROUP_VID_LENGTHS[i]}")
        fi
    done
fi
# put in the log file in case anyone is interested
if ! $VMGM_ONLY &&  [[ $MENU_NUM -eq 1 ]] && $DO_STATS; then
    get_stats files
    print2log ""
fi
if ! $VMGM_ONLY &&  [[ $MENU_NUM -eq 1 ]] && $GROUPING && $DO_STATS; then
    get_stats group
    print2log ""
fi

# run quick_menu to create an almost finished menu file ( intro.m2v )
$QUICK_MENU && quick_menu
# if doing switched menus, use the bgaudio from each video
# unless "none" is passed for -bgaudio
if $SWITCHED; then
    yecho ""
    let vid=MENU_NUM-1
    SHOWCASE_SEEK_VAL=${SEEK_VAL[vid]}
    # use silence if a short file ( probably a slide ) and no background audio
    if [[ -z $BG_AUDIO &&  $( ${bC} -l <<< "${VID_LEN[vid]} < 1") -eq 1 ]]; then
        BG_AUDIO="none"
    fi
    # if no audio is detected in the video
    if grep -q "A_NOAUDIO=:" <<< "${idvid_stats[vid]}"; then
        # if -bgaudio is not passed, or passed as 'none', use silence
        if [[ -z $BG_AUDIO || $BG_AUDIO = "none" ]]; then
            yecho "Using silence as audio background for ${FILES[vid]}"
        # if -bgaudio is passed, use the provided file
        else
            yecho "Using $BG_AUDIO as audio background for "${FILES[vid]}""
        fi
    else # audio detected in the video
        if [[ -z $BG_AUDIO && $BG_AUDIO != "none" ]]; then
            # use the audio from each video for each switched menu
            BG_AUDIO=${IN_FILES[vid]}
            if $STATIC; then
                [[ -z $MENU_AUDIOLEN ]] \
                && MENU_AUDIOLEN=${MENU_LEN[MENU_NUM-1]}
                # start audio at the beginning unless user passes -bgaudio-seek
                ! $USER_BG_AUDIO_SEEK && BG_AUDIO_SEEK=0
                # make sure MENU_AUDIOLEN value isn't longer than the video
                # FIXME if video shorter than menu length adjust MENU_LEN
                [[ $( ${bC} -l <<< "$MENU_AUDIOLEN > ${VID_LEN[vid]}") -eq 1 ]] \
                                            && MENU_AUDIOLEN=${VID_LEN[vid]}
                # MENU_LEN can't be longer than the audio length
                # don't use fade unless the video is long enough to support it
                [[ $( ${bC} -l <<< "${VID_LEN[vid]} < (($FADE * 2) + 2)") \
                -eq 1 ]] && AUDIO_FADE=false
            else
                # same seek value as video unless user passes -bgaudio-seek
                ! $USER_BG_AUDIO_SEEK && BG_AUDIO_SEEK=${SEEK_VAL[vid]}
                # the menu audio will be the same length as the switched video
            fi
            yecho "Using audio from "${FILES[vid]}" for the audio background,"
            ! $STATIC && info_message "using the same seek value for the audio \
            as the video. If you wish to use silence for the switched menu,
            use '-bgaudio none'"
        else
            if [[ $BG_AUDIO = "none" ]]; then # no audio if -bgaudio none
                BG_AUDIO=""
                MENU_AUDIOLEN=2
                AUDIO_FADE=false
            else # BG_AUDIO="$BG_AUDIO" if -bgaudio supplied and not 'none'
                [[ -z $MENU_AUDIOLEN ]] && \
                MENU_AUDIOLEN=${MENU_LEN[MENU_NUM-1]}
                yecho \
                "Using "$BG_AUDIO" as audio background for $SHOWCASE_VIDEO"
            fi
        fi
    fi
    yecho ""
fi
for ((i=0; i<${#VID_LEN[@]}; i++)); do
    NEW_LENGTH=( ${NEW_LENGTH[@]}   ${VID_LEN[i]%.*} )
done
# find out longest video and shortest video
for ((i=0; i<${#NEW_LENGTH[@]}; i++)); do
    val=${NEW_LENGTH[i]}
    [ -z "$MAX_VAL" ] || ((val > MAX_VAL)) && MAX_VAL=$val && max_key=$i
    if $ANI_SUB_MENU; then
        [ -z "$MIN_VAL" ]  || ((val < MIN_VAL)) && MIN_VAL=$val && min_key=$i
    fi
done
# if submenu selected, translate seconds of submenu length into # of frames
if $ANI_SUB_MENU; then
    for i in ${!IN_FILES[@]}; do
        SUBMENU_FRAMES+=( $(bc_math "$FRAME_RATE * ${SUBMENU_LEN[i]}" int) )
    done
fi
# if animated submenu check if videos are long enough for the # of chapters
if $ANI_SUB_MENU; then
    for ((i=0; i<=NUM_FILES; i++)); do
        S=$(bc_math "${SEEK_VAL[i]} * $FRAME_RATE" int)
        F=$(bc_math  "${CHAPTERS[i]} * 0" int )
        V=$(bc_math "${VID_LEN[i]} * $FRAME_RATE" int)
        if [ $((V - S)) -le $F ] ; then
            echo "Sorry, you can not use ${CHAPTERS[i]}
            chapters for ${IN_FILES[i]}.  Maximum chapters for this video
            (using a -seek of ${SEEK_VAL[i]}):
            $(bc_math "($V - $S) / ${SUBMENU_FRAMES[i]}" int) chapters" |
             format_output
            exit 1
        fi
        unset V F
    done
fi
# allow animated menus of length of longest video
MAX_MENU_LEN=$(bc_math "$FRAME_RATE * ${MENU_LEN[MENU_NUM-1]}" int)
MAX_VAL_FRAMES="$((MAX_VAL * 30))"

MENU_FRAMES=$MAX_MENU_LEN
if $STATIC; then
    if $SWITCHED && [[ -z $BG_VIDEO ]] && ! $MENU_FADE; then
        FRAMES=1
    elif [[ -z $BG_VIDEO && -z $SHOWCASE_VIDEO ]] && ! $MENU_FADE; then
        FRAMES=1
    else
        FRAMES=$MENU_FRAMES
    fi
    # THUMB_FRAMES is for extracting frames from video titles
    # a static menu can have animated bg or showcase video
    THUMB_FRAMES=1
else
    FRAMES=$MENU_FRAMES
    THUMB_FRAMES=$FRAMES
fi
# if -transition-to-menu used, the bg ends when the thumbs start to fade in
if $TRANSITION_TO_MENU; then
    BG_VIDEO_FRAMES=$THUMBS_FADEIN_ENDFRAME
else
    BG_VIDEO_FRAMES=$FRAMES
fi
# menu-fade only processes up to the THUMBS_FADEOUT_ENDTIME set previously
LAST_PIC=${LAST_PIC:-$FRAMES}

###############################################################################
#                           End of info block                                 #
###############################################################################

###############################################################################
#                       work on the clip title images                         #
###############################################################################
# extract images from the title videos

if ! $TEXTMENU && ! $SINGLE_SLIDESHOW && $DO_MENU; then
    echo
    echo "Creating $THUMB_FRAMES images from each video for the main menu"
    for ((i=0; i<=NUM_FILES; i++)) ; do
        if [ "$SC_FRAMESTYLE" = "glass" ]; then
            # some vars for get_framed_pics function
            D=2
            VOUT="png:z=7"
            FRAME_SIZE=$THUMB_SIZE
            echo "Using mplayer to get framed images from "${IN_FILES[i]}""
            OUT=$WORK_DIR/pics/$i
            echo "Working on "${IN_FILES[i]}""
            MPLAYER_SEEK_VAL=${SEEK_VAL[i]}
            get_framed_pics "${IN_FILES[i]}"   >> "$LOG_FILE" 2>&1
            echo
            for ((p=1; p<=$THUMB_FRAMES; p++)); do
                mv  "$WORK_DIR"/$(printf "%08d%s" $p .png) \
                  $WORK_DIR/pics/$i/$(printf "%06d%s" $p .png) 2>/dev/null
            done
        elif [[ ${file_is_image[i]} = "yes" ]]; then
            spin "Convert ${FILES[i]##*/} to proper size/format"
            convert "${FILES[i]}" -depth 8 \
              -resize ${THUMB_SIZE}! \
              "$WORK_DIR/pics/$i/$(printf "%06d%s"  0 .${IMG_FMT})"
        elif $USER_THUMBS; then
            : # allow substituting user image for images
        else
            echo
            echo "Working on ${IN_FILES[i]}"
            # for static menu use 9 frames so we can get the largest one below
            if $STATIC && $FRAME_SAFE; then
                thumb_frames=9
            else
                thumb_frames=$THUMB_FRAMES
            fi
            # warning to ignore transcode error messages
            $use_transcode && print_tcode_info
            if [ -s  "${IN_FILES[i]}.nav_log" ]; then
                NAV_SEEK[i]="--nav_seek"
                NAVSEEK[i]=${IN_FILES[i]}.nav_log
            fi
            ff_log_tmp="$WORK_DIR/pics/$i/ff_log.tmp"
            tc_log_tmp="$WORK_DIR/pics/$i/tc_log.tmp"
            if $use_transcode; then
                vid_stream="$WORK_DIR/pics/$i/out.yuv"
                 [[ ! -p "$vid_stream" ]] && mkfifo "$vid_stream"
                ff_seek=""
                ff_frames=""
            else
                # using ffmpeg directly on file, PIPE_FORMAT not needed
                vid_stream="${IN_FILES[i]}"
                unset PIPE_FORMAT
                ff_seek="-ss ${SEEK_VAL[i]}"
                ff_frames="-vframes $thumb_frames"
            fi

            # resize using ffmpeg instead of transcode
            FFMPEG_CMD2=($FFmpeg $PIPE_FORMAT -i "$vid_stream" $ff_seek \
            $ff_frames -f image2 $VF scale=${THUMB_SIZE%x*}:${THUMB_SIZE#*x} \
            -y "$WORK_DIR/pics/$i/%06d.$IMG_FMT")
            TRANSCODE_CMD2=(transcode --progress_rate 10 \
            --write_pid $WORK_DIR/tcode$i.pid -q 1 -i "${IN_FILES[i]}" \
            -c ${SEEK_FRAMES[i]}-$((${SEEK_FRAMES[i]} + $thumb_frames)) \
            ${NAV_SEEK[i]} "${NAVSEEK[i]}" -o "$vid_stream" \
            -f $FRAME_RATE $EXPORT)
            if $use_transcode; then
                print2log "Running ${TRANSCODE_CMD2[@]}"
                "${TRANSCODE_CMD2[@]}"  2>&1 | pipe2log transcode &
            fi
            print2log "Running ${FFMPEG_CMD2[@]}"
            "${FFMPEG_CMD2[@]}" > "$ff_log_tmp" 2>&1 &
            ffm_pid=$!
            if $use_transcode; then
                wait_for "$WORK_DIR/tcode$i.pid"
                tcode_pids="$tcode_pids $(<$WORK_DIR/tcode$i.pid)"
            fi
            if [[ -n "$ffm_pid" ]]; then
                wait_for "$WORK_DIR/pics/$i/000001.$IMG_FMT"
                while ps -p $ffm_pid >/dev/null; do
                    sleep 2 # spinner interval
                    last_image=$(find $WORK_DIR/pics/$i \
                    -maxdepth 1 -name \*.$IMG_FMT| sort |
                    awk -F / '{ field = $NF }; END{ print field }')
                    spin "Seeking in video and creating images: $last_image"
                done
                # wait for ffmpeg and transcode to finish
                wait $ffm_pid # get exit code of ffmpeg
                if (($? != 0)); then
                    cat "$ff_log_tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
                    rm -f "$ff_log_tmp"
                    runtime_error \
                      "Problem with ${FFmpeg##*/} while creating images from video"
                fi
                if $use_transcode; then
                    wait $(<$WORK_DIR/tcode$i.pid)
                    # get exit code of transcode
                    if (($? != 0)); then
                        runtime_error \
                        "Problem with transcode while creating images from video"
                    fi
                fi
                # get the largest image if static menu(we made 9)
                # get largest image of 9 if static menu and not -frame-safe
                if $STATIC && $FRAME_SAFE; then
                    largest=$(get_largest 6 $V_FRAMES "$WORK_DIR/pics/$i/")
                    # remove unused images after saving the largest as 1st
                    mv "$largest" "$WORK_DIR/pics/$i/000001.$IMG_FMT" 2>/dev/null
                    rm -f "$WORK_DIR"/pics/$i/00000{2..9}.png
                fi
                numpics=$(find $WORK_DIR/pics/$i/ -name  "*.${IMG_FMT}" | wc -l)
                # which video has the most frames encoded? Used in final encode
                ((numpics > ani_pics)) && ani_pics=$numpics
                # append ffmpeg output to the log
                echo -e \
                "\n$ME Log from ${FFmpeg##*/} (processing video stream)\n" \
                >> "$LOG_FILE"
                cat "$ff_log_tmp" | sed '/time=10000000000.00/d' | pipe2log ${FFmpeg##*/}
                rm -f "$ff_log_tmp"
                echo
                echo -n "Created $numpics images of $THUMB_FRAMES"
                echo -ne "\r$(printf %60s)" # print spaces to overwrite previous line
            else
                runtime_error "Problem creating images from the video."
            fi
            unset TRANSCODE_CMD2 numpics
        fi
        # copy 000001 image to 000000 as we use 0 based counting (transcode)
        # TODO transition to using "1" based' images as we use ffmpeg now
        [[ -s "$WORK_DIR/pics/$i/000001.$IMG_FMT" ]] && cp \
        "$WORK_DIR/pics/$i/000001.$IMG_FMT" "$WORK_DIR/pics/$i/000000.$IMG_FMT"
        dir_cnt=$(find "$WORK_DIR/pics/$i" -maxdepth 1 -name "*.$IMG_FMT" |wc -l)
        if ((dir_cnt > 1)); then
            last=$(find $WORK_DIR/pics/$i -maxdepth 1 -name \*.$IMG_FMT | \
            sort | awk 'END{print}')   
            rm -f "$last"
        fi
    done
fi
# create the pics for background image
if $DO_MENU; then
    if [ -z "$BG_PIC" ]; then
        echo
        echo "Creating a black background"
        # using JPEG here to save disk space as quality is not noticable
        BG_PIC="$WORK_DIR/pics/template1.png"
        if $QUICK_MENU; then
            convert  -size $VIDSIZE xc:none \
            -depth 8 -colorspace RGB -type TrueColorMatte "$BG_PIC"
        else
            convert  -size $VIDSIZE xc:$BG_CLR -depth 8 "$BG_PIC"
        fi
    else
        convert -size $VIDSIZE "$BG_PIC" -resize $VIDSIZE! \
        "$WORK_DIR/pics/template1.png"
    fi
    # create/resize submenu background, fill in array and symlink if needed
    if $SUB_MENU; then
        if [[ -n ${SM_BACKGROUND[@]} ]]; then
            if ((${#SM_BACKGROUND[@]} > 1)); then
                for f in ${!SM_BACKGROUND[@]}; do
                    convert  -size $VIDSIZE "${SM_BACKGROUND[f]}" \
                    -resize $VIDSIZE\! miff:- | convert - $IMG_DEPTH \
                    "$SM_BK_PNG" -gravity SouthEast -geometry +50+50 \
                    -composite "$WORK_DIR/submenu$((f+1))_template.$SM_IMG_FMT"
                done
            else
                convert  -size $VIDSIZE "$SM_BACKGROUND" \
                -resize $VIDSIZE\! miff:- | convert - $IMG_DEPTH \
                "$SM_BK_PNG" -gravity SouthEast -geometry +50+50 \
                -composite "$WORK_DIR/submenu_template.$SM_IMG_FMT"
            fi
        else
            convert  -size $VIDSIZE xc:$SUBMENU_BG_CLR miff:- |
            convert - $IMG_DEPTH "$SM_BK_PNG" -gravity SouthEast -geometry +50+50 \
            -composite "$WORK_DIR/submenu_template.$SM_IMG_FMT"
        fi
        if  ((${#SM_BACKGROUND[@]} == 1)) || [[ -z ${SM_BACKGROUND[@]} ]]; then
            for ((f=0; f<${#IN_FILES[@]}; f++)); do
                ln -s "$WORK_DIR/submenu_template.$SM_IMG_FMT" \
                "$WORK_DIR/submenu$((f+1))_template.$SM_IMG_FMT"
                SM_BACKGROUND[f]=$WORK_DIR/submenu$((f+1))_template.$SM_IMG_FMT
            done
        fi
    fi
    echo
fi
# chapters and submenu xml stuff
# this block does not run if user passing HH:MM:SS chapters
if [[ -n ${CHAPT_ARRAY[@]} ]]; then
    :
else
    for ((s=0; s<=NUM_FILES; s++)); do
        # make chapter points for videos, divide by $CHAPTERS to get
        # chapter lengths, then get running totals
        CHAPT_INTERVALS[s]=$(bc_math "${VID_LEN[s]} / ${CHAPTERS[s]}")
        # <TODO if GROUPING:  for group chapter thumbs feed group
        # chapter points to transcode in a loop as normal, but output
        # to different subdirs. Then rename according to frame number
        # moving all to the same subdir. Then follow usual procedure,
        # moving  into chapter subdirs for final montages  /TODO>

        # and format in HH:MM:SS
        L=( ${L[@]} $(for ((i=1; i<${CHAPTERS[s]}; i++)) ; \
        do echo "${CHAPT_INTERVALS[s]}";done) )
        chapt_intervals="0 $(running_total <<< ${L[@]})"
        chapters="$(for c in $chapt_intervals; \
        do echo $(format_seconds $c); done)"
        # replace commas for comma delimited locales
        if [ ${CHAPTERS[s]} = 1 ]; then chapters="00:00:00.000"; fi
        CHAPTS=$(for i in $chapters; do echo -n $i,;done)
        CHAPT_ARRAY[s]="${CHAPTS%?}" # %? to remove trailing ','
        unset L cmd
    done
fi
# slideshows can have submenus - these spu buttons are for videos only (inc_files)
if $SUB_MENU; then
    for ((s=0; s<=NUM_FILES; s++)); do
        if ! ${SLIDESHOW[s]}; then
            print2log "Creating highlight and select PNGs for submenu $((s + 1))"
            C=$((${CHAPTERS[s]} - 1))
            MENU_BUTTON_SIZE=${GEO_ARRAY[C]}
            get_button_geo
(
cat  <<EOF
rectangle 2,2 $GEO
EOF
)  > $WORK_DIR/draw_file${s}
            convert +antialias -size ${GEO_ARRAY[C]}+5+5 \
            xc:none -fill none -stroke "$SELECT_CLR" -strokewidth 4 \
            -draw @draw_file${s} "$WORK_DIR/Submenu${s}_Selectx1.png"
            convert +antialias -size ${GEO_ARRAY[C]}+5+5 \
            xc:none -fill none -stroke "$HLIGHT_CLR" -strokewidth 4 \
            -draw @draw_file${s} "$WORK_DIR/Submenu${s}_Highlightx1.png"
        fi
        CMD1=(montage -background none \
        $(for ((i=0; i<=C; i++)); do
        echo $WORK_DIR/Submenu${s}_Selectx1.png;done) \
        -bordercolor none -mattecolor transparent \
        -tile ${TILE_ARRAY[C]} \
        -geometry ${GEO_ARRAY[C]}+5+5 \
        -background none miff:-)
        CMD2=(montage -background none \
        $(for ((i=0; i<=C; i++)); do
        echo $WORK_DIR/Submenu${s}_Highlightx1.png;done) \
        -bordercolor none -mattecolor transparent \
        -tile ${TILE_ARRAY[C]} \
        -geometry ${GEO_ARRAY[C]}+5+5 \
        -background none miff:-)
        CMD3=(convert +antialias -size $VIDSIZE xc:none  \
        - -gravity north -geometry +0+45 -composite \
        "$WORK_DIR/sm_back_${HLIGHT_CLR/\#}.png" \
        -gravity SouthEast -geometry +50+50 -composite )
        CMD4=(convert +antialias -size $VIDSIZE xc:none  \
        - -gravity north -geometry +0+45 -composite \
        "$WORK_DIR/sm_back_${SELECT_CLR/\#}.png" \
        -gravity SouthEast -geometry +50+50 -composite )
        if ! ${SLIDESHOW[s]}; then
            "${CMD1[@]}" | "${CMD4[@]}" $WORK_DIR/Submenu${s}_Select.png
            "${CMD2[@]}" | "${CMD3[@]}" $WORK_DIR/Submenu${s}_Highlight.png
        else
            ! [[ -e "$WORK_DIR/Playall.png" ]] && \
             mk_play_button "#C6C6C6" '#101010' \
             default "$WORK_DIR/Playall.png"
            # make the button for spumux too
            mk_play_button  "$HLIGHT_CLR" "$HLIGHT_CLR" spu \
            "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png"
            mogrify -channel A -threshold 50% \
            "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png"
            mk_play_button   "$SELECT_CLR" "$SELECT_CLR" spu \
            "$WORK_DIR/Playall_${SELECT_CLR/\#}.png"
            mogrify -channel A -threshold 50% \
            "$WORK_DIR/Playall_${SELECT_CLR/\#}.png"
            convert +antialias -size $VIDSIZE xc:none \
            "$WORK_DIR/Playall_${SELECT_CLR/\#}.png" \
            -gravity SouthEast -geometry +50+50 -composite \
            "$WORK_DIR/Submenu${s}_Select.png"
            convert +antialias -size $VIDSIZE xc:none \
            "$WORK_DIR/Playall_${HLIGHT_CLR/\#}.png" \
            -gravity SouthEast -geometry +50+50 -composite \
            "$WORK_DIR/Submenu${s}_Highlight.png"
        fi
        for button in Select Highlight; do
            # the slideshow 'play' button is more likely to need this
            if ${SLIDESHOW[s]}; then
                mogrify -channel A -threshold 50% \
                "$WORK_DIR/Submenu${s}_${button}.png"
            fi
            num_colours=$(identify -ping -format %k \
            "$WORK_DIR/Submenu${s}_${button}.png")
            ((num_colours >3)) && \
            mogrify -channel A -threshold 99% \
            "$WORK_DIR/Submenu${s}_${button}.png"
        done

##############################################################################
#                    Make xml files for spumux and dvdauthor                 #
##############################################################################
(
    cat <<EOF
<subpictures>
   <stream>
     <spu force="yes" start="00:00:00.0"
          highlight="$WORK_DIR/Submenu${s}_Highlight.png"
          select="$WORK_DIR/Submenu${s}_Select.png"
          autooutline="infer"
          autoorder="rows"/>
   </stream>
 </subpictures>
EOF
) > "$WORK_DIR/submenu$((s + 1))_spumux.xml"
    done
fi

# debug chapters
if ! $VMGM_ONLY &&  [[ $MENU_NUM -eq 1 ]] && $DO_STATS; then
    echo
    for ((i=0; i<=NUM_FILES; i++)); do
        ! ${SLIDESHOW[i]} && \
        echo -e "Chapters for "${IN_FILES[i]}" are: \n"${CHAPT_ARRAY[i]}"\n" | \
        pipe2log
    done
fi
# get button coordinates if text-rect buttons (showcase menu only)
if [[ $BUTTON_STYLE = *text* ]] && $SHOWCASE; then
    for ((i=0; i<=NUM_FILES; i++)); do
        xdim=${TT_DIM[i]%%x*}
        ydim=${TT_DIM[i]##*x}
        X0=${SC_TITLES_X_ARRAY[i]}
        ! $TEXTMENU && X0=$( cut -f2 -d+ <<< ${THUMBTITLES_ARRAY[i]})
        X1=$((X0 + xdim))
        Y0=${SC_TITLES_Y_ARRAY[i]}
        Y1=$((Y0 + ydim))
        ((X0%2 && X0--)); ((Y0%2 && Y0--))
        ((X1%2 && X1++)); ((Y1%2 && Y1++))
        button_geos=(x0=\"$X0\" y0=\"$Y0\" x1=\"$X1\" y1=\"$Y1\")
        $SHOWCASE && btn_geos[i]=${button_geos[@]}
        unset button_geos
    done
fi
if [[ "$BUTTON_STYLE" = "text" && -z "$OUTLINEWIDTH" ]]; then
    OUTLINEWIDTH="\"14\""
else
    [[ -z "$OUTLINEWIDTH" ]] && OUTLINEWIDTH="\"6\""
fi
# the spumux here doc starts loops at 1, so NUM_BUTTONS has an extra index
if { $TSET_MODE && $VMGM_MENU ; } || \
 { $PLAYALL ||  { $TITLESET_MODE && $VMGM_MENU ; } ; }; then
    NUM_BUTTONS=$(( ${#FILES[@]} + 1 ))
else
    NUM_BUTTONS=${#FILES[@]}
fi
# no FILES for VMGM menu (titleset arrangements): use ${#TITLES[@]}
$VMGM_ONLY && NUM_BUTTONS=${#TITLES[@]}
$VMGM_ONLY && $PLAYALL && ((NUM_BUTTONS++))
$SWITCHED && SPUMUX_XML="$BASEDIR/spumux.xml"
if $SWITCHED; then
    down="down=\"ActionDown\"" && up="up=\"ActionUp\""
    right="right=\"ActionDown\"" && left="left=\"ActionUp\""
    updown="down=\"ActionDown\" up=\"ActionUp\""
fi
(
    cat <<EOF
$( { $SHOWCASE || $SINGLE_SLIDESHOW ; } && closebracket='>'
echo -e "<subpictures>"
echo -e  "  <stream>"
echo -e    "    <spu force=\"yes\" start=\"$START\"$END"
echo -e "         highlight=\"$WORK_DIR/Highlight.png\""
echo -e "         select=\"$WORK_DIR/Select.png\"$closebracket"
if ! $SHOWCASE && ! $SINGLE_SLIDESHOW; then
    echo -e "         autooutline=\"infer\""
    echo -e "         outlinewidth="$OUTLINEWIDTH""
    echo -e "         autoorder=\"$AUTOORDER\">"
fi)
$(if $QUICK_NAV && $SINGLE_SLIDESHOW; then
    echo -n "       <button name=\"1\" ${btn_geos[0]} "
    echo -e "       left=\"ActionLeft\" right=\"ActionRight\"/>"
    echo -e "        <action name=\"ActionLeft\"/>"
    echo -e "        <action name=\"ActionRight\"/>"
    if { $TITLESET_MODE || $TSET_MODE ; } && $VMGM_MENU; then
        echo -e "        <button name=\"2\"  ${btn_geos[1]} up=\"1\"/>"
    fi
elif $QUICK_NAV; then
    for ((i=1; i<=NUM_BUTTONS; i++)); do
        ! $SWITCHED_MENUS && \
        right="right=\"$((i+1))\"" && left="left=\"$((i-1))\""
        # $i -eq 1 should cover ((NUM_FILES==0)) situation
        if [[ $i -eq 1 ]]; then
            echo -n \
             "       <button name=\"$i\" ${btn_geos[i-1]} $down $up"
        elif ((i==NUM_FILES+1)); then
            if  $PLAYALL || $VMGM_MENU; then
                # no playall or vmgm button for vmgm menu
                dwn="down=\"$((i+1))\""
                echo -n \
                 "       <button name=\"$i\" ${btn_geos[i-1]} $up $dwn"
            else
                echo -n "       <button name=\"$i\" ${btn_geos[i-1]} $down $up"
            fi
        else
            ((i != NUM_FILES+2)) && \
            echo -e \
             "       <button name=\"$i\" ${btn_geos[i-1]} $left $right $down $up/>"
        fi
        if ((i==1)); then
            if ((NUM_FILES==0)); then # special case if only 1 file on menu
                echo -e " left=\"ActionLeft\" right=\"ActionRight\"/>"
                echo -e "       <action name=\"ActionLeft\"/>"
                echo -e "       <action name=\"ActionRight\"/>"
                if $SWITCHED_MENUS; then
                    echo -e "       <action name=\"ActionDown\"/>"
                    echo -e "       <action name=\"ActionUp\"/>"
                fi
            else
                echo -e " left=\"ActionLeft\" $right/>"
            fi
        elif ((i==NUM_FILES+1)) && ((NUM_FILES != 0)); then
            echo -e " right=\"ActionRight\" $left/>"
            echo -e "       <action name=\"ActionLeft\"/>"
            echo -e "       <action name=\"ActionRight\"/>"
            if $SWITCHED_MENUS; then
                echo -e "       <action name=\"ActionDown\"/>"
                echo -e "       <action name=\"ActionUp\"/>"
            fi
        fi
        if ((i==NUM_FILES+2)); then # quick-nav assumes titlesets
            # VMGM_MENU means NOT -no-vmgm
            if $VMGM_MENU && $PLAYALL && ! $VMGM_ONLY; then
                echo -n "       <button name=\"$i\" ${btn_geos[i-1]} "
                echo -e "up=\"$((i-1))\" down=\"$((i+1))\"/>"
                echo -e "       <button name=\"$((i+1))\" ${btn_geos[i]} $down/>"
            elif $PLAYALL; then # PLAYALL only
                echo -e "       <button name=\"$i\" ${btn_geos[i-1]} $down/>"
            else # vmgm button only
                echo -e "       <button name=\"$i\" ${btn_geos[i]} $down/>"
            fi
        fi
    done
fi)
$(if $SWITCHED && ! $QUICK_NAV; then
    for ((i=1; i<=NUM_BUTTONS; i++)); do
        if ((i==NUM_FILES+2)); then # extra button: Playall, or Return, or both
            if $TITLESET_MODE && $VMGM_MENU && $PLAYALL; then
                echo -n "       <button name=\"$i\" ${btn_geos[i-1]} "
                echo -e "up=\"$((i-1))\"/>"
                echo -e "       <button name=\"$((i+1))\" ${btn_geos[i]} $down/>"
            elif { $TITLESET_MODE && $VMGM_MENU ; }; then # Return only
                echo -n "       <button name=\"$i\" ${btn_geos[i]} "
                echo -e "up=\"$((i-1))\" $down/>"
            elif $PLAYALL; then # Playall only
                echo -n "       <button name=\"$i\" ${btn_geos[i-1]} "
                echo -e "up=\"$((i-1))\" $down/>"
            fi
        elif ((i==NUM_FILES+1)); then
            if ($TITLESET_MODE && $VMGM_MENU) || $PLAYALL; then
                echo -n "       <button name=\"$i\"  ${btn_geos[i-1]} "
                echo -e "$up down=\"$((i+1))\"/>"
            else
                echo -e "       <button name=\"$i\" ${btn_geos[i-1]} $updown/>"
            fi
        else
            echo -e "       <button name=\"$i\"  ${btn_geos[i-1]} $updown/>"
        fi
    done
    echo -e "       <action name=\"ActionDown\"/>"
    echo -e "       <action name=\"ActionUp\"/>"
fi)
$(if ! $SWITCHED && ! $QUICK_NAV; then
    if $SINGLE_SLIDESHOW; then
        echo -e "      <button name=\"1\" ${btn_geos[0]}/>"
        if $TITLESET_MODE && $VMGM_MENU; then
            echo -e "      <button name=\"2\" ${btn_geos[1]}/>"
        fi
    else
        for ((i=1; i<=NUM_BUTTONS; i++)); do
            if $SHOWCASE && ((NUM_FILES >= SPLIT)); then
                if ((i>SPLIT)) && ((i<NUM_BUTTONS)); then
                    left="left=\"$((i-SPLIT))\""; right=""
                elif  (( i<=SPLIT)) && (( (i+SPLIT) <= (NUM_FILES+1) )); then
                    right="right=\"$((i+SPLIT))\""; left=""
                else
                    left=""; right=""
                fi
            fi
            if ((i==NUM_FILES+2)); then
                if $TITLESET_MODE && $VMGM_MENU && $PLAYALL; then
                    # both Return button AND Playall buttons
                    echo -e \
                    "      <button name=\"$i\" $right $left ${btn_geos[i-1]}/>"
                    echo -e \
                    "      <button name=\"$((i+1))\" $right $left ${btn_geos[i]}/>"
                elif $PLAYALL; then
                    # Playall button only
                    echo -e \
                    "      <button name=\"$i\" $right $left ${btn_geos[i-1]}/>"
                elif $TITLESET_MODE && $VMGM_MENU; then
                    # Return button only
                    echo -e \
                    "      <button name=\"$i\" $right $left ${btn_geos[i]}/>"
                fi
            else # all other buttons besides Playall and Return
                echo -e \
                "      <button name=\"$i\" $right $left ${btn_geos[i-1]}/>"
            fi

        done
    fi
fi)
    </spu>
  </stream>
</subpictures>
EOF
) |sed '/^ *$/d'  > "$SPUMUX_XML"

if $SUB_MENU; then
    JUMP=menu
    POST="        <post> jump cell 1; </post>"
    if $ANI_SUB_MENU; then
        PAUSE=" pause=\"$PAUSE_TIME\""
    else
        PAUSE=" pause=\"inf\""
        unset POST
    fi
else
    JUMP=title
fi
# make dvdauthor.xml
# REGISTERS: g1: switched menus, g2: vmgm intro, g3: -quick-nav, g4: playall
# g5: button highlight, g6: VMGM button highlight, g7: vmgm playall
# g8: toggle showing if a video finished playing (used with g7)
# Note: for switched menus g1 is used for 'button highlight', not g5

# TSET_NUM is the titleset number being worked on
# ALLTITLES is an array of the number of titles in each titleset
# NUM_MENUS is the # of menus being made
# menu_num is the current menu being worked on
# the above 2 values always equal 1 unless doing switched menus
# TSET_NUM supplied by the calling todisc script and is the current titleset #
MENU_FILE="$BASEDIR/animenu${TSET_NUM}-${MENU_NUM}.mpg"
$DO_INTRO && SET_REG="if ( g2 eq 1 ) "
VMGM_PREJUMP="${SET_REG}jump titleset 1 menu;"
#$DO_INTRO && VMGM_POST="<post>g2=1; jump titleset 1 menu;</post>"
$VMGM_ONLY && MENU_FILE="$BASEDIR/VMGM.mpg"
$SWITCHED_MODE && ! $VMGM_ONLY \
&& MENU_FILE="$BASEDIR/animenu${TSET_NUM}-${MENU_NUM}.mpg"
if $PLAYALL || $VMGM_PLAYALL; then
    AUTHOR_PLAYALL=: # needed for VMGM playall logic
fi

$SWITCHED_MENUS && NUM_MENUS=${#FILES[@]} || NUM_MENUS=1
! $AUTHOR && DVDAUTHOR_XML="$BASEDIR/dvdauthor.xml"
# this 1st block (if $AUTHOR) refers to the VMGM of single titleset DVD's only
(
    cat <<EOF
$(if $AUTHOR; then
    echo     "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
    echo     "<dvdauthor dest=\"$OUT_DIR\" jumppad=\"0\">"
    echo -e  "  <vmgm>\n    <menus>"
    echo     "      <video format=\"${TV_STANDARD}\" aspect=\"4:3\"/>"
    echo     "      <pgc entry=\"title\" pause=\"0\">"
    echo     "        $INTRO"
    echo     "        <vob file=\"$WORK_DIR/dummy.mpg\"/>"
    echo     "        <pre>"
    echo     "        if ( g5 eq 0 ) g5=1; g4=0;"
    $SWITCHED_MENUS && \
    echo     "        if (g1 eq 0) g1=1;"
    echo     "        $VMGM_PREJUMP"
    echo     "        </pre>"
    $DO_INTRO && \
    echo     "        <post>g2=1; jump titleset 1 menu;</post>"
    echo -e  "      </pgc>\n    </menus>\n  </vmgm>"
fi)
  <titleset>
    <menus>
      <video format="${TV_STANDARD}" aspect="4:3"/>
$(for ((menu_num=1; menu_num<=NUM_MENUS; menu_num++)); do
    echo -e "      <pgc>"
    for ((i=1; i<=$V_TOTAL; i++)); do
        if $SUB_MENU; then
            JUMP_INC=$((i + NUM_MENUS))
        else
            JUMP_INC=$i
        fi
        if $SINGLE_SLIDESHOW; then
            :
        else
            if $VIDEOS_ARE_CHAPTERS && [[ -z ${grouping[@]} ]]; then
                echo -e \
                "        <button name=\"$i\">g5=$i; jump title 1 chapter $i;</button>"
            else
                echo -e \
                 "        <button name=\"$i\">g5=$i; jump $JUMP $JUMP_INC;</button>"
            fi
        fi
    done
    if $QUICK_NAV; then
        (( TSET_NUM == 1 )) && PREV=$TSET_TOT || PREV=$(( TSET_NUM - 1 ))
        (( TSET_NUM == TSET_TOT )) && NEXT=1 || NEXT=$(( TSET_NUM + 1))
        (( TSET_NUM == 1 )) && Ind=$((TSET_TOT-1)) || Ind=$(( TSET_NUM - 2 ))
    fi
    if $SINGLE_SLIDESHOW; then
        echo -e "        <button name=\"1\">jump title 1;</button>"
    fi
    if $QUICK_NAV; then
        echo -e "        <button name=\"ActionLeft\">"
        echo -e "        g1=${ALLTITLES[Ind]}; g5=${ALLTITLES[Ind]}; g3=$PREV; button=1024;"
        echo -e "        jump vmgm menu entry title;</button>"
        echo -e "        <button name=\"ActionRight\">"
        echo -e "        g1=1; g5=1; g3=$NEXT; button=1024;"
        echo -e "        jump vmgm menu entry title;</button>"
    fi
    if $SINGLE_SLIDESHOW; then
        if  $TITLESET_MODE && $VMGM_MENU; then
            echo -n "        <button name=\"2\">g2=1; g3=1000; g6=$TSET_NUM; jump vmgm menu;"
            echo -e "</button>"
        fi
    fi
    if $SWITCHED_MENUS; then
        if [[ $menu_num -eq $NUM_MENUS ]]; then
            inc=1
        else
            inc=$((menu_num+1))
        fi
        [[ $menu_num -eq 1 ]] && dec=$NUM_MENUS || dec=$((menu_num - 1))
        echo -e "        <button name=\"ActionUp\">g1=$dec; jump menu $dec;</button>"
        echo -e "        <button name=\"ActionDown\">g1=$inc; jump menu $inc;</button>"
    fi
    NAV_BTN_NUM=$V_TOTAL
    if $PLAYALL ; then # titleset playall has button here: not for $VMGM_PLAYALL
        ((NAV_BTN_NUM++))
        echo -e "        <button name=\"$NAV_BTN_NUM\">g4=1; jump title 1 chapter 1;</button>"
    fi
    if  $TITLESET_MODE && $VMGM_MENU && ! $SINGLE_SLIDESHOW; then
        ((NAV_BTN_NUM++))
        echo -e "        <button name=\"$NAV_BTN_NUM\">g2=1; g3=1000; g6=$TSET_NUM; jump vmgm menu;</button>"
    fi
    echo -e "        <vob file=\"$BASEDIR/animenu${TSET_NUM}-${menu_num}.mpg\" pause=\"$VMGM_PAUSE\"/>"
    if $SWITCHED_MENUS; then
        if [[ $menu_num -ne $NUM_MENUS ]]; then
            echo -e "        <pre>"
            echo -e "        button = g1 * 1024;"
            echo -e "        if (g1 ne $menu_num) jump menu $((menu_num+1)); g4=0;"
            echo -e "        if (g8==0) { g7=0; g4=0; }"
            echo -e "        if (g7==$TSET_NUM) { g4=1; jump title 1 chapter 1; }"
            echo -e "        </pre>"
        else
            echo -e "        <pre>button = g1 * 1024; g4=0;</pre>"
        fi
    else
        if $SINGLE_SLIDESHOW; then
            echo -e "        <pre>if (g5 gt 1) g5=1; button = g5 * 1024;</pre>"
        else
            if $VMGM_PLAYALL; then
                echo "        <pre>"
                echo "        button = g5 * 1024;"
                echo "        if (g8==0) { g7=0; g4=0; }"
                echo "        if (g7==$TSET_NUM) { g4=1; jump title 1 chapter 1; }"
                echo "        </pre>"
            else
                echo -e "        <pre>button = g5 * 1024; g4=0;</pre>"
            fi
        fi
    fi
    echo -e "$MAIN_PRE"
    echo -e "$MAIN_POST"
    echo -e "      </pgc>"
done)
$(if $SUB_MENU; then
    echo -ne "      <pgc>\n"
        for ((Y=1; Y<=$V_TOTAL; Y++)); do
            if ${SLIDESHOW[Y-1]}; then
                echo -e "        <button name=\"1\">jump title $Y;</button>"
            else
                for ((g=1; g<=${CHAPTERS[Y-1]}; g++)); do
                    echo -e "        <button name=\"$g\">jump title $Y chapter $g;</button>"
                done
                echo -e "        <button name=\"$g\">jump menu 1;</button>"
            fi
            echo -e "        <vob file=\"$BASEDIR/${TSET_NUM}-Menu$Y.mpg\"$PAUSE/>"
echo "$POST"
            echo "      </pgc>"
            echo "      <pgc>"
        done | sed '$d'
fi)
    </menus>
    <titles>
      $TITLES_VID_TAG
$(if [[ -n ${LANGS[@]} ]]; then
    for ((s=0; s<${#LANGS[@]}; s++)); do
        echo -e "      <audio lang=\"${LANGS[s]}\"/>"
    done
fi)
$(if $SUBTITLES; then
    for ((s=0; s<${#SUBS_ARRAY[@]}; s++)); do
        echo -e "      <subpicture lang=\"${SUBS_ARRAY[s]}\"/>"
    done
fi)
$(if $SINGLE_SLIDESHOW || $VIDEOS_ARE_CHAPTERS; then
    echo -e "      <pgc>"
fi)
$(z=1;for ((i=0; i<${#IN_FILES[@]}; i++)); do
    vid_pause=""; grp_vid_pause=""
    [[ -n ${VPAUSE[i]} ]] && vid_pause="pause=\"${VPAUSE[i]}\""
    [[ -n ${GRP_VPAUSE[i]} ]] && grp_vid_pause="pause=\"${GRP_VPAUSE[i]}\""
    unset j
    if $SINGLE_SLIDESHOW || $VIDEOS_ARE_CHAPTERS; then
        :
    else
        echo -e "      <pgc>"
    fi
    if [[ -n $AUDIO_CHANNEL ]]; then
        echo "${VOB_PRE[i]}"
    fi
    if [[ -n ${GROUP_ARR[i]} ]]; then
       ((MENU_NUM == 1 && ${CHAPTERS[i]} != 0)) && get_group_chapters $i format
        if ((${nochapt[i]})); then
            ! ${SLIDESHOW[i]} && echo -e \
             "        <vob file=\"$BASEDIR/${TSET_NUM}-$((i+1)).mpg\" $vid_pause/>"
            for ((m=1; m<=$((${GROUP_ARR[i]})); m++)); do
                mpg="$BASEDIR/${TSET_NUM}-group-$((i+1))-${m}.mpg"
                [[ -e $mpg ]] && \
                echo -e "        <vob file=\"$mpg\" $grp_vid_pause/>"
            done
        else
            ! ${SLIDESHOW[i]} && echo -e \
             "        <vob file=\"$BASEDIR/${TSET_NUM}-$((i+1)).mpg\" $chpts0 $vid_pause/>"
            for ((m=1; m<=$((${GROUP_ARR[i]})); m++)); do
                mpg="$BASEDIR/${TSET_NUM}-group-$((i+1))-${m}.mpg"
                [[ -e $mpg ]] && echo -e \
                 "        <vob file=\"$mpg\" ${chpts[++j]} $grp_vid_pause/>"
            done
        fi
    else
        # this block runs for single slideshows
        # max 99 titles, else we make a new <pgc>
        echo -ne "        <vob file=\"$BASEDIR/${TSET_NUM}-$((i+1)).mpg\""
        echo -e  " chapters=\""${CHAPT_ARRAY[i]}"\" $vid_pause/>"
        if $SINGLE_SLIDESHOW && ((t==96 && i < NUM_FILES)); then
            echo -e "        <post>jump title $((++z));</post>"
            echo -e "      </pgc>"
            echo -e "      <pgc>"
            t=0
        else
            unset CHAIN_PP
        fi
    fi
    if $CHAIN_VIDEOS; then
        if [ "${POST_PLAY[i]}" = "chain" ]; then
            (( i < NUM_FILES )) && CHAIN_PP="jump title $((i + 2)) chapter 1"
            (( i == NUM_FILES )) && CHAIN_PP="jump title 1 chapter 1"
        else
            CHAIN_PP="call menu"
        fi
        if $AUTHOR_PLAYALL; then
            if [ $i -lt $NUM_FILES ]; then
                $VMGM_PLAYALL && echo "        <pre>g8=0;</pre>"
                echo -e "        <post>"
                $VMGM_PLAYALL && echo -e "        g8=1;"
                echo -e \
                  "        if (g4==1) jump title $((i+2)) chapter 1; $CHAIN_PP;"
                echo -e  "        </post>"
            else
                if $VMGM_PLAYALL; then
                    echo -e  "        <pre>g8=0;</pre>"
                    echo     "        <post>"
                    echo     "        { if (g7>0) {"
                    echo     "              g8=1;"
                    echo -ne "              if (g7>=${TSET_TOT}) { g7=0; g4=0; } "
                    echo -e  "else g7=$((TSET_NUM+1));"
                    echo     "              call vmgm menu entry title;"
                    echo     "              }"
                    echo -e  "        }"
                    echo -e  "        call menu;"
                    echo -e  "        </post>"
                else
                    echo -e "        <post>call menu;</post>"
                fi
            fi
        else
            echo -e "        <post>$CHAIN_PP;</post>"
        fi
    else
        if $AUTHOR_PLAYALL; then
            if [ $i -lt $NUM_FILES ]; then
                $VMGM_PLAYALL && echo "        <pre>g8=0;</pre>"
                echo -e "        <post>"
                $VMGM_PLAYALL && echo -e "        g8=1;"
                echo -e "        if (g4==1) jump title $((i+2)) chapter 1; call menu;"
                echo "        </post>"
            else
                if $VMGM_PLAYALL; then
                    echo     "        <pre>g8=0;</pre>"
                    echo     "        <post>"
                    echo     "        { if (g7>0) {"
                    echo     "              g8=1;"
                    echo -ne "              if (g7>=${TSET_TOT}) { g7=0; g4=0; } "
                    echo     "else g7=$((TSET_NUM+1));"
                    echo     "              call vmgm menu entry title;"
                    echo     "              }"
                    echo     "        }"
                    echo     "        call menu;"
                    echo     "        </post>"
                else
                    echo     "        <post>call menu;</post>"
                fi
            fi
        else
            if $SINGLE_SLIDESHOW || $VIDEOS_ARE_CHAPTERS; then
                [[ $i = $NUM_FILES ]] && \
                 echo -e "        <post>call menu;</post>"
            else
                echo -e "        <post>call menu;</post>"
            fi
        fi
    fi
    if $SINGLE_SLIDESHOW || $VIDEOS_ARE_CHAPTERS; then
        :
    else
        echo -e "      </pgc>"
    fi
    ((t++)) # var for counting slides
done)
$( { $SINGLE_SLIDESHOW || $VIDEOS_ARE_CHAPTERS ; } &&
 echo -e "      </pgc>")
    </titles>
  </titleset>
$(if $AUTHOR; then
echo -e "</dvdauthor>"
fi)
EOF
) |sed '/^ *$/d' >> "$DVDAUTHOR_XML"
##############################################################################
#                            Make submenus                                   #
##############################################################################

# make dummy VMGM mpeg
if ! $TITLESET_MODE && ! $DO_TITLESETS; then
    yecho "Creating a blank mpeg for the vmgm menu"
    make_dummy
fi
# do submenu 1st for debug purposes
# TODO use exec 2>> "$LOG_FILE" to save lines
if $SUB_MENU; then
    yecho
    yecho "Building submenus"
    yecho
    print2log "Creating images for each chapter"
    if [ -z "$SM_TITLES" ]; then
        if $MULTILINE_TITLE; then
            for i in ${!TITLES[@]}; do
                SM_TITLES[i]="${TITLES[i]//\\n/ }"
            done
        else
            SM_TITLES=("${TITLES[@]}")
        fi
    fi
    # if animated: the length of the submenu audio will be the -submenu-length
    # if static:
    #     No audio: it will be 2 seconds long
    #     Audio and -submenu-length given: -submenu-length
    #     Audio and no -submenu-length given: full length of the audio file
    if $SUBMENU_AUDIO; then
        if [[ -n $SM_AUDIO_FILE ]]; then
            SM_AUDIOLEN=$(stream_length "$SM_AUDIO_FILE" audio)
        fi
        for ((i=0; i<=NUM_FILES; i++)); do
            [[ -n $SM_AUDIO_FILE ]] && SUBMENU_AUDIOLEN[i]=$SM_AUDIOLEN
            if $USER_SUBMENU_LEN; then
                SUBMENU_AUDIOLEN[i]=$( unformat_time ${SUBMENU_LEN[i]} )
            else
                if ${SLIDESHOW[i]}; then
                    yecho
                    spin "getting length of ${SM_AUDIO[i]} "
                    SUBMENU_AUDIOLEN[i]=$(stream_length "${SM_AUDIO[i]}" audio)
                    SUBMENU_LEN[i]=${SUBMENU_AUDIOLEN[i]}
                else
                    SUBMENU_AUDIOLEN[i]=$( unformat_time ${SUBMENU_LEN[i]} )
                fi
            fi
            # SM_LOOPS is the # of frames for static menus
            SM_LOOPS[i]=$( ${bC} \
             <<< "${SUBMENU_AUDIOLEN[i]} * $FRAME_RATE" 2>/dev/null)
            SM_LOOPS[i]=${SM_LOOPS[i]%.*}
        done
    else # we just use the menu length for generating silence
        if $ANI_SUB_MENU; then
            SUBMENU_AUDIOLEN[i]=${SUBMENU_LEN[i]}
        else
            SUBMENU_AUDIOLEN[i]=2
            for ((i=0; i<=NUM_FILES; i++)); do
                SM_LOOPS[i]=60
            done
        fi
    fi
    # if doing animated submenus, we need a 'carousel' (animated slideshow)
    # background or showcase carousel will not do, nor is it made if $STATIC
    if $ANI_SUB_MENU && ((sshows>=1)); then
        if ! carousel_menu_mode submenu; then
            yecho '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
            yecho "todisc encountered an error"
            cleanup && killall_instances
            exit 13
        fi
    fi
    for ((i=0; i<${#IN_FILES[@]}; i++)); do
        smframes=${SUBMENU_FRAMES[i]}
        if ! ${SLIDESHOW[i]}; then
            C=$((${CHAPTERS[i]} - 1))
            VSIZE=${GEO_ARRAY[C]}
            SN_BTN_XY=${GEO_ARRAY[C]} # button dimensions
            NUM_CHAPTERS=${CHAPTERS[i]}
            print2log "Creating a transparent title PNG"
            SMTITLE_CMD=(convert -size 620x300 xc:none -font "$SM_TITLE_FONT" \
            -pointsize $SUBMENU_FONTSIZE -fill "$SM_TITLE_CLR" \
            -draw "gravity center text 2,2 \"${SM_TITLES[i]}\"" \
            -stroke "$SUBMENU_STROKE" -strokewidth 1 \
            -fill "$SM_TITLE_CLR" -stroke "$SUBMENU_STROKE" \
            -draw "gravity center text 1,1 \"${SM_TITLES[i]}\"" )
            SMTITLE_TRIM_CMD=(convert $QUALITY -trim +repage - -blur 0x0.3 \
            $WORK_DIR/title${i}_txt.png)
            SMTITLE_FADE_CMD=(composite -blend 0x${SM_TITLE_OPACITY} \
            null: - -matte)
            if [[ -n $SM_TITLE_OPACITY ]]; then
                "${SMTITLE_CMD[@]}" miff:- | "${SMTITLE_FADE_CMD[@]}" miff:- |
                "${SMTITLE_TRIM_CMD[@]}"
            else
                "${SMTITLE_CMD[@]}" miff:- | "${SMTITLE_TRIM_CMD[@]}"
            fi

            # which is harmless as they get removed, but needs to be tweaked
            if [ $SM_IMG_FMT = "jpg" ]; then
                sm_img_fmt="JPEGS"
            elif [ $SM_IMG_FMT = "png" ]; then
                sm_img_fmt="PNGS"
            else
                sm_img_fmt=${SM_IMG_FMT}s
            fi
            if $ANI_SUB_MENU; then
                JPEG2YUV_OPTS=(-n $smframes)
                PICS_IN="$WORK_DIR/animenu/%0d.$SM_IMG_FMT"
                PICS_OUT="$WORK_DIR/animenu"
                CUT_TIME=$smframes
                IMG_DIR="$WORK_DIR/animenu"
                SLEEP=1
                TOTAL_IMGS=$(($smframes * ${CHAPTERS[i]}))

            else  # not animated submenu
                JPEG2YUV_OPTS=(-n 1 -l ${SM_LOOPS[i]})
                PICS_IN="$WORK_DIR/${i}-submenu.$SM_IMG_FMT"
                PICS_OUT="$WORK_DIR/submenu"
                CUT_TIME=1
                IMG_DIR="$WORK_DIR/submenu"
                SLEEP=.5
                TOTAL_IMGS=${CHAPTERS[i]}
                PREFIX=${i}-
            fi
            if [[ -n ${GROUP_ARR[i]} ]]; then
                unset x CUT c FILE_IN
                # this will also take care of grouped USER_CHAPTERS
                BASE=$WORK_DIR/${TSET_NUM}-group
                unset grp_chapters
                get_group_chapters $i
                ! $USER_CHAPTERS && ! ((${nochapt[i]})) && CUT[0]=30 && FILE_IN[0]=${IN_FILES[i]}
                for g in ${!grp_chapters[@]}; do
                    for pt in ${grp_chapters[g]}; do
                        pnt=$(unformat_time $pt)
                        if ((g == 0)); then
                            FILE_IN+=( "${IN_FILES[i]}" )
                        elif  ((${nochapt[i]})); then
                            FILE_IN+=( ${BASE}-$((i+1))-${g}.mpg )
                        elif [[ $pnt = 0 || -z $pnt ]]; then
                            # user passed +0: no chapter point in this video
                            continue
                        else
                            FILE_IN+=( ${BASE}-$((i+1))-${g}.mpg )
                        fi
                        # do not get CUT frames if user passed +0
                        # nochapt[i] is : for -chapters 0 videos, use 00:00:00
                        if ! ((${nochapt[i]})) && \
                        { [[ $g != 0 && $pnt = 0 ]] || [[ -z $pnt ]] ; }; then
                            :
                        else
                            CUT+=( $( bc_math "$pnt * $FRAME_RATE" int) )
                        fi
                    done

                done
            elif $USER_CHAPTERS; then
                unset x CUT c_array
                # CHAPT_ARRAY is left in HH:MM:SS,HH:MM:SS format: unformat now
                c_array="${CHAPT_ARRAY[i]//,/ }"
                for v in $c_array; do
                    f=$(unformat_time $v)
                    CUT[x++]=$( bc_math "$f * $FRAME_RATE" int)
                done
            else
                # CHAPT_INTERVALS is seconds: "${VID_LEN[i]}/ ${CHAPTERS[i]}"
                counts=$(bc_math "${CHAPT_INTERVALS[i]} * $FRAME_RATE" int)
                numchpts=${CHAPTERS[i]}
                CUT=( 30 $(running_total <<< $(for ((a=0; a<numchpts; a++)); do
                echo -n "$counts ";done)) )
            fi
            for c in ${!CUT[@]}; do
                [[ -n ${CUT[c]} ]] && \
                cmd[c]=${CUT[c]}-$(bc_math "${CUT[c]} + $CUT_TIME" int)
            done
            if $USER_CHAPTERS; then
                # 1 second seek for 1st chapt (00:00:00), to avoid black frames
                cmd[0]=30-$(bc_math "30 + $CUT_TIME" int)
            elif [[ -z ${GROUP_ARR[i]} ]]; then
                # auto chapters needs the last seek removed
                key=$((${#cmd[@]} - 1))
                unset cmd[key]
            fi
            print2log ""
            print2log "Creating $TOTAL_IMGS chapter images for ${IN_FILES[i]}"
            print2log ""
            unset cf f
            for t in "${!cmd[@]}"; do
                ! $use_transcode && break # don't run block if just using ffmpeg
                # warning to ignore transcode error messages
                print_tcode_info
                if [[ -n ${GROUP_ARR[i]} ]]; then
                    CUR_FILE="${FILE_IN[cf++]}"
                else
                    CUR_FILE="${IN_FILES[i]}"
                fi
                navlog=$(readlink -f "${CUR_FILE}").nav_log
                if [[ -s $navlog ]]; then
                    NAVSEEK="--nav_seek" && NAVLOG="$navlog"
                else
                    unset NAVSEEK NAVLOG
                fi
                ff_log_tmp="$PICS_OUT/ff_log.tmp"
                tc_log_tmp="$PICS_OUT/tc_log.tmp"
                yuv_fifo="$PICS_OUT/out.yuv"
                [[ ! -p "$yuv_fifo" ]] && mkfifo "$yuv_fifo"
                # resize using ffmpeg instead of transcode
                FFMPEG_CMD=($FFmpeg $PIPE_FORMAT -i "$yuv_fifo" \
                -f image2 $VF scale=${VSIZE%x*}:${VSIZE#*x} -y "$PICS_OUT/%06d.$SM_IMG_FMT")
                TCODE_CMD=(nice transcode --progress_rate 10 \
                --write_pid $WORK_DIR/tcode$i.pid -q 1 -i "$CUR_FILE" \
                $NAVSEEK "$NAVLOG" -o "$yuv_fifo" -f \
                $FRAME_RATE -c ${cmd[t]} $EXPORT)
                print2log "Running ${TCODE_CMD[@]}"
                print2log "Running ${FFMPEG_CMD[@]}"
                "${TCODE_CMD[@]}"  2>&1 | pipe2log transcode &
                "${FFMPEG_CMD[@]}" > "$ff_log_tmp" 2>&1 &
                ffm_pid=$!
                wait_for "$WORK_DIR/tcode$i.pid"
                TCODE_PID=$(<$WORK_DIR/tcode$i.pid)
                tcode_pids="$tcode_pids $TCODE_PID"
                if [[ -n $TCODE_PID ]]; then
                    while ps -p $ffm_pid >/dev/null; do
                        wait_for "$IMG_DIR/000001.$SM_IMG_FMT"
                        sleep 1 # spinner interval
                        end=$(find "$IMG_DIR" -maxdepth 1 -name \*.$SM_IMG_FMT |
                        sort | awk -F / '{ field = $NF }; END{ print field }')
                        e=${end##*/};  e=${e%%.*}; e=${e##*0} # strip to digit
                        spin \
                          "Seeking and making $e images for chapter $((t+1)): $end"
                    done
                    total_imgs=$(find "$IMG_DIR" -name "*.$SM_IMG_FMT" | wc -l)
                    wait
                    #yecho ""
                    print2log "Created $total_imgs $sm_img_fmt of $TOTAL_IMGS"
                else
                    runtime_error "Problem creating images from the video."
                fi
                cat "$ff_log_tmp" | pipe2log ${FFmpeg##*/}
                rm -f "$ff_log_tmp"
                unset TCODE_CMD
                # transcode loops so each loop uses %06d, then moved to %08d
                if ! $ANI_SUB_MENU ; then
                    mv $WORK_DIR/submenu/000001.$SM_IMG_FMT \
                    $WORK_DIR/submenu/$(printf "%08d%s\n" $((f++)) .$SM_IMG_FMT)
                    let f+=1
                elif $ANI_SUB_MENU; then
                    u=${t/*-}; v=${t/-*}
                    # names now start with 000001.  Rename starting at 000000.
                    for ((n=1; n<smframes+1; n++)); do
                       # if [ $v -eq ${CUT[0]} ]; then
                        curimage=$WORK_DIR/animenu/$(printf \
                        "%06d%s\n" $n .$SM_IMG_FMT)
                        lastimage=$WORK_DIR/animenu/$(printf \
                        "%06d%s\n" $((n-1)) .$SM_IMG_FMT)
                        nextimage=$WORK_DIR/animenu/$(printf \
                        "%08d%s\n" $((f++ )) .$SM_IMG_FMT)
                        if [[ ! -e $curimage ]]; then
                            cp "$lastimage" "$nextimage"
                        else
                            mv "$curimage" "$nextimage"
                        fi
                        let f+=1
                    done
                fi
            done
            if ! $use_transcode; then # don't run block if using transcode
                if [[ -n ${GROUP_ARR[i]} ]]; then
                    CUR_FILE="${FILE_IN[cf++]}"
                else
                    CUR_FILE="${IN_FILES[i]}"
                fi
                ff_log_tmp="$PICS_OUT/ff_log.tmp"
                frames=$CUT_TIME

                # avconv has no 'between' expr but keep commented code below
                #frames=$((CUT_TIME - 1))
                #[[ ${FFmpeg##*/} =~ avconv ]] && frames=$CUT_TIME
                # between filter is "inclusive" so between(300, 300) is 300
                #cur_frame=${cf%-*}
                #if [[ ${FFmpeg##*/} =~ avconv ]]; then
                #else # ffmpeg
                # "select using "between" expr
                #    for fr in ${cmd[@]}; do
                #        cur_frame=${fr%-*}
                #        select1+="between(n,${cur_frame},$(( cur_frame + frames)))+"
                #    done
                #fi

                for fr in ${cmd[@]}; do
                    cur_frame=${fr%-*}
                    select1+="(gt(n,${cur_frame}))*lte(n,$(( cur_frame + frames)))+"
                done

                # remove last '+' sign
                select1=${select1%+}
                select1="'${select1}'",setpts="'N/($ff_frame_rate*TB)'"
                scale1=scale=${VSIZE%x*}:${VSIZE#*x}
                ffm_cmd=($FFmpeg -i "$CUR_FILE" -vf select="${select1}",${scale1} \
                -y "$IMG_DIR/%08d.$SM_IMG_FMT")
                print2log "Running ${ffm_cmd[@]}"
                "${ffm_cmd[@]}" > "$ff_log_tmp" 2>&1 &
                ffm_pid=$!
                while ps -p $ffm_pid >/dev/null; do
                    wait_for "$IMG_DIR/00000001.$SM_IMG_FMT"
                    sleep 1 # spinner interval
                    end=$(find "$IMG_DIR" -maxdepth 1 -name \*.$SM_IMG_FMT |
                    sort | awk -F / '{ field = $NF }; END{ print field }')
                    e=${end##*/};  e=${e%%.*}; e=${e##*0} # strip to digit
                    spin \
                      "Seeking and making $TOTAL_IMGS images for chapters: $end"
                done
                total_imgs=$(find "$IMG_DIR" -name "*.$SM_IMG_FMT" | wc -l)
                print2log "Created $total_imgs $sm_img_fmt of $TOTAL_IMGS"
                wait
                cat "$ff_log_tmp" | pipe2log ${FFmpeg##*/}
                unset select1 ffm_cmd
            fi
            # make the chapter titles if needed.  Shadow is hardcoded at #101010
            if [[ -n  ${CHAPTER_TITLES[@]} ]]; then
                echo "Making Chapter titles for Video $((i+1))"
                for ((a=0; a<${CHAPTERS[i]}; a++)); do
                    ctitle="$WORK_DIR/${TSET_NUM}-${i}-chapter${a}.png"
                    ctcmd=(convert -size 620x300 xc:none \
                    -font "$CHAPT_FONT" -pointsize ${CHAPT_FONTSIZE[i]} \
                    -fill '#101010'  -stroke '#101010' -gravity South \
                    -annotate +0+0 "${CHAPTER_TITLES[a+I]}" -fill $CHAPTER_CLR \
                    -stroke "$CHAPTER_STROKE" -strokewidth 1 \
                    -annotate +1+1 "${CHAPTER_TITLES[a+I]}")
                    ct_fade_cmd=(composite -blend 0x${CHAPTER_TITLES_OPACITY} \
                    null: - -matte)
                    ct_trim_cmd=(convert $QUALITY - -trim +repage "$ctitle")
                    if [[ -n $CHAPTER_TITLES_OPACITY ]]; then
                        "${ctcmd[@]}" miff:- | "${ct_fade_cmd[@]}" miff:- |
                        "${ct_trim_cmd[@]}"
                    else
                        "${ctcmd[@]}" miff:- | "${ct_trim_cmd[@]}"
                    fi
                    # make sure title fits
                    ctitle_dim=$(identify -ping -format %w "$ctitle")
                    if  (($ctitle_dim >= ${GEO_ARRAY[C]%x*} )); then
                        newdim=$(bc_math "${GEO_ARRAY[C]%x*} * .9" int)
                        convert $QUALITY "$ctitle" -resize ${newdim}x "$ctitle"
                    fi
                done
            fi
            if $ANI_SUB_MENU ; then
                # move submenu images to subdirs: $WORK_DIR/animenu/{0,1,2,etc}
                # or if making chapter titles, output to subdirs; rm original
                for ((a=0; a<${CHAPTERS[i]}; a++)); do
                    unset num_procs smpids curimgs
                    # 2>/dev/null to work around perplexing spawned xterm bug
                    pics=($(find $WORK_DIR/animenu/ -maxdepth 1 -name \
                    00\*.$SM_IMG_FMT|sort 2>/dev/null|
                    head -n $smframes 2>/dev/null))
                    if [[ -n  ${CHAPTER_TITLES[@]} ]]; then
                        # title the chapters for submenu if needed
                        ctitle="$WORK_DIR/${TSET_NUM}-${i}-chapter${a}.png"
                        spin "Working on Video $((i+1)): chapter $((a+1))  "
                        for f in ${pics[@]}; do
                            if [[ -s $f ]]; then
                                ((num_procs++))
                                { convert -size ${GEO_ARRAY[C]} "$f" "$ctitle" \
                                -gravity south -geometry +0+5 -compose over \
                                -composite "$WORK_DIR/animenu/$a/${f##*/}" ; } &
                                smpids="$smpids $!"
                                if ((num_procs==max_procs)); then
                                    wait $smpids 2>/dev/null
                                    unset num_procs smpids
                                fi
                                # rm -f "$f"
                            fi
                        done
                        wait && rm -f "${pics[@]}"
                    else # no chapter titles
                        # moving images from Video $((i+1)) into subdirectories
                        for f in ${pics[@]}; do
                            mv "$f" $WORK_DIR/animenu/$a
                        done
                    fi
                    unset pics
                done
                # clean up left over pics in animenu/ dir
                rm -f $WORK_DIR/animenu/*.$SM_IMG_FMT
            fi

            if $ANI_SUB_MENU; then
                $DEBUG && stime=$(date +%s)
                TOYUV_CMD=(ppmtoy4m -v 0 -n $smframes -A $PIXEL_AR -F $YUV_FR \
                -I p -S 420mpeg2 -r)
                IMGENC_CMD=($FFmpeg -f yuv4mpegpipe -i - -an $FFMPEG_OPTS \
                -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} \
                -y "$WORK_DIR/menu$i.m2v")
                yecho ""
                print2log "Running ${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo |
                ${IMGENC_CMD[@]}"
                mkfifo "$WORK_DIR/ppm.fifo" 2>/dev/null
                mkfifo "$WORK_DIR/enc.fifo" 2>/dev/null
                "${TOYUV_CMD[@]}" < "$WORK_DIR/ppm.fifo" > \
                "$WORK_DIR/enc.fifo" 2>/dev/null &
                encpids="$encpids $!"
                "${IMGENC_CMD[@]}" <  "$WORK_DIR/enc.fifo"  2>/dev/null &
                encpids="$encpids $!"
                echo
                v=${IN_FILES[i]}
                #echo "Encoding $smframes frames for "${IN_FILES[i]}"" >&2
                # make fifos for intermediary piping
                for ((f=1; f<=max_procs; f++)); do
                    [[ ! -p "$WORK_DIR/temp-${f}.ppm" ]] && \
                     mkfifo "$WORK_DIR/temp-${f}.ppm"
                done
                unset smpids  num_procs
                for ((a=1; a<$smframes; a++)); do
                    ((num_procs++))
                    out_ppm="$WORK_DIR/temp-${num_procs}.ppm" # current frame
                    for ((b=0; b<${CHAPTERS[i]}; b++)); do
                        IMGS=( "${IMGS[@]}" $(find $WORK_DIR/animenu/$b \
                        -name \*.$SM_IMG_FMT| sort 2>/dev/null | head -n $a |
                        sed -n -e "$a p") )
                    done
                    IM_CMD=(convert "${IMGS[@]}" -bordercolor '#6E6E6E' \
                    -border $THUMB_FRAME_SIZE miff:-)
                    IM_CMD1=(montage - -tile ${TILE_ARRAY[C]} \
                    -geometry ${GEO_ARRAY[C]}+5+5 -bordercolor '#101010' \
                    -mattecolor '#101010' -background none miff:-)
                    IM_CMD2=(convert \
                    $WORK_DIR/submenu$((i+1))_template.$SM_IMG_FMT \
                    $WORK_DIR/title${i}_txt.png  -gravity south \
                    -geometry +0+55 -composite - -gravity north \
                    -geometry +0+45 -composite "$out_ppm")
                    { "${IM_CMD[@]}" | "${IM_CMD1[@]}" | "${IM_CMD2[@]}" ; } \
                    2>> "$LOG_FILE" &
                    smpids="$smpids $!"
                    ppm_fifos+=("$out_ppm") # all frames waiting to be processed
                    if ((num_procs==max_procs || a == smframes-1 )); then
                        spin "\r${v##*/}: Processing frame $((a+1)) of $smframes  " >&2
                        cat "${ppm_fifos[@]}"
                        wait $smpids 2>/dev/null
                        unset smpids num_procs ppm_fifos
                    fi

                    unset IMGS TOYUV_CMD IMGENC_CMD
                done > "$WORK_DIR/ppm.fifo"
                $DEBUG && etime=$(date +%s) && get_elapsed "the submenu m2v"

                # wait for ppmtoy4m and ffmpeg to finish
                wait
                echo >&2

                unset IM_CMD IM_CMD2 d f P v

            else # not $ANI_SUB_MENU

                yecho ""
                yecho "Making montage images for "${IN_FILES[i]}""
                # just use $CHAPTERS number of images
                imgs=( $(find $WORK_DIR/submenu -name \*.$SM_IMG_FMT |
                sort| head -n $NUM_CHAPTERS) )
                # title the chapter thumbs if titles supplied
                if [[ -n  ${CHAPTER_TITLES[@]} ]]; then
                    for P in "${!imgs[@]}"; do
                    curimage=$(awk -F / '{ print $NF }' <<< "${imgs[P]}")
                    spin "\rProcessing $curimage  "
                    ctitle="$WORK_DIR/${TSET_NUM}-${i}-chapter${P}.png"
                        sm_title_cmd=(convert "${imgs[P]}" \
                        "$ctitle" -gravity south -geometry +0+5 \
                        -compose over -composite  "${imgs[P]}"  )
                        "${sm_title_cmd[@]}" | tee -a "$LOG_FILE"
                    done
                fi
                IM_CMD=(convert "${imgs[@]}" -bordercolor '#6E6E6E' \
                -border $THUMB_FRAME_SIZE miff:-)
                IM_CMD1=(montage - -tile ${TILE_ARRAY[C]} -geometry \
                ${GEO_ARRAY[C]}+5+5 -background none miff:-)
                IM_CMD2=(convert $WORK_DIR/submenu$((i+1))_template.$SM_IMG_FMT \
                $IMG_DEPTH $WORK_DIR/title${i}_txt.png  -gravity south \
                -geometry +0+55 -composite - -gravity north -geometry +0+45 \
                -composite $WORK_DIR/${i}-submenu.$SM_IMG_FMT)
                "${IM_CMD[@]}" | "${IM_CMD1[@]}" | "${IM_CMD2[@]}"
            fi
            if ! $ANI_SUB_MENU; then

                yecho ""
                yecho "Converting chapter montage of ${IN_FILES[i]}
                to m2v video format"
                IMG_STREAM_CMD1=(convert "$PICS_IN" ppm:-)
                IMG_STREAM_CMD2=(ppmtoy4m -v 0 -n ${SM_LOOPS[i]} -A $PIXEL_AR -F $YUV_FR -I p \
                -S 420mpeg2 -r)
                ENC_CMD1=($FFmpeg -f yuv4mpegpipe -i - \
                -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} $FFMPEG_OPTS \
                -y "$WORK_DIR/menu$i.m2v")
                print2log "Running ${IMG_STREAM_CMD1[@]} | ${IMG_STREAM_CMD2[@]} | \
                ${ENC_CMD1[@]}"| format_output | tee -a "$LOG_FILE" 2>&1
                "${IMG_STREAM_CMD1[@]}" | "${IMG_STREAM_CMD2[@]}" |
                "${ENC_CMD1[@]}" 2>&1|strings >> "$LOG_FILE"
            fi

            # check if m2v was created ok before proceeding
            if is_video "$WORK_DIR/menu$i.m2v"; then
                :
            else
                echo
                runtime_error  \
                "The submenu video (m2v) does not appear to have been created"
            fi
            # clean out submenu dirs of images
            echo
            print2log "Cleaning up leftover pics in $REAL_WORK_DIR/animenu"
            rm -f $WORK_DIR/submenu/*
            find $WORK_DIR/animenu/ -maxdepth 1 -type f -exec rm -f {} \;
            if $ANI_SUB_MENU; then
                find $WORK_DIR/animenu/[0-9]*/ -type f -exec rm -f {} \;
            fi
            # increment submenu titles index
            I=$((I+NUM_CHAPTERS))
        else # it is a slideshow
            # mv carousel.m2v or polaroid stack appropriately
            if $ANI_SUB_MENU; then
                cp $WORK_DIR/carousel-$((i+1)).m2v $WORK_DIR/menu${i}.m2v
            else
                yecho "Making a 'polaroid stack' of your slides"
                mk_polaroid_stack "$WORK_DIR"/${TSET_NUM}-slide_grp-$((i+1))-*.mpg &
                polaroid_pid=$!
                while ps -p $polaroid_pid >/dev/null; do
                    sleep .5
                    spin $SPINNER
                done
                echo
                IM_CMD=(convert $WORK_DIR/submenu$((i+1))_template.$SM_IMG_FMT \
                "$WORK_DIR/polaroid_stack.png" \
                -gravity north -geometry +0+45 -composite \
                $WORK_DIR/thumb_title${i}.png \
                -gravity south -geometry +0+55 -composite \
                "$WORK_DIR/Playall.png" \
                -gravity SouthEast -geometry +50+50 -composite \
                -depth 8 "$WORK_DIR/polaroid_stack${i}.ppm")
                "${IM_CMD[@]}"

                # encode to m2v
                yecho "Encoding to compliant m2v video format"
                PPM_CMD=(ppmtoy4m -v 0 -n ${SM_LOOPS[i]} -A $PIXEL_AR -I p \
                -F $YUV_FR -S 420mpeg2 -r)
                FFM_CMD=($FFmpeg $PIPE_FORMAT -i - \
                -an -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} \
                $FFMPEG_OPTS -y "$WORK_DIR/menu${i}.m2v")
                yecho "Running ${PPM_CMD[@]} | ${FFM_CMD[@]}" | format_output
                cat "$WORK_DIR/polaroid_stack${i}.ppm" |
                "${PPM_CMD[@]}" | "${FFM_CMD[@]}" 2>&1 | strings >> "$LOG_FILE"
            fi
        fi
    done
    unset IMG_STREAM_CMD1 ENC_CMD1 JPEG2YUV_OPTS
    yecho "Working on submenu audio"
    for ((s=0; s<=NUM_FILES; s++)); do
        # create audio background for either animated or plain submenus
        #yecho "Creating an audio background"
        #yecho "Working on submenu audio for "${IN_FILES[s]}""
        if $SUBMENU_AUDIO; then # user supplied audio file for ths video
            if [[ -n "$SM_AUDIO_FILE" ]]; then # user supplied "1" audio file
                COPY_AC3=(cp -v $WORK_DIR/submenu.$AUDIO_EXT \
                $WORK_DIR/menu$s.$AUDIO_EXT)
                BGAUDIO_CMD=($FFmpeg -i "$SM_AUDIO_FILE" \
                -t ${SUBMENU_AUDIOLEN[s]} -ar 48000 -acodec pcm_s16le \
                -y $WORK_DIR/submenu.wav)
            elif [[ "${SM_AUDIO[s]}" = "none" ]]; then # user asked for silence
                SUBMENU_AUDIOLEN[s]=$(stream_length "$WORK_DIR/menu$s.m2v" m2v)
                BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero $AUDIO_OPTS \
                -t ${SUBMENU_AUDIOLEN[s]} -y $WORK_DIR/menu$s.$AUDIO_EXT)
            else
                # SM_AUDIO[s] is an audio file we will process it
                # do separate wavs for each supplied audio bg for each submenu
                # again using default or given submenu length
                BGAUDIO_CMD=($FFmpeg -i "${SM_AUDIO[s]}" \
                -t ${SUBMENU_AUDIOLEN[s]} -ar 48000 -acodec pcm_s16le \
                -y $WORK_DIR/menu$s.wav)
                BGAUDIO_CMD2=($FFmpeg -i $WORK_DIR/menu$s.wav \
                $AUDIO_OPTS -y $WORK_DIR/menu$s.$AUDIO_EXT)
            fi
        else # no supplied audio for submenu so create silence
            SUBMENU_AUDIOLEN[s]=$(stream_length "$WORK_DIR/menu$s.m2v" m2v)
            BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero $AUDIO_OPTS \
            -t ${SUBMENU_AUDIOLEN[s]} -y $WORK_DIR/menu$s.$AUDIO_EXT)
        fi
        # run if wav doesn't exist, or its a slideshow
        if [[ ! -s $WORK_DIR/submenu.wav ]] || ${SLIDESHOW[s]}; then
            print2log "Running ${BGAUDIO_CMD[@]}"
            # run command, error out if problem
            ! "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/} \
            && runtime_error "Problem getting audio for the submenu"
        fi
        # convert to DVD/SVCD format as long as not "none" or single audio file
        if $SUBMENU_AUDIO \
        && [[ ! "${SM_AUDIO[s]}" = "none" && -z "$SM_AUDIO_FILE" ]]; then
            if $SM_AUDIO_FADE; then
                #TIME=$(audio_length "$WORK_DIR/menu$s.wav")
                print2log "Running:
                sox $WORK_DIR/menu$s.wav $WORK_DIR/menu$s-processed.wav fade t
                $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE"
                sox -q $WORK_DIR/menu$s.wav $WORK_DIR/menu$s-processed.wav \
                 fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE
                rm $WORK_DIR/menu$s.wav
                mv $WORK_DIR/menu$s-processed.wav $WORK_DIR/menu$s.wav
            fi
            print2log "Running ${BGAUDIO_CMD2[@]}"
            "${BGAUDIO_CMD2[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
             ((${PIPESTATUS[0]} != 0)) && runtime_error "Problem getting audio for the submenu"
            unset TIME
        fi
        # if "1" audio file, then convert it if it has not been done yet
        if [[ -n "$SM_AUDIO_FILE" \
        && ! -s $WORK_DIR/submenu-processed.wav ]]; then
            if $SM_AUDIO_FADE; then
                #TIME=$(audio_length "$WORK_DIR/submenu.wav")
                print2log "Running:
                sox $WORK_DIR/submenu.wav $WORK_DIR/submenu-processed.wav \
                fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE"

                sox -q $WORK_DIR/submenu.wav $WORK_DIR/submenu-processed.wav \
                 fade t $SM_FADE ${SUBMENU_AUDIOLEN[s]} $SM_FADE
                rm -f $WORK_DIR/submenu.wav
                cp  $WORK_DIR/submenu-processed.wav $WORK_DIR/submenu.wav
            fi
            BGAUDIO_CMD3=($FFmpeg -i $WORK_DIR/submenu.wav \
            $AUDIO_OPTS -y $WORK_DIR/submenu.$AUDIO_EXT)
            if [ -s $WORK_DIR/submenu.$AUDIO_EXT ]; then # if exists do nothing
                :
            else
                print2log "Running ${BGAUDIO_CMD3[@]}"
                "${BGAUDIO_CMD3[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
                ((${PIPESTATUS[0]} != 0)) && runtime_error "Problem getting audio for the submenu"
            fi
        fi
        # copy the final file for each submenu if only 1 supplied
        "${COPY_AC3[@]}"
        print2log "Multiplexing video and audio together"
        S=$((s + 1))
        MPLEX_CMD=(mplex -V -f $MPLEX_FORMAT -o $WORK_DIR/menu$S.mpg \
        $WORK_DIR/menu$s.$AUDIO_EXT $WORK_DIR/menu$s.m2v)
        print2log "Running: ${MPLEX_CMD[@]}"
        "${MPLEX_CMD[@]}" 2>&1 |pipe2log mplex
        ((${PIPESTATUS[0]} != 0)) && runtime_error \
          "Problem muxing audio and video with mplex"
        # remove wav to save space
        rm -f $WORK_DIR/menu$s.wav
    done
    rm -f $WORK_DIR/submenu.{wav,$AUDIO_EXT}
    rm -fr $WORK_DIR/animenu/*
fi
##############################################################################
# End of submenus                                                            #
##############################################################################

##############################################################################
# Work on main menu                                                          #
##############################################################################
if $DO_MENU; then
    yecho
    yecho "Building main menu"
    yecho
fi
if [[ -n "$BG_VIDEO" ]] && ! $QUICK_MENU; then
    if $FAST_SEEK; then
        bg_pre_seek="-ss $BG_SEEK" && unset bg_post_seek
    else
        bg_post_seek="-ss $BG_SEEK" && unset bg_pre_seek
    fi
    yecho "Getting background video from $BG_VIDEO"
    FFMPEG_CMD=($FFmpeg $bg_pre_seek -i "$BG_VIDEO" -an $bg_post_seek \
    $VF scale=$VF_SCALE -f image2 \
    -vframes $BG_VIDEO_FRAMES -y "$WORK_DIR/bg/%d.$IMG_FMT")
    print2log "Extracting/resizing background images"
    print2log "Running: ${FFMPEG_CMD[@]}"
    # Run command and check for failure
    if ! "${FFMPEG_CMD[@]}" 2>&1 |strings >> "$LOG_FILE"; then
        runtime_error "Problem creating images from the background video"
    fi
    # make sure there are enough pics to make a bg video
    IMAGES=( "${IMAGES[@]}" \
    $(find $WORK_DIR/bg -maxdepth 1 -name \*[1-9]\*.$IMG_FMT | sort) )
    last_pic=${#IMAGES[@]}
    num_bgpics=$last_pic
    next_pic=$(($last_pic + 1))
    if [ $last_pic -lt $MAX_MENU_LEN ]; then
        for ((l=next_pic; l<=MAX_MENU_LEN; l++)); do
            cp $WORK_DIR/bg/${last_pic}.$IMG_FMT $WORK_DIR/bg/$l.$IMG_FMT
        done
    fi
    unset IMAGES PICS last_pic next_pic
fi
if [[ -n "$SHOWCASE_VIDEO" ]] && $SC_THUMB; then
    if $SWITCHED && $USER_THUMBS; then
        echo "Using supplied image for showcased thumb"
    else
        echo "Getting showcase video images from $SHOWCASE_VIDEO"
    fi
    if [ "$SC_FRAMESTYLE" = "glass" ]; then
        # some vars for get_framed_pics()
        D=2
        FRAME_SIZE=$SHOWCASE_SIZE
        VOUT="png:z=7"
        MPLAYER_SEEK_VAL=$SHOWCASE_SEEK_VAL
        $SWITCHED_MODE && MPLAYER_SEEK_VAL=${SEEK_VAL[MENU_NUM-1]}
        get_framed_pics "$SHOWCASE_VIDEO"  >> "$LOG_FILE" 2>&1
        for ((i=0; i<=$FRAMES; i++)); do
            mv  "$WORK_DIR"/$(printf "%08d%s"  $((i+1)) .png) \
            "$WORK_DIR"/showcase/$(printf "%06d%s"  $((i+1)) .png) 2>/dev/null
        done
    elif [ "$SC_FRAMESTYLE" = "none" ]; then
        if $SWITCHED_MODE; then
            FFMPEG_SEEK_VAL=${SEEK_VAL[MENU_NUM-1]}
        else
            FFMPEG_SEEK_VAL=$SHOWCASE_SEEK_VAL
        fi
        if $FAST_SEEK; then
            ffm_pre_seek="-ss $FFMPEG_SEEK_VAL" && unset ffm_post_seek
        else
            ffm_post_seek="-ss $FFMPEG_SEEK_VAL" && unset ffm_pre_seek
        fi
        if $SWITCHED && $USER_THUMBS; then
            #convert ${USER_PICS[MENU_NUM-1]} -resize $SHOWCASE_SIZE \
            cp "$WORK_DIR/showcase_img.png" "$WORK_DIR/showcase/000001.png"
        else
            FFMPEG_CMD=($FFmpeg $ffm_pre_seek -i "$SHOWCASE_VIDEO" \
            $VF scale=${SHOWCASE_SIZE%x*}:${SHOWCASE_SIZE#*x} -an -vframes \
            $FRAMES $ffm_post_seek -f image2 -y "$WORK_DIR/showcase/%06d.png")
            print2log "Running: ${FFMPEG_CMD[@]}"
            SED_VAR="frame="
            #"${FFMPEG_CMD[@]}" >> "$LOG_FILE.tmp" 2>&1 &
            "${FFMPEG_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/} &
            ffm_pid=$!
            while ps -p $ffm_pid >/dev/null; do
                sleep 1
                spin $SPINNER
            done
            wait $ffm_pid
            (($?)) && runtime_error "Problem creating images from the video."

            echo
        fi
    fi
    for ((i=FIRST_PIC; i<LAST_PIC; i++)); do
        SC_PICS=( ${SC_PICS[@]} $(find $WORK_DIR/showcase -maxdepth 1 \
        -name $(printf "%06d%s"  $((i+1)) .png) ) )
    done
    $SWITCHED && $STATIC && SC_PICS=( "$WORK_DIR/showcase/000001.png" )
    if [[ "$SC_FRAMESTYLE" = "glass" ]] \
    &&  [[ -z "$ROTATE" && -z "$WAVE" ]]; then
        :
    else
        unset impids
        num_procs=0
        for p in ${!SC_PICS[@]}; do
            ((num_procs++)) # how many processes are running
            this_pic=$(sed 's,.*/,,;s/^0*//;s/.png//' <<< "${SC_PICS[p]}")
            pic="${SC_PICS[p]}"
            # if glass and either wave or rotate
            if [ "$SC_FRAMESTYLE" = "glass" ] && \
             [[ -n "$WAVE" || -n "$ROTATE" ]]; then
                { convert -size $SHOWCASE_SIZE "$pic" -background none \
                 $ROTATE $WAVE -resize $SHOWCASE_SIZE! "$pic" ; } &
            # if glass and neither wave or rotate
            elif [ "$SC_FRAMESTYLE" = "glass" ] && \
             [[ -z "$WAVE" && -z "$ROTATE" ]]; then
                :
            else # not glass
                if $SHOWCASE_3D && [[ -n $SHOWCASE_SHAPE ]]; then
                    CURVE_VARS="5 3 5 1 1"
                    unset SC_RAISE # 3D shaped thumbs have no -raise - use command below
                    . todisc-fade-routine
                    sc_3d_cmd=(convert - -write mpr:${p}img -fx A  +matte \
                    -blur 0x$( LC_ALL="C" bash -c "printf  "%.2f" \
                    $(bc_math "6.9 + .${CURVE_ARRAY[p]/.}")" ) -shade \
                    $(bc_math "115 + ${CURVE_ARRAY[p]}" int)x30 \
                    -normalize mpr:${p}img \
                    -compose Overlay -composite mpr:${p}img -matte \
                    -compose Dst_In -composite)
                else
                    sc_3d_cmd=(convert - $SC_RAISE)
                fi
                if [[ -n $SHOWCASE_SHAPE ]]; then
                    { composite -compose CopyOpacity $SHOWCASE_MASK +matte \
                    "$pic" miff:- |
                    "${sc_3d_cmd[@]}" miff:- |
                    convert $QUALITY -size $SHOWCASE_SIZE - -background none \
                    $ROTATE $WAVE -resize ${SHOWCASE_SIZE}! "$pic" ; } 2>> "$LOG_FILE" &
                else
                    { convert -size $SHOWCASE_SIZE "$pic" $SC_RAISE miff:- |
                    convert - $SHOWCASE_FRAME -background none $ROTATE $WAVE miff:- |
                    convert - $QUALITY  -resize ${SHOWCASE_SIZE}! "$pic"  ; } \
                      2>> "$LOG_FILE" &
                fi
            fi
            impids="$impids $!"
            if ((num_procs==max_procs || p >= (${#SC_PICS[@]}-1) )); then
                spin "\rProcessing frame $this_pic of $LAST_PIC  "
                wait $impids 2>/dev/null
                unset impids num_procs
            fi
        done
    fi
    # make sure showcase video finishes at the time time as other menu items
    IMAGES=( $(find $WORK_DIR/showcase -maxdepth 1 -name 00\*.png|sort) )
    last_pic=$(( ${#IMAGES[@]} - 1 ))
    num_scpics=$last_pic
    next_pic=$(($last_pic + 1))
    if [ $last_pic -lt $MAX_MENU_LEN ] && ! $STATIC; then
        for ((l=next_pic; l<=MAX_MENU_LEN; l++)); do
            cp $WORK_DIR/showcase/$( printf %06d $last_pic).png \
            $WORK_DIR/showcase/$(printf %06d $l).png
        done
    fi

fi
# ani_pics is the largest # of animated image frames. Update this value
((num_bgpics > ani_pics)) && ani_pics=$num_bgpics
((num_scpics > ani_pics)) && ani_pics=$num_scpics
unset IMAGES last_pic next_pic FFMPEG_CMD pic

yecho ""
if [[ ! "$SC_FRAMESTYLE" = "glass" && ! $TEXTMENU ]]; then
    if $SHOWCASE; then
        yecho "Processing video images"
    else
        yecho "Adding title to video images and resizing"
    fi
fi
if ! $TEXTMENU && ! $SINGLE_SLIDESHOW && $DO_MENU; then
    for ((i=0; i<=NUM_FILES; i++)); do
        if $FEATHER && $THUMBS_3D && [ "$THUMB_SHAPE" != "normal" ]; then
            unset CURVE_ARRAY CURVE_VALUES CURVE_VARS
            CURVE_VARS="5 3 5 1 1"
            . todisc-fade-routine "3 5 5 1 1"
        fi
        PICS=( "${PICS[@]}" \
        $(find $WORK_DIR/pics/$i -maxdepth 1 -name \*[0-9]\*.$IMG_FMT|sort) )
        echo
        LAST_IMG=$LAST_PIC
        ((${#PICS[@]} < LAST_PIC)) && LAST_IMG=${#PICS[@]}
        if $STATIC; then
            START_PIC=0
            LAST_IMG=1
        else
            START_PIC=$FIRST_PIC
        fi
        yecho "Working on ${#PICS[@]} images from ${IN_FILES[i]}"
        num_procs=0
        for ((p=START_PIC; p<LAST_IMG; p++)); do
            ((num_procs++))
            # only let one process use the spinner at a time
            if ((num_procs==max_procs || p==LAST_IMG-1)); then
                spin "\rProcessing frame $((p+1)) "
            fi
            unset IM_CMD6
            [[ -n ${ROTATE_ARRAY[@]} ]] && \
            THUMB_ROTATE="-background none -rotate ${ROTATE_ARRAY[i]}"
            IM_CMD=(composite -compose CopyOpacity $THUMB_MASK \
            +matte "${PICS[p]}")
            #IM_CMD01=(convert "${PICS[p]}" -background '#101010' \
            #-bordercolor "#444744" $THUMB_FRAME )
            IM_CMD01=(convert "${PICS[p]}" -background '#101010' \
            -bordercolor $THUMB_FRAME_CLR $THUMB_FRAME )
            IM_CMD02=(convert "${PICS[p]}" $RAISE)
            IM_CMD03=(composite -compose CopyOpacity $THUMB_MASK +matte -)
            IM_CMD04=(convert - -background none \
            -bordercolor $THUMB_FRAME_CLR  "$WORK_DIR/thumb_title${i}.png" \
            -gravity south -geometry +0+5 -compose over -composite)
            IM_CMD1=(convert -resize ${THUMB_SIZE}! -)
            IM_CMD2=(composite -gravity center -compose DstOver \
            $WORK_DIR/feather_mask2.png -)
            ! $USE_FEATHER_MASK && IM_CMD2=(convert -)
            IM_CMD3=(convert "${PICS[p]}" -background none -bordercolor \
            $THUMB_FRAME_CLR $THUMB_FRAME "$WORK_DIR/thumb_title${i}.png" \
            -gravity south -geometry +0+5 -compose over -composite)
            IM_CMD4=(convert -background none -bordercolor $THUMB_FRAME_CLR \
            -border $THUMB_FRAME_SIZE -)
            IM_CMD4b=(convert -background none -bordercolor none \
            $THUMB_FRAME -)
            IM_CMD5=(convert -size ${THUMB_SIZE} - $QUALITY $THUMB_ROTATE \
            -resize ${THUMB_SIZE}! "${PICS[p]}")
            IM_CMD6=(convert - -write mpr:img${p} -fx A  +matte \
            -blur 0x$( LC_ALL="C" bash -c \
            "printf "%.2f" $(bc_math "7 + .${CURVE_ARRAY[p]/.}")" )  \
            -shade $(bc_math "115 + ${CURVE_ARRAY[p]}")x30 -normalize \
            mpr:img${p} -compose Overlay -composite mpr:img${p} \
            -matte -compose Dst_In -composite)
            IM_CMD7=(convert -trim +repage - )
            # single slideshow sets DO_FRAME to false - no titles
            ! $DO_FRAME && \
            IM_CMD04=(convert -) && IM_CMD3=(convert "${PICS[p]}")
            if $FEATHER &&  [ "$THUMB_SHAPE" != "normal" ] && $THUMBS_3D; then
                CURVE_UPDATE="with -blur 0x$( LC_ALL="C" bash -c \
                "printf  "%.2f" $(bc_math "7 + .${CURVE_ARRAY[p]/.}")" ) \
                -shade $( LC_ALL="C" bash -c "printf "%.2f" \
                $(bc_math "115 + ${CURVE_ARRAY[p]}")" )x30"
            fi
            if $FEATHER; then
                if $SHOWCASE; then
                    if $THUMBS_3D; then
                        if [ "$THUMB_SHAPE" != "normal" ]; then
                            { "${IM_CMD[@]}" miff:- | "${IM_CMD2[@]}" miff:- |
                            "${IM_CMD6[@]}" miff:- |  "${IM_CMD7[@]}" miff:- |
                            "${IM_CMD5[@]}" ; } 2>> "$LOG_FILE" &
                        else # normal thumbshape, with feather and 3D
                            { "${IM_CMD02[@]}" miff:- | "${IM_CMD03[@]}" miff:- |
                            "${IM_CMD2[@]}" miff:- |"${IM_CMD7[@]}" miff:- |
                            "${IM_CMD5[@]}" ; } 2>> "$LOG_FILE" &

                        fi
                    else
                        { "${IM_CMD[@]}" miff:- | "${IM_CMD2[@]}" miff:- |
                        "${IM_CMD5[@]}" ; } 2>> "$LOG_FILE" &
                    fi
                else # not SHOWCASE
                    if $THUMBS_3D; then
                        if [ "$THUMB_SHAPE" != "normal" ]; then
                            { "${IM_CMD[@]}" miff:- | "${IM_CMD6[@]}"  miff:- |
                            "${IM_CMD1[@]}" miff:- |"${IM_CMD04[@]}" miff:- |
                            "${IM_CMD1[@]}" miff:- | "${IM_CMD2[@]}" miff:- |
                            "${IM_CMD5[@]}" ; } 2>> "$LOG_FILE" &
                        else
                            { "${IM_CMD02[@]}" miff:- | "${IM_CMD04[@]}" miff:- |
                            "${IM_CMD2[@]}" miff:- |
                            "${IM_CMD5[@]}" ; } 2>> "$LOG_FILE" &
                        fi
                    else # not 3D
                        { "${IM_CMD[@]}" miff:- | "${IM_CMD04[@]}" miff:- |
                        "${IM_CMD1[@]}" miff:- |"${IM_CMD2[@]}" miff:- |
                        "${IM_CMD5[@]}" ; } 2>> "$LOG_FILE" &
                    fi
                fi
            else # not FEATHER
                if $SHOWCASE; then # showcase but not feather
                    if [[ "$SC_FRAMESTYLE" = "glass" \
                      && -z ${ROTATE_ARRAY[@]} ]]; then
                        :
                    else
                        if $THUMBS_3D; then
                            { "${IM_CMD02[@]}" miff:- | "${IM_CMD5[@]}" ; } \
                            2>> "$LOG_FILE" &
                        else
                            { "${IM_CMD01[@]}" miff:- | "${IM_CMD5[@]}" ; } \
                            2>> "$LOG_FILE" &
                        fi
                    fi
                else # not showcase or feather
                    if $THUMBS_3D; then
                        { "${IM_CMD02[@]}" miff:- | "${IM_CMD04[@]}" miff:- |
                        "${IM_CMD4[@]}" miff:- | "${IM_CMD5[@]}" ; } \
                        2>> "$LOG_FILE" &
                    else
                        { "${IM_CMD3[@]}" miff:- | "${IM_CMD5[@]}" ; } \
                        2>> "$LOG_FILE" &
                    fi
                fi
            fi
            title_pids="$title_pids $!"
            # wait on processes to keep on or below max # of processes
            if ((num_procs >= max_procs || i == LAST_IMG)); then
                wait
                unset num_procs title_pids
            fi
            if $STATIC; then unset PICS; fi
            unset IM_CMD0 IM_CMD1 IM_CMD2 IM_CMD3 IM_CMD4 IM_CMD5 IM_CMD6
        done
        wait
        # make sure all animated thumbs finish at the same time
        if ! $STATIC; then
            IMAGES=( "${IMAGES[@]}" \
            $(find $WORK_DIR/pics/$i -maxdepth 1 -name 00\*.$IMG_FMT|sort) )
            last_pic=$(( ${#IMAGES[@]} - 1 ))
            next_pic=$(($last_pic + 1))
            if (( (last_pic - 1) < MAX_MENU_LEN )) ; then
                for ((l=next_pic; l<=MAX_MENU_LEN; l++)); do
                    cp $WORK_DIR/pics/$i/$( printf %06d $last_pic).$IMG_FMT \
                    $WORK_DIR/pics/$i/$(printf %06d $l).$IMG_FMT
                done
            fi
            unset IMAGES last_pic next_pic
        fi
        unset PICS
    done
fi
if ! $QUICK_MENU && $DO_MENU; then
    yecho ""
    yecho "Making $FRAMES final montage frame(s) and compositing onto \
    background with title"
    yecho ""
fi
if $STATIC; then
    # we have a value for MENU_AUDIOLEN AND BG_AUDIO
    if [[ -n "$BG_AUDIO" && "$BG_AUDIO" != "none" ]] && ! $MENU_FADE; then
        LOOPS=$( ${bC} <<< "$MENU_AUDIOLEN * $FRAME_RATE" 2>/dev/null)
        LOOPS=${LOOPS%.*}
    # switched menu: no bg audio or video and not menu fade
    elif $SWITCHED && [[ -z $BG_VIDEO && -z $BG_AUDIO ]] && ! $MENU_FADE; then
        LOOPS=60
    # any animation will use the full menu length
    elif [[ -n $BG_VIDEO || -n $SHOWCASE_VIDEO ]] || $MENU_FADE; then
        LOOPS=$FRAMES
    else
        # anything I've missed that is static will be 60 frames long :)
        LOOPS=60
    fi
    PPM_LOOPS=$LOOPS
fi
if ! $QUICK_MENU && $DO_MENU; then
    echo
    echo \
    "Converting images to video and encoding to $TARGET-compliant format" >&2
    # convert images to video stream and encode to dvd compliant m2v
    [[ -n $PPM_LOOPS ]] && PPM_FRAMES=$PPM_LOOPS ||
    PPM_FRAMES=$((FRAMES))
    # extra black frames for menu fade at the end (check if doing fadeout 1st)
    fadevals=( $(. todisc-fade-routine && \
        echo ${ANIMENU_ENDFRAME} ${THUMBS_FADEOUT_STARTFRAME}) )
    (( ${fadevals[0]} > ${fadevals[1]} )) && $MENU_FADE && \
        PPM_FRAMES=$((PPM_FRAMES+18))
    TOYUV_CMD=(ppmtoy4m -v 2 -n $PPM_FRAMES -A $PIXEL_AR -I p -F $YUV_FR \
    -S 420mpeg2 -r)
    IMGENC_CMD=($FFmpeg $PIPE_FORMAT -i - -an \
    -r $ff_frame_rate $VF scale=${VF_SCALE},${ASPECT} $FFMPEG_OPTS \
    -y $WORK_DIR/intro.m2v)
    #print2log "Running ${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo | ${IMGENC_CMD[@]}" |
    print2log "Running:"
    echo "${TOYUV_CMD[@]} < $WORK_DIR/ppm.fifo | ${IMGENC_CMD[@]}" | \
    while read -r line; do
        print2log "$line"
    done
    mkfifo "$WORK_DIR/ppm.fifo" 2>/dev/null
    mkfifo "$WORK_DIR/enc.fifo" 2>/dev/null
    "${TOYUV_CMD[@]}" < "$WORK_DIR/ppm.fifo" > "$WORK_DIR/enc.fifo" \
     2>> "${LOG_FILE}.1-tmp" & #/dev/null &
    encpids="$encpids $!"
    "${IMGENC_CMD[@]}" <  "$WORK_DIR/enc.fifo"  2>> "${LOG_FILE}.2-tmp" & #/dev/null &
    encpids="$encpids $!"
fi
# make intermediary fifos for images.  They will get catted to ppm.fifo
for ((n=1; n<=max_procs; n++)); do
    [[ ! -e "$WORK_DIR/temp-${n}.ppm" ]] && mkfifo "$WORK_DIR/temp-${n}.ppm"
done
# TODO use exec 2>> "$LOG_FILE" to save lines
if $MENU_FADE && ! $QUICK_MENU; then
    . todisc-fade-routine
    # ani_frames is the last animated frame
    ((THUMBS_FADEIN_ENDFRAME > ani_pics )) && \
     ani_frames=$THUMBS_FADEIN_ENDFRAME || ani_frames=$ani_pics
    yecho >&2
    yecho "Creating background fade first" >&2
    yecho >&2
    if [ -z "$BG_VIDEO" ]; then
        for ((frame=0; frame<=ANIMENU_ENDFRAME; frame++)); do
            # copy template for fade out beginning and end frames
            cp $WORK_DIR/pics/template1.png $WORK_DIR/bg/$(($frame + 1)).png
        done
    fi
    unset bgfade_pids num_procs
    for ((frame=0; frame<=BG_FADEIN_ENDFRAME; frame++)); do
        ((num_procs++))
        D=`get_bg_opacity`
        composite -dissolve $D \
        $WORK_DIR/bg/$(($frame + 1)).png $WORK_DIR/black.ppm \
        $WORK_DIR/bg/$(($frame + 1)).png &
        bgfade_pids="$bgfade_pids $!"
        if ((num_procs >= max_procs || frame == BG_FADEIN_ENDFRAME)); then
            wait $bgfade_pids 2>/dev/null
            unset bgfade_pids num_procs
        fi
    done
    unset bgfade_pids num_procs
    for ((frame=BG_FADEOUT_STARTFRAME; frame<=BG_FADEOUT_ENDFRAME; frame++)); do
        #((num_procs++))
        D=`get_bg_opacity`
        composite -dissolve $D $WORK_DIR/bg/$frame.$IMG_FMT \
        $WORK_DIR/black.ppm $WORK_DIR/bg/$frame.$IMG_FMT
        #bgfade_pids="$bgfade_pids $!"
        #if ((num_procs >= max_procs || frame == BG_FADEOUT_ENDFRAME)); then
        #    wait $bgfade_pids
        #    unset bgfade_pids num_procs
        #fi
    done
    unset num_procs
    for ((frame=0; frame<ANIMENU_ENDFRAME; frame++)); do
        ((num_procs++)) # how many processes are running
        out_ppm="$WORK_DIR/temp-${num_procs}.ppm" # current frame
        # set dissolve vars from todisc-fade-routine functions
        BC=$(get_title_opacity)
        B=$(awk -F ':' '{print $1'}<<<$BC)
        C=$(awk -F ':' '{print $2'}<<<$BC)
        S=$(get_thumb_opacity)
        # experimental: allow using -menu-fade with static thumbs
        $STATIC && FRAME_NUM=0 || FRAME_NUM=$((frame + 1))

        for ((cnt=0; cnt<=NUM_FILES; cnt++)); do
            ANI_PICS=( "${ANI_PICS[@]}" $(find $WORK_DIR/pics/$cnt  \
            -name $(printf "%06d%s"  $FRAME_NUM .$IMG_FMT) ) )
        done
        if $SHOWCASE; then
            if ! $TEXTMENU; then
                for ((i=0; i<${#ANI_PICS[@]}; i++)); do
                    sc_cmd=( ${sc_cmd[@]} ${SHOWCASE_THUMB_PAGES[i]} \
                    "${ANI_PICS[i]}")
                done
            fi
            if $SC_THUMB; then
                SC_VIDEO_CMD="$SC_IMG_PAGE \
                "$WORK_DIR"/showcase/$(printf "%06d%s"  $(($frame + 1)) .png)"
            else
                unset SC_VIDEO_CMD
            fi
        fi
        $TEXTMENU && unset sc_cmd
        ! $TEXTMENU && MOSAIC="-mosaic"
        BG_PIC=$(find $WORK_DIR/bg -name $((frame + 1)).$IMG_FMT)
        # create the montage from the images in each video dir
        MONTAGE_CMD=(convert  -size $VIDSIZE -background none \
        ${sc_cmd[@]} $SC_IMG_CMD $MOSAIC)
        MONTAGE_CMD01=(convert  -size $VIDSIZE xc:none -background none \
        ${sc_cmd[@]} $SC_VIDEO_CMD $MOSAIC)
        MONTAGE_CMD02=(convert -size $VIDSIZE -background none \
        - ${sc_thumb_title_cmd[@]} -mosaic)
        MONTAGE_CMD03=(convert -size $VIDSIZE -background none \
        ${sc_thumb_title_cmd[@]} -mosaic)
        MONTAGE_CMD1=(montage "${ANI_PICS[@]}" -tile ${TILE_ARRAY[NUM_FILES]} \
        -geometry ${THUMB_SIZE}${MTG_GEO} -background none)
        #  dissolve the finished montages onto the background
        MONTAGE_CMD2=(composite -dissolve $S -gravity $BUTTON_GRAVITY \
        -geometry +${XGEO}+${YGEO} - $WORK_DIR/bg/$((frame + 1)).$IMG_FMT \
        -background none)
        MONTAGE_CMD2c=(composite -size $VIDSIZE -background none \
        -gravity NorthWest  -dissolve $S - $WORK_DIR/bg/$((frame + 1)).$IMG_FMT \
        -background none)
        # if MIST is called for, this dissolves the mist onto the background
        MONTAGE_CMD3=(composite -dissolve $B -gravity $TITLE_GRAVITY \
        -geometry ${mist_xoffset}${mist_yoffset} $WORK_DIR/white.png -)
        # finally, dissolve title onto MIST (or background) and pipe out a ppm
        # write out a ppm if montages are static from here on in
        if (( frame == ani_frames)) || ((frame == BG_FADEIN_ENDFRAME )); then
            write_ppm=(-write "$WORK_DIR/montage-${frame}.ppm")
            copy_ppm="$WORK_DIR/montage-${frame}.ppm"
        else
            unset write_ppm
        fi
        MONTAGE_CMD4=(composite -dissolve $C -gravity $TITLE_GRAVITY \
        -geometry ${title_xoffset}${title_yoffset} $WORK_DIR/title_txt.png - \
        -background none -depth 8 ppm:- )
        if $PLAYALL ; then
            MONTAGE_CMD5=(composite -dissolve $S -gravity SouthEast -geometry \
            $PLAYALL_BTN_OFFSETS "$WORK_DIR/Playall.png" - \
            -background none miff:-)
        else
            MONTAGE_CMD5=(cat)
        fi
        if $TITLESET_MODE && ! $VMGM_ONLY && $VMGM_MENU; then
            MONTAGE_CMD6=(composite -dissolve $S -gravity $RTN_BTN_GRAVITY \
            -geometry $RTN_BTN_OFFSETS "$WORK_DIR/Main.png" - \
            -background none miff:-)
        else
            MONTAGE_CMD6=(cat)
        fi
        MONTAGE_CMD7=(convert - -depth 8  "${write_ppm[@]}" "$out_ppm")
        # -menu-fade working with -static
        $SINGLE_SLIDESHOW && \
        IM_CMD1=(convert "$WORK_DIR/polaroid_stack.png" miff:- )
        # -text-menu can have showcase image so don't unset if it is present
        if $TEXTMENU && [[ -z "$SHOWCASE_IMG" ]]; then
            unset MONTAGE_CMD
            MONTAGE_CMD=( "${MONTAGE_CMD03[@]}" )
        fi
        # if doing less animated frames than the total # of frames
        # break from the loop and use ppmtoy4m to repeat last frame
        # if we are not doing a fadeout, or if doing fadeout, cat the last
        # animated frame in the loop till we reach the start of the fadeout
        # if we have a static background, then cat frames from the frame the bg
        # finishes fading in, to the frame where the title starts to fade in

        # make sure we don't start copying frames if fadein is not finished
        #f=$((frame + 2))
        f=$((frame + 1))
        if ((frame==ani_frames+1)); then
            cat_fifos=false
            endframe=$THUMBS_FADEOUT_STARTFRAME
            copy_frames=$((endframe - f))
            # no fadeout, just let ppmtoy4m repeat last frame till done
            if ((ANIMENU_ENDFRAME<=THUMBS_FADEOUT_STARTFRAME)); then
                spin  "\rEncoding frames $f to $endframe  " >&2
                if [[ -n ${ppm_fifos[@]} ]]; then
                    cat "${ppm_fifos[@]}"
                fi
                echo >&2
                break
            else
                # cat any backlog of backgrounded processes
                if [[ -n ${ppm_fifos[@]} ]]; then
                    cat "${ppm_fifos[@]}"
                fi
                if [[ -s "$copy_ppm" ]]; then
                    # endframe is the last unchanging frame in the video
                    for ((i=0; i<copy_frames; i++)); do
                        spin  "\rEncoding frames $f to $endframe  " >&2
                        cat "$copy_ppm"
                    done
                    total_frames=$((total_frames+copy_frames))
                    unset ppm_fifos num_procs
                    frame=$endframe
                fi
            fi
        elif [[ -z $BG_VIDEO ]] && ((frame==BG_FADEIN_ENDFRAME+1)); then
            # cat any backlog of backgrounded processes
            if [[ -n ${ppm_fifos[@]} ]]; then
                cat "${ppm_fifos[@]}"
            fi
            cat_fifos=false
            t_frames=$(( (TITLE_FADEIN_STARTFRAME) - (BG_FADEIN_ENDFRAME+1)))
            total_frames=$((total_frames+t_frames))
            for ((i=BG_FADEIN_ENDFRAME+1;
             i<TITLE_FADEIN_STARTFRAME; i++)); do
                spin "Encoding frames $f to $((TITLE_FADEIN_STARTFRAME-1)) " >&2
                cat "$copy_ppm"
            done
            rm -f "$WORK_DIR/montage.ppm" >&2
            unset ppm_fifos num_procs
            frame=$((TITLE_FADEIN_STARTFRAME-1))
        else
            ppm_fifos+=("$out_ppm") # all frames waiting to be processed
            cat_fifos=:
        fi

        # pipe all of above commands if using MIST
        if $MIST && $cat_fifos; then
            if $SHOWCASE; then
                if [[ -n "$SHOWCASE_VIDEO" ]]; then
                    { "${MONTAGE_CMD01[@]}" miff:-|"${MONTAGE_CMD02[@]}" miff:- |
                    "${MONTAGE_CMD2c[@]}" miff:- |"${MONTAGE_CMD3[@]}" miff:- |
                    "${MONTAGE_CMD5[@]}" | "${MONTAGE_CMD6[@]}" |
                    "${MONTAGE_CMD4[@]}" | "${MONTAGE_CMD7[@]}" ; } \
                    2>> "$LOG_FILE" &
                else # not SHOWCASE_VIDEO (SHOWCASE_IMG)
                    { "${MONTAGE_CMD[@]}" miff:- | "${MONTAGE_CMD02[@]}" miff:- |
                    "${MONTAGE_CMD2c[@]}" miff:- | "${MONTAGE_CMD5[@]}" |
                    "${MONTAGE_CMD6[@]}" | "${MONTAGE_CMD3[@]}" miff:- |
                    "${MONTAGE_CMD4[@]}" | "${MONTAGE_CMD7[@]}" ; } \
                    2>> "$LOG_FILE" &
                fi
            else # not SHOWCASE
                { "${MONTAGE_CMD1[@]}" miff:- | "${MONTAGE_CMD2[@]}" miff:- |
                "${MONTAGE_CMD3[@]}" miff:- | "${MONTAGE_CMD5[@]}" |
                "${MONTAGE_CMD6[@]}" | "${MONTAGE_CMD4[@]}" |
                "${MONTAGE_CMD7[@]}" ; } 2>> "$LOG_FILE" &
            fi
        elif ! $MIST && $cat_fifos; then  # no mist
            if $SHOWCASE; then
                if [[ -n "$SHOWCASE_VIDEO" ]]; then
                    { "${MONTAGE_CMD01[@]}" miff:-|"${MONTAGE_CMD02[@]}" miff:- |
                    "${MONTAGE_CMD2c[@]}" miff:- |"${MONTAGE_CMD5[@]}" |
                    "${MONTAGE_CMD6[@]}" | "${MONTAGE_CMD4[@]}" |
                    "${MONTAGE_CMD7[@]}" ; } 2>> "$LOG_FILE" &
                else
                    { "${MONTAGE_CMD[@]}" miff:- | "${MONTAGE_CMD02[@]}" miff:- |
                    "${MONTAGE_CMD2c[@]}" miff:- |"${MONTAGE_CMD5[@]}" |
                    "${MONTAGE_CMD6[@]}" | "${MONTAGE_CMD4[@]}" |
                    "${MONTAGE_CMD7[@]}" ; } 2>> "$LOG_FILE" &
                fi
            else
                { "${MONTAGE_CMD1[@]}" miff:- | "${MONTAGE_CMD2[@]}" miff:- |
                "${MONTAGE_CMD5[@]}" | "${MONTAGE_CMD6[@]}" |
                "${MONTAGE_CMD4[@]}"  | "${MONTAGE_CMD7[@]}" ; } \
                2>> "$LOG_FILE" &
            fi
        fi
        impids="$impids $!"
        rmpics+=( "$WORK_DIR/bg/$((frame+1)).$IMG_FMT" )
        rmpics+=( "$WORK_DIR"/showcase/$(printf "%06d%s"  $(($frame + 1)) .png) )
        # we reuse thumbs for static so don't rm ANI_PICS
        ! $STATIC && rmpics+=( "${ANI_PICS[@]}" )

        ((total_frames++))
        unset ANI_PICS sc_cmd writeppm
        if ((num_procs==max_procs || frame >= ANIMENU_ENDFRAME-1)) && $cat_fifos; then
            spin  "\rProcessing frame $(($frame + 1))  " >&2
            cat "${ppm_fifos[@]}"
            wait $impids 2>/dev/null
            rm -f "${rmpics[@]}"
            unset num_procs ppm_fifos impids rmpics
        fi
    done > "$WORK_DIR/ppm.fifo"
elif ! $MENU_FADE && ! $QUICK_MENU && $DO_MENU; then # Do not do menu fade
    if $TRANSPARENT; then # non transparent -showcase-* uses this block too
        num_procs=0
        for (( count=1; count<=$FRAMES; count++)); do
            ((num_procs++)) # how many processes are running
            out_ppm="$WORK_DIR/temp-${num_procs}.ppm" # current frame
            ppm_fifos+=("$out_ppm") # all frames waiting to be processed
            if ((num_procs==max_procs || count==FRAMES)); then
                spin "\rProcessing frame $count  " >&2
            fi
            # experimental: allow using -menu-fade with static thumbs
            $STATIC && FRAME_NUM=0 || FRAME_NUM=$((count - 1))

            for ((cnt=0; cnt<=NUM_FILES; cnt++)); do
                ANI_PICS=( "${ANI_PICS[@]}" $(find $WORK_DIR/pics/$cnt  \
                -name $(printf "%06d%s"  $FRAME_NUM .$IMG_FMT) ) )
            done
            for ((f=0; f<${#ANI_PICS[@]}; f++)); do
                sc_cmd=( ${sc_cmd[@]} \
                ${SHOWCASE_THUMB_PAGES[f]} "${ANI_PICS[f]}")
            done
            SC_VIDEO_CMD="$SC_IMG_PAGE \
            "$WORK_DIR"/showcase/$(printf "%06d%s"  $count .png)"
            $STATIC && [[ -z $SHOWCASE_VIDEO ]] && SC_VIDEO_CMD="$SC_IMG_PAGE \
            "$WORK_DIR"/showcase_img.png"
            $TEXTMENU && unset sc_cmd

            IM_CMD0=(convert  -size $VIDSIZE "$WORK_DIR/pics/template.png" \
            ${sc_cmd[@]} $SC_IMG_CMD -mosaic)
            IM_CMD01=(convert  -size $VIDSIZE xc:none -background none \
            ${sc_cmd[@]} $SC_VIDEO_CMD ${sc_thumb_title_cmd[@]} -mosaic)
            # dissolve piped images onto bgimage
            IM_CMD02=(composite -gravity NorthWest -dissolve $OPACITY - \
            $WORK_DIR/pics/template.png)
            # dissolve piped images onto bgvideo
            IM_CMD03=(composite -size $VIDSIZE -background none \
            -gravity NorthWest  -dissolve $OPACITY - \
            $WORK_DIR/bg/$count.$IMG_FMT -background none)
            # dissolve titles onto bgvideo
            IM_CMD04=(convert -size $VIDSIZE -background none \
             - ${sc_thumb_title_cmd[@]} -mosaic)
            IM_CMD05=(convert  -size $VIDSIZE xc:none -background none \
            ${sc_cmd[@]} $SC_IMG_CMD ${sc_thumb_title_cmd[@]} -mosaic)
            IM_CMD1=(montage ${ANI_PICS[@]} -tile ${TILE_ARRAY[NUM_FILES]} \
            -geometry ${THUMB_SIZE}${MTG_GEO} -background none miff:-)
            IM_CMD2=(composite -dissolve $OPACITY \
            -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} - \
            $WORK_DIR/pics/template1.png -background none miff:-)
            IM_CMD2b=(composite -dissolve $OPACITY \
            -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} - \
            $WORK_DIR/bg/$count.$IMG_FMT -background none miff:-)
            IM_CMD3=(composite -dissolve 30 -gravity $TITLE_GRAVITY \
            -geometry ${mist_xoffset}${mist_yoffset} \
            $WORK_DIR/white.png - miff:-)
            IM_CMD4=(convert - -depth 8 $WORK_DIR/title_txt.png -gravity \
            $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
            -composite "${ADD_RTN_BTN[@]}" "${ADD_PLAYALL_BTN[@]}" \
            "$out_ppm" )
            $SINGLE_SLIDESHOW && \
            IM_CMD1=(convert "$WORK_DIR/polaroid_stack.png" miff:- )
            if $MIST; then
                # showcase, mist, showcase-video
                if $SHOWCASE && [[ -n "$SHOWCASE_VIDEO" ]]; then
                    if test -n "$BG_VIDEO"; then # also bgvideo
                        { "${IM_CMD01[@]}" miff:- |
                       "${IM_CMD03[@]}" miff:- |  "${IM_CMD3[@]}" |
                        "${IM_CMD4[@]}" ; } &
                    else # not with bgvideo
                        { "${IM_CMD01[@]}" miff:- |
                        "${IM_CMD02[@]}" -depth 8 "$out_ppm" ; } &
                    fi
                # showcase, mist, showcase-image
                elif $SHOWCASE && [[ -n "$SHOWCASE_IMG" ]]; then
                    # showcase, mist, showcase-image with bgvideo
                    if test -n "$BG_VIDEO"; then
                        { "${IM_CMD05[@]}" miff:- |
                        "${IM_CMD03[@]}" miff:- |"${IM_CMD3[@]}" |
                        "${IM_CMD4[@]}" ; } &
                    else # showcase, mist, showcase-image, not bgvideo
                        { "${IM_CMD0[@]}" -depth 8 "$out_ppm" ; } &
                    fi
                elif ! $SHOWCASE; then
                    if test -n "$BG_VIDEO"; then
                        { "${IM_CMD1[@]}" | "${IM_CMD2b[@]}" | "${IM_CMD3[@]}" |
                        "${IM_CMD4[@]}" ; } 2>> "$LOG_FILE" &
                    else
                    { "${IM_CMD1[@]}" | "${IM_CMD2[@]}" | "${IM_CMD3[@]}" |
                    "${IM_CMD4[@]}" ; } 2>> "$LOG_FILE" &
                    fi
                fi
            else # showcase, no mist, showcase-video
                if $SHOWCASE && [[ -n "$SHOWCASE_VIDEO" ]]; then
                    if test -n "$BG_VIDEO"; then
                        # with bgvideo
                        { "${IM_CMD01[@]}" miff:- |
                        "${IM_CMD03[@]}" miff:- | "${IM_CMD4[@]}" ; } \
                        2>> "$LOG_FILE" &
                    else # no bgvideo
                        { "${IM_CMD01[@]}" $pngpipe |
                        "${IM_CMD02[@]}"  $pngpipe | "${IM_CMD4[@]}" ; } \
                        2>> "$LOG_FILE" &
                    fi
                elif $SHOWCASE && [[ -n "$SHOWCASE_IMG" ]]; then
                # showcase, no mist, showcase-image
                    if test -n "$BG_VIDEO"; then # with bgvideo
                        { "${IM_CMD05[@]}" miff:- |
                        "${IM_CMD03[@]}" miff:- | "${IM_CMD4[@]}" ; } \
                        2>> "$LOG_FILE" &
                    else # no bgvideo
                        { "${IM_CMD0[@]}" -depth 8 "$out_ppm" ; } \
                        2>> "$LOG_FILE" &
                    fi
                elif ! $SHOWCASE; then
                    if test -n "$BG_VIDEO"; then
                        { "${IM_CMD1[@]}" |
                         "${IM_CMD2b[@]}" | "${IM_CMD4[@]}" ; } \
                        2>> "$LOG_FILE" &
                    else
                        { "${IM_CMD1[@]}" | "${IM_CMD2[@]}" |
                        "${IM_CMD4[@]}" ; } 2>> "$LOG_FILE" &
                    fi
                fi
            fi
            impids="$impids $!"
            # remove images after they are used each cat run
            rmpics+=( "$WORK_DIR"/showcase/$(printf "%06d%s"  $count .png) )
            rmpics+=( "$WORK_DIR/bg/$count.$IMG_FMT" )
            # we reuse thumbs for static so don't rm ANI_PICS
            ! $STATIC && rmpics+=( "${ANI_PICS[@]}" )
            if ((num_procs==max_procs || count >= FRAMES)); then
                cat "${ppm_fifos[@]}"
                wait $impids 2>/dev/null
                rm -f "${rmpics[@]}"
                unset num_procs ppm_fifos impids rmpics
                # remove now unneeded images to keep disc usage low
            fi
            unset ANI_PICS sc_cmd
        done > "$WORK_DIR/ppm.fifo"
    else # Not transparent (non transparent showcase uses transparent block ^^)
        C=$((${CHAPTERS[s]} - 1))
        num_procs=0
        for (( count=1; count <=FRAMES; count++)); do
            ((num_procs++)) # how many processes are running
            out_ppm="$WORK_DIR/temp-${num_procs}.ppm" # current frame
            ppm_fifos+=("$out_ppm") # all frames waiting to be processed
            if ((num_procs==max_procs || count==FRAMES)); then
                spin -ne "\rProcessing frame $count  " >&2
            fi
            $STATIC && FRAME_NUM=0 || FRAME_NUM=$((count - 1))

            for ((cnt=0; cnt<=NUM_FILES; cnt++)); do
                ANI_PICS=( "${ANI_PICS[@]}" \
                $(find $WORK_DIR/pics/$cnt \
                -name $(printf "%06d%s" $FRAME_NUM  .$IMG_FMT) ) )
            done
            # make final montages and composite onto grey background with title
            IM_CMD0=(montage ${ANI_PICS[@]} -tile ${TILE_ARRAY[NUM_FILES]} \
            -geometry ${THUMB_SIZE}${MTG_GEO} -background none miff:-)
            IM_CMD1=(convert $WORK_DIR/pics/template1.png \
            -  -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} \
            -composite miff:-)
            IM_CMD2=(convert $WORK_DIR/bg/$count.$IMG_FMT \
            -  -gravity $BUTTON_GRAVITY -geometry +${XGEO}+${YGEO} \
            -composite miff:-)
            IM_CMD3=(composite -dissolve 30 -gravity $TITLE_GRAVITY -geometry \
            ${mist_xoffset}${mist_yoffset} $WORK_DIR/white.png - miff:-)
            IM_CMD4=(convert -depth 8 - $WORK_DIR/title_txt.png -gravity \
            $TITLE_GRAVITY -geometry ${title_xoffset}${title_yoffset} \
            -composite "${ADD_RTN_BTN[@]}" "${ADD_PLAYALL_BTN[@]}" "$out_ppm" )
            $SINGLE_SLIDESHOW && \
            IM_CMD0=(convert "$WORK_DIR/polaroid_stack.png" miff:- )

            if test -n "$BG_VIDEO"; then
                if $MIST; then
                    { "${IM_CMD0[@]}" | "${IM_CMD2[@]}" | "${IM_CMD3[@]}" |
                    "${IM_CMD4[@]}" ; } 2>> "$LOG_FILE" &
                else # no mist
                    { "${IM_CMD0[@]}" | "${IM_CMD2[@]}" | "${IM_CMD4[@]}" ; } \
                    2>> "$LOG_FILE" &
                fi
            else # no bg video
                if $MIST; then
                    { "${IM_CMD0[@]}" | "${IM_CMD1[@]}" | "${IM_CMD3[@]}" |
                    "${IM_CMD4[@]}" ; } 2>> "$LOG_FILE" &
                else # no mist
                    { "${IM_CMD0[@]}" | "${IM_CMD1[@]}" | "${IM_CMD4[@]}" ; } \
                    2>> "$LOG_FILE" &
                fi
            fi
            impids="$impids $!"
            rmpics+=( "$WORK_DIR/bg/$count.$IMG_FMT" )
            # static reuses the thumbs so don't rm each cat run
            ! $STATIC && rmpics+=( "${ANI_PICS[@]}" )
            if ((num_procs==max_procs || count >= FRAMES)); then
                cat "${ppm_fifos[@]}"
                wait $impids 2>/dev/null
                rm -f "${rmpics[@]}"
                unset num_procs ppm_fifos impids rmpics
            fi
            unset ANI_PICS
        done > "$WORK_DIR/ppm.fifo"
    fi
fi # end making final montages
# wait for ppmtoy4m and ffmpeg to finish
wait
# send formated ffmpeg output to log
if [[ -e "${LOG_FILE}.1-tmp" ]]; then
    cat "${LOG_FILE}.1-tmp" | pipe2log ppmtoy4m
    rm -f "${LOG_FILE}.1-tmp"
fi
if [[ -e "${LOG_FILE}.2-tmp" ]]; then
    cat "${LOG_FILE}.2-tmp" | pipe2log ${FFmpeg##*/}
    rm -f "${LOG_FILE}.2-tmp"
fi

if ! $QUICK_MENU && $DO_MENU; then
    echo
    print2log "Cleaning up montage images"
    rm -f $WORK_DIR/animenu/*.$IMG_FMT
    rm -f $WORK_DIR/animenu/*.png
fi
# check if m2v was created ok before proceeding
if $DO_MENU; then
    if ! is_video "$WORK_DIR/intro.m2v"; then
        echo
        runtime_error  "The menu video file has not been created !"
    fi
fi
if $DO_MENU; then
    MENU_ATIME=$(stream_length "$WORK_DIR/intro.m2v" m2v)
    $SWITCHED && MENU_ATIME=${MENU_LEN[MENU_NUM-1]}
fi
# use mplayer to dump audio if mplayer used for video
# but first check if audio same file as video and its not a static menu
if [[ $SC_FRAMESTYLE = "glass" && $BG_AUDIO = $SHOWCASE_VIDEO ]]; then
    ! $STATIC && USE_MPLAYER_4AUDIO=:
fi
BG_AUDIO_LENGTH="-t $MENU_ATIME"
# audio background for main menu #
if $DO_MENU; then
    if [[ -z "$BG_AUDIO" || "$BG_AUDIO" = "none" ]]; then # use silence
        ! $SWITCHED && AUDIO_FADE=false # do not fade silence
        BGAUDIO_CMD=($FFmpeg -f s16le -ar 48000 -i /dev/zero -ar 48000 \
        -t $MENU_ATIME -ac 2 -acodec pcm_s16le -y $WORK_DIR/intro.wav)
        print2log "Running ${BGAUDIO_CMD[@]}"
        "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}
        if [[ ! -s "$WORK_DIR/intro.wav" ]]; then
            runtime_error "There was a problem creating menu background silence"
        fi
    # Make sure file exists
    elif test ! -s "$BG_AUDIO"; then
        runtime_error "Cannot find background audio file: $BG_AUDIO"
    else # audio supplied: convert to wav then later to dvd format
        # TODO if ! $BG_AUDIOVIDEO_FILE; then  # check if same file and if so
        # decode the audio and jpegs in one step above, and skip this block
        if $USE_MPLAYER_4AUDIO; then
            pipe_prog=mplayer
            BGAUDIO_CMD=(mplayer -quiet -vc null -vo null -ss \
            $MPLAYER_SEEK_VAL -ao pcm:waveheader:file="$WORK_DIR/intro.wav" \
            -endpos $MENU_ATIME  "$BG_AUDIO")
        else
            pipe_prog=${FFmpeg##*/}
            BGAUDIO_CMD=($FFmpeg -y \
            -i "$BG_AUDIO" -vn -ss $BG_AUDIO_SEEK $BG_AUDIO_LENGTH -ar 48000 \
            -acodec pcm_s16le $WORK_DIR/intro.wav)
        fi
        print2log "Running ${BGAUDIO_CMD[@]}"
        "${BGAUDIO_CMD[@]}" 2>&1 |pipe2log $pipe_prog
        ((${PIPESTATUS[0]} != 0)) && runtime_error \
          "Problem creating wav file during background audio processing"

        if $AUDIO_FADE; then  # bgaudio supplied and audio fade selected
            WAV_TIME=$(stream_length "$WORK_DIR/intro.wav" audio)
            print2log "Running:
            sox $WORK_DIR/intro.wav $WORK_DIR/intro-processed.wav fade t
            $FADE $WAV_TIME $FADE"
            sox $WORK_DIR/intro.wav \
            $WORK_DIR/intro-processed.wav fade t $FADE $WAV_TIME $FADE 2>&1 | pipe2log sox
            $KEEP_FILES || rm $WORK_DIR/intro.wav
            mv $WORK_DIR/intro-processed.wav $WORK_DIR/intro.wav
        fi
    fi
    unset BGAUDIO_CMD TIME

    # convert to proper audio format
    BGAUDIO_CMD=($FFmpeg -i $WORK_DIR/intro.wav \
    $AUDIO_OPTS -y $WORK_DIR/intro.$AUDIO_EXT)
    echo "Running "${BGAUDIO_CMD[@]}"" | pipe2log
    "${BGAUDIO_CMD[@]}" 2>&1 | pipe2log ${FFmpeg##*/}

     ! [[ -s $WORK_DIR/intro.$AUDIO_EXT ]] && runtime_error
    unset BGAUDIO_CMD
    $KEEP_FILES || rm -f "$WORK_DIR/intro.wav"
    print2log "Multiplexing main menu audio and video together"
    # mplex main menu audio and video together
    INTRO_MPLEX_CMD="mplex -V -f $MPLEX_FORMAT -o $WORK_DIR/intro.mpg \
      $WORK_DIR/intro.$AUDIO_EXT $WORK_DIR/intro.m2v"
    print2log "Running: $INTRO_MPLEX_CMD"
    ${INTRO_MPLEX_CMD[@]} 2>&1 |pipe2log mplex
    ((${PIPESTATUS[0]} != 0)) && runtime_error \
      "Problem muxing the menu video and audio with mplex"  

    if $SWITCHED_MODE || $SWITCHED_MENUS; then
        echo "Copying the menu mpeg" |pipe2log
        if [[ $MENU_NUM -ne 1 ]]; then
            cp -v "$REAL_WORK_DIR/intro.mpg" \
              "$BASEDIR/${TSET_NUM}-${MENU_NUM}intro.mpg"
        else
            cp -v  "$REAL_WORK_DIR/intro.mpg"  \
              "$REAL_WORK_DIR/${TSET_NUM}-${MENU_NUM}intro.mpg"
        fi
        sleep 2
        if $SWITCHED_MODE; then
            $KEEP_FILES && mv -v "$REAL_WORK_DIR" \
              "$BASEDIR"/TITLESET${TSET_NUM}-MENU${MENU_NUM}
            ( KEEP_FILES=false && cleanup )
            exit
        fi
    fi
    if $SWITCHED_MENUS; then
        print2log "Running spumux to create navigation buttons."
        for ((i=1; i<=${#FILES[@]}; i++)); do
            MENU_FILE="$BASEDIR/animenu${TSET_NUM}-${i}.mpg"
            print2log "Running spumux $SPUMUX_XML \
              < $REAL_WORK_DIR/${TSET_NUM}-${i}intro.mpg > $MENU_FILE"
            spumux "$SPUMUX_XML" < "$WORK_DIR/${TSET_NUM}-${i}intro.mpg" \
              > "$MENU_FILE" 2>> "${LOG_FILE}.tmp"
            wait
            [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log spumux
            rm -f ${LOG_FILE}.tmp
            check_menufile
        done
    fi
fi
if ! $SWITCHED_MENUS && ! $SWITCHED_MODE; then
    print2log "Running spumux $SPUMUX_XML < $WORK_DIR/intro.mpg > $MENU_FILE"
    spumux "$SPUMUX_XML" < $WORK_DIR/intro.mpg > "$MENU_FILE" 2>> "${LOG_FILE}.tmp"
    wait
    [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log spumux
    rm -f ${LOG_FILE}.tmp
    check_menufile
fi
if $SUB_MENU; then
    echo "Creating submenus" | pipe2log
    print2log "Running spumux to create navigation buttons"
    for ((x=1; x<=V_TOTAL; x++)); do
        print2log "Running spumux "$WORK_DIR/submenu${x}_spumux.xml" < \
        $WORK_DIR/menu${x}.mpg > \
        $(sed 's/\(.*\)menu/\1Menu/' <<< $WORK_DIR/menu${x}.mpg)"|fold -bs
        spumux "$WORK_DIR/submenu${x}_spumux.xml" < \
        $WORK_DIR/menu${x}.mpg > \
        $(sed 's/\(.*\)menu/\1Menu/' <<< $BASEDIR/${TSET_NUM}-menu${x}.mpg) \
        2>> "${LOG_FILE}.tmp"
        wait
        [[ -e ${LOG_FILE}.tmp ]] && cat "${LOG_FILE}.tmp" | pipe2log spumux
        rm -f ${LOG_FILE}.tmp
        
    done
fi
if $TITLESET_MODE; then
    $KEEP_FILES && mv -v "$REAL_WORK_DIR" "$BASEDIR"/TITLESET${TSET_NUM}
fi

if $AUTHOR && ! $VMGM_ONLY && ! $DO_TITLESETS && ! $SWITCHED_MODE; then
    yecho "Running dvdauthor to create the DVD filesystem"
    dvdauthor -x "$DVDAUTHOR_XML" 2>&1  | pipe2log dvdauthor
    if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
        dvdauthor_error
    fi
    #strings "$LOG_FILE.tmp" >> "$LOG_FILE" && rm -f "$LOG_FILE.tmp"
fi
print2log "Cleaning up unwanted files in $REAL_WORK_DIR"
find "$WORK_DIR"/ -name '*.$IMG_FMT' ! -name preview.$IMG_FMT -exec rm -f {} \; \
> /dev/null 2>&1
rm -fr "$WORK_DIR/animenu" "$WORK_DIR/pics" "$WORK_DIR/submenu"
$VMGM_ONLY && $KEEP_FILES && mv -v "$REAL_WORK_DIR" "$BASEDIR"/VMGM
if ! $VMGM_ONLY && ! $SWITCHED_MODE && ! $TITLESET_MODE && ! $DO_TITLESETS; then
    thanks_goodbye
    $BURN && burn_disc
fi
! $DO_TITLESETS && cleanup

