Home ]

PLAYER MP3 SOUS MOZILLA

Clément Chatelain

Université de Rouen
Maitrise IUP GEII année 2000-2001


Remerciements

Je tiens à remercier particulièrement David Olivari, mon maitre de stage, pour son aide et ses précieux conseils.

Je remercie également toute l'équipe d'eProcess pour m'avoir accueilli pour mon stage, et d'avoir facilité mon intégration au sein de l'entreprise.

Table des matières
Introduction
1. Contexte
1.1. L'entreprise: eProcess
1.1.1. Présentation
1.1.2. Les orientations techniques de la société
1.2. Situation dans l'entreprise
2. Etudes préalables
2.1. La programmation modulaire
2.1.1. Le XPCOM
2.1.2. Mozilla
2.2. étude du format mp3
2.2.1. Codage
2.2.2. Décodage
2.3. langages utilisés
2.3.1. HTML/XML/XUL
2.3.2. Le CSS
2.3.3. Le JavaScript
3. Réalisation
3.1. la librairie de décompression
3.1.1. recherche d'une librairie adaptée
3.1.2. transformation de la librairie
3.1.3. compilation
3.2. création du composant
3.2.1. création de l'interface et génération des squelettes
3.2.2. Implémentation des fonctions
3.3. interface utilisateur
3.3.1. le fichier JavaScript
3.3.2. le fichier xul
3.3.3. intégration du player à mozilla
Conclusion
Bibliographie
A. les abbréviations
B. listing

Introduction

On peut définir le Multimédia comme l'ensemble des techniques et des produits qui présentent l'information sous forme combinée de sons, d'images, d'animations et de vidéos. C'est une activité dont la demande est forte auprès du grand public. C'est de ce postulat qu'est né le projet d'eProcess: réaliser une plateforme modulaire logicielle permettant de manipuler de l'information multimédia en environnement embarqué. Chacun des modules constitue un composant logiciel réutilisable.

L'objectif de mon stage était de réaliser un module player mp3 destiné à rejoindre la plateforme de composants logiciels. Le player devait être intégré à Mozilla, navigateur internet également conçu avec la technologie des composants logiciels. eProcess utilise pour ses composants la meme librairie que mozilla, qui permet la programmation modulaire: la librairie XPCOM.

J'ai débuté mon stage par des recherches et études concernant la programmation modulaire, puis le format de compression audio MP3. J'ai ensuite fait l'apprentissage d'un certain nombre d'outils et de langages tels que linux, le XML, ou le JavaScript, ce qui m'a permis de débuter la réalisation du player mp3 avec toutes les connaissances indispensables. Je présenterai donc la société eProcess qui m'a accueilli, ainsi que ses choix technologiques, puis j'exposerai mes recherches et la réalisation de mon projet.


Chapitre 1. Contexte

1.1. L'entreprise: eProcess

eProcess est une société récente située à Montpellier, dont l'activité est le développement d'applications multimédia pour systèmes embarqués.


1.1.1. Présentation

eProcess est une société anonyme d'une douzaine de personne créée en aout 1999. C'est un éditeur logiciel de produits multimédia pour systèmes embarqués. Elle a consacré sa première année d'existence à la recherche, ce qui lui a permis de cibler son activité: développement d'une technologie logicielle modulaire permettant le traitement d'information multimédia.

les activités de la société

eProcess développe une plateforme modulaire qui permet, en fonction de la demande du client, d'ajouter des modules necessaires à différentes applications multimédias. On aura donc un module "vidéo", un module "internet", un module "mp3", etc... L'application principale prévue est la VOD: Vidéo On Demand, installée par exemple dans des chambres d'hotel. Tous ces modules sont placés sur un système d'exploitation réduit. Cette plateforme s'intègre en environnement embarqué: principalement des set top boxes (boitier qu'on "pose sur un poste de télévision").

eProcess a developpé une plate forme logicielle sur une base de noyau linux baptisée "enux", capable de faire tourner ces modules. enux possède les particularités suivantes héritées de linux: aspect multiplate-forme, stabilité, évolutivité, compatibilité. L'embarqué dont il est question doit permettre une utilisation grand public et donc simple. Ce projet repose en partie sur un postulat: le développement de l'internet haut débit.

L'entreprise étant récente, la recherche et développement constitue sa principale activité. Les modules opérationnels ou en cours de développement sont: les modules player vidéo MPEG 1, 2 et 4, browser internet, scheduler, lecteur flash, micro-serveur web.


1.1.2. Les orientations techniques de la société

la communauté open source

L'entreprise contribue à la communauté "open source". La communauté open source consiste à partager ses créations logicielles en les plaçant sous une licence GPL: cette licence sert à ce que le programme ne soit pas récupéré puis vendu. La licence GPL assure la gratuité du programme.

Cela implique beaucoup de choses: dans le souci de portabilité des programmes, ceux ci sont pour la plupart multi plateforme: ils font abstraction aussi bien du hardware (type de matériel) que de l'OS. Tous ces "logiciels libres" sont developpés dans des langages "standards". L'ensemble des sources de ses réalisations sont mises à disposition gratuitement sur internet. L'entreprise fait ses bénéfices en vendant des applications spécifiques de plus haut niveau, en utilisant le code open source. Elle contribue à la communauté en plaçant elle meme des programmes

Les avantages sont le partage de connaissances, et l'habitude d'analyser des programmes. Si cela est parfois difficile ou fastidieux à "décoder", cela est très formateur et impose un codage propre et lisible. La récupération de programme, module ou librairie est donc fréquente, d'où un gros travail de mise à jour des connaissances: "qu'existe t'il comme programme et comme outil dans tel ou tel domaine ?". L'open source ou "logiciel libre" permet également de bénéficier des améliorations et évolutions permanentes.

la technologie des composants logiciels

Si on associe cette "philosophie" avec le langage objet, on voit se profiler le principe suivant: il ne sert à rien de developper plusieurs fois la même application ou partie d'application; tous les algorithmes principaux existent. Il ne sert donc à rien de les réécrire, il est préférable d'apprendre à les réutiliser. C'est la technologie des composants logiciels: la valeur du programme n'est plus dans le code en lui même mais dans la connexion et l'intégration de programmes simples. C'est là que le langage objet prend toute sa dimension par sa réutilisabilité, sa lisibilité et sa sécurité.

Un autre principe directeur d'eProcess est la réalisation de logiciels "cross platform", c'est à dire de logiciels faisant abstraction du support matériel et du système d'exploitation acceuillant ce logiciel. Ce principe se voit respecté grâce à l'utilisation de linux et de variables NSPR (types de variables génériques qui s'adaptent ensuite au système sur lequel le logiciel est implanté). L'utilisation de linux et du logiciel libre implique également l'utilisation de toute la gamme des outils GNU tels que gcc, emacs,...


1.2. Situation dans l'entreprise

L'entreprise est divisée en différents pôles:

  • le pole Framework aspect modulaire des projets, XPCOM

  • le pole Services

  • le pole Hardware

  • le pole Vidéo

J'étais intégré au sein du pole "framework", dont le projet est de réaliser une plateforme pour le developpement d'applications multimédias baptisé "COMEDIA" (COMponents for multiMEDIA). Le but étant de creer un catalogue de modules, d'outils de développement, ou environnement d'éxécution. Par exemple la télé interactive, le push média ou la vidéo on demand. Cette plateforme devra pouvoir tourner en embarqué, c'est à dire que la manipulation et l'exploitation des données seront faits en environnements différents d'un ordinateur classique. Ceci impose une plateforme et des modules "cross platform". D'ou le choix pour Comedia de s'appuyer sur les travaux de mozilla: mozilla est un browser internet developpé par Netscape grace au XPCOM, et placé en open source avec des caractéristiques intéressantes qui seront developpées par la suite.

C'est donc dans ce contexte que s'est déroulé mon stage: j'ai réalisé un player MP3 qui constituera un module capable de s'intégrer à comédia.


Chapitre 2. Etudes préalables

Vue d'ensemble du projet

Mon stage consiste à réaliser un "module mp3" ou "composant mp3" en utilisant la technologie des composants logiciels. C'est à dire un composant réutilisable, multiplateforme. Ce projet s'est déroulé en deux phases: études et réalisation du player.

Nous allons utiliser une librairie de décompression déja existante, qui sera accessible par le composant XPCOM. Puis le composant XPCOM se contrôlera grâce à un fichier JavaScript.

Figure 2-1. les couches logicielles du player mp3

Ce projet s'est déroulé en deux phases: études, puis réalisation du player. L'étude comprend plusieurs parties:


2.1. La programmation modulaire

La programmation modulaire apporte plusieurs avantages par rapport à la programmation traditionnelle. Elle permet la réutilisabilité grâce au fractionnement du code source en module. Un module est un ensemble de fonctions ou de classes cohérentes. Le module ou composant est défini par une partie publique qui va permettre un controle du composant depuis l'exterieur, et une partie privée qui ne sera pas accessible depuis l'exterieur. La partie publique est appelée interface, et la partie privée est sécurisée et constitue la "mécanique interne du composant. La réutilisabilité du code dépendra de la qualité de définition de l'interface.

Nous avons vu que la programmation modulaire permettait la réutilisabilité, ses règles d'écriture rendent également le programme lisible, portable, plus facile à comprendre, à maintenir et à modifier. En effet, le fractionnement en module implique une compilation fractionnée, il suffit donc de recompiler la seule partie modifiée et non l'ensemble du code. La librairie XPCOM permet la programmation en composants logiciels. J'ai étudié cette librairie pour développer mon player mp3. Puis je me suis intéréssé à mozilla, navigateur internet développé par Netscape et utilisant la technologie XPCOM. A terme le player sera intégré à Mozilla.


2.1.1. Le XPCOM

généralités

XPCOM signifie Cross Platform Component Object Model. Il permet la programmation modulaire. Les composants logiciels ainsi créés sont cross-platform. Les composants peuvent être écrit et sont accessible en C, C++ ou JavaScript. Le XPCOM se rapproche du modèle COM Microsoft (MSCOM) mais se distingue par le fait que tous les composants XPCOM de mozilla sont open source. La librairie MSCOM appartient à microsoft qui est succeptible de la modifier. En XPCOM, les sources des 150 composants de mozilla sont accessibles et gratuites. Le XPCOM est une librairie basée sur les interfaces: les composants disposent d'interfaces dont ils peuvent hériter entre eux.

Aspect "Cross Platform" grâce au NSPR

La librairie XPCOM permet la programmation dite "cross platform", c'est à dire indépendante du support de l'OS et du hardware. On peut réaliser de tels programmes grâce à des types de variables appelées variables NSPR (Netscape Portable Runtime). La librairie NSPR compilée sur la machine transforme la variable NSPR en type de donnée adapté au système présent.

exemple: Si on prend une variable int en C, elle ne sera pas interprétée de la même manière suivant le système d'exploitation et le type de machine. Elle pourra être codée comme un entier de 8, 16 ou 32 bits. Par contre en XPCOM, un entier de 8 bits sera un NSInt8. Puisque la librairie NSPR aura fait le lien entre NSInt8 et "entier de 8 bits" à sa compilation, on aura bien un entier de 8 bits.

Les types NSPR permettent de manipuler les variables de type entiers,flottants, pointeurs, mais aussi de manipuler des threads (création, synchronisation, contrôle), d'avoir accès aux entrées sortie: fichiers, adresses réseau, sockets, impression, de manipuler des images bitmaps, de gerer la mémoire,... Les variables NSPR utilisées systématiquement rendent donc un programme portable.

le partage du code

Le XPCOM permet la programmation modulaire grâce au chargement dynamique des librairies. Les librairies dynamiques (fichiers *.so: Shared Object) permettent d'avoir un code commun et de ne séparer que les données. D'où un gain de place en mémoire et sur le disque. Les librairies dynamiques sont donc des ressources qu'il faut gérer au fur et à mesure des besoins de telle ou telle application: elles ont des points d'entrée dynamiques. Au lieu d'avoir à la compilation la création d'un fichier objet (fichier *.o) utilisable par une seule application, on obtient un shared object accessible par plusieurs autres objets en même temps. Quand la librairie n'est plus demandée, on coupe les liaisons.

Les interfaces

Les composants ne peuvent communiquer entre eux que par l'intermédiaire d'une interface. L'interface définit tout ce qui est accessible depuis l'extérieur d'un composant. Les composants possèdent tous au moins une interface, c'est à dire un "moyen de les commander". Mais ils peuvent en avoir plusieurs. La mécanique interne du composant est protégée. On voit donc apparaitre l'interêt du langage objet pour ce type de programmation: sécurité, protection des membres entre les classes. L'interface définit un contrat entre le composant et l'extérieur. L'exterieur peut être une utilisation directe (par exemple par l'intermédiaire d'un fichier JavaScript), ou bien un autre composant. Par exemple dans le cas du player MP3, l'interface sera l'ensemble des fonctions auquel l'utilisateur aura accès pour jouer de la musique: fonctions play, pause, stop,... Le code nécessaire à la décompression du MP3 ne fait pas partie de l'interface car l'utilisateur ne doit pas y avoir accès. Il restera interne au composant.

En XPCOM, il existe un système d'héritage entre les interfaces. Toutes les interfaces dérivent d'une seule : "nsISupport". Cette interface est la plus élémentaire et ne contient que trois membres:

	  interface nsISupports
{
void QueryInterface(in nsIIDRef uuid, out nsQIResult result);
nsrefcnt AddRef();
nsrefcnt Release();
};

  • La méthode QueryInterface: Pointeur sur l'interface. Permet de faire une requète pour savoir quelles interfaces sont supportées par un composant.

  • La méthode AddRef: incrémente le nombre d'instance en cours du composant.

  • La méthode Release: décrémente le nombre d'instance en cours du composant.

Toute interface contiendra donc au minimum ces trois méthodes dont le rôle est de gerer un compteur de référence qui représente les points d'entrée effectivement utilisés. Si le compteur devient nul, on detruit l'objet. Le programmeur devra faire heriter son interface de nsISupport (au minimum) , et de rajouter les méthodes ou attributs qui seront accessibles depuis l'extérieur.

On définit l'interface dans un fichier IDL: Interface Description Langage. L'IDL possède son propre compilateur, xpidl. C'est dans ce fichier qu'on précise l'héritage. On créé donc une classe d'interface qui possède des méthodes et attributs définit dans l'idl et dans les interfaces héritées. Voici un exemple de fichier idl:

	  #include "nsISupports.idl"  

[scriptable, uuid(e4c3f63c-9073-4625-8e61-3f308b05cce0)]

/* L'interface hérite de nsISupports */
interface cmIFoo : nsISupports
{
/* attributs */
attribute float variable_1;
attribute string variable_2;

/* méthodes */
void (in entree_1 out sortie_1 );
};

La compilation d'un idl donne un xpt: fichier binaire qui décrit l'interface. La compilation de l'idl donne également un header file C++ qui contient le squelette des classes nécessaires à la création du composant. C'est le point de départ de l'écriture du code source. Nous verrons par la suite (chapitre III: Réalisation) comment créer le composant en lui même à partir du fichier d'interface.


2.1.2. Mozilla

historique

L'application la plus connue utilisant la librairie XPCOM est mozilla, le navigateur internet de Netscape. Ce projet a été lancé en janvier 1998, date à laquelle Netscape a rendu tous les codes sources de mozilla publics, ne pouvant lutter commercialement devant l'extension de l'internet explorer de Microsoft. En même temps que la mise en open source de ce projet, Netscape ouvre le site mozilla.org qui sert de plaque tournante à tous les développeurs s'interessant au XPCOM et à la programmation modulaire. Plusieurs ingénieurs animateurs s'occupent par ailleurs du projet. Cette action sert autant aux développeurs qui peuvent se servir des composants existants, qu'à Netscape, qui développe ainsi sa plateforme modulaire.

Aspects techniques

Mozilla utilise un langage de description d'interface utilisateur appelé XUL dérivant du XML (cf. 2.3.1). Ce qui permet un aspect rendu "skinnable", c'est à dire un aspect graphique facilement modifiable. Toute la navigation est effectuée par le javascript qui accède aux objets XPCOM par l'intermédiaire du XPConnect.

Mozilla demande beaucoup de ressources: il a été conçu en anticipant l'accélération de la puissance des PC. Ceci est du à l'utilisation du XUL pour l'aspect rendu, ainsi que du javascript dans les pages web. En effet, le javascript est précompilé à chaque chargement, et le XML doit etre transformé en DOM. Le DOM (Document Object Model) est une représentation logique qui décrit les interfaces de manière neutre. Les programmes et scripts XML accèdent dynamiquement au contenu des pages. Inversement, les autres navigateurs tels que Netscape ou internet explorer ont un traitement statique de l'interface: les menus, boutons, boites de dialogue sont fait par l'intermédiaire du C ou C++. D'une manière générale, mozilla demande plus de ressources qu'un navigateur traditionnel, mais il est plus souple si la machine est suffisament puissante.

Mozilla étant conçu en XPCOM, il hérite du mécanisme des types NSPR. Lors de la compilation de mozilla, la librairie NSPR fait la relation entre le système et les types NSPR.


2.2. étude du format mp3

Introduction au mp3

Le MP3 est un format de fichier audio compressé définit par MPEG (Moving Pictures Expert Group), créé en 1991. MP3 signifie MPeg layer 3. Il était au départ utilisé pour coder la partie audio du MPEG1 qui est un format de vidéo (utilisé dans les anciens CDI Philips). Le but est de réduire la taille des fichiers audios habituellement assez lourds en espace mémoire. Le MP3 peut avoir un taux de compression variable mais très couramment il est de 1/12: c'est la limite admise où il n'y a pas de pertes de qualité sonore pour l'oreille humaine par rapport à la qualité CD. Le MP3 est basé sur un algorithme de compresssion dit perceptuel: il utilise une description mathématique des limitations de la perception auditive humaine.

Le décodage du mp3 demande de bien comprendre les principes de codage et les formats des fichiers mp3. Nous allons donc commencer par exposer les principes de l'encodage.


2.2.1. Codage

Le principe de codage est basé sur l'hypothèse qu'il n'est pas nécessaire de coder les fréquences inaudibles par l'homme. En effet, certains sons ont des fréquences trop élevées ou trop faibles pour être entendus, et certains sont cachés par d'autres sons ayant une amplitude plus importante. On se sert des caractéristiques de l'ouïe humaine et du traitement par le cerveau des informations acoustiques: c'est la psychoacoustique. Par exemple le chant d'un oiseau à coté d'un marteau piqueur ne sera pas codé, ou deux fréquences de même ordre jouées en même temps: on ne codera que celle ayant la plus grande amplitude. Si on fait une analyse en fréquence, on verra ces signaux, mais l'oreille humaine ne les distinguera pas.

Il y a donc suppression d'information mais pas de pertes de qualité sonore. Dans l'absolu la qualité MP3 est inférieure à celle du CD: une analyse spectrale à partir de bruits blancs revèle des trous et une coupure du spectre à  16KHz, mais pour l'oreille humaine, il est très difficile de faire la différence entre un son MP3 et un son CD.

On voit donc apparaitre l'algorithme utilisé pour coder du MP3: on va subdiviser le signal d'entrée en petites bandes de fréquences grâce à fourier, puis on va determiner si oui ou non cette bande de fréquence (donc de l'information) devra être codée grâce au modèle psychoacoustique. Il reste ensuite à quantifier et coder.

voici le schéma général de l'encodage MP3:

Figure 2-2. schema global de l'encodage mp3

Le modèle Psychoacoustique

Le modèle psychoacoustique décompose le signal d'entrée en petites portions appelées frames et determine les composantes spectrales de chaque portion, via une transformation en fréquence. Puis en fonction des propriétés de l'oreille humaine, il estime un seuil de masquage (threshold) pour chaque bande de fréquence. Toute les valeurs inférieures à ce seuil ne seront pas codées.

la partie filtre

La partie filtre appartient à la famille des filtres hybrides: elle est composée d'abord d'un banc de filtre polyphase qui sépare en trente-deux canaux, suivi d'une MDCT (Modified Discrete Cosine Transform).

quantification et codage

Enfin, en fonction des sorties des deux blocs précédents, il reste à faire la quantification et le codage. La quantification est faite en gardant le bruit de quantification en dessous du seuil de masquage. L'algorithme utilisé pour le codage de l'information quantifiée est le traditionnel codage Huffman. Le codage Huffman parcourt la suite d'information une première fois et determine la fréquence de chacune des informations élémentaires. Puis on parcourt une deuxième fois les valeurs et on code chaque valeur par un nombre binaire dont la taille (le nombre de bits) dépend de la fréquence de la valeur. Plus la fréquence est élevée, moins le nombre de bit pour coder cette valeur sera grand. On minimise ainsi la taille de l'information en compressant l'information redondante.

les frames

Il y a une séparation du flot de bit (bitstream) en frames. chaque frame a deux facteurs la caractérisant: le modèle mathématique donné par la partie psycho-acoustique, et le bit rate, qui est le nombre de bit donné par seconde pour stocker l'information. Le bitrate standard pour le MP3 est de 128 Kbps. On est alors à taux constant (CBR: Constant Bit Rate). L'inconvénient du CBR est que la musique (et le son en général) n'est pas prévue pour être codée à taux constant: certains sons sont plus riches que d'autres. D'ou l'apparition du VBR: Variable Bit Rate. Il permet d'assigner moins de bit à des portions de son qui ne necessitent pas un gros bit rate, contrairement à des sons complexes où plusieurs instruments jouent en même temps par exemple, où il est alors interessant d'avoir plus de place. Il peut alors arriver qu' un son soit trop complexe pour etre codé sans perte de qualité sonore avec un certain bitrate. On utilise alors un buffer de quelques octets qui stocke temporairement ces données. Le buffer (appelé "reservoir of bytes") se videra lors de passages qui necessitent un bitrate plus faible.

stéréo

Il y a deux manières de coder la stereo:

-soit on code les deux canaux tels quels (on double alors la taille mémoire),

-soit on utilise la redondance qui existe entre le canal droit et gauche. On utilise alors le mode Joint Stero (JS) qui code d'un coté la somme des deux signaux, et de l'autre la différence. C'est le mode le plus fréquemment utilisé.

remarque sur le principe d'encodage: Le codage Huffman est le parfait complément du modèle perceptuel: Quand les sons sont complexes, le modèle perceptuel est très efficace car il masque beaucoup de fréquences du fait de leur grand nombre (compression par suppression de données). Par contre lors de sons purs, c'est le codage Huffman qui est très bien adapté pour la compression. En effet, les sons purs contiennent des séries d'octets répétitives, ce qui convient au codage huffman puisque les parties réccurentes sont codées avec peu de bits.


2.2.2. Décodage

Le décodage est beaucoup moins complexe que l'encodage. Il se fait en trois parties successives: le décodage du bitstream, la quantification inverse, et le filtrage de synthèse qui permet de recuperer le signal audio.

Nous allons ici nous interesser au format de fichier MP3. Le bitstream est composé de frames. Pour chaque format MPEG, il y a un nombre de frame constant par seconde. Pour le MPEG-1, il est de 38 fps. Donc pour une fréquence d'échantillonnage et un bitrate donné, la taille d?une frame est constante et est donnée par la formule:

taille_frame = 144*bit rate/freq. d'echantillonnage

Par exemple pour un son de départ échantillonné à 44.1 KHZ, et pour un bitrate de 128 Kbps pour le MP3 (fréquent), la taille d'une frame sera de 418 octets. Le rôle du decodeur sera donc d'assembler les données des millions de frames constituant un fichier MP3 pour reconstituer les données audio.

les entête ou "header" de frame

Chaque frame contient une entête (header) de 4 octets contenant les méta-données telles que la synchronisation, la version MPEG, le bitrate, la fréquence d'échantillonnage, la couche(layer), etc... Ceci permet aux frame d'être indépendantes les unes des autres si on est à un bit rate constant (CBR: Constant Bit Rate, en opposition au VBR: Variable Bit Rate). Dans les fichiers CBR, l'en-tête est identique pour chaque frame, alors qu'elle ne l'est pas dans les fichiers VBR puisque le bitrate est compris dedans.

les 32 bits du header:

Figure 2-3. header de frame mp3

  • SYNC: 11 bits de synchronisation

  • ID: ID de la version MPEG

  • Layer: numéro de la couche (layer)

  • Prot Bit: bit de protection

  • Bitrate: index du bitrate: une table donne le bitrate en fonction de cet index et de la version MPEG.

  • frequency: index de la fréquence d'échantillonnage.

  • Pad bit: padding bit

  • Priv bit: private bit

  • Mode: channel mode (stéréo/mono/joint stéréo/dual channel)

  • Mode extension: mode extension

  • Copy: copyright

  • Home: original

  • Emphasis: emphasis

  • Audio data: données

Le decodeur se préoccupe simplement d'examiner le bitstream de header et de données. Les données sont fréquentielles et codées par huffman. Il faut d'abord detecter les bits de synchronisation, puis analyser le header des frames et les informations telles que le ID3. Puis on utilise une IMDCT (Inverse Modified Discrete Cosine Transform) pour repasser en temporel. Ensuite il suffit de décoder les données en fonction des informations trouvées dans l'en tête (en particulier le bitrate et la fréquence d'échantillonnage) et de reconstruire le signal audio.

Pour pouvoir decoder du MP3, il faut une machine de type pentium. Les machines assez récentes permettent donc largement de decoder du MP3. Par contre le décodage requiert des ressources; cela reste assez transparent sur les OS gérant bien le multitâche (Linux, BeOS,...), mais sur les autres systèmes d'exploitation le décodage ralenti les autres tâches. Sur une machine correcte, les différences entre les différents lecteurs MP3 sont négligeables.

Remarques:

  • En CBR, les en-tête de chaque frame sont identiques, il y a donc redondance de l'information. En fait, ce n'est pas grave car la taille de l'en-tête (4 octets) est négligeable par rapport à la taille d'une frame ( 418 octets en général).

  • Dans les fichiers MP3, on a la possibilité de mettre un tag ID3 qui permet de stocker des informations concernant la bande audio. Elle contient le nom de l'artiste, le titre, le copyright ou des commentaires. Il existe deux spécifications de ID3: ID3v1 et ID3v2. la version 2 n'est pas lisible par les vieux lecteurs MP3 mais elle permet de stocker beaucoup plus de données que ID3v1. Ces tags peuvent etre placés avant ou après les frames mais il est préférable de les placer avant, pour connaitre ces informations dès le début en cas de streaming.

  • Il existe une version MPEG 2.5: c'est une extension rajoutée à la version MPEG 2 pour les fichiers à bit rate très bas. Elle permet d'utiliser des fréquences d'échantillonnage plus faibles. Dans le cas d'une utilisation de MPEG2.5, il est recommendé de mettre 12 et non 11 bit de synchronisation.


2.3. langages utilisés

Ne connaissant pas tous les langages de programmation nécessaires à la réalisation et à l'utilisation d'un composant XPCOM, j'ai appris les techniques de standards tels que le XML, CSS, JavaScript.


2.3.1. HTML/XML/XUL

Je tiens à remercier particulièrement David Olivari, mon maitre de stage, pour son aide et ses précieux conseils.

le HTML

HTML signifie HyperText Markup Language, ou langage de balisage hypertexte. C' est un langage de présentation utilisant des balises. Il a été créé par le Tim Berners-Lee à partir de SGML (Standard Generalized Markup Language ). Son objectif est de permettre la création de pages Web riches en images et en textes. Tout navigateur sait comment afficher un document HTML, même si celui-ci ne contient pas d'informations stylistiques.

le XML

Le XML a été créé par le W3C et, comme HTML, c'est un langage de balisage. Il est né de la simplification de SGML (Standard Generalized Markup Language ) pour que ce dernier soit plus largement adopté par les développeurs et adaptable au Web, tout en gardant sa richesse. Le W3C a veillé à ce qu'il soit simple et compatible avec SGML. L'objectif de XML est de laisser le développeur créer ses propres balises afin d'identifier précisément le contenu (comme dans une base de données). XML est donc une généralisation du HTML.

Le DOM (Document Object Model) est la manière de représenter le XML de façon logique. C'est le DOM qui permet de manipuler les objets du XML. Il contient des méthodes permettant de modifier les attributs de ces objets.

le XUL

Le XUL (XML based User Interface Language) a été créé pour réaliser l'interface utilisateur de mozilla. Le XUL a un rôle de description logique d'une page. Il peut afficher des éléments tels que des menus, boutons, champs de texte, barres de défilement, arbres,etc... Il remplace un fichier XML, et permet de controler tous les aspects d'une interface web. Ce langage fait parti de la famille XML, et contient donc toutes les fonctionnalités du XML. Il permet de changer facilement et rapidement l'allure d'une page. Ce langage n'est pour l'instant compris que par Netscape 6 ou Mozilla, mais il est conçut de manière à être portable. On définit des zones avec plus ou moins de "mollesse" (flex), ce qui permet de gérer le comportement des pages lors d'un redimmensionnement.


2.3.2. Le CSS

XML, comme SGML, ne décrit pas comment afficher le contenu d'un document. Un mécanisme stylistique doit donc être associé à un document XML afin de pouvoir l'afficher. Il fallait donc trouver un moyen d'améliorer l'aspect mise en page du HTML. Le Consortium W3, l'organisme chargé de standardiser les technologies Web, a donc recommandé l'adoption de la norme CSS, c'est-à-dire "Cascading Style Sheet" ou feuilles de style en cascade. Le but des feuilles de style consiste à associer différents styles aux marqueurs HTML. Plutot que d'avoir un style prédéfini pour chaque marqueur (par exemple le texte de type H1 a une taille et une police prédéfinie), les feuilles de style offrent la possibilité de modifier les styles prédéfinis à l'aide de règles. Pour associer un fichier CSS à un fichier HTML ou XUL, il suffit de le preciser grace à la ligne:

	    <?xml-stylesheet href="player.css" type="text/css"?>
La même feuille de style peut s'appliquer à plusieurs documents HTML. Le CSS permet de changer tout l'aspect d'une page HTML/XUL selon ses préférences.


2.3.3. Le JavaScript

Le JavaScript va permettre de contrôler le composant XPCOM en créant une instance du composant, puis en faisant appel aux membres de celui ci.

Caractéristiques du JavaScript

JavaScript a été développé par Netscape, il permet de manipuler des objets et donc de rendre les pages web interactives. C'est un langage "interprété", c'est à dire qu'il n'est pas compilé, il est éxécuté à la volée par le navigateur (coté client). Comme il est éxécuté au moment du chargement sans compilation, le code est visible et est accessible par tout le monde(view source). Il peut être:

  • intégré par un fichier HTML ou XUL qui lui attache un fichier JavaScript (.js) qui va contenir des fonctions appelées sur des évènements (events: click de souris,...)

  • intégré dans un fichier HTML ou XUL par l'intermédiaire des balises

    <SCRIPT> ... </SCRIPT>
    dans ce cas quand le navigateur fait appel à un document HTML, il en fait la lecture de haut en bas en exécutant les codes JavaScript qui sont rencontrés.

JavaScript découpe les pages HTML (ou XUL) en objets et permet d'acceder à ces objets, d'en retirer des informations et de les manipuler. En particulier, le javascript va avoir accès aux composants XPCOM par l'intermédiaire du XPConnect.

le lien JavaScript-XPCOM

Dans le cas du player mp3, l'objet à manipuler sera un objet XPCOM qui devra etre créé, puis manipulé par l'intermédiaire de l'interface décrite dans l'IDL. Le JavaScript est conçut pour réagir à des actions utilisateur: appui sur un bouton, click de souris,... C'est donc le JavaScript qui va faire le lien entre le composant XPCOM et l'interface utilisateur.

D'une manière générale, on peut résumer le rôle des différents langages:

  • créer le composant: XPCOM

  • acceder et piloter le composant: javascript via XPConnect.

  • réaliser l'interface utilisateur: XUL, CSS.

Il existe un outil grâce auquel j'ai pu manipuler des composants: XPCshell. C'est un interpreteur de javascript en ligne de commande. XPCshell utilise le XPConnect qui permet d'acceder au XPCOM par le JavaScript. J'ai donc pu instancier des composants XPCOM déja existant et faire appel à leurs membres. voici un exemple de manipulation d'un objet XPCOM par du javascript:

	    var ma_classe = Components.classes["@mozilla.org/sample;1"]
var mon_interface = Components.interfaces.nsISample
var mon_instance = ma_classe.createInstance();
mon_objet = mon_instance.QueryInterface(mon_interface);
mon_objet.methode1();
ce script créé une instance d'un composant et appelle une de ses fonctions. Plus précisement:

Les deux premières lignes sont deux variables reprèsentant une classe et une interface avec laquelle on désire l'utiliser. La troisième ligne créé une instance de la classe ["@mozilla.org/sample;1"]. Puis on fait une requète (méthode QueryInterface) sur cette instance qui demande l'accès à une interface de ce compos ant: nsISample. En effet les composants peuvent supporter plusieurs interfaces. Enfin on peut acceder aux méthodes de l'objet ainsi créé par un appel classique: objet.méthode().

remarque:l'entité classes["@mozilla.org/sample;1"] est appelé le "contractID" et représente un identifiant littéral d'un numéro de classe unique de 128 bits:4f0b5784-d59f-4605-9776-41aa8b399f59


Chapitre 3. Réalisation

Ayant aquis les connaissance requises, j'ai pu réaliser le player mp3. Le player sera constitué d'un composant XPCOM et d'un fichier JavaScript, et l'interface utilisateur sera réalisée en XUL. Le XUL qui permet une interface conviviale (boutons, menus,...) accèdera au JavaScript qui instanciera et pilotera le composant XPCOM. J'ai dans un premier temps mené des recherches sur la forme de la librairie de décompression, puis j'ai réalisé le composant XPCOM, et enfin l'interface permettant de le piloter.


3.1. la librairie de décompression

3.1.1. recherche d'une librairie adaptée

Dans le but de placer mon projet en open source, je me suis intéréssé à du code placé sous licence GPL. J'ai étudié de nombreuses librairies pour voir laquelle était la plus adaptée à mon player: les sources de xmms, mpg123, mpglib, icecast, et l'implémentation "originale" du fraunhofer Institute. Tous les codes sources étaient issus de ce dernier. Aucune ne contenait de fonctions évoluées de type play, pause,... ; et toutes étaient difficiles d'accès depuis un programme éxterieur. En effet, les librairies de décompression sont complexes et entourées de couches logicielles successives contenant l'aspect graphique des players, ainsi que de nombreuses options superflues pour mon projet. J'ai choisi les sources de mpg123, qui reprend lui aussi le code original avec très peu de changements. Mpg123 est un player tournant sous linux en mode console et avec une licence GPL. Ce code contient des fonctions d'assez bas niveau telles que le décodage d'une frame, de son header, le vidage du buffer "reservoir of byte" lorsque le bitrate est plus faible, etc. Il est composé d'une imbrication d'environ 80 fichier pour l'ensemble du code.


3.1.2. transformation de la librairie

Le code source a été modifié en supprimant des fichiers inutiles pour la création du composant. Le but est d'avoir accès depuis l'extérieur à une fonction "lecture". Pour cela, le programme principal a été extrait de son fichier, et remplacé par un programme principal et les fonctions "lecture d'un fichier mp3", "chargement d'un fichier mp3" et initialisation. Pour cela les fonctions principales appellent les fonctions de bas niveau suivantes nécessaires à la lecture :

  • open_stream(file_name,-1);  // ouverture du flot de données et passage en argument du nom de fichier à decoder
  • read_frame_init();     // lecture de la frame et de son header pour 
    avoir son bitrate
  • play_frame(init,&fr);  // jouage d'une frame

et à l'initialisation:

  • audio_info_struct_init(&ai);
  • make_decode_tables(outscale1);
  • audio_capabilities(&ai);
  • init_layer2();
  • init_layer3(fr.down_sample);

remarque: Les structures fr et ai représentent les frames.

On a donc remplacé l'ancien programme principal (qui prenait en compte des options inutiles et toute l'interface graphique) par un nouveau beaucoup plus court ne contenant que des appels de fonctions. Ceci a entrainé plusieurs problèmes, en particulier au niveau des déclarations. Une bonne analyse du code source m'a permis de rendre l'ensemble de fichier cohérent et compilable. Toutes les variables globales utilisées qui sont déclarées dans un autre fichier doivent être reconnues dans le nouveau fichier. Elles ont donc été déclarées en extern dans mon programme principal. Pour la cohérence des déclarations, une mise à jour des header files à également été nécessaire. (cf. main.c)


3.1.3. compilation

Ces fonctions vont être compilées en une librairie dynamique. Plutôt que de faire la compilation à la main, on utilise l'utilitaire UNIX Make permettant la compilation et l'édition des liens, ainsi que la création de la librairie dynamique. Make fonctionne avec un fichier: Makefile qui fait l'appel aux commandes de compilation. On peut utiliser n'importe quel compilateur; nous utiliserons gcc, compilateur universel GNU. Make possède une syntaxe particulière. Il est possible d'y inserer des commandes shell. Le principe est de spécifier pour chaque fichier que l'on veut créer l'ensemble des fichiers nécessaires, suivit de la commabde à éxécuter: la syntaxe est la suivante:

	  cible: liste de dépendances
commandes UNIX

Make va parcourir le fichier et résoudre les dépendances, c'est à dire qu'il va determiner l'ordre dans lequel il faut compiler les fichiers pour avoir les fichiers necessaires à la compilation suivante. Son éxécution (commande make) va créer les fichiers dans l'ordre logique des dépendances. Par exemple la création de la librairie dynamique nécessite les fichiers objets qui eux même nécessitent les fichiers C et les headers (cf. fichier Makefile). Make va alors d'abord créer les fichiers objets, et ensuite la librairie dynamique.

voici un exemple de ligne de commande de Makefile: La première ligne spécifie les fichiers nécessaires à la création d'un fichier objet ; la seconde est la ligne de commande en elle même (l'entité $(CFLAGS) représente des options de compilation).

	  fichier_objet.o: header1.h fichier1.cpp header2.h fichier2.cpp
g++ $(CFLAGS) -c fichier1.cpp fichier2.cpp

Makefile permet d'éxécuter toute la compilation en une seule commande. Cela se révèle très utile quand le nombre de fichiers augmente. Il permet également de spécifier le chemin des librairies utilisées et de modifier les commandes de compilation en fonction de l'OS utilisé.

Le fichier Makefile existant a été modifié: on y inclut le nouveau main contenant les fonctions de contrôle du player, et on rajoute en fin de fichier la commande qui créé la librairie dynamique:

	  libCLEMP3.so: mpg123.o common.o $(OBJECTS) decode_2to1.o decode_4to1.o \
tabinit.o audio.o layer1.o layer2.o layer3.o buffer.o \
getlopt.o httpget.o xfermem.o equalizer.o \
decode_ntom.o wav.o readers.o getbits.o \
control_generic.o decode_i386.o dct64_i386.o audio_oss.o
gcc -shared -lm mpg123.o tabinit.o common.o layer1.o \
layer2.o layer3.o audio.o buffer.o decode_2to1.o \
decode_4to1.o getlopt.o httpget.o xfermem.o decode_ntom.o \
wav.o readers.o getbits.o control_generic.o decode_i386.o\
dct64_i386.o audio_oss.o -o libCLEMP3.so

On a ainsi créé notre librairie dynamique de "ressource", celle qui contient les algorithmes de décompression. On va maintenant s'occuper de rendre cette librairie accessible dynamiquement pour l'utiliser en tant que composant. Ce sera le role du composant XPCOM: il se chargera de faire le lien entre un client qui désire par exemple acceder à la fonction lecture, et la librairie de décompression.


3.2. création du composant

La création du composant s'articule autour de l'interface, d'où une reflexion sur celle ci: L'interface doit répondre à la question suivante: Quels doivent etre les éléments accessibles de l'exterieur destinés à controler le composant ? Ou, dans le cas du player mp3: grâce à quelles méthodes et attributs va t'on pouvoir piloter le composant "player mp3" ? L'interface sera donc composée de:

  • La méthode "lecture" ou "play"

  • La méthode "stop"

  • La méthode "pause"

  • L'attribut "nom du fichier" ("nomfic")

  • La méthode "chargement" ou "load" prenant en argument un nom de fichier

  • La méthode "initialisation" ou "init"


3.2.1. création de l'interface et génération des squelettes

Nous avons définit l'interface du player mp3. Avant d'écrire le fichier idl, il est indispensable de creer un id pour cette interface. On utilise pour cela uuidgen sous linux. L'id est alors unique. Voici le fichier idl pour l'interface du player mp3 intitulée cmIMP3player :

	    /*
* IDL pour le player mp3
*/

#include "nsISupports.idl"

[scriptable, uuid(e4c3f63c-9073-4625-8e61-3f308b05cce0)]

interface cmIMP3player : nsISupports
{
attribute string nomfic;
void Play();
void pause();
void stop();
void load(in string fname );
void init();
};

remarque: l'option "scriptable" précise que l'interface sera accessible par du JavaScript. Dans le cas contraire c'est une sécurité: on interdit l'accès direct et l'interface ne pourra être utilisée qu'à partir d'un autre composant. Si l'interface est scriptable, alors les types des attributs doivent être compatibles avec le JavaScript. Le fichier idl contient également l'identifiant de l'interface: uuid(e4c3f63c-9073-4625-8e61-3f308b05cce0). L'interface hérite de nsISupports, l'interface minimale de contrôle.

Compilation de l'idl

On compile ce fichier avec xpidl. On obtient en sortie un header file C++: cmIMP3Player.h et un fichier xpt contenant le descriptif de l'interface. Le header C++ contient:

  • Le squelette de la classe cmMP3Player déclarée dans le fichier cmMP3player.h Cette classe hérite de l'interface et va implémenter des fonctions supplémentaires nécessaires au fonctionnement interne du composant.

  • Le squelette des méthodes de l'interface implémentées dans le fichier cmMP3Player.cpp.

Figure 3-1. De l'idl aux sources du composant.


3.2.2. Implémentation des fonctions

L'implémentation des fonctions du composant fait appel aux fonctions de la librairie dynamique. Les méthodes play et load du composant font simplement appel aux fonctions de la librairie. La gestion du stop et pause se fait grâce à des variables: les appels aux méthodes stop et pause attibueront la valeur 1 respectivemant aux variables flag_stop et flag_pause. Ces variables sont déclarées dans la classe cmMP3Player en privée puisqu'elles restent internes au composant. Il faut alors scruter ces variables pour lancer les fonctions de la librairie. Il faut donc simultanément scruter les flag et decoder le mp3. D'où l'emploi de threads.

Les threads

Les threads sont des processus legers qui permettent de partager le temps CPU entre plusieurs tâches que le programme effectue simultanément. Contrairement aux processus, ils n'ont pas d'espace mémoire individuel, d'où une necessité de proteger les accès à la mémoire. La création d'un processus par un fork() dupliquera les ressources, alors que la création d'un thread se limitera à executer en parallèle deux codes différents. L'avantage est un temps de création et de commutation beaucoup plus court. Il faut cependant veiller à proteger ses variables: deux threads pouvant accéder au même espace mémoire, il y a danger dans le cas d'un accès simultané en écriture sur la même variable. D'où l'emploi de fonctions NSPR permettant la gestion des threads et des variables utilisées dans ceux ci. On utilisera en particulier la fonction PR_AtomicSet(&variable,valeur); qui assure un accès protégé en écriture (deux threads ne peuvent avoir accès en même temps au même espace mémoire.

Figure 3-2. threads de contrôle et de lecture

On créé donc un thread dont le rôle est de jouer le mp3. Les deux threads communiquent par l'intermédiaire des variables de contrôle. Le thread de contrôle se sert des fonctions PR_AtomicSet pour flag_pause et flag_stop, et le thread de lecture scrute ces variables à chaque frame lue. Il réagit en conséquence en stoppant le thread ou en le mettant en attente s'il s'agit d'un pause.

enregistrement du composant

On créé un fichier cmMP3PlayerModule.cpp qui va se charger d'enregistrer le composant. Il contient le contractID et le nom du composant et effectue l'enregistrement automatiquement. Quand le composant est créé, on place le fichier xpt dans un repertoire de Mozilla. Au lancement de celui ci, il enregistre l'emplacement de la librairie dynamique. Lorsqu'on créé une instance du composant (méthode CreateInstance()), c'est la classe déclarée dans cmMP3PlayerModule.cpp qui est créée (appelée Factory) et qui elle même construit le composant. Le fait de passer par la Factory constitue un intermédiaire indispensable: en effet les Factory sont des classes qui ont tous la même taille. On sait donc quel espace mémoire il faut allouer, contrairement à un composant dont la taille peut varier.

librairie dynamique "cmMP3player.so"

On créé un makefile pour automatiser la génération des fichiers objets, et la librairie dynamique. La librairie dynamique se créé de la façon suivante dans le makefile:

	  cmMP3player.so: cmMP3player.o cmMP3playerModule.o
g++ -shared $(LFLAGS) cmMP3player.o cmMP3playerModule.o
-o cmMP3player.so

La première ligne spécifie les fichiers dont on a besoin pour la créer: les fichiers binaires. La deuxième est la ligne qui créé la librairie: on utilise g++, et on précise avec l'option -shared qu'on veut un objet "partageable", c'est à dire dynamique. Nous disposons desormais de deux librairies dynamiques: l'une contenant la décompression MP3, et l'autre contenant le composant XPCOM qui appelle les fonctions de décompression.

xpcshell permet de faire appel aux fonctions du composant. Voici un script réalisant cette opération:

	     // On déclare une classe de type "@enux.net/mp3;1":
var classe_mp3 = Components.classes["@enux.net/mp3;1"];

// On créé un instance de cette classe:
var instance_mp3 = classe_mp3.createInstance();

// déclaration de l'interface:
var interface_mp3 = Components.interfaces.cmIMP3player;

// Appel à QueryInterface pour preciser avec quelle
// interface on souhaite utiliser le composant:
var player_mp3=instance_mp3.QueryInterface(interface_mp3);

// Appels à différentes fonctions du composant:
player_mp3.init();
player_mp3.load(chemin);
player_mp3.Play();

La dernière partie du projet consiste à réaliser une interface graphique utilisateur permettant d'accéder de manière conviviale aux fonctions du composants.


3.3. interface utilisateur

Jusqu'ici Le player ne fonctionnait qu'en mode console par l'intermédiaire de xpcshell qui permettait d'instancier puis de controler le player. La dernière étape consiste à réaliser une interface utilisateur attractive et simple. Nous allons d'abord écrire un fichier JavaScript qui accèdera aux méthodes du composant, puis un fichier XUL qui sera l'environnement de l'utilisateur.

voici un exemple illustrant le fonctionnement de l'interface utilisateur:

Figure 3-3. interface utilisateur


3.3.1. le fichier JavaScript

Le contrôle du composant se fait par l'intermédiaire du XPConnect avec des fonctions JavaScript faisant directement appel aux méthodes du composant XPCOM. Le Javascript doit instancier le composant XPCOM. Au lancement du fichier, on éxécute automatiquement cette instanciation grâce à la fonction Onload(). On précise que sur cette action, le JavaScript éxécutera le script suivant:

	  
function Startup()
{
// Droits Netscape pour utiliser le XPConnect:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

// On déclare une classe de type "@enux.net/mp3;1";
// puis création d'une instancede type classe_mp3, et déclaration de l'interface:

var classe_mp3 = Components.classes["@enux.net/mp3;1"];
var instance_mp3 = classe_mp3.createInstance();
var interface_mp3 = Components.interfaces.cmIMP3player;

// Spécification de l'interface

var player_mp3=instance_mp3.QueryInterface(interface_mp3);

//On initialise le composant et des variables internes au fichier JavaScript:
player_mp3.init();
lecture=0;
pause=0;
}

Puis l'implémentation des fonctions de lecture, pause et arret se résume à des appels aux méthodes du composant. Ces fonctions ont simplement pour rôle de faire la transition entre l'utilisateur et le composant.

On créé également une fonction file_picker() permettant de parcourir l'arborescence pour choisir un fichier. Pour cela on utilise l'interface XPCOM nsIFilePicker qu'on instancie puis qu'on lance par les appels aux méthodes:

	  fp.init(fp.parent , "Select a File",fp.modeOpen);
fp.appendFilter("mp3 Files","*.mp3");

Ce nouveau composant de la classe classes["@mozilla.org/filepicker;1"] permet l'apparition d'une boite de dialogue laissant le choix du fichier. La méthode appendFilter restreint la recherche à certains types de fichiers. Ici les fichiers *.mp3. Cet exemple montre l'emploi puissant et rapide des composants.

Nous avons désormais un accès plus simple aux méthodes du composant XPCOM, nous allons maintenant réaliser l'interface graphique en XUL, le JavaScript faisant le lien entre celui ci et le composant.


3.3.2. le fichier xul

Le XUL permet de réaliser une interface avec des boutons, fenetres, images,... Sur des actions de l'utilisateur (events), le fichier XUL peut lancer les fonctions du fichier JavaScript. Celui ci controle ensuite le composant XPCOM grâce à la technologie XPConnect. Le fichier Javascript fait le lien entre le composant et l'interface.

Le XUL se présente sous la forme de balises semblables au HTML. chaque élément comporte plusieurs attributs réglables. Par exemple l'élément "button" possède des attributs tels que le "label": étiquette à placer sur le bouton, ou "id" qui permet de l'identifier. Le XUL permet de placer des box verticales ou horizontales dans lesquelles on place les boutons. On créé un bouton pour chaque fonction de pilotage du player. voici un exemple de création de bouton:

	  
<button id="play"
flex="1"
onclick="play();"
onMouseOver="play();"/>

On a ici défini un bouton dont l'ID est play et dont l'attribut flex est à 1: cela signifie que le bouton cherchera à occuper le plus d'espace possible dans la fenêtre. Puis sur les events onclick (click de souris) ou onMouseOver (curseur sur le bouton), la fonction play() du fichier JavaScript attaché sera éxécuté.

interactions XUL JavaScript

Les fichiers XUL peuvent acceder aux fichiers JavaScript par l'intermédiaire d'une ligne placé au début du fichier XUL:

<script language="javascript" src="player.js"></script>

cette ligne permet ensuite de lancer des fonctions JavaScript, en particulier sur des events.

Le xul peut donc lancer des fonctions JavaScript. Inversement, le JavaScript permet d'acceder au xul par l'intermédiaire des méthodes du DOM qui accèdent aux objets du XUL. On utilise en particulier les méthodes getElementById et setAttribute qui permettent de modifier les attributs des objets. Si on reprend l'exemple du bouton play, on peut réduire son attribut flex par la ligne suivante dans le fichier JavaScript:

	  document.getElementById("play").setAttribute("flex","0");

Nous avons donc réalisé une interface graphique utilisateur évoluée de manière simple et rapide grâce au XUL.

Figure 3-4. interface graphique xul


3.3.3. intégration du player à mozilla

Dans un premier temps, le player est simplement associé à mozilla à son lancement en tant que chrome. Un chrome est une application qui est éxécutée par Mozilla. Il suffit pour cela de lancer la commande:

	  mozilla -chrome file:/home/people/cchatelain/comedia/src/MP3player/player.xul 

Nous avons maintenant une interface qui contrôle le composant qui est lancée par Mozilla. Le player mp3 fonctionne et possède les fonctionnalités suivantes: Lecture, arrêt, pause, ouvrir un fichier, et donner des informations sur le fichier. Certaines fonctions n'ont pas été implémentées par manque de temps: avance rapide, jouage d'une playlist, etc... Elles seront néammoins faciles à ajouter puisqu'il s'agit simplement de jouer sur l'avancement des frames. La fonction avance rapide peut par exemple être mise au point en jouant 1 frames toutes les n frames.


Conclusion

Les objectifs du stage ont été atteint: on a un composant player mp3 XPCOM tournant sous Mozilla. Faute de temps, je n'ai pu rendre le player totalement portable. En effet la librairie de décompression devrait également être écrite en XPCOM. En effet elle est pour l'instant implémentée en C, et n'utilise pas les types NSPR, ce qui ne permet pas des accès mémoire protégés ni une portabilité satisfaisante. Toutes les fonctions de la librairie devraient donc être remplacées par leur équivalentes NSPR.

Mon stage a été très formateur sur le plan technique car j'ai éffectué de nombreuses recherches et études, j'ai découvert l'informatique logicielle qui m'était jusqu'alors peu familière. J'ai ainsi acquis une bonne maitrise de GNU linux, en particulier de la distribution Debian. J'ai également fait l'apprentissage de nombreux langages désormais largement répandus tels que le JavaScript. L'étude de la compression mp3 fut également intéressante car elle est une combinaison d'applications de notions théoriques comme la transformée de fourier et d'un procédé plus empirique qu'est le modèle psychoacoustique.

Au dela de l'apprentissage technique, j'ai appris à mener un objectif sur une longue période, en particulier à mener toutes les études nécessaires à un projet avant de passer à la réalisation. Le temps passé à faire l' analyse se récupère sur la réalisation qui en est facilitée. Enfin j'ai beaucoup travaillé en équipe, dans un climat de partage de connaissances très constructif.


Bibliographie

[DocBook] DocBook: The Definitive Guide .

[eProcess] eProcess: site de la société .

[NSPR] NSPR: Netscape Portable Runtime .

[DOM] Document Object Model: Site du DOM .

[MPEG] Moving Picture Expert Group: Site du MPEG .

[MP3] O'reilly: mp3: the definitive guide .

[MP3] Le Fraunhofer Institute: Site du Fraunhofer Institute .

[Open] Open source: Presentation du logiciel libre .

Un site expliquant les principes du logiciel libre.

[Mozilla] Mozilla: Le site de Mozilla .

[XUL] Le XUL: Tutorial Xulplanet .

[JS] Le JavaScript: spécification du langage ECMA .

Le JavaScript n'est que le nom donné par Netscape à ECMA.

[CSS] Le Cascading Style Sheets: Validation par W3C du langage CSS .


Annexe A. les abbréviations


Annexe B. listing