#/bin/ksh 
#!/bin/sh 

# Copyright by Krzysztof Krakowiak, 2011.
# Feel free to redistribute under GPL 2.0(or any later) license terms
# Contact me at krzysztof.krakowiak@gmail.com


# To install, simply put in i.e. into /usr/local/bin and make correct symlinks



function install
{
	if [ -d "$1" ]; then
		dest="$1"
	else
		if [ -d "/usr/local/bin" ]; then
			dest=/usr/local/bin
		else
			dest=/usr/bin
		fi
	fi
	cp "$0" "$dest/" && chmod a+rx "$dest/$basename" \
		&& for i in flac vorbis mp3 aac; do
			ln -s "$basename" "$dest/any2$i"
		done \
		&& echo "'$basename' succesfully installed to '$dest'" \
		|| (echo "ERROR: Cannot install '$basename' to '$dest'" >&2; return 1)

	return 0
}

function is_quality
{
	q="$1"
	[ -n "$q" ] && [[ "$q" == +([0-9-]) ]] && [ "$q" -ge "-10" ] && [ "$q" -le "10" ]
}

function set_enc
{
	case "$1" in
		?lac|?LAC)
			enc_pipe="flacenc name=enc quality=8"; # Higher quality there means longer encoding and potentially smaller file size!
			extension=flac;;
		?orbis|VORBIS|OGG|?gg|?ga|og?)
			enc_pipe="vorbisenc name=enc quality=`echo "scale=1; $quality/10"|bc` ! oggmux";
			#enc_pipe="vorbis name=enc quality=`echo "scale=1; $quality/10"|bc` ! oggmux";
			extension=ogg;;
		mp3|MP3)
			enc_pipe="lamemp3enc target=quality quality=$quality ! id3v2mux";
			extension=mp3;;
		aac|AAC)
			#enc_pipe="dmaienc_aac outputformat=2 ! qtmux";
			enc_pipe="faac ! qtmux";
			extension=m4a;;
		#dts|DTS)
		#	enc_pipe="matroskamux";
		#	extension=mka;;
		mk?|MK?|?atroska|MATROSKA)
			enc_pipe="matroskamux";
			extension=mka;;
		#ape|APE)
		#	enc_pipe="";
		#	extension=ape;;
		pgmc|PGMC)
			banner;
			exit 0;;
		*)
			return 99;;
	esac
}

function recode
{
	iFile="$1" oFile="$2"
	
	#"$GST_LAUNCH_BIN" uridecodebin uri=file:"$iFile" ! audioconvert ! audioresample ! $enc_pipe ! filesink location="$oFile"
	#gst-launch -p filesrc location="$iFile" ! decodebin ! audioconvert ! audioresample ! $enc_pipe ! filesink location="$oFile"
	"$GST_LAUNCH_BIN" filesrc location="$iFile" ! decodebin ! audioconvert ! audioresample ! $enc_pipe ! filesink location="$oFile"
	result=$?
	if [ "$result" != "0" ]; then
		echo ERROR: Command \'filesrc location="$iFile" ! decodebin ! audioconvert ! audioresample ! $enc_pipe ! filesink location="$oFile"\' exited with status: $result >&2
		if [ "$exit_on_gstrerr" = "yes" ]; then
			exit $result
		fi
		if [ "$copy_on_gstrerr" = "yes" ]; then
			echo -e "-- Copying \'$iFile\' to \'$oFile\'"
			cp "$iFile" "$oFile"
		fi

	else
		echo -e "-- Succesfully transcoded '$iFile' to '$oFile'\n"
	fi
}

function print_centered
{
	t_width="`tput cols`"

	ctr=0
	for text; do
		let align=t_width-${#text}
		let align/=2
		for i in `seq $align`; do
			echo -n " "
		done
		echo "$text"
	done
}

function banner
{
	# vim-made banner by Krzysztof Krakowiak
	el[1]="          ________       ________            "
	el[2]="             _____\     /_____               "
	el[3]="                ___\ ^ /___                  "
	el[4]="       ____  _ _ _  \ /  ___ ___ ___ ___     "
	el[5]="  --- /  _||/ |_| |  +  /   |   | * |  _| ---"
	el[6]=" --- /  _/ / / / /_    / /-/ / /   <  _/ --- "
	el[7]="     \__/\__/_/\__/    \__/\__/_/__/__/      "

	# Figlet generated banner using font "rectangles" (by David Villegas)
	pl[1]=" _____                   ___     _    _____     _                         2011"
	pl[2]="|  _  |___ _ _ _ ___ ___|  _|_ _| |  |   __|___| |_ ___ ___ ___ _____ ___ ___ "
	pl[3]="|   __| . | | | | -_|  _|  _| | | |  |  |  |_ -|  _|  _| -_| .'|     | -_|  _|"
	pl[4]="|__|  |___|_____|___|_| |_| |___|_|  |_____|___|_| |_| |___|__,|_|_|_|___|_|  "
	pl[5]="  _____         _          _____                     _           "
	pl[6]=" |     |_ _ ___|_|___     |     |___ ___ _ _ ___ ___| |_ ___ ___ "
 	pl[7]=" | | | | | |_ -| |  _|    |   --| . |   | | | -_|  _|  _| -_|  _|"
	pl[8]=" |_|_|_|___|___|_|___|    |_____|___|_|_|\_/|___|_| |_| |___|_|  "
	 
	echo -e "\n[PGMC] - Powerful Gstreamer-based Music Converter (by Krzysztof Krakowiak)\nSend any suggestions/bugs/patches to krzysztof.krakowiak@gmail.com\nFeel free to distribute under GPL/BSD (whatever version you want) terms."
	#print_centered "" "[PGMC] - Powerful Gstreamer-based Music Converter (by Krzysztof Krakowiak)" "Send any suggestions/bugs/patches to krzysztof.krakowiak@gmail.com" "Feel free to distribute under GPL/BSD (whatever version you want) terms."
	print_centered "${el[@]}" "" "- presents -   " "${pl[@]}" "" "TIP: To learn how to use this script, type '$basename usage'"


}

function usage
{
	echo -e "Powerful Gstreamer-based Music Converter by Krzysztof Krakowiak\n"

	echo -e "Usage: $basename iDir/iFile [oDir]/[oFile] [enCoder] [Quality]\nWhere:\n\tiDir  - directory with files to be converted\n\tiFile - single sound file to be converted\n\toDir  - directory where converted files should be put in\n\toFile - output(converted) file [only valid if iFile is specified, not iDir!]\n\tenCoder - audio encoder/container like mp3/vorbis/flac..etc\n\n* If [iFile] is detected to be existing directory, then its used as [iDir]. Same apply for [oFile].\n* If [oDir] is not given, then [iDir] value is used as [oDir]\n* While all args, but [iDir/iFile], are optional, they must appear in correct order.\n* If [enCoder] is not specified, then $AUDIO_ENCODER env var is used(if not empty). Otherwise 'format' from 'any2format'[appname, current: '$basename'] (i.e. mp3 from any2mp3)\n* When last arg is decimal value between -10 and 10, then its alawys threated then as 'Quality', not 'oFile'!. Quality is only valid for Vorbis and MP3 for now(ignored for other encoders). [default value: $DEFAULT_QUALITY].\n\nHonored environment variables:\n\t\$OVERWRITE_FILES=yes|no|ask [default: ask]\n\t\$EXIT_ON_GSTREAMER_ERROR=yes|no [default: no]\n\t\$COPY_ON_GSTREAMER_ERROR=yes|no [default: yes]\n\t\$AUDIO_ENCODER (for details, check code)\n\t\$GST_LAUNCH_BIN - 'gst-launch' binary executable name(and/or path to it)\n\nTo install, simply call: '$basename install [destination]'\n\t[destination] must in in your \$PATH env var.\n\tIf [destination] is not specified, then '/usr/local/bin' if exists or '/usr/bin' is used. (you need sudo/root acount for that)"
}

function warn_skip
{
	iFile="$1" oFile="$2"
	echo "WARNING: Skipping recode of '$iFile', because destination '$oFile' alreay exists" >&2
}

function warn_over
{
	iFile="$1" oFile="$2"
	echo "WARNING: Overwriting '$oFile'!" >&2
}

function process_files
{
	typeset iDir oDir iFile oFile tmp

	if [ -r "$1" ]; then

		# Quality must be set before defining Encoding Pipe!		
		for tmp in "$4" "$3" "$2" "$DEFAULT_QUALITY"; do
			if [ ! -d "$tmp" ] && is_quality "$tmp"; then
				quality="$tmp"
				break
			fi
		done
		# Quality is known, so we can set Encoding Pipe
		for tmp in "$4" "$3" "$2" "$AUDIO_ENCODER" "`echo $basename | sed 's/^[[:alpha:]]*2//'`"; do
			if set_enc "$tmp"; then
				encoder="$tmp"
				break
			fi
		done

		if [ -f "$1" ]; then
			iFile="$1"
		else
			if [ -d "$1" ]; then
				iDir="$1"
			else
				echo "ERROR: '$1' is not file or directory" >&2
				exit 103
			fi
		fi

		if ! set_enc "$encoder"; then # Encoding pipe must be set there, because file extension is defined there
			echo "General ERROR: '$encoder' from '$basename' not supported!\n\nType '$basename usage' for more info, or open 'basename' in text editor if you got any programming skills."
			exit 99
		fi

		if [ -d "$2" ]; then
			oDir="$2"
		else
			if [ -n "$2" ]; then
				oFile="$2"
			else
				if [ -z "$iDir" ]; then
					oDir="`dirname \"$iFile\"`"
				else
					oDir="$iDir"
				fi
			fi
			oDir="`dirname \"$oFile\"`"
		fi
		if [ -f "$iFile" ]; then
			oFile="$oDir/`basename \"$iFile\" | sed 's/\.[[:alnum:]]*$/'.$extension/`"
		fi
		if ! [ -w "$oDir" ]; then
			echo "ERROR: You don't have permission to write inside '$oDir' directory" >&2
			exit 107
		fi

		if [ -n "$iFile" ]; then
			echo "-- Transcoding '$iFile' into '$oFile'"
			if [ -f "$oFile" ]; then
				case "$overwrite_files" in
					yes|YES|Yes) warn_over "$iFile" "$oFile"; recode "$iFile" "$oFile" ;;
					no|NO|No) warn_skip "$iFile" "$oFile";;
					*) echo "Do you want to overwrite '$oFile'?"; select choice in "Overwrite once" "Skip once" "Always overwrite" "Always skip" "Abort conversion"; do 
						repeat=no
						case "$choice" in
							"Overwrite once") warn_over "$iFile" "$oFile";  recode "$iFile" "$oFile" >&2; break;;
							"Skip once") warn_skip "$iFile" "$oFile"; break;;
							"Always overwrite") overwrite_files=yes; warn_over "$iFile" "$oFile"; recode "$iFile" "$oFile"; break;;
							"Always skip") overwrite_files=no; warn_skip "$iFile" "$oFile"; break;;

							"Abort conversion") echo "WARNING: Aborting on user request!" >&2; exit 127;;
							*)  echo "\nInvalid Choice\n" >&2; repeat=yes;;
						esac
						if [ "$repeat" = "no" ]; then
							break
						fi
				 	done;;
				esac
			else
				recode "$iFile" "$oFile"
			fi
		else # is Directory
			typeset file_path filename
			for file_path in "$iDir"/*; do
				filename="`basename \"$file_path\"`"
				if [ -d "$file_path" ]; then
					typeset oDir_new
					oDir_new="$oDir/$filename"
					if [ "$oDir" = "$iDir" ] || [ -d "$oDir_new" ] || mkdir "$oDir_new"; then
						if ! process_files "$file_path" "$oDir_new" "$encoder" "$quality"; then
							echo "ERROR: Something went wrong while executing 'process_files $file_path $oDir_new $encoder $quality'" >&2
							exit 104
						fi
					else
						echo "ERROR: Something went wrong while creating directory '$oDir_new'" >&2
						exit 105
					fi
				else
					if [ -f "$file_path" ]; then
						if ! process_files "$file_path" "$oDir" "$encoder" "$quality"; then
							echo "ERROR: Something went wrong while executing ' process_files $file_path $oDir $encoder $quality'" >&2
							exit 106
						fi
					else
						echo "WARNING: Ignoring '$file_path' which is not file or directory" >&2
					fi
				fi
			done
		fi
	else
		echo "ERROR: You don't have permission to read $1" >&2
		exit 102
	fi
}

basename=`basename "$0"`
DEFAULT_QUALITY=4 # Default value for mp3/Ogg Vorbis VBR encoders

case "$1" in
	help|-help|--help|-h|usage|-usage|--usage)
		usage;;
	install|--install)
		install "$2"; return $?;;
	banner)
		banner;;
	*)
		if [ "${#@}" -lt "1" ]; then
			banner
		else
			for gst_launch_bin in "$GST_LAUNCH_BIN" gst-launch-1.0 gst-launch gst-launch-0.10 GST_LAUNCH_NOT_FOUND; do
				which "$gst_launch_bin" >/dev/null 2>&1 && GST_LAUNCH_BIN="$gst_launch_bin" && break
				if [ "$gst_launch_bin" = "GST_LAUNCH_NOT_FOUND" ]; then
					echo -e "ERROR: Cannot locate 'gst-launch' binary!\nCheck your gstreamer installation >&2"
					exit 100
				fi
			done

			echo "GST_LAUNCH_BIN=$GST_LAUNCH_BIN"

			test -n "$OVERWRITE_FILES" && overwrite_files="$OVERWRITE_FILES" || overwrite_files=ask
			test -n "$EXIT_ON_GSTREAMER_ERROR" && exit_on_gstrerr="$EXIT_ON_GSTREAMER_ERROR" || exit_on_gstrerr=no
			test -n "$COPY_ON_GSTREAMER_ERROR" && copy_on_gstrerr="$COPY_ON_GSTREAMER_ERROR" || copy_on_gstrerr=yes

			process_files "$@"
		fi;;
esac

