Skywalker13

Diary of an ex-GeeXboX developer…

Enna et les Metadata ~ 🇫🇷

Posted at — Apr 3, 2010

Hello,

Depuis plusieurs semaines j’ai passablement baissé le rythme sur les projets. D’une part pour cause d’obligations qui ne me permettent pas de passer énormément de temps sur GeeXboX et d’autre part parce que depuis octobre à février j’ai passé beaucoup de temps sur Enna, libplayer et libvalhalla, et ça commençait un peu à me saturer.

En principe je devrais me concentrer sur le générateur d’ISO. Depuis la branche 2 de GeeXboX, ce pauvre générateur est complètement dépassé. Que se sois les fichiers de configuration qui ont changés, des variables renommées, la disparition des thèmes du bootsplash et du menu OSD. Bref plein de petites choses qui ensemble font un gros paquet. J’ai qu’en même commencé gentiment son nettoyage de printemps. Reste à trouver aussi la motivation nécessaire (comme d’habitude).

Enna et le “ondemand”

Au début de la semaine, j’ai fais quelques petites modifications sur libvalhalla. Puis en re-testant sous Enna, un ancien “problème” m’a ennuyé plus que d’habitude. C’est un comportement bien connu depuis longtemps mais qui demandait peut être un surplus de motivation pour en venir à bout. Non pas que c’est difficile à “corriger”, mais plutôt que ce n’était pas spécialement intéressant à faire. Du coup j’ai laissé trainé depuis des mois. Jusqu’à cette semaine où ça m’a particulièrement contrarié. Peut être était-ce juste une mauvaise journée, j’ai donc qu’en même pris le temps de régler cet “inconvénient”.

Comme vous le savez (j’espère), Enna utilise libvalhalla pour les méta-données. Si on ne se fie que sur ce que montre Enna, il y avait un comportement qui donnait l’impression que c’était très lent à afficher les méta-données. Par exemple, vous sélectionnez un film et il n’y a pas de backdrop, de titre, etc,… Vous pouviez laisser une heure la sélection sur le même film, vous n’auriez rien vu s’afficher de plus. La première réaction c’est que c’est lent. Mais en réalité ce n’est pas le cas. Il faut savoir que libvalhalla met à disposition plus de fonctionnalités qu’Enna en utilise. Une de ces fonctionnalité est le “ondemand”. Celle-ci était (jusqu’à hier) uniquement utilisée à moitié.

Le principe (avant):

  1. Vous sélectionnez un film
  2. Enna envoie une requête “ondemand” à libvalhalla
  3. libvalhalla va faire un certain nombre de choses pour donner plus de priorité à cette demande que pour les fichiers trouvés par le scanner. Et
  4. c’est tout :-)

En fait Enna demandait à libvalhalla de lui donner en priorité les metadata d’un fichier, mais sans aller consulter libvalhalla pour savoir si les metadata étaient disponibles ou non. Du coup il était nécessaire de changer de fichier, puis de revenir sur le précédent pour que ça commence à afficher quelque chose. Bref, c’est ça qui m’a énervé en début de semaine.

En fait libvalhalla peut signaler à Enna où en est le fichier dans les étapes que sont le “parsing”, “grabbing” et “downloading”. Mais Enna ignorait complètement ces événements.

Le principe (depuis hier):

  1. Vous sélectionnez un film
  2. Enna envoie une requête “ondemand” à libvalhalla
  3. libvalhalla va faire un certain nombre de choses pour donner plus de priorité à cette demande que pour les fichiers trouvés par le scanner.
  4. libvalhalla envoie l’événement “parsed”
  5. Enna l’attrape et remet à jour certaines metadata (comme le titre par exemple)
  6. libvalhalla envoie un événement “grabbed” après chaque grabber.
  7. Enna l’attrape et remet à jour certaines metadata (comme le synopsis par exemple)
  8. libvalhalla envoie un événement “ended”
  9. Enna l’attrape et remet à jour une fois pour toute.

Ainsi, on voit apparaitre au fur et à mesure les informations (également dans le panneau d’informations CTRL+I). C’est bien plus sympathique.

Le fait de sélectionner un fichier, indique à Enna qu’une requête “ondemand” doit être envoyée à libvalhalla, et ce mécanisme a des effets importants. En passant d’un fichier à l’autre vous envoyez chaque fois une nouvelle requête “ondemand” (à noter que la requête n’a aucun impacte si le fichier demandé est déjà complètement disponible dans la base de donnée).

Rappel sur le “ondemand”

La fonction s’utilise très simplement.

valhalla_ondemand (valhalla_t * handle, const char * path);

On donne le chemin du fichier qui nous intéresse (qu’il soit référencé par le scanner ou non). Maintenant imaginons qu’on appel 10 fois cette fonction à petit intervalle de temps avec des fichiers différents. Le but du “ondemand” c’est de donner une haute priorité à un fichier ou quelques fichiers. Si vous appelez la fonction pour beaucoup de fichiers, finalement ils deviennent tous “haute priorité” et entre eux il n’y a plus de différence (trop de “ondemand”, tue le “ondemand”). Mais pour comprendre pourquoi, il m’est nécessaire de donner plus de détails sur le fonctionnement de libvalhalla.

J’ai déjà donné passablement d’explications dans d’autres billets de ce blog, ainsi je vais aller droit au but. Le fait qu’il y ait beaucoup de threads et qu’un “paquet” (donc une structure qui identifie un fichier) peut exister dans plusieurs threads à la fois (des cas très particuliers que je ne vais pas expliquer ici); il est difficile de savoir où se trouve un fichier à un moment précis. Ainsi la requête “ondemand” va endormir tous les threads concernés pour pouvoir chercher le fichier pour qui il faut donner une plus haute priorité. Et c’est cette action qui a un impacte non négligeable sur libvalhalla. La plupart des threads sont rapidement endormis. Mais certains sont un peu plus récalcitrants. Je pense tout particulièrement aux grabbers. Il suffit qu’un webservice bloque (problème de connexion), et donc il est nécessaire d’attendre le timeout de libcurl jusqu’au moment de pouvoir endormir ce fameux thread. Ce timeout je l’ai mis à 20 sec. Mais je me tâte presque à le réduire encore un peu (à noter qu’avec libvalhalla-1 et donc Enna-0.4 les timeouts sont pires car se sont ceux de l’OS et en principe ils sont bien supérieurs à 20 secondes).

Maintenant imaginez plusieurs “ondemand” à des intervalles relativement proches et ce foutu webservice qui bloque. Il faut donc patienter sur libcurl. Ce phénomène est visible également à la fermeture d’Enna. Si les grabbers sont actifs, au moment du “force-stop”; au pire avec Enna-devel vous devez attendre 20 sec sur un grabber. Il serait peut être bien que je permette de paramétrer ce temps directement depuis l’enna.cfg. Actuellement il est en dur dans la configuration pour libcurl de libvalhalla.

Je parle de “timeout”, mais en réalité c’est un petit peu différent. C’est le temps maximal autorisé pour une transmission. Par exemple si un fichier prend plus de 20 secondes à être téléchargé, libcurl va qu’en même l’interrompre à 20 secondes. Ainsi en utilisant un temps bien trop faible, vous risquez de faire échouer bêtement la plupart des grabbers.

L’idéal serait de pouvoir forcer libcurl à interrompre une liaison indépendamment de la valeur du “timeout”. Ca serait particulièrement utile lors du “force-stop”.
[EDIT: ce problème a été fixé!]

Autre phénomène

Les threads de libvalhalla communiquent par l’intermédiaire de FIFO. La haute priorité est simplement d’utiliser le FIFO en tant que LIFO le temps du push. Dit autrement, au lieu de mettre le paquet au fond de la pile, on le met directement au-dessus. Ainsi s’il y a plusieurs requêtes “ondemand”, chacune d’elle va se remettre au-dessus. Peu importe que la requête a été fait avant ou après. Chaque fois qu’un paquet change de thread il se remet au-dessus. C’est un peu comme si tous les paquets “ondemand” se battaient pour la première place.

Au final, tous les paquets “ondemand” seront traités en priorité par rapport au scanner, tout en restant entre eux, sur le même pied d’égalité.

Il reste encore du travail

L’état actuel n’est pas encore parfait. Dans l’activité musique, les requêtes “ondemand” se font uniquement lorsqu’un fichier est sélectionné (tout comme pour la vidéo). Le passage d’un fichier à l’autre par le biais des boutons précédent/suivant et via l’événement EOS (End Of Stream) ne provoque aucun “ondemand”. La raison vient directement de l’implémentation du “mediaplayer”. Les actions ne se font pas dans l’activité, mais directement en interne dans le mediaplayer. Et les metadata ne sont pas tout à fait considérées de la même manière entre l’activité vidéo et musique. Pour avoir un “ondemand” plus homogène, il faudrait revoir en profondeur le “mediaplayer” et éliminer les particularités (ennuyeuses) de chaque activité.

A bientôt,
Mathieu SCHROETER