aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Game/Code/Classes/UCommon.pas87
-rw-r--r--Game/Code/Classes/USong.pas34
-rw-r--r--Game/Code/Classes/USongs.pas651
3 files changed, 364 insertions, 408 deletions
diff --git a/Game/Code/Classes/UCommon.pas b/Game/Code/Classes/UCommon.pas
index 5af018b7..1872b789 100644
--- a/Game/Code/Classes/UCommon.pas
+++ b/Game/Code/Classes/UCommon.pas
@@ -67,6 +67,9 @@ function IsAlphaNumericChar(ch: WideChar): boolean;
function IsPunctuationChar(ch: WideChar): boolean;
function IsControlChar(ch: WideChar): boolean;
+// A stable alternative to TList.Sort() (use TList.Sort() if applicable, see below)
+procedure MergeSort(List: TList; CompareFunc: TListSortCompare);
+
implementation
@@ -613,6 +616,90 @@ begin
end;
end;
+(*
+ * Recursive part of the MergeSort algorithm.
+ * OutList will be either InList or TempList and will be swapped in each
+ * depth-level of recursion. By doing this it we can directly merge into the
+ * output-list. If we only had In- and OutList parameters we had to merge into
+ * InList after the recursive calls and copy the data to the OutList afterwards.
+ *)
+function _MergeSort(InList, TempList, OutList: TList; StartPos, BlockSize: integer;
+ CompareFunc: TListSortCompare): TList;
+var
+ LeftSize, RightSize: integer; // number of elements in left/right block
+ LeftEnd, RightEnd: integer; // Index after last element in left/right block
+ MidPos: integer; // index of first element in right block
+ Pos: integer; // position in output list
+begin
+ LeftSize := BlockSize div 2;
+ RightSize := BlockSize - LeftSize;
+ MidPos := StartPos + LeftSize;
+
+ // sort left and right halves of this block by recursive calls of this function
+ if (LeftSize >= 2) then
+ _MergeSort(InList, OutList, TempList, StartPos, LeftSize, CompareFunc)
+ else
+ TempList[StartPos] := InList[StartPos];
+ if (RightSize >= 2) then
+ _MergeSort(InList, OutList, TempList, MidPos, RightSize, CompareFunc)
+ else
+ TempList[MidPos] := InList[MidPos];
+
+ // merge sorted left and right sub-lists into output-list
+ LeftEnd := MidPos;
+ RightEnd := StartPos + BlockSize;
+ Pos := StartPos;
+ while ((StartPos < LeftEnd) and (MidPos < RightEnd)) do
+ begin
+ if (CompareFunc(TempList[StartPos], TempList[MidPos]) <= 0) then
+ begin
+ OutList[Pos] := TempList[StartPos];
+ Inc(StartPos);
+ end
+ else
+ begin
+ OutList[Pos] := TempList[MidPos];
+ Inc(MidPos);
+ end;
+ Inc(Pos);
+ end;
+
+ // copy remaining elements to output-list
+ while (StartPos < LeftEnd) do
+ begin
+ OutList[Pos] := TempList[StartPos];
+ Inc(StartPos);
+ Inc(Pos);
+ end;
+ while (MidPos < RightEnd) do
+ begin
+ OutList[Pos] := TempList[MidPos];
+ Inc(MidPos);
+ Inc(Pos);
+ end;
+end;
+
+(*
+ * Stable alternative to the instable TList.Sort() (uses QuickSort) implementation.
+ * A stable sorting algorithm preserves preordered items. E.g. if sorting by
+ * songs by title first and artist afterwards, the songs of each artist will
+ * be ordered by title. In contrast to this an unstable algorithm (like QuickSort)
+ * may destroy an existing order, so the songs of an artist will not be ordered
+ * by title anymore after sorting by artist in the previous example.
+ * If you do not need a stable algorithm, use TList.Sort() instead.
+ *)
+procedure MergeSort(List: TList; CompareFunc: TListSortCompare);
+var
+ TempList: TList;
+begin
+ TempList := TList.Create();
+ TempList.Count := List.Count;
+ if (List.Count >= 2) then
+ _MergeSort(List, TempList, List, 0, List.Count, CompareFunc);
+ TempList.Free;
+end;
+
+
initialization
InitConsoleOutput();
diff --git a/Game/Code/Classes/USong.pas b/Game/Code/Classes/USong.pas
index 66169ef0..3c365720 100644
--- a/Game/Code/Classes/USong.pas
+++ b/Game/Code/Classes/USong.pas
@@ -63,10 +63,10 @@ type
FileName: widestring;
// sorting methods
- Category: array of widestring; // I think I won't need this
+ Category: array of widestring; // TODO: do we need this?
Genre: widestring;
Edition: widestring;
- Language: widestring; // 0.5.0: new
+ Language: widestring;
Title: widestring;
Artist: widestring;
@@ -80,7 +80,7 @@ type
Background: widestring;
Video: widestring;
VideoGAP: real;
- VideoLoaded: boolean; // 0.5.0: true if the video has been loaded
+ VideoLoaded: boolean; // true if the video has been loaded
NotesGAP: integer;
Start: real; // in seconds
Finish: integer; // in miliseconds
@@ -98,19 +98,20 @@ type
OrderTyp: integer; // type of sorting for this button (0=name)
CatNumber: integer; // Count of Songs in Category for Cats and Number of Song in Category for Songs
- SongFile: TextFile; // all procedures in this unit operates on this file
+ SongFile: TextFile; // all procedures in this unit operate on this file
Base : array[0..1] of integer;
Rel : array[0..1] of integer;
Mult : integer;
MultBPM : integer;
- constructor create ( const aFileName : WideString );
+ constructor Create (); overload;
+ constructor Create ( const aFileName : WideString ); overload;
function LoadSong: boolean;
function LoadXMLSong: boolean;
function Analyse(): boolean;
function AnalyseXML(): boolean;
- procedure clear();
+ procedure Clear();
end;
implementation
@@ -121,42 +122,33 @@ uses
UMusic, //needed for Lines
UMain; //needed for Player
-constructor TSong.create( const aFileName : WideString );
+constructor TSong.Create();
begin
+end;
+constructor TSong.Create( const aFileName : WideString );
+begin
Mult := 1;
-
MultBPM := 4;
-
-
fFileName := aFileName;
-
if fileexists( aFileName ) then
-
begin
-
self.Path := ExtractFilePath( aFileName );
self.Folder := ExtractFilePath( aFileName );
self.FileName := ExtractFileName( aFileName );
-
-(*
-
+ (*
if ReadTXTHeader( aFileName ) then
-
begin
-
LoadSong();
-
end
else
begin
Log.LogError('Error Loading SongHeader, abort Song Loading');
Exit;
end;
-*)
+ *)
end;
-
end;
//Load TXT Song
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas
index df748e74..fd9accb5 100644
--- a/Game/Code/Classes/USongs.pas
+++ b/Game/Code/Classes/USongs.pas
@@ -53,7 +53,6 @@ type
Length: string;
end;
-
{$IFDEF USE_PSEUDO_THREAD}
TSongs = class( TPseudoThread )
{$ELSE}
@@ -72,7 +71,6 @@ type
protected
procedure Execute; override;
public
-// Song : array of TSong; // array of songs
SongList : TList; // array of songs
Selected : integer; // selected song index
constructor create();
@@ -96,8 +94,8 @@ type
CatNumShow: integer; // Category Number being seen
CatCount: integer; //Number of Categorys
+ procedure SortSongs();
procedure Refresh; // refreshes arrays by recreating them from Songs array
-// procedure Sort(Order: integer);
procedure ShowCategory(Index: integer); // expands all songs in category
procedure HideCategory(Index: integer); // hides all songs in category
procedure ClickCategoryButton(Index: integer); // uses ShowCategory and HideCategory when needed
@@ -197,8 +195,6 @@ begin
end;
procedure TSongs.int_LoadSongList;
-const
- cUSNGPath = '/usr/share/games/ultrastar-ng/songs';
begin
try
fProcessing := true;
@@ -211,12 +207,6 @@ begin
if UserSongPath <> SongPath then
BrowseDir(UserSongPath);
-(*
- if ( cUSNGPath <> SongPath ) AND
- ( cUSNGPath <> UserSongPath ) then
- BrowseDir( cUSNGPath ); // todo : JB this is REAL messy,
-*) // we should have some sort of path manager that lets us specify X number of extra paths to search
-
if assigned( CatSongs ) then
CatSongs.Refresh;
@@ -317,112 +307,69 @@ begin
end;
+(*
+ * Comparison functions for sorting
+ *)
+
+function CompareByEdition(Song1, Song2: Pointer): integer;
+begin
+ Result := CompareText(TSong(Song1).Edition, TSong(Song2).Edition);
+end;
+
+function CompareByGenre(Song1, Song2: Pointer): integer;
+begin
+ Result := CompareText(TSong(Song1).Genre, TSong(Song2).Genre);
+end;
+
+function CompareByTitle(Song1, Song2: Pointer): integer;
+begin
+ Result := CompareText(TSong(Song1).Title, TSong(Song2).Title);
+end;
+
+function CompareByArtist(Song1, Song2: Pointer): integer;
+begin
+ Result := CompareText(TSong(Song1).Artist, TSong(Song2).Artist);
+end;
+
+function CompareByFolder(Song1, Song2: Pointer): integer;
+begin
+ Result := CompareText(TSong(Song1).Folder, TSong(Song2).Folder);
+end;
+
+function CompareByLanguage(Song1, Song2: Pointer): integer;
+begin
+ Result := CompareText(TSong(Song1).Language, TSong(Song2).Language);
+end;
+
procedure TSongs.Sort(Order: integer);
var
- S: integer;
- S2: integer;
- TempSong: TSong;
+ CompareFunc: TListSortCompare;
begin
+ // FIXME: what is the difference between artist and artist2, etc.?
case Order of
sEdition: // by edition
- begin
- for S2 := 0 to SongList.Count -1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Edition, TSong( SongList[S-1] ).Edition) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
- end;
+ CompareFunc := CompareByEdition;
sGenre: // by genre
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Genre, TSong( SongList[S-1] ).Genre) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
- end;
+ CompareFunc := CompareByGenre;
sTitle: // by title
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Title, TSong( SongList[S-1] ).Title) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
-
- end;
+ CompareFunc := CompareByTitle;
sArtist: // by artist
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Artist, TSong( SongList[S-1] ).Artist) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
- end;
+ CompareFunc := CompareByArtist;
sFolder: // by folder
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Folder, TSong( SongList[S-1] ).Folder) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
- end;
+ CompareFunc := CompareByFolder;
sTitle2: // by title2
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Title, TSong( SongList[S-1] ).Title) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
-
- end;
+ CompareFunc := CompareByTitle;
sArtist2: // by artist2
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Artist, TSong( SongList[S-1] ).Artist) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
- end;
+ CompareFunc := CompareByArtist;
sLanguage: // by Language
- begin
- for S2 := 0 to SongList.Count-1 do
- for S := 1 to SongList.Count-1 do
- if CompareText(TSong( SongList[S] ).Language, TSong( SongList[S-1] ).Language) < 0 then
- begin
- TempSong := SongList[S-1];
- SongList[S-1] := SongList[S];
- SongList[S] := TempSong;
- end;
- end;
-
+ CompareFunc := CompareByLanguage;
end; // case
+
+ // Note: Do not use TList.Sort() as it uses QuickSort which is instable.
+ // For example, if a list is sorted by title first and
+ // by artist afterwards, the songs of an artist will not be sorted by title anymore.
+ // The stable MergeSort guarantees to maintain this order.
+ MergeSort(SongList, CompareFunc);
end;
function TSongs.FindSongFile(Dir, Mask: widestring): widestring;
@@ -436,315 +383,245 @@ begin
FindClose(SR);
end;
-procedure TCatSongs.Refresh;
-var
- S: integer; // temporary song index
- CatLen: integer; // length of CatSongs.Song
- Letter: char; // current letter for sorting using letter
- SS: string; // current edition for sorting using edition, genre etc.
- Order: integer; // number used for ordernum
- Letter2: char; //
- CatNumber:integer; // Number of Song in Category
+procedure TCatSongs.SortSongs();
begin
- CatNumShow := -1;
-// Songs.Sort(0); // by title
-
-case Ini.Sorting of
+ case Ini.Sorting of
sEdition: begin
- Songs.Sort(sArtist);
- Songs.Sort(sEdition);
- end;
+ Songs.Sort(sTitle);
+ Songs.Sort(sArtist);
+ Songs.Sort(sEdition);
+ end;
sGenre: begin
- Songs.Sort(sArtist);
- Songs.Sort(sGenre);
- end;
+ Songs.Sort(sTitle);
+ Songs.Sort(sArtist);
+ Songs.Sort(sGenre);
+ end;
sLanguage: begin
- Songs.Sort(sArtist);
- Songs.Sort(sLanguage);
- end;
- sFolder: begin
- Songs.Sort(sArtist);
- Songs.Sort(sFolder);
- end;
- sTitle: Songs.Sort(sTitle);
- sArtist: Songs.Sort(sArtist);
- sTitle2: Songs.Sort(sTitle2); // by title2
- sArtist2: Songs.Sort(sArtist2); // by artist2
-
+ Songs.Sort(sTitle);
+ Songs.Sort(sArtist);
+ Songs.Sort(sLanguage);
+ end;
+ sFolder: begin
+ Songs.Sort(sTitle);
+ Songs.Sort(sArtist);
+ Songs.Sort(sFolder);
+ end;
+ sTitle: begin
+ Songs.Sort(sTitle);
+ end;
+ sArtist: begin
+ Songs.Sort(sTitle);
+ Songs.Sort(sArtist);
+ end;
+ sTitle2: begin
+ Songs.Sort(sArtist2);
+ Songs.Sort(sTitle2);
+ end;
+ sArtist2: begin
+ Songs.Sort(sTitle2);
+ Songs.Sort(sArtist2);
+ end;
end; // case
+end;
+
+procedure TCatSongs.Refresh;
+var
+ SongIndex: integer;
+ CurSong: TSong;
+ CatIndex: integer; // index of current song in Song
+ Letter: char; // current letter for sorting using letter
+ CurCategory: string; // current edition for sorting using edition, genre etc.
+ Order: integer; // number used for ordernum
+ LetterTmp: char;
+ CatNumber: integer; // Number of Song in Category
+
+ procedure AddCategoryButton(const CategoryName: string);
+ var
+ PrevCatBtnIndex: integer;
+ begin
+ Inc(Order);
+ CatIndex := Length(Song);
+ SetLength(Song, CatIndex+1);
+ Song[CatIndex] := TSong.Create();
+ Song[CatIndex].Artist := '[' + CategoryName + ']';
+ Song[CatIndex].Main := true;
+ Song[CatIndex].OrderTyp := 0;
+ Song[CatIndex].OrderNum := Order;
+ Song[CatIndex].Cover := CatCovers.GetCover(Ini.Sorting, CategoryName);
+ Song[CatIndex].Visible := true;
+
+ // set number of songs in previous category
+ PrevCatBtnIndex := CatIndex - CatNumber - 1;
+ if ((PrevCatBtnIndex >= 0) and Song[PrevCatBtnIndex].Main) then
+ Song[PrevCatBtnIndex].CatNumber := CatNumber;
+
+ CatNumber := 0;
+ end;
+begin
+ CatNumShow := -1;
+
+ SortSongs();
- Letter := ' ';
- SS := '';
+ CurCategory := '';
Order := 0;
CatNumber := 0;
- //Songs leeren
- SetLength (Song, 0);
+ // Note: do NOT set Letter to ' ', otherwise no category-button will be
+ // created for songs beginning with ' ' if songs of this category exist.
+ // TODO: trim song-properties so ' ' will not occur as first chararcter.
+ Letter := #0;
+
+ // clear song-list
+ for SongIndex := 0 to Songs.SongList.Count-1 do
+ begin
+ // free category buttons
+ // Note: do NOT delete songs, they are just references to Songs.SongList entries
+ CurSong := TSong(Songs.SongList[SongIndex]);
+ if (CurSong.Main) then
+ CurSong.Free;
+ end;
+ SetLength(Song, 0);
- for S := 0 to Songs.SongList.Count-1 do
+ for SongIndex := 0 to Songs.SongList.Count-1 do
begin
+ CurSong := TSong(Songs.SongList[SongIndex]);
+ // if tabs are on, add section buttons for each new section
if (Ini.Tabs = 1) then
- if (Ini.Sorting = sEdition) and (CompareText(SS, TSong( Songs.SongList[S] ).Edition) <> 0) then begin
- // add Category Button
- Inc(Order);
- SS := TSong( Songs.SongList[S] ).Edition;
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := '[' + SS + ']';
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
- CatSongs.Song[CatLen].OrderNum := Order;
-
-
-
- // 0.4.3
- // if SS = 'Singstar' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar.jpg';
- // if SS = 'Singstar Part 2' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar.jpg';
- // if SS = 'Singstar German' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar.jpg';
- // if SS = 'Singstar Spanish' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar.jpg';
- // if SS = 'Singstar Italian' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar.jpg';
- // if SS = 'Singstar French' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar.jpg';
- // if SS = 'Singstar Party' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar Party.jpg';
- // if SS = 'Singstar Popworld' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar Popworld.jpg';
- // if SS = 'Singstar 80s' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar 80s.jpg';
- // if SS = 'Singstar 80s Polish' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar 80s.jpg';
- // if SS = 'Singstar Rocks' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar Rocks.jpg';
- // if SS = 'Singstar Anthems' then CatSongs.Song[CatLen].Cover := CoversPath + 'Singstar Anthems.jpg';
-
- {// cover-patch
- if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';//}
-
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
-
- //CatNumber Patch
- if (SS <> '') then
+ begin
+ if (Ini.Sorting = sEdition) and
+ (CompareText(CurCategory, CurSong.Edition) <> 0) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
+ CurCategory := CurSong.Edition;
+
+ // TODO: remove this block if it is not needed anymore
+ {
+ if CurSection = 'Singstar Part 2' then CoverName := 'Singstar';
+ if CurSection = 'Singstar German' then CoverName := 'Singstar';
+ if CurSection = 'Singstar Spanish' then CoverName := 'Singstar';
+ if CurSection = 'Singstar Italian' then CoverName := 'Singstar';
+ if CurSection = 'Singstar French' then CoverName := 'Singstar';
+ if CurSection = 'Singstar 80s Polish' then CoverName := 'Singstar 80s';
+ }
+
+ // add Category Button
+ AddCategoryButton(CurCategory);
+ end
- CatSongs.Song[CatLen].Visible := true;
- end
-
- else if (Ini.Sorting = sGenre) and (CompareText(SS, TSong( Songs.SongList[S] ).Genre) <> 0) then begin
- // add Genre Button
- Inc(Order);
- SS := TSong( Songs.SongList[S] ).Genre;
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := SS;
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
- CatSongs.Song[CatLen].OrderNum := Order;
-
- {// cover-patch
- if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
-
- //CatNumber Patch
- if (SS <> '') then
+ else if (Ini.Sorting = sGenre) and
+ (CompareText(CurCategory, CurSong.Genre) <> 0) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
+ CurCategory := CurSong.Genre;
+ // add Genre Button
+ AddCategoryButton(CurCategory);
+ end
- CatSongs.Song[CatLen].Visible := true;
- end
-
- else if (Ini.Sorting = sLanguage) and (CompareText(SS, TSong( Songs.SongList[S] ).Language) <> 0) then begin
- // add Language Button
- Inc(Order);
- SS := TSong( Songs.SongList[S] ).Language;
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := SS;
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
- CatSongs.Song[CatLen].OrderNum := Order;
-
- {// cover-patch
- if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
-
- //CatNumber Patch
- if (SS <> '') then
+ else if (Ini.Sorting = sLanguage) and
+ (CompareText(CurCategory, CurSong.Language) <> 0) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
+ CurCategory := CurSong.Language;
+ // add Language Button
+ AddCategoryButton(CurCategory);
+ end
- CatSongs.Song[CatLen].Visible := true;
- end
-
- else if (Ini.Sorting = sTitle) and
- (Length(TSong( Songs.SongList[S] ).Title)>=1) and
- (Letter <> UpperCase(TSong( Songs.SongList[S] ).Title)[1]) then begin
- // add a letter Category Button
- Inc(Order);
- Letter := Uppercase(TSong( Songs.SongList[S] ).Title)[1];
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
-// Order := ord(Letter);
- CatSongs.Song[CatLen].OrderNum := Order;
-
-
- {// cover-patch
- if FileExists(CoversPath + 'Title' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Title' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
-
- //CatNumber Patch
- if (Letter <> ' ') then
+ else if (Ini.Sorting = sTitle) and
+ (Length(CurSong.Title) >= 1) and
+ (Letter <> UpperCase(CurSong.Title)[1]) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
+ Letter := Uppercase(CurSong.Title)[1];
+ // add a letter Category Button
+ AddCategoryButton(Letter);
+ end
- CatSongs.Song[CatLen].Visible := true;
- end
-
- else if (Ini.Sorting = sArtist) and (Length(TSong( Songs.SongList[S] ).Artist)>=1) and
- (Letter <> UpperCase(TSong( Songs.SongList[S] ).Artist)[1]) then begin
- // add a letter Category Button
- Inc(Order);
- Letter := UpperCase(TSong( Songs.SongList[S] ).Artist)[1];
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
-// Order := ord(Letter);
- CatSongs.Song[CatLen].OrderNum := Order;
-
- {// cover-patch
- if FileExists(CoversPath + 'Artist' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Artist' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
-
- //CatNumber Patch
- if (Letter <> ' ') then
+ else if (Ini.Sorting = sArtist) and
+ (Length(CurSong.Artist) >= 1) and
+ (Letter <> UpperCase(CurSong.Artist)[1]) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
+ Letter := UpperCase(CurSong.Artist)[1];
+ // add a letter Category Button
+ AddCategoryButton(Letter);
+ end
- CatSongs.Song[CatLen].Visible := true;
- end
-
- else if (Ini.Sorting = sFolder) and (CompareText(SS, TSong( Songs.SongList[S] ).Folder) <> 0) then begin
- // 0.5.0: add folder tab
- Inc(Order);
- SS := TSong( Songs.SongList[S] ).Folder;
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := SS;
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
- CatSongs.Song[CatLen].OrderNum := Order;
-
- {// cover-patch
- if FileExists(CoversPath + SS + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + SS + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, SS);
-
- //CatNumber Patch
- if (SS <> '') then
+ else if (Ini.Sorting = sFolder) and
+ (CompareText(CurCategory, CurSong.Folder) <> 0) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
-
- CatSongs.Song[CatLen].Visible := true;
- end
+ CurCategory := CurSong.Folder;
+ // add folder tab
+ AddCategoryButton(CurCategory);
+ end
- else if (Ini.Sorting = sTitle2) AND (Length(TSong( Songs.SongList[S] ).Title)>=1) then begin
- if (ord(TSong( Songs.SongList[S] ).Title[1]) > 47) and (ord(TSong( Songs.SongList[S] ).Title[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(TSong( Songs.SongList[S] ).Title)[1];
- if (Letter <> Letter2) then begin
- // add a letter Category Button
- Inc(Order);
- Letter := Letter2;
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
-// Order := ord(Letter);
- CatSongs.Song[CatLen].OrderNum := Order;
-
- {// cover-patch
- if FileExists(CoversPath + 'Title' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Title' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
-
- //CatNumber Patch
- if (Letter <> ' ') then
+ else if (Ini.Sorting = sTitle2) and
+ (Length(CurSong.Title) >= 1) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
+ // pack all numbers into a category named '#'
+ if (CurSong.Title[1] >= '0') and (CurSong.Title[1] <= '9') then
+ LetterTmp := '#'
+ else
+ LetterTmp := UpperCase(CurSong.Title)[1];
- CatSongs.Song[CatLen].Visible := true;
- end;
- end
+ if (Letter <> LetterTmp) then
+ begin
+ Letter := LetterTmp;
+ // add a letter Category Button
+ AddCategoryButton(Letter);
+ end;
+ end
- else if (Ini.Sorting = sArtist2) AND (Length(TSong( Songs.SongList[S] ).Artist)>=1) then begin
- if (ord(TSong( Songs.SongList[S] ).Artist[1]) > 47) and (ord(TSong( Songs.SongList[S] ).Artist[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(TSong( Songs.SongList[S] ).Artist)[1];
- if (Letter <> Letter2) then begin
- // add a letter Category Button
- Inc(Order);
- Letter := Letter2;
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
- CatSongs.Song[CatLen].Artist := '[' + Letter + ']';
- CatSongs.Song[CatLen].Main := true;
- CatSongs.Song[CatLen].OrderTyp := 0;
-// Order := ord(Letter);
- CatSongs.Song[CatLen].OrderNum := Order;
-
- {// cover-patch
- if FileExists(CoversPath + 'Artist' + Letter + '.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'Artist' + Letter + '.jpg'
- else if FileExists(CoversPath + 'NoCover.jpg') then CatSongs.Song[CatLen].Cover := CoversPath + 'NoCover.jpg';}
- CatSongs.Song[CatLen].Cover := CatCovers.GetCover(Ini.Sorting, Letter);
-
- //CatNumber Patch
- if (Letter <> ' ') then
+ else if (Ini.Sorting = sArtist2) and
+ (Length(CurSong.Artist)>=1) then
+ begin
+ // pack all numbers into a category named '#'
+ if (CurSong.Artist[1] >= '0') and (CurSong.Artist[1] <= '9') then
+ LetterTmp := '#'
+ else
+ LetterTmp := UpperCase(CurSong.Artist)[1];
+
+ if (Letter <> LetterTmp) then
begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
+ Letter := LetterTmp;
+ // add a letter Category Button
+ AddCategoryButton(Letter);
end;
-
- CatSongs.Song[CatLen].Visible := true;
end;
end;
+ CatIndex := Length(Song);
+ SetLength(Song, CatIndex+1);
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
+ Inc(CatNumber); // increase number of songs in category
- Inc (CatNumber); //Increase Number in Cat
+ // copy reference to current song
+ Song[CatIndex] := CurSong;
- CatSongs.Song[CatLen] := TSong( Songs.SongList[S] );
- CatSongs.Song[CatLen].OrderNum := Order; // assigns category
- CatSongs.Song[CatLen].CatNumber := CatNumber;
+ // set song's category info
+ CurSong.OrderNum := Order; // assigns category
+ CurSong.CatNumber := CatNumber;
- if (Ini.Tabs = 0) then CatSongs.Song[CatLen].Visible := true
- else if (Ini.Tabs = 1) then CatSongs.Song[CatLen].Visible := false;
-// if (Ini.Tabs = 1) and (Order = 1) then CatSongs.Song[CatLen].Visible := true; // open first tab
-//CatSongs.Song[CatLen].Visible := true;
+ if (Ini.Tabs = 0) then
+ CurSong.Visible := true
+ else if (Ini.Tabs = 1) then
+ CurSong.Visible := false;
+ {
+ if (Ini.Tabs = 1) and (Order = 1) then
+ begin
+ //open first tab
+ CurSong.Visible := true;
+ end;
+ CurSong.Visible := true;
+ }
+ end;
+ // set CatNumber of last category
+ if (Ini.Tabs_at_startup = 1) and (High(Song) >= 1) then
+ begin
+ // set number of songs in previous category
+ SongIndex := CatIndex - CatNumber;
+ if ((SongIndex >= 0) and Song[SongIndex].Main) then
+ Song[SongIndex].CatNumber := CatNumber;
end;
-//CatNumber Patch - Set CatNumber of Last Category
-if (ini.Tabs_at_startup = 1) And (high(Song) >=1) then
- Song[CatLen - CatNumber].CatNumber := CatNumber;//Set CatNumber of Categroy
-//CatCount Patch
-CatCount := Order;
+
+ // update number of categories
+ CatCount := Order;
end;
procedure TCatSongs.ShowCategory(Index: integer);
@@ -754,7 +631,7 @@ begin
CatNumShow := Index;
for S := 0 to high(CatSongs.Song) do
begin
- if (CatSongs.Song[S].OrderNum = Index) AND (Not CatSongs.Song[S].Main) then
+ if (CatSongs.Song[S].OrderNum = Index) and (not CatSongs.Song[S].Main) then
CatSongs.Song[S].Visible := true
else
CatSongs.Song[S].Visible := false;
@@ -777,9 +654,9 @@ var
begin
Num := CatSongs.Song[Index].OrderNum;
if Num <> CatNumShow then
- begin
+ begin
ShowCategory(Num);
- end
+ end
else begin
ShowCategoryList;
end;
@@ -806,18 +683,18 @@ end;
function TCatSongs.FindNextVisible(SearchFrom:integer): integer;//Find next Visible Song
var
I: Integer;
- begin
+begin
Result := -1;
I := SearchFrom + 1;
while not CatSongs.Song[I].Visible do
- begin
+ begin
Inc (I);
if (I>high(CatSongs.Song)) then
I := low(CatSongs.Song);
if (I = SearchFrom) then //Make One Round and no song found->quit
break;
- end;
end;
+end;
//Wrong song selected when tabs on bug End
function TCatSongs.VisibleSongs: integer;
@@ -842,7 +719,7 @@ function TCatSongs.SetFilter(FilterStr: String; const fType: Byte): Cardinal;
var
I, J: Integer;
cString: String;
- SearchStr: Array of String;
+ SearchStr: array of String;
begin
{fType: 0: All
1: Title
@@ -853,18 +730,18 @@ begin
//Create Search Array
SetLength(SearchStr, 1);
I := Pos (' ', FilterStr);
- While (I <> 0) do
+ while (I <> 0) do
begin
SetLength (SearchStr, Length(SearchStr) + 1);
cString := Copy(FilterStr, 1, I-1);
- if (cString <> ' ') AND (cString <> '') then
+ if (cString <> ' ') and (cString <> '') then
SearchStr[High(SearchStr)-1] := cString;
Delete (FilterStr, 1, I);
I := Pos (' ', FilterStr);
end;
//Copy last Word
- if (FilterStr <> ' ') AND (FilterStr <> '') then
+ if (FilterStr <> ' ') and (FilterStr <> '') then
SearchStr[High(SearchStr)] := FilterStr;
for I:=0 to High(Song) do begin
@@ -877,9 +754,9 @@ begin
end;
Song[i].Visible:=True;
//Look for every Searched Word
- For J := 0 to High(SearchStr) do
+ for J := 0 to High(SearchStr) do
begin
- Song[i].Visible := Song[i].Visible AND AnsiContainsText(cString, SearchStr[J])
+ Song[i].Visible := Song[i].Visible and AnsiContainsText(cString, SearchStr[J])
end;
if Song[i].Visible then
Inc(Result);
@@ -891,7 +768,7 @@ begin
end
else begin
for i:=0 to High(Song) do begin
- Song[i].Visible:=(Ini.Tabs=1)=Song[i].Main;
+ Song[i].Visible := (Ini.Tabs=1) = Song[i].Main;
CatNumShow := -1;
end;
Result := 0;