aboutsummaryrefslogblamecommitdiffstats
path: root/Game/Code/Classes/UPlaylist.pas
blob: 585f9271dbdbd23aa79c31c2702ce0896d3f99eb (plain) (tree)













































































































































































































































































































































































































                                                                                                                                       
unit UPlaylist;

interface

type
  TPlaylistItem = record
    Artist: String;
    Title:  String;
    SongID: Integer;
  end;

  APlaylistItem = array of TPlaylistItem;

  TPlaylist = record
    Name:     String;
    Filename: String;
    Items:    APlaylistItem;
  end;

  APlaylist = array of TPlaylist;

  //----------
  //TPlaylistManager - Class for Managing Playlists (Loading, Displaying, Saving)
  //----------
  TPlaylistManager = class
    private

    public
      Mode:         Byte;     //Current Playlist Mode for SongScreen
      CurPlayList:  Cardinal;
      CurItem:      Cardinal;

      Playlists:    APlaylist;

      constructor Create;
      Procedure   LoadPlayLists;
      Function    LoadPlayList(Index: Cardinal; Filename: String): Boolean;
      Procedure   SavePlayList(Index: Cardinal);

      Procedure   SetPlayList(Index: Cardinal);

      Function    AddPlaylist(Name: String): Cardinal;

      Procedure   AddItem(const SongID: Cardinal; const iPlaylist: Integer = -1);
      Procedure   DelItem(const iItem: Cardinal; const iPlaylist: Integer = -1);

      Procedure   GetNames(var PLNames: array of String);
      Function    GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer = -1): Integer;
    end;

    {Modes:
      0: Standard Mode
      1: PlayList Mode
      2: Category Mode}

  var
    PlayListMan:  TPlaylistManager;


implementation
uses USongs, ULog, UPliki, UGraphic, UThemes, SysUtils;

//----------
//Create - Construct Class - Dummy for now
//----------
constructor TPlayListManager.Create;
begin
  LoadPlayLists;
end;

//----------
//LoadPlayLists - Load list of Playlists from PlayList Folder
//----------
Procedure   TPlayListManager.LoadPlayLists;
var
  SR:   TSearchRec;
  Len:  Integer;
begin
  SetLength(Playlists, 0);

  if FindFirst(PlayListPath + '*.upl', 0, SR) = 0 then
  begin
    repeat
      Len := Length(Playlists);
      SetLength(Playlists, Len +1);

      if not LoadPlayList (Len, Sr.Name) then
        SetLength(Playlists, Len);

    until FindNext(SR) <> 0;
    FindClose(SR);
  end;
end;

//----------
//LoadPlayList - Load a Playlist in the Array
//----------
Function    TPlayListManager.LoadPlayList(Index: Cardinal; Filename: String): Boolean;
  var
    F: TextFile;
    Line: String;
    PosDelimiter: Integer;
    SongID: Integer;
    Len: Integer;

  Function FindSong(Artist, Title: String): Integer;
  var I: Integer;
  begin
    Result := -1;

    For I := low(CatSongs.Song) to high(CatSongs.Song) do
    begin
      if (CatSongs.Song[I].Title = Title) AND (CatSongs.Song[I].Artist = Artist) then
      begin
        Result := I;
        Break;
      end;
    end;
  end;
begin
  if not FileExists(PlayListPath + Filename) then
  begin
    Log.LogError('Could not load Playlist: ' + Filename);
    Result := False;
    Exit;
  end;
  Result := True;

  //Load File
  AssignFile(F, PlayListPath + FileName);
  Reset(F);

  //Set Filename
  PlayLists[Index].Filename := Filename;
  PlayLists[Index].Name := '';

  //Read Until End of File
  While not Eof(F) do
  begin
    //Read Curent Line
    Readln(F, Line);

    if (Length(Line) > 0) then
    begin
    PosDelimiter := Pos(':', Line);
      if (PosDelimiter  <> 0) then
      begin
        //Comment or Name String
        if (Line[1] = '#') then
        begin
          //Found Name Value
          if (Uppercase(Trim(copy(Line, 2, PosDelimiter - 2))) = 'NAME') then
            PlayLists[Index].Name := Trim(copy(Line, PosDelimiter + 1,Length(Line) - PosDelimiter))
            
        end
        //Song Entry
        else
        begin
          SongID := FindSong(Trim(copy(Line, 1, PosDelimiter - 1)), Trim(copy(Line, PosDelimiter + 1, Length(Line) - PosDelimiter)));
          if (SongID <> -1) then
          begin
            Len := Length(PlayLists[Index].Items);
            SetLength(PlayLists[Index].Items, Len + 1);

            PlayLists[Index].Items[Len].SongID := SongID;

            PlayLists[Index].Items[Len].Artist := Trim(copy(Line, 1, PosDelimiter - 1));
            PlayLists[Index].Items[Len].Title  := Trim(copy(Line, PosDelimiter + 1, Length(Line) - PosDelimiter));
          end
          else Log.LogError('Could not find Song in Playlist: ' + PlayLists[Index].Filename + ', ' + Line);
        end;
      end;
    end;
  end;

  //If no special name is given, use Filename
  if PlayLists[Index].Name = '' then
  begin
    PlayLists[Index].Name := ChangeFileExt(FileName, '');
  end;

  //Finish (Close File)
  CloseFile(F);
end;

//----------
//SavePlayList - Saves the specified Playlist
//----------
Procedure   TPlayListManager.SavePlayList(Index: Cardinal);
var
  F: TextFile;
  I: Integer;
begin
  if (Not FileExists(PlaylistPath + Playlists[Index].Filename)) OR (Not FileisReadOnly(PlaylistPath + Playlists[Index].Filename)) then
  begin

    //open File for Rewriting
    AssignFile(F, PlaylistPath + Playlists[Index].Filename);
    try
      Rewrite(F);

      //Write Version (not nessecary but helpful)
      WriteLn(F, '######################################');
      WriteLn(F, '#Ultrastar Deluxe Playlist Format v1.0');
      WriteLn(F, '#Playlist "' + Playlists[Index].Name + '" with ' + InttoStr(Length(Playlists[Index].Items)) + ' Songs.');
      WriteLn(F, '######################################');

      //Write Name Information
      WriteLn(F, '#Name: ' + Playlists[Index].Name);

      //Write Song Information
      WriteLn(F, '#Songs:');

      For I := 0 to high(Playlists[Index].Items) do
      begin
        WriteLn(F, Playlists[Index].Items[I].Artist + ' : ' + Playlists[Index].Items[I].Title);
      end;

    finally
      CloseFile(F);
    end;
  end;
end;

//----------
//SetPlayList - Display a Playlist in CatSongs
//----------
Procedure   TPlayListManager.SetPlayList(Index: Cardinal);
var
  I: Integer;
begin
  If (Index > High(PlayLists)) then
    exit;

  //Hide all Songs
  For I := 0 to high(CatSongs.Song) do
     CatSongs.Song[I].Visible := False;

  //Show Songs in PL
  For I := 0 to high(PlayLists[Index].Items) do
  begin
    CatSongs.Song[PlayLists[Index].Items[I].SongID].Visible := True;
  end;

  //Set CatSongsMode + Playlist Mode
  CatSongs.CatNumShow := -3;
  Mode := 1;

  //Show Cat in Topleft:
  ScreenSong.ShowCatTLCustom(Format(Theme.Playlist.CatText,[Playlists[Index].Name]));

  //Fix SongSelection
  ScreenSong.Interaction := 0;
  ScreenSong.SelectNext;
  ScreenSong.FixSelected;

  //Play correct Music
  ScreenSong.ChangeMusic;
end;

//----------
//AddPlaylist - Adds a Playlist and Returns the Index
//----------
Function    TPlayListManager.AddPlaylist(Name: String): Cardinal;
var I: Integer;
begin
  Result := Length(Playlists);
  SetLength(Playlists, Result + 1);

  Playlists[Result].Name      := Name;

  I := 1;

  if (not FileExists(PlaylistPath + Name + '.upl')) then
    Playlists[Result].Filename  := Name + '.upl'
  else
  begin
    repeat
      Inc(I);
    until not FileExists(PlaylistPath + Name + InttoStr(I) + '.upl');
    Playlists[Result].Filename := Name + InttoStr(I) + '.upl';
  end;

  //Save new Playlist
  SavePlayList(Result);
end;

//----------
//AddItem - Adds an Item to a specific Playlist
//----------
Procedure   TPlayListManager.AddItem(const SongID: Cardinal; const iPlaylist: Integer);
var
  P: Cardinal;
  Len: Cardinal;
begin
  if iPlaylist = -1 then
    P := CurPlaylist
  else if (iPlaylist >= 0) AND (iPlaylist <= high(Playlists)) then
    P := iPlaylist
  else
    exit;

  if (SongID <= High(CatSongs.Song)) AND (NOT CatSongs.Song[SongID].Main) then
  begin
    Len := Length(Playlists[P].Items);
    SetLength(Playlists[P].Items, Len + 1);

    Playlists[P].Items[Len].SongID  := SongID;
    Playlists[P].Items[Len].Title   := CatSongs.Song[SongID].Title;
    Playlists[P].Items[Len].Artist  := CatSongs.Song[SongID].Artist;

    //Save Changes
    SavePlayList(P);

    //Correct Display when Editing current Playlist
    if (CatSongs.CatNumShow = -3) and (P = CurPlaylist) then
      SetPlaylist(P);
  end;
end;

//----------
//DelItem - Deletes an Item from a specific Playlist
//----------
Procedure   TPlayListManager.DelItem(const iItem: Cardinal; const iPlaylist: Integer);
var
  I: Integer;
  P: Cardinal;
begin
  if iPlaylist = -1 then
    P := CurPlaylist
  else if (iPlaylist >= 0) AND (iPlaylist <= high(Playlists)) then
    P := iPlaylist
  else
    exit;

  if (iItem <= high(Playlists[P].Items)) then
  begin
    //Move all entrys behind deleted one to Front
    For I := iItem to High(Playlists[P].Items) - 1 do
      Playlists[P].Items[I] := Playlists[P].Items[I + 1];

    //Delete Last Entry
    SetLength(PlayLists[P].Items, Length(PlayLists[P].Items) - 1);

    //Save Changes
    SavePlayList(P);
  end;

  //Correct Display when Editing current Playlist
  if (CatSongs.CatNumShow = -3) and (P = CurPlaylist) then
    SetPlaylist(P);
end;

//----------
//GetNames - Writes Playlist Names in a Array
//----------
Procedure    TPlayListManager.GetNames(var PLNames: array of String);
var
  I: Integer;
  Len: Integer;
begin
  Len := High(Playlists);
  
  if (Length(PLNames) <> Len + 1) then
    exit;

  For I := 0 to Len do
    PLNames[I] := Playlists[I].Name;
end;

//----------
//GetIndexbySongID - Returns Index in the specified Playlist of the given Song
//----------
Function    TPlayListManager.GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer): Integer;
var
  P: Integer;
  I: Integer;
begin
  if iPlaylist = -1 then
    P := CurPlaylist
  else if (iPlaylist >= 0) AND (iPlaylist <= high(Playlists)) then
    P := iPlaylist
  else
    exit;

  Result := -1;

  For I := 0 to high(Playlists[P].Items) do
  begin
    if (Playlists[P].Items[I].SongID = SongID) then
    begin
      Result := I;
      Break;
    end;
  end;
end;

end.