Construction d'un lecteur multimédia de base
Remonter à Tutoriel : Audio-vidéo dans FireMonkey
Ce tutoriel illustre comment construire un lecteur multimédia de base en utilisant TMediaPlayer et TMediaPlayerControl avec FireMonkey. Le lecteur multimédia contient des fonctions standard (lecture, pause, suivant et précédent) et offre la possibilité de manipuler le média en cours de lecture (volume et position en cours). Ce lecteur multimédia de base permet de charger un ensemble de fichiers multimédia dans un TListBox et d'en démarrer la lecture en double-cliquant sur un élément de la liste.
Sommaire
Conception de la fiche
- Sélectionnez Fichier > Nouveau > Application multi-périphérique - Delphi > Application vide.
- Ajoutez un TLayout à la fiche. La disposition ayant la focalisation, dans l'inspecteur d'objets, définissez la propriété Align sur
Left
et la propriété Name sur MainLayout. Redimensionnez MainLayout de façon à afficher des images vidéo. - Ajoutez les éléments suivants à MainLayout :
-
- Un TLayout. Nommez-le ControlPlayLayout et alignez-le sur le bas du MainLayout. Cette disposition contient tous les composants qui contrôlent le fichier multimédia.
- Un TLayout. Nommez-le TextLayout et alignez-le sur le haut du MainLayout. Cette disposition contient les libellés utilisés pour afficher le nom et la durée du média en cours de lecture.
- Un TMediaPlayerControl. Définissez sa propriété Align sur
Client
.
-
- Ajoutez les éléments suivants à ControlPlayLayout :
-
- Cinq objets TButton, un pour chaque fonction standard d'un lecteur multimédia. Remplacez le nom des boutons par PreviousButton, PlayButton, PauseButton, StopButton et NextButton.
- Deux objets TTrackBar : un pour contrôler le volume, l'autre pour contrôler la position en cours de lecture. Remplacez le nom des barres graduées par VolumeTrackBar et PositionTrackBar. Alignez PositionTrackBar sur le haut de ControlPlayLayout.
- Un TCheckBox et nommez-le ShuffleCheckBox.
-
- Ajoutez deux objets TLabel à TextLayout : un pour afficher le nom du média en cours de lecture et l'autre pour afficher la durée totale des fichiers en cours de lecture en minutes et en secondes. Nommez les deux libellés NameLabel et DurationLabel. Définissez DurationLabel de façon à ce qu'il soit aligné sur la droite et définissez sa propriété AutoSize sur True. Définissez la propriété de Align de NameLabel sur
Client
et spécifiez que le texte sera affiché au centre en définissant sa propriété TextAlign surCenter
. - Ajoutez un autre TLayout à la fiche, définissez sa propriété Align sur
Client
et renommez-le PlayListLayout. - Ajoutez les éléments suivants à PlayListLayout :
- Ajoutez trois objets TButton à PlayListLayout. Nommez-les LoadFileButton, ClearAllButton et ClearButton. Alignez les trois boutons sur la gauche de leur parent.
- Ajoutez les éléments suivants à la fiche :
-
- Un TMediaPlayer
- Un TOpenDialog
- Un TTimer
- Un TActionList
- La fiche doit ressembler à ceci :
-
Implémentation
L'implémentation peut être divisée en plusieurs étapes :
- Associer des actions standard à des contrôles standard
- Construire et manipuler la sélection
- Implémenter les fonctions de base d'un lecteur multimédia
- Implémenter les méthodes et classes utiles
- Personnaliser le fichier multimédia en cours de lecture
Associer des actions standard à des contrôles standard
Double-cliquez sur votre TActionList puis, sur l'éditeur de liste d'actions qui s'ouvre :
- Sélectionnez Nouveau > Nouvelle action standard.
- Sous Bibliothèque multimédia, sélectionnez les actions suivantes :
- TMediaPlayerStop
- TMediaPlayerCurrentTime
- TMediaPlayerVolume
- Cliquez sur OK pour ajouter ces actions à votre composant liste d'actions.
A présent, configurez ces actions sur la propriété Action des contrôles suivants :
- StopButton
- PositionTrackBar
- VolumeTrackBar
Construire et manipuler la sélection
- 1 Double-cliquez sur le bouton LoadFileButton pour lui attacher les gestionnaires d'événement OnClick et remplir la PlayListBox. L'appui sur LoadFileButton provoque l'ouverture de la boîte de dialogue Ouvrir. Sélectionnez un ou plusieurs fichiers devant être ajoutés à la liste lorsque l'utilisateur appuie sur le bouton OK de la boîte de dialogue Ouvrir.
procedure TForm1.LoadFileButtonClick(Sender: TObject);
var
Files: TStrings;
I: integer;
MediaEntry: TMediaEntry;
begin
// Sets the Filter so only the supported files to be displayed
OpenDialog1.Filter := TMediaCodecManager.GetFilterString;
if (OpenDialog1.Execute) then
begin
Files := OpenDialog1.Files;
for I := 0 to Files.Count - 1 do
begin
MediaEntry := TMediaEntry.Create(Files[I]);
PlayListBox.Items.AddObject(extractFileName(Files[I]), MediaEntry);
end;
end;
end;
void __fastcall TForm1::LoadFileButtonClick(TObject *Sender) {
int i;
TMedia *Media;
TStrings *Files = new TStringList();
// Sets the Filter so only the supported files to be displayed
OpenDialog1->Filter = TMediaCodecManager::GetFilterString();
if (OpenDialog1->Execute()) {
Files = OpenDialog1->Files;
for (i = 0; i < Files->Count; i++) {
Media = TMediaCodecManager::CreateFromFile(Files->operator[](i));
PlayListBox->Items->AddObject
(ExtractFileName((UnicodeString)Files->operator[](i)), Media);
}
}
}
- 2. Double-cliquez sur les boutons ClearAllButton et ClearButton pour leur attacher les gestionnaires d'événement OnClick.
ClearAllButton | ClearButton |
---|---|
Delphi :
procedure TForm1.ClearAllButtonClick(Sender: TObject);
var
I: integer;
begin
if (PlayListBox.Count > 0) then
begin
for I := 0 to PlayListBox.Count - 1 do
PlayListBox.Items.Objects[I].Free;
PlayListBox.Clear;
PlayListBox.ItemIndex := -1;
SetLength(Played, 0);
CurrentPlayedIndex := -1;
MediaPlayer1.Clear;
NameLabel.Text := '';
DurationLabel.Text := '';
end;
end;
C++Builder :
void __fastcall TForm1::ClearAllButtonClick(TObject *Sender) {
int i;
if (PlayListBox->Count > 0) {
for (i = 0; i < PlayListBox->Count; i++) {
PlayListBox->Items->Objects[i]->Free();
}
PlayListBox->Clear();
PlayListBox->ItemIndex = -1;
Played.resize(0);
CurrentPlayedIndex = -1;
MediaPlayer1->Clear();
NameLabel->Text = "";
DurationLabel->Text = "";
}
}
|
Delphi :
procedure TForm1.ClearButtonClick(Sender: TObject);
var
I, J: integer;
begin
if PlayListBox.Count < 0 then
Exit;
PlayListBox.Items.Objects[PlayListBox.ItemIndex].Free;
PlayListBox.Items.Delete(PlayListBox.ItemIndex);
J := 0;
// Makes sure that the deleted media is not on the Playlist
while J < Length(Played) - 1 do
begin
if (Played[J] = PlayListBox.ItemIndex) then
begin
for I := J to Length(Played) - 1 do
Played[I] := Played[I + 1];
SetLength(Played, Length(Played) - 1);
end;
J := J + 1;
end;
end;
C++Builder :
void __fastcall TForm1::ClearButtonClick(TObject *Sender) {
unsigned int i, j;
if (PlayListBox->Count < 0) {
return;
}
PlayListBox->Items->Objects[PlayListBox->ItemIndex]->Free();
PlayListBox->Items->Delete(PlayListBox->ItemIndex);
j = 0;
// Makes sure that the deleted media is not on the Playlist
while (j < Played.size() - 1) {
if (Played[j] == PlayListBox->ItemIndex) {
for (i = j; i < Played.size(); i++) {
Played[i] = Played[i + 1];
}
Played.resize(Played.size() - 1);
}
j += 1;
}
}
|
- 3. Pour éviter de garder en mémoire des objets qui ne sont plus utilisés, assurez-vous que chaque objet ajouté à PlayListBox est libéré de la mémoire. Lorsque vous retirez un élément de PlayListBox, seul le lien existant entre l'élément de la zone de liste et l'objet attaché est libéré ; l'objet reste alloué en mémoire.
procedure TForm1.FormDestroy(Sender: TObject);
var
I: integer;
begin
if (PlayListBox.Count > 0) then
for I := 0 to PlayListBox.Count - 1 do
PlayListBox.Items.Objects[I].Free;
end;
void __fastcall TForm1::FormDestroy(TObject *Sender) {
int i;
if (PlayListBox->Count > 0) {
for (i = 0; i < PlayListBox->Count; i++) {
PlayListBox->Items->Objects[i]->Free();
}
}
}
Implémenter les fonctions de base d'un lecteur multimédia
Pour démarrer le lecteur, appuyez sur PlayButton, NextButton ou double-cliquez sur un élément de la sélection (playlist). Attachez un gestionnaire d'événement OnDblClick au PlayListBox. Double-cliquez sur chacun des boutons du ControlPlayLayout pour leur attacher les gestionnaires d'événement OnClick et implémenter les fonctions de base d'un lecteur multimédia.
PlayButton |
PlayListBoxDblClick |
Delphi :
procedure TForm1.PlayButtonClick(Sender: TObject);
begin
if MediaPlayer1.Media <> nil then
begin
if (MediaPlayer1.State = TMediaState.Stopped) and
(MediaPlayer1.CurrentTime < MediaPlayer1.Duration) then
begin
MediaPlayer1.Play;
DisplayText(extractFileName(MediaPlayer1.FileName));
end
else
begin
MediaPlayer1.CurrentTime := 0;
end;
end
else
begin
if (PlayListBox.Count = 0) then
Exit;
if (PlayListBox.ItemIndex = -1) then
PlayListBox.ItemIndex := 0;
FindAndPlay(PlayListBox.ItemIndex);
if (ShuffleCheckBox.IsChecked) then
AddToPlayedList(PlayListBox.ItemIndex);
end;
end;
C++Builder :
void __fastcall TForm1::PlaybuttonClick(TObject *Sender) {
if (MediaPlayer1->Media != NULL) {
if ((MediaPlayer1->State == TMediaState::Stopped) &&
(MediaPlayer1->CurrentTime < MediaPlayer1->Duration)) {
MediaPlayer1->Play();
DisplayText(ExtractFileName(MediaPlayer1->FileName));
}
else
MediaPlayer1->CurrentTime = 0;
}
else {
if (PlayListBox->Count == 0) {
return;
}
if (PlayListBox->ItemIndex == -1) {
PlayListBox->ItemIndex = 0;
}
FindAndPlay(PlayListBox->ItemIndex);
if (ShuffleCheckBox->IsChecked) {
AddToPlayedList(PlayListBox->ItemIndex);
}
}
}
|
Delphi :
procedure TForm1.PlayListBoxDblClick(Sender: TObject);
begin
if (PlayListBox.Count < 0) then
Exit;
MediaPlayer1.Clear;
MediaPlayer1.FileName:= TMediaEntry(
PlayListBox.Items.Objects[PlayListBox.ItemIndex]).Path;
if MediaPlayer1.Media <> nil then
begin
MediaPlayer1.Play;
DisplayText(extractFileName(MediaPlayer1.FileName));
AddToPlayedList(PlayListBox.Items.IndexOf
(extractFileName(MediaPlayer1.FileName)));
end;
end;
C++Builder :
void __fastcall TForm1::PlayListBoxDblClick(TObject *Sender) {
if (PlayListBox->Count < 0) {
return;
}
MediaPlayer1->Clear();
MediaPlayer1->FileName = dynamic_cast<TMedia *>
(PlayListBox->Items->Objects[PlayListBox->ItemIndex])->FileName;
if (MediaPlayer1->Media != NULL) {
MediaPlayer1->Play();
DisplayText(ExtractFileName(MediaPlayer1->FileName));
AddToPlayedList(PlayListBox->Items->IndexOf
(ExtractFileName(MediaPlayer1->FileName)));
}
}
|
PauseButton |
NextButton |
Delphi :
procedure TForm1.PauseButtonClick(Sender: TObject);
begin
if MediaPlayer1.Media <> nil then
MediaPlayer1.Stop;
end;
C++Builder :
void __fastcall TForm1::PauseButtonClick(TObject *Sender) {
if (MediaPlayer1->Media != NULL) {
MediaPlayer1->Stop();
}
}
|
Delphi :
procedure TForm1.NextButtonClick(Sender: TObject);
begin
if (PlayListBox.Count > 0) then
begin
PlayNext;
end;
end;
C++Builder :
void __fastcall TForm1::NextButtonClick(TObject *Sender) {
if (PlayListBox->Count > 0) {
PlayNext();
}
}
|
PreviousButton |
|
Delphi :
procedure TForm1.PreviousButtonClick(Sender: TObject);
begin
if ShuffleCheckBox.IsChecked then
begin
if (Length(Played) > 0) and (CurrentPlayedIndex > 0) then
begin
CurrentPlayedIndex := CurrentPlayedIndex - 1;
FindAndPlay(Played[CurrentPlayedIndex]);
PlayListBox.ItemIndex := Played[CurrentPlayedIndex];
end;
end
else if (PlayListBox.ItemIndex > 0) then
begin
FindAndPlay(PlayListBox.ItemIndex - 1);
PlayListBox.ItemIndex := PlayListBox.ItemIndex - 1;
end;
end;
C++Builder :
void __fastcall TForm1::PreviousButtonClick(TObject *Sender) {
if (ShuffleCheckBox->IsChecked) {
if ((Played.size() > 0) && (CurrentPlayedIndex > 0)) {
CurrentPlayedIndex = CurrentPlayedIndex - 1;
FindAndPlay(Played[CurrentPlayedIndex]);
PlayListBox->ItemIndex = Played[CurrentPlayedIndex];
}
}
else
if (PlayListBox->ItemIndex > 0) {
FindAndPlay(PlayListBox->ItemIndex - 1);
PlayListBox->ItemIndex = PlayListBox->ItemIndex - 1;
}
}
|
Implémenter les méthodes et les classes utiles
- 1. Ajoutez les membres publics suivants à la classe TForm1 :
public
{ Public declarations }
Played: array of integer;
CurrentPlayedIndex: integer;
procedure AddToPlayedList(Index: integer);
procedure DisplayText(str: string);
procedure PlayNext();
procedure FindAndPlay(Index: integer);
end;
TMediaEntry = class(TObject)
public
Path: String;
constructor Create(FilePath: String);
end;
public: // User declarations
std::vector<int> Played;
unsigned int CurrentPlayedIndex;
void __fastcall AddToPlayedList(int index);
void __fastcall DisplayText(String s);
void __fastcall PlayNext();
void __fastcall FindAndPlay(int index);
};
class TMediaEntry : public TObject
{
public:
TMediaEntry(UnicodeString FilePath);
UnicodeString Path;
};
- 2. Le tableau Played est utilisé pour garder les index des fichiers multimédia lus dans PlayListBox lorsque le lecteur multimédia fonctionne en mode Shuffle (ShuffleChekBox est activé). Le fichier multimédia en cours de lecture est enregistré de façon à obtenir le média précédent ou suivant. CurrentPlayedIndex conserve l'index du média en cours de lecture dans Played. La méthode AddToPlayedList ajoute un média spécifié à la liste Played.
procedure TForm1.AddToPlayedList(Index: integer);
var
Len: integer;
begin
Len := Length(Played);
SetLength(Played, Len + 1);
Played[Len] := Index;
CurrentPlayedIndex := Len;
PlayListBox.ItemIndex := index;
end;
void __fastcall TForm1::AddToPlayedList(int index) {
int len;
len = Played.size();
Played.resize(len + 1);
Played[len] = index;
CurrentPlayedIndex = len;
PlayListBox->ItemIndex = index;
}
- 3. La méthode FindAndPlay identifie le média à lire grâce à l'index contenu dans PlayListBox. PlayNext obtient ensuite l'index du média à lire puis appelle FindAndPlay pour identifier et lire le média avec l'index calculé.
FindAndPlay | PlayNext |
---|---|
Delphi :
procedure TForm1.FindAndPlay(Index: integer);
begin
MediaPlayer1.Clear;
PositionTrackBar.Value := PositionTrackBar.Min;
if Index >= PlayListBox.Items.Count then
Index := 0;
MediaPlayer1.FileName := TMediaEntry(PlayListBox.Items.Objects[Index]).Path;
if MediaPlayer1.Media <> nil then
begin
MediaPlayer1.Play;
DisplayText(extractFileName(MediaPlayer1.FileName));
end;
end;
C++Builder :
void __fastcall TForm1::FindAndPlay(int index) {
MediaPlayer1->Clear();
PositionTrackBar->Value = PositionTrackBar->Min;
MediaPlayer1->FileName = dynamic_cast<TMedia*>
(PlayListBox->Items->Objects[index])->FileName;
if (MediaPlayer1->Media != NULL) {
MediaPlayer1->Play();
DisplayText(ExtractFileName(MediaPlayer1->FileName));
}
}
|
Delphi :
procedure TForm1.PlayNext();
var
Index: integer;
begin
if (ShuffleCheckBox.IsChecked) then
begin
if (CurrentPlayedIndex < Length(Played) - 1) then
begin
CurrentPlayedIndex := CurrentPlayedIndex + 1;
FindAndPlay(Played[CurrentPlayedIndex]);
end
else
begin
Index := Random(PlayListBox.Count - 1);
FindAndPlay(Index);
AddToPlayedList(Index);
end;
PlayListBox.ItemIndex := Played[CurrentPlayedIndex];
end
else
begin
FindAndPlay(PlayListBox.ItemIndex + 1);
PlayListBox.ItemIndex := PlayListBox.ItemIndex + 1;
end;
end;
C++Builder :
void __fastcall TForm1::PlayNext() {
unsigned int index;
if (ShuffleCheckBox->IsChecked) {
if (CurrentPlayedIndex < Played.size() - 1) {
CurrentPlayedIndex = CurrentPlayedIndex + 1;
FindAndPlay(Played[CurrentPlayedIndex]);
}
else {
index = Random(PlayListBox->Count - 1);
FindAndPlay(index);
AddToPlayedList(index);
}
PlayListBox->ItemIndex = Played[CurrentPlayedIndex];
}
else {
FindAndPlay(PlayListBox->ItemIndex + 1);
PlayListBox->ItemIndex = PlayListBox->ItemIndex + 1;
}
}
|
- 4. DisplayText affiche le nom et la durée (en minutes et secondes) du média en cours de lecture.
procedure TForm1.DisplayText(str: string);
var
DurationMin, DurationSec: integer;
begin
NameLabel.Text := str;
DurationMin := MediaPlayer1.Duration div 10000 div 60000;
DurationSec := MediaPlayer1.Duration div 10000 mod 60000 div 1000;
DurationLabel.Text := IntToStr(DurationMin) + ':' + IntToStr(DurationSec);
end;
void __fastcall TForm1::DisplayText(String s) {
int DurationMin, DurationSec;
NameLabel->Text = s;
DurationMin = MediaPlayer1->Duration / 10000 / 60000;
DurationSec = MediaPlayer1->Duration / 10000 % 60000 / 1000;
DurationLabel->Text = IntToStr(DurationMin) + ':' + IntToStr(DurationSec);
}
- 5. TMediaEntry encapsule le chemin d'accès absolu d'un fichier multimédia à partir de la sélection, TListBox permettant de stocker une instance de sous-classe TObject en même temps que chaque entrée de la zone de liste. Définissez son constructeur comme suit :
constructor TMediaEntry.Create(FilePath: String);
begin
Path := FilePath;
end;
TMediaPlayer::TMediaPlayer(UnicodeString FilePath)
: Path(FilePath)
{
}
Personnaliser le fichier multimédia en cours de lecture
- 1. Lire le fichier multimédia suivant
Pour que le lecteur multimédia lise le fichier multimédia suivant à la fin de la lecture du fichier en cours, utilisez le TTimer sur un certain intervalle.
Double-cliquez sur le TTimer pour lui attacher les gestionnaires d'événement OnTimer.
procedure TForm1.Timer1Timer(Sender: TObject);
begin
// When the current media ends the player starts playing
// the next media in playlist
if (MediaPlayer1.State = TMediaState.Playing) and
(MediaPlayer1.CurrentTime = MediaPlayer1.Duration) then
PlayNext;
end;
void __fastcall TForm1::Timer1Timer(TObject *Sender) {
PositionTrackBar->Tag = 1;
PositionTrackBar->Value = MediaPlayer1->CurrentTime;
PositionTrackBar->Tag = 0;
// When the current media ends the player starts playing
// the next media in playlist
if ((MediaPlayer1->State == TMediaState::Playing) &&
(MediaPlayer1->CurrentTime == MediaPlayer1->Duration)) {
PlayNext();
}
}
- 2. Activer/désactiver le mode shuffle (mode aléatoire)
Si ShuffleCheckBox n'est pas activée, le prochain fichier multimédia devant être lu est le média suivant dans PlayListBox. Si la case à cocher est activée, le prochain fichier multimédia à être lu sera un média aléatoire dans PlayListBox. Si le lecteur multimédia n'est pas configuré en mode shuffle, il n'est pas nécessaire d'utiliser le vecteur Played, car l'ordre de lecture est le même que l'ordre défini dans PlayListBox.
procedure TForm1.ShuffleCheckBoxChange(Sender: TObject);
begin
If (not ShuffleCheckBox.IsChecked) then
begin
SetLength(Played, 0);
CurrentPlayedIndex := -1;
end;
end;
void __fastcall TForm1::ShuffleCheckBoxChange(TObject *Sender) {
if (!ShuffleCheckBox->IsChecked) {
Played.resize(0);
CurrentPlayedIndex = -1;
}
}
Exécuter l'application
- 1. Pour exécuter le projet, appuyez sur F9.
- 2. Chargez les fichiers dans PlayListBox en appuyant sur le bouton LoadFileButton.
- 3. Démarrez le lecteur multimédia en appuyant sur PlayButton ou NextButton ou en double-cliquant sur un élément de PlayListBox.