unit USongs;
interface
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
{$I switches.inc}
uses
{$IFDEF MSWINDOWS}
Windows,
{$ifdef Delphi}
DirWatch,
{$endif}
{$ELSE}
{$IFNDEF DARWIN}
oldlinux,
syscall,
{$ENDIF}
baseunix,
UnixType,
{$ENDIF}
SysUtils,
Classes,
ULog,
UTexture,
UCommon,
UCatCovers;
type
TBPM = record
BPM: real;
StartBeat: real;
end;
TScore = record
Name: widestring;
Score: integer;
Length: string;
end;
TSong = record
Path: widestring;
Folder: widestring; // for sorting by folder
FileName: widestring;
// sorting methods
Category: array of widestring; // I think I won't need this
Genre: widestring;
Edition: widestring;
Language: widestring; // 0.5.0: new
Title: widestring;
Artist: widestring;
Text: widestring;
Creator: widestring;
Cover: widestring;
CoverTex: TTexture;
Mp3: widestring;
Background: widestring;
Video: widestring;
VideoGAP: real;
VideoLoaded: boolean; // 0.5.0: true if the video has been loaded
NotesGAP: integer;
Start: real; // in seconds
Finish: integer; // in miliseconds
Relative: boolean;
Resolution: integer;
BPM: array of TBPM;
GAP: real; // in miliseconds
Score: array[0..2] of array of TScore;
// these are used when sorting is enabled
Visible: boolean; // false if hidden, true if visible
Main: boolean; // false for songs, true for category buttons
OrderNum: integer; // has a number of category for category buttons and songs
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
end;
TSongs = class( TThread )
private
BrowsePos : Cardinal; //Actual Pos in Song Array
fNotify ,
fWatch : longint;
fParseSongDirectory : boolean;
fProcessing : boolean;
{$ifdef Delphi}
fDirWatch : TDirectoryWatch;
{$endif}
procedure int_LoadSongList;
procedure DoDirChanged(Sender: TObject);
protected
procedure Execute; override;
public
Song : array of TSong; // array of songs
Selected : integer; // selected song index
constructor create();
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
AktSong: TSong; // one song *unknown use)
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
inherited create( false );
self.freeonterminate := true;
{$ifdef Delphi}
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}
Setlength(Song, 0);
end;
procedure TSongs.DoDirChanged(Sender: TObject);
begin
LoadSongList();
end;
procedure TSongs.Execute();
var
fChangeNotify : THandle;
begin
fParseSongDirectory := true;
while not self.terminated do
begin
if fParseSongDirectory then
begin
writeln( 'int_LoadSongList' );
int_LoadSongList();
end;
self.suspend;
end;
end;
procedure TSongs.int_LoadSongList;
begin
try
fProcessing := true;
Setlength(Song, 0);
Log.LogError('SongList', 'Searching For Songs');
Setlength(Song, 50);
BrowsePos := 0;
// browse directories
BrowseDir(SongPath);
//Set Correct SongArray Length
SetLength(Song, BrowsePos);
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;
// TODO : JB - THis whole function SUX ! and needs refactoring ! :P
procedure TSongs.BrowseDir(Dir: widestring);
var
SLen: integer;
{$ifdef Delphi}
SR: TSearchRecW; // for parsing Songs Directory
{$ENDIF}
// eddie: can we merge that? is baseunix working on linux? oldlinux is
// not available on mac os x.
{$IFDEF LINUX}
TheDir : oldlinux.pdir;
ADirent : oldlinux.pDirent;
Entry : Longint;
info : oldlinux.stat;
{$ENDIF}
{$IFDEF DARWIN}
TheDir : pdir;
ADirent : pDirent;
Entry : Longint;
info : stat;
{$ENDIF}
begin
{$ifdef Delphi}
if FindFirstW(Dir + '*', faDirectory, SR) = 0 then // JB_Unicode - windows
begin
repeat
if (SR.Name <> '.') and (SR.Name <> '..') then
begin
BrowseDir(Dir + Sr.Name + PathDelim);
end
until FindNextw(SR) <> 0;
end; // if
FindClosew(SR);
if FindFirstW(Dir + '*.txt', 0, SR) = 0 then
begin
repeat
SLen := BrowsePos;
Song[SLen].Path := Dir;
Song[SLen].Folder := Copy(Dir, Length(SongPath)+1, 10000);
Song[SLen].Folder := Copy(Song[SLen].Folder, 1, Pos( PathDelim , Song[SLen].Folder)-1);
Song[SLen].FileName := SR.Name;
if (AnalyseFile(Song[SLen]) = false) then
Dec(BrowsePos)
else
begin
if Song[SLen].Cover = '' then
Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg');
end;
//Change Length Only every 50 Entrys
Inc(BrowsePos);
if (BrowsePos mod 50 = 0) AND (BrowsePos <> 0) then
begin
SetLength(Song, Length(Song) + 50);
end;
until FindNextW(SR) <> 0;
end; // if FindFirst
FindCloseW(SR);
{$ENDIF}
{$IFDEF LINUX}
// Itterate the Songs Directory... ( With unicode capable functions for linux )
TheDir := oldlinux.opendir( Dir ); // JB_Unicode - linux
if TheDir <> nil then
begin
repeat
ADirent := oldlinux.ReadDir(TheDir);
If ADirent<>Nil then
begin
With ADirent^ do
begin
if ( name[0] <> '.') then
BrowseDir( Dir + name + pathdelim );
end;
end;
Until ADirent=Nil;
end;
TheDir := oldlinux.opendir( Dir ); // JB_Unicode - linux
if TheDir <> nil then
begin
repeat
ADirent := oldlinux.ReadDir(TheDir);
if ( ADirent <> Nil ) AND
( pos( '.txt', ADirent^.name ) > 0 ) then
begin
writeln ('***** FOUND TXT' + ADirent^.name );
SLen := BrowsePos;
Song[SLen].Path := Dir;
Song[SLen].Folder := Copy(Dir, Length(SongPath)+1, 10000);
Song[SLen].Folder := Copy(Song[SLen].Folder, 1, Pos( PathDelim , Song[SLen].Folder)-1);
Song[SLen].FileName := ADirent^.name;
if (AnalyseFile(Song[SLen]) = false) then
Dec(BrowsePos)
else
begin
if Song[SLen].Cover = '' then
Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg');
end;
//Change Length Only every 50 Entrys
Inc(BrowsePos);
if (BrowsePos mod 50 = 0) AND (BrowsePos <> 0) then
begin
SetLength(Song, Length(Song) + 50);
end;
end;
Until ADirent=Nil;
end; // if FindFirst
{$endif}
{$IFDEF DARWIN}
// Itterate the Songs Directory... ( With unicode capable functions for linux )
TheDir := FPOpenDir( Dir ); // JB_Unicode - linux
if TheDir <> nil then
begin
repeat
ADirent := FPReadDir(TheDir);
If ADirent<>Nil then
begin
With ADirent^ do
begin
if ( d_name[0] <> '.') then
BrowseDir( Dir + d_name + pathdelim );
end;
end;
Until ADirent=Nil;
end;
TheDir := FPOpenDir( Dir ); // JB_Unicode - linux
if TheDir <> nil then
begin
repeat
ADirent := FPReadDir(TheDir);
if ( ADirent <> Nil ) AND
( pos( '.txt', ADirent^.d_name ) > -1 ) then
begin
SLen := BrowsePos;
Song[SLen].Path := Dir;
Song[SLen].Folder := Copy(Dir, Length(SongPath)+1, 10000);
Song[SLen].Folder := Copy(Song[SLen].Folder, 1, Pos( PathDelim , Song[SLen].Folder)-1);
Song[SLen].FileName := ADirent^.d_name;
if (AnalyseFile(Song[SLen]) = false) then
Dec(BrowsePos)
else
begin
if Song[SLen].Cover = '' then
Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg');
end;
//Change Length Only every 50 Entrys
Inc(BrowsePos);
if (BrowsePos mod 50 = 0) AND (BrowsePos <> 0) then
begin
SetLength(Song, Length(Song) + 50);
end;
end;
Until ADirent=Nil;
end; // if FindFirst
{$endif}
// Log.LogStatus('Parsing directory: ' + Dir + SR.Name, 'LoadSongList');
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 Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Edition, Song[S-1].Edition) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sGenre: // by genre
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Genre, Song[S-1].Genre) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sTitle: // by title
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Title, Song[S-1].Title) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sArtist: // by artist
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Artist, Song[S-1].Artist) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sFolder: // by folder
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Folder, Song[S-1].Folder) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sTitle2: // by title2
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Title, Song[S-1].Title) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sArtist2: // by artist2
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Artist, Song[S-1].Artist) < 0 then begin
// zamiana miejscami
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[S] := TempSong;
end;
end;
sLanguage: // by Language
begin
for S2 := 0 to Length(Song)-1 do
for S := 1 to Length(Song)-1 do
if CompareText(Song[S].Language, Song[S-1].Language) < 0 then begin
TempSong := Song[S-1];
Song[S-1] := Song[S];
Song[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 := Low(Songs.Song) to High(Songs.Song) do begin
if (Ini.Tabs = 1) then
if (Ini.Sorting = sEdition) and (CompareText(SS, Songs.Song[S].Edition) <> 0) then begin
// add Category Button
Inc(Order);
SS := Songs.Song[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, Songs.Song[S].Genre) <> 0) then begin
// add Genre Button
Inc(Order);
SS := Songs.Song[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, Songs.Song[S].Language) <> 0) then begin
// add Language Button
Inc(Order);
SS := Songs.Song[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(Songs.Song[S].Title)>=1) and
(Letter <> UpperCase(Songs.Song[S].Title)[1]) then begin
// add a letter Category Button
Inc(Order);
Letter := Uppercase(Songs.Song[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(Songs.Song[S].Artist)>=1) and (Letter <> UpperCase(Songs.Song[S].Artist)[1]) then begin
// add a letter Category Button
Inc(Order);
Letter := UpperCase(Songs.Song[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, Songs.Song[S].Folder) <> 0) then begin
// 0.5.0: add folder tab
Inc(Order);
SS := Songs.Song[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(Songs.Song[S].Title)>=1) then begin
if (ord(Songs.Song[S].Title[1]) > 47) and (ord(Songs.Song[S].Title[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(Songs.Song[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(Songs.Song[S].Artist)>=1) then begin
if (ord(Songs.Song[S].Artist[1]) > 47) and (ord(Songs.Song[S].Artist[1]) < 58) then Letter2 := '#' else Letter2 := UpperCase(Songs.Song[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] := Songs.Song[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.