#!/bin/bash

usage()
{
	echo "makecd v0.1.4 (part of dvdrtools)"
	[ -n "$1" ] && echo $1
	cat <<EOF
Usage:
makecd [-a bitrate] [-b] [-g] [-k] [-d device] [-f format] [-s standard] [-v bitrate] file1 [file2] ...
	-a:          Set audio bitrate (for DVD images only)
	-b:          Blank CD-RW first
	-g:          GUI mode - make the output GUI parseable
	-k:          Keep ISO file
	-d device:   Use specified device [default: 0,0,0]
	-f format:   Use specified format:
	             data: Normal data CD/DVD
	             dvd: Video DVD
	             audio: Audio CD
                     mp3: MP3 CD (for HW MP3 players)
	             mpeg4: MPEG4 CD/DVD
	-s standard: TV standard (for video DVD)
	             ntsc: NTSC (720x480, 29.970 fps)
	             pal: NTSC (720x576, 25 fps)
	-t dir:      Place temporary files in a directory other
	             than /tmp (they can get big...)
	-v:          Preferred video bitrate (for DVD images only)
	             If given as "x,y", x is the avg. bitrate, y the maximum
	             bitrate.
EOF
	exit 0
}

prompt() {
	if [ -n "$GUIMODE" ]; then
		echo "PROMPT[ok|cancel]: `echo $1 |sed -e 's,\\\n, ,g'`"
	else
		echo -e $1
		echo $"Press return or type \"cancel\" to exit"
	fi
	read a
	[ "`echo $a |tr A-Z a-z`" = "cancel" ] && exit 1
}

# Parse arguments
GUIMODE=""
BLANK=""
KEEP=""
VBITRATE=""
MAXBITRATE=""
AUDIOBITRATE=""
FORMAT="data"
STANDARD=""
DEVICE="dev=0,0,0"
TMP="/tmp/"
PARAM=""
while [ "`echo $1 |cut -b1`" = "-" ]; do
	case $1 in
	-b)
		# Start blanking right away - maybe we're done by the time
		# we actually write something...
		BLANK=done
		dvdrecord $DEVICE blank=fast -v &>/dev/null &
		PARAM="$PARAM -b"
		;;
	-a)
		shift
		ABITRATE="$1"
		;;
	-v)
		shift
		VBITRATE="$1"
		if echo $VBITRATE |grep -q ","; then
			MAXBITRATE=`echo $VBITRATE |sed -e "s%.*,%%"`
			VBITRATE=`echo $VBITRATE |sed -e "s%,.*%%"`
		else
			MAXBITRATE=$(( $VBITRATE + 512 ))
		fi
		;;
	-d)
		shift
		DEVICE="dev=$1"
		PARAM="$PARAM -d $1"
		;;
	-k)
		KEEP=yes
		PARAM="$PARAM -k"
		;;
	-f|--format)
		shift
		FORMAT=`echo $1 |tr A-Z a-z`
		if ! echo $FORMAT |grep -qE '(data|dvd|audio|mp3|mpeg4|vcd|svcd)'; then
			usage $"Unknown format $1"
		fi
		PARAM="$PARAM -f $FORMAT"
		;;
	-g|--gui)
		GUIMODE=yes
		PARAM="$PARAM -g"
		;;
	-s|--standard)
		shift
		STANDARD=`echo $1 |tr A-Z a-z`
		if [ "$STANDARD" != "pal" -a "$STANDARD" != "ntsc" ]; then
			usage $"Unknown standard $1"
		fi
		PARAM="$PARAM -s $STANDARD"
		;;
	-t|--tmp)
		shift
		TMP="`echo $1/ |sed -e 's,//$,/,'`"
		if [ ! -d "$TMP" ]; then
			mkdir -p "$TMP"
			if [ ! -d "$TMP" ]; then
				usage $"Directory $TMP doesn't exist and can't be created."
				exit 1
			fi
		fi
		PARAM="$PARAM -t $TMP"
		;;
	*)
		usage $"WARNING: Unknown flag $1"
		;;
	esac
	shift
done

# Some users apparently like passing us whole directories...
# Catch it, and do what they meant.
# (Yes, this is ugly ;) )
for i in "$@"; do
	if [ -d "$i" ]; then
		SCRIPT=`mktemp /tmp/makecdXXXXXX`
		cat >$SCRIPT <<EOF
#!/bin/bash
$0 $PARAM \\
EOF
		for j in "$@"; do
			if [ -d "$j" ]; then
				find "$j" -type f |while read f; do
					[ -d "$f" ] || echo "	\"$f\" \\" >>$SCRIPT
				done
			else
				echo "	\"$j\" \\" >>$SCRIPT
			fi
		done
		cat >>$SCRIPT <<EOF

rm -f $SCRIPT
EOF
		chmod 0700 $SCRIPT
		exec $SCRIPT
	fi
done

# Generate image...
ISO_FILE=`mktemp $TMP/isoXXXXXX`
ISOSIZE=0
# trap "rm -rf $ISO_FILE" `seq 0 31`
case $FORMAT in
data)
	mkisofs -f -v -J -r -o $ISO_FILE "$@" 2>&1
	FILES="$ISO_FILE"
	ISOSIZE=`ls -l $ISO_FILE |awk '{ print $5; }'`
	;;
dvd)
	[ -z "$ABITRATE" ] && ABITRATE="128"
	[ -z "$VBITRATE" ] && VBITRATE="6000"
	[ -z "$MAXBITRATE" ] && MAXBITRATE="8192"
	if [ -z "$STANDARD" ]; then
		# Check if we're supposed to resize things, and
		# decide on PAL vs. NTSC
		# (Majority decision w/ frame rates)
		NTSC=0
		PAL=0
		for i in "$@"; do
			INFO=`mktemp $TMP/transcodeXXXXXX`
			LANG=C LC_MESSAGES=C tcprobe -i "$i" >$INFO
			FR=`cat $INFO |grep "frame rate:"`
			if [ -n "$FR" ]; then
				FR=`echo $FR |sed -e "s,.*-f ,,;s, .*,,"`
				if [ "$FR" = "25.000" ]; then
					PAL=$(( $PAL + 1))
				elif [ "$FR" = "29.970" -o "$FR" = "30.000" ]; then
					NTSC=$(( $NTSC + 1 ))
				fi
			fi
			rm $INFO
		done
		if [ "$PAL" -ge "$NTSC" ]; then
			STANDARD="pal"
		else
			STANDARD="ntsc"
		fi
	fi
	DIR=`pwd`

	if [ "`echo $STANDARD |tr A-Z a-z`" = "pal" ]; then
		RESIZE="-Z720x576 -f 25"
	elif [ "`echo $STANDARD |tr A-Z a-z`" = "ntsc" ]; then
		RESIZE="-Z720x480 -f 29.970"
	else
		RESIZE="-Z$STANDARD"
	fi
	
	OLDLANG="$LANG"
	export LANG=C # We need to parse the output of other apps
	mkdir $TMP/vobs
	pushd $TMP/vobs
	for i in `seq 1 $#`; do
		FN="track$i.vob"
		INPUT="$1"
		ARGS=""
		[ "`echo $INPUT |cut -b1`" != "/" ] && INPUT="$DIR/$INPUT"
		KEEP_ASR="--keep_asr"
		if echo $INPUT | grep -qE '\.a[0-9]+\.avi$'; then
			# The Archimedis VCR marks the aspect ratio of MPEG-4 files
			# in the filename because normal AVI files don't remember it...
			# Detect and handle those files, adjusting to the closest match.
			# This is greatly suboptimal, but better than nothing
			# (transcode's --import_asr just isn't flexible enough).
			ASPECT=`echo $INPUT | sed -e 's,\.avi$,,;s,.*\.a,,'`
			if [ $ASPECT -le 110 ]; then
				ARGS="--import_asr 1" # <= 1.1:1 -> 1:1
			elif [ $ASPECT -le 155 ]; then
				ARGS="--import_asr 2" # <= 1.55:1 -> 4:3 (1.33:1)
			elif [ $ASPECT -le 199 ]; then
				ARGS="--import_asr 3" # <= 1.99:1 -> 16:9 (1.77:1)
			else
				ARGS="--import_asr 4" # >  1.99:1 -> 2.21:1
			fi
		fi
		if tcprobe -i "$INPUT" |grep -q -E "import frame size:.*4..x(576|480)"; then
			# Weirdo scaled TV must not be rescaled with keep_asr
			# (odd pixel size)
			KEEP_ASR=""
		fi
		# TODO: -A etc. for AC3, ogg support
		ARGS="$ARGS -N 0x50 -y mpeg,mpeg -V -x mplayer,mplayer -F d -w $VBITRATE --video_max_bitrate $MAXBITRATE -b $ABITRATE"
		if ! transcode -i "$INPUT" $ARGS -o tmp $RESIZE $KEEP_ASR; then
			# Try without --keep_asr
			if ! transcode -i "$INPUT" $ARGS -o tmp $RESIZE; then
				# The stream seems to be broken, and mencoder is less
				# picky. This is UGLY, but works
				ASPECT=`mencoder -oac copy -ovc copy "$INPUT" -o "$TMP/fixedstream.avi" 2>/dev/null |grep aspect |sed -e 's,.*aspect *,,;s,).*,,'`
				if ! echo $ARGS |grep -q import_asr; then
					[ -n "$ASPECT" ] && ARGS="$ARGS --import_asr $ASPECT"
				fi
				if ! transcode -i "$TMP/fixedstream.avi" $ARGS -o tmp $RESIZE --keep_asr; then
					if ! transcode -i "$TMP/fixedstream.avi" $ARGS -o tmp $RESIZE; then
						echo "Is this really a video??" >&2
					fi
				fi
				rm -f "$TMP/fixedstream.avi"
			fi
		fi
		tcmplex -o $FN -i tmp.m2v -p tmp.mpa -m d
		VOBS="$VOBS $FN"
		if [ -z "$KEEP" ]; then
			rm -f tmp.m2v tmp.mpa
		else
			mv -f tmp.m2v track$i.m2v
			mv -f tmp.mpa track$i.mpa
		fi
		shift
	done
	ifogen --video $STANDARD --audio mp2 -o "$TMP/image" $VOBS
	ifogen --toc -o "$TMP/image"
	popd
	[ -z "$KEEP" ] && rm -rf "$TMP/vobs"
	mkisofs -dvd-video -udf -o "$ISO_FILE" "$TMP/image"
	[ -z "$KEEP" ] && rm -rf "$TMP/image"
	export LANG="$OLDLANG"
	FILES="$ISO_FILE"
	ISOSIZE=`ls -l $ISO_FILE |awk '{ print $5; }'`
	;;
vcd|svcd)
	WORK="`mktemp -d $TMP/vcdXXXXXX`"
	VCD_FILES=""
	t=0
	pushd "$WORK"
	for i in "$@"; do
		EXTENSION="`echo $i |sed -e 's,.*\.,,'`"
		case $EXTENSION in
		mpg|mpeg|mp1|mp2)
			dvb-mplex -t `echo $FORMAT |tr a-z A-Z` -o track$t.mpg "$i"
			;;
		avi|dv|divx)
			transcode -V -x mplayer,mplayer -y mpeg,mpeg -o tmp$t -N 0x50 -i "$i"
			tcmplex -o "track$t-temp.mpg" -i tmp$t.m2v -p tmp$t.mpa
			rm -f tmp$t.m2v tmp$t.mpa
			dvb-mplex -t `echo $FORMAT |tr a-z A-Z` -o track$t.mpg track$t-temp.mpg
			rm track$t-temp.mpg
			;;
		esac
		VCD_FILES="$VCD_FILES track$t.mpg"
		t=$(( $t + 1 ))
	done
	if [ "$FORMAT" = "vcd" ]; then
		FORMAT="vcd11"
	fi
	vcdimager -t $FORMAT $VCD_FILES

	# We can't handle bin/cue files ATM --> use cdrdao for now
	# Unfortunately this means we can't write VCD/SVCD format data to
	# DVDs for now.
	# Wait until blanking is done...
	while [ -n "`/sbin/pidof dvdrecord`" ]; do
		sleep 1s
	done
	cdrdao write `echo $DEVICE |sed -e "s,^dev=,--device ,"` --driver generic-mmc --overburn videocd.cue
	# rm -f videocd.bin videocd.cue
	popd
	rm -f $ISO_FILE
	;;
audio)
	rm $ISO_FILE
	mkdir -p $ISO_FILE
	TRACK=1
	FILES="-audio -pad"
	for i in "$@"; do
		EXTENSION="`echo $i |sed -e 's,.*\.,,'`"
		case $EXTENSION in
		ogg)
			oggdec -o "$ISO_FILE/track-$TRACK.tmp.wav" "$i"
			;;
		mp1|mp2|mp3)
			lame --decode "$i" "$ISO_FILE/track-$TRACK.tmp.wav"
			;;
		avi|mpg|dv)
			# Hmm... A video. Probably we want the soundtrack.
			rm -f stream.yuv # Workaround for transcode bug
			transcode -x mplayer,mplayer -y null,wav -o /dev/null -m "$ISO_FILE/track-$TRACK.tmp.wav" -i "$i"
			;;
		*)
			# Phew... Let's hope the best
			ln "$i" "$ISO_FILE/track-$TRACK.tmp.wav" || cp "$i" "$ISO_FILE/track-$TRACK.tmp.wav"
			;;
		esac
		sox "$ISO_FILE/track-$TRACK.tmp.wav" -r 44100 -c 2 -w "$ISO_FILE/track-$TRACK.wav" resample || mv -f "$ISO_FILE/track-$TRACK.tmp.wav" "$ISO_FILE/track-$TRACK.wav"
		rm -f "$ISO_FILE/track-$TRACK.tmp.wav"
		FILES="$FILES $ISO_FILE/track-$TRACK.wav"
		# FIXME This is not accurate
		ISOSIZE=$(( $ISOSIZE + `ls -l $ISO_FILE/track-$TRACK.wav |awk '{ print $5; }'` ))
		TRACK=$(( $TRACK + 1 ))
	done
	;;
mp3)
	TMP=`mktemp -d $TMP/mp3cdXXXXXX`
	for i in "$@"; do
		EXTENSION="`echo $i |sed -e 's,.*\.,,'`"
		TARGET="`basename \"$i\" |sed -e \"s,$EXTENSION,mp3,\"`"
		case $EXTENSION in
		ogg)
			oggdec -o "$TMP/track-$TRACK.tmp.wav" "$i"
			lame "$i" "$TMP/$TARGET"
			;;
		mp1|mp2|mp3)
			ln "$i" "$TMP/$TARGET" || cp "$i" "$TMP/$TARGET"
			;;
		avi|mpg|dv)
			# Hmm... A video. Probably we want the soundtrack.
			rm -f stream.yuv # Workaround for transcode bug
			transcode -x mplayer,mplayer -y null,wav -o /dev/null -m "$TMP/$TARGET.wav" -i "$i"
			lame "$TMP/$TARGET.wav" "$TMP/$TARGET"
			rm -f "$TMP/$TARGET.wav"
			;;
		*)
			# Phew... Let's hope the best
			lame "$i" "$TMP/$TARGET"
			;;
		esac
	done
	pushd $TMP
	mkisofs -f -v -J -r -o $ISO_FILE . 2>&1
	popd
	ISOSIZE=`ls -l $ISO_FILE |awk '{ print $5; }'`
	rm -rf $TMP
	;;
mpeg4)
	TMP=`mktemp -d $TMP/mp4cdXXXXXX`
	for i in "$@"; do
		EXTENSION="`echo $i |sed -e 's,.*\.,,'`"
		TARGET="`basename \"$i\" |sed -e \"s,$EXTENSION,avi,\"`"
		if tcprobe -i "$i" 2>&1 |grep -q DIVX; then
			# This is already MPEG-4...
			ln "$i" "$TMP/$TARGET" || cp -a "$i" "$TMP/$TARGET"
		else
			mencoder "$i" -ovc lavc -lavcopts vcodec=mpeg4:vhq:vqmin=2:vqmax=4:lumi_mask=0.05:dark_mask=0.01 -vop pp=de/lb -oac mp3lame -lameopts vbr=0:aq=0:br=128 -sws 2 -o "$TMP/$TARGET"
		fi
	done
	pushd $TMP
	mkisofs -f -v -J -r -o $ISO_FILE . 2>&1
	popd
	FILES="$ISO_FILE"
	ISOSIZE=`ls -l $ISO_FILE |awk '{ print $5; }'`
	rm -rf $TMP
	;;
esac
if [ -z "$FILES" ]; then
	if [ -e "$ISO_FILE" ]; then
		FILES="-data $ISO_FILE"
		ISOSIZE=`ls -l $ISO_FILE |awk '{ print $5; }'`
	else
		# We can't write VCDs yet, so we left it to cdrdao...
		exit 0
	fi
fi
# Wait until blanking is done...
while [ -n "`/sbin/pidof dvdrecord`" ]; do
	sleep 1s
done
while true; do
	ATIP=`dvdrecord -atip $DEVICE 2>&1`
	if echo $ATIP |grep -q "No disk"; then
		eject
		if [ -z "$GUIMODE" ]; then
			prompt $"Please insert a blank disc and press return."
		else
			prompt $"Please insert a blank disc."
		fi
		[ -n "$BLANK" ] && BLANK=yes
	elif echo $ATIP |grep -q "lead out"; then
		# This is a CD-R/CD-RW, not a DVD-R/DVD-RW
		LEADOUT=`echo $ATIP |sed -e "s,.*start of lead out: ,," |awk '{ print $2; }' |sed -e 's,^(,,;s,)$,,;s,:,,;s,/,,'`
		if [ "$LEADOUT" -le 740000 ]; then
			# 640 MB medium
			MAXSIZE=671088640
		elif [ "$LEADOUT" -le 800000 ]; then
			# 700 MB
			MAXSIZE=734003200
		elif [ "$LEADOUT" -le 900000 ]; then
			# 800 MB (?)
			MAXSIZE=838860800
		else
			# 870 MB (?)
			MAXSIZE=912261120
		fi
		if [ "$ISOSIZE" -gt "$MAXSIZE" ]; then
			eject
			SIZE=$(( $ISOSIZE / 1048576 ))
			if [ -z "$GUIMODE" ]; then
				prompt $"This amount of data ($SIZE MB) will not fit on this disc.\nPlease insert a CD-R[W] with more space or a DVD-R[W] and press return."
			else
				prompt $"This amount of data ($SIZE MB) will not fit on this disc.\nPlease insert a CD-R[W] with more space or a DVD-R[W]."
			fi
			[ -n "$BLANK" ] && BLANK=yes
		else
			break
		fi
	else
		# This is a DVD-R/DVD-RW
		if [ "$ISOSIZE" -gt 5046586572 ]; then
			prompt $"Unfortunately this amount of data will not fit on any disc."
			exit 1
		fi
		break
	fi
done

[ "$BLANK" = "yes" ] && dvdrecord $DEVICE blank=fast -v

while ! dvdrecord $DEVICE -gui -delay 1 -eject -v -dao $FILES 2>&1; do
	ATIP=`dvdrecord -atip $DEVICE 2>&1`
	if echo $ATIP |grep -q "No disk"; then
		eject
		if [ -z "$GUIMODE" ]; then
			prompt $"Please insert a blank disc and press return."
		else
			prompt $"Please insert a blank disc."
		fi
		[ -n "$BLANK" ] && BLANK=yes
	elif echo $ATIP |grep -q "lead out"; then
		# This is a CD-R/CD-RW, not a DVD-R/DVD-RW
		LEADOUT=`echo $ATIP |sed -e "s,.*start of lead out: ,," |awk '{ print $2; }' |sed -e 's,^(,,;s,)$,,;s,:,,;s,/,,'`
		if [ "$LEADOUT" -le 740000 ]; then
			# 640 MB medium
			MAXSIZE=671088640
		elif [ "$LEADOUT" -le 800000 ]; then
			# 700 MB
			MAXSIZE=734003200
		elif [ "$LEADOUT" -le 900000 ]; then
			# 800 MB (?)
			MAXSIZE=838860800
		else
			# 870 MB (?)
			MAXSIZE=912261120
		fi
		if [ "$ISOSIZE" -gt "$MAXSIZE" ]; then
			eject
			SIZE=$(( $ISOSIZE / 1048576 ))
			if [ -z "$GUIMODE" ]; then
				prompt $"This amount of data ($SIZE MB) will not fit on this disc.\nPlease insert a CD-R[W] with more space or a DVD-R[W] and press return."
			else
				prompt $"This amount of data ($SIZE MB) will not fit on this disc.\nPlease insert a CD-R[W] with more space or a DVD-R[W]."
			fi
			[ -n "$BLANK" ] && BLANK=yes
		fi
	else
		# This is a DVD(-R/DVD-RW)
		eject
		if [ -z "$GUIMODE" ]; then
			prompt $"Please insert a blank disc and press return."
		else
			prompt $"Please insert a blank disc."
		fi
		[ -n "$BLANK" ] && BLANK=yes
	fi
	[ "$BLANK" = "yes" ] && dvdrecord $DEVICE blank=fast -v
done

if [ -z "$KEEP" ]; then
	for i in $FILES; do
		if [ "`echo $i |cut -c1`" != "-" ]; then
			rm -f $i
		fi
	done
fi
