La vidéo par libplayer avec Enna

Hello,

cet article tente d’expliquer techniquement et sans partir dans trop de détails, comment il est possible d’afficher la vidéo de MPlayer (ou même d’un autre wrapper comme xine) directement dans la fenêtre de Enna.

Avant la révision 801 de libplayer

Un problème majeur persistait avec libplayer depuis toujours. La fenêtre X11 créée pour la sortie vidéo avec Enna n’était pas bien adaptée à un environnement géré par un Window Manager. Cela veut dire que cette fenêtre ne peut pas être manipulée par l’utilisateur (invisible dans la barre des applications, elle ne peut pas être attrapée avec la souris, …), comme si elle n’existait pas.

Techniquement, la raison vient du flag override_redirect de la fenêtre principale (il faut comprendre par “principale” que la fenêtre a pour parent le root), mit à 1, qui veut dire qu’elle doit être ignorée du Window Manager. On peut alors légitimement se poser la question:

Pourquoi donc ne pas créer une fenêtre sans l’override_redirect et ainsi pouvoir la manipuler commes les autres?

Et bien la réalité n’est pas aussi simple. Une fenêtre atteignable par l’utilisateur est une fenêtre qui peut attraper des évènements (clavier et souris par exemple). Et dans le cas contraire, les évènements ignorés par la fenêtre sont soient propagés à la fenêtre parente (propagation ascendante), soient détruits (pour les lecteurs qui froncent les sourcils, comprenez que je ne parle pas des cas particuliers).
L’illustration ci-contre montre une fenêtre principale A qui a un enfant B qui lui à un enfant C. Les évènements étant alors propagés de C à A. On pourrait bien sûr imaginer de détruire les évènements dans B pour ne pas les propager sur A. Tout est possible (même rediriger les évènements ailleurs), mais l’idée présentée ici fait office de comportement par défaut.

C’est donc là que l’avantage principal de la fenêtre en override_redirect intervient. Celle-ci étant ignorée du Window Manager, aucun évènement ne lui parvient car ils sont naturellement envoyés à la fenêtre qui à le focus (logique non?). Prenons un exemple.. Vous avez une petite application basée sur libplayer qui fonctionne en mode console. Vous ouvrez votre terminal GNOME et lancez un film via cette application. libplayer va créer une fenêtre en override_redirect et en plein écran, les évènements seront donc envoyés au terminal (la fenêtre vidéo ne pouvant pas avoir le focus). Ainsi l’exposition de la fenêtre devant celle du terminal n’a aucun impacte.
Mais il y a un piège! Si vous changez de fenêtre à l’aide de ALT-TAB (par exemple), le focus sera dirigé ailleurs mais la vidéo restera toujours en avant plan. Il ne vous est plus possible de piloter votre programme vidéo car les évènements seront renvoyés à la fenêtre attrapée avec ALT-TAB jusqu’à ce que vous rendiez le focus au terminal.

Cette exemple peut être testé à l’aide de l’application test-player compilée avec libplayer.

$test-player -p mplayer video.mpg
action> p

Mouais, alors que faire?

Le fait de travailler sur Enna m’a forcé à trouver une solution propre. Le problème cité précédemment n’aurait pas d’impact direct sur GeeXboX car la seule application active dans X11 serait Enna. Mais libplayer doit être universel, alors un changement s’imposait de toute façon.

Les fenêtres qui se listent dans votre barre d’applications sont des fenêtres dont le parent est le root du display X11 en cours (grosso-modo). Mais une application peut elle-même être composée de sous-fenêtres, et elles ne sont pas toujours visibles directement par l’utilisateur (imaginez des calques qui se superposent comme dans un logiciel de dessin).
Il faut bien comprendre que le langage du serveur X est relativement bas niveau. Si vous utilisez GNOME, les fenêtres sont gérées par GTK. Ce que vous voyez, c’est uniquement ce que GTK veut bien vous montrer. Et c’est exactement la même chose avec Qt. Mais que se sois GTK ou Qt, derrière il y a toujours le serveur X avec son langage, exploitable via les librairies Xlib et XCB. libplayer utilisant Xlib (implicitement XCB par wrapping), il est donc facile de dialoguer avec le serveur X sans se soucier du Window Manager. Et pour ce faire, il faut connaître l’identifiant de la fenêtre avec laquelle on désire y faire des manipulations. Il est très facile de retrouver cet identifiant avec les EFL (cf. r275 de Enna).

Une solution se profile

Mon but était de créer la fenêtre non plus par rapport au root de X11, mais par rapport à la fenêtre de Enna (je connais son ID). La fenêtre de libplayer n’est donc plus sœur avec la fenêtre de Enna, mais enfant. Ainsi, les évènements envoyés sur la fenêtre de libplayer sont renvoyés sur Enna sans la moindre écriture de code. La propagation ascendante de X11 fait simplement son job. Il est donc désormais possible de changer de fenêtre avec ALT-TAB et de revenir sur Enna comme avec n’importe quel application. Car la vidéo n’étant plus rattachée au root, elle suivra implicitement sa fenêtre parente “Enna” comme si elle faisait partie intégrante du programme.

On peut alors se demander qu’est-ce qui se passe au niveau de Enna. Et bien Ecore_Evas ne rentre pas en compte car il ignore l’existence de cette fenêtre enfant.

A bientôt,

Mathieu SCHROETER

3 thoughts on “La vidéo par libplayer avec Enna

  1. Merci Mathieu pour les efforts de communication sur le Blog. Comme je l’ai dit sur le forum c’est un plus non négligeable pour ceux qui suivent l’évolution de leur distro préféré … :)

  2. C’est aussi un plus pour moi et les autres devs. Ca permet de garder un suivi avec quelques explications plus détaillées sur les pourquoi et comment des commits.
    Surtout que je ne cherche pas à vulgariser les articles pour le commun des mortels :-P

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s