Gestionnaire de fichiers musicaux

Description

Quand vous extraiiez de la musique depuis un CD, il est courant que votre lecteur appel vos fichiers musicaux "01 piste 01.mp3" par exemple. De plus les TAGs (informations binaires non prise en compte a la lecture classique du fichier) ID3 (associer au fichier mp3), c'est a dire le nom de l'artiste, le nom de l'album (Clique droit -> Propriétés -> Résumé pour ceux qui découvre - Cette procédure est vrai sous Windows !) sont généralement incomplet ! Et cette tache devient longue et très pénible quand vous avez plein de fichier à traité. Ce programme vous permet de traité autant de fichier que vous souhaité, rapidement.

Mon programme utilise deux modules que je n'ai pas écrit pour lire et écrire les TAGs (j'ai bien galèré pour les trouvé). Malheureusement ils ne traitent que les fichier mp3 et pas le wma. C'est pour ça que mon programme ne traite que les fichiers mp3. Si quelqu'un trouve un algoritme pour traité les fichiers wma (supportant également les TAGs), ce n'est pas de refut, mais moi je n'ai plus le courrage. Pour plus d'information sur les TAGs, voir http://fr.wikipedia.org/wiki/ID3 !!!

Source / Exemple :

""" Gestionnaire de fichiers musicaux

Ce programme permet de modifier de façon simple et surtout rapide les TAGs (informations binaires non prise en compte
a la lecture classique du fichier) ID3 (associer au fichier mp3)

Actuelement se programme ne fonctionne que pour les fichiers mp3"""

import wx
import  wx.lib.scrolledpanel as scrolled
import wx.media
from id3reader import *
from ID3Writer import *
import wx.lib.hyperlink as hl
import  wx.html as  html

nombre=['0','1','2','3','4','5','6','7','8','9'] # Tous les chiffres !!! (variable global) 
version ='1.0' # Version du programme (variable global) 



class Aide(wx.Frame):
    def __init__(self, parent):
        "Classe de la fenêtre d'aide"
        wx.Frame.__init__(self, parent, -1,"Aide sur le Gestionnaire de fichiers musicaux", size=wx.Size(1000,700))
        self.SetIcon(wx.Icon("Data\Icone_Aide.ico", wx.BITMAP_TYPE_ICO )) # Icone de la fenêtre

        self.path = "Data\index.htm"
        
        self.html = html.HtmlWindow(self, -1, style=wx.NO_FULL_REPAINT_ON_RESIZE)

        self.printer = html.HtmlEasyPrinting()

        self.box = wx.BoxSizer(wx.VERTICAL)

        self.box.Add(self.html, 1, wx.GROW)
        self.SetSizer(self.box)
        self.SetAutoLayout(True)

        self.Home()


    def Home(self):
        "Charger la page html"
        self.html.LoadPage(self.path)



class About(wx.Dialog):
    def __init__(
            self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition, 
            style=wx.DEFAULT_DIALOG_STYLE
            ):
        'Classe Fenêtre de Dialogue pour le "À propos de ..." (fenêtre 1)'
        pre = wx.PreDialog()
        pre.Create(parent, ID, title, pos, size, style)

        self.PostCreate(pre)

        sizer = wx.BoxSizer(wx.VERTICAL)

        t0=u"Gestionnaire de fichiers musicaux - Version %s" % (version)
        font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
        t1=u"""Imformation juridique sur le programme :

Ce programme est protégé par la loi sur le droit d'auteur. Ce programme est gratuit et libre. Source déposé au prés de CodeS-SourceS

Copyright © "Gestionnaire de fichiers musicaux" - All rights reserved
Merci de votre compréhention"""

        bmp = wx.Bitmap("Data\Musique.bmp", wx.BITMAP_TYPE_BMP)
        mask = wx.Mask(bmp, wx.WHITE)
        bmp.SetMask(mask)
        image=wx.StaticBitmap(self, -1, bmp, (80, 50), (bmp.GetWidth(), bmp.GetHeight()))
        
        text0 = wx.StaticText(self, -1, t0)
        text0.SetForegroundColour(wx.BLUE)
        text0.SetSize(text0.GetBestSize())
        text0.SetFont(font)
        text1 = wx.TextCtrl(self, -1, t1, size=(500,100), style=wx.TE_MULTILINE|wx.TE_READONLY)

        bout1 = wx.Button(self, -1, u"Imformations législatives")
        bout2 = wx.Button(self, -1, u"Imformations complémentaire")
        bout3 = wx.Button(self, -1, u"License du programme")
        bout4 = wx.Button(self, -1, u"Fermer cette fenêtre")
        self.Bind(wx.EVT_BUTTON, self.quitter, bout4)
        self.Bind(wx.EVT_BUTTON, self.leg, bout1)
        self.Bind(wx.EVT_BUTTON, self.lis, bout3)
        self.Bind(wx.EVT_BUTTON, self.info, bout2)
        
        sizer.Add(image, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(text0, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(text1, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        box = wx.BoxSizer(wx.VERTICAL)
        box.Add(bout1, 0, wx.ALIGN_CENTER|wx.ALL|wx.GROW, 5)
        box.Add(bout2, 0, wx.ALIGN_CENTER|wx.ALL|wx.GROW, 5)
        box.Add(bout3, 0, wx.ALIGN_CENTER|wx.ALL|wx.GROW, 5)
        sizer.Add(box, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
        sizer.Add(bout4, 0, wx.ALIGN_CENTER|wx.ALL, 5)

        btnsizer = wx.StdDialogButtonSizer()
        
        self.SetSizer(sizer)
        sizer.Fit(self)
    def quitter(self, evt):
        "Quiiter ==> Sans commenatire ..."
        self.Destroy()
    def leg(self,evt):
        "Les informations législatives : Interressant de savoir ca que dit la loi ..."
        t10=u"Rappel de la légisation Française : Article L. 111-1 / 123-1 du Code de la propriété intellectuelle"
        t11=u"""Article L. 111-1 du Code de la propriété intellectuelle :
        
L'auteur d'une oeuvre de l'esprit jouit sur cette oeuvre, du seul fait de sa création, d'un droit de propriété incorporelle exclusif et opposable à tous.
Ce droit comporte des attributs d'ordre intellectuel et moral, ainsi que des attributs d'ordre patrimonial [...]."""
        t12=u"""Article L. 123-1 du Code de la propriété intellectuelle :
        
L'auteur jouit, sa vie durant du droit exclusif d'exploiter son oeuvre sous quelque forme que ce soit et d'en tirer un profit pécuniaire.
Au décès de l'auteur, ce droit persiste au bénéfice de ses ayants-droits pendant l'année civile en cours et les soixante-dix années qui suivent."""
        dg = fenetreleg(self, -1, u"Imformations législatives",t10,t11,t12, size=(350, 200),
                         style = wx.DEFAULT_DIALOG_STYLE
                         )
        dg.CenterOnScreen()
        val = dg.ShowModal()
    def lis(self,evt):
        "La licence : Libre"
        t10=u"License d'utilisation du Gestionnaire de fichiers musicaux version %s" % (version)
        t11=u"""La présente version du logiciel "Gestionnaire de fichiers musicaux" est gratuite. Vous l'utiliser à votre guise et y apporter toute les modification que vous souhaiter.
Ce qui précède n'exclut pas la possibilité que certaines versions du logiciel deviennent payantes, à l'avenir.

Vous avez le droit d'incorporer le "Gestionnaire de fichiers musicaux" (en tout ou en partie) dans d'autres logiciels ou ensembles logiciels sans demander aucune autorisation à l'auteur."""
        t12=u"""Le "Gestionnaire de fichiers musicaux" est un logiciel libre : son code source peut être modifié voire réutilisé dans d'autres projets sans demander aucune autorisation à l'auteur et redistribution est libre.
Pour plus d'informations à ce sujet, repportez vous à la communoté du "Free".

Copyright © "Gestionnaire de fichiers musicaux".
Tous droits réservé - All rights reserved"""
        dg = fenetreleg(self, -1, u"License du Gestionnaire de fichiers musicaux",t10,t11,t12, size=(350, 200),
                         style = wx.DEFAULT_DIALOG_STYLE
                         )
        dg.CenterOnScreen()
        val = dg.ShowModal()
    def info(self,evt):
        "Un peu d'info sur l'auteur :p"
        dg = fenetreinfo(self, -1, u"Informations complémentaires", size=(350, 200),
                         style = wx.DEFAULT_DIALOG_STYLE
                         )
        dg.CenterOnScreen()
        val = dg.ShowModal()
class fenetreleg(wx.Dialog):
    def __init__(
            self, parent, ID, title,t0,t1,t2, size=wx.DefaultSize, pos=wx.DefaultPosition, 
            style=wx.DEFAULT_DIALOG_STYLE
            ):
        'Classe Fenêtre de Dialogue pour le "À propos de ..." (fenêtre 2)'
        pre = wx.PreDialog()
        pre.Create(parent, ID, title, pos, size, style)

        self.PostCreate(pre)

        sizer = wx.BoxSizer(wx.VERTICAL)

        text0 = wx.StaticText(self, -1, t0)
        text0.SetSize(text0.GetBestSize())
        font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL)
        text0.SetFont(font)
        text1 = wx.TextCtrl(self, -1, t1, size=(500,100), style=wx.TE_MULTILINE|wx.TE_READONLY)
        text2 = wx.TextCtrl(self, -1, t2, size=(500,100), style=wx.TE_MULTILINE|wx.TE_READONLY)
        bout1 = wx.Button(self, -1, u"Fermer cette fenêtre")
        self.Bind(wx.EVT_BUTTON, self.quitter, bout1)

        sizer.Add(text0, 0, wx.ALIGN_CENTRE|wx.ALL, 20)        
        sizer.Add(text1, 0, wx.ALIGN_CENTRE|wx.ALL, 10)
        sizer.Add(text2, 0, wx.ALIGN_CENTRE|wx.ALL, 10)
        sizer.Add(bout1, 0, wx.ALIGN_CENTER|wx.ALL, 5)

        btnsizer = wx.StdDialogButtonSizer()
        
        self.SetSizer(sizer)
        sizer.Fit(self)
    def quitter(self, evt):
        "Quiiter ==> Sans commenatire ..."
        self.Destroy()
class fenetreinfo(wx.Dialog):
    def __init__(
            self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition, 
            style=wx.DEFAULT_DIALOG_STYLE
            ):
        pre = wx.PreDialog()
        pre.Create(parent, ID, title, pos, size, style)

        self.PostCreate(pre)

        sizer = wx.BoxSizer(wx.VERTICAL)

        bmp = wx.Bitmap("Data\Aeragroup.bmp", wx.BITMAP_TYPE_BMP)
        image=wx.StaticBitmap(self, -1, bmp, (80, 50), (bmp.GetWidth(), bmp.GetHeight()))
        


        textaprop="""
À propos de ce programme :
_____________________________

Créé par Aéra Group pour Code-SourceS.
Version """ + version + """.1 ;"""

        label = wx.StaticText(self, -1, textaprop)
        hyper = hl.HyperLinkCtrl(self, wx.ID_ANY, "Source déposé sur Python-France",
                                        URL="http://www.pythonfrance.com/")
        sizer.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(hyper, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(image, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        btnsizer = wx.StdDialogButtonSizer()
        
        if wx.Platform != "__WXMSW__":
            btn = wx.ContextHelpButton(self)
            self.box.Add(btn, 0, wx.ALL|wx.CENTER, 5)
            
        btn = wx.Button(self, wx.ID_OK,u"OK")
        btn.SetDefault()

        sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)

        sizer.Add(btnsizer, 0, wx.ALL|wx.CENTER, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)





class Panneau(scrolled.ScrolledPanel):
    """Classe du ScrolledPanel :
Les 3 pages sont ici définit sous forme de fonctions que la classe de la fenêtre principale appel pour modifier le "ScrolledPanel"
D'autre fonctions n'essaire au bon fonctionnement des objets graphiques sont présente"""
    def __init__(self, parent,panel):
        scrolled.ScrolledPanel.__init__(self, panel)
        self.SetBackgroundColour(wx.WHITE) # Couleur du Panel
        self.parent=parent # La fenêtre principale
        self.selec='' # Pour la liste de la page 1

        self.font_titre = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD) # Attribut de certain texte dans les StaticTexts (ou "Labels" sous Tkinter)
        self.font_sous_titre = wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD)

        self.page_debut() # On commencent par le début c'est normal
        
    def detruire(self):
        "Détruit tous les objets graphiques et arrête une boucle temporisé grace à wx.Time (très pratique :) !!!)"
        try: # Comme la boucle n'existe pas toujours, on met une exception !
            self.timer.Stop()
        except:
            pass
        self.DestroyChildren()

    def page_debut(self):
        "La page 1"
        self.detruire() # On détruit tout !!! (même s'il n'y a rien ...)
        # On ne détail pas la création des objets graphiques !
        self.text = wx.StaticText(self, -1, u"Bienvenu dans le gestionnaire de fichiers Musicaux",None, None,wx.ALIGN_RIGHT)
        self.text.SetFont(self.font_titre)

        self.text2 = wx.StaticText(self, -1, u"Ce programme vous permet de renommer vos fichiers musicaux et d'y entrer des informations très simplement\n\n",None, None,wx.ALIGN_LEFT)
        self.text2.SetFont(self.font_sous_titre)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.text, 0, wx.ALL|wx.ALIGN_RIGHT, 10)
        self.sizer.Add(self.text2, 0, wx.ALL|wx.ALIGN_LEFT, 10)

        label = wx.StaticText(self, -1, u"Entrer le titre de l'album :")        
        self.entre = wx.TextCtrl(self, -1,self.parent.nom_album , size=(180,-1))
        bo = wx.BoxSizer(wx.HORIZONTAL)
        bo.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        bo.Add(self.entre, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(bo, 0, wx.ALL|wx.ALIGN_LEFT, 10)

        label = wx.StaticText(self, -1, u"Entrer l'année de parution :")        
        self.entre2 = wx.TextCtrl(self, -1,self.parent.annee_info , size=(180,-1))
        bo = wx.BoxSizer(wx.HORIZONTAL)
        bo.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        bo.Add(self.entre2, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.sizer.Add(bo, 0, wx.ALL|wx.ALIGN_LEFT, 10)

        box = wx.StaticBox(self, -1, u"Sélection des fichiers à traiter")
        label = wx.StaticText(self, -1, u"Sélectionner les fichiers que vous souhaitez modifier")
        b1 = wx.Button(self, -1, u"Parcourir ...")
        self.Bind(wx.EVT_BUTTON, self.ajout_fichier, b1) # Détection des événements
        boite = wx.StaticBoxSizer(box, wx.VERTICAL)
        bo = wx.BoxSizer(wx.HORIZONTAL)
        bo.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        bo.Add(b1, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        boite.Add(bo, 0, wx.ALL|wx.LEFT, 5)
        self.liste = wx.ListCtrl(self,-1,style=wx.LC_REPORT)
        self.liste.Bind(wx.EVT_CHAR, self.clavier) # Événement claviers
        self.liste.InsertColumn(0, u"Fichiers")
        self.liste.SetColumnWidth(0,780)
        self.liste.Bind(wx.EVT_CONTEXT_MENU, self.menu_clic) # Détection du "clique droit"
        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.selection_liste, self.liste) # Détection des événements
        self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.deselection_liste, self.liste) # Détection des événements
        boite.Add(self.liste, 1, wx.ALL|wx.LEFT|wx.GROW, 5)
        self.sizer.Add(boite, 1, wx.ALL|wx.ALIGN_LEFT|wx.GROW, 10)
        
        
        
        
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.SetupScrolling()
        self.faire_liste() # Créé la liste des fichiers à traiter
        self.entre.SetFocus() # L'entrée du titre de l'album est active = on peut tout de suite commencer à taper le titre de l'album !

    def page_modif(self,fichier):
        "La page 2 : La plus importante"
        self.detruire() # On détruit tout !!!
        nom_fichier=fichier.split(chr(92))[len(fichier.split(chr(92)))-1] # Nom du fichier sans le chemain

        try: # Le fichier existe-t-il ?
            open(fichier,'r').close() # Oui ... si on arrive à l'ouvrir !!!
            reader = Reader(fichier) # Lecture des TAGs
            info=[reader.getValue('title'),reader.getValue('album'),reader.getValue('performer'),reader.getValue('year'),reader.getValue('track')]
            for index in range(len(info)): # S'il n'y a rien, le lecteur renvoie "None", mais nous on préfert une chaine vide ("") !!!
                if info[index]==None:
                    info[index]=""
        except: # Le fichier n'existe pas ou il est imposible à lire
            info=[] # Pas d'info
            if not fichier in self.parent.erreur: # S'il n'est pas répertorié comme erreur, se n'est plus qu'une question de temps ... :p
                self.parent.erreur.append(fichier)

        # On ne détail pas la création des objets graphiques !
        self.text = wx.StaticText(self, -1, u"Édition du fichier "+nom_fichier,None, None,wx.ALIGN_CENTRE)
        self.text.SetFont(self.font_titre)
                
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.text, 0, wx.ALL|wx.ALIGN_CENTRE, 10)
        
        if fichier in self.parent.fichier_deja_traiter: # Si le fichier est déja traiter, il faut en informer clairement l'utilisateur (Texte en gras et en vert)
            traiter=1
            self.text2 = wx.StaticText(self, -1, u"Fichier déjà traiter",None, None,wx.ALIGN_LEFT)
            self.text2.SetFont(self.font_sous_titre)
            self.text2.SetForegroundColour(wx.GREEN)
            self.sizer.Add(self.text2, 0, wx.ALL|wx.ALIGN_LEFT, 10)
        else:
            traiter=0

        box_ligne = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(self, -1, u"Liste des fichiers à traiter :")        
        box_ligne.Add(label, 0, wx.ALL|wx.ALIGN_LEFT, 5)
        self.liste = wx.ListCtrl(self,-1,size=(500,100),style=wx.LC_REPORT)
        self.liste.InsertColumn(0, u"Fichiers")
        self.liste.SetColumnWidth(0,480)
        box_ligne.Add(self.liste, 0, wx.ALL|wx.ALIGN_LEFT, 5)
        self.sizer.Add(box_ligne, 0, wx.ALL|wx.ALIGN_LEFT, 5)

        if info==[] or fichier in self.parent.erreur: # Si il est répetorier comme erreur, on ne s'embette pas a créé tous les élements graphiques : Un texte en rouge disant que c'est une erreur sufira
            self.text2 = wx.StaticText(self, -1, u"ERREUR : Impossible de traiter le fichier sélectionné",None, None,wx.ALIGN_LEFT)
            self.text2.SetFont(self.font_sous_titre)
            self.text2.SetForegroundColour(wx.RED)
            self.sizer.Add(self.text2, 0, wx.ALL|wx.ALIGN_LEFT, 10)
            self.faire_liste()
            
        else: # Si ce n'est pas une erreur ...
            box_ligne = wx.BoxSizer(wx.HORIZONTAL)
            
            box = wx.StaticBox(self, -1, u"Informations actuel sur le fichier")
            boite = wx.StaticBoxSizer(box, wx.VERTICAL)
            label = wx.StaticText(self, -1, u"Ici sont inscrit les information relatif au fichier\n")        
            boite.Add(label, 0, wx.ALL|wx.CENTRE, 5)
            label = wx.StaticText(self, -1, u"Titre : " + info[0])        
            boite.Add(label, 0, wx.ALL|wx.LEFT, 5)
            label = wx.StaticText(self, -1, u"Artiste : " + info[2])        
            boite.Add(label, 0, wx.ALL|wx.LEFT, 5) 
            label = wx.StaticText(self, -1, u"Album : " + info[1])        
            boite.Add(label, 0, wx.ALL|wx.LEFT, 5)
            label = wx.StaticText(self, -1, u"Année : " + info[3])        
            boite.Add(label, 0, wx.ALL|wx.LEFT, 5)
            label = wx.StaticText(self, -1, u"Numéro de piste : " + info[4])        
            boite.Add(label, 0, wx.ALL|wx.LEFT, 5)
            box_ligne.Add(boite, 0, wx.ALL|wx.ALIGN_LEFT, 10)

            box = wx.StaticBox(self, -1, u"Nouvelle informations")
            boite = wx.StaticBoxSizer(box, wx.VERTICAL)
            label = wx.StaticText(self, -1, u"Entrer ici vos modifications")        
            boite.Add(label, 0, wx.ALL|wx.CENTRE, 5)
            label = wx.StaticText(self, -1, u"Titre :")
            if traiter==0: # Si on a déja traiter le fichier, autant remplire tout de suite le champs d'entrée
                notertitre=""
            else:
                notertitre=info[0]
            self.entre_titre = wx.TextCtrl(self, -1,notertitre , size=(180,-1))

            bo = wx.BoxSizer(wx.HORIZONTAL)
            bo.Add(label, 1, wx.ALL|wx.ALIGN_LEFT, 5)
            bo.Add(self.entre_titre, 1, wx.ALL|wx.ALIGN_RIGHT, 3)
            boite.Add(bo, 1, wx.ALIGN_LEFT, 5)

            label = wx.StaticText(self, -1, u"Artiste :")
            self.entre_artiste = wx.TextCtrl(self, -1,info[2] , size=(180,-1))
            bo = wx.BoxSizer(wx.HORIZONTAL)
            bo.Add(label, 1, wx.ALL|wx.ALIGN_LEFT, 5)
            bo.Add(self.entre_artiste, 1, wx.ALL|wx.ALIGN_RIGHT, 3)
            boite.Add(bo, 1, wx.ALIGN_LEFT, 5) 

            label = wx.StaticText(self, -1, u"Album :")
            if traiter==0: # Si on a déja traiter le fichier, autant remplire tout de suite le champs d'entrée
                noteralbum=self.parent.nom_album
            else:
                noteralbum=info[1]
            self.entre_album = wx.TextCtrl(self, -1,noteralbum , size=(180,-1))
            bo = wx.BoxSizer(wx.HORIZONTAL)
            bo.Add(label, 1, wx.ALL|wx.ALIGN_LEFT, 5)
            bo.Add(self.entre_album, 1, wx.ALL|wx.ALIGN_RIGHT, 3)
            boite.Add(bo, 1, wx.ALIGN_LEFT, 5)

            label = wx.StaticText(self, -1, u"Année :")
            if self.parent.annee_info=='': # Si on a déja traiter le fichier, autant remplire tout de suite le champs d'entrée
                annee=info[3]
            else:
                annee=self.parent.annee_info
            self.entre_annee = wx.TextCtrl(self, -1,annee , size=(180,-1))
            bo = wx.BoxSizer(wx.HORIZONTAL)
            bo.Add(label, 1, wx.ALL|wx.ALIGN_LEFT, 5)
            bo.Add(self.entre_annee, 1, wx.ALL|wx.ALIGN_RIGHT, 3)
            boite.Add(bo, 1, wx.ALIGN_LEFT, 5)

            label = wx.StaticText(self, -1, u"Numéro de piste :")
            if nom_fichier[0] in nombre and nom_fichier[1] in nombre and traiter==0: # Quand on extrait de la musique depuis la plus part des lecteurs,
                nbpiste=nom_fichier[:2]                                              # le nom du fichier commence par le numéro de piste (exemple : "01 piste 01")
            else:                                                                    # Si c'est le cas pour notre fichier autant noter tout de suite le numéro de piste
                nbpiste=info[4]                                                      # dans le champs d'enter, ansi l'utilisateur ira plus vite
            self.entre_numero = wx.TextCtrl(self, -1,nbpiste , size=(180,-1))
            bo = wx.BoxSizer(wx.HORIZONTAL)
            bo.Add(label, 1, wx.ALL|wx.ALIGN_LEFT, 5)
            bo.Add(self.entre_numero, 1, wx.ALL|wx.ALIGN_RIGHT, 3)
            boite.Add(bo, 1, wx.ALIGN_LEFT, 5)
            box_ligne.Add(boite, 0, wx.ALL|wx.ALIGN_LEFT, 10)

            self.sizer.Add(box_ligne, 1, wx.ALIGN_LEFT, 5)

            box = wx.StaticBox(self, -1, u"Écouter le fichier")
            boite = wx.StaticBoxSizer(box, wx.VERTICAL)
            bo = wx.BoxSizer(wx.HORIZONTAL)
            self.blire = wx.Button(self, -1, u"Lire")
            bo.Add(self.blire, 0, wx.ALL|wx.LEFT, 5)
            self.bpause = wx.Button(self, -1, u"Pause")
            bo.Add(self.bpause, 0, wx.ALL|wx.LEFT, 5)
            self.bstop = wx.Button(self, -1, u"Stop")
            bo.Add(self.bstop, 0, wx.ALL|wx.LEFT, 5)
            boite.Add(bo, 1, wx.ALL|wx.LEFT|wx.GROW, 5)
            self.position = wx.Slider(self, -1, 0, 0, 0) # Petit ascenseur pour positionner la lecteur
            self.position.SetMinSize((150, -1))
            self.Bind(wx.EVT_SLIDER, self.positionner, self.position) # Événement
            boite.Add(self.position, 0, wx.ALL|wx.LEFT|wx.GROW, 5)
            self.aff = wx.StaticText(self, -1, u"'00:00:000/00:00:000'",None, None,wx.ALIGN_LEFT)
            boite.Add(self.aff, 0, wx.ALL|wx.ALIGN_LEFT, 5)
            self.Bind(wx.EVT_BUTTON, self.lire, self.blire) # Événement
            self.Bind(wx.EVT_BUTTON, self.pause, self.bpause) # Événement
            self.Bind(wx.EVT_BUTTON, self.stop, self.bstop) # Événement
            self.Bind(wx.media.EVT_MEDIA_LOADED, self.media_charger) # Le temps du chargement du titre on déactive le bouton lecture pour éviter les erreurs
                                                                     # donc on associe un évément pour s'avoir quand on peut le réactiver
            
            self.media = wx.media.MediaCtrl(self,size=wx.Size(1,1)) # Petit lecteure très puissant ! Il y a un "écran" puisqu'il peut aussi visualiser les films
            boite.Add(self.media,0, wx.ALL|wx.LEFT, 5)              # mais on en a pas besoin d'ou sa taille de 1 pixel pour être sur de pas le voir !!!
            self.sizer.Add(boite, 0, wx.ALL|wx.ALIGN_LEFT, 10)

            label = wx.StaticText(self, -1, u"Renommer :")
            self.entre_rename = wx.TextCtrl(self, -1,nom_fichier , size=(180,-1))
            bo = wx.BoxSizer(wx.HORIZONTAL)
            bo.Add(label, 0, wx.ALL|wx.ALIGN_LEFT, 5)
            bo.Add(self.entre_rename, 0, wx.ALL|wx.ALIGN_LEFT, 3)
            self.sizer.Add(bo, 0, wx.ALIGN_LEFT, 5)

            self.charger(fichier) # Chargemnt du fichier dans le lecteure
            self.timer = wx.Timer(self)                   # Boucle de répétition bien pratique :
            self.Bind(wx.EVT_TIMER, self.au_cour_du_temp) # actualise l'affichage du temps de lecture toutes les 100 ms
            self.timer.Start(100)

            self.faire_liste() # Créé la liste des fichiers à traiter
            self.entre_titre.SetFocus() # L'entrée du titre est active = on peut tout de suite commencer à taper le titre !
                    
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.SetupScrolling()

        

    def page_fin(self):
        "La page 3"
        self.detruire() # On détruit tout !!!
        # On ne détail pas la création des objets graphiques !
        self.text = wx.StaticText(self, -1, u"Gestionnaire de fichiers Musicaux",None, None,wx.ALIGN_RIGHT)
        self.text.SetFont(self.font_titre)

        self.text2 = wx.StaticText(self, -1, u"Fin du processus !",None, None,wx.ALIGN_LEFT)
        self.text2.SetFont(self.font_sous_titre)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.text, 0, wx.ALL|wx.ALIGN_RIGHT, 10)
        self.sizer.Add(self.text2, 0, wx.ALL|wx.ALIGN_LEFT, 10)

        box = wx.StaticBox(self, -1, u"Fichiers traités avec succés")
        boite = wx.StaticBoxSizer(box, wx.VERTICAL)
        self.liste = wx.ListCtrl(self,-1,style=wx.LC_REPORT,size=(400,100))
        self.liste.InsertColumn(0, u"Fichiers")
        self.liste.SetColumnWidth(0,380)
        self.parent.fichier_deja_traiter.sort() # On trie la liste pour l'avoir dans l'ordre alphabétique
        for index in range(len(self.parent.fichier_deja_traiter)):
            self.liste.InsertStringItem(index,self.parent.fichier_deja_traiter[index]) # On ajoute à la liste
        boite.Add(self.liste, 0, wx.ALL|wx.LEFT, 5)
        self.sizer.Add(boite, 0, wx.ALL|wx.ALIGN_LEFT, 10)

        box = wx.StaticBox(self, -1, u"Erreurs")
        boite = wx.StaticBoxSizer(box, wx.VERTICAL)
        erreur=u''
        if self.parent.erreur==[]:
            erreur=u'Aucune erreur détecter'
        else:
            self.parent.erreur.sort()
            erreur=u"Les fichiers suivant n'on pas pu être traiter convenablement :\n"
            for index in range(len(self.parent.erreur)):
                erreur = erreur + self.parent.erreur[index]+ u'\n'
        text = wx.TextCtrl(self, -1, erreur, size=(500,80), style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH)
        if self.parent.erreur!=[]:
            text.SetStyle(0, len(erreur)-1, wx.TextAttr("RED",wx.NullColour))
        text.Bind(wx.EVT_CONTEXT_MENU, self.menu_clic2) # Événement
        boite.Add(text, 0, wx.ALL|wx.LEFT, 5)
        self.sizer.Add(boite, 0, wx.ALL|wx.ALIGN_LEFT, 10)

        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.SetupScrolling()

    def ajout_fichier(self,evt):
        "Ajouter un fichier à la liste"
        dlg = wx.FileDialog(self, message=u"Sélectionner les fichiers à traiter", 
        defaultFile="", wildcard=u"Fichier de musique mp3 (*.mp3)|*.mp3", style=wx.OPEN|wx.MULTIPLE)
        if dlg.ShowModal() == wx.ID_OK:
            fichiers = dlg.GetPaths()
            for element in fichiers:
                if not element in self.parent.liste_fichier:
                    self.parent.liste_fichier.append(element)
            self.parent.liste_fichier.sort() # On trie la liste pour l'avoir dans l'ordre alphabétique (c'est mieu pour traiter les fichiers de la piste 01 à la fin :p !!!)
            self.faire_liste() # On actualise la liste
            if self.parent.liste_fichier !=[]: # Si il y a au moin un fichier, alors au active le bouton "suivant"
                self.parent.suivant.Enable(True)
                self.parent.fichier.Enable(12,True)
            
    def faire_liste(self):
        "Actualisation de la liste"
        self.liste.DeleteAllItems() # On détruit tout les éléments de la liste (même s'il n'y en a pas :p !!!)
        for index in range(len(self.parent.liste_fichier)):
            self.liste.InsertStringItem(index,self.parent.liste_fichier[index])
            item = self.liste.GetItem(index)
            if self.parent.liste_fichier[index] in self.parent.erreur: # Si le fichier est répertorier comme erreur : ROUGE
                couleur=wx.RED
            elif self.parent.liste_fichier[index] in self.parent.fichier_deja_traiter: # Si le fichier est déja traité : vert
               couleur=wx.GREEN
            else: # Pour les autres : bleu (ouai, le noire ça me dérangé :) donc j'ai mis bleu :p )
                couleur=wx.BLUE
            if self.parent.fichier_actuel==self.parent.liste_fichier[index]: # Si c'est le fichier actuelement traiter : surlignier en jaune
                item.SetBackgroundColour("yellow")
            item.SetTextColour(couleur)
            self.liste.SetItem(item)

    def supprimer(self,evt):
        "Suppression d'un élement de la liste"
        self.parent.liste_fichier.remove(self.liste.GetItemText(self.selec))
        if self.liste.GetItemText(self.selec) in self.parent.fichier_deja_traiter:
            self.parent.fichier_deja_traiter.remove(self.liste.GetItemText(self.selec))
        if self.liste.GetItemText(self.selec) in self.parent.erreur:
            self.parent.erreur.remove(self.liste.GetItemText(self.selec))
        self.liste.DeleteItem(self.selec)
        self.parent.liste_fichier.sort()
        self.faire_liste()
        if self.parent.liste_fichier==[]: # S'il n'y a plus de fichier, on déactive le bouton "Suivant"
            self.parent.suivant.Enable(False)
            self.parent.fichier.Enable(12,False)

    def menu_clic(self,evt):
        "Au clique droit sur la liste à la page 1, on créé un menu"
        self.Bind(wx.EVT_MENU, self.supprimer, id=01)
        self.Bind(wx.EVT_MENU, self.ajout_fichier, id=02)

        menu = wx.Menu()
        menu.AppendItem(wx.MenuItem(menu, 01,u"Supprimer"))
        menu.AppendItem(wx.MenuItem(menu, 02,u"Ajouter des fichiers à la liste"))
        if self.selec=='': # Si aucun élément de la liste n'est sélectionner, on déactive le menu "Supprimer"
            menu.Enable(01,False)
        self.PopupMenu(menu)
        menu.Destroy()

    def menu_clic2(self,evt):
        """Le fait d'avoir mis l'attribut "TE_RICH" a la saisit de texte "erreur" de la page 3
fait que quand on fait un "clique droit" le menu est en Anglais et ça me dérange profondément ...
donc on le déctive ... :p"""
        wx.Bell()

    def lire(self,evt):
        "Lecture d'un média dans le lecteure"
        if not self.media.Play(): # Erreur !!!
            wx.MessageBox(u"Imposible de lire le fichier",
                          u"Erreur",
                          wx.ICON_ERROR | wx.OK)
        else:
            self.position.SetRange(0, self.media.Length()) # On redéfinit la position de l'ascenseur

    def pause(self,evt):
        "Pause du lecteure dans le lecture"
        self.media.Pause()
    
    def stop(self, evt):
        "Arret de la lecteure"
        self.media.Stop()

    def positionner(self, evt):
        "Position de la lecture quand on touche à l'ascenseur"
        self.media.Seek(self.position.GetValue())

    def charger(self,path):
        "Chargement d'un média dans le lecteur"
        self.blire.Disable() # On déactive le bouton "lire" pour évité que l'utilisateur ne veuille lire le média avant sont chargement total
        if not self.media.Load(path): # Erreur
            wx.Bell()
        else:
            self.position.SetRange(0, self.media.Length()) # On redéfinit la position de l'ascenseur

    def media_charger(self, evt):
        'Le média est charger, on peut réactiver le bouton "lire"'
        self.blire.Enable()

    def au_cour_du_temp(self, evt):
        "On actualise l'affichage du temps au cour de la lecture"
        offset = self.media.Tell()
        self.position.SetValue(offset)
        self.aff.SetLabel(self.format_heure(offset)+u'/'+self.format_heure(self.media.Length()))

    def format_heure(self,ms):
                "Transforme une date en ms en un format hh:mm:ss:ms"
		if ms <= 0:
                    return u'00:00:000'
		time_sec, ms = ms / 1000, ms % 1000
		time_min, time_sec = time_sec / 60, time_sec % 60
		time_hor, time_min = time_min / 60, time_min % 60
		if time_hor == 0:
                    return u'%02d:%02d:%03d'%(time_min, time_sec, ms)
		return u'%02d:%02d:%02d:%03d'%(time_hor, time_min, time_sec, ms)

    def selection_liste(self,evt):
        "Un élément est sélectionner dans la liste"
        self.selec=evt.m_itemIndex
        self.parent.edition.Enable(22,True)
    def deselection_liste(self,evt):
        "L'élément sélectionner dans la liste a été désélectionner"
        self.selec=''
        self.parent.edition.Enable(22,False)

    def clavier(self,evt=None):
        "Évémement au clavier"
        if self.selec!='': # Si un élément de la liste est sélectionner
            if evt.GetKeyCode()==127: # Correspont a l'appuis de la touche "Supprimer"
                self.supprimer(None) # On supprimer !!!



class Frame_Principal(wx.Frame):
    """Classe de la fenêtre principale :
La fenêtre principale est composer d'un panel clasique et d'un "ScrolledPanel", c'est à dire
un panel avec un ascenseur au cas ou la fenêtre serait trop petite et que des objets graphiques
seraient cachés ! Ce panel est régulièrement détruit puis reconstruit au fure et a meusure de l'utilisation"""
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, -1, title,size=(850,700))
        self.SetIcon(wx.Icon(u"Data\Icon_Musique.ico", wx.BITMAP_TYPE_ICO )) # Permet de définir un Icone à la fenêtre
        self.Bind(wx.EVT_CLOSE, self.quitter) # Quand on clique sur la croix, on execute la fonction "quitter"

        self.numero_page=1 # J'appel "page" les différents aperçu du ScrolledPanel. Il y a trois pages : 1 = Page d'acceuil
                                                            # 2 = Page de configuration du fichier mp3 (la plus importante)
                                                            # 3 = Page de fin
        self.nom_album=u'' # On par du principe que tous les fichiers traités appartiennent au même album donc on fait de sont nom une variable pour pouvoir l'utiliser plusieur fois
        self.annee_info='' # De même l'année de parution risque d'être la même
        self.liste_fichier=[] # Liste des fichiers sélectionnés
        self.fichier_deja_traiter=[] # Liste des fichiers déja traiter
        self.fichier_actuel="" # Fichier actuelement traiter ==> Chaine vide si aucun fichier traité à un instant précit (exemple à la page 1 ou 3)
        self.erreur=[] # Liste des fichiers qui n'ont pas pu être traités correctement

       
        panel = wx.Panel(self) # Le panel principal
        panel.SetBackgroundColour(wx.WHITE) # Sa couleur ...

        
        self.precedent = wx.Button(panel, -1, u"Étape précédente")   # Ici la liste des boutons
        self.precedent.Enable(False)                                 # Comme dans un asistant clasique il y a
        self.suivant = wx.Button(panel, -1, u"Débuter le processus") # 3 boutons : précédent, suivant et quitter
        self.suivant.Enable(False)                                   # Ici on déactive au début les deux premiers boutons
        self.annuler = wx.Button(panel, -1, u"Quitter")
        
        self.paneau = Panneau(self,panel) # Le ScrolledPanel (on en a fait une classe à part)

        ##### Création de la barre de menu #####
        menuBar = wx.MenuBar()

         
        self.fichier = wx.Menu()        
        self.fichier.Append(11,"Précédent\tCtrl+P", "Effectuer l'action précédente")
        self.fichier.Append(12,"Suivant\tCtrl+S", "Effectuer l'action suivante")
        self.fichier.AppendSeparator()
        self.fichier.Append(13,"Quitter\tAlt+F4", "Quitter le programme")
        self.fichier.Enable(11,False)
        self.fichier.Enable(12,False)
        
        self.Bind(wx.EVT_MENU, self.pre, id=11)
        self.Bind(wx.EVT_MENU, self.sui, id=12)
        self.Bind(wx.EVT_MENU, self.quitter, id=13)

        self.edition = wx.Menu()        
        self.edition.Append(21,"Ajouter un fichier\tCtrl+A", "Ajouter un fichier à la liste")
        self.edition.Append(22,"Supprimer\tSuppr", "Supprimer le fichier sélectionner de la liste")
        self.edition.AppendSeparator()
        self.edition.Append(23,"Lire\tCtrl+L", "Lire le fichier sélectionner")
        self.edition.Append(24,"Pause\tCtrl+O", "Mettre en pause la lecture")
        self.edition.Append(25,"Ajouter un fichier\tCtrl+M", "Arrêter la lecture")
        self.edition.Enable(22,False)
        self.edition.Enable(23,False)
        self.edition.Enable(24,False)
        self.edition.Enable(25,False)
        
        self.Bind(wx.EVT_MENU, self.paneau.ajout_fichier, id=21)
        self.Bind(wx.EVT_MENU, self.paneau.supprimer, id=22)
        self.Bind(wx.EVT_MENU, self.paneau.lire, id=23)
        self.Bind(wx.EVT_MENU, self.paneau.pause, id=24)
        self.Bind(wx.EVT_MENU, self.paneau.stop, id=25)

        aide = wx.Menu()        
        aide.Append(31,"Aide", "Aide sur le programme")
        aide.Append(32,"À propos de ...", "Informations sur le programme")
        
        self.Bind(wx.EVT_MENU, self.aide, id=31)
        self.Bind(wx.EVT_MENU, self.about, id=32)


        menuBar.Append(self.fichier, "Fichier")
        menuBar.Append(self.edition, "Édition")
        menuBar.Append(aide, "Aide")
        self.SetMenuBar(menuBar)
        self.CreateStatusBar()
        
        ##### Fin de la création de la barre de menu #####
        
        self.Bind(wx.EVT_BUTTON, self.pre, self.precedent) # Événement sur les boutons
        self.Bind(wx.EVT_BUTTON, self.sui, self.suivant)
        self.Bind(wx.EVT_BUTTON, self.quitter, self.annuler)

        sizer_global = wx.BoxSizer(wx.VERTICAL) # Positionnent des élement dans le Panel principal

        sizer_global.Add(self.paneau,1, wx.ALL|wx.GROW,5)
        
        box = wx.BoxSizer(wx.HORIZONTAL)
        box.Add(self.precedent, 0, wx.ALL|wx.RIGHT, 5)
        box.Add(self.suivant, 0, wx.ALL|wx.RIGHT, 5)
        box.Add(self.annuler, 0, wx.ALL|wx.RIGHT, 5)
        line = wx.StaticLine(panel, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        sizer_global.Add(line, 0, wx.GROW|wx.ALL,10)
        sizer_global.Add(box, 0, wx.ALL|wx.ALIGN_RIGHT, 0)
        
        panel.SetSizer(sizer_global)
        panel.Layout()
        self.Centre()


    def quitter(self, evt):
        "Permet de quitter l'application ==> Sans commentaire ..."
        dia=wx.MessageDialog(self, "Voullez-vous quitter le programme ?", caption = u"Quitter le programme", style = wx.YES_NO|wx.ICON_QUESTION,pos = wx.DefaultPosition)
        valeur = dia.ShowModal()
        if valeur==wx.ID_YES:
            self.Destroy()

    def pre(self,evt):
        """Fonction associée au bouton "Précédent" :
- Quand on est à la page 1 on passe ne peut pas renenir en arrière (ça paret logique d'où la déactivation du bouton au début)
- Quand on est à la page 2 on passe à la page 1 si on est au premier fichier à traité sionon on reste à la page 2 mais on passe au fichier précédent
- Quand on est à la page 3 on passe revient à la page 2 en s'occupant du dernier fichier"""
        if self.numero_page==2:
            if self.fichier_actuel==self.liste_fichier[0]: # Es le premier fichier ?
                self.fichier_actuel=""
                self.numero_page=1
                self.paneau.page_debut()
                self.precedent.Enable(False)
                self.fichier.Enable(11,False)
                self.precedent.SetLabel(u"Étape précédente")
                self.suivant.SetLabel(u"Débuter le processus")
                self.edition.Enable(23,False)
                self.edition.Enable(24,False)
                self.edition.Enable(25,False)
                self.edition.Enable(21,True)
            else:
                traitement = self.traitement() # On effectue les modifications à apporter au fichier. Renvoie 1 ou 0 ==> 1 = On passe au fichier suivant 
                if traitement==1:
                    self.fichier_actuel=self.liste_fichier[self.liste_fichier.index(self.fichier_actuel)-1]
                    if self.fichier_actuel==self.liste_fichier[0]:
                        self.precedent.SetLabel(u"Étape précédente")
                    else:
                        self.precedent.SetLabel(u"Fichier précédent")
                    self.paneau.page_modif(self.fichier_actuel)
                    self.suivant.SetLabel(u"Fichier suivant")
                    self.edition.Enable(23,True)
                    self.edition.Enable(24,True)
                    self.edition.Enable(25,True)
                    self.edition.Enable(21,False)
                
        elif self.numero_page==3:
            self.numero_page=2
            self.fichier_actuel=self.liste_fichier[len(self.liste_fichier)-1]
            self.precedent.SetLabel(u"Fichier précédent")
            self.paneau.page_modif(self.fichier_actuel)
            self.suivant.SetLabel(u"Étape suivante")
            self.edition.Enable(23,True)
            self.edition.Enable(24,True)
            self.edition.Enable(25,True)
            self.edition.Enable(21,False)

        
    def sui(self,evt):
        """Fonction associée au bouton "Suivant" :
- Quand on est à la page 1 on passe à la page 2 mais sement si des ficheiers ont été sélectionné (d'où la déactivation du bouton au début)
- Quand on est à la page 2 on passe à la page 3 si on est au dernier fichier à traité sionon on reste à la page 2 mais on passe au fichier suivant
- Quand on est à la page 3 on passe revient à la page 1 en réinitialisant l'application"""
        if self.numero_page==1:
            self.numero_page=2
            self.fichier_actuel=self.liste_fichier[0]
            self.nom_album=self.paneau.entre.GetValue()
            self.annee_info=self.paneau.entre2.GetValue()
            self.precedent.SetLabel(u"Étape précédente")
            self.paneau.page_modif(self.fichier_actuel)
            self.precedent.Enable(True)
            self.fichier.Enable(11,True)
            if len(self.liste_fichier)==1:
                self.suivant.SetLabel(u"Étape suivante")
            else:
                self.suivant.SetLabel(u"Fichier suivant")
            self.edition.Enable(23,True)
            self.edition.Enable(24,True)
            self.edition.Enable(25,True)
            self.edition.Enable(21,False)
            self.edition.Enable(22,False)
            
        elif self.numero_page==2:
            traitement = self.traitement() # On effectue les modifications à apporter au fichier. Renvoie 1 ou 0 ==> 1 = On passe au fichier suivant 
            if traitement==1:
                if self.fichier_actuel==self.liste_fichier[len(self.liste_fichier)-1]: # Es le dernier fichier ?
                    self.numero_page=3
                    self.paneau.page_fin()
                    self.suivant.SetLabel(u"Traiter d'autres fichiers")
                    self.precedent.SetLabel(u"Étape précédente")
                    self.edition.Enable(23,False)
                    self.edition.Enable(24,False)
                    self.edition.Enable(25,False)
                    self.edition.Enable(21,False)
                else:
                    self.fichier_actuel=self.liste_fichier[self.liste_fichier.index(self.fichier_actuel)+1]
                    self.precedent.SetLabel(u"Fichier précédent")
                    self.paneau.page_modif(self.fichier_actuel)
                    if self.fichier_actuel==self.liste_fichier[len(self.liste_fichier)-1]: # Es le dernier fichier ?
                        self.suivant.SetLabel(u"Étape suivante")
                    else:
                        self.suivant.SetLabel(u"Fichier suivant")
                    self.edition.Enable(23,True)
                    self.edition.Enable(24,True)
                    self.edition.Enable(25,True)
                    self.edition.Enable(21,False)


        elif self.numero_page==3: # Initialisation
                self.numero_page=1
                self.nom_album=u''
                self.liste_fichier=[]
                self.fichier_deja_traiter=[]
                self.fichier_actuel=""
                self.annee_info=''
                self.erreur=[]
                self.paneau.page_debut()
                self.precedent.Enable(False)
                self.suivant.Enable(False)
                self.precedent.SetLabel(u"Étape précédente")
                self.suivant.SetLabel(u"Débuter le processus")
                self.fichier.Enable(11,False)
                self.fichier.Enable(12,False)
                self.edition.Enable(21,True)
                self.edition.Enable(22,False)

    def traitement(self):
        "Fonction modifie les TAGs (informations binaires non prise en compte a la lecture classique du fichier) ID3 (associer au fichier mp3)"
        if not self.fichier_actuel in self.erreur: # On vérifie que le fichier n'a pas de problème
            err1=0
            err2=0
            for index in range(len(self.paneau.entre_annee.GetValue())): # On vérifie que la date est bien un nombre
                if not self.paneau.entre_annee.GetValue()[index] in nombre:
                    err1=1
                    break
            for index in range(len(self.paneau.entre_numero.GetValue())): # On vérifie que le numéro de piste est bien un nombre
                if not self.paneau.entre_numero.GetValue()[index] in nombre:
                    err2=1
                    break
            if err1==0 and err2==0 :  # La date et le numéro de piste sont-ils conforme ?
                    try:  # En cas d'erreur ...
                        self.paneau.charger("Data\Attente.mp3")  # Comme le lecteur charge le fichier, il est imposible de modifier ses informations. Le fichier "Attente.mp3" est donc la pour libérer le fichier à traiter
                        if self.paneau.entre_numero.GetValue()=='':  # L'éditeur de TAGs ne suposte pas que le numéro de piste soit une chaine vide ==> On met donc 00 en cas de vide
                            numero='00'
                        else:
                            numero=self.paneau.entre_numero.GetValue()
                            # Appel à l'éditeur de TAGs
                        Writer(self.fichier_actuel, numero,\
                               self.paneau.entre_artiste.GetValue().encode("latin1","replace"),\
                               self.paneau.entre_titre.GetValue().encode("latin1","replace"),\
                               self.paneau.entre_album.GetValue().encode("latin1","replace"),\
                               self.paneau.entre_annee.GetValue())
                        if self.paneau.entre_rename.GetValue() != self.fichier_actuel.split(chr(92))[len(self.fichier_actuel.split(chr(92)))-1]:  # Le nom demandé et le nom actuel du fichier sont -ils les même ?
                            liste_chemain=self.fichier_actuel.split(chr(92)) # chr(92) = "\"
                            liste_chemain.remove(self.fichier_actuel.split(chr(92))[len(self.fichier_actuel.split(chr(92)))-1])  # Extraction du chemain d'accée
                            liste_chemain.append(self.paneau.entre_rename.GetValue())      # Ajout du nouveau nom au chemain d'accée
                            os.rename(self.fichier_actuel, (chr(92).join(liste_chemain)))  # On renome le fichier
                        if not self.fichier_actuel in self.fichier_deja_traiter:  # Avions nons déja traiter le fichier ?
                            self.fichier_deja_traiter.append(self.fichier_actuel)
                        return 1   # Tout c'est bien passé on peut rééditer le Panel
                    except:   # Erreur = Ajout à la liste + message d'erreur
                        self.erreur.append(self.fichier_actuel)
                        dia=wx.MessageDialog(self, u"Une erreur est survenu : Impossible de traiter le fichier", caption = u"Erreur", style = wx.OK|wx.ICON_ERROR,
                                 pos = wx.DefaultPosition)
                        valeur = dia.ShowModal()
                        return 1   # Cette erreur n'empèche pas de rééditer le Panel
            else: # La date ou/et le numéro de piste ne sont pas conforme = Message d'erreur
                dia=wx.MessageDialog(self, u"La date et le numéro de piste ne peuvent contenir que des nombres !", caption = u"Erreur dans les données", style = wx.OK|wx.wx.ICON_EXCLAMATION,
                                         pos = wx.DefaultPosition)
                valeur = dia.ShowModal()
                return 0 # On ne réédite pas le Panel tant que la date ou/et le numéro de piste ne sont pas conforme
        else:
            return 1 # L'erreur n'empèche pas de rééditer le Panel
        
    def about(self,evt):
        dlg = About(self, -1, u"À propos de ...")
        dlg.CenterOnScreen()
        val = dlg.ShowModal()

    def aide(self,evt):
        dlg = Aide(self)
        dlg.Show(True)
        dlg.CenterOnScreen()
        

class Demarage(wx.App):
    "Classe de démarage : Pas de commentaire"
    def OnInit(self):
        frame = Frame_Principal(None, u"Gestionnaire de fichiers Musicaux")
        frame.Show(True)
        return True
        
app = Demarage(False) # Démarage (Pourquoi "False" en argument ? Pour que les erreurs et les "print" soit affichier dans la console et non dans une fenêtre de WxPython annexe)
app.MainLoop()

Conclusion :

J'ai mis plus d'une heure à tout commenté !!! J'espère que ça pourra aider les débutants (c'est le but !) Je précise qu'il faut télécharger le ZIP pour que ça fonctionne.
POUR CEUX QUI DÉSIR TÉLÉCHARGER WX.PYTHON :

Allez sur le site http://www.wxpython.org/download.php et sélectionner la version correspondant à votre version de Python et à votre système d'exploitation.

POUR CEUX QUI DÉSIR TÉLÉCHARGER WINZIP OU WINRAR :

Vous pouvez le télécharger entre autre à cette adresse http://www.clubic.com/telecharger-fiche9488-winzip.html

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.