#!/usr/bin/python
# -*- coding: Utf-8 -*-

import os, glob
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from gui_modules_animation.animation_base import Base
from moteur_modules_animation.mencoder import WidgetMEncoder
from moteur_modules_animation.mplayer import Mplayer

class Animation_MontagVideoVidPlusAudio(QWidget):
	""" --------------------------------------------
	# Cadre accueillant les widgets de :
	# Animation >> Montage vidéo >> Vidéo et Audio
	# -------------------------------------------"""
	def __init__(self, parent):
		QWidget.__init__(self)
		
		# -------------------------------
		# Parametres généraux du widget
		# -------------------------------
		self.base = Base(self) # module de animation
		#=== tout sera mis dans une boîte verticale ===#
		vbox=QVBoxLayout(self)
		
		#=== Variable de configuration ===#
		self.config=parent.config
		
		# Identifiant de la classe
		self.idSection = "Animation - Montage Video et Audio"
		self.base.printSection()
		
		# Création des répertoires temporaires
		self.repTampon = '/tmp/ekd/tampon/temp_anim_montage_video_et_audio/'
		if os.path.isdir(self.repTampon) is False:
        		os.makedirs(self.repTampon)
		
		# Au cas où le répertoire existait déjà et qu'il n'était pas vide -> purge (simple précausion)
		for toutRepCompo in glob.glob(self.repTampon+'*.*'):
			os.remove(toutRepCompo)
		
		# Liste de fichiers initiaux (contenu dans le fichier de configuration)
		self.lstFichiersSource = []
		self.lstFichiersSourceProv = [] # idem mais provisoire (sert à récupérer les chemins dans l'ordre de sélection)
		
		self.lstFichiersSourceAudio = []
		self.lstFichiersSourceProvAudio = []
		
		self.statusBar = parent.statusBar()
		
		# -------------------------------------------------------------------
		# Boîte de groupe : "Fichiers source"
		# -------------------------------------------------------------------
		
		groupSource = QGroupBox(_(u"Fichiers source"))
		
		grid = QGridLayout(groupSource)
		self.ligneEditionSource=QLineEdit()
		self.ligneEditionSource.setReadOnly(True)
		boutParcourirVideo = QPushButton(_(u"Ouvrir Vidéos"))
		boutParcourirVideo.setFocusPolicy(Qt.NoFocus)
		self.connect(boutParcourirVideo, SIGNAL("clicked()"), self.ouvrirSourceVideo)
		grid.addWidget(self.ligneEditionSource,0,0)
		grid.addWidget(boutParcourirVideo,0,1)
		
		self.ligneEditionSourceAudio = QLineEdit()
		self.ligneEditionSourceAudio.setReadOnly(True)
		boutParcourirAudio = QPushButton(_(u"Ouvrir Audio"))
		boutParcourirAudio.setFocusPolicy(Qt.NoFocus)
		self.connect(boutParcourirAudio, SIGNAL("clicked()"), self.ouvrirSourceAudio)
		grid.addWidget(self.ligneEditionSourceAudio,1,0)
		grid.addWidget(boutParcourirAudio,1,1)
		
		vbox.addWidget(groupSource)
		
		# -------------------------------------------------------------------
		# Boîte de groupe "Réglage de sortie de l'encodage"
		# -------------------------------------------------------------------
		
		#=== Création de la boite de groupe de réglage (contenant la boite self.layoutReglage) ===#
		self.base.widgetReglage(vbox, boite='vbox', nomReglage=_(u"Réglage de l'ordre de montage des fichiers audio/video qui vont constituer la vidéo"))
		
		#=== Widget qui seront inclus dans la boite de réglage ===#
		# boite de combo
		self.combo=QComboBox() # le self sert à afficher des informations sur les items à partir de la fonction
		# listeCombo=[(texte, clé QVariant)...]
		listeCombo=[	(_(u'Classement par ordre de sélection') ,'sans_ordre_alpha'),\
				(_(u'Classement par ordre alpha-numérique') ,'avec_ordre_alpha'),]
		
		# Insertion des codecs de compression dans la combo box
		for i in listeCombo:
                	self.combo.addItem(i[0],QVariant(i[1]))
		
		self.connect(self.combo, SIGNAL("activated(int)"), self.ordonnerListeVideo)
		self.connect(self.combo, SIGNAL("activated(int)"), self.ordonnerListeAudio)
		
		self.layoutReglage.addWidget(self.combo, 0, Qt.AlignHCenter)
		
		# Chargement du paramètre de configuration
		try:
			typ = self.config.get(self.idSection,'type_ordre_montage')
			indice = 0 # indice de la ligne de self.listeCombo correspondant au type d'ordre
			for i in listeCombo:
				if i[1]!=typ:
					indice += 1
				else:
					break
			self.combo.setCurrentIndex(indice)
		except:
			self.combo.setCurrentIndex(0)
		
		# ---------------------------
		# Boite de groupe de mplayer
		# ---------------------------
		group=QGroupBox("")
		vboxMplayer = QVBoxLayout(group)
		self.mplayer=Mplayer(taille=self.base.tailleMplayer,
			choixWidget=(Mplayer.PRECEDENT_SUIVANT,Mplayer.CURSEUR_A_PART))
		self.mplayer.listeVideos = self.lstFichiersSource
		self.mplayer.setEnabled(False)
		hbox = QHBoxLayout()
		hbox.addStretch()
		hbox.addWidget(self.mplayer)
		hbox.addStretch()
		vboxMplayer.addLayout(hbox)
		
		self.radioSource = QRadioButton(_(u"vidéo(s) source(s)"))
		self.radioSource.setEnabled(False)
		self.radioSource.setChecked(True)
		self.connect(self.radioSource, SIGNAL("toggled(bool)"), self.fctRadioSource)
		self.radioConvert = QRadioButton(_(u"vidéo convertie"))
		self.radioConvert.setEnabled(False)
		self.connect(self.radioConvert, SIGNAL("toggled(bool)"), self.fctRadioConvert)
		self.radioAudio = QRadioButton(_(u"audio(s) source(s)"))
		self.radioAudio.setEnabled(False)
		self.connect(self.radioAudio, SIGNAL("toggled(bool)"), self.fctRadioAudio)
		hbox = QHBoxLayout()
		hbox.addWidget(self.radioSource)
		hbox.addWidget(self.radioConvert)
		hbox.addWidget(self.radioAudio)
		hbox.setAlignment(Qt.AlignHCenter)
		vboxMplayer.addLayout(hbox)
		
		group.setAlignment(Qt.AlignHCenter)
		vbox.addWidget(group)
		
		# -------------------------------------------------------------------
		# widgets du bas : ligne + boutons Aide et Appliquer
		# -------------------------------------------------------------------
		self.base.widgetBas(vbox)
		
		
		
		# affichage de la boîte principale
		self.setLayout(vbox)
	
	
	def fctRadioSource(self, bool=None):
		""""Communique la vidéo appropriée à mplayer"""
		if bool: self.mplayer.listeVideos = self.lstFichiersSource
	
	def fctRadioAudio(self, bool=None):
		""""Communique la vidéo appropriée à mplayer"""
		if bool: self.mplayer.listeVideos = self.lstFichiersSourceAudio
	
	def fctRadioConvert(self, bool=None):
		""""Communique la vidéo appropriée à mplayer"""
		if bool: self.mplayer.listeVideos = self.lstFichiersSortie
	
	def ordonnerListeVideo(self):
		"""Mets une liste de chemins vidéos dans l'ordre alpha-numérique si tel est le choix de l'utilisateur"""
		i=self.combo.currentIndex()
		idCombo = str(self.combo.itemData(i).toStringList()[0])
		print "Combo :", idCombo
		# Si ordre alpha-numérique choisi, alors on ordonne la liste
		if idCombo == 'avec_ordre_alpha':
			self.lstFichiersSource.sort()
		elif idCombo == 'sans_ordre_alpha':
			self.lstFichiersSource = self.lstFichiersSourceProv[:]
		self.ligneEditionSource.setText(str(self.lstFichiersSource))
		self.config.set(self.idSection,'type_ordre_montage',idCombo)
		if self.radioSource.isChecked(): self.mplayer.listeVideos=self.lstFichiersSource
	
	
	def ordonnerListeAudio(self):
		"""Mets une liste de chemins vidéos dans l'ordre alpha-numérique si tel est le choix de l'utilisateur"""
		i=self.combo.currentIndex()
		idCombo = str(self.combo.itemData(i).toStringList()[0])
		print "Combo :", idCombo
		# Si ordre alpha-numérique choisi, alors on ordonne la liste
		if idCombo == 'avec_ordre_alpha':
			self.lstFichiersSourceAudio.sort()
		elif idCombo == 'sans_ordre_alpha':
			self.lstFichiersSourceAudio = self.lstFichiersSourceProvAudio[:]
		self.ligneEditionSourceAudio.setText(str(self.lstFichiersSourceAudio))
		if self.radioAudio.isChecked(): self.mplayer.listeVideos=self.lstFichiersSourceAudio
	
	
	def widgetReglage(self, vboxParent, nomReglage, boite):
		""" Boîte de groupe de réglage """
		Base.widgetReglage(self, vboxParent, nomReglage, boite)
		self.ordonnerListeVideo
	
	
	def listeChemins(self, ch):
		"""transforme une chaine de caractères en liste de chemins"""
		lst = ch.split("'")
		for i in lst: # i: élément de la ligne
			if (',' in i) or ('[' in i) or (']' in i):
				lst.remove(i)
		return lst
	
	
	def ouvrirSourceAudio(self, nomEntree=None):
		""" Récupération des chemins vidéo sélectionnée """
		
		if self.lstFichiersSourceAudio!=[] and os.path.exists(os.path.dirname(self.lstFichiersSourceAudio[0])):
			repEntree = os.path.dirname(self.lstFichiersSourceAudio[0])
		else: 
			try:
				repEntree = self.config.get('Animation','path_audio')
				if not QFileInfo(repEntree).exists():
					self.config.set('Animation','path_audio','~')
			except:
				self.config.set('Animation','path_audio','~')
				repEntree = '~'
		txt = _(u"Fichiers audio")
		if not nomEntree:
			chemin=QFileDialog.getOpenFileNames(None, _(u"Ouvrir"), os.path.expanduser(repEntree), "%s (*.ogg *.mp3 *.wav *.ac3 *.wmv *.mp2)\n*" %txt)
		else: # module séquentiel
			chemin = nomEntree
		
		if len(chemin)==0: return
		self.config.set('Animation','path_audio',os.path.dirname(str(chemin[0])))
		
		self.lstFichiersSourceAudio = []
		
		for fichier in chemin:
			self.lstFichiersSourceAudio.append(str(fichier))
		
		self.lstFichiersSourceProvAudio = self.lstFichiersSourceAudio[:] # ':' car sinon on créé un alias
		
		# Ordonner la liste si l'option a été sélectionnée et l'afficher dans la ligne d'édition
		self.ordonnerListeAudio()
		
		# Ajoute le paramètre de chemin au tampon de la configuration
		# Il ne sera pas sauvegardé dans le fichier de configuration ici
		self.config.set(self.idSection,'path_audio',str(self.ligneEditionSourceAudio.text()))
		
		self.boutApp.setEnabled(True)
		
		self.mplayer.setEnabled(True)
		self.mplayer.listeVideos = self.lstFichiersSourceAudio
		self.radioAudio.setChecked(True)
		self.radioConvert.setEnabled(False)
		
		if len(self.lstFichiersSource)!=0:
			self.radioSource.setEnabled(True)
			self.radioAudio.setEnabled(True)
		else:
			self.radioSource.setEnabled(False)
			self.radioAudio.setEnabled(False)
		
		self.statusBar.showMessage(_(u"La vidéo résultante ne pourra pas être lue avec tous les logiciels (ex. bon avec mplayer mais pas avec xine)"))
	
	
	def ouvrirSourceVideo(self, nomEntree=None):
		""" Récupération des chemins vidéo sélectionnée """
		
		chemin = self.base.recupSources(nomEntree)
		if not chemin: return
		print "chemin vidéo d'entrée:", chemin, type(chemin)
		
		self.lstFichiersSource = []
		
		for fichier in chemin:
			self.lstFichiersSource.append(str(fichier))
		
		self.lstFichiersSourceProv = self.lstFichiersSource[:] # ':' car sinon on créé un alias
		
		# Ordonner la liste si l'option a été sélectionnée et l'afficher dans la ligne d'édition
		self.ordonnerListeVideo()
		
		self.boutApp.setEnabled(True)
		
		self.mplayer.setEnabled(True)
		self.mplayer.listeVideos = self.lstFichiersSource
		self.radioSource.setChecked(True)
		self.radioConvert.setEnabled(False)
		
		if len(self.lstFichiersSourceAudio)!=0:
			self.radioSource.setEnabled(True)
			self.radioAudio.setEnabled(True)
		else:
			self.radioSource.setEnabled(False)
			self.radioAudio.setEnabled(False)
		
		self.statusBar.showMessage(_(u"La vidéo résultante ne pourra pas être lue avec tous les logiciels (ex. bon avec mplayer mais pas avec xine)"))
	
	
	def afficherAide(self):
		""" Boîte de dialogue de l'aide """
		#self.base.afficherAide(_(u"aide"))
		self.base.afficherAide(_(u"Blablablablablablablablablabla ... blablabla ... blablablabla ... blablabla."))
		'''
		messageAide=QMessageBox(self)
		messageAide.setText(_(u"Blablablabla ... blabla anim_montage_video_vid_plus_audio."))
		messageAide.setWindowTitle(_(u"Aide"))
		messageAide.setIcon(QMessageBox.Information)
		messageAide.exec_()
		'''
		
	
	def appliquer(self, nomSortie=None, ouvert=1):
		"""Fusion de vidéos"""
		
		#=== Récupération de la liste de fichiers ===#
		if not nomSortie:
			cheminVideoSorti=str(QFileDialog.getSaveFileName(None, _(u"Sauver"), os.path.expanduser(os.path.dirname(self.lstFichiersSource[0])), _(u"Tous les fichiers *.*")))
		else: # module séquentiel
			cheminVideoSorti=nomSortie
		
		if cheminVideoSorti=="": return
		
		#=== Chemins de sortie ===#
		# Vidéo
		extVideo=os.path.splitext(self.lstFichiersSource[0])[1] # Extension de fichier: ext
		cheminVideoSorti = cheminVideoSorti+extVideo # Chemin de sortie de la vidéo
		
		# Chemin de sortie temporaire de la vidéo
		cheminVideoProv = self.repTampon+"video"
		
		# Audio
		# Chemin de sortie temporaire de l'audio
		cheminAudioProv = self.repTampon+"audio"
		
		#=== Commande de concaténation basique ===#
		# Concaténation vidéo
		commande = "cat"
		for cheminFichiers in self.lstFichiersSource:
			commande = commande +" \""+cheminFichiers+"\""
		commande = commande + " > " + cheminVideoProv
		
		print "COMMANDE :\n", commande
		os.system(commande)
		
		# Concaténation audio
		commande = "cat"
		for cheminFichiers in self.lstFichiersSourceAudio:
			commande = commande +" \""+cheminFichiers+"\""
		commande = commande + " > " + cheminAudioProv
		
		print "COMMANDE :\n", commande
		os.system(commande)
		
		#=== Commandes de concaténation finale ===#
		# Vidéo
		commande = "mencoder -noidx -audiofile " + cheminAudioProv + " -oac lavc -lavcopts acodec=ac3 -stereo 0 -ovc copy -o " + "\"" + cheminVideoSorti + "\" " + cheminVideoProv
		print "COMMANDE :\n", commande
		#os.system(commande)
		try:
			mencoder = WidgetMEncoder('fusion_audio_et_video_1', (cheminVideoProv, cheminAudioProv), cheminVideoSorti, laisserOuvert=0)
			mencoder.setWindowTitle(_(u"Fusion des fichiers vidéos et audios"))
			mencoder.exec_()
		except:
			messageErrAnEnc=QMessageBox(self)
			messageErrAnEnc.setText(_(u"Problème lors de l'étape 1 finale de concaténation vidéo et audio (mencodeur)"))
			messageErrAnEnc.setWindowTitle(_(u"Erreur"))
			messageErrAnEnc.setIcon(QMessageBox.Warning)
			messageErrAnEnc.exec_()
			os.remove(cheminVideoProv)
			os.remove(cheminAudioProv)
			return
		
		# Audio
		commande = "mencoder -noidx -audiofile " + cheminAudioProv + " -oac copy -stereo 0 -ovc copy -o " + "\"" + cheminVideoSorti + "\" " + cheminVideoProv
		print "COMMANDE :\n", commande
		#os.system(commande)
		try:
			mencoder = WidgetMEncoder('fusion_audio_et_video_2', (cheminVideoProv, cheminAudioProv), cheminVideoSorti, laisserOuvert=ouvert)
			mencoder.setWindowTitle(_(u"Fusion des fichiers vidéos et audios"))
			mencoder.exec_()
		except:
			messageErrAnEnc=QMessageBox(self)
			messageErrAnEnc.setText(_(u"Problème lors de l'étape 2 finale de concaténation vidéo et audio (mencodeur)"))
			messageErrAnEnc.setWindowTitle(_(u"Erreur"))
			messageErrAnEnc.setIcon(QMessageBox.Warning)
			messageErrAnEnc.exec_()
			os.remove(cheminVideoProv)
			os.remove(cheminAudioProv)
			return
		
		# Suppression des fichiers temporaires
		os.remove(cheminVideoProv)
		os.remove(cheminAudioProv)
		
		self.lstFichiersSortie = cheminVideoSorti # pour la boite de dialogue de comparaison
		self.radioConvert.setChecked(True)
		self.radioSource.setEnabled(True)
		self.radioConvert.setEnabled(True)
		self.radioAudio.setEnabled(True)
		return cheminVideoSorti # module séquentiel
	
	
	def sequentiel(self, entree, sortie, ouvert=0):
		"""Utile dans le module du même nom. Applique les opérations de la classe. Retourne le vrai nom du fichier de sortie"""
		self.ouvrirSourceVideo(entree[0])
		self.ouvrirSourceAudio(entree[1])
		return self.appliquer(sortie, ouvert)
	
	
	def sequentielReglage(self):
		"""Utile dans le module du même nom. Récupère le widget de réglage associé à l'identifiant donné en 1er argument. Retourne l'instance du widget de réglage"""
		return self.groupReglage