Bonsoir
Je suis sous ubuntu 9.10. J'essaye de créer une interface graphique en pyGtk pour Mencoder afin de convertir des vidéos lisible par mon lecteur mp4. Après avoir récupéré le nom des fichiers source, cible et les paramètres de qualité et de format, je construis une commande shell que je lance via subprocess.Popen. Mon programme fonctionne mais je butte sur deux problèmes qui viennent probablement de ma méconnaissance de subprocess :
- J'ai tenté de créer une fonction stop() tuant le processus mais elle en fonctionne pas.
- Je voudrais incrémenter une barre de progression en fonction de l'avancée de l'encodage. J'ai essayé de récupérer la sortie de Mencoder via communicate() mais lorsque je tube les sorties, l'application graphique se fige,donc impossible de traiter quelque information que ce soit. Par ailleurs, lorsque je récupère les sorties, les lignes contenant l'état d'avancement de l'encodage n'apparaissent pas.
Voilà la partie où ce situe le problème.
Code Python :
#!/usr/bin/python
# -*- Encoding: Latin-1 -*-
class encodage_start(gtk.HBox):
"Cette classe créer une zone contenant un bouton pour lacer l'encodage et une barre de progression qui pulsera grace à la methode pulsate. Elle recoit en argument les 2 objets fichiers et video contenant les nom des fichiers et les parametres d'encodage"
def __init__(self,fichiers,video):
gtk.HBox.__init__(self,False,2)
self.fichiers=fichiers
self.video=video
self.button_encoder = gtk.Button("Convertir...",stock=gtk.STOCK_CONVERT)
#Fix me On créer un bouton stop qui ne fonctionne pas pour l'instant
self.button_stop = gtk.Button("Stop",stock=gtk.STOCK_STOP)
self.pack_start(self.button_encoder, False, True, 0)
self.barre=gtk.ProgressBar(adjustment=None)
self.pack_end(self.barre,True,True,0)
self.pack_end(self.button_stop,False,True,0)
self.button_encoder.connect("clicked", self.OnButton_encoder)
self.button_stop.connect("clicked",self.OnButton_stop)
def OnButton_encoder(self,widget):
#On instancie un objet à partir de la classe encodeur qui va lancer mencodeur. On récupère les nom de fichiers grace aux methode get_name() et get_parameters() des objet fichiers et video
self.encodage = encodeur(self.fichiers.get_name(),self.video.get_parameters())
#L'objet encodeur lance mencodeur grace à subprocess.Popen. On lance donc la methode pulsate toutes les 100 ms pour faire defiler la barre de progression.
#fix me Trouver une solution pour faire une veritable barre de progression qui indiquerait l'état d'avancement de l'encodage.
# Lors d'essai avec la récuperation des sorties standard de mencoder grace à la methode communicate(), la barre ne pulse plus.
timer = gobject.timeout_add (100, self.pulsate)
def OnButton_stop(self,widget):
#lance la methode stop de l'objet encodage. Ne fonctionne pas !
self.encodage.stop()
def pulsate(self):
#la methode poll est une sorte de recopie de la methode Popen.poll().Tant qu'elle ne renvoit rien, on fait pulser la barre
while self.encodage.poll() is None:
self.barre.set_text("Encodage en cours, patientez ...")
self.barre.pulse()
return True
#Dès qu'elle renvoit une valeur, c'est que le processus lancé par popen est terminé. Si le returncode est 0, tout va bien c'est terminé
if self.encodage.poll() == 0:
self.barre.set_fraction(1)
self.barre.set_text("Terminé")
return False
#Sinon la fonction renvoit la sortie de mencoder. Celle ci s'affiche dans une boite de message instancié à partir de l'objet BoiteDialogue.
else:
erreur = BoiteDialogue("Erreur lors de l'execution de Mencoder !\n\n\n"+self.encodage.poll())
class encodeur:
"Cette classe lance mencoder à partir de subprocess.Popen. La commande shell est construite en récuperant d'une part les nom de fichiers sources et cible renvoyée par le gui et les parametre sont récupérés dans un fichier .ini lisible par ConfigParser"
def __init__(self,fichiers,parametres):
self.fichiers=fichiers
self.parametres=parametres
self.message=""
ini=ConfigParser.ConfigParser()
ini.read(fichier_ini)
param=ini.get("Qualite",self.parametres[0])+"-"+ini.get("Resolution",self.parametres[1])+"-"+ini.get("Echelle",self.parametres[2])
parametres=ini.get("parametre",param)
self.commande_shell = "mencoder "+self.fichiers[0]+" "+parametres+" -o "+self.fichiers[1]
self.retour = subprocess.Popen(self.commande_shell, shell=True)
def poll(self):
#Cette fonction est proche de subprocess.Popen.poll()
while self.retour.poll() is None:
return None
#Impossible d'avoir un returncode 1 avec try: subprocess.popen(mencoder) en cas d'erreur lors de l'encodage.
#De plus, lorsque on tube les sorties standard et erreur, on arrive plus a faire pulser la barre de progression.
#On a donc recreer une structure try else en utilisant la methode wait() de subprocess.Popen
#Si le returncode est 0, on retourne 0
if self.retour.wait() == 0:
return 0
#Sinon, on refait tourner le programme en ouvrant des tubes pour récupere le message revoyé par mencoder
# pour une fenere de dialogue permettant de debuger
else :
self.retour = subprocess.Popen(self.commande_shell, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True)
self.message= self.retour.communicate()[0]
return self.message
def stop(self):
#Cette methode n'arrête pas le processus.
print "stop"
self.retour.kill()
Voilà, si quelqu'un (ou quelques uns) peuvent éclairer ma lanterne, je lui (ou leur) en saurais fort gré
Si quelqu'un est intéressé par ce qui marche déjà, je suis tout disposé à le transmettre.
Merci d'avance