MeMP - Mein einfacher Mp3-Player

Kapitel 12. Playlisten laden und speichern

Playlist-Formate gibt es ungefähr genauso viele wie Player. Ein recht einfaches und noch dazu sehr verbreitetes ist m3u, das u.a. von Winamp gerne verwendet wird. Wir erweitern jetzt unsere Playlistklasse um Lade- und Speicherroutinen für solche Dateien.

TMeMPPlaylist = Class(TMeMPPlayer)
  private
    procedure LoadFromM3U(aFilename: String);
    procedure SaveAsM3U(aFilename: String);
  public
    procedure LoadFromFile(aFilename: String);
    procedure SaveToFile(aFilename: String);
end;

Das Vorgehen ist hier ähnlich wie ganz am Anfang bei der Audioklasse. Wir haben eine öffentliche Methode, die je nach Dateiendung die richtige Untermethode aufruft. Wer mag, kann später Methoden zum Laden und Speichern anderer Formate hinzufügen. Für Webradio ist das pls-Format noch interessant, was im Wesentlichen eine Ini-Datei ist.

procedure TMeMPPlaylist.LoadFromFile(aFilename: String);
begin
  if LowerCase(ExtractFileExt(aFilename)) = '.m3u' then
    LoadFromM3U(aFilename);
end;
 
procedure TMeMPPlaylist.SaveToFile(aFilename: String);
begin
  if LowerCase(ExtractFileExt(aFilename)) = '.m3u' then
    SaveAsM3U(aFilename);
end;

M3U-Listen kann man z.B. wie folgt laden und für unsere Zwecke verarbeiten. Da wir sowieso die Dateien untersuchen, ignorieren wir die oft vorhandenen ExtInf-Daten – die müssten wir sonst mit pos und copy auseinanderfriemeln, was ich mir an dieser Stelle sparen möchte.

procedure TMeMPPlaylist.LoadFromM3U(aFilename: String);
var mylist: TStringlist;
  i: Integer;
  s: String;
begin
  mylist := TStringlist.Create;
  mylist.LoadFromFile(aFilename);
  if (myList.Count > 0) then
  begin
    if (myList[0] = '#EXTM3U') then //Liste ist im EXT-Format
    begin
      i := 1;
      while (i < myList.Count) do
      begin
        // Zuerst kommen ggf. die ExtInf-Daten
        s := myList[i];
        if trim(s) = '' then
          inc(i)
        else
        begin
          if (copy(s,0,7) = '#EXTINF') then // ExtInf-Zeile auslassen
            inc(i);
          Add(ExpandFilename(myList[i]));
          inc(i);
        end;
      end;
    end
    else
      // Liste ist nicht im EXT-Format - einfach nur Dateinamen
      for i := 0 to myList.Count - 1 do
      begin
        if trim(mylist[i])='' then continue;
        Add(ExpandFilename(myList[i]));
      end;
  end;
  FreeAndNil(myList);
end;

Beim Speichern müssen wir weniger Fehler abfangen, daher geht das kürzer:

procedure TMeMPPlaylist.SaveAsM3U(aFilename: String);
var myList: tStringlist;
    i:integer;
    aAudiofile: TAudioFile;
begin
  myList := TStringList.Create;
  myList.Add('#EXTM3U');
  for i := 0 to fPlayList.Count - 1 do
  begin
    aAudiofile := fPlaylist[i] as TAudioFile;
    myList.add('#EXTINF:' + IntTostr(aAudiofile.Dauer) + ','
          + aAudioFile.Interpret + ' - ' + aAudioFile.Titel);
    myList.Add(ExtractRelativePath(aFilename, aAudioFile.Pfad ));
  end;
  myList.SaveToFile(afilename);
  FreeAndNil(myList);
end;

Wie wir das in unseren Player einbauen, ist hoffentlich klar. Auf die Form einfach noch zwei weiterere Buttons, einen OpenDialog und einen SaveDialog draufpacken und im OnClick-Event der beiden Buttons nach dem Execute des Dialogs die Liste laden oder speichern.