#!/bin/bash  
#versión 0.2.0
#By GorristeR 2007. gorrister_ARROBA_linuxmail.org 
#Under GPL License

#480x272 (h264/AVC)
ENCODER_480H264="-acodec aac -ab 128 -vcodec h264 -b 512kb -ar 48000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 480x272 -r 30000/1001 -f psp -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8"

#320x240 (h264/AVC)
ENCODER_320H264="-acodec aac -ab 128 -vcodec h264 -b 512kb -ar 48000 -mbd 2 -coder 1 -cmp 2 -subcmp 2 -s 320x240 -r 30000/1001 -f psp -flags loop -trellis 2 -partitions parti4x4+parti8x8+partp4x4+partp8x8+partb8x8"

#368x208 (MPEG4/SP)
ENCODER_368MPG4="-vcodec xvid -s 368x208 -r 29.97 -qscale 10 -acodec aac -ac 2 -ar 24000 -ab 64 -f psp"

#320x240 (MPEG4/SP)
ENCODER_320MPG4="-vcodec xvid -s 320x240 -r 29.97 -qscale 10 -acodec aac -ac 2 -ar 24000 -ab 64 -f psp"

APP_NAME=`basename $0`
APP_VERSION=0.2.0
ENV="kde"

ShowError () {
	#
	# Muestra una ventana de error
	# Entrada: Texto del error, Caption
	# Salida: nada
	#
	case "$ENV" in 
		"kde" )
			kdialog --error "$1" --caption "$2" --icon error
			;;
	esac
}

ShowPassivePopup () {
	#
	# Muestra una ventana "popup" el tiempo indicado
	# Entrada: Texto, segundos mostrada
	# Salida: nada
	#
	case "$ENV" in
		"kde" )
			kdialog --passivepopup "$1" $2
			;;
	esac
}
ShowErrorLog () {
	#
	# Muestra una ventana con iconos de error que contiene un texto
	# Entrada: Fichero del log, Caption
	# Salida: nada
	#
	case "$ENV" in 
		"kde" )
			kdialog --textbox "$1" 600 550 --caption "$2" --icon error
			;;
	esac
}

ShowOk () {
	#
	# Muestra una ventana de ok
	# Entrada: Texto, Caption
	# Salida: nada
	#
	case "$ENV" in 
		"kde" )
	kdialog --msgbox "$1" --caption "$2" --icon ok
			;;
	esac
}

ShowGetDirectory () {
	#
	# Muestra una ventana para seleccionar un directorio
	# Entrada: Caption, variable de la ultima seleccion (sólo kde) ó directorio inicial (otros)
	# Salida: El nombre del directorio ó "" si no se seleccionó
	#
	local result=""
	case "$ENV" in 
		"kde" )
			result=$(kdialog --getexistingdirectory "$2" --caption "$1");
			;;
	esac
	echo $result
}

ShowRadioList () {
	#
	# Muestra una ventana radiolist con diversas opciones
	# Entrada: Texto descriptivo, Caption, el resto de parámetros son las opciones del radio list
	# Salida: Opción seleccionada
	#
	local result
	local text=$1	
	local caption=$2
	local options
	local i
	shift; shift

	#Hay que pasar las opciones como un array, sino no funciona
	i=0
	while [ -n "$1" ]; do
		options[$i]=$1
		i=$(($i+1))
		shift
	done

	case "$ENV" in 
		"kde" )
			result=$(kdialog --caption "${caption}" --radiolist "${text}" "${options[@]}");
			;;
	esac
	echo $result
}

GetBaseName () {
	#
	# Una versión mejorada del comando "basename", no hace falta especificarle la extensión
	# Entrada: Nombre del fichero
	# Salida: Nombre base sin extensión
	#
	local result
	local ext
	ext=$(echo $1 | sed 's:.*\([\.]\)::')
	result=$(basename "$1" ".$ext")
	echo $result
}

GetTitleFromFileName () {
	#
	# Intenta devolver una cadena de texto que sea lo mejor posible para poner un título
	# a partir de un nombre de fichero. Por ejemplo "The.Halt.Red[SPANISH].[Divx-XDiv].[WWW.XXxXX.Net].avi"
	# devolvería "The Halt Red"
	# Entrada: Nombre del fichero
	# Salida: Titulo
	#
	local result
	local foo

	result=$(GetBaseName "$1")
	#Quitamos corchetes
	foo=$(echo $result | cut -d"[" -f1)
	#Es posible que haya un corchete al principio :(
	[ -z "$foo" ] && foo=$result
	result=$(echo $foo |sed  's/\./\ /g')
	echo $result
}

GetRandom () {
	#
	# Genera un número aleatorio comprendido entre 2 valores, por limitaciones del shell, este número
	# se trata como un entero con signo, así que tiene que ser como mucho 32767
	# Entrada: [Valor mínimo], [valor máximo]
	# Salida: Número generado
	#
	local result=0
	local min=$1
	local max=$2
	[ -z "$min" ] && min=0
	[ -z "$max" ] && max=32767
	while [ "$result" -le $min ]; do
			result=$RANDOM
			let "result %= $max"
	done
	echo $result
}

GetTimeStamp () {
	#
	# Devuelve la fecha del fichero indicado en el formato usado por ffmpeg
	# Entrada: [Nombre del fichero]
	# Salida: Fecha generada del fichero, o se no se indico ninguno, la actual
	#
	local result
	local param_file=""
	[ -n "$1" ] && param_file=-r 
	result=$(date $param_file "$1" +"%F %H:%M:%S")
}

if [ $# -lt 1 ]; then
	ShowError "Esta aplicación no puede ser llamada directamente, es usada por Konqueror."  \
		"Conversor de video a formato PSP versión $APP_VERSION"
	exit 1
fi
dest_folder=$(ShowGetDirectory "$APP_NAME: Selecciona directorio destino" :$APP_NAME-dest_folder)
[ -z "$dest_folder" ] && exit 1

encoder_params=$(ShowRadioList "Selecciona tipo de codificacion (fíjate en tu versión de firmware):" \
 	"$APP_NAME $APP_VERSION" \
	"ENCODER_480H264" "480x272 H264/AVC (firmware >= 3.03 OE-B)" on \
	"ENCODER_320H264" "320x240 H264/AVC (firmware >= 2.0)" off \
	"ENCODER_368MPG4" "368x208 MPEG4/SP (cualquier firmware)" off \
	"ENCODER_320MPG4" "320x240 MPEG4/SP (cualquier firmware)" off)
[ -z "$encoder_params" ] && exit 1

#El prefijo del fichero cambia según la codificación que tenga
file_prefix="MAQ"
[ -n "$(echo $encoder_params |grep MPG4)" ] && file_prefix="M4V"
encoder_params=${!encoder_params}

#El número ficheros que vamos a procesar
files_count=$#
file_num=0
while [ -n "$1" ]; do
	file_num=$(($file_num+1))
	#Generamos un fichero aleatorio que no exista
	file_id=$(GetRandom 10000)
	file_mp4=${dest_folder}/${file_prefix}${file_id}.MP4
	while [ -f "$file_mp4" ]; do
		file_id=$(GetRandom 10000)
		file_mp4=${dest_folder}/${file_prefix}${file_id}.MP4
	done
	
	title=$(GetTitleFromFileName "$1")
	file_thm=${dest_folder}/${file_prefix}${file_id}.THM
	file_info=${dest_folder}/${file_prefix}${file_id}-"${title}".info
	file_log=${dest_folder}/${file_prefix}${file_id}.log
	time_stamp=$(GetTimeStamp "$1")
	time_total=$(mplayer -identify -vc null -vo null -ao null -frames 0 "$1" | grep ^ID_LENGTH | cut -f2 -d"="|  cut -f1 -d".")
	
	
	win_handle=$(kdialog --progressbar "Codificando $title... ($file_num/$files_count)" "$time_total" --caption "$APP_NAME" --icon gear)
	dcop $win_handle showCancelButton true
	ffmpeg -y -i "$1" -title "$title" -timestamp "$time_stamp" $encoder_params "$file_mp4" 2>"$file_log" &
	pid=$!
	sleep 2
	while [ -n "$(ps aux | awk '{print $2}' | grep ^$pid)" ]; do
		if [ "$time_total" != "" ]; then
			time_current=`tail -c 100 "$file_log" | awk -F "time=" {'print $2'} | cut -f1 -d"."`
			dcop $win_handle setProgress $time_current
		fi
		if [ "true" = "$(dcop $win_handle wasCancelled)" ]; then
			kill -9 "$pid"
			dcop $win_handle close
			ShowError "Operación cancelada por $USER" "$APP_NAME $APP_VERSION"
			[ -f "$file_mp4" ] && rm "$file_mp4" 
			exit 1
		fi
		sleep 1 
	done
	
	if [ -f "$file_mp4" ]; then
		dcop $win_handle setProgress $time_total
		dcop $win_handle setLabel "Generando tumbnail..."
		ffmpeg -y -i "$1" -f image2 -ss 5 -vframes 1 -r 1 -s 160x120 -an "$file_thm" 2>/dev/null
		dcop $win_handle setLabel "Creando fichero info..."
		touch "$file_info"
		dcop $win_handle close
		if [ $file_num -eq $files_count ]; then
			ShowOk "$title\n $file_mp4\n Todo sin problemas. ($file_num/$files_count)" "$APP_NAME $APP_VERSION"
		else
			ShowPassivePopup "$title. Creado sin problemas. ($file_num/$files_count)" 3
		fi
		[ -f "$file_log" ] && rm "$file_log" 
	else
		dcop $win_handle close
		ShowErrorLog "$file_log" "$APP_NAME: Error durante la codificación"
		ShowError "No se pudo generar el video\n $title" "$APP_NAME $APP_VERSION"
		[ -f "$file_log" ] && rm "$file_log" 
		#No entiendo esto: Sé que hay un error pq no se ha generado el fichero
		#Aunque luego si está "corrupto" en el disco. por eso lo borro aqui
		[ -f "$file_mp4" ] && rm "$file_mp4" 
		exit 1
	fi
	shift
done
exit 0