Catégorie : Audio-vidéo     Tags :      

     Retrouvez cet article dans : Linux Magazine 82

    Dans cet article, nous allons voir comment améliorer la façon dont Freevo accède aux fichiers musicaux.

    Les logiciels de lecture musicale historiques (XMMS, Winamp, etc.) basent leurs listes de lectures sur le système de fichiers : l’utilisateur doit rechercher dans l’arborescence des fichiers le morceau qu’il veut écouter.

    Les lecteurs multimédias évolués actuels (Rhythmbox, Amarok, JuK, iTunes...) permettent au contraire de simplifier cette tâche, et d’effectuer une sélection musicale par artiste, par genre ou encore par album.
    Freevo ne propose pas de liste de lecture intelligente : il ne permet que de naviguer dans le système de fichiers.
    Il est possible d’implémenter ce principe au niveau du système de fichiers, par le biais de répertoires et liens symboliques.
    Bien que moins performante que le support natif de la fonctionnalité, cette astuce permet de l’émuler avec n’importe quel logiciel multimédia basé sur le système de fichiers, dont Freevo.
    Nous allons créer pour cela un script Python. Le choix de ce langage se justifie ici par deux points :

    • C’est le langage utilisé par Freevo ;
    • Il est simple à comprendre.

    Pour plus d’informations sur Python, consultez http://docs.python.org.

    Note:
    Ce principe n’est pas limité à Freevo, il est applicable à tout lecteur audio basé sur le système de fichiers.

    Structure du script

    Nous allons tout d’abord créer une structure de base pour ce script, dans le fichier /home/freevo/bin/freevo_make_music_links.py. Ce squelette parcourt la liste des fichiers à traiter, et affiche leur nom :

    #! /usr/bin/env python
    FILESROOT = ‘/home/freevo/Media/Musique’
    LINKSROOT = ‘/home/freevo/Media/MusiqueLiens’
    import os, sys
    
    def main():
        for d in os.walk(FILESROOT):
            for f in d[2]:
                do_file(os.path.join(d[0], f))
    
    def do_file(f):
        print f
    
    if __name__ == ‘__main__’:
        main()

    Quand on exécute directement un script Python, la variable __name__ contient la chaîne «__main__». Quand le fichier est importé par un autre script Python, son contenu est différent.
    Le test que l’on fait ici permet donc d’exécuter la fonction main() lorsque l’on exécute le script. Il est placé à la fin du script pour que toutes les fonctions soient définies avant exécution.
    La fonction os.walk permet de parcourir un répertoire (dans notre cas, celui qui est pointé par FILESROOT) et de retourner tous les fichiers trouvés.
    La fonction do_file sera replacée par le code de traitement de chacun des fichiers. Pour l’instant, elle ne fait qu’afficher le nom du fichier.
    Lorsque le fichier est créé, n’oubliez pas de lui donner les droits d’exécution (chmod u+x /home/freevo/bin/freevo_make_music_links.py). Si on exécute ce script, il affichera la liste des fichiers musicaux disponibles.

    Traitement des fichiers

    Nous allons nous baser sur les méta-informations contenues dans les fichiers MP3 et OGG Vorbis afin de créer notre base de données musicale.
    Après différenciation des fichiers .ogg et .mp3, leurs informations sont récupérées à l’aide de programmes externes : ogginfo et mp3info ; ils sont disponibles dans la plupart des distributions. La fonction do_file est donc remplacée :

    def do_file(f):
        infos = {‘artist’:’’, ‘title’:’’, ‘album’:’’,
                 ‘tracknumber’:’’, ‘genre’:’’}
        fname = f.replace(‘»’, ‘\\»’)
        if f[-4:].lower() == ‘.ogg’:
            answ = os.popen(‘ogginfo «%s»’ % fname)
            for i in answ.readlines():
                for type in infos.keys():
                    if ‘%s=’ % type in i.lower():
                        data = i.split(‘=’, 1)[1].strip()
                        infos[type] = data
            answ.close()
        elif f[-4:].lower() == ‘.mp3’:
            answ = os.popen(‘mp3info -p «%%a\n%%t\n%%l\n%%n\n%%g\n» «%s»’ % fname)
            i = [ j.strip() for j in answ.readlines() ]
            answ.close()
            infos = {‘artist’:i[0], ‘title’:i[1], ‘album’:i[2],
                     ‘tracknumber’:i[3], ‘genre’:i[5]}
    
        print f, ‘:’, infos

    L’expression f[-4:] retourne les quatre derniers caractères de la chaîne f, c’est-à-dire dans notre cas l’extension du fichier. Ceci permet de définir le programme à exécuter pour accéder au fichier. La fonction os.popen exécute une commande externe et en récupère la sortie standard. La fonction readlines transforme la sortie du programme, ligne par ligne, en une liste de chaînes de caractères.
    Dans le cas de ogginfo, on parcourt les informations retournées, afin de retrouver celles qui nous intéressent et de remplir le dictionnaire infos. Dans le cas de mp3info, on a la possibilité de faire formater la sortie du programme comme on veut, ce qui simplifie grandement le traitement.

    Si on exécute freevo_make_music_links.py à cette étape, il retournera la liste des fichiers suivis de leurs informations sous forme d’un dictionnaire Python.
    Pour plus d’informations sur les dictionnaires, vous pouvez vous référer à la section 5.5 du didacticiel sur http://docs.python.org/tut/tut.html.

    Création des liens

    Maintenant que nous avons les méta-informations concernant tous les fichiers, il nous suffit de créer des liens symboliques dans une arborescence spéciale. Nous allons remplacer la ligne print f, ‘:’, infos par les suivantes :

        # The file extension
        ext = f[-3:]
    
        link = ‘%s.%s’ % (infos[‘title’], ext)
    
        # Tracks from an artist
        if infos[‘artist’]:
            dir = os.path.join(LINKSROOT, ‘artist’, infos[‘artist’])
            lnk(f, dir, link)
    
        # Artists, by genre
        if infos[‘genre’] and infos[‘artist’]:
            dir = os.path.join(LINKSROOT, ‘genre+artist’,
                               infos[‘genre’], infos[‘artist’])
            lnk(f, dir, link)
    
        link = ‘%s - %s.%s’ % (infos[‘tracknumber’], infos[‘title’], ext)
    
        # Albums
        if infos[‘album’]:
            dir = os.path.join(LINKSROOT, ‘album’, infos[‘album’])
            lnk(f, dir, link)
    
        # Albums, by artist
        if infos[‘album’] and infos[‘artist’]:
            dir = os.path.join(LINKSROOT, ‘artist+album’,
                            infos[‘artist’], infos[‘album’])
            lnk(f, dir, link)
    
        # Albums, by genre
        if infos[‘genre’] and infos[‘album’]:
            dir = os.path.join(LINKSROOT, ‘genre+album’,
                               infos[‘genre’], infos[‘album’])
            lnk(f, dir, link)
    
        # Albums, by genre and artist
        if infos[‘genre’] and infos[‘album’] and infos[‘artist’]:
            dir = os.path.join(LINKSROOT, ‘genre+artist+album’, infos[‘genre’],
                               infos[‘artist’], infos[‘album’])
            lnk(f, dir, link)
    
    def lnk(f, dir, link):
        try:
            os.makedirs(dir)
        except:
            pass
    
        link = link.replace(‘/’, ‘_’)
        fullpath = os.path.join(dir, link)
        try:
            os.symlink(f, fullpath)
        except OSError:
            if os.readlink(fullpath) != f:
                linklist = link.split(‘.’)
                linklist[-1] = ‘%s_’ % linklist[-1]
                link = ‘.’.join(linklist)
                lnk(f, dir, link)

    Pour chacune des informations de classement, nous testons si cette information existe (if infos[‘XXX’]) ; si tel est le cas, la fonction lnk est exécutée.
    Cette fonction crée le répertoire voulu s’il n’existe pas déjà (os.makedirs), puis crée un lien symbolique vers le fichier réel (os.symlink).
    Si un tel lien existe déjà, un second lien est créé en ajoutant le caractère _ au nom de fichier, ceci pour gérer les cas où deux pistes auraient le même nom.

    Résultat

    Après l’exécution de ce script, le répertoire /home/freevo/Media/MusiqueLiens contient une arborescence logique, permettant de naviguer plus facilement parmi les pistes musicales.
    Il nous suffit ensuite de paramétrer Freevo pour accéder de manière élégante à ces répertoires. Dans le fichier /home/freevo/.frevo/local_conf.py, la variable AUDIO_ITEMS est modifiée :

    AUDIO_ITEMS = [
       (‘Album’,
          ‘/home/freevo/Media/MusiqueLiens/album’),
       (‘Artiste’,
          ‘/home/freevo/Media/MusiqueLiens/artist’),
       (‘Artiste / Album’,
          ‘/home/freevo/Media/MusiqueLiens/artist+album’),
       (‘Genre / Album’,
          ‘/home/freevo/Media/MusiqueLiens/genre+album’),
       (‘Genre / Artiste’,
          ‘/home/freevo/Media/MusiqueLiens/genre+artist’),
       (‘Genre / Artiste / Album’,
          ‘/home/freevo/Media/MusiqueLiens/genre+artist+album’),
       (‘Accès direct’, ‘/home/freevo/Media/Musique’),
    ]

    Après relancement de Freevo, le menu Ecouter de la musique contient ces différentes catégories.

    Cette méthode a bien sûr plusieurs inconvénients, le principal étant que ces informations ne sont pas mises à jour en temps réel. Cependant, une collection musicale n’étant généralement pas très dynamique, il suffira de faire des mises à jour de temps en temps : soit manuellement après avoir modifié ou ajouté des fichiers, soit automatiquement, toutes les nuits par exemple. Par ailleurs, ce script n’efface pas les liens pointant vers des fichiers inexistants.

    Mise à jour automatique

    Le meilleur moyen de mettre à jour ces informations de manière automatique est d’ajouter une ligne dans crontab, avec la commande crontab –e :

    0 5     * * *   /home/freevo/bin/freevo_make_music_links.py
    30 5    * * *   /usr/bin/freevo cache >/dev/null 2>&1

    Ces lignes font exécuter le script à 5h00 tous les jours et mettre à jour le cache de Freevo à 5h30.

    Améliorations

    Il est bien sûr possible d’améliorer cette procédure. Il est par exemple envisageable de garder les informations de mises à jour dans une base de données à part, afin de ne pas analyser les fichiers déjà traités ; ou encore de gérer les dates de sortie des albums pour les classer par ordre chronologique. Il peut également être intéressant de créer un script qui nettoie les liens devenus inutiles... Mais maintenant, c’est à vous de jouer !

     Retrouvez cet article dans : Linux Magazine 82

    Posté par admin-web (fabrice) | Signature : Sébastien Munch | Article paru dans

    Laissez une réponse

    Vous devez avoir ouvert une session pour écrire un commentaire.


    • Il y a actuellement

    • 465 articles/billets en ligne.