Vive la ligne de commande pour lire les vidéos sur internet

L’essor de la vidéo en streaming est une cause d’engorgement du réseau. La mauvaise solution apportée par les opérateurs d’internet est d’instaurer un péage: qui peut payer pourra voir son traffic vidéo privilégié. Cela est à combattre car allant à l’encontre de la libre circulation des données: internet doit rester agnostique du contenu des paquets qui transitent. Cette libre circulation permet à n’importe qui d’avoir l’audience qu’il merite puisque plus son contenu est intéressant, plus il pourra être consulté sans préjuger de sa capacité financière.

L’engordement du réseau à cause de la vidéo reste néanmoins un problème entier et comme souvent nous avons des oeillères qui nous empêchent de voir la solution. Dans de nombreux cas, le streaming n’est pas une contrainte: le poste client est-il réellement limité en espace de stockage ? Le téléchargement de la vidéo est alors un mode de visualisation qui répond au besoin et évite l’engorgement du réseau en cas de visionnage répété de la même vidéo… Il existe des plugins pour Firefox afin de télécharger les vidéos des sites qui les proposent en streaming pour mieux garder l’utilisateur captif de leur portail. Hier soir pourtant ces plugin montrèrent une faille: impossible de télécharger la vidéo convoitée. Je n’en connais pas la cause mais en passant par le script youtube-dl la vidéo était sur mon disque dur en deux temps trois mouvements via la petite commande suivante:

youtube-dl //www.youtube.com/watch?v=v4yOa3tBrB8

Ce programme mérite à être connu car il permet de s’affranchir de la mise à jour forcée vers les nouvelles versions de flash et d’éviter de cautionner l’usage de javascript propriétaire dans nos navigateurs. La ligne de commande c’est bien !

Application Mougeon pour N900

L’arrivé de Free Mobile n’a laissé personne indifférents. Même un collègue peu au fait de la téléphonie, n’ayant pas changé d’abonnement depuis 10 ans, va aller chez Free car il en a assez de payer 7€50 pour un abonnement rechargeable ie communication en sus. Les concurrents aussi ont réagi et Orange le réseau où Free fait du roaming prétend que Free Mobile ne respecte pas vraiment l’accord d’itinérance dans son esprit en faisant passer toutes les communications, ou presque, par Orange.

Pour Android, des applications ont fleuri pour afficher clairement le réseau utilisé (Free ou Orange). Ne voulant pas que le N900 soit en reste, j’ai décidé de faire ma petite application Mougeon. Elle se veut simple car le mougeon à une ascendance de pigeon et n’a pas beaucoup de cervelle, alors bientôt même le mougeon pourra dire s’il est Free ou Orange.

Squelette de projet python pour Maemo5

Le projet Pyjama est aujourd’hui dans un état presque utilisable. Pyjama est un outil écrit en python pour générer un squelette de projet python pour Maemo5. Il s’agit d’un “bootstrapper” à la manière du plugin archetype de maven.

Le principal objectif de Pyjama est atteint puisque la version disponible sous forme de source permet de générer un embryon d’application exécutable. Les sources générés comprennent des outils afin de gérer le messages d’informations, la remontée de bug via googlecode et les tâches asynchrones.

Le prochaine étape est la création d’une interface de saisie des paramètres du projet ainsi que d’une IHM pour Maemo5. Ainsi on pourra créer le squelette sur PC ou bien directement sur le terminal.

Pattern Visiteur: Java vs Python

Duke, the Java Mascot, in the waving pose. Duk...
Image via Wikipedia

Le développement du moteur de génération de pyjama est plus long que prévu. Je le souhaitais extensible facilement mais avec le moins de dépendance externe possible. Après avoir jeté un oeil sur la version python de stringTemplate, j’en ai conclu que le besoin de templating de Pyjama pouvais se contenter de la classe standard string.Template de python. Nul besoin de dépendre d’une librairie externe.

Si le mécanisme de remplacement était trouvé, le moteur de génération restait encore à écrire. En effet dans mon esprit ce moteur doit pouvoir prendre en charge une modification du modèle de projet ou carrément de nouveau type de projet. Les notions de Template en tant que modèle de fichier, de Transformateur en tant qu’unité de transformation commencèrent a émerger, chacune étant indépendante l’une de l’autre et la première à priori fixe tandis que la seconde pouvant s’enrichir au grès des besoins de générations.

Les transformateurs sont appliqués à l’ensemble des templates et un transformateur donné doit agir différemment selon la nature du template. Par exemple le transformateur de source python ne doit pas agir sur le fichier logo du projet et inversement le transformateur de logo doit créer des logos de différentes tailles pour le bureau hildon mais ne pas agir sur les sources python ! Le pattern visiteur frappe à la porte.

Le pattern visiteur permet d’ajouter des comportements à un ensemble d’objet sans toucher aux objets eux-mêmes. Le visiteur ne sait pas sur qui il agit et c’est l’élément visité qui rappel le visiteur en indiquant qui il est, ainsi le visiteur peut appliquer le bon comportement.

Son implémentation la plus simple en Java est la suivante:

public interface IVisitor {
    public void visit(VisitedElement ve);
}

public interface IVisitable {
    public void accept(IVisitor v);
}

class VisitedElement implements IVisitable {
    public void accept(IVisitor visitor){
        visitor.visit(self)
    }
}

class Visitor implements IVisitor {
    public void visit(VisitedElement visiteElement){
       // faire algo spécific à VisitedElement
    }
 }

Ainsi pour appliquer un visiteur à un d’element il suffit de faire

IVisitable e = VisitedElement();
IVisitor v = Visitor();
e.accept(v);

Pour apliquer le visiteur à un ensemble d’élément de nature différente, il suffit d’appeler la méthode accept(IVisitor) de leur interface commune dont l’implémentation, identique dans chacune d’elle, appelle le visiteur en passant l’élément lui-même. Ici opère la magie du compilateur Java qui traduit cela par un appel à la méthode prenant un paramètre du type de l’élément. Ainsi le visiteur sait qui il visite !

Malheureusement en Python une méthode ou plus généralement une fonction ne se définie pas par sa signature (nom + paramètre) mais uniquement par son nom. En python la surcharge de fonction n’existe pas mais uniquement l’écrasement (la redéfinition). Ainsi il n’existe que une et une seule fonction portant un nom donné!

Cela nous empêche d’avoir une implémentation identique de la méthode accept(IVisitor). Les éléments doivent indiquer qui ils sont en appelant des méthodes nommées différemment.

 class IVisitable():
     def accept(self, visitor):
         pass

 class IVisitor():
     def visit_Element(self, e):
         pass

 class Element(IVisitable):
     def accept(self,visitor):
         visitor.visit_Element(self)

 class Visitor(IVisitor):
     def visit_Element(self, e):
         # action spécifique quand on gère un Element
         pass

Autorotation des applications Python sous Maemo 5

A screenshot of the Maemo interface on a Nokia...
Image via Wikipedia

La rotation de l’affichage suivant l’orientation du terminal est devenue depuis la PR1.3 une fonctionnalité intégrée au bureau Hildon, si bien que toutes les applications sont encouragées à proposer également la rotation de leur IHM suivant la position du mobile.

La gestion de l’orientation se fait par interception et appel à l’Hardware Abstract Layer (HAL) par le D-Bus. Cela peut en rebuter plus d’un, mais heureusement un hacker (comprendre développeur) australien, Thomas Perl, propose une classe python qui s’occupe de la gestion de l’orientation. Cette classe fait partie de la version maemo5 de gPodder et est disponible en GPL3. C’est donc avec bonheur que toutes les applications python sous Maemo 5 (évidement en GPL3) peuvent accéder à l’autorotation.

La classe en elle-même possède un dépendance sur gpodder et il faudra alors modifier 2 lignes de code relatives à l’internationalisation afin de la réutiliser dans sa propre application. C’est ce que j’ai fait pour ajouter l’autorotation à Gnatirac.

Le libre c’est bon !

Prototype d’application python pour Maemo 5

Often called "albino", this amelanis...
Image via Wikipedia

La mise en place d’un nouveau projet python pour Maemo5 est consitituée de plusieurs étapes:

  1. création du référentiel de sources: ex: subversion chez google code
  2. création du projet sous ESBox
  3. ajout des fichiers pour setuptool
  4. ajout de l’arborescence initiale du projet (architecture)
  5. import des sources dans le référentiel
  6. enregistrement du projet sur PYPI
  7. création du site du projet: ex: blog chez blogspot
  8. création du groupe de discussion: ex: google group

La création des fichiers initiaux est une tâche rébarbative mais nécessaire pour d’une part industrialiser la production (build, déploiement et d’autre part assurer la qualité du code (architecture en couche, réutilisation…). D’un projet à l’autre ces étapes ne diffèrent que par les caractéristiques du projet:

  • Nom du projet
  • Nom de l’auteur
  • Licence du projet
  • Date de création
  • Nom de certaines classes etc.

En somme la phase d’initialisation du projet doit pouvoir s’automatiser. Un peu à la manière des archétypes maven, il serait intéressant de pouvoir générer à l’aide d’une commande (et d’un assistant) le squelette d’un nouveau projet qui compile et s’exécute !

Le projet Pyjama est sans doute le dernier que je crée par copier/coller d’un projet précédent. Pyjama doit en effet permettre la création de projet via une simple commande.

Client Picasa pour N900

English: Nokia N900 smartphone (display shows ...
Image via Wikipedia

Le N900 dispose d’une grande capacité de stockage (27 Go) mais cela n’élude pas le besoin de sauvegarde externe qui peut se faire par un script utilisant rsync automatisé par alarmed ou bien par l’utilitaire Caritang qui permet de transférer les médias (photo et vidéo) sur Picasa.

Nous nous intéressons au cas où les médias sont archivés sur Picasa. La consultation des médias ne peut pas se faire aisément sur le terminal. En effet, la version complète utilise un style d’affichage prévu pour les écrans d’ordinateur et non pas pour le petit écran du N900. De plus l’utilisation des javascript mettent déjà à mal la puissance faiblarde du N900 dont le CPU plafonne à 600 Mhz (voire 800 Mhz par overclocking) et l’avènement de nouvelles technologies telles que HTML5 vont rendre le navigateur du N900 inopérant sur les nouveaux sites. Finalement l’utilisation de la version web de picasa n’est donc pas une solution viable.

Un client spécific permettrait d’utiliser correctement les possibilités du terminal (écran, cpu) afin de rendre accessible les média archivés. Mais il semble que ce besoin n’ait pas eu d’écho dans la communauté des développeurs Maemo5: il n’y a pas d’application cliente Picasa pour le N900 ! Alors j’en ai développé une: Gnatirac. Gnatirac utilise le binding python de l’API Gdata pour Picasa Web et permet de naviguer dans les albums et les photos d’un compte picasa. Voilà, le N900 dispose de son client Picasa.

Création de widget GTK+ en python sous Maemo5

En dépiThe new GTK+ logo.t de mon idée première de dériver de la classe gtk.Widget, ne maîtrisant pas toutes les subtilités de GTK+, je me suis rabattu sur la solution de spécialiser la classe gtk.DrawingArea.

La classe GenTree du projet Maegen illustre comment il est aisé de fabriquer ses propres widgets ! Dans cette exemple le widget n’est pas interactif et il se contente de se dessiner. C’est déjà un début.

L’interaction avec l’utilisateur se fera simplement en s’abonant aux événements et ne devrait pas poser de difficultés. Ma seule inquiètude se situe dans la capacité à s’interfacer avec les autres conteneurs GTK tels que les Aligment etc. Un widget bien élevé doit être capable d’adapter sa taille en fonction de son conteneur. Peut-on le faire avec un DrawingArea ?

Créer un widget GTK en python sous Maemo5

GTK Widgets
Image by crafterm via Flickr

Dans le développement de Maegen j’ai eu envie de créer une vue affichant l’arbe généalogique de manière arborescente. Pour cela j’ai utilisé un gtk.DrawingArea dans lequel je dessine l’arbre. Les méthodes de dessin et les diverses variables sont portées par la fenêtre qui contient le gtk.DrawingArea.

L’envie de réutiliser cette arbre ailleur qu’en pleine fenêtre m’invite à en faire un widget à part entière que je pourrai mettre dans une fenêtre ou tout autre widget conteneur.

Le site learningpython montre un exemple de création de widget personnalisé et l’exemple fonctionne quasiment parfaitement sur Ubuntu 11.04. Quasiment car le widget ne s’affiche que si on redimensionne la fenêtre. Je me lance alors dans un refatoring pour extraire le code de dessin et le mettre dans une classe dérivant de gtk.Widget. Voir le code ici.

Le premier problème vient d’une inattention fébrile à l’idée de créer mon premier widget… L’oublie de la ligne suivante:

# register the class as a Gtk widget
gobject.type_register(MyOwnWidgetClass)

qui est obligatoire sinon la méthode __init__() de la classe gtk.Widget refuse de s’éxécuter sur la classe dérivée.

Malheueusement une fois cette ligne ajoutée, le widget reste définivement vide sans le moindre petit arbre dedans. En y regardant de plus près, la méthode do_expose_event() n’est pas appelée. Cela est encore pour moi un mystère…

Quoiqu’il en soit il y a un contournement qui consiste à dériver de gtk.DrawingArea pour créer mon widget. Cette solution est sans doute la plus simple compte tenu du fait que mon code de départ manipule un DrawingArea ! Le site suivant montre une telle réalisation : zetcode.com

Google Data API 2.0.15 et Maemo5 en python

.AVI en el N900Maegen, une application de généalogie pour Maemo5/N900 utilise le service googlecode de google pour la soumission de bug. Pour cela Maegen se base sur la librairie gdata fournie par google. Le code de rapport de bug a été écrit il y a plus d’un an et suppose que la version de gdata soit la 2.0.9 alors que la version courante est la 2.0.15

Ayant testé Maegen sur des machines différentes sur lesquelles des versions récentes de gdata étaient installées, je pensais qu’une dépendance de type au moins la 2.0.9 était une solution valable. Cela donne dans le fichier setup.py

setup(... install_requires=["gdata>=2.0.9"], ...)

Tout semblait marcher correctement puisque à la fois sur le terminal et les machines de développement (Virtual Appliance Maemo SDK), Maegen s’executait correctement, jusqu’à ce que je décide de passer sur une machine vierge (Virtual Appliance Maemo SDK) où jamais gdata n’avait été installé. Et là ce fut le drame, Maegen ne fonctionnait plus. La faute à gdata introuvable.

Une première solution est provoquer l’installation des dépendances. Pour cela se mettre sous l’environnement de compilation croisée

scratchbox

puis se placer dans le répertoire du projet

cd workspace/maegen

et enfin lancer une installation

python2.5 setup.py install

Lorsque les lignes cabalistiques ont fini de défiler, on remarque que gdata 2.0.15 a été installé. Le lancement de Maegen echoue cette fois sur l’absence du paquet json !

D’où vient le problème ? En regardant la version de gdata sur les machine où Maegen fonctionne, je remarque alors une différence: c’est la 2.0.14. Je désinstalle donc gdata 2.0.15 et installe la 2.0.14 à partir des sources dans scratchbox et là le miracle se produit: Maegen reprend vie !

En comparant le module gdata.gauth.py entre la 2.0.14 et la 2.0.15, on constate que des tentatives d’imports de json sont effectués à partir de la ligne 64 et finalement suppose que python 2.6 est utlisé en essyant un ultime import json, ce qui malheureusement échouera lamentablement sur le N900 qui ne dispose que de python 2.5 !

Voilà, le mystère est résolu, à moins de rajouter une dépendance vers json, je doit me résoudre à ne pas utliser la dernière version de gdata. Pour cela la directive de dépendance dans le fichier setup.py devient:

install_requires=["gdata>=2.0.9, <=2.0.14"]

En conclusion, les dépendances externes doivent être utiliser avec parcimonie et on doit éviter les dépendances ouvertes en leur préférant une dépendance exacte si possible. En effet moins il y a de dépendance, plus l’application est autonome et légère avec des risque de conflit de version en moins. De plus les dépendances ouvertes ouvrent la porte à une régression apportée par une nouvelle version.