#!/bin/bash 

# Ferme de rendu parallélisé pour Cinelerra GG

#	Structure:
#		fab-render.sh	-	Ce script est l'application principale
#		fab-render.py	-	Tinypy script pour le rendu via avidemux  

#	Divers: 
# 		number_of_nodes: Pour du h264, j'utilise un nombre de noeuds fille correspondant à 
#		10% du nombre de threads du pc et ce, afin de garantir une température processeur sous les 90°
#
#		number_of_pipes: number_of_nodes + 1 (cinelerra serveur) * number_of_jobs_per_node
	

destruction_of_the_renderfarm_and_working_directory () {

	# Lister tous les processus cin actifs des port 1030 à 1130 et les détruits
	for i in $(lsof -nP -i tcp:1030-$((1030 + 1130)) | grep LISTEN | grep cin | awk '{print  $2}')
	do
		kill $i
	done
	rm -r "${WORKING_DIRECTORY}" 
}



create_of_the_renderfarm_and_pipe_files () { 

	# Création des répertoires
	mkdir -p "${WORKING_DIRECTORY}" "${WORKING_DIRECTORY}"/pipes "${WORKING_DIRECTORY}"/renderFarm

	# Créer noeuds cinelerraGG qui servirons de client
	for n in $(seq 1030 $((1030 + number_of_nodes)))
	do 
		cin -d $n
	done

	# Création des pipes 	
	for n in $(seq -w 000 $((000 + number_of_pipes + 1)))
	do
		mknod "${WORKING_DIRECTORY}"/pipes/piper$n.yuv p
	done 
}



check_missing_packages () {

	missing_packages=""
	for requirement in ${1} ; do
		[[ ! -a /usr/bin/${requirement} ]] && missing_packages="${missing_packages}\t-${requirement}\n"		
	done

	i=0
	msg[++i]="Paquets nécessaires à l'application:\n\n<b>$missing_packages</b>"
	msg[++i]="\n\nA installer obligatoirement avant de continuer."
	if [[ $missing_packages != "" ]]; then
		zenity  --error \
			--width=200 \
			--title "Erreur de dépendance" \
			--text="${msg[*]}" 
	 	exit 
	fi

	unset i msg
}



check_and_video_rendering () { 

	msg[++i]="\n\t\t\t\t\t\t\t<big><b>Rendu de la partie vidéo</b></big>"
	msg[++i]="\n\nMoi, votre ordinateur, je viens de:"
	msg[++i]="\n\t- Créer, configurer et démarrer les noeuds cinelerra GG."
	msg[++i]="\n\t- Créer les pipes nécessaires."
	msg[++i]="\n\t- Créer les répertoires filles du répertoire <b>$WORKING_DIRECTORY</b>."
	msg[++i]="\n\n\n<u><i>De votre côté, veuillez vous assurer que:</i></u>"
	msg[++i]="\n\n1. La porte frontale du boitier est bien ouverte afin d'améliorer le"
	msg[++i]="\n     refroidissement du Pc."
	msg[++i]="\n\n2. Le proxy est désactivé."
	msg[++i]="\n\n3. Menu /Configuration/Format\n\t- Image/seconde:\t\t\t\t\t\t\t\t\t<b>50.0</b>"
	msg[++i]="\n\t- Largeur:\t\t\t\t\t\t\t\t\t\t\t<b>1920</b>"
	msg[++i]="\n\t- Hauteur:\t\t\t\t\t\t\t\t\t\t\t<b>1080</b>"
	msg[++i]="\n\t- Le modèle couleur:\t\t\t\t\t\t\t\t<b>Yuv-8 bit</b> ou du <b>YUVA 8 bit</b>."
	msg[++i]="\n\n4. Menu /Configuration/Préférences/Performances"
	msg[++i]="\n\t- CPI SMP du projet:\t\t\t\t\t\t\t\t<b>$number_of_threads</b>"
	msg[++i]="\n\t- Utiliser une grappe de calcul pour le rendu:\t<b>coché</b>"
	msg[++i]="\n\t- Délais d'attente du watchdog du client:\t\t<b>60</b>"
	msg[++i]="\n\t- Nombre de travaux à créer:\t\t\t\t\t\t<b>$number_of_pipes</b>"
	msg[++i]="\n\t- Noeuds déclarés\t\tNom d'hôte:\t\t\t<b>localhost</b>"
	msg[++i]="\n\t\t\t\t\t\t\t\tPort: \t\t\t\t\t<b>1030->$((1030 + number_of_nodes))</b>"
	msg[++i]="\n\n5. Menu /fichier/rendu"
	msg[++i]="\n\t- Fichier-type :\t\t\t\t\t\t\t\t\t<b>FFMPEG</b> - <b>yuv</b>"
	msg[++i]="\n\t- Fichier de destination pour le rendu:\t\t\t<b>$WORKING_DIRECTORY/pipes/piper000.yuv</b>"
	msg[++i]="\n\t- Préréglage vidéo :\t\tCompression:\t\t\t<b>raw.yuv</b>"
	msg[++i]="\n\t\t\t\t\t\t\t\tDébit binaire:\t\t\t<b>0</b>"
	msg[++i]="\n\t\t\t\t\t\t\t\tQualité:\t\t\t\t<b>-1</b>"
	msg[++i]="\n\t\t\t\t\t\t\t\tPixels:\t\t\t\t\t<b>yuv420p</b>"
	msg[++i]="\n\n\n<i><b>Après ces vérifications, lancer le rendu puis passer à l'étape suivante.</b></i>"
	zenity --info --width=600 --title="FAB-RENDER" --text="${msg[*]}"

	cd "${WORKING_DIRECTORY}"/pipes

	(ls piper*.yuv | parallel \
	ffmpeg	-f rawvideo \
		-pixel_format yuv420p \
		-video_size 1920x1080 \
		-r 50 \
		-i {} \
		-c:v libx264 \
		-preset slow \
		-crf 20 \
		-vf scale=1280:-1:flags=lanczos \
		-ac 2 \
		-c:a aac \
		-b:a 224k \
		"${WORKING_DIRECTORY}"/renderFarm/{.}.mkv ) | \
	zenity	--progress \
		--title="FAB-RENDER" \
		--text "Rendu vidéo en cours..." \
		--auto-close \
		--no-cancel \
		--pulsate 

	unset i msg
}



concatenate_all_pipe_files () {

	cd "${WORKING_DIRECTORY}"/renderFarm
	
	ffmpeg 	-f concat \
		-safe 0 \
		-i <(for f in ./*.mkv; do echo "file '$PWD/$f'"; done) \
		-c copy \
		piperMux.mkv | \
	zenity 	--progress \
		--title="FAB-RENDER"  \
		--text "Concaténation des fichiers vidéo en cours..." \
		--auto-close \
		--no-cancel \
		--pulsate 
}



check_and_audio_rendering () {

	msg[++i]="\n\t\t\t\t\t\t\t<big><b>  Rendu de la partie audio</b></big>"
	msg[++i]="\n\nMoi, votre ordinateur, je viens de réaliser la concaténation des fichiers vidéo précédemment traités par la ferme de rendu."
 	msg[++i]="\nCe fichier à été sauvé dans le répertoire <b>$WORKING_DIRECTORY/renderFarm</b>."
	msg[++i]="\n\n\n<u><i>De votre côté, veuillez vous assurer que:</i></u>"
	msg[++i]="\n\n1. Menu /Configuration/Préférences/Performances"
	msg[++i]="\n\t- Utiliser une grappe de calcul pour le rendu:\t\t<b>Décoché</b>"
	msg[++i]="\n\n2. Menu /fichier/rendu"
	msg[++i]="\n\t- Fichier-type :\t\t\t\t\t\t\t\t\t\t<b>Microsoft WAV</b>"
	msg[++i]="\n\t- Fichier de destination pour le rendu:\t\t\t\t<b>$WORKING_DIRECTORY/pipes/piper000.wav</b>"
	msg[++i]="\n\t- Préréglage audio :\t\tCompression:\t\t\t\t<b>16 Bits Linear</b>"
	msg[++i]="\n\t\t\t\t\t\t\t\tTramage:\t\t\t\t\t<b>Décoché</b>"
	msg[++i]="\n\n\n<i><b>Après ces vérifications, lancer le rendu et attendre sa fin avant de passer à l'étape suivante.</b></i>" 
	zenity --info --width=610 --title="FAB-RENDER" --text="${msg[*]}"

	unset i msg
}



mixing_video_and_audio () {

	i=0
	msg[++i]="\n\t\t\t\t\t<big><b>  Mixage de la video et de l'audio</b></big>"
	msg[++i]="\n\n\nMoi, votre ordinateur, je vais réaliser le mixage des fichiers vidéo et audio avec les caractéristiques suivante:"
	msg[++i]="\n\n\t-Vidéo\t\t\t\t\tCodec:\t\t\t\t<b>Copie</b>"
	msg[++i]="\n\t-Audio\t\t\t\t\tCodec: \t\t\t<b>AAC (FDK)</b>"
	msg[++i]="\n\t\t\t\t\t\t\tDébit: \t\t\t\t<b>224 Kb</b>"
	msg[++i]="\n\t-Fichier de sortie\t\t\t\t\t\t\t <b>${WORKING_DIRECTORY}/final.mkv</b>"
	zenity --info --width=600 --title="FAB-RENDER" --text="${msg[*]}"

	# Via avidemux
	sleep 2
	avidemux	--load "${WORKING_DIRECTORY}"/renderFarm/piperMux.mkv \
			--run "${DIRECTORY_OF_THIS_SCRIPT}"/fab-render.py \
			--save "${WORKING_DIRECTORY}"/final_via_avidemux.mkv \
			--quit | \
	zenity		--progress \
			--title="FAB-RENDER" \
			--text "Mixage audio/vidéo en cours de traitement..." \
			--auto-close \
			--no-cancel \
			--pulsate
		

	# et/ou via ffmpeg
	sleep 2
	ffmpeg  	-i "${WORKING_DIRECTORY}"/renderFarm/piperMux.mkv \
			-i "${WORKING_DIRECTORY}"/pipes/piper000.wav \
			-c:v copy \
			-c:a libfdk_aac \
			-b:a 224k \
			-shortest \
			"${WORKING_DIRECTORY}"/final_via_ffmpeg\(en_test\).mkv | \
	zenity		--progress \
			--title="FAB-RENDER" \
			--text "Mixage audio/vidéo en cours de traitement..." \
			--auto-close \
			--no-cancel \
			--pulsate 

	unset i msg
}



opening_the_final_rendering_directory () {

	nautilus "$WORKING_DIRECTORY"/ &	

	msg[++i]="\n\t\t\t\t\t\t\t<big><b>Nettoyage</b></big>"
	msg[++i]="\n\n\nMoi, votre ordinateur, je viens d'ouvrir pour vous le contenu du répertoire"
 	msg[++i]="\n<b>$WORKING_DIRECTORY</b>, vous y trouverez le fichier <b>final.mkv</b>."
	msg[++i]="\n\n\n<u><i>De votre côté, assurez-vous que ce fichier correspond à vos besoins."
	msg[++i]="\nSi tel est bien le cas, il y a lieu d'en faire une copie afin de le sauvegarder.</i></u>"
	msg[++i]="\n\n\nEn effet, dès votre validation je vais faire un petit peu de ménage, à savoir:"
	msg[++i]="\n\t- Tuer les noeuds CinelerraGG créés précédemment."
	msg[++i]="\n\t- Supprimer du disque le répertoire <b>$WORKING_DIRECTORY</b> et son contenu."
	msg[++i]="\n\n\n<i><b>Valider pour acter le nettoyage.</b></i>" 
	zenity --info --width=600 --title="FAB-RENDER" --text="${msg[*]}"

	unset i msg
}


main () {

	check_missing_packages "zenity bc ffmpeg avidemux"		

	# Constantes
	readonly WORKING_DIRECTORY="/tmp/fab-render"			
	readonly DIRECTORY_OF_THIS_SCRIPT=$(dirname $0)		

	# Variables
	number_of_threads=$(cat /proc/cpuinfo | grep processor | wc -l)	
	number_of_nodes=$(echo "$number_of_threads / 10" | bc)		
	number_of_jobs_per_node=4 						
	number_of_pipes=$(echo "($number_of_nodes + 1 ) * $number_of_jobs_per_node" | bc) 		

	create_of_the_renderfarm_and_pipe_files			
	check_and_video_rendering			
	concatenate_all_pipe_files		
	check_and_audio_rendering			
	mixing_video_and_audio		
	opening_the_final_rendering_directory		
	destruction_of_the_renderfarm_and_working_directory			
}

main



