#!/bin/bash

#----------------------------------------------------------------------------
# BImage
# Copyright (C) 2007 Nathan Shearer
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
#
# 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.
#   51 Franklin Street
#   Fifth Floor
#   Boston, MA
#   02110-1301
#   USA

COPYRIGHT="Copyright (C) 2007 Nathan Shearer"
VERSION="1.2.0.0"

function abdvde_cleanup
{
	printf "\n"
	if ! $DEBUG; then
		rm -rf "$TMP"
	fi
	exit
}

function abdvde_cleanup_title
{
	# if ! $DEBUG; then
		rm -rf "$TMP/audio"*
		rm -rf "$TMP/chapters.txt"
		rm -rf "$TMP/mplayer"*
		rm -rf "$TMP/subtitles"*
		rm -rf "$TMP/tags.xml"
		rm -rf "$TMP/temp"*
		rm -rf "$TMP/video.avi"
		sleep 1
	# fi
}

function abdvde_create_mkv
{
	unset MKVMERGE_ARGS
	# video
	MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="--default-duration"
	MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="0:${OUTPUT_FRAMERATE}fps"
	MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="--noaudio"
	MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="$TMP/video.avi"
	# audio streams
	for FILE in "$TMP/audio"*; do
		if [ "$FILE" = "$TMP/audio*" ]; then
			break
		fi
		LANGUAGE=`printf "$FILE" | sed -r "s/.*audio\\.[0-9]+\\.([a-z]+)/\\1/"`
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="--language" 
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="0:$LANGUAGE"
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="$FILE"
	done
	# subtitle streams
	for FILE in "$TMP/subtitles"*.idx; do
		if [ "$FILE" = "$TMP/subtitles*.idx" ]; then
			break
		fi
		LANGUAGE=`printf "$FILE" | sed -r "s/.*subtitles\\.[0-9]+\\.([a-z]+)\\.idx/\\1/"`
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="--language" 
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="0:$LANGUAGE"
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="--stracks"
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="0"
		MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="$FILE"
	done
	# tags
	MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="--global-tags" 
	MKVMERGE_ARGS[${#MKVMERGE_ARGS[@]}]="$TMP/tags.xml"
	printf "Muxing everything together: "
	mkvmerge -o "$BASENAME.mkv" --chapters "$TMP/chapters.txt" "${MKVMERGE_ARGS[@]}" > /dev/null
	printf "\"$BASENAME.mkv\" created.\n"
}

function abdvde_detect_crop
{
	printf "Detecting crop widnow: "
	WIDTH=0
	HEIGHT=0
	LEFT=0
	TOP=0
	if [ `printf "$LENGTH" | tr -d .` -lt 2000 ]; then
		WIDTH=720
		case "$FORMAT" in
			"NTSC")
				HEIGHT=480
				;;
			"PAL")
				HEIGHT=576
				;;
		esac
	else
		for I in `seq 8 120`; do
			OFFSET=$(( `printf "$LENGTH" | tr -d .` * $I / 128000 ))
			TEMP=`mplayer dvd://${TITLE} -dvd-device "$INPUT" -vo null -nosound -benchmark -vf cropdetect=24:0 -ss ${OFFSET} -frames 4 2>/dev/null | grep crop= | tail -n 1 | grep -o -E "[0-9]+:[0-9]+:[0-9]+:[0-9]+"`
			NEWWIDTH=`printf "$TEMP" | sed -r "s/([0-9]+):.+/\\1/"`
			if printf "$NEWWIDTH" | grep -E "[0-9]+" > /dev/null; then
				if [ $WIDTH -lt $NEWWIDTH ]; then
					WIDTH=$NEWWIDTH
					LEFT=`printf "$TEMP" | sed -r "s/[0-9]+:[0-9]+:([0-9]+):.+/\\1/"`
				fi
			fi
			NEWHEIGHT=`printf "$TEMP" | sed -r "s/[0-9]+:([0-9]+):.+/\\1/"`
			if printf "$NEWHEIGHT" | grep -E "[0-9]+" > /dev/null; then
				if [ $HEIGHT -lt $NEWHEIGHT ]; then
					HEIGHT=$NEWHEIGHT
					TOP=`printf "$TEMP" | sed -r "s/[0-9]+:[0-9]+:[0-9]+:([0-9]+)/\\1/"`
				fi
			fi
		done
	fi
	CROP="$WIDTH:$HEIGHT:$LEFT:$TOP"
	printf "$CROP\n"
}

function abdvde_detect_telecine
{
	unset TELECINE_METHOD
	printf "Detecting telecine method: "
	# foramt and framerate
	case "$FORMAT" in
		"NTSC")
			mplayer -dvd-device "$INPUT" dvd://${TITLE} -vo null -nosound -quiet -benchmark 2>"$TMP/mplayer_output_2" > "$TMP/mplayer_output_1"
			DEMUX_MPG_COUNT=`grep "demux_mpg" "$TMP/mplayer_output_1" | wc -l`
			if [ "$DEMUX_MPG_COUNT" = "0" ]; then
				FRAMES=$(( `printf "$LENGTH" | tr -d .` * 30000 / 1001000 ))
				INPUT_FRAMERATE="30000/1001"
			elif [ "$DEMUX_MPG_COUNT" = "1" ]; then
				FRAMES=$(( `printf "$LENGTH" | tr -d .` * 24000 / 1001000 ))
				INPUT_FRAMERATE="24000/1001"
			else
				FRAMES=$(( `printf "$LENGTH" | tr -d .` * 30000 / 1001000 ))
				INPUT_FRAMERATE="VFR"
			fi
			;;
		"PAL")
			FRAMES=$(( `printf "$LENGTH" | tr -d .` * 25 ))
			INPUT_FRAMERATE="25"
			;;
	esac
	#detect telecine method
	case "$INPUT_FRAMERATE" in
		"24000/1001")
			TELECINE_METHOD="24000/1001p soft telecined to 30000/1001t"
			PROGRESSIVE_PERCENTAGE=100
			printf "${TELECINE_METHOD}. Input is ${PROGRESSIVE_PERCENTAGE}%% progressive\n"
			;;
		"25")
			TELECINE_METHOD="25p telecined to 25i"
			PROGRESSIVE_PERCENTAGE="unknown"
			printf "Unknown. Assuming ${TELECINE_METHOD}\n"
			;;
		"30000/1001")
			# look for 24000/1001
			mencoder dvd://"$TITLE" -dvd-device "$INPUT" -fps 30000/1001 -vf pullup,softskip,decimate -ofps 24000/1001 -nosound -ovc raw -of avi -o /dev/null 2>"$TMP/temp" >/dev/null
			SKIPPED_FRAMES=`grep "Skipping frame" "$TMP/temp" | wc -l`
			if [ $SKIPPED_FRAMES -eq 0 ]; then
				TELECINE_METHOD="24000/1001p hard telecined to 30000/1001t"
				PROGRESSIVE_PERCENTAGE=100
				printf "${TELECINE_METHOD}. Input is ${PROGRESSIVE_PERCENTAGE}%% progressive\n"
			# if less than $INTERLACE_TOLERANCE% is interlaced, than the video was likely edited after it was telecined
			elif [ $SKIPPED_FRAMES -lt $(( $FRAMES * $INTERLACE_TOLERANCE / 100 )) ]; then
				TELECINE_METHOD="24000/1001p hard telecined to 30000/1001t"
				PROGRESSIVE_PERCENTAGE=$(( ( $FRAMES - $SKIPPED_FRAMES ) * 100 / $FRAMES ))
				printf "${TELECINE_METHOD}. Input is ${PROGRESSIVE_PERCENTAGE}%% progressive\n"
			# look for 30000/1001. $SKIPPED_FRAMES should equal $FRAMES / 5
			elif [ $(( $SKIPPED_FRAMES * 500 / $FRAMES )) -gt $(( 100 - $INTERLACE_TOLERANCE )) ]; then
				# is it 30000/1001i or 60000/1001f, hard to tell...
				TELECINE_METHOD="30000/1001p telecined to 30000/1001i"
				PROGRESSIVE_PERCENTAGE="unknown"
				printf "Unknown. Assuming ${TELECINE_METHOD}\n"
			fi
			;;
		"VFR")
			# look for 24000/1001
			mencoder dvd://"$TITLE" -dvd-device "$INPUT" -fps 30000/1001 -vf pullup,softskip,decimate -ofps 24000/1001 -nosound -ovc raw -of avi -o /dev/null 2>"$TMP/temp" >/dev/null
			SKIPPED_FRAMES=`grep "Skipping frame" "$TMP/temp" | wc -l`
			if [ $SKIPPED_FRAMES -eq 0 ]; then
				TELECINE_METHOD="24000/1001p randomly soft and hard telecined to 30000/1001t"
				PROGRESSIVE_PERCENTAGE=100
				printf "${TELECINE_METHOD}. Input is ${PROGRESSIVE_PERCENTAGE}%% progressive\n"
			# if less than $INTERLACE_TOLERANCE% is interlaced, than the video was likely edited after it was telecined
			elif [ $SKIPPED_FRAMES -lt $(( $FRAMES * $INTERLACE_TOLERANCE / 100 )) ]; then
				TELECINE_METHOD="24000/1001p randomly soft and hard telecined to 30000/1001t"
				PROGRESSIVE_PERCENTAGE=$(( ( $FRAMES - $SKIPPED_FRAMES ) * 100 / $FRAMES ))
				printf "${TELECINE_METHOD}. Input is ${PROGRESSIVE_PERCENTAGE}%% progressive\n"
			fi
			;;
	esac
	if [ "$TELECINE_METHOD" = "" ]; then
		TELECINE_METHOD="unknown"
		PROGRESSIVE_PERCENTAGE=$(( ( $FRAMES - $SKIPPED_FRAMES ) * 100 / $FRAMES ))
		printf "Unknown. Assuming VFR. ${PROGRESSIVE_PERCENTAGE}%% is progressive material\n"
	fi
}

function abdvde_dump_device
{
	if [ -b "$INPUT" ]; then
		printf "Dumping \"$INPUT\" to your hard drive..."
			dd if="$INPUT" of="$TMP/dvd.iso" bs=2048 conv=noerror,sync 2>/dev/null
			INPUT="$TMP/dvd.iso"
		printf " done.\n"
	fi
}

function abdvde_encode_video
{
	unset MENCODER_ARGS
	# inverse telecine
	case "$TELECINE_METHOD" in
		"24000/1001p soft telecined to 30000/1001t")
			# 300.1
			# ALPHA_DOG.1
			# AUSTIN_POWERS_2.1
			# BALLISTIC_ECKS_VS_SEVER.1
			# BIGMAMA.1
			# BIG_BULLY.1
			# BLACKSHEEP.1
			# BODY_OF_LIES.1
			# BRAVHART.1
			# CAPN_CORELLIS_MANDOLIN.1
			# CONSTANTINE_DISC_1.1
			# TIM_BURTONS_CORPSE_BRIDE.1
			INPUT_FRAMERATE=""
			MENCODER_FILTERS=""
			OUTPUT_FRAMERATE="24000/1001"
			;;
		"24000/1001p hard telecined to 30000/1001t")
			INPUT_FRAMERATE=""
			MENCODER_FILTERS="filmdint=io=5:4:fast=0,softskip"
			OUTPUT_FRAMERATE="24000/1001"
			;;
		"24000/1001p randomly soft and hard telecined to 30000/1001t")
			# ALIEN_VS_PREDATOR.1
			# AUSTIN_WS.1
			# A_BEAUTIFUL_MIND.1
			# BOOGEYMAN.1
			# CABIN_FEVER.1
			# CHEAPER_BY_THE_DOZEN.1
			# CHILDREN_OF_MEN.1
			# CHRISTMAS_WITH_THE_KRANKS.1
			# FARSCAPE_S2_V1D1.5
			# FARSCAPE_S2_V1D1.10
			# GOLDMEMBER.2
			# TEENAGE_DRAMA_QUEEN.1
			INPUT_FRAMERATE=""
			MENCODER_FILTERS="filmdint=io=5:4:fast=0,softskip"
			OUTPUT_FRAMERATE="24000/1001"
			;;
		"25p telecined to 25i")
			# RICHMAN_POORMAN_DISC1.3
			# RICHMAN_POORMAN_DISC1.4
			INPUT_FRAMERATE=""
			MENCODER_FILTERS="filmdint=io=1:1:fast=0,softskip" # some interlacing sneaks through on frames with little movement
			MENCODER_FILTERS="pullup,softskip" # this works much better
			MENCODER_FILTERS="phase,softskip" # this works best, PAL guys have it easy!
			OUTPUT_FRAMERATE="25"
			;;
		"30000/1001p telecined to 30000/1001i")
			INPUT_FRAMERATE=""
			MENCODER_FILTERS="filmdint=io=1:1:fast=0,softskip"
			OUTPUT_FRAMERATE="30000/1001"
			;;
		"60000/1001f") # not currently used
			;;
		*)
			INPUT_FRAMERATE=""
			MENCODER_FILTERS="filmdint=io=1:4:=fast=0,softskip"
			OUTPUT_FRAMERATE="120000/1001"
			;;
	esac
	# crop
	if [ "$MENCODER_FILTERS" = "" ]; then
		MENCODER_FILTERS="crop=${CROP}"
	else
		MENCODER_FILTERS="${MENCODER_FILTERS},crop=${CROP}"
	fi
	# scale
	MENCODER_FILTERS="${MENCODER_FILTERS},scale=-9:-9"

	CWD=`pwd`
	cd "$TMP"
		printf "Encoding the video stream...\n"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-dvd-device"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="$INPUT"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="dvd://${TITLE}"
		if [ "$INPUT_FRAMERATE" != "" ]; then
			MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-fps"
			MENCODER_ARGS[${#MENCODER_ARGS[@]}]="$INPUT_FRAMERATE"
		fi
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-sws"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="9"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-vf"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="$MENCODER_FILTERS"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-ofps"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="$OUTPUT_FRAMERATE"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-oac"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="copy"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-ovc"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="x264"
		MENCODER_ARGS[${#MENCODER_ARGS[@]}]="-x264encopts"
		if echo "$X264_BITRATE" | grep -E -q "%"; then
			X264_OPTIONS="bitrate="$(( $BITRATE * `echo "$X264_BITRATE" | tr -d "%"` / 100 ))":$X264_OPTIONS"
		else
			X264_OPTIONS="bitrate=$X264_BITRATE:$X264_OPTIONS"
		fi
		if $DEBUG; then
			mencoder "${MENCODER_ARGS[@]}" qp=14:turbo=2:nob_pyramid:nodeblock:nocabac:me=dia:subq=0:threads=0 -of avi -o "$TMP/video.avi" $MENCODER_OPTIONS -msglevel all=1:statusline=5 2>/dev/null | tail -n +3 | head -n 1; printf "\n"
		else
			mencoder "${MENCODER_ARGS[@]}" $X264_OPTIONS:pass=1 -of avi -o /dev/null $MENCODER_OPTIONS -msglevel all=1:statusline=5 2>/dev/null | tail -n +3 | head -n 1; printf "\n"
			mencoder "${MENCODER_ARGS[@]}" $X264_OPTIONS:pass=3 -of avi -o /dev/null $MENCODER_OPTIONS -msglevel all=1:statusline=5 2>/dev/null | tail -n +3 | head -n 1; printf "\n"
			mencoder "${MENCODER_ARGS[@]}" $X264_OPTIONS:pass=2 -of avi -o "$TMP/video.avi" $MENCODER_OPTIONS -msglevel all=1:statusline=5 2>/dev/null | tail -n +3 | head -n 1; printf "\n"
		fi
	cd "$CWD"
	# tag the video
	printf "Creating tags... "
		echo "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" > "$TMP/tags.xml"
		echo "<!DOCTYPE Tags SYSTEM \"matroskatags.dtd\">" >> "$TMP/tags.xml"
		echo "<Tags>" >> "$TMP/tags.xml"
		echo   "<Tag>" >> "$TMP/tags.xml"
		echo     "<Simple>" >> "$TMP/tags.xml"
		echo       "<Name>Source</Name>" >> "$TMP/tags.xml"
		echo       "<String>DVD</String>" >> "$TMP/tags.xml"
		echo       "<Simple>" >> "$TMP/tags.xml"
		echo         "<Name>Volume ID</Name>" >> "$TMP/tags.xml"
		echo         "<String>${VOLUMEID}</String>" >> "$TMP/tags.xml"
		echo       "</Simple>" >> "$TMP/tags.xml"
		echo       "<Simple>" >> "$TMP/tags.xml"
		echo         "<Name>Telecine Method</Name>" >> "$TMP/tags.xml"
		echo         "<String>${TELECINE_METHOD}</String>" >> "$TMP/tags.xml"
		echo       "</Simple>" >> "$TMP/tags.xml"
		echo       "<Simple>" >> "$TMP/tags.xml"
		echo         "<Name>Bitrate</Name>" >> "$TMP/tags.xml"
		echo         "<String>${BITRATE}</String>" >> "$TMP/tags.xml"
		echo       "</Simple>" >> "$TMP/tags.xml"
		echo     "</Simple>" >> "$TMP/tags.xml"
		echo   "</Tag>" >> "$TMP/tags.xml"
		echo   "<Tag>" >> "$TMP/tags.xml"
		echo     "<Simple>" >> "$TMP/tags.xml"
		echo       "<Name>Abdvde Version</Name>" >> "$TMP/tags.xml"
		echo       "<String>${VERSION}</String>" >> "$TMP/tags.xml"
		echo     "</Simple>" >> "$TMP/tags.xml"
		echo   "</Tag>" >> "$TMP/tags.xml"
		echo   "<Tag>" >> "$TMP/tags.xml"
		echo     "<Simple>" >> "$TMP/tags.xml"
		echo       "<Name>Mencoder Filters</Name>" >> "$TMP/tags.xml"
		echo       "<String>${MENCODER_FILTERS}</String>" >> "$TMP/tags.xml"
		echo     "</Simple>" >> "$TMP/tags.xml"
		echo   "</Tag>" >> "$TMP/tags.xml"
		echo   "<Tag>" >> "$TMP/tags.xml"
		echo     "<Simple>" >> "$TMP/tags.xml"
		echo       "<Name>x264encopts</Name>" >> "$TMP/tags.xml"
		echo       "<String>$X264_OPTIONS</String>" >> "$TMP/tags.xml"
		echo       "<Simple>" >> "$TMP/tags.xml"
		echo         "<Name>bitrate</Name>" >> "$TMP/tags.xml"
		if echo "$X264_BITRATE" | grep -E -q "%"; then
			echo       "<String>"$(( $BITRATE * `echo "$X264_BITRATE" | tr -d "%"` / 100 ))"</String>" >> "$TMP/tags.xml"
		else
			echo       "<String>$X264_BITRATE</String>" >> "$TMP/tags.xml"
		fi
		echo       "</Simple>" >> "$TMP/tags.xml"
		echo       "<Simple>" >> "$TMP/tags.xml"
		echo         "<Name>passes</Name>" >> "$TMP/tags.xml"
		echo         "<String>3</String>" >> "$TMP/tags.xml"
		echo       "</Simple>" >> "$TMP/tags.xml"
		echo     "</Simple>" >> "$TMP/tags.xml"
		echo   "</Tag>" >> "$TMP/tags.xml"
		echo "</Tags>" >> "$TMP/tags.xml"
	printf "done\n"
}

function abdvde_extract_audio
{
	printf "Extracting audio streams: "
		for INDEX in `mplayer dvd://${TITLE} -dvd-device "$INPUT" -vo null -nosound -frames 10 2>/dev/null | grep "audio stream" | sed -r "s/audio stream: ([0-9]+).*/\\1/"`; do
			STREAM="$INDEX"
			INDEX=`mplayer dvd://${TITLE} -dvd-device "$INPUT" -vo null -nosound -frames 10 2>/dev/null | grep "audio stream: $INDEX"`
			#AUTIO_FORMAT=`printf "$INDEX" | sed -r "s/.*format: (.+) language.*/\\1/"`
			LANGUAGE=`printf "$INDEX" | sed -r "s/.*language: ([a-z]+) .*/\\1/"`
			if [ "$LANGUAGE" = "unknown" ]; then
				LANGUAGE="en"
			fi
			AID=`printf "$INDEX" | sed -r "s/.*([0-9]{3})\\./\\1/"`
			mplayer dvd://${TITLE} -dvd-device "$INPUT" -aid ${AID} -dumpaudio -dumpfile "$TMP/audio.${STREAM}.${LANGUAGE}" 1>/dev/null 2>&1
			if [ -s "$TMP/audio.${STREAM}.${LANGUAGE}" ]; then
				printf "${LANGUAGE} "
			else
				rm -f "$TMP/audio.${STREAM}.${LANGUAGE}"
			fi
		done
	printf "\n"
}

function abdvde_extract_chapters
{
	printf "Extracting chapter information: "
		dvdxchap -t ${TITLE} "$INPUT" > "$TMP/chapters.txt"
	printf "done\n"
}

function abdvde_extract_subtitles
{
	printf "Extracting subtitles:"
	CWD=`pwd`
	cd "$TMP"
	if [ "$SUBTITLE_STREAMS" -ne 0 ]; then
		poweriso extract "$INPUT" VIDEO_TS/VTS_01_0.IFO -od "$TMP" >/dev/null
		mv "VTS_01_0.IFO" "abdvde.ifo"
		for INDEX in `mplayer dvd://${TITLE} -dvd-device "$INPUT" -v -vo null -nosound -frames 10 2>/dev/null | grep "( sid )" | sed -r "s/subtitle \\( sid \\): ([0-9]).*/\\1/"`; do
			SID="$INDEX"
			INDEX=`mplayer dvd://${TITLE} -dvd-device "$INPUT" -v -vo null -nosound -frames 10 2>/dev/null | grep "subtitle ( sid ): $SID"`
			LANGUAGE=`printf "$INDEX" | sed -r "s/.*language: ([a-z]+)/\\1/"`
			if [ "$LANGUAGE" = "unknown" ]; then
				LANGUAGE="en"
			fi
			mplayer dvd://${TITLE} -dvd-device "$INPUT" -dumpstream -dumpfile /dev/fd/3 3>&1 1>/dev/null 2>/dev/null | \
				tccat -L | \
				tcextract -x ps1 -t vob -a $(( 32 + $SID )) | \
				subtitle2vobsub -o "subtitles."$(( 32 + $SID ))".$LANGUAGE" -i "abdvde.ifo" -a $(( 32 + $SID ))
			printf " ${LANGUAGE}"
		done
		printf "\n"
	else
		printf " None found.\n"
	fi
	cd "$CWD"
	# cleanup
	rm -f "$TMP/abdvde.ifo"
}

function abdvde_get_info_1
{
	mplayer -dvd-device "$INPUT" -msglevel identify=6 -frames 0 dvd:// 2>/dev/null > "$TMP/abdvde.dvd_info"
	VOLUMEID=`grep "ID_DVD_VOLUME_ID" "$TMP/abdvde.dvd_info" | sed -r "s/ID_DVD_VOLUME_ID=(.+)/\\1/"`
	printf "Volume ID: ${VOLUMEID}\n"
	DISCID=`grep "ID_DVD_DISC" "$TMP/abdvde.dvd_info" | sed -r "s/ID_DVD_DISC=(.+)/\\1/"`
	#printf "Disc ID: ${DISCID}\n"
	TITLES=`grep "ID_DVD_TITLES" "$TMP/abdvde.dvd_info" | sed -r "s/ID_DVD_TITLES=([0-9]+)/\\1/"`
	printf "This disc contains $TITLES titles:\n"
	TITLE_LONGEST=0
	TITLE_MOST_AUDIO_STREAMS=0
	TITLE_MOST_SUBTITLE_STREAMS=0
	for I in `seq 1 $TITLES`; do
		mplayer -dvd-device "$INPUT" -msglevel identify=6 -frames 0 dvd://$I 2>/dev/null > "$TMP/abdvde.title_$I.info"
		ANGLES=`grep ID_DVD_TITLE_${I}_ANGLES "$TMP/abdvde.title_$I.info" | sed -r "s/ID_DVD_TITLE_${I}_ANGLES=([0-9]+)/\\1/"`
		CHAPTERS=`grep ID_DVD_TITLE_${I}_CHAPTERS "$TMP/abdvde.title_$I.info" | sed -r "s/ID_DVD_TITLE_${I}_CHAPTERS=([0-9]+)/\\1/"`
		LENGTH=`grep ID_DVD_TITLE_${I}_LENGTH "$TMP/abdvde.title_$I.info" | sed -r "s/ID_DVD_TITLE_${I}_LENGTH=([0-9]+)(\\..*)?/\\1/"`
		printf "  Title $I: $ANGLES angles, $CHAPTERS chapters, $LENGTH seconds long\n"
		AUDIO_STREAMS=`grep "number of audio channels on disk" "$TMP/abdvde.title_$I.info" | sed -r "s/number of audio channels on disk: ([0-9]+)[^0-9]*/\\1/"`
		if [ $AUDIO_STREAMS -ne 0 ]; then
			printf "    $AUDIO_STREAMS audio streams:\n"
			for J in `grep "audio stream: " "$TMP/abdvde.title_$I.info" | sed -r "s/audio stream: ([0-9]+).*/\\1/"`; do
				AUDIO_STREAM="$J"
				J=`grep "audio stream: $J" "$TMP/abdvde.title_$I.info"`
				FORMAT=`printf "$J" | sed -r "s/.*format: (.+) language.*/\\1/"`
				LANGUAGE=`printf "$J" | sed -r "s/.*language: ([a-z]+) .*/\\1/"`
				AID=`printf "$J" | sed -r "s/.*([0-9]{3})\\./\\1/"`
				printf "      $LANGUAGE, $FORMAT\n"
			done
		fi
		SUBTITLE_STREAMS=`grep "number of subtitles on disk" "$TMP/abdvde.title_$I.info" | sed -r "s/number of subtitles on disk: ([0-9]+)/\\1/"`
		if [ $SUBTITLE_STREAMS -ne 0 ]; then
			printf "    $SUBTITLE_STREAMS subtitle streams:\n"
			for J in `grep "( sid )" "$TMP/abdvde.title_$I.info" | sed -r "s/subtitle.+language: ([a-z]{2})/\\1/"`; do
				printf "      $J\n"
			done
		fi
		# guess which title is likely the feature film
		if [ $LENGTH -gt $TITLE_LONGEST ]; then
			TITLES_TO_RIP=$I
			TITLE_LONGEST=$LENGTH
			TITLE_MOST_AUDIO_STREAMS=$AUDIO_STREAMS
			TITLE_MOST_SUBTITLE_STREAMS=$SUBTITLE_STREAMS
		elif [ $LENGTH -eq $TITLE_LONGEST ]; then
			if [ $AUDIO_STREAMS -gt $TITLE_MOST_AUDIO_STREAMS -o $SUBTITLE_STREAMS -gt $TITLE_MOST_SUBTITLE_STREAMS ]; then
				TITLES_TO_RIP=$I
				TITLE_LONGEST=$LENGTH
				TITLE_MOST_AUDIO_STREAMS=$AUDIO_STREAMS
				TITLE_MOST_SUBTITLE_STREAMS=$SUBTITLE_STREAMS
			fi
		fi
	done
}

function abdvde_get_info_2
{
	SUBTITLE_STREAMS=`grep "number of subtitles on disk" "$TMP/abdvde.title_$TITLE.info" | sed -r "s/number of subtitles on disk: ([0-9]+)/\\1/"`
	AUDIO_STREAMS=`grep "number of audio channels on disk" "$TMP/abdvde.title_$TITLE.info" | sed -r "s/number of audio channels on disk: ([0-9]+)[^0-9]*/\\1/"`
	LENGTH=`grep "ID_DVD_TITLE_${TITLE}_LENGTH" "$TMP/abdvde.title_${TITLE}.info" | sed -r "s/.+=(.+)/\\1/"`
	printf "Calculating video bitrate: "
		if $DEBUG; then
			BITRATE=8192
		else
			BITRATE=`mencoder dvd://$TITLE -dvd-device "$INPUT" -nosound -ovc copy -of rawvideo -o /dev/null 2>/dev/null | grep "Video stream" | sed -r "s/Video stream: *([0-9]+)\\..*/\\1/"`
		fi
	printf "$BITRATE\n"
	ASPECT_RATIO=`mplayer dvd://$TITLE -dvd-device "$INPUT" -vo null -nosound -frames 4 2>/dev/null | grep "Movie-Aspect" | sed -r "s/^Movie-Aspect is ([0-9])\\.([0-9]+):.*/\\1\\2/"`
	case `grep "ID_VIDEO_HEIGHT" "$TMP/abdvde.title_${TITLE}.info" | sed -r "s/.+=(.+)/\\1/" | sed -r "s/ID_VIDEO_HEIGHT=([0-9]+)/\\1/"` in
		"480")
			FORMAT="NTSC"
			;;
		"576")
			FORMAT="PAL"
			;;
	esac
}

function abdvde_get_info_user
{
	printf "\n"
	if [ "$BATCH_MODE" != "" ]; then
		case "$BATCH_MODE" in
			"all")
				BASENAME="$VOLUMEID"
				TITLES_TO_RIP=`seq 1 $TITLES`
				printf "Using \"$BASENAME\" as the base filename.\n"
				;;
			"longest")
				BASENAME="$VOLUMEID"
				printf "Using \"$BASENAME\" as the base filename.\n"
				;;
			*)
				if ! printf "$TITLES_TO_RIP" | grep -E -q "( ?[0-9]+)+"; then
					printf "$0: Titles must be a space separated list.\n"
					exit 1
				fi
				BASENAME="$VOLUMEID"
				TITLES_TO_RIP="$BATCH_MODE"
				printf "Using \"$BASENAME\" as the base filename.\n"
				;;
		esac
	else
		BASENAME="$VOLUMEID"
		read -p "Please enter the title(s) you want to rip [$TITLES_TO_RIP]: " USER_TITLE
		case "$USER_TITLE" in
			"");;
			"*")
				TITLES_TO_RIP=`seq 1 $TITLES`
				;;
			*)
				TITLES_TO_RIP="$USER_TITLE"
				;;
		esac
		printf "No more user input required.\n"
	fi
}

function abdvde_help
{
	printf "abdvde is a shell script which automates the process of ripping a DVD to your\n"
	printf "hard drive.\n\n"
	printf "Usage:\n"
	printf "  abdvde [options] [<input>]\n\n"
	printf "Options:\n"
	printf "  -b [all|longest|title(s)]\n"
	printf "    Operate in batch mode. Do not ask the user for anything and rip\n"
	printf "    all, longest, or the specified title(s).\n"
	printf "  -h\n"
	printf "    Display this help message and exit.\n"
	printf "  -i <input>\n"
	printf "    Rip from <input> instead of /dev/dvd. <input> may be a device or an iso.\n"
	printf "  -I\n"
	printf "    Display information about the DVD and exit.\n"
	#printf "  -n N\n"
	#printf "    Add integer N to the niceness (default 20).\n"
	printf "  -v\n"
	printf "    Print the version and exit.\n\n"
	printf "Examples:\n"
	printf "  abdvde -b longest\n"
	printf "    Rips the longest title on /dev/dvd\n"
	printf "  abdvde -b longest disc1.iso\n"
	printf "    Rips the longest titles on disc1.iso and disc2.iso\n"
	exit
}

function abdvde_version
{
	printf "abdvde $VERSION $COPYRIGHT\n"
	exit
}

# defaults
DEBUG=false
INPUT=/dev/dvd
TMP="/tmp"
INTERLACE_TOLERANCE=5 # if less than 5% is interlaced, than the video was likely edited after it was telecined. Perform IVTC and encode CFR.
X264_OPTIONS="keyint=120:keyint_min=1:frameref=16:bframes=16:b_pyramid:direct_pred=auto:weight_b:partitions=all:8x8dct:subq=9:chroma_me:mixed_refs:nofast_pskip:threads=0:nointerlaced"
X264_BITRATE="50%" # this can also be an integer like "2048". Measured in Kb.

# load configuration
if [ -r /etc/abdvde/abdvde.conf ]; then
	. /etc/abdvde/abdvde.conf
fi
if [ -r ~/.abdvde.conf ]; then
	. ~/.abdvde.conf
fi

if $DEBUG; then
	TMP="$TMP/abdvde"
else
	TMP="$TMP/abdvde."`date +%s`
fi
mkdir -p "$TMP"

while getopts "b:hI:v" OPTION; do
	case "$OPTION" in
		"b") BATCH_MODE="$OPTARG";;
		"h") abdvde_help;;
		"I") abdvde_get_info_1; exit;;
		#"n") NICE="$OPTARG";;
		"v") abdvde_version;;
		*) abdvde_help;;
	esac
done
shift $(($OPTIND - 1))
if [ $# -gt 0 ]; then
	INPUT=`readlink -f "$1"`
fi

#------------------------------------------------------------------------------
# prepare environment

trap abdvde_cleanup SIGINT SIGTERM
# ensure "$INPUT" can be read
if [ ! -r "$INPUT" ]; then
	printf "$0: \"$INPUT\" cannot be read.\n"
	exit 1
fi
# ensure there is a DVD in the drive
if [ -b "$INPUT" ]; then
	eject -t "$INPUT" 2>/dev/null
	if ! dd if="$INPUT" of=/dev/null bs=1 count=1 2>/dev/null; then
		while ! dd if="$INPUT" of=/dev/null bs=1 count=1 2>/dev/null > /dev/null; do
			printf "No medium found...\n"
			sleep 10
		done
		filestat "$INPUT" 1>/dev/null 2>/dev/null
		printf "\n"
	fi
fi

#------------------------------------------------------------------------------
# begin execution

# collect information
abdvde_get_info_1
#   VOLUMEID          The Volume ID
#   DISCID            The Disc ID
#   TITLES            The number of titles on the DVD
#   TITLE_LONGEST     The longest title on the DVD
abdvde_get_info_user
#   BASENAME          The base filename to use
#   TITLES_TO_RIP     The title(s) to rip
abdvde_dump_device
for TITLE in $TITLES_TO_RIP; do
	BASENAME="$VOLUMEID.$TITLE"
	printf "\nRipping title $TITLE.\n"
	abdvde_get_info_2
	#   AUDIO_STREAMS         The number of audio streams
	#   SUBTITLE_STREAMS      The number of subtitle streams
	#   LENGTH                The length of TITLE in seconds
	#   FORMAT                NTSC or PAL
	abdvde_detect_telecine
	#   FRAMES                The length of TITLE in frames
	#   TELECINE_METHOD       The method used to telecine TITLE
	abdvde_detect_crop
	#   WIDTH             The width of the video.
	#   HEIGHT            The height of the video.
	#   CROP              The crop window.
	abdvde_extract_audio
	abdvde_extract_subtitles
	abdvde_extract_chapters
	abdvde_encode_video
	#   INPUT_FRAMERATE       The framerate of TITLE
	#   OUTPUT_FRAMERATE      The framerate of the original footage and encoded video
	abdvde_create_mkv
	abdvde_cleanup_title
done
abdvde_cleanup

