Perroquet 1.0.1

Perroquet 1.0.1 vient de sortir. Cette version apporte quelques améliorations mais corrige surtout beaucoup de petits bugs.

- Amélioration du comportement de la fenêtre lors d’un redimensionnement
- Ajouts de nouveaux raccourcis
- Suppression automatique des balises HTML présentes dans les fichiers srt
- Remplacement des | présents dans les fichiers de sous-titres par des retours à la ligne
- Intégration des fichiers perroquet au système (ouvrir avec, type mime, icone,…)
- Amélioration de la boite de dialogue de création d’exercices
- Ajout d’infobulles
- Amélioration du système de frappe pour support les caractères spéciaux (touches mortes par exemple)
- Corrections de divers bugs
- Mise à jour des traductions (Français et turc)

Les téléchargements sont disponibles à cette adresse:

https://launchpad.net/perroquet/+download

PPA:

https://launchpad.net/~fred-bertolus/+archive/perroquet

Plus d’informations sur Perroquet ici:

http://perroquet.b219.org

Sortie de Perroquet 1.0.0, c’est à vous de répéter.

J’ai développé un petit logiciel et je vais vous le présenter.

Origine

J’ai un problème avec les langues étrangères et si j’arrive à lire l’anglais sans trop de problème à force de lire des man-pages, je ne comprend presque rien en écoutant. On me conseille de regarder des films en anglais, mais quand je regarde un film sans les sous-titres, je ne comprend habituellement qu’un seul mot dans chaque phrase (souvent le dernier) et avec les sous-titres, je les lis et comprend sans écouter. Bref, ça ne marche pas avec moi parce que je suis trop nul pour amorcer le cercle vertueux de la compréhension orale.

Après une petite étude de l’existant sous Linux, j’ai conclus que si je voulais un logiciel pour améliorer mon anglais, disponible sous Linux et libre, il fallait que je le crée moi-même.

Ainsi naquit Perroquet.

Principe

Le principe de Perroquet est de créer des exercices de compréhension à partir d’une vidéo en anglais (mais ça marche aussi avec un fichier son) et un fichier de sous-titres lui aussi en anglais.
À partir des timecodes des fichiers de sous-titres, le logiciel fait écouter de courtes séquences du film en présentant un texte à trou que l’utilisateur doit compléter pour continuer le visionnage. L’utilisateur peut répéter chaque séquence autant de fois qu’il est nécessaire pour trouver les réponses ou pour abandonner et demander la correction.
En effet, Perroquet peut aider les plus nuls en complétant partiellement puis totalement certains mots ou en affichant la traduction française si on a pris le soin de fournir en plus un sous-titre français. On peut aussi chercher un mot dans la liste des mots à trouver dans tout l’exercice (bien sûr, le filtre prend des expressions régulières).

Voici pour le principe de Perroquet. Certains diront que ça doit être très long voir un film avec ce système, mais il ne faut pas perdre de vu qu’il s’agit d’un logiciel éducatif et que le but premier est d’apprendre une autre langue.

Perroquet n’est actuellement « compatible » que pour apprendre l’anglais mais il suffira de peu pour permettre de travailler avec d’autres langues.

Première release

Comme Perroquet ne plantais plus sur les 4 postes différents auxquels j’ai eu accès et avec mes 3 fichiers vidéo de test, je me suis dis qu’il était temps d’en faire profiter aux autres.

Voici donc la première version de Perroquet, la symbolique 1.0.0

Le site officiel [1] propose une explication peut-être plus claire du logiciel, une capture d’écran [2] (j’ai abandonné le screencast, il faudra peut être faire un journal concernant le son sous Linux), une documentation [3] et des informations pour le téléchargement et l’installation [4].

Une archive contenant une version très compressée d’Elephant Dream avec les sous-titres vous attend ici [5] pour tester rapidement.

Le logiciel est distribué sous GPL v3.

1 – Accueil du site de Perroquet
2 – Captures d’écran
3 – Documentation
4 – Téléchargement
5 – Demo Elephant Dream

Technologies utilisées

Pour développer, j’ai essayer de récupérer le maximum de choses, j’utilise donc:

  • Python
  • Gstreamer pour la lecture vidéo
  • Gtk via pygtk via gtkbuider via Glade
  • Gettext et Launchpad pour les traductions (il permet de récupérer les pot et de commiter automatiquement les po issues des traductions fait sur Launchpad)

Qt aurait surement pu faire ça à lui tout seul mais je ne connaissais pas Gtk alors c’était l’occasion d’apprendre.

La partie qui m’a posé le plus de problème a été la mise en place des autotools afin qu’un ./configure, make, make install (ou dist) mette tout (icône, code python, fichier de traduction,…) automatiquement au bon endroit pour la création de paquet devient un jeu d’enfant. (Et j’ai pas encore trouver comment ne pas avoir à faire de make install pour tester mes modifications d’ui maintenant que le fichier se trouve dans /usr/…) J’ai pas trouvé de doc concluante sur les autotools et python donc j’ai dû comprendre le fonctionnemt grâce à beaucoup d’apt-get source.

Légalités

Les DVD c’est pas libre, mais si il n’y avait que ça…

J’ai eu beaucoup d’hésitations avant de faire ce logiciel à cause de la légalités des « divx ».
Au départ, je pensais lire directement les DVDs pour y trouver des films et leur sous-titres. Malheureusement l’organisation d’un DVD semble être faite pour dissuader quiconque de les lire (mon logiciel aurais dû trouver les pistes vidéos, audio et les bon sous-titres et lancer tout ça, sans parler de la précision du seek sur un DVD…). De plus les sous-titres sont stockés sous forme d’images, et leur conversion en un format texte exploitable pour mes exercices passe par des systèmes d’OCR à paramètrer à la main pour chaque DVD. L’extraction des sous-titres d’un DVD prend plusieurs heures.

D’un autre coté on a les « divx » qui se lisent très simplement en quelques lignes avec gstreamer et les fichier srt qui se parsent en quelques lignes.

Malheureusement, je n’ai pas trouvé d’informations claires sur la légalité de la possession et de la récupération d’un « divx » dont on détient un DVD.
Savez-vous ce qu’il en est ?

Maintenant, que je connais par cœur Elephant Dream, j’espère qu’il y aura beaucoup de dialogues dans Durian, parce que Big Buck Bunny n’aura pas beaucoup aidé mon projet.

Conclusion

Je remercie Yekcim, que je connais en tant que grand chef graphiste de Wormux, pour avoir respecté à la lettre la GPL pour ses images en fournissant les sources svg (ce qui est rare). Grâce à cela, j’ai modifier le « Thunderbird » de Wormux pour faire un icône présentable en quelques minutes sans avoir utilisé Inkscape auparavant.

Donc, maintenant, j’attends les retours de bug, les patchs, le port KDE et des liens vers des films libre de droit pour pourvoir s’entrainer en tout légalité.

Un fond d’écran Hubble aléatoire en une commande ? C’est possible !

Dans un article du Clapico’s Blog, il est question d’un programme permettant d’afficher en fond d’écran de manière dynamique une image provenant des « Astronomy Picture of the Day ». Ce programme marche très bien mais les images de cette base d’images sont relativement petites et laisse trop de marges à mon gout. En effet, je suis en bi-écran et la surface à couvrir est très grande.

Après quelques recherches j’ai trouvé une base d’images de grande taille : la base d’image du site http://hubblesite.org qui offre des images de très haute définition.

Évidement, la récupération automatique d’images sur un site est spécifique à ce site donc la majorité du programme du Clapico’s Blog était inutilisable. De plus dans le cas de ce programme, l’adresse de l’image peut être directement déduite puisqu’elle est basée uniquement sur la date, et il ya une et une seule image par jour. J’ai donc décidé de tout refaire, pour que ça soit plus amusant, le faire en language shell et en une seul ligne de commande.

La voici :

  1. mkdir -p ~/hubble && gconftool -t string -s /desktop/gnome/background/picture_filename ~/hubble/nowallpaper.jpg && wget -q -O – http://hubblesite.org/gallery/album/entire/npp/all/  | grep  -E ‘pr[0-9]+[a-z]‘ | sed ’s/^.*pr\([0-9]\+[a-z]\+\).*$/\1/g’ | grep -v title | shuf -n 1 | sed ’s/^\([0-9]\{4\}\)0\?\([0-9]\{2\}\)\([a-z]\+\)$/http:\/\/stsciopo.cachefly.net\/hu\/db\/images\/hs-\1-\2-\3-full_jpg.jpg/’ | wget -q -i – -O ~/hubble/wallpaper.jpg && gconftool -t string -s /desktop/gnome/background/picture_filename ~/hubble/wallpaper.jpg

Cette commande est assez longue alors je vais la détailler pas à pas.

  1. mkdir -p ~/hubble

Création d’un dossier « hubble » dans le home de l’utilisateur, et on ne rale pas si le dossier existe déja (pratique si on veux exécuter la commande plusieurs fois).

  1. gconftool -t string -s /desktop/gnome/background/picture_filename ~/hubble/nowallpaper.jpg

On met comme image de fond d’écran une image qui n’existe pas encore. Cela perment d’éviter à gnome de recharger l’image alors qu’elle n’est pas encore totatement téléchargée.

  1. wget -q -O – http://hubblesite.org/gallery/album/entire/npp/all/

On télécharge la page d’acceuil de la galerie avec comme nombre d’image par page « Toutes les images ». On dit aussi à wget d’être silencieux et de ne pas sauver la page dans un fichier mais plutot de l’envoyer à la commande suivante. Cette page HTML contient des miniatures et des liens vers une page permettant de télécharger l’image dans différents formats.

  1. grep  -E ‘pr[0-9]+[a-z]‘

Chaque miniature contient dans le code html un code identifiant l’image. Ce code est constitué de « pr » suivi de 7 chiffres et de 1 ou 2 lettre, par exemple « pr2008035h ». Les quatres premiers chiffres correspondent à l’année le reste est la référence de la photo. Cette partie de la commande permet de filtrer les lignes du fichier HTML pour ne garder que les lignes contenant un code valide. Le résultat est envoyé à la commande suivante.

  1. sed ’s/^.*pr\([0-9]\+[a-z]\+\).*$/\1/g’

Cette partie de la commande isole le code contenu dans les lignes filtrés. On obtient donc une liste de codes.Le résultat est envoyé à la commande suivante.

  1. grep -v title

Cette partie de la commande ne devrait pas être nécessaire mais il s’avère que certaine ligne reste entière parce au lieu d’isoler le code. Je n’ai pas trouvé la raison mais je n’ai pas beaucoup cherché. En tout cas, cette commande enlève toute les lignes contenant « title ». On obtient donc vraiment une liste de codes.Le résultat est envoyé à la commande suivante.

  1. shuf -n 1

Cette partie de la commande permet de tirer au sort un code parmi tous les codes disponible. Le code sélectionné est envoyé à la commande suivante.

  1. sed ’s/^\([0-9]\{4\}\)0\?\([0-9]\{2\}\)\([a-z]\+\)$/http:\/\/stsciopo.cachefly.net\/hu\/db\/images\/hs-\1-\2-\3-full_jpg.jpg/’

Cette partie de la commande permet de transformer le code en l’URL de l’image correspondante. Ainsi, « pr2008035h » devient « http://stsciopo.cachefly.net/hu/db/images/hs-2008-35-h-full_jpg.jpg ». Il y a une subtilité, si la 2ème partie du code, « 035 » içi, commence par un zero, il faut le tronquer.

  1. wget -q -i – -O ~/hubble/wallpaper.jpg

Cette partie de la commande sauvegarde l’image dans le dossier hubble.

  1. gconftool -t string -s /desktop/gnome/background/picture_filename ~/hubble/wallpaper.jpg

Enfin, l’image enregistrée est placée comme fond d’écran.

Quelques informations complémentaires :
- Cette ligne de commande ne fonctionne que sur Gnome, mais devrait être facilement adaptable aux autres environnement de bureau.
- Il y a des vraiment grosses images, la plus grosse que j’ai eu dans mes essais faisait 125mio (oui, c’est bien du jpg !). Certains changement de fond d’écran peuvent être assez long.
- Pour automatiser le changement d’image, je vous laisse consulter l’article de référence qui détaille très bien la procédure.

Shrew-gallery 1.1.2

Un tout petit article pour signaler que ma galerie web « Shrew-gallery » vient de sortir en version 1.1.2. Cette version propose juste la correction d’un bug dans le cas de l’utilisation de tirets dans les noms d’albums.

Le site officiel : http://shrew-gallery.b219.org
Une démo : http://shrew-gallery.b219.org/demo

Redimensionnement et rotation automatique de photos

Je manipule souvent des photos de très grandes tailles. J’ai 2 problématique principales :

- Les photos sont souvent trop lourdes pour être facilement transportable ou diffusable sur un site web.
- Les visionneuses et explorateurs de fichiers sous linux utilisent les données EXIF pour connaitre l’orientation des photos et les afficher correctement. Quand je copie mes photos sur l’ordinateur d’un utilisateur de Windows, on me reproche de ne pas avoir tourné mes photos (opération que la personne en question fait souvent à la main).

J’ai donc fait un petit script qui permet de :

  • recompresser l’original pour gagner de la place (facteur 2 environ)
  • réorienter automatiquement les photos grâce aux données EXIF
  • créer une miniature de 800px de large en conservant le ratio

  1. #!/bin/sh
  2. for img in `ls *.jpg`
  3. do
  4. thumb=`echo $img| sed ’s/^\(.*\).jpg$/\1-thumb.jpg/’`
  5.  
  6. convert $img -resize 800x $thumb
  7. convert $thumb -auto-orient $thumb
  8. convert $img -auto-orient $img
  9. done

Ce script nécessite le logiciel « ImageMagic » disponible ici : http://www.imagemagick.org ou apt://imagemagick pour les Ubunteros.

Shrew-gallery 1.1.1

Je vous avais parlé d’une petite galerie photos en PHP que j’ai développé il y a quelques semaines. Une nouvelle version de ce logiciel est sortie : la version 1.1.1.

Voici la liste des améliorations :

  • Ajout du multi-album
  • Ajout des règles d’accès avancés
  • Support des données EXIF
  • Affichage de la licence
  • Miniatures
  • Support du ogg (theora/vorbis)

Pour rappel le site officiel qui contient un peu plus d’informations : http://shrew-gallery.b219.org

On y trouve entre aussi une démo :
http://shrew-gallery.b219.org/demo

Différencier Theora et Vorbis dans un Ogg en PHP

J’ai eu besoin pour la galerie web que je développe en PHP d’un moyen de détecter le type d’encodage d’un fichier ogg. En effet, les types MIMES trouvés pour un ogg/theora et un ogg/vorbis sont « application/ogg ». Cette information ne me suffit pas car j’ai besoin de savoir si je dois ajouter mon « .ogg » dans une balise « video » ou une balise « audio ».

PHP ne proposant pas en standart cette possibilité de différenciation, j’ai développé une petite classe permettant de le faire. Après une étude rapide des plusieurs fichiers ogg et de la spécification, j’ai pondu ça :

  1. class Ogg {
  2.   private $path;
  3.  
  4.   public function __construct($path){
  5.     $this->path = $path;
  6.   }
  7.  
  8.   function IsOgg(){
  9.     $isOgg;
  10.     $handle = fopen($this->path,‘rb’);
  11.    
  12.     $type = fread($handle,4);
  13.     if($type === false){
  14.       $isOgg = false;
  15.     }else{
  16.       $isOgg = ($type == ‘OggS’);
  17.     }
  18.    
  19.     fclose($handle);
  20.     return $isOgg;
  21.   }
  22.  
  23.   function GetCodec(){
  24.     if(!$this->IsOgg()){
  25.       return false;
  26.     }
  27.    
  28.     $codec;
  29.     $handle = fopen($this->path,‘rb’);
  30.    
  31.     //Read begin of header
  32.     fread($handle,0×1D);
  33.    
  34.     $codec = fread($handle,6);
  35.    
  36.     fclose($handle);
  37.     return $codec;
  38.   }
  39. }
  • IsOgg() renvoie « true » si le fichier est bien un fichier ogg, « false » dans les autres cas.
  • GetCodec() renvoie « false » si le fichier n’est pas de type ogg. Dans les autres cas, cette fonction renvoie le nom du codec, habituellement « theora » ou « vorbis ».

Cette classe fonctionne avec les 4 vidéos dont je dispose et il n’est pas garantis qu’elle fonctionne pour tous les ogg.

(Merci à newneo et SnakeFast pour l’impulsion sur #php-fr)

Shrew gallery

J’ai développé une petite galerie web nommé « Shrew gallery » qui est aussi légère que l’animal dont elle porte le nom.

Le but est de passer 3s pour faire une galerie :

- Créez un dossier et mettez y « index.php » fournis par shrew-gallery
- Copier vos photos par votre moyen préféré

C’est tout.

Le site officiel qui contient un peu plus d’informations : http://shrew-gallery.b219.org

On y trouve entre autre 2 démos utilisant des images du domaine public :
http://shrew-gallery.b219.org/demo
http://shrew-gallery.b219.org/protected_demo (Pour montre l’authentification. Login et mdp : « test »)

print2print : gestionnaire d’impression avancé

Problématique

N’avez-vous jamais galéré pour imprimer quelque chose autrement que via la configuration par défaut de votre imprimante ? Vous essayer de mettre une image en petit, malheureusement un des éléments de la chaine de fabrication de votre feuille imprimé a décider que la mettre au centre est la meilleure des solutions. Vous voulez imprimer en 4 feuilles par pages en paysage, malheureusement en fonction du logiciel, le résultat sera plus ou moins exotique. Pire, imaginez que vous voulez imprimer les pages 3 et 5 en sur la même page, en noir et blanc (pour l’encre, évidement) et mettre un filigramme Confidentiel sur chaque pages mais vous n’avez qu’un pdf protégé… Bon courage.

Introduction

Toutes les interfaces d’impression proposent un certain nombre d’outils qui s’applique à l’ensemble du fichier. Il en résulte que les combinaisons entre ces options est totalement arbitraire si elles ne sont pas commutatives (par exemple, marges de 2cm + 2 par pages). Je propose un programme qui offre une interface différente.

L’idée serait de configurer l’impression via des nodes appliquant des fonctions différentes au document. Une interface graphique permettrait de manière intuitive et puissante de configurer l’impression.

Pour illustrer un peu le concepts, on peut regarder ce qu’a fait Blender pour la configuration du rendu :

http://www.freewebs.com/pwnage303/screens/bloom_DOF.jpg

http://e-learning.tul.cz/~hnidek/pics/blender_render_node_compositor.png

Le but : Pouvoir faire facilement les choses actuellement difficiles et pouvoir faire les choses actuellement impossibles.

Présentation

Le logiciel serait composé de 3 parties :

  • Une bibliothèque comportant le cœur d’interprétation du fichier de configuration et générant les sorties.
  • Une interface graphique permettant de configurer son impression ou de développer des nouvelles fonctionnalités d’impression.
  • Un interpréteur de commande pour exécuter des conversions via un fichier de configuration d’impression.

Idéalement, le programme prendrait en entrée un ensemble de document et génèrerait un ensemble de document.

Cœur d’interprétation

Le cœur d’interprétation met à disposition un ensemble de fonctions qui font chacune une opération simple. Une fonction est un modèle de node et un node est une utilisation d’une fonction (« Perroquet » est une fonction est « coco » est un node de type « Perroquet »). Une fonction prend des paramètres en entrée et génère des paramètres de sortie. Ces paramètres sont typés.

Exemple : coco est un Perroquet. Un Perroquet prend en entrée une phrase et un niveau d’entêtement et génère des phrases.

Pour présenter rapidement un perroquet, j’utiliserai la syntaxe suivante :

  1. Perroquet(string(phrase),number(entetement)=1->string(out)) // répète ‘entetement’ fois ‘phrase’ dans out. En absence de paramêtre ‘entetement’ celui-ci prend la valeur 1

Pour utiliser rapidement un perroquet et afficher qu’il dit :

  1. coco.print
  2. input=InArgument(pos(0))
  3. toString=FileToString(input.out)
  4. coco=Perroquet(phrase("plop"),entetement(10))
  5. fromString=StringToFile(in(coco.out))
  6. output=OutCout(fromString.out)

print -i coco.print « plop  » donne : plop plop plop plop plop plop plop plop plop plop

Les types

Voici une liste non exaustive des types d’entrée et de sortie des fonctions :

  • file : flux d’octet
  • document : ensemble de pages
  • number : un nombre
  • dimension : dimension réelle, par exemple 2.34cm
  • sequence : ensemble de position, par exemple 1-5;10;20-30
  • string : chaine de character
  • boolean : booléen
  • setting : réglage
  • function :fonction

Les fonctions

Voici quelques exemples de fonctions :

Entrée/Sorties

  1. InCin(->file(out))

Ouverture de fichier via l’entrée stardart. Utilisable uniquement en ligne de commande

  1. nArgument(number(argument)->file(out))

Ouverture de fichier dont le chemin correspond au paramètre numéro ‘argument’ du programme

  1. InFile(string(path)->file(out))

Ouverture de fichier dont le chemin est ‘path’

InExec(string(command)->file(out))
Ouverture de fichier dont le contenu est le résultat de l’execution de la commande ‘command’

FileToPdf(file(in)->document(out))
Convertion d’un fichier PDF en document

FileToDvi(file(in)->document(out))
Convertion d’un fichier DVI en document

FileToPs(file(in)->document(out))
Convertion d’un fichier PostScript en document

FileToOdt(file(in)->document(out))
Convertion d’un fichier ODT en document

FileToJpg(file(in)->document(out))
Convertion d’un fichier JPEG en document

OutCout(file(in)->)
Envoie du fichier vers la sortie standart

OutFile(file(in),string(path)->)
Envoie du fichier vers le fichier ‘path’

OutPrint(document(in),setting*(setting)->)
Imprime le document. (le ‘*’ sur le type indique la possibité de paramètre multiples)

FileFromPdf(document(in)->file(out))
Convertit un document en fichier PDF

FileFromDvi(document(in)->file(out))
Convertit un document en fichier DVI

FileFromPs(document(in)->file(out))
Convertit un document en fichier PostScript

FileFromJpg(document(in),number(page)=0->file(out))
Convertit la page ‘page’ de ‘in’ en image jpg

Filtre

Negative(document(in)->document(out))
Passage en négatif

Luminosity(document(in),number(intensity)=0->document(out))

Constast(document(in),number(intensity)=0->document(out))

GreyScale(document(in)->document(out))
Passage en niveau de gris

Sepia(document(in)->document(out))
Passage en sépia

BlackAndWhite(document(in),number(ceil)=128->document(out))
Passage en noir et blanc. Ce qui est au dessus de ceil est blanc, le reste est noir

Structure

SubDocument(document(in),sequence(position)->document(out)
Récupération d’une partie du document, comme une page, ou un ensemble de page

Insert(document(in),document(docToInsert),number(position)=docToInsert.nb_page->document(out))
Insertion d’un document au sein d’un autre document

Concat(document(doc1),document(doc2)->document(out))<code>
Mise bout à bout de 2 documents

<code>Split(document(in),number(position)->document(part1),document(part2));
Coupe ‘in’ a la position ‘position’. Il en résulte ‘part1′ et ‘part2′

Composition

Filigram(document(in),document(filigram),number(opacity)->document(out)
Superpose ‘filigrame’ à ‘in’ avec une opacité de ‘opacity’

WhitePage(->document(out))
Génère une page blanche

Template(document(main),dimension**(template)->document(out))
Réagence les pages d’un document

Type

StringToBoolean(string(in)->boolean(out))

Not(boolean(in)->boolean(out))

LessThan(number(arg1),number(arg2)->boolean(out))

Equal(number(arg1),number(arg2)->boolean(out))

Avancé

ApplyFunction(document(in),function(fnc(document->document))->document(out))
Applique ‘fnc’ à ‘in’

Setting(boolean(rectoVerso),boolean(draft))

Évidement, on peut imaginer beaucoup d’autre fonctions

Exécution

Un script est donc la description d’un ensemble de node exerçant une fonction et reliés entre eux par les paramètres d’entrée et de sortie, formant ainsi un espèce de graphe.

Lors de l’exécution, les nœuds de sorties (ceux de la catégorie « out ») sont identifiés. Toute le processus d’exécution va consister à calculer ces nœuds en résolvant récursivement leur paramètres d’entrés, et donc les nœuds correspondant. Ces nœuds sont identifié puis calculé un par un dans l’ordre adéquate. Enfin, les sorties sont générés (fichier, affichage, …).

Interface graphique

Le but de ce système est de simplifier d’impression. Taper des scripts ne simplifie la vie qu’a une petite partie d’utilisateur. L’interface que je trouverais la plus adéquate à ce genre de travail est une interface ressemblante au « node editor » de Blender.

Composition Blender
Le principe est de représenter chaque node du script par une boite. Sur de coté gauche de la boite des symboles représentent les paramètres d’entrée, et sur la droite, les paramètres de sortie. Des lignes indiquent les relations entre les différents node et une symbolique permet de différencier les différents types.

Les fonctions composés de plusieurs fonctions native peuvent être représenté comme une seule boite, plus ou moins détaillée :

Composition Blender

Les liens se créent par simples glissez-déplacer et l’ajout de node par des menus.

Ligne de commande

Il peut être parfois intéressant d’automatiser la production de document. La CLI (command line interface) permet d’exécuter un script développé indépendamment.

Voici un exemple d’utilisation de la CLI :

print2print -i script.print toto.pdf

Le fichier script.print est un format XML dont un exemple de syntaxe est décrit dans la partie « Exemples ».
Lors de l’utilisation de la CLI, les fonctions « InCin » , « InArgument » et « OutCout » peuvent devenir utiles.

Exemples

Représentation XML de la fonction Insert

Voici un exemple de la manière de coder la fonction Insert(document(main), document(docToInsert), number(position)=docToInsert.nb_page-> document(out))

  1. <function>
  2.     <name>Insert</name>
  3.     <input_list>
  4.         <input>
  5.             <name>main</name>
  6.             <type>document</document>
  7.         </input>
  8.         <input>
  9.             <name>docToInsert</name>
  10.             <type>document</document>
  11.         </input>
  12.         <input>
  13.             <name>position</name>
  14.             <type>integer</document>
  15.             <default>docToInsert.nb_page</default>
  16.         </input>
  17.     </input_list>
  18.     <output_list>
  19.         <output>
  20.             <name>out</name>
  21.             <type>document</document>
  22.             <process>concatSecondPart.out</process>
  23.             <disable>main</disable>
  24.         </output>
  25.     </output_list>
  26.     <nodes>
  27.         <node name="firstPart">
  28.             <function>SubDocument</function>
  29.             <input name="main">main</input>
  30.             <input name="sequence">"0-"+position</input>
  31.         </node>
  32.         <node name="secondPart">
  33.             <function>SubDocument</function>
  34.             <input name="main">main</input>
  35.             <input name="sequence">position+"-"+main.nbPage</input>
  36.         </node>
  37.         <node name="concatFirstPart">
  38.             <function>Concat</function>
  39.             <input name="doc1">first.out</input>
  40.             <input name="doc2">docToInsert</input>
  41.         </node>
  42.         <node name="concatSecondPart">
  43.             <function>Concat</function>
  44.             <input name="doc1">concatFirstPart.out</input>
  45.             <input name="doc2">secondPart.out</input>
  46.         </node>
  47.     </nodes>
  48. </function>

(notez que cette fonction aurait pu être plus simple avec l’utilisation de ‘Split’ apparu après)

Exemple d’impression brouillon, recto verso, 2 par pages,noir et blanc du fichier test.pdft

Logique

  1. input = InFile(file("test.pdf"))
  2. pdf_file = FileToPdf(in(input.out))
  3. noirEtBlanc = BlackAndWhite(in(pdf_file.out))
  4. deuxParPages = Template(main(noirEtBlanc.out),
  5.                                 template("((100%,0%),(100%,50%),(0%,50%),(0%,0%))"
  6.                                  "((100%,50%),(100%,100%),(0%,100%),(0%,50%))"))
  7. rectoVerso = Setting(rectoVerso(true));
  8. draft = Setting(draft(true));
  9. OutPrint(main(deuxParPages.out), setting(rectoVerso,draft))

XML

  1.  
  2. <print>
  3.     <node name="input">
  4.         <function>InFile</function>
  5.         <input name="file">"test.pdf"</input>
  6.     </node>
  7.     <node name="pdf_file">
  8.         <function>FileToPdf</function>
  9.         <input name="in">input.out</input>
  10.     </node>
  11.     <node name="noirEtBlanc">
  12.         <function>BlackAndWhite</function>
  13.         <input name="in">pdf_file.out</input>
  14.     </node>
  15.     <node name="deuxParPages">
  16.         <function>Template</function>
  17.         <input name="main">noirEtBlanc.out</input>
  18.         <input name="template">
  19.             "((100%,0%),(100%,50%),(0%,50%),(0%,0%))"
  20.             "((100%,50%),(100%,100%),(0%,100%),(0%,50%))"
  21.         </input>
  22.     </node>
  23.    
  24.     <node name="rectoVerso">
  25.         <function>Setting</function>
  26.         <input name="rectoVerso">true</input>
  27.     </node>
  28.     <node name="draft">
  29.         <function>Setting</function>
  30.         <input name="draft">true</input>
  31.     </node>
  32.    
  33.     <node>
  34.         <function>OutPrint</function>
  35.         <input name="main">deuxParPages.out</input>
  36.         <input name="setting">rectoVerso.out,draft.out</input>
  37.     </node>
  38. </print>
  39.  

Axes d’améliorations

Conditions

Pour plus de flexibilité, il peut être interessant d’avoir des conditions. Voici un mécanisme permetant de les implémeter :

Chaque fonction a automatiquement un paramètre d’entrée « boolean(enable) » qui permet de désactiver ou activer une fonction. Une fonction désactivée va essayer de retourner l’identité. (la fonction codée ci dessus en exemple retourne ‘main’ si elle est désactivée)

Par exemple voici de fonction en code logique pour passer le document en noir et blanc si le document fait plus de 5 pages, sinon, le passer en sepia :

  1. SepiaOrNB(document(in)->document(out)=in)
  2. {
  3.         moreThanFive = TestSup(in.nb_pages,5)
  4.         sepia = Sepia(in(in),enable(!moreThanFive))
  5.         out = BlackAndWhite(in(sepia),enable(moreThanFive))
  6. }
  7.  

Boucles

Les boucles peuvent être utiles pour effectuer des tache répetitive. Malheuresement, le modéle en node actuel permet difficilement d’ajouter simplement la notion de boucle.

Une des manières de procéder est que le cœur d’analyse mette à disposition une fonction For(number(from),number(to)->number(i)). Cette fonction aurait un effet très spécial sur le graphe. Rien de mieux qu’un petit exemple :

  1.  
  2. docComplet = GetDoc() // Document de 10 pages
  3. for = For(from(0),to(docComplet.out.nb_pages))
  4. file = FileFromJpg(in(page.out),page(for.i))
  5. OutFile(in(file.out),path("image"+for.i+".jpg")
  6.  

Ce code permet de génerer 1 image jpeg par page du document de base. En fait, le cœur d’analyse va creer 10 instance de la branche d’arbre qui à pour dépendance le for, chacune ayant une valeur différente pour « for.i ».

Parfois, la boucle peut avoir un intérêt autre part qu’a la sortie du processus comme sur le script ci-dessus. Dans ce cas, on veut pouvoir éviter que tout l’arbre soit dupliqué. Pour cela, il faut ajouter la fonction du cœur « JoinDocument(document(in),number(position)->document(out)) » qui va permettre de fusionner toutes les instances liés à ce nœud.

  1.  
  2. for = For(from(5),to(10))   /
  3. file = InFile("plop"+for.i+".jpg")
  4. page = FileToJpeg(in(file.out))
  5. document = JoinDocument(in(page.out),position(for.i))
  6. out_file = FileFromPdf(in(document.out))
  7. OutFile(in(file.out),path("plop.pdf")
  8.  

Dans ce script, les 3 premiers nœud sont évalué 5 fois mais le nœud « document » et les suivants ne le sont qu’une seul fois : la fonction « JointDocument » a fusionné les 5 instances de « page » en un seul document.

Ce support des boucles est primitif et ne fonctionne pas forcement, mais propose une idée. Pour un usage plus confortable il faut surement implémenter d’autres fonctions de type Join

Conclusion

Un système de ce type pourrait être bien sympa pour produire des documents. Malheureusement, pour l’utiliser, il faut l’implémenter et je n’en ai pas le temps. Mais si un développeur qui s’enuis ce lance dans cette périlleuse tâche (via un projet open source bien sûr), je serais ravi de l’aider.

PS : Cet article est trop long pour que j’ai le courage de le relire. Si certaines fautes vous éborgnent, n’hésitez pas à m’en faire part.

Que fait firefox pendant mon absence ?

Ce soir est la soirée de la ligne de commande, et j’ai décidé que je voulais savoir si firefox utilisais mon disque dur lorsque je le laisse tourner avec mes onglets habituels. Après quelques minutes de recherche, j’ai trouvé la commande « lsof » qui permet de lister les entrés sortie des différents programmes en cours d’execution. Cette commande possède un mode « repeat » qui permet de scanner régulièrement les entrées sortie en cours :

lsof -r 1 | grep firefox

L’option « -r 1 » signifie « reapeat »toutes les secondes.

J’ai donc laissé tourné cette commande tourner quelques minutes avant d’étudier les logs. Je m’attendais à ce que netvibes ai la palme des entrées/sortie mais j’ai eu la surprise de constater que gmail, en plus de faire une requête chaque seconde mais surtout, via google gears, gmail effectue une dizaine d’entrée sortie sur le disque dur lui même dans « GoogleEmail-Database ».

Cette commande à pas mal de potentiel puisqu’elle permet de visualiser les flux réseau, les flux de fichiers et de bibliothèques et je crois, les appels aux objets de syncronisations. La commande lsof affiche des lignes de ce genre.

firefox   23616       fred   66r      REG        8,1     131036   805679 /usr/share/libthai/thbrk.br

Ici le type d’entrée sortie est « REG » qui signifie « regular file » ce qui correspond aux entrées sortie sur les fichiers du disque dur. « REG » est le type d E/S le plus fréquent mais il y en a bien d’autre. À l’aide d’une belle commande, j’ai identifié tout les différents types d’entrées sorties de mon système à un moment données. Voici la fameuse commande

lsof | sed « s/^[a-zA-Z0-9_-]*s*[0-9]*s*freds*[0-9a-zA-Z]*s*// » | sed « s/^([a-zA-Z0-9_-]*).*/1/ » |sort -u | tr « n »  » « 

Je vais détailler cette commande parce qu’il s’agit de ma première commande utilisant « sed ».

  • « lsof » envoie dans le pipe la liste des entrées sortie suivant le format ci-dessus.
  • « sed « s/^[a-zA-Z0-9_-]*s*[0-9]*s*freds*[0-9a-zA-Z]*s*// » » isole et suprime de début de chaque ligne jusqu’au paramêtre à isoler (REG ou équivalent).
  • « sed « s/^([a-zA-Z0-9_-]*).*/1/ » » remplace l’ensemble de la chaine restante par le premier mot de la chaine restante, soit le paramêtre à isoler.
  • « sort -u » permet de supprimer les doublons  dans la liste de type d’entrée sortie.
  • « tr « n »  »  » permet de remplacer dans la liste d’E/S les retours à la ligne par des espace pour obtenir une liste un peu moins encombrante.

Voici le résulat :

0000 acpid aio apache2 ata ata_aux atd avahi-dae bluetooth bonobo-ac btaddconn btdelconn CHR COMMAND compiz compiz-de console-k cqueue cron cupsd dbus-daem dbus-laun dd dhclient DIR events evolution fast-user FIFO firefox gconfd-2 gconf-hel gdm getty gnome-do gnome-key gnome-pan gnome-pow gnome-scr gnome-set gtk-windo gvfsd gvfsd-bur gvfsd-tra gvfs-fuse gvfs-gpho gvfs-hal- hald hald-addo hald-runn init IPv4 IPv6 kacpid kacpi_not kblockd khelper khubd kintegrit kjournald klogd kondemand krfcommd kseriod ksoftirqd ksuspend_ kswapd0 kthreadd migration mixer_app multiload nautilus NetworkMa nm-system notificat pdflush pulseaudi python REG rt61pci scsi_eh_0 scsi_eh_1 scsi_eh_2 scsi_eh_3 scsi_eh_4 scsi_eh_5 seahorse- sh sshd syslogd system-to tracker-a trackerd trashappl udevd unix unknown update-no watchdog wpa_suppl Xorg x-session

Voila. Je doite que ce soit utile mais en tout cas j’ai appris beaucoup de chose.