#! /usr/bin/env bash
# interactive program to convert videos to MPEG so they can play in Rockbox
# Copyright 2008 Christopher Williams
# This is licensed under the GNU General Public License, version 2 or later

# these two values depend on the platform!
screenwidth=220; screenheight=176

# Players                                     LCD size  4:3 video  16:9 video
# iPod Video & Gigabeat                       320x240   320x240    320x180
# iriver H300, iPod Color/Photo & Sansa e200  220x176   220x166    220x124
# iPod Nano                                   176x132   176x128    176x100
# iAudio X5 / M5 and iriver H10 20GB / H120   160x128   160x120    160x90
# iPod Mini 1G / 2G                           138x110   138x104    138x78
# iriver H10 5/6GB                            128x128   128x96     128x72
# Sansa c200                                  132x80    106x80     132x74

# default values
framerate=25
audiobr=64
videobr=256
croptb=0
croplr=0


[ $# -ge 2 ] || {
	echo "Usage: $0 [ -o \"options_to_pass_to_ffmpeg\" ] infile outfile ..."
	echo "  where infile and outfile come in pairs"
	exit
}

opts=

getscreensize()
{
	local w h
	printf "Screen width (default $screenwidth): "
	read w
	screenwidth=${w:-$screenwidth}
	
	printf "Screen height (default $screenheight): "
	read h
	screenheight=${h:-$screenheight}
	
	echo screenwidth=$screenwidth screenheight=$screenheight
}

getaspectratio()
{
	local ar x y eof=true
	echo "Output aspect ratio (5:4 is full screen):"
	select ar in "4:3" "5:4" "16:9" "221:100" "other"; do
		eof=false
		case "$ar" in
		'4:3') x=4; y=3; break;;
		'5:4') x=5; y=4; break;;
		'16:9') x=16; y=9; break;;
		'221:100') x=221; y=100; break;;
		'other') printf 'Other ratio (width height): '; read x y; break;;
		*) echo "please select one of the options!";;
		esac
		eof=true
	done
	$eof && return 1
	
	# "x*h > y*w" is mathematically equivalent to "x/w > y/h", but the
	# former compares only integers (no division hence no fractions)
	local xy yx
	let xy='x*screenheight'
	let yx='y*screenwidth'
	
	if [ $xy -gt $yx ]; then
		# limit width to the screen width
		width=$screenwidth
		# /2*2 makes height a multiple of 2
		let height='(width*y+x)/(2*x)*2'
	else
		# limit height to the screen height
		height=$screenheight
		# /2*2 makes width a multiple of 2
		let width='(height*x+y)/(2*y)*2'
	fi
	echo width=$width height=$height
}

getyesno()
{
	local yn
	while :; do
		printf "%s" "$1"
		read yn
		case "$yn" in
		[Yy]*) return 0;;
		[Nn]*) return 1;;
		*) echo "Please answer 'y' or 'n'";;
		esac
	done
}

getcrop()
{
	# if there are black bars on the top and bottom (such as a 16:9 video
	# playing inside a 4:3 video), the amount to crop is
	#   (h - (w / ar)) / 2
	# where h is the source height, w is the source width, and ar is the
	# output aspect ratio. For 320x240 source video containing a 16:9
	# video, use 30 for top/bottom crop value.
	# (240 - (320 / (16/9))) / 2 = 30.
	printf "Crop top/bottom by amount (in pixels) (default $croptb): "
	read croptb
	
	# the same applies to cropping the sides, except the formula is
	# inverted (I can't be arsed to do that right now :)
	printf "Crop left/right by amount (in pixels) (default $croplr): "
	read croplr
	echo crop top/bottom=$croptb left/right=$croplr
}

getframerate()
{
	local fr r eof=true
	echo "Output frame rate ($framerate):"
	select fr in "24" "25" "29.97" "30" "other"; do
		eof=false
		case "$fr" in
		'24') framerate=24; break;;
		'25') framerate=25; break;;
		'29.97') framerate=29.97; break;;
		'30') framerate=30; break;;
		'other')
			printf 'Other frame rate: '
			read r
			framerate=${r:-$framerate}
			break;;
		*) echo "please select one of the options!";;
		esac
		eof=true
	done
	$eof && return 1
	echo framerate=$framerate
}

getvb()
{
	local vb
	printf "Output video bitrate ($videobr): "
	read vb
	if [ -n "$vb" ]; then videobr="$vb"; fi
	echo videobr=$videobr
}

getab()
{
	local ab
	printf "Output audio bitrate ($audiobr): "
	read ab
	if [ -n "$ab" ]; then audiobr="$ab"; fi
	echo audiobr=$audiobr
}

while [ $# -ge 2 ]; do
	case "$1" in
	-o) echo got option >&2; opts="$2"; shift 2; continue;;
	esac
	infile="$1"
	outfile="$2"
	shift 2
	echo
	echo "Configuration for $infile"
	echo
	if ! { getscreensize &&
	       getaspectratio &&
	       getcrop &&
	       getframerate &&
	       getvb &&
	       getab; }; then
		echo "processing next file..."
		continue
	fi
	ffmpeg -i "$infile" -deinterlace -vcodec mpeg2video -ac 2 -ar 44100 -acodec libmp3lame ${framerate:+-r $framerate} ${croptb:+-croptop $croptb -cropbottom $croptb} ${croplr:+-cropleft $croplr -cropright $croplr} -s ${width}x${height} -vb ${videobr}k -ab ${audiobr}k -f mpeg $opts "$outfile"
done
exit
