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

