# DVDShrink 2.6/BatchRip 2.6
# Script functions
#
# This is the functions file for dvdshrink 2.6.This file should 
# be in the same directory as the script itself and should have 
# at least 644 permisions.

# A lot of the functions here appear arduous but it's for a reason.
# Instead of calling external programs to do the work of the
# script (grep, awk, bc etc) I've gone the route of keeping as
# much as possible 'in-shell'. This speeds up thing quite sig-
# nifigantly at the sake of portability (bash IS required).
######################################################

# The long-help synopsis. Shown if we call the script with the
# --long-help option.
#-----------------------------------------------------
function usage_long {
clear
cat << ENDUSE
DVDShrink $VERSION - $DATE
---------------------------
Command synopsis
---------------------------
Usage: dvdshrink [options]

-A | --authoronly
    The script will do everything but burn the DVD. The authored DVD
    will be availabe in $WORKDIR/BUILD

-B | --noburn
    The script will force AUTOBURN=0. If both -b and -B are issued then
    the script will force AUTOBURN=0 and you will be prompted for a
    blank DVD.

-D | --nodeletefiles
    Force do not remove working files. Ignores the settings in the
    .dvdshrinkrc file. Equivalent to RMFILES=0 If both -d and -D are
    issued then the script will force RMFILES=0 and files will not
    be deleted during execution.

-F | --forceburn
    If this option is issued, it expects that there are two devices
    and that there is already a blank in the writer and the source
    in the reader and will burn one way or the other.

-I | --info
    Display some information about the source DVD.

-K | --noshrink
    Don't shrink the video stream. This means that if it's bigger
    than the space available on the blank DVD things will get ugly.
    
-L | --listall
    Acts as if the options '-t list -a list -u list' issued.

-M | --bigmpegonly
    Create an MPEG2 file only. The video stream will NOT be shrunk.

-O | --saveiso
    Create an ISO image along with burning the new DVD

-S | --bigstreamonly
    Create the audio and video streams then exit. The video stream
    will NOT be compressed.

-T | --showtitles
    Show a list of the titles on the DVD with channel/frame information.
 
-V | --showvalues
    The script will do nothing but show you it's setup. All of the
    variables that it needs to run will be printed. Use this switch
    if you are over-riding the defaults to check that your command-
    line is correct.
           
-a | --audio <num|list>
    The audio stream to rip (default 0). Generally, the default audio
    stream is the one you want. If there are different languages on
    the DVD you'll have to select the appropriate audio stream. Use
    '-a l' to show a list.

-b | --burn
    Force auto-burn the DVD. This ignores the values in the configur-
    ation file and will tell the script to auto-burn to the blank 
    DVD. Equivalent to setting AUTOBURN=1 in the .dvdshrinkrc file.
    If -b and -B are both issued then the script will force AUTOBURN=0
    and you will be prompted for a disk at the end of execution.

-c | --configure
    Runs the script configuration. 

-d | --deletefiles
    Force remove working files. Ignores the settings in the 
    .dvdshrinkrc file. Equivalent to RMFILES=1. If both -d and
    -D are issued then the script will force RMFILES=0 and files
    will not be deleted during execution.

-e | --episodes
    For 'episodic' DVDs, how many per new DVD

-i | --isoonly
    Don't burn the DVD but create an ISO image ready for burning.
    Overrides any of the burn switches or entries in .dvdshrinkrc.
    This will automatically set AUTOBURN to 0 over-riding the
    defaults from .dvdshrinkrc and the -b argument.

-k | --shrinkfactor <value>
    Use your own custom 'shrink' factor. While the script will cal-
    culate one that works, you may want more or less depending on
    your needs. You can enter one here.
    
-l | --deletelogs
    Delete the log files in your home directory after a successful
    copy.
-m | --mpegonly

    Proceed as far as the creation of the remuxed MPEG2 file and
    stop at that point.

-o | --isodir <dir>
    Specify where to save ISO images

-p | --project <name>
    The script usually assigns it's own project name from the volume
    id of the DVD. If you wish to you can assign your own.

-r | --readdevice </dev/showrestartvars>
    The read device of the DVD reader. On single device systems this
    will be /dev/dvd. Test as above.
    
-s | --streamonly
    Create the ripped and shrunk video stream, the audio stream and
    exit.

-t | --title <num|list>
    The title number on the DVD (default 1). Most DVDs have the most
    chapters in the main title, some are different.Use 'vobcopy -I'
    to check the DVD and set -t <num> appropriately or issue '-t list'
    for a list of titles on the DVD.

-u | --subtitle <num|list>
    The subtitle stream to rip from the DVD. Use '-u list' to see a list
    of tracks to chose from.

-v | --version
    Show the version information and exit.
 
-w | --writedevice </dev/showrestartvars>
    The device of the DVD burner. Depending on where the device
    is on the machine or if it is the only DVD device this could
    be /dev/dvd. To check put a DVD in the drive and run your
    favourite movie player telling it to play the DVD. If the 
    play the DVD. If the player errors then the other device is
    /dev/dvd.
    
-h | --help
    The short help screen.
    
--restart
    If the script should error out you can restart it from where it left
    off by giving the script this option.
    
--jumpin
    If the script should error out AND you've checked the output and it
    looks good (happens with multiplexing at times) you can issue this
    option and jump back in starting at the NEXT command sequence.
    
--long-help
    This expanded help screen.
    
Some options preclude others. If you have asked for a partial run (say
you want only the streams) then things like AUTOBURN are disabled etc.
    
ENDUSE
}

# The short help synopsis is shown if we call the script with
# the -h option or we give it some wacky value that it can't
# figure out.
#---------------------------------------------------
function usage {
   echo -e "\033[1mUsage:\033[0m"
   echo "dvdshrink [options]"
   echo "    -A|--authoronly            Don't burn, just author"
   echo "    -B|--noburn                Force no auto-burn"   
   echo "    -D|--nodeletefiles         Force no file cleanup" 
   echo "    -F|--forceburn             Don't prompt... just burn"  
   echo "    -I|--info                  DVD Information"   
   echo "    -K|--noshrink              Don't shrink the video stream"
   echo "    -L|--listall               Prompt for title, audio and subtitles"
   echo "    -M|--bigmpegonly           Create un-shrunk MPEG2 file only"
   echo "    -O|--saveiso               Create an ISO along with the new DVD"
   echo "    -S|--bigstreamonly         Create un-shrunk streams only"  
   echo "    -T|--showtitles            Show the titles on the DVD"
   echo "    -V|--showvalues            Variable check"
   echo "    -a|--audio <num|list>      The audio stream to rip"
   echo "    -b|--burn                  Force auto-burn"
   echo "    -c|--configure             Re-configure the script"
   echo "    -d|--deletefiles           Force file cleanup" 
   echo "    -e|--episodes <num>        Episodes per DVD"  
   echo "    -i|--isoonly               ISO only"
   echo "    -k|--shrinkfactor <val>    Set your own re-quantization factor"
   echo "    -l|--deletelogs            Delete logs"
   echo "    -m|--mpegonly              Create a shrunk MPEG2 only"
   echo "    -o|--isodir <dir>          Where to save ISO images"
   echo "    -p|--project <name>        Project name"
   echo "    -r|--readdevice <dev>      The read device"   
   echo "    -s|--streamonly            Exit after extracting streams"
   echo "    -t|--title <num|list>      The title to rip"
   echo "    -u|--subtitle <num|list>   The subtitle stream to rip"
   echo "    -v|--version               Show version and exit"
   echo "    -w|--writedevice <dev>     The write device"
   echo "    -h|--help                  This help synopsis"
   echo "    --restart                  Restart from where the script errored"
   echo "    --jumpin                   Restart from after the script errored"
   echo "    --long-help                Expanded help information"
}

# Just a translation from 1|0 to Yes|No
#---------------------------------------------------
function yesno {
   if (($1)); then echo "Yes"; else echo "No"; fi
}

# Cleanup and exit
#---------------------------------------------------
function doexit {
   RET=$1
   if [ -e $PIDFILE ]; then rm -f $PIDFILE; fi
   if ((! $RET && $DELETELOGS)); then rm -f $LOGFILE; fi
   if ((! $BATCH)); then echo -e "\n   \033[1mThank you for using OzWare!\033[0m\n"; fi
   pauseprompt
   exit $RET
}

# Just checks for a yes or no answer
#---------------------------------------------------
function getyn {
   case $1 in
      y|Y)  return 0;;
      *)    return 1;;
   esac
}

# If we've called the script with the -s option it means
# 'just show me what you're going to use'. This function prints
# out the values the script will use
#---------------------------------------------------
function showvalues {
   clear
   echo -e "\033[1mDVDShrink $VERSION run-time settings check\033[0m\n"
   echo -e "\033[1mProject settings\033[0m"
   echo "   Project name              $PROJNAME"
   echo "   Write Device              $WDEVICE"
   echo "   Read Device               $RDEVICE"
   echo "   Title to rip              $TITLE"
   echo "   Audio stream to rip       $AUDIO"
   if (($ADDTITLES)); then echo "   Subtitle stream to rip    $SUBTITLE"; fi
   echo -e "\n\033[1mExecution flags\033[0m"
   echo "   Re-quantize video?        "`yesno $SHRINK`
   echo -n "   Shrink factor             "
   if ((${MYSHRINK//\./})); then echo $MYSHRINK; else echo "Automatic"; fi
   echo "   Auto remove files?        "`yesno $RMFILES`
   echo "   Create streams only?      "`yesno $STREAMONLY`
   echo "   Create big streams only?  "`yesno $BIGSTREAMONLY`
   echo "   Create MPEG2 only?        "`yesno $MPEGONLY`
   echo "   Create big MPEG2 only?    "`yesno $BIGMPEGONLY`
   echo "   Author DVD only?          "`yesno $AUTHORONLY`
   echo "   Create ISO only?          "`yesno $ISOONLY`  
   echo "   Save ISO with burn?       "`yesno $SAVEISO`
   echo "   Auto-burn new DVD?        "`yesno $AUTOBURN`   
   echo -e "\n\033[1mProject directories and files\033[0m"
   echo "   Base directory            $BASEDIR"
   echo "   Working directory         $WORKDIR"
   echo "   DVD build directory       $WORKDIR/BUILD"
   echo "   M2V filename              $VIDEOFILE"
   echo "   AC3 filename              $AUDIOFILE"
   if (($ADDTITLES)); then echo "   Subtitle filename         $SUBFILE"; fi
   if (($SHRINK)); then echo "   Shrunken M2V filename     $SHRNKFILE"; fi
   echo -n "   Final MPEG2 filename      "
   if (( $BIGSTREAMONLY || $STREAMONLY )); then echo "None. Streams only!"
   else echo $MPGFILE; fi
   echo
   echo -n "Use these values? [y/n]             "
   read USYN
   if ! getyn $USYN; then doexit 0
   else
      banner
      showsynopsis
   fi
}

# Simple grep replacement
#---------------------------------------------------
function teststring {
   VAR=${1%%$2*}
   if [ "$VAR" = "$1" ]; then echo 0; else echo 1; fi 
}

# Simple case-insensitive grep replacement
#---------------------------------------------------
function testistring {
   INP=`echo $1 | tr 'a-z' 'A-Z'`
   TST=`echo $2 | tr 'a-z' 'A-Z'`
   VAR=${INP%%$TST*}
   if [ "$VAR" = "$INP" ]; then echo 0; else echo 1; fi 
}

# Show the elapsed time from the beginning of execution.
# Some of us are interested in things like this.
#---------------------------------------------------
function elapsedtime {
   ESEC=$(($2-$1))
   HR=$(($ESEC/3600))
   MIN=$(($ESEC%3600/60))
   SEC=$(($ESEC%3600%60))
   if [ $HR  -lt 10 ]; then HR="0"$HR; fi
   if [ $MIN -lt 10 ]; then MIN="0"$MIN; fi
   if [ $SEC -lt 10 ]; then SEC="0"$SEC; fi
   ELAPSED="[$HR:$MIN:$SEC]"   
}

# Test command-line arguments for validity. This just checks
# for the non-existance of values where one is needed by the 
# script (ie: -p with no name supplied).
#---------------------------------------------------
function testarg {
   BADARG=0
   if [ -z "$1" ]; then BADARG=1
   elif ((`teststring "$1" "-"`)); then BADARG=1; fi
}

# If there's an error in a command-line option... tell us
# then call 'usage' and exit. It gives us which option was bad
# and what was expected.
#---------------------------------------------------
function argerror {
   echo -e "\nERROR! No $1 specified with $2 option\n"
   if [ $PROGRAM  = "DVDSHRINK" ]; then usage; else busage; fi
   doexit 1
}

# The main error trap information thingy. This just tells us that
# one of the commands returned a non-zero value and then tells us
# which command it was. This way we can try to figure things out
# and hopefully fix them so we can re-run the script with the 
# --restart option.
#---------------------------------------------------
function errortrap {
   ERRCODE=$1
   ERROR='Unknown'
   CMDRUN='Unknown'
   ERRFILE=$DEBUGFILE
   echo "Error!"
   case $ERRCODE in
      2)          # Errors in the extraction function
                  killall tcextract
                  rm -f *.?fifo
                  ERROR="tccat reported an error copying title!"
                  CMDRUN="$TCCMD";;

      3)          # Errors in re-quantifying (resizing) the video
                  ERROR="tcrquant reported an error re-sizing MPEG2!" 
                  CMDRUN="$TQCMD";;

      4)          # Errors in re-multiplexing
                  ISERR=1
                  MSIZE=`stat -c %s $MPGFILE`
                  if (($MSIZE)); then
                     ASIZE=`stat -c %s $AUDIOFILE`
                     VSIZE=`stat -c %s $VIDEOFILE`
                     OSIZE=$(($ASIZE+$VSIZE))
                     OLDFS=$IFS
                     IFS=$'\n'
                     for LINE in `cat $DEBUGFILE`; do
                        if ((`teststring "$LINE" '%d'`)); then
                           if [ $MSIZE -gt $OSIZE ]; then
                              ISERR=0
                           fi
                        fi
                     done
                     IFS=$OLDIFS
                  fi
                  if [ $ISERR -eq 1 ]; then
                     ERROR="mplex reported an error re-multiplexing the MPEG2!" 
                     CMDRUN="$MPCMD" 
                  fi;;
      5a)         # Errors in the checking of the generated XML file for invalid entries
                  ERROR="CheckXML (internal) created a bad SPUMUX file"
                  CMDRUN="checkxml (internal function)"
                  ERRFILE='none';;

      5b)         # Errors in creating subtitle images
                  ERROR="subtitle2pgm reported an error creating subtitle images" 
                  CMDRUN="$SBCMD" ;;

      5c)         # Errors in re-multiplexing in the subtitles
                  ERROR="spumux reported an error muxing subtitles" 
                  CMDRUN="$SPCMD";;

      6a)         # Errors in generating the new DVD structure on the hard drive
                  ERROR="dvdauthor reported an error building the DVD structure!" 
                  CMDRUN="$DGCMD";;

      6b)         # Errors in authoring the new DVD
                  ERROR="dvdauthor reported an error building the DVD on disk!"
                  CMDRUN="$DACMD";;

      6c)         # Errors in creating a table of contents
                  ERROR="dvdauthor reported an error writing the TOC!"
                  CMDRUN="$DTCMD";;

      7)          # Errors in creating an ISO image
                  ERROR="mkisofs reported an error creating the ISO!" 
                  CMDRUN="$MICMD";;

      8)          # Error in reading the source audio/video sync
                  ERROR="CheckAVSync (internal) reported an error reading title!"
                  CMDRUN="tccat -i /dev/dvd2 -T $TITLE,-1 > $WORKDIR/test.vob 2>$DEBUGFILE &";;

      9)          # Unknown file system error (or other)
                  ERROR="Linux reported a file system error (permissions?)"
                  ERRFILE='none';;

      10)         # Error in burning the new DVD
                  ERROR="growisofs reported an error writing the new DVD!"
                  CMDRUN="$GRCMD";;

      11)         # Error in reading the source DVD volume ID
                  ERROR="dd could not read the Volume ID from the DVD!"
                  CMDRUN="dd if=$RDEVICE bs=1 skip=32808 count=32"
                  ERRFILE='none';;

      *)          ERROR="An unknown error occurred!"
                  ERRFILE='none'
                  WriteToLog "Unknown error trapped" 1;;
   esac

   # If we actually HAVE an error then we'd better generate some log entries
   # and some on-screen gibberish to tell us (or try to tell us) what barfed.

   if [ "$ERROR" != 'Unknown' ]; then
      WriteToLog "$CMDRUN failed!" 1
      WriteToLog "$ERROR" 0
      WriteToLog "Run terminated!" 0
      if ((! $BATCH)); then
         echo
         echo -e "   \033[1mDVDShrink has failed!\033[0m"
         echo -e "   \033[1mError:\033[0m"
         echo "      -> $ERROR"
         echo -e "   \033[1mCommand run:\033[0m"
         echo "      -> $CMDRUN"
         echo
         echo "   Check all your files etc. If it appears that the problem is"
         echo "   ephemeral restart the script with 'dvdshrink --restart'"
         echo
         if [ $ERRFILE != 'none' ]; then
            echo -e "   \033[1mEnd of command output\033[0m"
            echo -e "   ---------------------------------------\n"
            tail -n 5 $ERRFILE
            echo
         fi
         echo "   See the log file at $LOGFILE for more information."
         echo -e "   Exiting!\n"
      fi

      # If an actual error file has been generated then we'll spin the last
      # five lines on-screen. Perhaps this will help but the whole file is
      # available for perusal.

      if [ $ERRFILE != 'none' ]; then
         WriteToLog "  " 0
         WriteToLog "Output of debug file" 0
         WriteToLog "  " 0
         cat $ERRFILE >> $LOGFILE
      fi
      doexit 1                
   fi
}

# If we are not in batch mode and are in GUI mode then
# prompt us to a keystroke to close the terminal and exit
#---------------------------------------------------
function pauseprompt {
   if ((! $BATCH && $GUI)); then 
      echo -en "\nHit any key to close terminal and exit!\n"
      read
   fi
}

# Just writes the date/time and some information to the
# run log file.
#---------------------------------------------------
function WriteToLog {
      ADDDT=$2
      if (($ADDDT)); then
         echo -n `date +"%D %H:%M:%S"`      >> $LOGFILE
         echo "    $1"                      >> $LOGFILE
      else
         echo -e "                     $1"  >> $LOGFILE
      fi
}

# Configure the script (Creates ~/.dvdshrinkrc)
#---------------------------------------------------
function sconfigure {
   if [ -e ~/.dvdshrinkrc ]; then rm -f ~/.dvdshrinkrc; fi
   cWDEVICE=/dev/dvd
   cRDEVICE=/dev/dvd
   cBASEDIR=/tmp
   cSPEED=1
   cRMFILES=0
   cAUTOBURN=0
   cTERMINAL="konsole"
   cDELETE=0

   echo -e "   \033[1mDVDShrink Configuration\033[0m\n"
   
   # If we have more than one DVD device then we'll want the script to know
   # about both of them. This allows promptless copying. Remeber that we want
   # a device name in here, NOT a mountpoint. 
   
   echo -n "   Do you have more than one DVD device? [y/n]      "
   read MDYN
   if [ -z $MDYN ]; then MDYN=n; fi
   if getyn $MDYN; then
      MULTIDRIVE=1
      echo -n "   Enter the device of the reader (/dev/hd?)        "
      read RDEVICE
      if [ -z $RDEVICE ]; then RDEVICE=$cRDEVICE
         echo -e "   ----> Using default \033[1m$cRDEVICE\033[0m"
      fi
      echo -n "   Enter the device of the burner (/dev/hd?)        "
      read WDEVICE
      if [ -z $WDEVICE ]; then WDEVICE=$cWDEVICE
         echo -e "   ----> Using default \033[1m$cWDEVICE\033[0m"
      fi
   else
      MULTIDRIVE=0
      echo -n "   Enter the DVD device (/dev/dvd)                  "
      read WDEVICE
      if [ -z $WDEVICE ]; then WDEVICE=$cWDEVICE
         echo -e "   ----> Using default \033[1m$cWDEVICE\033[0m"
      fi
      RDEVICE=$WDEVICE
   fi

   # Check that the devices are actually a block device and not a mountpoint
   
   while [ ! -b $RDEVICE ]; do
      banner
      echo "   The read device entered is not a block device"
      echo -n "   Enter the device of the reader (/dev/dvd)        "
      read RDEVICE
   done
   
   while [ ! -b $WDEVICE ]; do
      banner
      echo "   The write device entered is not a block device"
      echo -n "   Enter the device of the writer (/dev/dvd)        "
      read WDEVICE
   done
   
   echo "WDEVICE=$WDEVICE"       > ~/.dvdshrinkrc
   echo "RDEVICE=$RDEVICE"       >> ~/.dvdshrinkrc
   echo "MULTIDRIVE=$MULTIDRIVE" >> ~/.dvdshrinkrc

   # Enter the burn speed we want to use. Growisofs will detect the
   # default maximum speed of a blank, but a lot of times we want to
   # slow down the process.

   echo -n "   Enter the burn speed                             "
   read SPEED
   if [ -z $SPEED ]; then SPEED=$cSPEED
      echo -e "   ----> Using default speed \033[1m$cSPEED\033[0m"
   fi
   echo "SPEED=$SPEED" >> ~/.dvdshrinkrc

   # We need two directories specified; one for the working files
   # and one for ISO image storage. Remember that you'll want a 
   # minimum of 2X the size of what you're copying in the working
   # directory and at least 4.7G in the ISO directory.
   
   echo -n "   Enter a LARGE directory to keep working files    "
   read BASEDIR
   if [ -z $BASEDIR ]; then BASEDIR=$cBASEDIR
      echo -e "   ----> Using default base directory \033[1m$cBASEDIR\033[0m"
   fi
   if [ ! -d $BASEDIR ]; then
      echo -n "$BASEDIR does not exist! Create it? (y/n)        "
      read DYN
      if getyn $DYN; then mkdir -p $BASEDIR; fi
   fi
   echo "BASEDIR=$BASEDIR" >> ~/.dvdshrinkrc
   
   echo -n "   Enter a LARGE directory to save ISO images to    "
   read ISODIR
   if [ -z $ISODIR ]; then ISODIR=$cISODIR; fi
   if [ ! -d $ISODIR ]; then 
      echo -n "$ISODIR does not exist! Create it? (y/n)      "
      read IYN
      if getyn $IYN; then mkdir -p $ISODIR; fi
   fi
   echo "ISODIR=$ISODIR" >> ~/.dvdshrinkrc

   # To save space we can tell the script to remove working files
   # as they're no longer needed. This works fine until something
   # barfs, then you might have to start over again (rarely).

   echo -n "   Remove working files as we go? [y/n]             "
   read RMFILES
   if [ -z $RMFILES ]; then
      RMFILES=$cRMFILES
      echo -e "   ----> Using default value \033[1m$cRMFILES\033[0m"
   else
      if getyn $RMFILEs; then RMFILES=1; else RMFILES=0; fi
   fi
   echo "RMFILES=$RMFILES" >> ~/.dvdshrinkrc

   # Here we set whether we want a burn to automatically start when 
   # things are ready. Actually, it still prompts you but you can set
   # the --forceburn option to bypass the prompt.
   
   echo -n "   Automatically start burn when done? [y/n]        "
   read AUTOBURN
   if [ -z $AUTOBURN ]; then 
      AUTOBURN=$cAUTOBURN
      echo -e "   ----> Using default value \033[1m$cAUTOBURN\033[0m"
   else
      if getyn $AUTOBURN; then AUTOBURN=1; else AUTOBURN=0; fi
   fi
   echo "AUTOBURN=$AUTOBURN" >> ~/.dvdshrinkrc

   # The script generates a log file for each title ripped, here we can
   # specify whether we want these deleted on success.

   echo -e "\n   Log files will be written to your home directory for each"
   echo "   rip performed. Do you want these files deleted at the com-"
   echo -en "   pletion of a successful rip? (y/n)               "
   read DELETELOGS
   if [ -z $DELETELOGS ]; then
      DELETELOGS=0
      echo -e "   ----> Using default value \033[1m$cDELETE\033[0m"
   else
      if getyn $DELETELOGS; then DELETELOGS=1; else DELETELOGS=0; fi
   fi
   echo "DELETELOGS=$DELETELOGS" >> ~/.dvdshrinkrc

   # For use with the Gtk2 graphical interface we need to know which
   # terminal you want to use. Just select one.
   
   echo -e "   Enter the console to use in X mode\n"
   echo "      1. Konsole (default)"
   echo "      2. Gnome-Terminal"
   echo "      3. Eterm"
   echo "      4. Xterm"
   echo "      5. RXvt"
   echo -e "      6. None\n"
   
   echo -n "   Enter your selection                             "
   read TERML
   if [ -z $TERML ]; then 
      TERMINAL=$cTERMINAL
      echo "   ----> Using default terminal $cTERMINAL"
   elif [ $TERML -eq 1 ]; then TERMINAL="konsole"
   elif [ $TERML -eq 2 ]; then TERMINAL="gnome-terminal"
   elif [ $TERML -eq 3 ]; then TERMINAL="eterm"
   elif [ $TERML -eq 4 ]; then TERMINAL="xterm"
   elif [ $TERML -eq 5 ]; then TERMINAL="rxvt"
   else TERMINAL="none"; fi
   
   echo "TERMINAL=$TERMINAL" >> ~/.dvdshrinkrc   

   # Ok, we're done. If this is the first time we've run the script then
   # we can just continue on. If we're re-configuring we should restart
   # the script.
         
   if (($FIRSTTIME)); then
      echo -e "\n   \033[1mConfiguration complete!\033[0m\n"
      echo -n "   Do you wish to run the script now? (y/n)         "
      read RYN
      case $RYN in 
         y|Y)     . ~/.dvdshrinkrc
                  if [ $PROGRAM = "DVDSHRINK" ]; then banner; fi;;
         *)       doexit 0;;
      esac
   else
      echo -e "\n   \033[1mRe-configuration complete!\033[0m\n\n   Hit any key to exit then restart the script!"
      read JUNK
      doexit 0
   fi
}

# Create a project name based on the volume id of the DVD.
# Of course, this can be over-ridden with the -p option.
#-----------------------------------------------------
function getprojname {
   if [ $SELPROJ = 'none' ]; then
      PROJNAME=`dd if=$RDEVICE bs=1 skip=32808 count=32 2> /dev/null`
      if (($?)); then errortrap 11; fi
      PROJNAME=${PROJNAME// /}
      if [ -z $PROJNAME ]; then 
         PROJNAME="MOVIE"
      fi
   else
      PROJNAME=$SELPROJ
      PROJNAME=${PROJNAME// /_}
   fi
   LOGFILE=~/$PROJNAME.log
}

# All of the needed variables that the script uses are written to
# a variable holding file in case we have an abend and need to 
# fix something and rerun the script with the --restart option.
#-----------------------------------------------------
function writevarfile {
   echo "WDEVICE=$WDEVICE"                     >  $VARFILE
   echo "RDEVICE=$RDEVICE"                     >> $VARFILE
   echo "RMFILES=$RMFILES"                     >> $VARFILE
   echo "AUTOBURN=$AUTOBURN"                   >> $VARFILE
   echo "AUDIO=$AUDIO"                         >> $VARFILE
   echo "TITLE=$TITLE"                         >> $VARFILE
   echo "SUBTITLE=$SUBTITLE"                   >> $VARFILE
   echo "ALANG=$ALANG"                         >> $VARFILE
   echo "SLANG=$SLANG"                         >> $VARFILE   
   echo "PROJNAME=$PROJNAME"                   >> $VARFILE
   echo "CHAPFILE=$CHAPFILE"                   >> $VARFILE
   echo "WORKDIR=$WORKDIR"                     >> $VARFILE
   echo "VIDEOFILE=$VIDEOFILE"                 >> $VARFILE
   echo "SHRNKFILE=$SHRNKFILE"                 >> $VARFILE
   echo "AUDIOFILE=$AUDIOFILE"                 >> $VARFILE
   echo "SUBFILE=$SUBFILE"                     >> $VARFILE
   echo "MPGFILE=$MPGFILE"                     >> $VARFILE
   echo "MUXFILE=$MUXFILE"                     >> $VARFILE
   echo "VFIFO=$VFIFO"                         >> $VARFILE
   echo "AFIFO=$AFIFO"                         >> $VARFILE
   echo "SFIFO=$SFIFO"                         >> $VARFILE
   echo "CMDFILE=$CMDFILE"                     >> $VARFILE
   echo "VARFILE=$VARFILE"                     >> $VARFILE
   echo "INFOFILE=$INFOFILE"                   >> $VARFILE
   echo "ISOONLY=$ISOONLY"                     >> $VARFILE
   echo "SHRINK=$SHRINK"                       >> $VARFILE
   echo "STREAMONLY=$STREAMONLY"               >> $VARFILE
   echo "BIGSTREAMONLY=$BIGSTREAMONLY"         >> $VARFILE
   echo "MPEGONLY=$MPEGONLY"                   >> $VARFILE
   echo "BIGMPEGONLY=$BIGMPEGONLY"             >> $VARFILE
   echo "RMFILES=$RMFILES"                     >> $VARFILE
   echo "ADDTITLES=$ADDTITLES"                 >> $VARFILE
   echo "MYSHRINK=$MYSHRINK"                   >> $VARFILE
   echo "AUTHORONLY=$AUTHORONLY"               >> $VARFILE
   echo "DELETELOGS=$DELETELOGS"               >> $VARFILE
   
   WriteToLog "Project variables" 0
   WriteToLog "-----------------------------------------------\n" 0

   OLDIFS=$IFS
   IFS=$'\n'
   for LINE in `cat $VARFILE`; do WriteToLog "$LINE" 0; done
   IFS=$OLDIFS
}

# Set some variables and write them to the variable holding file
# The file exists so we can do a --restart with the correct values.
#-----------------------------------------------------
function setfiles {
   WORKDIR=$BASEDIR/$PROJNAME                  # Working directory
   VIDEOFILE=$WORKDIR/$PROJNAME.m2v            # MPG2 Video filename
   SHRNKFILE=$WORKDIR/shrunken.$PROJNAME.m2v   # Shrunken MPG2 Video
   AUDIOFILE=$WORKDIR/$PROJNAME.ac3            # AC3 Audio filename
   SUBFILE=$WORKDIR/$PROJNAME.sub              # Subtitle filename
   MPGFILE=$WORKDIR/$PROJNAME.mpg              # Final MPGE2 filename
   MUXFILE=$WORKDIR/muxed.mpg                  # Muxed file (subtitles in)
   VFIFO=/tmp/videofifo                        # Video named pipe
   AFIFO=/tmp/audiofifo                        # Audio named pipe
   SFIFO=/tmp/subtitlefifo                     # Subtitle named pipe
   CMDFILE=$BASEDIR/dvdshrink.prog             # Progress file
   VARFILE=$BASEDIR/dvdshrink.var              # Variable holding file
   INFOFILE=$WORKDIR/$PROJNAME.info            # Title information file
   CHAPFILE=$WORKDIR/$PROJNAME.chap            # Chapter file
   if ((! $DVDINFO)); then
      if [ -e $LOGFILE ]; then rm -f $LOGFILE; fi
      touch $LOGFILE
      WriteToLog "DVDShrink log for $PROJNAME\n" 1
   fi
   if ((! $RESTART)); then
      builddirs
      writevarfile
   fi
}

# Using the '-a list' option will bring up a list of the audio channels
# in the selected title and prompt us to select one. It must be numeric
# and be in the list to be accepted. The script only handles AC3 channels
# so we won't select any 'dts' stream here.
#-----------------------------------------------------
function selectaudio {
   banner
   echo -e "   \033[1mAudio channels on DVD\033[0m\n"
   OLDIFS=$IFS
   IFS=$'\n'
   TCOUNT=0
   for a in $DINFO; do
      if ((`teststring "$a" " drc "`)); then
         if ((`teststring "$a" " dts "`)); then
            ((TCOUNT++))
         else
            echo -e "      \033[31m$TCOUNT\033[0m) - ${a##*\) }"
            ((TCOUNT++))
         fi
      fi
   done   
   echo
   IFS=$OLDIFS
   ((TCOUNT--))
   echo -en "   Select an audio stream (or enter for 0)    "
   read AUDIO
   if [ -z $AUDIO ]; then
      AUDIO=0
   else
      testselect $AUDIO "stream" "selectaudio" $TCOUNT
   fi
   getaudiolang $AUDIO
}

# Find out the audio stream language from the input channel
#-----------------------------------------------------
function getaudiolang {
   AINPUT=$1
   OLDIFS=$IFS
   IFS=$'\n'
   TCOUNT=0
   for a in $DINFO; do
      if ((`teststring "$a" ' drc '`)); then
         if [ $TCOUNT -eq $AINPUT ]; then 
            ALANG=${a##*ac3 } && ALANG=${ALANG%% drc* }
            ALANG=${ALANG%% *}
            ((TCOUNT++))
         fi
      fi
   done
   IFS=$OLDIFS
   WriteToLog "" 0
   WriteToLog "Source DVD Selections" 0
   WriteToLog "-----------------------------------------------\n" 0
   WriteToLog "Title:                   $TITLE" 0
   WriteToLog "Audio stream:            $AUDIO" 0
   WriteToLog "Audio language:          $ALANG" 0
}

# With the -t list option we're presented with a list of titles
# we can select from
#-----------------------------------------------------
function selecttitle {
   banner
   showtitles
   echo -n "Select the title to rip (or enter for 1)   "
   read TITLE
   if [ -z $TITLE ]; then
      TITLE=1
   else
      testselect $TITLE "title" "selecttitle" $TITLES
   fi
}

# This function just lists the titles on the DVD
#-----------------------------------------------------
function showtitles {
   PAD="00000"
   tcprobe -i $RDEVICE > /tmp/titleinfo 2>&1
   OLDIFS=$IFS
   IFS=$'\n'
   for a in `cat /tmp/titleinfo`; do
      if ((`teststring "$a" 'DVD title'`)); then
         TITLES=${a##\(*\/} && TITLES=${TITLES%%:*}
         break
      fi   
   done
   echo -e "   \033[1mList of titles\033[0m"
   echo -e "   Title      Chapters        Frames        Playback time\n"
   SEQ=1
   while [ $SEQ -le $TITLES ]; do
      tcprobe -i $RDEVICE -T $SEQ -H 200 > /tmp/titleinfo 2>&1
      for a in `cat /tmp/titleinfo`; do
         if ((`teststring "$a" 'DVD title'`)); then
            CHAPTERS=${a#*: } && CHAPTERS=${CHAPTERS%% *}         
         fi
         if ((`teststring "$a" 'playback time'`)); then
            TIME=${a##*time: } && TIME=${TIME%% *}
         fi
         if ((`teststring "$a" " frames,"`)); then
            FRAMES=${a##*: } && FRAMES=${FRAMES%% *}         
         fi
       done
      if [ $CHAPTERS -lt 10 ]; then CHAPTERS="$CHAPTERS "; fi 
      FRAMES=$FRAMES${PAD:0:$((7-${#FRAMES}))}
      TTITLE="  $SEQ"
      if [ $SEQ -lt 10 ]; then TTITLE=" $TTITLE"; fi
      echo  -e "   \033[31m$TTITLE\033[0m)      $CHAPTERS chapter(s)   $FRAMES       $TIME"
      rm -f /tmp/titleinfo
      ((SEQ++))
   done
   IFS=$OLDIFS
   echo
}

# With the list option we can select which subtitle to rip
#-----------------------------------------------------
function selectsubtitle {
   banner
   echo -e "   \033[1mSubtitle channels on DVD\033[0m"
   echo
   OLDIFS=$IFS
   IFS=$'\n'
   TCOUNT=0
   for a in $DINFO; do
      if ((`teststring "$a" ' subtitle '`)); then
         a=${a##*\) }
         a=${a//subtitle/0x2$TCOUNT}
         echo -e "      \033[31m$TCOUNT\033[0m) - ${a//[=<>]/ }"
         ((TCOUNT++))
      fi
   done
   echo
   IFS=$OLDIFS
   ((TCOUNT--))
   echo -n "   Select a sub stream (or enter for none)    "
   read SUBTITLE
   if [ -z $SUBTITLE ]; then
      SUBTITLE=0
      ADDTITLES=0
   else
      if [ ! `testselect $SUBTITLE "stream" "selectsubtitle" $TCOUNT` ]; then
         ADDTITLES=1
      fi
   fi
}

# Test our selection of title, audio and subtitle
#-----------------------------------------------------
function testselect {
   VAR=$1
   ISALPHA=0
   VARLEN=${#VAR}
   POS=0
   while [ $POS -lt $VARLEN ]; do
      THISVAR=${VAR:$POS:1}
      case $THISVAR in
         [0-9])   ISALPHA=$ISALPHA;;
         *)       ((ISALPHA++));;
      esac
      ((POS++));
   done
   if (($ISALPHA)); then
      echo -en "   \033[1mSelection must be numeric! Hit any key to re-select!\033[0m  "
      read
      banner
      $3
   elif [ $VAR -gt $4 ]; then
      echo -en "   \033[1mSelected $2 doesn't exist! Hit any key to re-select!\033[0m   "
      read
      banner
      $3
   else
      return 0
   fi
}



# With the list option we can select which subtitle to rip
#-----------------------------------------------------
function getsubtitlelang {
   STRACK="0x2"$1
   OLDIFS=$IFS
   IFS=$'\n'
   for a in $DINFO; do
      if ((`teststring "$a" "subtitle0$1"`)); then
         SLANG=${a##*\) }
         SLANG=${SLANG//[0-9=<>]/}
         break
      fi
   done   
   if ((! $ADDTITLES)); then
      WriteToLog "Sub stream:              None selected" 0
   else
      WriteToLog "Sub stream:              $SUBTITLE" 0
      WriteToLog "Sub language:            $SLANG" 0
   fi 
   banner
}

# Test for a readable DVD in the read device
#-----------------------------------------------------
function Test4DVD {
   dd if=$RDEVICE bs=1 count=32 skip=32808 > /dev/null 2>&1
   if (($?)); then
      echo -e "\n   \033[1mThere appears to be no readable DVD in $RDEVICE\033[0m\n"
      echo -n "   Place the source DVD in $RDEVICE and hit any key to continue...   "
      read
      banner
   fi
}

# Test for a blank DVD in the read device
#-----------------------------------------------------
function Test4NonblankDVD {
   dd if=$WDEVICE bs=1 count=32 skip=32808 > /dev/null 2>&1
   if ((! $?)); then
      echo -e "\n   \033[1mThe DVD in $WDEVICE appears to have data on it!\033[0m\n"
      echo -n "   Place a blank DVD in $WDEVICE and hit any key to continue...   "
      read
   fi
}
   
# List a bunch of pertinent data on the title that you want to shrink.
#-----------------------------------------------------
function dvdinfo {
   OLDIFS=$IFS
   IFS=$'\n'
   for LINE in $DINFO; do

   # Find out the playing time of the title

      if ((`testistring "$LINE" "[tcprobe]"`)); then
         if ((`testistring "$LINE" " sec "`)); then
            PLAYTIME=${LINE%% sec*} && PLAYTIME=${PLAYTIME##* }
            PLAYHOUR=$(($PLAYTIME/3600))
            PLAYMINS=$((($PLAYTIME%3600)/60))
            PLAYSECS=$((($PLAYTIME%3600)%60))
            TIME="$PLAYHOUR:$PLAYMINS:$PLAYSECS"
            FRAMES=${LINE##*V: } && FRAMES=${FRAMES%% *}
            BRATE=$(((1000*$FRAMES)/$PLAYTIME)) && FRATE=${BRATE:0:2}"."${BRATE:2:4}
         fi
      fi

   # Find out the frame size and aspect ratio of the title

      if ((`testistring "$LINE" "import frame size"`)); then
         FSIZE=${LINE##*-g } && FSIZE=${FSIZE%% *}      
      fi
      if ((`testistring "$LINE" "aspect ratio"`)); then
         RATIO=${LINE##*: } && RATIO=${RATIO%% *}            
      fi

   # Find out the number of chapters in the title

      if ((`testistring "$LINE" "dvd title"`)); then
         CHAPTERS=${LINE#*: } && CHAPTERS=${CHAPTERS%% *}
      fi
   done

   # Print some information

   echo -e "   \033[1mTitle Information\033[0m"
   echo  "      Volume ID:               "$PROJNAME
   echo  "      Selected title:          "$TITLE
   echo  "      Chapters in this title:  "$CHAPTERS
   echo  "      Number of frames:        "$FRAMES
   echo  "      Frame size:              "$FSIZE
   echo  "      Frame rate:              "$FRATE
   echo  "      Playback time:           "$TIME
   echo -e "      Aspect ratio:            "$RATIO"\n"
   echo -e "   \033[1mAudio tracks\033[0m"
   TCOUNT=0

   # Show us the available audio streams

   for a in $DINFO; do
      if ((`teststring "$a" " drc "`)); then
         echo -e "      \033[31m$TCOUNT\033[0m) - ${a#* }"
         ((TCOUNT++))
      fi
   done

   # Show us the available subtitle streams

   echo -e "\n   \033[1mSubtitles\033[0m"
   TCOUNT=0
   for a in $DINFO; do
      if ((`teststring "$a" "subtitle"`)); then 
         a=${a#*subtitle } 
         echo -e "      \033[31m$TCOUNT\033[0m) -  0x2$TCOUNT ${a//[=<>]/ }"
         ((TCOUNT++))
      fi
   done
   if ((! $TCOUNT)); then echo "   No subtitle streams in this title."; fi
   IFS=$OLDIFS
   rm -rf $WORKDIR
   echo
   doexit 0
}

# Prompt for the disks. If the options we've selected call for
# a burn, then we want to prompt for the blank. Else we're just
# going to be prompted for the source.
#-----------------------------------------------------
function diskprompt {
   echo "   Place the source DVD in the read device"
   if (($MULTIDRIVE)); then
      echo "   Place a blank DVD in the write device"
   fi
   echo -en "\n   Hit any key to start..."
   read
   clear
   banner
}

# Create the working directories. The scheme here is to put the working
# directories into $BASEDIR. For a project calling for a burn we'll need
# a directory for the working files ($BASEDIR/$PROJNAME) and a directory
# to build the new DVD ($BASEDIR/$PROJNAME/BUILD).
#-----------------------------------------------------
function builddirs {
   if [ ! -d $WORKDIR ];    then mkdir -p $WORKDIR 2> /dev/null; fi
   if ((! $NOBUILD));       then mkdir $WORKDIR/BUILD 2> /dev/null; fi
   if (($ADDTITLES));       then mkdir $WORKDIR/SUBPGM 2> /dev/null; fi

}

# Give us a synopsis of what we're going to do. Really just something
# to make us feel good but it does tell us where to look for the 
# files etc.
#-----------------------------------------------------
function showsynopsis {
   echo -e "   \033[1mINFORMATION\033[0m\n"
   echo "   Project:                                  $PROJNAME"
   echo "   File cleanup?                             "`yesno $RMFILES`
   echo -n "   Auto-burn?                                "
   if (($ISOONLY)); then echo "No, ISO only."
   elif (( $MPEGONLY || $BIGMPEGONLY )); then echo "No, create MPEG files only."
   elif (( $STREAMONLY || $BIGSTREAMONLY )); then echo "No, create streams only."
   elif (($AUTHORONLY)); then echo "No, Author only."
   elif (($FORCEBURN)); then echo "Yes, no prompts (forced)!"
   else
      if (($AUTOBURN)); then echo "Yes, prompt"
      else echo "No, prompt"; fi
   fi
   echo "   Save ISO with burn?                       "`yesno $SAVEISO`
   echo "   DVD Title:                                $TITLE" 
   echo "   Audio channel:                            $AUDIO"
   echo -n "   Subtitle channel:                         "
   if ((! $ADDTITLES)); then echo "None"
   else echo $SUBTITLE; fi
}

# A little background timer that will count up to $1 and then
# kill process named $2. We're really only using it for
# the CheckAVSync function, but it may be handy in the
# future. It will first run a loop that checks for the presence
# of the process ($2) before starting the test. Then it will
# keep checking every second for the process for the number
# of seconds in $1. If it doesn't detect the process for 5
# seconds it will fail. If the process stops before the number
# of seconds in $1 it till fail. Either way the rip continues
# but with no A/V adjustment.
#-----------------------------------------------------
function ProcTimer {
   TIMER=$1
   COMMAND=$2
   ATEST=1
   CHECKFAIL=0
   CTIME=`date +%s`
   while (($ATEST)); do
      if [ `date +%s` -eq $(($CTIME+5)) ]; then
         echo "Error!"
         ((CHECKFAIL++))
         break
      fi
      ps -C $COMMAND > /dev/null 2>&1
      ATEST=$?
   done
   if ! (($CHECKFAIL)); then
      for a in `seq 1 $TIMER`; do
         sleep 1
         if ! ps -C $COMMAND > /dev/null 2>&1; then
            echo "A/V Synchronization check failed!" >> $DEBUGFILE
            echo "CMD: tccat -i $RDEVICE -T $TITLE,-1 > $WORKDIR/test.vob 2>$DEBUGFILE &" >> $DEBUGFILE
            echo "Error!"
            break
         fi         
      done
   fi
   kill -2 `ps -C $COMMAND --no-headers -o pid` > /dev/null 2>&1
}

# Check the A/V synchronization of the DVD. It should come out
# to be the same. If not we're going to _ATTEMPT_ to re-sync
# the audio and video on re-multiplexing. To do this we're going
# to start a test rip (5 seconds worth) and then probe it.
#-----------------------------------------------------
function CheckAVSync {
   DEBUGFILE=$WORKDIR/syncdebug.txt
   ProcTimer 22 tccat &
   tccat -i $RDEVICE -T $TITLE,-1 > $WORKDIR/test.vob 2>$DEBUGFILE
   rm -f $DEBUGFILE
   tcprobe -i $WORKDIR/test.vob -H 10 > $WORKDIR/sync.txt 2>&1
   PTSINFO=`cat $WORKDIR/sync.txt`
   rm -f $WORKDIR/sync.txt $WORKDIR/test.vob
   OLDIFS=$IFS
   IFS=$'\n'
   COUNT=1
   for LINE in $PTSINFO; do
      if ((`testistring "$LINE" 'PTS='`)); then
         if [ $COUNT -eq 1 ]; then
            VPTS=${LINE// /} && VPTS=${VPTS:4:6}
            if ((! ${VPTS:0:1})); then VPTS=${VPTS:2:4 }
            else VPTS=${VPTS//\./}; fi
         else
            ACNT=$(($COUNT - 2 ))
            if [ $ACNT -eq $AUDIO ]; then
               APTS=${LINE// /} && APTS=${APTS:4:6}
               if ((! ${APTS:0:1})); then APTS=${APTS:2:4}
               else APTS=${APTS//\./}; fi
            fi
         fi
         ((COUNT++))
      fi
   done
   IFS=$OLDIFS
   CORR=$(($APTS-$VPTS))
               
   WriteToLog "Video PTS: $VPTS" 0
   WriteToLog "Audio PTS: $APTS" 0
   if (($CORR)); then
      ASYNCVAL="-O "$CORR"ms"
      WriteToLog "A/V synchronization needed. Using a factor of $CORR milliseconds!" 0
   else
      ASYNCVAL=""
      WriteToLog "No A/V synchronization issues." 0
   fi
}

# Read the chapter list for the selected title. This is a comma-
# delimited list that will be passed to dvdauthor. I've stuck the
# call for 'CheckAVSync' in here for utility
#-----------------------------------------------------
function readchapters {
   Test4DVD
   echo "1" > $CMDFILE
   echo -e "\n   \033[1mPROGRESS\033[0m   Rip started at \033[34m"`date +%H:%M:%S`"\033[0m\n"
   echo -e "   \033[1mDVDSHrink Function                        Status    Elapsed\033[0m\n"
   echo -en "   Reading the chapter list                  \033[31m\033[5mWorking!\033[0m"
   OLDIFS=$IFS
   IFS=$'\n'
   WriteToLog "" 0
   WriteToLog "Chapter list" 0
   WriteToLog "-----------------------------------------------\n" 0
   CHAPLIST=
   for a in $DINFO; do
      if ((`teststring "$a" "[Chapter "`)); then
         a=${a##*] } && a=${a%% ,*}
         CHAPLIST=$CHAPLIST",$a"
      fi
   done
   CHAPLIST=${CHAPLIST#*,}
   IFS=$OLDIFS   
   IFS=$OLDIFS
   elapsedtime $STIME `date +%s`
   echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED" 
   echo "CHAPLIST=$CHAPLIST" >> $VARFILE   
   WriteToLog "$CHAPLIST" 0
   echo -n "$CHAPLIST" > $CHAPFILE
}

# Extract the video/audio streams from the selected title. The script
# can (at the present time) only handle a single audio stream and 
# subtitle stream along with the video track.
#-----------------------------------------------------
function extractvideo {
   echo "2" > $CMDFILE
   WriteToLog "Commenced DVD rip." 1
   WriteToLog "Video stream: $VIDEOFILE" 0
   WriteToLog "Audio stream: $AUDIOFILE" 0
   DEBUGFILE=$WORKDIR/tccatdebug.txt

   # Create the named pipes that we'll need. There are three; one each
   # for the video, audio and (optional) subtitle streams.

   FIFOLIST="$VFIFO $AFIFO"
   if [ ! -p $VFIFO ]; then 
      mkfifo $VFIFO > /dev/null 2>&1
      if [ ! -e $VFIFO ]; then errortrap 9; fi
   fi
   if [ ! -p $AFIFO ]; then 
      mkfifo $AFIFO > /dev/null 2>&1
      if [ ! -e $AFIFO ]; then errortrap 9; fi
   fi

   # Start the stream extraction

   tcextract -i $VFIFO -t vob -x mpeg2 > $VIDEOFILE 2> /dev/null &
   tcextract -i $AFIFO -a $AUDIO -x ac3 -t vob > $AUDIOFILE 2> /dev/null &
   if (($ADDTITLES)); then
      if [ ! -p $SFIFO ]; then mkfifo $SFIFO > /dev/null 2>&1; fi
      if (($?)); then
         errortrap 9
      else 
         FIFOLIST="$FIFOLIST $SFIFO"
         WriteToLog "Subtitle stream $SUBFILE" 0      
         tcextract -i $SFIFO -a $STRACK -x ps1 -t vob > $SUBFILE 2> /dev/null&       
      fi
   fi

   # Start ripping the title. We'll pass the output to the named pipes we've
   # created above and therefore generate all the needed elemental streams in
   # one pass.

   echo -en "   Ripping Title                             \033[31m\033[5mWorking!\033[0m"
   TCCMD="nice -n +19 tccat -i $RDEVICE -T $TITLE,-1 -L 2> $DEBUGFILE | tee $FIFOLIST >/dev/null 2> /dev/null"
   eval "$TCCMD"
   if (($?)); then errortrap 2; fi

   # Check that the generated files are not 0 length

   if ((! `stat -c %s $VIDEOFILE`)); then 
      WriteToLog "Video file size 0. Error!" 1
      errortrap 2
   fi
   if ((! `stat -c %s $AUDIOFILE`)); then 
      WriteToLog "Audio file size 0. Error!" 1
      errortrap 2
   fi
   if [ $ADDTITLES -eq 1 ]; then
      if ((! `stat -c %s $SUBFILE`)); then 
         WriteToLog "Subtitle stream size 0. Error!" 1
         errortrap 2
      fi
   fi   
   rm -f $DEBUGFILE
   elapsedtime $STIME `date +%s`
   echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
   WriteToLog "DVD rip completed. Elapsed time $ELAPSED" 1

   # If we've asked for just the un-resized elemental streams then
   # we want to exit here.

   rm -f $WORKDIR/*.?fifo
   if (($BIGSTREAMONLY)); then
      WriteToLog "Uncompressed streams created. Run complete!" 1
      echo -e "\n   Un-compressed video stream $VIDEOFILE created!"
      echo "   Audio stream $AUDIOFILE created!"
      if (($ADDTITLES)); then echo -e "   Subtitle stream $SUBSTREAM created!\n"; fi
      if (($RMFILES)); then rm -f $CMDFILE $VARFILE $INFOFILE $CHAPFILE; fi
      echo -e "   \n033[1mYour DVD streams are ready in $WORKDIR!\033[0m"
      doexit 0
   fi   

}

# Converts a random floating point value into a 3 digit integer
#-----------------------------------------------------
function Shrink2Integer {
   SHVAL=$1
   SHVAL=${SHVAL//0\./\.}
   if [ ${SHVAL:0:1} != "." ]; then      
      SHVAL=${SHVAL//\./}
      SHVAL=${SHVAL:0:4}
      if   [ $SHVAL -lt 10 ];   then SHVAL=$(($SHVAL*1000))
      elif [ $SHVAL -lt 100 ];  then SHVAL=$(($SHVAL*100))
      elif [ $SHVAL -lt 1000 ]; then SHVAL=$(($SHVAL*10)); fi
      SHRINKSTR=${SHVAL:0:1}
      SHRINKEND=${SHVAL:1:2}
      SHRINKTST=${SHVAL:3:1}
      if [ $SHRINKTST -ge 5 ]; then ((SHRINKEND++)); fi
      echo $SHRINKSTR$SHRINKEND      
   else
      SHVAL=${SHVAL//\./}"000"
      echo ${SHVAL:0:2}
   fi
}

# Re-size the video stream if needed. As most commercial movies
# take up more than will fit onto a DVD-R or RW we'll have to do some
# shrinking here. We only shrink the video stream and the script will
# determine how much shrinking needs to be done. Of course, if you 
# want to do something different you can use the -k <value> option to
# use your own requantizing factor.
#-----------------------------------------------------
function requantize {
   echo "3" > $CMDFILE
   if (($SHRINK)); then
      if [ -f $SHRNKFILE ]; then rm -f $SHRNKFILE; fi

      # If we've not given the script a value for a user-defined
      # shrink factor, then the script will generate one.

      if ((! $MYSHRINK)); then
         VSIZE=`stat -c %s $VIDEOFILE`
         ASIZE=`stat -c %s $AUDIOFILE`
         SSIZE=$(($ADDTITLES*10000000))
         TSIZE=$(($VSIZE+$ASIZE+$SSIZE))
         FFACTOR=$(((105*$VSIZE)/($MAXMPGSIZE-($ASIZE+$SSIZE))))
         WriteToLog "Maximum size per title allowed:   $MAXMPGSIZE" 0
         WriteToLog "Size of elemental streams: Video: $VSIZE" 0
         WriteToLog "                           Audio: $ASIZE" 0
         WriteToLog "                           Sub:   $SSIZE" 0
         if [ $FFACTOR -gt 100 ]; then
            WriteToLog "Calculated shrink factor:         ${FFACTOR:0:1}"."${FFACTOR:1:5}" 0
         else
            WriteToLog "Calculated shrink factor:         .$FFACTOR" 0
            WriteToLog "No shrink required" 0
         fi
         if [ $FFACTOR -ge 100 ]; then
            RFACTOR=${FFACTOR:0:1}"."${FFACTOR:1:5}
         fi

      # If we HAVE given the script a shrink value use it

      else
         FFACTOR=$MYSHRINK
         for a in 1 2; do FFACTOR=${FFACTOR/#0/}; done
         RFACTOR=${FFACTOR:0:1}"."${FFACTOR:1:5}
         WriteToLog "User supplied shrink factor: $RFACTOR" 0
      fi

      # If the shrink factor (either generated or defined) is greater than 1.00 
      # then start re-quantizing the video. If it's not then we'll ignore the re-size.

      if [ $FFACTOR -gt 100 ]; then         
         WriteToLog "M2V re-quantization of $VIDEOFILE commenced. Factor $RFACTOR" 1
         DEBUGFILE=$WORKDIR/requantdebug.txt
         echo -en "   Resizing MPEG2 video stream               \033[31m\033[5mWorking!\033[0m"
         TQCMD="nice -n +19 tcrequant -i $VIDEOFILE -d 0 -o $SHRNKFILE -f $RFACTOR 2> $DEBUGFILE"
         eval "$TQCMD"
         if (($?)); then errortrap 3; fi
         if [ `stat -c %s $SHRNKFILE` -eq 0 ]; then
            WriteToLog "Compressed M2V file 0 length. Error!" 1
            errortrap 3
         fi
         rm -f $DEBUGFILE
         elapsedtime $STIME `date +%s`
         echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
         WriteToLog "M2V re-quantization completed. Elapsed time $ELAPSED" 1
         mv -f $SHRNKFILE $VIDEOFILE
         NVSIZE=`stat -c %s $VIDEOFILE`
         WriteToLog "New video stream size $NVSIZE" 0
      fi

      # If we've told the script that all we want are the elemental streams with
      # the video 'shrunk' then we're going to exit here.

      if (($STREAMONLY)); then
         WriteToLog "Requested streams only. Run completed!" 1
         echo -e "\n   Compressed video stream $VIDEOFILE created!"
         echo "   Audio stream $AUDIOFILE created!"
         if (($ADDTITLES)); then echo "   Subtitle stream $SUBFILE created!"; fi
         if (($RMFILES)); then rm -f $CMDFILE $VARFILE $INFOFILE $CHAPFILE; fi
         echo -e "\n   \033[1mYour DVD streams are ready in $WORKDIR!\033[0m\n"
         doexit 0
      fi
   fi
}

# Re-combine the video/audio into a single MPEG2 file that is
# dvdauthor compatible.
#-----------------------------------------------------
function multiplexvideo {
   echo "4" > $CMDFILE
   DEBUGFILE=$WORKDIR/mplexdebug.txt   
   WriteToLog "Re-multiplexing of $MPGFILE started." 1
   if [ -f $MPGFILE ]; then rm -f $MPGFILE; fi
   echo -en "   Remultiplexing                            \033[31m\033[5mWorking!\033[0m"
#   MPCMD="nice -n +19 mplex $ASYNCVAL -f 8 -o $MPGFILE $VIDEOFILE $AUDIOFILE 2> $DEBUGFILE"
   MPCMD="nice -n +19 mplex -f 8 -o $MPGFILE -S 0 $VIDEOFILE $AUDIOFILE 2> $DEBUGFILE"
   eval "$MPCMD"
   
   # Some versions of mplex will generate spurious errors about 'splitting the file'. This should
   # trap out those errors.   
   
   if (($?)); then 
      if [ -f $MPGFILE ]; then
         TMPG=`stat -c %s $MPGFILE`
         TVID=`stat -c %s $VIDEOFILE`
         TAUD=`stat -c %s $AUDIOFILE`
         TSTR=$(($TVID+$TAUD))
         if  [ $TMPG -le $TSTR ]; then
            errortrap 4
         fi
      fi
   fi

   # So, now that we've re-sized, check for a valid MPEG file (not 0 length)

   if ((! `stat -c %s $MPGFILE`)); then
      WriteToLog "Re-muxed MPEG2 file 0 length. Error!" 1
      errortrap 4
   fi
   
   elapsedtime $STIME `date +%s`   
   rm -f $DEBUGFILE
   echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
   WriteToLog "Re-multiplexing completed. Elapsed time $ELAPSED" 1
   if (($RMFILES)); then rm -f $VIDEOFILE $AUDIOFILE; fi

   # If we've asked for only an MPEG2 file to be returned then we're going
   # to exit here.

   if (($MPEGONLY || $BIGMPEGONLY)); then
      createsubtitles
      SHRUNKEN="Compressed"
      if (($BIGMPEGONLY)); then SHRUNKEN="Uncompressed"; fi
      echo -e "\n   $SHRUNKEN MPEG2 file $MPGFILE Created!\n"
      WriteToLog "Requested MPEG file only. Run completed!" 1
      if (($RMFILES)); then rm -f $CMDFILE $VARFILE $INFOFILE $CHAPFILE; fi
      echo -e "   \033[1mYour MPEG2 file is ready in $WORKDIR!\033[0m\n";
      doexit 0
   fi
}

# Convert a time string from hh:mm:ss.sss to number of milliseconds
#-----------------------------------------------------
function Milliseconds {
   INPUT=$1
   HOUR=${INPUT:0:2} && HOUR=$((${HOUR/#0/}*3600000))
   MINS=${INPUT:3:2} && MINS=$((${MINS/#0/}*60000))
   SECS=${INPUT:6:6} && SECS=${SECS/\./}
   for a in 1 2 3 4; do SECS=${SECS/#0/}; done
   echo $((HOUR+$MINS+SECS))
}

# This function will paw through our created xml file for spumux
# and remove any suspect subtitles.
#-----------------------------------------------------
function checkxml {
   if [ -e $WORKDIR/spumux.xml ]; then rm -f $WORKDIR/spumux.xml; fi
   OLDIFS=$IFS
   IFS=$'\n'
   BADSPU=0
   for LINE in `cat $WORKDIR/SUBPGM/$PROJNAME.dvdxml`; do
       if ((`teststring "$LINE" "spu start"`)); then
         START=${LINE#*start=}
         START=${START%% *}
         START=${START//\"/}
         END=${LINE##*end=}
         END=${END%% *}
         END=${END//\"/}
         if [ $((`Milliseconds $END`-`Milliseconds $START`)) -gt 1000 ]; then
            echo "$LINE" >> $WORKDIR/spumux.xml
         else
            ((BADSPU++))
         fi
      else echo "$LINE" >> $WORKDIR/spumux.xml; fi
   done
   IFS=$OLDIFS
   if ((! `stat -c %s $WORKDIR/spumux.xml`)); then
      WriteToLog "SPUMUX file 0 length. Error!" 1
      errortrap 5a
   fi
   return 0
}

# Process/mux in subtitles
#-----------------------------------------------------
function createsubtitles {
   echo "5" > $CMDFILE
   if (($ADDTITLES)); then
      DEBUGFILE=$WORKDIR/subtitle2pgmdebug.txt
      WriteToLog "Subtitle creation started." 1
      echo -en "   Creating subtitle images                  \033[31m\033[5mWorking!\033[0m"

   # Create a proper -X parameter for subtitle2pgm if the version will handle it

      TESTSUBVER=`subtitle2pgm -h 2>&1 | grep -c "\-X"`
      TVRESVAL=""
      if (($TESTSBUVER)); then
         TVRESVAL="-X$TVRES"
      fi

   # done test

      SBCMD="nice -n +19 subtitle2pgm -i $SUBFILE -o $WORKDIR/SUBPGM/$PROJNAME $TVRESVAL -g 5 -t 1 2> $DEBUGFILE"
      eval "$SBCMD"
      if (($?)); then errortrap 5b; fi
      rm -f $DEBUGFILE
      elapsedtime $STIME `date +%s`   
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
      WriteToLog "Subtitles creation complete. Elapsed time $ELAPSED" 1
      WriteToLog "Commenced XML file check" 1
      echo -en "   Checking xml for suspect entries          \033[31m\033[5mWorking!\033[0m"
      checkxml
      elapsedtime $STIME `date +%s`   
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
      WriteToLog "XML file check finished. $BADSPU entries dropped. Elapsed time $ELAPSED" 1
      SPUMUXDEBUG=$WORKDIR/spumuxdebug.txt
      WriteToLog "Commenced muxing in subtitles" 1
      echo -en "   Muxing in subtitles                       \033[31m\033[5mWorking!\033[0m"
      SPCMD="nice -n +19 spumux $WORKDIR/spumux.xml < $MPGFILE > $MUXFILE 2> $DEBUGFILE"
      eval "$SPCMD"
      if (($?)); then errortrap 5c; fi
      rm -f $DEBUGFILE
      elapsedtime $STIME `date +%s`   
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
      WriteToLog "Subtitle remux complete. Elapsed time $ELAPSED" 1
      mv -f $MUXFILE $MPGFILE
      if (($RMFILES)); then 
         rm -f $SUBFILE
         rm -f $WORKDIR/spumux.xml
         rm -rf $WORKDIR/SUBPGM
      fi
   fi
}

# Author the new DVD. To match some older versions of
# dvdauthor, if 'dvddirgen' is present we'll run it.
#-----------------------------------------------------
function authordvd {
   echo "6" > $CMDFILE
   WriteToLog "Commenced DVD author in $WORKDIR/BUILD" 1
   DEBUGFILE=$WORKDIR/authordebug.txt
   SUBOPTS=""
   if (($ADDTITLES)); then SUBOPTS="-s $SLANG"; fi
   if (($RESTART)); then
      echo -en "   Cleaning up old DVD structure             \033[31m\033[5mWorking!\033[0m"
      if [ -d $WORKDIR/BUILD/VIDEO_TS ]; then rm -rf $WORKDIR/BUILD/*; fi
      elapsedtime $STIME `date +%s`      
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
   fi

   # Some older versions of dvdauthor had the 'dvddirgen' utility. If it's
   # present then run it. <shrug>

   if which dvddirgen > /dev/null 2>&1; then
      echo -en "   Creating new DVD structure                \033[31m\033[5mWorking!\033[0m"
      DGCMD="dvddirgen -o $WORKDIR/BUILD 2> $DEBUGFILE"
      eval "$DGCMD"
      if (($?)); then errortrap 6a; fi
      elapsedtime $STIME `date +%s`
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
      WriteToLog "dvddirgen complete. Elapsed time $ELAPSED" 1
   fi

   # Build the new dvd on the hard drive

   WriteToLog "Commenced building DVD on drive" 1
   
   # Build an XML file   
 
   XMLFILE=$WORKDIR/DVD.xml
   echo -en "   Building XML file                             \033[31m\033[5mWorking!\033[0m"
   CHAPTERS=`cat $CHAPFILE`
   echo "<dvdauthor dest=\"$WORKDIR/BUILD\">" > $XMLFILE
   echo "<vmgm />" >> $XMLFILE
   echo "<titleset>" >> $XMLFILE
   echo "<titles>" >> $XMLFILE
   echo "<audio lang=\"$ALANG\" />" >> $XMLFILE
   if (($ADDTITLES)); then echo "<subpicture lang=\"$SLANG\" />" >> $XMLFILE; fi        
   echo "<pgc>" >> $XMLFILE
   echo "<vob file = \"$MPGFILE\" chapters=\"$CHAPLIST\" />" >> $XMLFILE
   echo "</pgc>" >> $XMLFILE
   echo "</titles>" >> $XMLFILE
   echo "</titleset>" >> $XMLFILE
   echo "</dvdauthor>" >> $XMLFILE
   
   echo -e "\033[8D\033[32mDone!    \033[0m"
   
   # Author the DVD

   echo -en "   Building DVD on drive                     \033[31m\033[5mWorking!\033[0m"   
   DACMD="nice -n +19 dvdauthor -x $XMLFILE 2> $DEBUGFILE"
   eval "$DACMD"
   if (($?)); then errortrap 6b; fi
   elapsedtime $STIME `date +%s`
   echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
   WriteToLog "Authoring complete. Elapsed time $ELAPSED" 1
   
   
   WriteToLog "Commenced writing DVD TOC" 1
   echo -en "   Building TOC                              \033[31m\033[5mWorking!\033[0m"
   DTCMD="dvdauthor -o $WORKDIR/BUILD -T 2> $DEBUGFILE"
   eval "$DTCMD"
   if (($?)); then errortrap 6c; fi
   rm -f $DEBUGFILE
   elapsedtime $STIME `date +%s`
   WriteToLog "TOC build completed. Elapsed time $ELAPSED" 1
   echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
   if (($RMFILES)); then rm -f $WORKDIR/* 2> /dev/null; fi

   # If we've asked the script to generate a new DVD only then we'll
   # be exiting here.

   if (($AUTHORONLY)); then
      echo -e "\n   \033[1mYour DVD has been authored in $WORKDIR/BUILD!\033[0m\n"
      doexit 0
   fi
}

# This function just creates an ISO image of the new DVD. We'll
# use it if we want JUST an ISO or if we want to create and save
# and ISO along with the new DVD burn
#-----------------------------------------------------
function CreateISO {
      if [ -e $ISODIR/$PROJNAME.iso ]; then rm -f $ISODIR/$PROJNAME.iso; fi
      DEBUGFILE=$WORKDIR/mkisodebug.txt
      WriteToLog "ISO file $ISODIR/$PROJNAME.iso creation commenced." 1
      echo -en "   Creating ISO file                         \033[31m\033[5mWorking!\033[0m"
      MICMD="nice -n +19 mkisofs -dvd-video -V $PROJNAME -o $ISODIR/$PROJNAME.iso $WORKDIR/BUILD/ > /dev/null 2> $DEBUGFILE"
      eval "$MICMD"
      if (($?)); then errortrap 7; fi
      rm -f $DEBUGFILE
      elapsedtime $STIME `date +%s`
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
      WriteToLog "ISO creation complete. Elapsed time $ELAPSED" 1
}


# We've built the DVD structure and populated it. Now we either
# burn it to a blank DVD or create an ISO file to burn later
# depending on the flags given to the script
#-----------------------------------------------------
function burndvd {
   echo "7" > $CMDFILE

   # If we've asked for an ISO only then that's what we'll do, but there 
   # is also the option of creating an ISO along with burning a new
   # DVD; that's included in here too.

   if (($ISOONLY)); then 
      CreateISO
      WriteToLog "Requested ISO file only. Run completed!" 0
      echo -e "\n   \033[1mYour DVD ISO ($ISODIR/$PROJNAME.iso) is ready!\033[0m"
      if (($RMFILES)); then rm -rf $WORKDIR; fi
   else
      DEBUGFILE=$WORKDIR/growisofsdebug.txt
      if (($SAVEISO)); then CreateISO; fi
      if ((! $FORCEBURN)); then
         echo -e "\n   \033[1mReady to start burning the new DVD!\033[0m\n"      
         if (( $AUTOBURN )); then echo "   Place a blank DVD in the burner!"; fi
         echo -en "   Hit 'q' to quit or any other key to start burning the new DVD... "
         read BYN
         if [ -z $BYN ]; then BYN='x'; fi
         if ((`testistring $BYN 'q'`)); then 
            WriteToLog "Burn sequenced but cancelled by user. Run terminated!" 1
            if (($RMFILES)); then rm -f $CMDFILE $VARFILE $INFOFILE $CHAPFILE; fi
            echo
            doexit 0
         fi
         echo   
      fi
      Test4NonblankDVD
      WriteToLog "DVD burn commenced." 1
      echo -en "   Writing new DVD                           \033[31m\033[5mWorking!\033[0m" 
      GRCMD="growisofs -speed=$SPEED -Z $WDEVICE -dvd-video -V $PROJNAME $WORKDIR/BUILD/ > /dev/null 2> $DEBUGFILE"
      eval "$GRCMD"
      if (($?)); then errortrap 10; fi
      rm -f $DEBUGFILE
      elapsedtime $STIME `date +%s`
      echo -e "\033[8D\033[32mDone!\033[0m    $ELAPSED"
      WriteToLog "DVD burn completed. Elapsed time $ELAPSED" 1
      WriteToLog "Run completed!" 0
      echo -e "\n   \033[1mYour new DVD is ready!\033[0m"
   fi
   if (($RMFILES)); then rm -rf $WORKDIR; fi
   doexit 0
}

# Check that we have all the needed tools available to us
#-----------------------------------------------------
function checktools {
   RETS=0
   for EXE in tccat mplex growisofs mkisofs dvdauthor subtitle2pgm; do
      if ! which $EXE > /dev/null 2>&1; then
         if   [ "$EXE" = "tccat" ];        then EXE="transcode"
         elif [ "$EXE" = "mplex" ];        then EXE="mjpegtools"
         elif [ "$EXE" = "growisofs" ];    then EXE="dvd+rw-tools"
         elif [ "$EXE" = "subtitle2pgm" ]; then EXE="subtitleripper"
         fi
         ((RETS++))
         echo -e "   \033[1mRequired tools in package '$EXE' missing or unexecutable!\033[0m"
      fi
   done

   if (($RETS)); then 
       echo -e "\n   You are missing needed tools or the tools are not executable"
       echo -e "   by your user. Update or repair your toolset as needed.\n"
       exit 9
   fi
}

# If we've restarted due to errors then show the values that we're
# going to use to restart where we left off then confirm the
# restart
#-----------------------------------------------------
function showrestartvars {
   SPOINT="$1"
   banner
   echo -e "\n   DVDShrink has been restarted after an error.\nRe-starting with $SPOINT\n"
   echo -n "   Do you wish to see the restart variables? (y/n)   "
   read SYN
   if getyn $SYN; then
      echo -e "Here are the values the script will use:\n"
      for LINE in `cat $VARFILE`; do 
         echo "    $LINE"
      done
      echo -en "\n   Are these values correct? (y/n)                   "
      read CYN
      if getyn $CYN; then
         echo "   Check your files and try restart once again!"
         doexit 0
      fi
   fi
   echo
}  

# Run the necessary commands in sequence when a --restart is
# called for. This reads the contents of the progress file
# and runs the command set from the correct place.
#-----------------------------------------------------
function runcommands {
   ARG=$1
   CMDLIST="readchapters;extractvideo;requantize;multiplexvideo;createsubtitles;authordvd;burndvd"
   if [ $ARG -eq 0 ]; then 
      STARTCMD=$CMDLIST
   else
      a=1
      while [ $a -lt $ARG ]; do
         CMDLIST=${CMDLIST#*;}
         STARTCMD=$CMDLIST
         ((a++))
      done   
   fi
   case $ARG in
      1)    SCPOS="reading the chapter list!";;
      2)    SCPOS="extracting the streams!";;
      3)    SCPOS="re-sizing the video stream!";;
      4)    SCPOS="re-multiplexing the MPEG2!";;
      5)    SCPOS="creating/muxing subtitles!";;
      6)    SCPOS="authoring the DVD on disk!";;
      7)    SCPOS="burning the new DVD!";;
      *)    echo "   Unknown restart value ( $ARG )! (something funky happened)"; doexit 10;;
   esac
   WriteToLog "Restarting at $SCPOS" 1
   WriteToLog "Running commands: $STARTCMD" 0
   showrestartvars "$SCPOS"
   STIME=`date +%s`
   eval $STARTCMD
}

# Blatant plug
#-----------------------------------------------------
function banner {
   clear
   echo -e "________________________________________________________\n"
   echo -e "   \033[1mDVDShrink $VERSION - $DATE\033[0m"
   echo -e "   \033[31m$AUTHOR\033[0m"
   echo -e "________________________________________________________\n"
}

# Read the config file if it's there. If it's not then run the
# configuration routine.
#-----------------------------------------------------
function readconfig {
   if [ -e ~/.dvdshrinkrc ]; then
      FIRSTTIME=0
      . ~/.dvdshrinkrc
   else
      FIRSTTIME=1
      sconfigure
   fi
}

# Set the default variables and flag values
#-----------------------------------------------------
function setdefaultvars {
   SELPROJ='none'                # Place holder for ad-hoc project name
   TITLE=1                       # Default title number
   SUBTITLE=0                    # Default subtitle track
   AUDIO=0                       # Default audio stream number
   ALANG="en"                    # Default audio language
   SLANG="en"                    # Default subtitle language
   SELSHOW=0                     # Show values
   SELPROJ='none'                # User defined project name
   AUTOBURN=0                    # Auto-burn the new DVD.. but prompt
   FORCEBURN=0                   # Don't prompt... just burn
   RESTART=0                     # Script running fresh... no restart
   JUMPIN=0                      # Restart at the NEXT command
   ISOONLY=0                     # No-burn, ISO only
   SHRINK=1                      # Shrink the DVD9 to DVD5
   SHOWTITLES=0                  # Show title information
   STREAMONLY=0                  # Stop at the stream creation stage (shrunk)
   BIGSTREAMONLY=0               # Stop at the stream creation stage
   MPEGONLY=0                    # Stop at the MPEG creation stage (shrunk)
   BIGMPEGONLY=0                 # Stop at the MPEG creation stage
   AUTHORONLY=0                  # Stop at the DVD authoring stage
   DVDINFO=0                     # Show DVD information
   MYSHRINK=0                    # Force a 'shrink' factor
   ADDTITLES=0                   # Add a subtitle channel
   DISKPROMPT=1                  # Prompt for DVD's if needed
   MAXMPGSIZE=4700000000         # Maximum MPEG size (x 100)
   RETCODE=0                     # Return code
   DELETELOGS=0                  # Delete logs after successful copy
   SAVEISO=0                     # Save and ISO along with writing the new DVD

   # Set BATCH and GUI depending on what's running.

   BATCH=0
   if  ps -C batchrip.sh > /dev/null 2>&1; then BATCH=1; fi
   GUI=0
   if ps -C xdvdshrink.pl > /dev/null 2>&1; then GUI=1; fi

}

############### BatchRip specific functions ##################

# Set some default values
#--------------------------------------------
function readbatchdefaults {
   TVNAME="SHOW"        # The name of the TV Show
   AUDIOSTREAM=0        # The audiostream to rip
   SUBSTREAM=99         # The substream to rip (99=none)
   FRSTTITLE=1          # The first title to rip
   LASTTITLE=8          # The last title to rip
   SHRINKFAC=""         # The shrink factor
   EPISODES=3           # The number of episodes to put on each new DVD
   INTERACTIVE=0        # Run interactive
   BUILDXML=0           # Build the XML files needed
   RIPLIST=0            # List of titles to rip
   AUTHORDVD=0          # Author DVD(s) from the created XML files
   BURNDVDS=0           # Burn the DVDs
   FORCEBURN=0          # Burn the new DVD with no prompt
   ISOONLY=0            # Create ISO file only
   RESTART=0            # Restarted after failure
   DELETELOGS=0         # Delete logs after rip
   TVMODE="NTSC"        # The default TV mode
   RMFILES=0            # Remove working files
   MENU=1               # Create menus if multi-episode
   POSTPROCESS=0        # Jump straight to post-processing

   # Set BATCH and GUI depending on what's running.

   BATCH=0
   if ! ((`ps -C batchrip.sh > /dev/null 2>&1`)); then BATCH=1; fi
   GUI=0
   if ! ((`ps -C xdvdshrink.pl > /dev/null 2>&1`)); then GUI=1; fi
   SAVEISO=0            # Save an ISO along with the burn(s)

   APPDIR=/usr/share/applications/dvdshrink
}

# Build a minimal but usable XML file for 'dvdauthor'
#--------------------------------------------
function BuildXML {
   XMLSTART=0
   THISDVD=0
   MENUFILE=""
   echo -en "   Building XML file(s)                          \033[31m\033[5mWorking!\033[0m"
   if [ $MENU -ne 0 -a $MAXEPISODES -gt 1 -a $MAXEPISODES -lt 9 ]; then
      if [ $TVMODE = "NTSC" ]; then
         MENUFILE="nselect"$MAXEPISODES".mpg"
      else
         MENUFILE="pselect"$MAXEPISODES".mpg"
      fi
   fi

   for MPG in `ls $BUILDDIR/*.mpg`; do
      CHAPFILE=${MPG//\.mpg/\.chap}
      CHAPTERS=`cat $CHAPFILE`
      if ! (($XMLSTART%$MAXEPISODES)); then
         ((THISDVD++))
         XMLSTART=0
         XMLFILE=$BUILDDIR/DVD.$THISDVD.xml
         echo "<dvdauthor dest=\"$BUILDDIR/DVD.$THISDVD\">" > $XMLFILE
         echo "<titleset>" >> $XMLFILE
         if [ ! -z $MENUFILE ]; then
            echo "<menus>" >> $XMLFILE
            echo "<pgc>" >> $XMLFILE
            if [ $MAXEPISODES -gt 1 -a $MAXEPISODES -lt 9 ]; then
               BUTTON=1
               while [ $BUTTON -le $MAXEPISODES ]; do
                  echo "<button> jump title $BUTTON; </button>" >> $XMLFILE
                  ((BUTTON++))
               done
               echo "<vob file=\"$APPDIR/menus/$MENUFILE\"/>" >> $XMLFILE
               echo "<post> jump cell 1; </post>" >> $XMLFILE
               echo "</pgc>" >> $XMLFILE
               echo "</menus>" >> $XMLFILE
            fi
         fi
         echo "<titles>" >> $XMLFILE
      fi
      ((XMLSTART++))
      echo "<pgc>" >> $XMLFILE
      echo "<vob file = \"$MPG\" chapters=\"$CHAPTERS\"/>" >> $XMLFILE
      if [ $MENU -eq 1 -a $MAXEPISODES -gt 1 -a $MAXEPISODES -lt 9 ]; then
         echo "<post> call menu; </post>" >> $XMLFILE
      fi
      echo "</pgc>" >> $XMLFILE
   done
   for XMLFILE in `ls $BUILDDIR/*.xml`; do
      echo "</titles>" >> $XMLFILE
      echo "</titleset>" >> $XMLFILE
      echo "</dvdauthor>" >> $XMLFILE
   done
   echo -e "\033[8D\033[32mDone!    \033[0m"
}

# Create an ISO file only
#--------------------------------------------
function CreateISOe {
   for DVD in `ls $BUILDDIR/*.xml`; do
      OLDIFS=$IFS
      IFS=$'\n'
      for LINE in `cat $DVD`; do
         if ((`teststring "$LINE" 'dest='`)); then
            DVDDIR=${LINE##*=}
            DVDDIR=${DVDDIR//[\"\>]/}
            break
         fi
      done
      IFS=$OLDIFS
      DVDCOUNT=${DVD//\.xml} && DVDCOUNT=${DVDCOUNT##*\.}
      echo -en "   Creating ISO file $DVDCOUNT                           \033[31m\033[5mWorking!\033[0m"
      mkisofs -dvd-video -V $TVNAME"_D"$DVDCOUNT -o $ISODIR/$TVNAME"_D"$DVDCOUNT".iso" $DVDDIR > /dev/null 2>&1
      echo -e "\033[8D\033[32mDone!   \033[0m"
   done
}

# Burn the DVD(s) that we've built
#--------------------------------------------
function BurnDVDs {
   if (($SAVEISO)); then CreateISOe; fi
   for DVD in `ls $BUILDDIR/*.xml`; do
      OLDIFS=$IFS
      IFS=$'\n'
      for LINE in `cat $DVD`; do
         if ((`teststring "$LINE" 'dest='`)); then
            DVDDIR=${LINE##*=}
            DVDDIR=${DVDDIR//[\"\>]/}
            break
         fi
      done
      IFS=$OLDIFS
      if ((! $FORCEBURN)); then
         echo -e "\n   \033[1mConfirm a blank DVD is in the burning drive then hit any key\033[0m"
         echo -en "   \033[1mto commence burning... or enter 'q' to quit\033[0m  "
         read DQN
         echo
         if [ -z $DQN ]; then DQN='x'; fi
         if ((`testistring $DQN 'q'`)); then doexit 0; fi
      fi
      Test4NonblankDVD        
      DVDCOUNT=${DVD//\.xml} && DVDCOUNT=${DVDCOUNT##*\.}
      echo -en "   Writing DVD $DVDCOUNT                                 \033[31m\033[5mWorking!\033[0m"
      growisofs -speed=$SPEED -Z $WDEVICE -dvd-video -V $TVNAME"_D"$DVDCOUNT $DVDDIR > /dev/null 2>&1
      echo -e "\033[8D\033[32mDone!   \033[0m"
   done
}

# Clean up the working files if requested
#-----------------------------------------------------
function CleanUpFiles {
   if (($RMFILES)); then
      echo -en "\n   Removing working files...                  \033[31m\033[5mWorking!\033[0m"
      rm -rf $BUILDDIR
      echo -e "\033[8D\033[32mDone!\033[0m"
   fi
}

# Author DVD using an XML file
#-----------------------------------------------------
function AuthorUsingXML {
   SCOUNT=1
   for FILE in `ls $BUILDDIR/*.xml`; do
      OLDIFS=$IFS
      IFS=$'\n'
      for LINE in `cat $FILE`; do
         if ((`testistring "$LINE" 'dest='`)); then
            DVDDIR=${LINE##*=}
            DVDDIR=${DVDDIR//[\"\>]/}
            break
         fi
      done
      IFS=$OLDIFS
      echo -en "   Authoring DVD $SCOUNT                               \033[31m\033[5mWorking!\033[0m"
      dvdauthor -x $FILE > /dev/null 2>&1
      dvdauthor -o $DVDDIR -T > /dev/null 2>&1
      echo -e "\033[8D\033[32mDone!   \033[0m"
      ((SCOUNT++))
   done
}

# The 'usage'
#--------------------------------------------
function busage {
   echo -e "\033[1mUsage:\033[0m"
   echo "batchrip.sh <options>"
   echo "   -B | --burndvds             Burn the authored DVDs"
   echo "   -F | --forceburn            Auto-burn the new DVD with no prompt" 
   echo "   -L | --deletelogs           Delete logs"
   echo "   -M | --nomenu               Don't create DVD menu system"
   echo "   -N | --noremovefiles        Don't remove working files"
   echo "   -O | --saveiso              Create/save an ISO image along with new DVD"
   echo "   -R | --removefiles          Remove working files"
   echo "   -a | --audiostream <num>    Set the audio stream to rip"
   echo "   -d | --builddvd             Author the DVD(s) from created XML files"   
   echo "   -e | --episodes             Episodes on each new DVD (3)"
   echo "   -i | --interactive          Ask for values (off)"
   echo "   -k | --shrinkfactor <float> Shrink factor (1.5)"
   echo "   -l | --lasttitle <num>      Last title to rip (8)"
   echo "   -m | --createmenu           Create DVD menu system"
   echo "   -n | --showname             TV Show Name"
   echo "   -o | --isodir <dir>         Where to store ISO image files"
   echo "   -r | --riplist <list>       Comma delimited list of titles to rip"
   echo "   -s | --starttitle <num>     Starting title to rip (1)"
   echo "   -u | --substream <num>      Set the subtitle stream to rip"
   echo "   -x | --buildxml             Build the XML files (off)"
   echo "   -h | --help                 This page"
   echo "   --restart                   Restart after error"
   echo "   --postprocess               Jump straight to postprocessing after error"
   echo
   rm -f ~/.batchrip.pid
   exit
}

# Get the TV mode (ntsc/pal)
#-----------------------------------------------------
function gettvmode {
   OLDIFS=$IFS
   IFS=$'\n'
   ISNTSC=0
   for LINE in $DINFO; do 
      if ((`teststring "$LINE" 'ntsc'`)); then 
         ((ISNTSC++))
         break
      fi
   done
   IFS=$OLDIFS
   if ((! $ISNTSC)); then TVMODE="PAL"; fi
}

# The 'batchrip.sh' banner 
#---------------------------------------------
function ebanner {
   clear
   echo -e "______________________________________________________\n"
   echo -e "   \033[1mBatchRip $EVERSION - $EDATE\033[0m"
   echo -e "   \033[31mRick Saunders <ozzzy1@gmail.com>\033[0m"
   echo -e "______________________________________________________\n"
}

     
