Serge Arbiol - programmation

LazMPlayer

Cet article montre comment utiliser le composant multimédia TMplayerControl avec Lazarus / Free Pascal. Je vous propose de créer pas à pas une application appelée LazMPlayer. Je l'ai écrite sous la configuration suivante : Kubuntu 16.04 et Lazarus 1.6.4.

Attention : LazMPlayer a été codé uniquement pour Linux. Il ne peut pas fonctionner tel quel sur un autre système.

1. Télécharger et installer le composant TMplayerControl

Qu'est-ce que TMplayerControl ?

TMplayerControl est un composant visuel basé sur l'application MPlayer pour GNU/Linux qui permet de lire la plupart des formats audios et vidéos. Il faut donc avoir installé au préalable MPlayer pour pouvoir utiliser TMPlayerControl.

Téléchargement

Vous trouverez ici toutes les indications nécessaires pour télécharger et installer TMplayerControl via SVN.
SVN (Subversion) est un outil de gestion de versions. Si vous ne l'avez pas installé, vous trouverez ici tous les renseignements nécessaires pour le faire. Vous pourrez ensuite coller dans un terminal (clic droit-> Coller) l'instruction suivante (après l'avoir copiée, bien sûr) :

svn co https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr/components/mplayer mplayer

Astuce pour les amateurs de Dolphin : Placez-vous dans le répertoire où vous voulez télécharger le composant TMplayerControl (par exemple /home/nom_utilisateur/Pascal/Composants) puis collez dans le terminal de Dolphin (Affichage/Panneaux/Terminal) l'instruction encadrée ci-dessus (svn co https://lazarus...etc.). Le dossier mplayer est alors téléchargé dans le répertoire où vous vous trouvez. Il contient le paquet à installer pour Lazarus, les sources et 2 exemples (FullFeatured et Simple) comme on peut le voir sur l'arborescence suivante :

MPlayer01.png
Fig. 1 : Contenu du dossier MPlayer

Je me suis rendu compte en consultant les exemples fournis que le premier était trop complexe et le second pas assez détaillé. Je n'ai par exemple pas trouvé comment placer le lecteur sur une position donnée. Après moult recherches, il m'a semblé évident de partager le fruit de mes efforts avec tous ceux qui souhaitent programmer un lecteur multimédia sous Linux sans trop perdre de temps.

Je vous propose donc de créer pas à pas une petite application permettant de lire un fichier audio ou vidéo comme indiqué dans les exemples fournis avec le composant, mais en ajoutant quelques fonctions et explications qui vous feront gagner du temps dans vos recherches.

Installation sous Lazarus

1) Paquet/Ouvrir un fichier de paquets (lpk)
Ouvrir le fichier /mplayer/mplayercontrollaz.lpk
2) Compiler puis Utiliser/installer
Si tout s'est bien passé, le composant figure dans l'onglet Multimedia de la palette de Lazarus.

2. Création de l'application LazMPlayer

1) On crée un dossier nommé LazMPlayer

Pour moi, c'est un sous-dossier du répertoire Pascal: /home/serge/Pascal/LazMPlayer

2) On crée une nouvelle application avec Lazarus

Projet/Nouveau projet/Application

3) On l'enregistre dans le dossier LazMPlayer

Fichier/Enregistrer
Nommez le projet LazMPlayer.lpi et laissez unit1.pas pour la fiche.

Redimensionnez la fiche en 300/600 (Height/Width).

3. Les composants visuels de l'application

Je vous propose de glisser sur la fiche 3 panels, 5 boutons, une TrackBar entourée de 2 labels et un dialogue d'ouverture de fichier.

1) Ajout de 3 panels

On crée 3 panels : Un pour les boutons, un autre pour contenir une TrackBar (ainsi que 2 labels indiquant la position et la durée) et enfin un dernier pour le composant TMplayerControl.

Placer sur la fiche 3 Panels et affecter ainsi leur propriété align avec l'inspecteur d'objets:
Panel1.align := alTop
Panel2.align := alBottom
Panel3.align := alClient

MPlayer02.png
Fig. 2 : Les 3 Panels sont en place

2) Ajout de 5 boutons

5 boutons permettront d'ouvrir un document multimédia, de reculer d'1 seconde, d'avancer d'1 seconde, de mettre le lecteur en pause et de placer le lecteur sur une position précise.
1) Glisser 5 boutons sur Panel1
2) Renseigner ainsi leur propriété Caption :
Bouton1: "Ouvrir",
Bouton2: "<--",
Bouton3: "-->",
Bouton4: "Play/Pause",
Bouton5: "00:01:00,000"
3) Modifier leur propriété Name :
Bouton1: "BtOuvrir",
Bouton2: "BtReculer",
Bouton3: "BtAvancer",
Bouton4: "BtPlay",
Bouton5: "BtPosition"

MPlayer03.png
Fig. 3 : Les 5 boutons sont en place

3) Ajout du composant TMplayerControl

Avec ma version de Lazarus, le composant se trouve dans l'onglet "Multimedia". On le glisse dans Panel3 et on met sa propriété align sur alClient.

MPlayer04.png
Fig. 4 : Le composant TMPlayerControl est en place

4) Ajout de 2 labels et d'une TrackBar

1) Glisser 2 labels dans Panel2 et affecter leur propriété align :
Label1.align:=alLeft
Label2.align:=alRight
2) Modifiez leur propriété Name ainsi :
Label1:LbPos,
Label2:LbDuree,
3) Sur la place restée vacante entre les deux labels, glissez une TrackBar (ce composant se trouve dans Common Controls), redimensionnez-la à votre convenance et placez-la au centre de Panel2. Nommez-la TrackBarVideo.

MPlayer05.png
Fig. 5 : La TrackBar et les deux Labels sont en place

5) Ajout d'un dialogue d'ouverture de fichier

Glisser un composant OpenDialog. On mettra sa propriété Filter sur les formats voulus (vidéos et/ou audios) dans l'événement onCreate de la fiche. Il ne manque plus qu'à mettre un chaîne vide aux propriétés Caption des 3 Panels, ce sera nettement plus esthétique.

Vous devriez obtenir à peu près ceci :

MPlayer06.png
Fig. 6 : Les composants visuels sont en place

4. Les procédures et fonctions

1) la procédure FormCreate

On crée le gestionnaire onCreate de la fiche avec l'inspecteur d'objet. Nous allons y mettre quelques instructions pour initialiser notre composant.

Mais d'abord, on met un titre sympa :

Caption:='LazMPlayer - Serge Arbiol - Juillet 2017';

Réglage du volume

Je vous propose une valeur que vous pouvez bien sûr modifier à votre guise. Il serait plus pratique de placer une TrackBar pour régler le volume. Ce sera l'objet d'un développement ultérieur.

MPlayerControl1.Volume := 80;

Paramètres de lancement du composant

Il s'agit des paramètres du programme de base MPlayer que gère notre composant TMplayerControl. Voir la documentation.

MPlayerControl1.StartParam := '-vo x11 -zoom -fs';

L'instruction ci-dessus indique à MPlayer qu'il doit utiliser la sortie vidéo x11 et permettre le zoom logiciel et l'affichage plein écran si le pilote le supporte.

Propriété Filter du dialogue d'ouverture de fichier

Pour pouvoir lire des vidéos mais aussi des documents audios, nous allons procéder ainsi :
Définissons 2 variables de type chaîne de caractères : FormatsVideo et FormatsAudio auxquelles nous affecterons les formats les plus répandus.

procedure TForm1.FormCreate(Sender: TObject);
var
FormatsVideo,
FormatsAudio : String;

FormatsVideo:='*.AVI;*.avi;*.WMV;*.wmv;*.MOV;*.mov;*.MKV;*.mkv;*.MP4;*.mp4;*.MPG;*.mpg;*.MPEG;*.mpeg;
*.VOB;*.vob;*.FLV;*.flv;*.WEBM;*.webm'; FormatsAudio:='*.MP3;*.mp3;*.AAC;*.aac;*.WAV;*.wav;*.WMA;*.wma;*.CDA;*.cda;*.FLAC;*.flac;*.M4A;*.m4a;
*.MID;*.mid;*.MKA;*.mka;*.OGG;*.ogg;*.APE;*.ape';

Affectons ensuite ces variables à la propriété Filter du dialogue d'ouverture de fichiers.

OpenDialog1.Filter:='Vidéo|'+FormatsVideo+'|Audio|'+FormatsAudio;

Nous en avons terminé avec onCreate. Récapitulons :

procedure TForm1.FormCreate(Sender: TObject);
var
FormatsVideo,
FormatsAudio : String;
begin
// On règle le volume de départ
MPlayerControl1.Volume := 150;
// Paramètres de lancement de MPlayerControl1
MPlayerControl1.StartParam := '-vo x11 -zoom -fs';
// Propriété Filter du dialogue d'ouverture de fichiers FormatsVideo:='*.AVI;*.avi;*.WMV;*.wmv;*.MOV;*.mov;*.MKV;*.mkv;*.MP4;*.mp4;*.MPG;*.mpg;*.MPEG;
*.mpeg;*.VOB;*.vob;*.FLV;*.flv;*.WEBM;*.webm';
FormatsAudio:='*.MP3;*.mp3;*.AAC;*.aac;*.WAV;*.wav;*.WMA;*.wma;*.CDA;*.cda;*.FLAC;*.flac;*.M4A;*.m4a;
*.MID;*.mid;*.MKA;*.mka;*.OGG;*.ogg;*.APE;*.ape';
OpenDialog1.Filter:='Vidéo|'+FormatsVideo+'|Audio|'+FormatsAudio;
end;

Fig. 6 : La procédure onCreate complète

2) La procédure BtOuvrirClick

On peut maintenant ouvrir un document en exécutant le dialogue d'ouverture de fichier. Les instructions suivantes sont limpides et se passent de commentaire.

procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
MPlayerControl1.Stop;
MPlayerControl1.Filename:=OpenDialog1.FileName;
MPlayerControl1.Play;
end;
end;

Fig. 7 : La procédure BtOuvrirClick complète

3) La procédure MPlayerControl1Play

Ça y est, notre fichier est lancé. Il serait souhaitable à présent d'en récupérer le nom, la durée et d'initialiser la TrackBar pour qu'elle nous indique la position courante. Pour ce faire, nous avons la procédure MPlayerControl1Play.
L'événement MPlayerControl1Play se déclenche, comme son nom l'indique, lorsqu'on exécute l'instruction MPlayerControl1.Play; Voici quelques lignes de code fort utiles:

Modifions le titre de notre application :

Caption := MPlayerControl1.Filename;

Réglons la propriété Max de notre TrackBar sur la durée du média :

TrackBarVideo.Max := Trunc(MPlayerControl1.Duration);

Affichons la durée du média dans Label2 :

LbDuree.Caption:=FormatDateTime('hh:nn:ss,zzz', MPlayerControl1.Duration / (24 * 60 * 60));

Nous avons bien progressé, mais impossible pour le moment de mettre le lecteur sur pause et d'en connaître la position. Nous avons besoin pour cela de la procédure MPlayerControl1Playing qui fonctionne comme un Timer.

procedure TForm1.MPlayerControl1Play(Sender: TObject);
begin
Caption := MPlayerControl1.Filename;
TrackBarVideo.Max := Trunc(MPlayerControl1.Duration);
LbDuree.Caption:=FormatDateTime('hh:nn:ss,zzz', MPlayerControl1.Duration / (24 * 60 * 60));
end;

Fig. 8 : La procédure MPlayerControl1Play complète

4) La procédure MPlayerControl1Playing

Dans cette procédure nous allons d'abord actualiser TrackBarVideo pour qu'elle indique la position courante du lecteur. Mais avant tout, il faut neutraliser l'événement TrackBarVideo.onChange pour éviter un comportement indésirable du curseur et n'exécuter le code que si un média est chargé :

Si la durée du média est supérieure à 0 (donc un fichier est ouvert dans le lecteur), on peut continuer :

If (MPlayerControl1.Duration>0) Then

On neutralise TrackBar1.onChange :

TrackBarVideo.OnChange:=Nil;

On peut ensuite actualiser la position courante grâce à la variable APosition figurant dans les paramètres de la procédure MPlayerControl1Playing:

TrackBarVideo.Position:=Trunc(APosition);

Profitons-en pour actualiser LbPos qui indique la position courante :

LbPos.Caption := FormatDateTime('hh:nn:ss,zzz', APosition / (24 * 60 * 60));

N'oublions surtout pas de relancer l'événement TrackBarVideo.onChange car nous en aurons besoin pour modifier la position du lecteur.

TrackBarVideo.OnChange := @TrackBarVideoChange;

Récapitulons :

procedure TForm1.MPlayerControl1Playing(ASender: TObject; APosition: single);
begin
If (MPlayerControl1.Duration>0) Then
begin
// pour éviter la récursivité
TrackBarVideo.OnChange:=Nil;
TrackBarVideo.Position:=Trunc(APosition);
LbPos.Caption := FormatDateTime('hh:nn:ss,zzz', APosition / (24 * 60 * 60));
// rétablit la procédure
TrackBarVideo.OnChange := @TrackBarVideoChange;
end;
end;

Fig. 9 : La procédure MPlayerControl1Playing complète

Si vous exécutez le programme à ce stade, vous obtiendrez une erreur car on n'a pas encore renseigné l'événement onChange de TrackBarVideo. Faisons-le de ce pas !

5) La procédure TrackBarVideoChange

Le code est très simple :

procedure TForm1.TrackBarVideoChange(Sender: TObject);
begin
// On affecte au lecteur la position correspondant à  celle de TrackBarVideo
If (MPlayerControl1.Running) then MPlayerControl1.Position := TrackBarVideo.Position;
end;

Fig. 10 : La procédure TrackBarVideoChange

6) Les procédures BtReculerClick et BtAvancerClick

Ces boutons permettent d'avancer ou reculer d'1 seconde. Modifiez-les à votre convenance :

procedure TForm1.BtReculerClick(Sender: TObject);
begin
// Recule d'1 seconde
If (MPlayerControl1.Running) then MPlayerControl1.Position:=MPlayerControl1.Position-1;
end;

procedure TForm1.BtAvancerClick(Sender: TObject);
begin
// Avance d'1 seconde
If (MPlayerControl1.Running) then MPlayerControl1.Position:=MPlayerControl1.Position+1;
end;

Fig. 11 : Les procédures BtReculerClick et BtAvancerClick

7) La procédure BtPlayClick

Cette procédure permet de mettre en pause ou de relancer le média.

procedure TForm1.BtPlayClick(Sender: TObject);
begin
If (MPlayerControl1.Running) then MPlayerControl1.Paused := Not MPlayerControl1.Paused;
end;

Fig. 12 : La procédure BtPlayClick

8) La procédure BtPositionClick

Voila une procédure intéressante qui va nous permettre de placer le lecteur sur une position au format "hh:nn:ss,zzz". Nous savons déjà le faire en secondes, mais là c'est plus amusant car ça pose des problèmes de conversion et de compatibilité.

Dans l'événement onClick du bouton BtPosition, nous récupérons la valeur Caption de ce bouton et la convertissons en secondes avant de l'affecter à la position du lecteur.

Une fonction très pratique de l'unité DateUtils renvoie le résultat d'une date en secondes. Il s'agit de SecondOfTheDay. Mais, car il y a un mais, si votre séparateur décimal est une virgule, ça ne marche pas. J'ai eu la mauvaise idée d'utiliser DecimalSeparator := ',' mais alors c'était la procédure MPlayerControl1Playing qui ne fonctionnait plus. Donc, plutôt que d'imposer la norme française et risquer ainsi des erreurs dans les fonctions internes de ce cher Free Pascal, j'ai jugé plus sage de convertir tout simplement la virgule en point avec StringReplace pour garder une compatibilité toute anglo-saxonne avec le système.

Déclaration de l'unité DateUtils :

MPlayer07.png
Fig. 13 : Ajout de l'unité DateUtils

Et voici le résultat :

procedure TForm1.BtPositionClick(Sender: TObject);
Var
Chaine : String;
begin
// Place le lecteur sur la position indiquée dans le Caption du bouton
if (MPlayerControl1.Duration>0) Then
begin
MPlayerControl1.Paused := True;
Chaine:=BtPosition.Caption;
// convertit chaine au format hh:mn:ss.mls en TDateTime
// si le séparateur décimal est une virgule, la remplacer
// ne surtout pas utiliser DecimalSeparator := ','
Chaine:=StringReplace(Chaine,',','.',[rfReplaceAll]);
// SecondOfTheDay de l'unité DateUtils renvoie le résultat d'une date en secondes
// permet de convertir en secondes une chaine comme '00:01:20.123'
// -> ajouter DateUtils dans uses
MPlayerControl1.Position:=SecondOfTheDay(StrToTime(Chaine));
end;
end;

Fig. 14 : La procédure BtPositionClick

9) La procédure MPlayerControl1Stop

Peaufinons un tout petit peu. Lorsque le média est stoppé, laissons donc le Caption de la fiche comme on l'avait trouvé en entrant :

procedure TForm1.MPlayerControl1Stop(Sender: TObject);
begin
If csDestroying In ComponentState Then exit;
Caption := 'LazMPlayer - Serge Arbiol - Juillet 2017';
end;

5. Conclusion

Nous avons vu comment télécharger, installer et utiliser le composant TMplayerControl en créant l'application LazMPlayer avec Lazarus. Ceci peut être considéré comme une base sur laquelle on peut développer un sous-titreur de vidéos, un lecteur audio, voire un séquenceur vidéo comme celui que j'avais programmé en Delphi il y a une dizaine d'années et dont je me servais chaque jour dans le cadre des cours de russe et de français dont j'avais la charge à l'université Paul Sabatier de Toulouse. J'écrirai prochainement un article sur le sujet.

J'espère avoir été utile. Bonne programmation !

6. Téléchargement

Le fichier source au format PDF est téléchargeable ici

Le programme complet au format ZIP est téléchargeable ici