#!/bin/bash
#
# io GNU/Linux Audio Record Tool
#
# Copyright  (C) 2014 Manu Kebab <io.gnu.linux@free.fr>
#
#------------------------------------------------------


PROGNAME=${0##*/}

set -a
source gettext.sh
set +a
export TEXTDOMAIN="${PROGNAME}"
export TEXTDOMAINDIR="/usr/share/locale"
. /usr/bin/gettext.sh

WINID=""
WIDTH=0
HEIGHT=0
SIZE_X=0
SIZE_Y=0
TIMESTAMP=$(date +%Y%m%d-%Hh%Mm%Ss)
TITLE="$(eval_gettext $'~ io Screencast Recorder ~')"

# create a FIFO file, used to manage the I/O redirection from shell
PIPE=$(mktemp -u --tmpdir ${0##*/}.XXXXXXXX)
mkfifo $PIPE

# attach a file descriptor to the file
exec 3<> $PIPE

# add handler to manage process shutdown
on_exit()
{
	echo "quit" >&3
	rm -f $PIPE
}
trap on_exit EXIT


basic_checks()
{
	# create conf dir, if not existing...
	[ ! -d ~/.config/io-record-tools ] && mkdir -p ~/.config/io-record-tools

	# check if JACK is started
	if jack_control status | grep started
	then
		if egrep ENCODER ~/.config/io-record-tools/screencast.conf
		then
			. ~/.config/io-record-tools/screencast.conf
			recorder_gui
		else
			cat > ~/.config/io-record-tools/screencast.conf << EOF
ENCODER="x264 (high quality)"
SIZE="No resize"
FRAMERATE="10"
AUDIO_SRC="Capture 1-2"
EOF
			. ~/.config/io-record-tools/screencast.conf
			recorder_gui
		fi

	else
		yad --title "${TITLE}" \
		--button="gtk-ok:0" \
		--image=dialog-error \
		--window-icon=multimedia-volume-control \
		--text="$(eval_gettext $'Error, JACK is not running.\\n Aborting...')" \
		--text-align=center
		exit 0
	fi
}



recorder_gui()
{
	YAD_ENCODER=$(echo "x264 (high quality)@huffyuv (lossless)" | sed -e 's/'"${ENCODER}"'@//' | sed -e 's/@'"${ENCODER}"'//')
	YAD_SIZE=$(echo "No resize@HD-1080p (1920x1080)@HD-720p (1280x720)@DVD-Pal (720x576)@480p (640x480)" | sed -e 's/'"${SIZE}"'@//' | sed -e 's/@'"${SIZE}"'//')
	YAD_FRAMERATE=$(echo "10@15@25@30@50@60" | sed -e 's|'"${FRAMERATE}"'@||' | sed -e 's|@'"${FRAMERATE}"'||')
	YAD_CAPTURE=$(echo "Capture 1-2@Capture 3-4@Capture 5-6@Capture 7-8@Capture 9-10" | sed -e 's|'"${AUDIO_SRC}"'@||' | sed -e 's|@'"${AUDIO_SRC}"'||')

	sleep 0.5
	REC_INFOS=$(yad --width 580 --height 380 --title="${TITLE}" \
			--image=/usr/share/icons/Gant/128x128/apps/rec-screencast.png \
			--window-icon=rec-screencast --text-align=center \
			--text="$(eval_gettext $'<b><big><u>io Screencast Recorder</u></big></b>\\nRecord a video of a window or your desktop.\\n\\nConfigure the screencast to your needs and press OK, you will then have to choose the window you want to grab.\\n\\n(to finish the recording click on the Rec icon in the systray)')" \
			--button="gtk-close:1" --button="gtk-ok:0" \
			--field=":LBL" \
			--form --field="$(eval_gettext $'File name:')" \
			--field="$(eval_gettext $'Recording folder:'):DIR" \
			--field=":LBL" \
			--field="$(eval_gettext $'Encoder:'):CB" \
			--field="$(eval_gettext $'Size:'):CB" \
			--field="$(eval_gettext $'Framerate (FPS):'):CB" \
			--field="$(eval_gettext $'Audio input:'):CB" \
			--field=":LBL" \
			--item-separator=@ "" "Rec-${TIMESTAMP}" "" "" "${ENCODER}@${YAD_ENCODER}" "${SIZE}@${YAD_SIZE}" "${FRAMERATE}@${YAD_FRAMERATE}" "${AUDIO_SRC}@${YAD_CAPTURE}")
	ret=$?

	[ "${ret}" -eq 1 ] && exit 0

	CUSTOM_NAME=$(echo "${REC_INFOS}" | cut -d "|" -f2)
	REC_FOLDER=$(echo "${REC_INFOS}" | cut -d "|" -f3)
	REC_ENCODER=$(echo "${REC_INFOS}" | cut -d "|" -f5)
	REC_SIZE=$(echo "${REC_INFOS}" | cut -d "|" -f6)
	REC_FRAMERATE=$(echo "${REC_INFOS}" | cut -d "|" -f7)
	CAPTURE_PORTS=$(echo "${REC_INFOS}" | cut -d "|" -f8)

	if [ -z "${CUSTOM_NAME}" ]
	then
		REC_NAME="Rec-${TIMESTAMP}"
	else
		REC_NAME="${CUSTOM_NAME}"
	fi
	
	if [ "${ret}" -eq 0 ]
	then
		sed -i -r -e 's|ENCODER.*|ENCODER\=\"'"${REC_ENCODER}"'\"|' \
		-e 's|SIZE.*|SIZE\=\"'"${REC_SIZE}"'\"|' \
		-e 's|FRAMERATE.*|FRAMERATE\=\"'"${REC_FRAMERATE}"'\"|' \
		-e 's|AUDIO_SRC.*|AUDIO_SRC\=\"'"${CAPTURE_PORTS}"'\"|' \
		~/.config/io-record-tools/screencast.conf

		if [ "${REC_ENCODER}" = "x264 (high quality)" ]
		then
			VKODER="libx264 -qp 0 -preset ultrafast"
			AKODER="pcm_s16le"
			OUTPUT="mkv"
		elif [ "${REC_ENCODER}" = "huffyuv (lossless)" ]
		then
			VKODER="huffyuv -qp 0"
			AKODER="pcm_s16le"
			OUTPUT="mkv"
		fi

		if [ "${REC_SIZE}" = "No resize" ]
		then
			SCALE_X=
			SCALE_Y=
		elif [ "${REC_SIZE}" = "HD-1080p (1920x1080)" ]
		then
			SCALE_X=1920
			SCALE_Y=1080
		elif [ "${REC_SIZE}" = "HD-720p (1280x720)" ]
		then
			SCALE_X=1280
			SCALE_Y=720
		elif [ "${REC_SIZE}" = "DVD-Pal (720x576)" ]
		then
			SCALE_X=720
			SCALE_Y=576
		elif [ "${REC_SIZE}" = "480p (640x480)" ]
		then
			SCALE_X=640
			SCALE_Y=480
		fi

		if [ "${REC_FRAMERATE}" -eq 10 ]
		then
			FPS=10
		elif [ "${REC_FRAMERATE}" -eq 15 ]
		then
			FPS=15
		elif [ "${REC_FRAMERATE}" -eq 25 ]
		then
			FPS=25
		elif [ "${REC_FRAMERATE}" -eq 30 ]
		then
			FPS=30
		elif [ "${REC_FRAMERATE}" -eq 50 ]
		then
			FPS=50
		elif [ "${REC_FRAMERATE}" -eq 60 ]
		then
			FPS=60
		fi

		CAPTURE_L=$(echo "${CAPTURE_PORTS}" | awk '{print substr($2,1,1)}')
		CAPTURE_R=$((CAPTURE_L+1))

		capture_window
	fi
}


capture_window()
{
	if [ "${WINID}" = "" ]
	then
		wininfo=`LANG="" xwininfo | tr '\n' ' '`
	elif [ "${WINID}" = "root" ]
	then
		wininfo=`LANG="" xwininfo -root | tr '\n' ' '`
	else
		wininfo=`LANG="" xwininfo -id ${WINID} | tr '\n' ' '`
	fi

	regex='Width: *([0-9]+).*Height: *([0-9]+).*Corners: *\+([0-9]+)\+([0-9]+)'

	if [[ "$wininfo" =~ $regex ]]
	then
		WIDTH=${BASH_REMATCH[1]}
		HEIGHT=${BASH_REMATCH[2]}
		POS_X=${BASH_REMATCH[3]}
		POS_Y=${BASH_REMATCH[4]}
	else
		sleep 0.5
		yad --title "~ io Audio Recorder ~" --center \
			--image=dialog-error \
			--window-icon=rec-audio \
			--button=gtk-yes:0 \
			--text="$(eval_gettext $'Error: xwininfo returned wrong Data: ${wininfo}.\\nExiting...')" \
			--buttons-layout=center --text-align=center
		exit 1
	fi

	SIZE_X=$(( $WIDTH / 4 * 4))
	SIZE_Y=$(( $HEIGHT / 4 * 4))

	[ ! "$SIZE_X" = "$WIDTH" ] && echo "(!!!) Width $WIDTH is not a multiple of 4. Truncated to $SIZE_X"

	[ ! "$SIZE_Y" = "$HEIGHT" ] && echo "(!!!) Height $HEIGHT is not a multiple of 4. Truncated to $SIZE_Y"

	run_screencast
}


# add handler for tray icon left click
kill_ffmpeg()
{
	kill -15 SIGKILL `ps -ef | grep ffmpeg | grep "${REC_NAME}" | awk '{ print $2 }'`
	exit 0
}
export -f kill_ffmpeg


run_screencast()
{
	sleep 1
	if [ ! "${SIZE_X}" = "${SCALE_X}" ] || [ ! "${SIZE_Y}" = "${SCALE_Y}" ]
	then
		if [ ! "${SCALE_X}" = "" ] || [ ! "${SCALE_Y}" = "" ]
		then
			ffmpeg -thread_queue_size 512 -f x11grab -r $FPS -s ${SIZE_X}x${SIZE_Y} -i :0.0+${POS_X},${POS_Y} -f jack -ac 2 -r:a 48000 -i screencast -acodec ${AKODER} -vcodec ${VKODER} -vf scale=${SCALE_X}:${SCALE_Y} -threads 0 ${REC_FOLDER}/${REC_NAME}.${OUTPUT} &
		else
			ffmpeg -thread_queue_size 512 -f x11grab -r $FPS -s ${SIZE_X}x${SIZE_Y} -i :0.0+${POS_X},${POS_Y} -f jack -ac 2 -r:a 48000 -i screencast -acodec ${AKODER} -vcodec ${VKODER} -threads 0 ${REC_FOLDER}/${REC_NAME}.${OUTPUT} &
		fi
	elif  [ "${SIZE_X}" = "${SCALE_X}" ] || [ "${SIZE_Y}" = "${SCALE_Y}" ]
	then
		ffmpeg -thread_queue_size 512 -f x11grab -r $FPS -s ${SIZE_X}x${SIZE_Y} -i :0.0+${POS_X},${POS_Y} -f jack -ac 2 -r:a 48000 -i screencast -acodec ${AKODER} -vcodec ${VKODER} -threads 0 ${REC_FOLDER}/${REC_NAME}.${OUTPUT} &
	fi

	sleep 1
	jack_connect "screencast:input_1" "system:capture_${CAPTURE_L}" > /dev/null 2>&1
	jack_connect "screencast:input_2" "system:capture_${CAPTURE_R}" > /dev/null 2>&1

	screencast_notif
}


screencast_notif()
{
	FFMPEG_PID=$(ps -ef | grep ffmpeg | grep "${REC_NAME}" | awk '{ print $2 }')

	if [ -n "${FFMPEG_PID}" ]
	then
		yad --notification --image="gtk-media-record" --command="bash -c kill_ffmpeg" --text="$(eval_gettext $'Stop screencast recording')" --listen ; exit 0
	fi
}


basic_checks
recorder_gui


exit 0
