aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes/USongs.pas
diff options
context:
space:
mode:
Diffstat (limited to 'Game/Code/Classes/USongs.pas')
-rw-r--r--Game/Code/Classes/USongs.pas1779
1 files changed, 893 insertions, 886 deletions
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas
index 97e8d073..b502f703 100644
--- a/Game/Code/Classes/USongs.pas
+++ b/Game/Code/Classes/USongs.pas
@@ -1,886 +1,893 @@
-unit USongs;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-{$IFDEF DARWIN}
- {$IFDEF DEBUG}
- {$DEFINE USE_PSEUDO_THREAD}
- {$ENDIF}
-{$ENDIF}
-
-uses
- {$IFDEF MSWINDOWS}
- Windows,
- DirWatch,
- {$ELSE}
- {$IFNDEF DARWIN}
- syscall,
- {$ENDIF}
- baseunix,
- UnixType,
- {$ENDIF}
- SysUtils,
- Classes,
- UPlatform,
- ULog,
- UTexture,
- UCommon,
- {$IFDEF DARWIN}
- cthreads,
- {$ENDIF}
- {$IFDEF USE_PSEUDO_THREAD}
- PseudoThread,
- {$ENDIF}
- USong,
- UCatCovers;
-
-type
-
- TBPM = record
- BPM: real;
- StartBeat: real;
- end;
-
- TScore = record
- Name: widestring;
- Score: integer;
- Length: string;
- end;
-
-
- {$IFDEF USE_PSEUDO_THREAD}
- TSongs = class( TPseudoThread )
- {$ELSE}
- TSongs = class( TThread )
- {$ENDIF}
- private
- fNotify ,
- fWatch : longint;
- fParseSongDirectory : boolean;
- fProcessing : boolean;
- {$ifdef MSWINDOWS}
- fDirWatch : TDirectoryWatch;
- {$endif}
- procedure int_LoadSongList;
- procedure DoDirChanged(Sender: TObject);
- protected
- procedure Execute; override;
- public
-// Song : array of TSong; // array of songs
- SongList : TList; // array of songs
- Selected : integer; // selected song index
- constructor create();
- destructor destroy(); override;
-
-
- procedure LoadSongList; // load all songs
- procedure BrowseDir(Dir: widestring); // should return number of songs in the future
- procedure Sort(Order: integer);
- function FindSongFile(Dir, Mask: widestring): widestring;
- property Processing : boolean read fProcessing;
- end;
-
-
- TCatSongs = class
- Song: array of TSong; // array of categories with songs
- Selected: integer; // selected song index
- Order: integer; // order type (0=title)
- CatNumShow: integer; // Category Number being seen
- CatCount: integer; //Number of Categorys
-
- 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
- procedure ShowCategoryList; //Hides all Songs And Show the List of all Categorys
- function FindNextVisible(SearchFrom:integer): integer; //Find Next visible Song
- function VisibleSongs: integer; // returns number of visible songs (for tabs)
- function VisibleIndex(Index: integer): integer; // returns visible song index (skips invisible)
-
- function SetFilter(FilterStr: String; const fType: Byte): Cardinal;
- end;
-
-var
- Songs: TSongs; // all songs
- CatSongs: TCatSongs; // categorized songs
-
-const
- IN_ACCESS = $00000001; //* File was accessed */
- IN_MODIFY = $00000002; //* File was modified */
- IN_ATTRIB = $00000004; //* Metadata changed */
- IN_CLOSE_WRITE = $00000008; //* Writtable file was closed */
- IN_CLOSE_NOWRITE = $00000010; //* Unwrittable file closed */
- IN_OPEN = $00000020; //* File was opened */
- IN_MOVED_FROM = $00000040; //* File was moved from X */
- IN_MOVED_TO = $00000080; //* File was moved to Y */
- IN_CREATE = $00000100; //* Subfile was created */
- IN_DELETE = $00000200; //* Subfile was deleted */
- IN_DELETE_SELF = $00000400; //* Self was deleted */
-
-
-implementation
-
-uses StrUtils,
- UGraphic,
- UCovers,
- UFiles,
- UMain,
- UIni;
-
-{$IFDEF DARWIN}
-function AnsiContainsText(const AText, ASubText: string): Boolean;
-begin
- Result := AnsiPos(AnsiUppercase(ASubText), AnsiUppercase(AText)) > 0;
-end;
-{$ENDIF}
-
-constructor TSongs.create();
-begin
- // do not start thread BEFORE initialization (suspended = true)
- inherited create( true );
- self.freeonterminate := true;
-
- SongList := TList.create();
-
- {$ifdef MSWINDOWS}
- fDirWatch := TDirectoryWatch.create(nil);
- fDirWatch.OnChange := DoDirChanged;
- fDirWatch.Directory := SongPath;
- fDirWatch.WatchSubDirs := true;
- fDirWatch.active := true;
- {$ENDIF}
-
- {$IFDEF linux}
- (*
- Thankyou to : http://www.linuxjournal.com/article/8478
- http://www.tin.org/bin/man.cgi?section=2&topic=inotify_add_watch
- *)
-(*
- fNotify := -1;
- fWatch := -1;
-
- writeln( 'Calling inotify_init' );
- fNotify := Do_SysCall( syscall_nr_inotify_init );
- if ( fNotify < 0 ) then
- writeln( 'Filesystem change notification - disabled' );
- writeln( 'Calling inotify_init : '+ inttostr(fNotify) );
-
- writeln( 'Calling syscall_nr_inotify_init ('+SongPath+')' );
- fWatch := Do_SysCall( syscall_nr_inotify_init , TSysParam( fNotify ), longint( pchar( SongPath ) ) , IN_MODIFY AND IN_CREATE AND IN_DELETE );
-
- if (fWatch < 0) then
- writeln ('inotify_add_watch');
- writeln( 'Calling syscall_nr_inotify_init : '+ inttostr(fWatch) );
-*)
- {$endif}
-
- // now we can start the thread
- Resume();
-end;
-
-destructor TSongs.destroy();
-begin
- freeandnil( SongList );
-end;
-
-procedure TSongs.DoDirChanged(Sender: TObject);
-begin
- LoadSongList();
-end;
-
-procedure TSongs.Execute();
-var
- fChangeNotify : THandle;
-begin
-{$IFDEF USE_PSEUDO_THREAD}
- int_LoadSongList();
-{$ELSE}
- fParseSongDirectory := true;
-
- while not self.terminated do
- begin
-
- if fParseSongDirectory then
- begin
- writeln( 'int_LoadSongList' );
- int_LoadSongList();
- end;
-
- self.suspend;
- end;
-{$ENDIF}
-end;
-
-procedure TSongs.int_LoadSongList;
-begin
- try
- fProcessing := true;
-
- Log.LogError('SongList', 'Searching For Songs');
-
- // browse directories
- BrowseDir(SongPath);
-
- if UserSongPath <> SongPath then
- BrowseDir(UserSongPath);
-
- if assigned( CatSongs ) then
- CatSongs.Refresh;
-
- if assigned( CatCovers ) then
- CatCovers.Load;
-
- if assigned( Covers ) then
- Covers.Load;
-
- if assigned(ScreenSong) then
- begin
- ScreenSong.GenerateThumbnails();
- ScreenSong.OnShow; // refresh ScreenSong
- end;
-
- finally
- Log.LogError('SongList', 'Search Complete');
-
- fParseSongDirectory := false;
- fProcessing := false;
- end;
-end;
-
-
-procedure TSongs.LoadSongList;
-begin
- fParseSongDirectory := true;
- self.resume;
-end;
-
-procedure TSongs.BrowseDir(Dir: widestring);
-var
- i : Integer;
- Files : TDirectoryEntryArray;
- lSong : TSong;
-begin
-
- Files := Platform.DirectoryFindFiles( Dir, '.txt', true);
-
- for i := 0 to Length(Files)-1 do
- begin
- if Files[i].IsDirectory then
- begin
- BrowseDir( Dir + Files[i].Name + PathDelim );
- end
- else
- begin
- lSong := TSong.create( Dir + Files[i].Name );
-
- if NOT lSong.Analyse then
- begin
- Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
- freeandnil( lSong );
- end
- else
- begin
- SongList.add( lSong );
- end;
-
- end;
- end;
- SetLength( Files, 0);
-end;
-
-procedure TSongs.Sort(Order: integer);
-var
- S: integer;
- S2: integer;
- TempSong: TSong;
-begin
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
-
- end; // case
-end;
-
-function TSongs.FindSongFile(Dir, Mask: widestring): widestring;
-var
- SR: TSearchRec; // for parsing song directory
-begin
- Result := '';
- if FindFirst(Dir + Mask, faDirectory, SR) = 0 then begin
- Result := SR.Name;
- end; // if
- 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
-begin
- CatNumShow := -1;
-// Songs.Sort(0); // by title
-
-case Ini.Sorting of
- sEdition: begin
- Songs.Sort(sArtist);
- Songs.Sort(sEdition);
- end;
- sGenre: begin
- 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
-
- end; // case
-
-
- Letter := ' ';
- SS := '';
- Order := 0;
- CatNumber := 0;
-
- //Songs leeren
- SetLength (Song, 0);
-
- for S := 0 to Songs.SongList.Count-1 do
- begin
- 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
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
-
- CatSongs.Song[CatLen].Visible := true;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
-
- CatSongs.Song[CatLen].Visible := true;
- 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
- begin
- Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
- CatNumber := 0;
- end;
-
- CatSongs.Song[CatLen].Visible := true;
- end;
- end;
-
-
- CatLen := Length(CatSongs.Song);
- SetLength(CatSongs.Song, CatLen+1);
-
- Inc (CatNumber); //Increase Number in Cat
-
- CatSongs.Song[CatLen] := TSong( Songs.SongList[S] );
- CatSongs.Song[CatLen].OrderNum := Order; // assigns category
- CatSongs.Song[CatLen].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;
-
- 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;
-end;
-
-procedure TCatSongs.ShowCategory(Index: integer);
-var
- S: integer; // song
-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
- CatSongs.Song[S].Visible := true
- else
- CatSongs.Song[S].Visible := false;
- end;
-end;
-
-procedure TCatSongs.HideCategory(Index: integer); // hides all songs in category
-var
- S: integer; // song
-begin
- for S := 0 to high(CatSongs.Song) do begin
- if not CatSongs.Song[S].Main then
- CatSongs.Song[S].Visible := false // hides all at now
- end;
-end;
-
-procedure TCatSongs.ClickCategoryButton(Index: integer);
-var
- Num, S: integer;
-begin
- Num := CatSongs.Song[Index].OrderNum;
- if Num <> CatNumShow then
- begin
- ShowCategory(Num);
- end
- else begin
- ShowCategoryList;
- end;
-end;
-
-//Hide Categorys when in Category Hack
-procedure TCatSongs.ShowCategoryList;
-var
- Num, S: integer;
-begin
- //Hide All Songs Show All Cats
- for S := 0 to high(CatSongs.Song) do begin
- if CatSongs.Song[S].Main then
- CatSongs.Song[S].Visible := true
- else
- CatSongs.Song[S].Visible := false
- end;
- CatSongs.Selected := CatNumShow; //Show last shown Category
- CatNumShow := -1;
-end;
-//Hide Categorys when in Category Hack End
-
-//Wrong song selected when tabs on bug
-function TCatSongs.FindNextVisible(SearchFrom:integer): integer;//Find next Visible Song
-var
- I: Integer;
- begin
- Result := -1;
- I := SearchFrom + 1;
- while not CatSongs.Song[I].Visible do
- 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;
-//Wrong song selected when tabs on bug End
-
-function TCatSongs.VisibleSongs: integer;
-var
- S: integer; // song
-begin
- Result := 0;
- for S := 0 to high(CatSongs.Song) do
- if CatSongs.Song[S].Visible = true then Inc(Result);
-end;
-
-function TCatSongs.VisibleIndex(Index: integer): integer;
-var
- S: integer; // song
-begin
- Result := 0;
- for S := 0 to Index-1 do
- if CatSongs.Song[S].Visible = true then Inc(Result);
-end;
-
-function TCatSongs.SetFilter(FilterStr: String; const fType: Byte): Cardinal;
-var
- I, J: Integer;
- cString: String;
- SearchStr: Array of String;
-begin
- {fType: 0: All
- 1: Title
- 2: Artist}
- FilterStr := Trim(FilterStr);
- if FilterStr<>'' then begin
- Result := 0;
- //Create Search Array
- SetLength(SearchStr, 1);
- I := Pos (' ', FilterStr);
- While (I <> 0) do
- begin
- SetLength (SearchStr, Length(SearchStr) + 1);
- cString := Copy(FilterStr, 1, I-1);
- 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
- SearchStr[High(SearchStr)] := FilterStr;
-
- for I:=0 to High(Song) do begin
- if not Song[i].Main then
- begin
- case fType of
- 0: cString := Song[I].Artist + ' ' + Song[i].Title + ' ' + Song[i].Folder;
- 1: cString := Song[I].Title;
- 2: cString := Song[I].Artist;
- end;
- Song[i].Visible:=True;
- //Look for every Searched Word
- For J := 0 to High(SearchStr) do
- begin
- Song[i].Visible := Song[i].Visible AND AnsiContainsText(cString, SearchStr[J])
- end;
- if Song[i].Visible then
- Inc(Result);
- end
- else
- Song[i].Visible:=False;
- end;
- CatNumShow := -2;
- end
- else begin
- for i:=0 to High(Song) do begin
- Song[i].Visible:=(Ini.Tabs=1)=Song[i].Main;
- CatNumShow := -1;
- end;
- Result := 0;
- end;
-end;
-
-
-
-// -----------------------------------------------------------------------------
-
-
-
-
-end.
+unit USongs;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+{$IFDEF DARWIN}
+ {$IFDEF DEBUG}
+ {$DEFINE USE_PSEUDO_THREAD}
+ {$ENDIF}
+{$ENDIF}
+
+uses
+ {$IFDEF MSWINDOWS}
+ Windows,
+ DirWatch,
+ {$ELSE}
+ {$IFNDEF DARWIN}
+ syscall,
+ {$ENDIF}
+ baseunix,
+ UnixType,
+ {$ENDIF}
+ SysUtils,
+ Classes,
+ UPlatform,
+ ULog,
+ UTexture,
+ UCommon,
+ {$IFDEF DARWIN}
+ cthreads,
+ {$ENDIF}
+ {$IFDEF USE_PSEUDO_THREAD}
+ PseudoThread,
+ {$ENDIF}
+ USong,
+ UCatCovers;
+
+type
+
+ TBPM = record
+ BPM: real;
+ StartBeat: real;
+ end;
+
+ TScore = record
+ Name: widestring;
+ Score: integer;
+ Length: string;
+ end;
+
+
+ {$IFDEF USE_PSEUDO_THREAD}
+ TSongs = class( TPseudoThread )
+ {$ELSE}
+ TSongs = class( TThread )
+ {$ENDIF}
+ private
+ fNotify ,
+ fWatch : longint;
+ fParseSongDirectory : boolean;
+ fProcessing : boolean;
+ {$ifdef MSWINDOWS}
+ fDirWatch : TDirectoryWatch;
+ {$endif}
+ procedure int_LoadSongList;
+ procedure DoDirChanged(Sender: TObject);
+ protected
+ procedure Execute; override;
+ public
+// Song : array of TSong; // array of songs
+ SongList : TList; // array of songs
+ Selected : integer; // selected song index
+ constructor create();
+ destructor destroy(); override;
+
+
+ procedure LoadSongList; // load all songs
+ procedure BrowseDir(Dir: widestring); // should return number of songs in the future
+ procedure Sort(Order: integer);
+ function FindSongFile(Dir, Mask: widestring): widestring;
+ property Processing : boolean read fProcessing;
+ end;
+
+
+ TCatSongs = class
+ Song: array of TSong; // array of categories with songs
+ Selected: integer; // selected song index
+ Order: integer; // order type (0=title)
+ CatNumShow: integer; // Category Number being seen
+ CatCount: integer; //Number of Categorys
+
+ 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
+ procedure ShowCategoryList; //Hides all Songs And Show the List of all Categorys
+ function FindNextVisible(SearchFrom:integer): integer; //Find Next visible Song
+ function VisibleSongs: integer; // returns number of visible songs (for tabs)
+ function VisibleIndex(Index: integer): integer; // returns visible song index (skips invisible)
+
+ function SetFilter(FilterStr: String; const fType: Byte): Cardinal;
+ end;
+
+var
+ Songs: TSongs; // all songs
+ CatSongs: TCatSongs; // categorized songs
+
+const
+ IN_ACCESS = $00000001; //* File was accessed */
+ IN_MODIFY = $00000002; //* File was modified */
+ IN_ATTRIB = $00000004; //* Metadata changed */
+ IN_CLOSE_WRITE = $00000008; //* Writtable file was closed */
+ IN_CLOSE_NOWRITE = $00000010; //* Unwrittable file closed */
+ IN_OPEN = $00000020; //* File was opened */
+ IN_MOVED_FROM = $00000040; //* File was moved from X */
+ IN_MOVED_TO = $00000080; //* File was moved to Y */
+ IN_CREATE = $00000100; //* Subfile was created */
+ IN_DELETE = $00000200; //* Subfile was deleted */
+ IN_DELETE_SELF = $00000400; //* Self was deleted */
+
+
+implementation
+
+uses StrUtils,
+ UGraphic,
+ UCovers,
+ UFiles,
+ UMain,
+ UIni;
+
+{$IFDEF DARWIN}
+function AnsiContainsText(const AText, ASubText: string): Boolean;
+begin
+ Result := AnsiPos(AnsiUppercase(ASubText), AnsiUppercase(AText)) > 0;
+end;
+{$ENDIF}
+
+constructor TSongs.create();
+begin
+ // do not start thread BEFORE initialization (suspended = true)
+ inherited create( true );
+ self.freeonterminate := true;
+
+ SongList := TList.create();
+
+ {$ifdef MSWINDOWS}
+ fDirWatch := TDirectoryWatch.create(nil);
+ fDirWatch.OnChange := DoDirChanged;
+ fDirWatch.Directory := SongPath;
+ fDirWatch.WatchSubDirs := true;
+ fDirWatch.active := true;
+ {$ENDIF}
+
+ {$IFDEF linux}
+ (*
+ Thankyou to : http://www.linuxjournal.com/article/8478
+ http://www.tin.org/bin/man.cgi?section=2&topic=inotify_add_watch
+ *)
+(*
+ fNotify := -1;
+ fWatch := -1;
+
+ writeln( 'Calling inotify_init' );
+ fNotify := Do_SysCall( syscall_nr_inotify_init );
+ if ( fNotify < 0 ) then
+ writeln( 'Filesystem change notification - disabled' );
+ writeln( 'Calling inotify_init : '+ inttostr(fNotify) );
+
+ writeln( 'Calling syscall_nr_inotify_init ('+SongPath+')' );
+ fWatch := Do_SysCall( syscall_nr_inotify_init , TSysParam( fNotify ), longint( pchar( SongPath ) ) , IN_MODIFY AND IN_CREATE AND IN_DELETE );
+
+ if (fWatch < 0) then
+ writeln ('inotify_add_watch');
+ writeln( 'Calling syscall_nr_inotify_init : '+ inttostr(fWatch) );
+*)
+ {$endif}
+
+ // now we can start the thread
+ Resume();
+end;
+
+destructor TSongs.destroy();
+begin
+ freeandnil( SongList );
+end;
+
+procedure TSongs.DoDirChanged(Sender: TObject);
+begin
+ LoadSongList();
+end;
+
+procedure TSongs.Execute();
+var
+ fChangeNotify : THandle;
+begin
+{$IFDEF USE_PSEUDO_THREAD}
+ int_LoadSongList();
+{$ELSE}
+ fParseSongDirectory := true;
+
+ while not self.terminated do
+ begin
+
+ if fParseSongDirectory then
+ begin
+ writeln( 'int_LoadSongList' );
+ int_LoadSongList();
+ end;
+
+ self.suspend;
+ end;
+{$ENDIF}
+end;
+
+procedure TSongs.int_LoadSongList;
+const
+ cUSNGPath = '/usr/share/games/ultrastar-ng/songs';
+begin
+ try
+ fProcessing := true;
+
+ Log.LogError('SongList', 'Searching For Songs');
+
+ // browse directories
+ BrowseDir(SongPath);
+
+ 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;
+
+ if assigned( CatCovers ) then
+ CatCovers.Load;
+
+ if assigned( Covers ) then
+ Covers.Load;
+
+ if assigned(ScreenSong) then
+ begin
+ ScreenSong.GenerateThumbnails();
+ ScreenSong.OnShow; // refresh ScreenSong
+ end;
+
+ finally
+ Log.LogError('SongList', 'Search Complete');
+
+ fParseSongDirectory := false;
+ fProcessing := false;
+ end;
+end;
+
+
+procedure TSongs.LoadSongList;
+begin
+ fParseSongDirectory := true;
+ self.resume;
+end;
+
+procedure TSongs.BrowseDir(Dir: widestring);
+var
+ i : Integer;
+ Files : TDirectoryEntryArray;
+ lSong : TSong;
+begin
+
+ Files := Platform.DirectoryFindFiles( Dir, '.txt', true);
+
+ for i := 0 to Length(Files)-1 do
+ begin
+ if Files[i].IsDirectory then
+ begin
+ BrowseDir( Dir + Files[i].Name + PathDelim );
+ end
+ else
+ begin
+ lSong := TSong.create( Dir + Files[i].Name );
+
+ if NOT lSong.Analyse then
+ begin
+ Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
+ freeandnil( lSong );
+ end
+ else
+ begin
+ SongList.add( lSong );
+ end;
+
+ end;
+ end;
+ SetLength( Files, 0);
+end;
+
+procedure TSongs.Sort(Order: integer);
+var
+ S: integer;
+ S2: integer;
+ TempSong: TSong;
+begin
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+
+ end; // case
+end;
+
+function TSongs.FindSongFile(Dir, Mask: widestring): widestring;
+var
+ SR: TSearchRec; // for parsing song directory
+begin
+ Result := '';
+ if FindFirst(Dir + Mask, faDirectory, SR) = 0 then begin
+ Result := SR.Name;
+ end; // if
+ 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
+begin
+ CatNumShow := -1;
+// Songs.Sort(0); // by title
+
+case Ini.Sorting of
+ sEdition: begin
+ Songs.Sort(sArtist);
+ Songs.Sort(sEdition);
+ end;
+ sGenre: begin
+ 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
+
+ end; // case
+
+
+ Letter := ' ';
+ SS := '';
+ Order := 0;
+ CatNumber := 0;
+
+ //Songs leeren
+ SetLength (Song, 0);
+
+ for S := 0 to Songs.SongList.Count-1 do
+ begin
+ 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
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ end;
+
+ CatSongs.Song[CatLen].Visible := true;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ end;
+
+ CatSongs.Song[CatLen].Visible := true;
+ 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
+ begin
+ Song[CatLen - CatNumber - 1].CatNumber := CatNumber;//Set CatNumber of Categroy
+ CatNumber := 0;
+ end;
+
+ CatSongs.Song[CatLen].Visible := true;
+ end;
+ end;
+
+
+ CatLen := Length(CatSongs.Song);
+ SetLength(CatSongs.Song, CatLen+1);
+
+ Inc (CatNumber); //Increase Number in Cat
+
+ CatSongs.Song[CatLen] := TSong( Songs.SongList[S] );
+ CatSongs.Song[CatLen].OrderNum := Order; // assigns category
+ CatSongs.Song[CatLen].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;
+
+ 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;
+end;
+
+procedure TCatSongs.ShowCategory(Index: integer);
+var
+ S: integer; // song
+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
+ CatSongs.Song[S].Visible := true
+ else
+ CatSongs.Song[S].Visible := false;
+ end;
+end;
+
+procedure TCatSongs.HideCategory(Index: integer); // hides all songs in category
+var
+ S: integer; // song
+begin
+ for S := 0 to high(CatSongs.Song) do begin
+ if not CatSongs.Song[S].Main then
+ CatSongs.Song[S].Visible := false // hides all at now
+ end;
+end;
+
+procedure TCatSongs.ClickCategoryButton(Index: integer);
+var
+ Num, S: integer;
+begin
+ Num := CatSongs.Song[Index].OrderNum;
+ if Num <> CatNumShow then
+ begin
+ ShowCategory(Num);
+ end
+ else begin
+ ShowCategoryList;
+ end;
+end;
+
+//Hide Categorys when in Category Hack
+procedure TCatSongs.ShowCategoryList;
+var
+ Num, S: integer;
+begin
+ //Hide All Songs Show All Cats
+ for S := 0 to high(CatSongs.Song) do begin
+ if CatSongs.Song[S].Main then
+ CatSongs.Song[S].Visible := true
+ else
+ CatSongs.Song[S].Visible := false
+ end;
+ CatSongs.Selected := CatNumShow; //Show last shown Category
+ CatNumShow := -1;
+end;
+//Hide Categorys when in Category Hack End
+
+//Wrong song selected when tabs on bug
+function TCatSongs.FindNextVisible(SearchFrom:integer): integer;//Find next Visible Song
+var
+ I: Integer;
+ begin
+ Result := -1;
+ I := SearchFrom + 1;
+ while not CatSongs.Song[I].Visible do
+ 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;
+//Wrong song selected when tabs on bug End
+
+function TCatSongs.VisibleSongs: integer;
+var
+ S: integer; // song
+begin
+ Result := 0;
+ for S := 0 to high(CatSongs.Song) do
+ if CatSongs.Song[S].Visible = true then Inc(Result);
+end;
+
+function TCatSongs.VisibleIndex(Index: integer): integer;
+var
+ S: integer; // song
+begin
+ Result := 0;
+ for S := 0 to Index-1 do
+ if CatSongs.Song[S].Visible = true then Inc(Result);
+end;
+
+function TCatSongs.SetFilter(FilterStr: String; const fType: Byte): Cardinal;
+var
+ I, J: Integer;
+ cString: String;
+ SearchStr: Array of String;
+begin
+ {fType: 0: All
+ 1: Title
+ 2: Artist}
+ FilterStr := Trim(FilterStr);
+ if FilterStr<>'' then begin
+ Result := 0;
+ //Create Search Array
+ SetLength(SearchStr, 1);
+ I := Pos (' ', FilterStr);
+ While (I <> 0) do
+ begin
+ SetLength (SearchStr, Length(SearchStr) + 1);
+ cString := Copy(FilterStr, 1, I-1);
+ 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
+ SearchStr[High(SearchStr)] := FilterStr;
+
+ for I:=0 to High(Song) do begin
+ if not Song[i].Main then
+ begin
+ case fType of
+ 0: cString := Song[I].Artist + ' ' + Song[i].Title + ' ' + Song[i].Folder;
+ 1: cString := Song[I].Title;
+ 2: cString := Song[I].Artist;
+ end;
+ Song[i].Visible:=True;
+ //Look for every Searched Word
+ For J := 0 to High(SearchStr) do
+ begin
+ Song[i].Visible := Song[i].Visible AND AnsiContainsText(cString, SearchStr[J])
+ end;
+ if Song[i].Visible then
+ Inc(Result);
+ end
+ else
+ Song[i].Visible:=False;
+ end;
+ CatNumShow := -2;
+ end
+ else begin
+ for i:=0 to High(Song) do begin
+ Song[i].Visible:=(Ini.Tabs=1)=Song[i].Main;
+ CatNumShow := -1;
+ end;
+ Result := 0;
+ end;
+end;
+
+
+
+// -----------------------------------------------------------------------------
+
+
+
+
+end.