From a0ff0b75e3562e04f17f11fc41f2e49040d620c5 Mon Sep 17 00:00:00 2001 From: eddie-0815 Date: Thu, 8 Nov 2007 21:02:07 +0000 Subject: Added UPlatform.pas. This should be the first step to move the simple platform specific code to one file for each platform to reduce the IFDEFs in the remaining files. The first available function is a unicode capable DirectoryFindFiles. It is now used in the BrowseDir function in file USongs.pas. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@595 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UMain.pas | 3 - Game/Code/Classes/UPlatform.pas | 56 +++++++++ Game/Code/Classes/UPlatformLinux.pas | 66 ++++++++++ Game/Code/Classes/UPlatformMacOSX.pas | 66 ++++++++++ Game/Code/Classes/UPlatformWindows.pas | 58 +++++++++ Game/Code/Classes/USongs.pas | 222 ++++++--------------------------- 6 files changed, 284 insertions(+), 187 deletions(-) create mode 100644 Game/Code/Classes/UPlatform.pas create mode 100644 Game/Code/Classes/UPlatformLinux.pas create mode 100644 Game/Code/Classes/UPlatformMacOSX.pas create mode 100644 Game/Code/Classes/UPlatformWindows.pas (limited to 'Game/Code/Classes') diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas index f25eaa87..c11b68d9 100644 --- a/Game/Code/Classes/UMain.pas +++ b/Game/Code/Classes/UMain.pas @@ -12,9 +12,6 @@ uses {$IFDEF MSWINDOWS} Windows, {$ENDIF} - {$IFDEF DARWIN} // needed for initialization of cthreads - cthreads, - {$ENDIF} SDL, UGraphic, UMusic, diff --git a/Game/Code/Classes/UPlatform.pas b/Game/Code/Classes/UPlatform.pas new file mode 100644 index 00000000..cc971bed --- /dev/null +++ b/Game/Code/Classes/UPlatform.pas @@ -0,0 +1,56 @@ +unit UPlatform; + +// Comment by Eddie: +// This unit defines an interface for platform specific utility functions. +// The Interface is implemented in separate files for each platform: +// UPlatformWindows, UPlatformLinux and UPlatformWindows. + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses Classes; + +type + + TDirectoryEntry = Record + Name : WideString; + IsDirectory : Boolean; + IsFile : Boolean; + end; + + TDirectoryEntryArray = Array of TDirectoryEntry; + + IPlatform = interface + + // DirectoryFindFiles returns all files matching the filter. Do not use '*' in the filter. + // If you set ReturnAllSubDirs = true all directories will be returned, if yout set it to false + // directories are completely ignored. + Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; + end; + +var + Platform : IPlatform; + +implementation + +uses + {$IFDEF MSWINDOWS} + UPlatformWindows; + {$ENDIF} + {$IFDEF LINUX} + UPlatformLinux; + {$ENDIF} + {$IFDEF DARWIN} + UPlatformMacOSX; + {$ENDIF} + +initialization + + Platform := TPlatform.Create; + +end. diff --git a/Game/Code/Classes/UPlatformLinux.pas b/Game/Code/Classes/UPlatformLinux.pas new file mode 100644 index 00000000..1713df1c --- /dev/null +++ b/Game/Code/Classes/UPlatformLinux.pas @@ -0,0 +1,66 @@ +unit UPlatformLinux; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses Classes, UPlatform; + +type + + TPlatform = class(TInterfacedObject, IPlatform) + public + Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; + end; + +implementation + +uses SysUtils, oldlinux; + +Function TPlatform.DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; +var + i : Integer; + TheDir : oldlinux.pdir; + ADirent : oldlinux.pDirent; + Entry : Longint; + info : oldlinux.stat; + lAttrib : integer; +begin + i := 0; + Filter := LowerCase(Filter); + + TheDir := oldlinux.opendir( Dir ); + if Assigned(TheDir) then + repeat + ADirent := oldlinux.ReadDir(TheDir); + + If Assigned(ADirent) and (ADirent^.d_name <> '.') and (ADirent^.d_name <> '..') then + begin + lAttrib := FileGetAttr(Dir + ADirent^.d_name); + if ReturnAllSubDirs and ((lAttrib and faDirectory) <> 0) then + begin + SetLength( Result, i + 1); + Result[i].Name := ADirent^.d_name; + Result[i].IsDirectory := true; + Result[i].IsFile := false; + i := i + 1; + end + else if (Length(Filter) = 0) or (Pos( Filter, LowerCase(ADirent^.d_name)) > 0) then + begin + SetLength( Result, i + 1); + Result[i].Name := ADirent^.d_name; + Result[i].IsDirectory := false; + Result[i].IsFile := true; + i := i + 1; + end; + end; + Until ADirent = nil; + + oldlinux.CloseDir(TheDir); +end; + +end. diff --git a/Game/Code/Classes/UPlatformMacOSX.pas b/Game/Code/Classes/UPlatformMacOSX.pas new file mode 100644 index 00000000..56469299 --- /dev/null +++ b/Game/Code/Classes/UPlatformMacOSX.pas @@ -0,0 +1,66 @@ +unit UPlatformMacOSX; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses Classes, UPlatform; + +type + + TPlatform = class(TInterfacedObject, IPlatform) + public + Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; + end; + +implementation + +uses SysUtils, baseunix; + +Function TPlatform.DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; +var + i : Integer; + TheDir : pdir; + ADirent : pDirent; + Entry : Longint; + info : stat; + lAttrib : integer; +begin + i := 0; + Filter := LowerCase(Filter); + + TheDir := FPOpenDir(Dir); + if Assigned(TheDir) then + repeat + ADirent := FPReadDir(TheDir); + + If Assigned(ADirent) and (ADirent^.d_name <> '.') and (ADirent^.d_name <> '..') then + begin + lAttrib := FileGetAttr(Dir + ADirent^.d_name); + if ReturnAllSubDirs and ((lAttrib and faDirectory) <> 0) then + begin + SetLength( Result, i + 1); + Result[i].Name := ADirent^.d_name; + Result[i].IsDirectory := true; + Result[i].IsFile := false; + i := i + 1; + end + else if (Length(Filter) = 0) or (Pos( Filter, LowerCase(ADirent^.d_name)) > 0) then + begin + SetLength( Result, i + 1); + Result[i].Name := ADirent^.d_name; + Result[i].IsDirectory := false; + Result[i].IsFile := true; + i := i + 1; + end; + end; + Until ADirent = nil; + + FPCloseDir(TheDir); +end; + +end. diff --git a/Game/Code/Classes/UPlatformWindows.pas b/Game/Code/Classes/UPlatformWindows.pas new file mode 100644 index 00000000..eb432335 --- /dev/null +++ b/Game/Code/Classes/UPlatformWindows.pas @@ -0,0 +1,58 @@ +unit UPlatformWindows; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses Classes, UPlatform; + +type + + TPlatform = class(TInterfacedObject, IPlatform) + public + Function DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; + end; + +implementation + +uses SysUtils, Windows; + +Function TPlatform.DirectoryFindFiles(Dir, Filter : WideString; ReturnAllSubDirs : Boolean) : TDirectoryEntryArray; +var + i : Integer; + SR : TSearchRecW; +begin + i := 0; + Filter := LowerCase(Filter); + + if ReturnAllSubDirs then begin + if FindFirstW(Dir + '*', faDirectory, SR) = 0 then + repeat + if (SR.Name <> '.') and (SR.Name <> '..') then + begin + SetLength( Result, i + 1); + Result[i].Name := SR.Name; + Result[i].IsDirectory := true; + Result[i].IsFile := false; + i := i + 1; + end; + until FindNextW(SR) <> 0; + FindCloseW(SR); + end; + + if FindFirstW(Dir + '*' + Filter, 0, SR) = 0 then + repeat + SetLength( Result, i + 1); + Result[i].Name := SR.Name; + Result[i].IsDirectory := true; + Result[i].IsFile := false; + i := i + 1; + until FindNextW(SR) <> 0; + FindCloseW(SR); +end; + +end. diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas index 9b9ab7bb..dcca08bd 100644 --- a/Game/Code/Classes/USongs.pas +++ b/Game/Code/Classes/USongs.pas @@ -30,6 +30,7 @@ uses {$ENDIF} SysUtils, Classes, + UPlatform, ULog, UTexture, UCommon, @@ -299,198 +300,51 @@ begin 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; - lAttrib : integer; - {$ENDIF} + i : Integer; + Files : TDirectoryEntryArray; 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 assigned(ADirent) and (ADirent^.d_name <> '.') and (ADirent^.d_name <> '..') then - begin - lAttrib := FileGetAttr(Dir + ADirent^.d_name); - if (lAttrib and faDirectory) <> 0 then - begin - //Log.LogError('Entering dir "' + Dir + ADirent^.d_name + PathDelim + '" now.'); - BrowseDir(Dir + ADirent^.d_name + PathDelim); - end - else if Pos( '.txt', LowerCase(ADirent^.d_name)) > 0 then - begin - SLen := BrowsePos; - - try - Song[SLen].Path := Dir; - Song[SLen].Folder := Copy(String(Dir), Length(String(SongPath))+1, 10000); - Song[SLen].Folder := Copy(String(Song[SLen].Folder), 1, Pos( PathDelim , Song[SLen].Folder)-1); - Song[SLen].FileName := ADirent^.d_name; - //Log.LogError( 'Song: ' + ADirent^.d_name + ', Length(Song) = ' + inttostr(Length(Song)) + ', BrowsePos = ' + IntToStr(BrowsePos) + ', Dir = "' + Dir + '"'); - - if (AnalyseFile(Song[SLen]) = false) then - begin - Log.LogError('AnalyseFile failed for "' + ADirent^.d_name + '".'); - Dec(BrowsePos); - end - else - begin - if Song[SLen].Cover = '' then - Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg'); - end; - except - 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; - end; - - Until ADirent=Nil; - - if (FPCloseDir(TheDir) <> 0) then + 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 - Log.LogError('TSongs.BrowseDir: Exception: Error closing dir: "' + Dir + '".') + SLen := BrowsePos; + + Song[SLen].Path := Dir; + Song[SLen].Folder := Copy(String(Dir), Length(String(SongPath))+1, 10000); + Song[SLen].Folder := Copy(String(Song[SLen].Folder), 1, Pos( PathDelim , Song[SLen].Folder)-1); + Song[SLen].FileName := Files[i].Name; + + if (AnalyseFile(Song[SLen]) = false) then + begin + Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".'); + Dec(BrowsePos); + end + 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; - end; + end; + SetLength( Files, 0); - {$endif} - // Log.LogStatus('Parsing directory: ' + Dir + SR.Name, 'LoadSongList'); - - end; procedure TSongs.Sort(Order: integer); -- cgit v1.2.3