MeMP - Mein einfacher Mp3-Player

Kapitel 11. MeMP, Version 0.0,5

Bauen wir uns jetzt als unseren ersten halbwegs richtigen Player zusammen. Wir können auch unser letztes Projekt fortführen, was wir aber gründlich entrümpeln. Zunächst schmeißen wir die Memo von der Form runter, ebenso den ganzen Code drumherum. Stattdessen packen wir eine ListView auf die Form, stellen den Style auf vsReport und fügen zwei Spalten hinzu, Titel und Dauer.

Bei unserem OpenDialog stellen wir ofAllowMultiSelect auf True und erlauben so die Auswahl mehrerer Dateien. Caption und Name von Button und Dialog werden der neuen Funktion „Dateien der Playlist hinzufügen“ angepasst.

Als nächstes entfernen wir den MeMPPlayer und ersetzen ihn durch das erweiterte Konstrukt MeMPPlaylist. Die globale Variable GlobalAudioFile wird nun auch nicht mehr benötigt.

Hinzu kommen zwei Buttons für „Vor“ und „Zurück“.

Die FormCreate-Prozedur erweitern wir, um die Playlist komplett zu initialisieren.

procedure TForm1.FormCreate(Sender: TObject);
begin
  MeMPPlaylist := TMeMPPlaylist.Create;
  // ...
  MeMPPlaylist.OnAddItem  := OnPlaylistAddItem;
  MeMPPlaylist.OnClear    := OnPlaylistClear;
 
  AddFilesDialog.Filter := MeMPPlaylist.Filter;
end;

Das MeMPPlayer.Play im OnClick-Event des Play-Buttons ersetzen wir durch

MeMPPlaylist.Play(-1);

und unsere Reaktion auf das Event OnEndFile ändern wir so ab:

procedure TForm1.OnMeMPEndFile(Sender: TObject);
begin
  MeMPPlaylist.PlayNext;
end;

Der alte Auswahl-Button bekommt nun diese Funktion:

procedure TForm1.BtnAddFilesClick(Sender: TObject);
var i: Integer;
begin
  if AddFilesDialog.Execute then
    for i := 0 to AddFilesDialog.Files.Count - 1 do
      MeMPPlaylist.Add(AddFilesDialog.Files[i]);
end;

Damit die eingefügten Dateien auch in der Listview angezeigt werden, reagieren wir entsprechend auf das OnAddItem-Event der Playlist.

procedure TForm1.OnPlaylistAddItem(Sender: TObject; NewAudioFile: TAudioFile);
var newItem: TListItem;
    t: Integer;
begin
  newItem := PlaylistView.Items.Add;
  newItem.Caption := NewAudioFile.PlaylistTitel;
  t := NewAudioFile.Dauer;
  NewItem.SubItems.Add(Format('%d:%.2d',[t Div 60, t Mod 60]));
  NewItem.Data := NewAudioFile;
end;

Damit wir den Player halbwegs schön bedienen können, kommt ein

procedure TForm1.PlaylistViewDblClick(Sender: TObject);
begin
  MeMPPlaylist.Play(PlaylistView.ItemIndex);
end;

dazu, und die Anzeige, welches Lied gerade in der Liste aktuell ist, erledigen wir einfach so:

procedure TForm1.PlaylistViewCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  If TAudioFile(Item.Data) = MeMPPlaylist.PlayingFile then
    PlaylistView.Canvas.Font.Style := [fsBold];
end;

Damit das vernünftig funktioniert, müssen wir im OnPlay-Event ein

PlaylistView.Refresh;

einfügen, damit bei einem Titelwechsel die Anzeige aktualisiert wird. Möchte man z.B. auch ein Statusicon davor setzen, sollte man das auch im OnPause, OnResume und OnStop hinzufügen.

Bleiben noch die Buttons „Vor“ und „Zurück“ sowie das OnClear-Event der Playlist. Aber was da zu tun ist, ist ja wohl hoffentlich klar, oder?

Zusammenfassung bis hierhin

Das Konzept für unseren Player ist nun fertig. Wir haben eine Playlist, die neben dem Titel auch die Spieldauer anzeigt, die Playlist läuft von vorne bis hinten durch, wir können stoppen, pausieren und weiterspielen, die Lautstärke ändern und im Titel an eine beliebige Stelle springen. Das ist schon eine ganze Menge. Dabei haben wir darauf geachtet, dass wir eine klare Trennung von Daten und Darstellung haben, und somit unser Programm leicht erweiterbar ist, ohne alles umzuschreiben.

Im Zusammenhang mit Playlisten ist noch eine Frage sehr interessant, nämlich das Speichern und Laden der gängigen Formate, und irgendwie ist ein Player ohne eine Visualisierung auch nicht wirklich fertig. Man muss ja nicht direkt psychedelischen Unsinn darstellen, aber so ein paar hüpfende Balken sind doch ganz nett. Und das tollste daran: Das geht ganz einfach. Sagte ich schon, dass man sich die Beispielprojekte der bass.dll mal genauer ansehen sollte? Dann ist ja gut – also auf geht’s zum Endspurt!