aboutsummaryrefslogtreecommitdiffstats
path: root/unicode/src
diff options
context:
space:
mode:
Diffstat (limited to 'unicode/src')
-rw-r--r--unicode/src/base/TextGL.pas22
-rw-r--r--unicode/src/base/UCatCovers.pas114
-rw-r--r--unicode/src/base/UCommandLine.pas25
-rw-r--r--unicode/src/base/UCommon.pas82
-rw-r--r--unicode/src/base/UConfig.pas8
-rw-r--r--unicode/src/base/UCovers.pas51
-rw-r--r--unicode/src/base/UDLLManager.pas57
-rw-r--r--unicode/src/base/UDataBase.pas23
-rw-r--r--unicode/src/base/UFilename.pas464
-rw-r--r--unicode/src/base/UFiles.pas142
-rw-r--r--unicode/src/base/UFilesystem.pas2
-rw-r--r--unicode/src/base/UFont.pas47
-rw-r--r--unicode/src/base/UGraphic.pas22
-rw-r--r--unicode/src/base/UImage.pas63
-rw-r--r--unicode/src/base/UIni.pas179
-rw-r--r--unicode/src/base/ULanguage.pas31
-rw-r--r--unicode/src/base/ULog.pas22
-rw-r--r--unicode/src/base/UMain.pas8
-rw-r--r--unicode/src/base/UMusic.pas53
-rw-r--r--unicode/src/base/UPath.pas260
-rw-r--r--unicode/src/base/UPathUtils.pas120
-rw-r--r--unicode/src/base/UPlatform.pas95
-rw-r--r--unicode/src/base/UPlatformLinux.pas98
-rw-r--r--unicode/src/base/UPlatformMacOSX.pas92
-rw-r--r--unicode/src/base/UPlatformWindows.pas125
-rw-r--r--unicode/src/base/UPlaylist.pas250
-rw-r--r--unicode/src/base/USkins.pas77
-rw-r--r--unicode/src/base/USong.pas291
-rw-r--r--unicode/src/base/USongs.pas68
-rw-r--r--unicode/src/base/UTextEncoding.pas474
-rw-r--r--unicode/src/base/UTexture.pas45
-rw-r--r--unicode/src/base/UThemes.pas41
-rw-r--r--unicode/src/base/UUnicodeUtils.pas10
-rw-r--r--unicode/src/base/UXMLSong.pas86
-rw-r--r--unicode/src/lib/midi/MidiFile.pas26
-rw-r--r--unicode/src/media/UAudioCore_Bass.pas12
-rw-r--r--unicode/src/media/UAudioDecoder_Bass.pas21
-rw-r--r--unicode/src/media/UAudioDecoder_FFmpeg.pas39
-rw-r--r--unicode/src/media/UAudioInput_Bass.pas5
-rw-r--r--unicode/src/media/UAudioPlaybackBase.pas23
-rw-r--r--unicode/src/media/UAudioPlayback_Bass.pas6
-rw-r--r--unicode/src/media/UMedia_dummy.pas15
-rw-r--r--unicode/src/media/UVideo.pas19
-rw-r--r--unicode/src/menu/UDisplay.pas55
-rw-r--r--unicode/src/menu/UMenu.pas90
-rw-r--r--unicode/src/menu/UMenuBackgroundColor.pas144
-rw-r--r--unicode/src/menu/UMenuBackgroundFade.pas6
-rw-r--r--unicode/src/menu/UMenuBackgroundNone.pas138
-rw-r--r--unicode/src/menu/UMenuBackgroundTexture.pas7
-rw-r--r--unicode/src/menu/UMenuBackgroundVideo.pas11
-rw-r--r--unicode/src/screens/UScreenCredits.pas67
-rw-r--r--unicode/src/screens/UScreenEditConvert.pas11
-rw-r--r--unicode/src/screens/UScreenEditHeader.pas25
-rw-r--r--unicode/src/screens/UScreenEditSub.pas24
-rw-r--r--unicode/src/screens/UScreenOpen.pas19
-rw-r--r--unicode/src/screens/UScreenOptionsRecord.pas4
-rw-r--r--unicode/src/screens/UScreenOptionsThemes.pas4
-rw-r--r--unicode/src/screens/UScreenPartyOptions.pas26
-rw-r--r--unicode/src/screens/UScreenPartyScore.pas12
-rw-r--r--unicode/src/screens/UScreenPopup.pas8
-rw-r--r--unicode/src/screens/UScreenSing.pas30
-rw-r--r--unicode/src/screens/UScreenSingModi.pas22
-rw-r--r--unicode/src/screens/UScreenSong.pas27
-rw-r--r--unicode/src/screens/UScreenSongMenu.pas2
-rw-r--r--unicode/src/screens/UScreenStatMain.pas2
-rw-r--r--unicode/src/ultrastardx.dpr4
66 files changed, 1997 insertions, 2454 deletions
diff --git a/unicode/src/base/TextGL.pas b/unicode/src/base/TextGL.pas
index 65d716c2..7fe98d29 100644
--- a/unicode/src/base/TextGL.pas
+++ b/unicode/src/base/TextGL.pas
@@ -37,9 +37,10 @@ uses
gl,
glext,
SDL,
+ Classes,
UTexture,
UFont,
- Classes,
+ UPath,
ULog;
type
@@ -75,26 +76,26 @@ uses
UMain,
UPathUtils;
-function FindFontFile(FontIni: TCustomIniFile; Font: string): string;
+function FindFontFile(FontIni: TCustomIniFile; Font: string): IPath;
var
- Filename: string;
+ Filename: IPath;
begin
- Filename := FontIni.ReadString(Font, 'File', '');
- Result := FontPath + Filename;
+ Filename := Path(FontIni.ReadString(Font, 'File', ''));
+ Result := FontPath.Append(Filename);
// if path does not exist, try as an absolute path
- if (not FileExists(Result)) then
+ if (not Result.IsFile) then
Result := Filename;
end;
procedure BuildFont;
var
FontIni: TMemIniFile;
- FontFile: string;
+ FontFile: IPath;
begin
ActFont := 0;
SetLength(Fonts, 4);
- FontIni := TMemIniFile.Create(FontPath + 'fonts.ini');
+ FontIni := TMemIniFile.Create(FontPath.Append('fonts.ini').ToNative);
try
@@ -117,8 +118,9 @@ begin
FontFile := FindFontFile(FontIni, 'Outline2');
Fonts[3].Font := TFTScalableOutlineFont.Create(FontFile, 64, 0.08);
- except on E: Exception do
- Log.LogCritical(E.Message, 'BuildFont');
+ except
+ on E: Exception do
+ Log.LogCritical(E.Message, 'BuildFont');
end;
// close ini-file
diff --git a/unicode/src/base/UCatCovers.pas b/unicode/src/base/UCatCovers.pas
index 86f675c5..6e004b22 100644
--- a/unicode/src/base/UCatCovers.pas
+++ b/unicode/src/base/UCatCovers.pas
@@ -38,20 +38,21 @@ interface
{$I switches.inc}
uses
- UIni;
+ UIni,
+ UPath;
type
TCatCovers = class
protected
- cNames: array [0..high(ISorting)] of array of string;
- cFiles: array [0..high(ISorting)] of array of string;
+ cNames: array [0..high(ISorting)] of array of UTF8String;
+ cFiles: array [0..high(ISorting)] of array of IPath;
public
constructor Create;
procedure Load; //Load Cover aus Cover.ini and Cover Folder
- procedure LoadPath(const CoversPath: string);
- procedure Add(Sorting: integer; Name, Filename: string); //Add a Cover
- function CoverExists(Sorting: integer; Name: string): boolean; //Returns True when a cover with the given Name exists
- function GetCover(Sorting: integer; Name: string): string; //Returns the Filename of a Cover
+ procedure LoadPath(const CoversPath: IPath);
+ procedure Add(Sorting: integer; const Name: UTF8String; const Filename: IPath); //Add a Cover
+ function CoverExists(Sorting: integer; const Name: UTF8String): boolean; //Returns True when a cover with the given Name exists
+ function GetCover(Sorting: integer; const Name: UTF8String): IPath; //Returns the Filename of a Cover
end;
var
@@ -63,9 +64,10 @@ uses
IniFiles,
SysUtils,
Classes,
- // UFiles,
+ UFilesystem,
ULog,
UMain,
+ UUnicodeUtils,
UPathUtils;
constructor TCatCovers.Create;
@@ -79,25 +81,28 @@ var
I: integer;
begin
for I := 0 to CoverPaths.Count-1 do
- LoadPath(CoverPaths[I]);
+ LoadPath(CoverPaths[I] as IPath);
end;
(**
* Load Cover from Cover.ini and Cover Folder
*)
-procedure TCatCovers.LoadPath(const CoversPath: string);
+procedure TCatCovers.LoadPath(const CoversPath: IPath);
var
Ini: TMemIniFile;
- SR: TSearchRec;
List: TStringlist;
I, J: Integer;
- Name, Filename, Temp: string;
+ Filename: IPath;
+ Name, TmpName: UTF8String;
+ CatCover: IPath;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
begin
Ini := nil;
List := nil;
try
- Ini := TMemIniFile.Create(CoversPath + 'covers.ini');
+ Ini := TMemIniFile.Create(CoversPath.Append('covers.ini').ToNative);
List := TStringlist.Create;
//Add every Cover in Covers Ini for Every Sorting option
@@ -106,63 +111,65 @@ begin
Ini.ReadSection(ISorting[I], List);
for J := 0 to List.Count - 1 do
- Add(I, List.Strings[J], CoversPath + Ini.ReadString(ISorting[I], List.Strings[J], 'NoCover.jpg'));
+ begin
+ CatCover := Path(Ini.ReadString(ISorting[I], List.Strings[J], 'NoCover.jpg'));
+ Add(I, List.Strings[J], CoversPath.Append(CatCover));
+ end;
end;
finally
Ini.Free;
List.Free;
end;
- try
- //Add Covers from Folder
- if (FindFirst (CoversPath + '*.jpg', faAnyFile, SR) = 0) then
- repeat
- //Add Cover if it doesn't exist for every Section
- Name := SR.Name;
- Filename := CoversPath + Name;
- Delete (Name, length(Name) - 3, 4);
-
- for I := 0 to high(ISorting) do
- begin
- Temp := Name;
- if ((I = sTitle) or (I = sTitle2)) and (Pos ('Title', Temp) <> 0) then
- Delete (Temp, Pos ('Title', Temp), 5)
- else if (I = sArtist) or (I = sArtist2) and (Pos ('Artist', Temp) <> 0) then
- Delete (Temp, Pos ('Artist', Temp), 6);
-
- if not CoverExists(I, Temp) then
- Add (I, Temp, Filename);
- end;
- until FindNext (SR) <> 0;
- finally
- FindClose (SR);
+ //Add Covers from Folder
+ Iter := FileSystem.FileFind(CoversPath.Append('*.jpg'), 0);
+ while Iter.HasNext do
+ begin
+ FileInfo := Iter.Next;
+
+ //Add Cover if it doesn't exist for every Section
+ Filename := CoversPath.Append(FileInfo.Name);
+ Name := FileInfo.Name.SetExtension('').ToUTF8;
+
+ for I := 0 to high(ISorting) do
+ begin
+ TmpName := Name;
+ if ((I = sTitle) or (I = sTitle2)) and (UTF8Pos('Title', TmpName) <> 0) then
+ UTF8Delete(TmpName, UTF8Pos('Title', TmpName), 5)
+ else if (I = sArtist) or (I = sArtist2) and (UTF8Pos('Artist', TmpName) <> 0) then
+ UTF8Delete(TmpName, UTF8Pos('Artist', TmpName), 6);
+
+ if not CoverExists(I, TmpName) then
+ Add(I, TmpName, Filename);
+ end;
end;
end;
//Add a Cover
-procedure TCatCovers.Add(Sorting: integer; Name, Filename: string);
+procedure TCatCovers.Add(Sorting: integer; const Name: UTF8String; const Filename: IPath);
begin
- if FileExists (Filename) then //If Exists -> Add
+ if Filename.IsFile then //If Exists -> Add
begin
- SetLength (CNames[Sorting], Length(CNames[Sorting]) + 1);
- SetLength (CFiles[Sorting], Length(CNames[Sorting]) + 1);
+ SetLength(CNames[Sorting], Length(CNames[Sorting]) + 1);
+ SetLength(CFiles[Sorting], Length(CNames[Sorting]) + 1);
- CNames[Sorting][high(cNames[Sorting])] := Uppercase(Name);
+ CNames[Sorting][high(cNames[Sorting])] := UTF8Uppercase(Name);
CFiles[Sorting][high(cNames[Sorting])] := FileName;
end;
end;
//Returns True when a cover with the given Name exists
-function TCatCovers.CoverExists(Sorting: integer; Name: string): boolean;
+function TCatCovers.CoverExists(Sorting: integer; const Name: UTF8String): boolean;
var
I: Integer;
+ UpperName: UTF8String;
begin
Result := False;
- Name := Uppercase(Name); //Case Insensitiv
+ UpperName := UTF8Uppercase(Name); //Case Insensitiv
for I := 0 to high(cNames[Sorting]) do
begin
- if (cNames[Sorting][I] = Name) then //Found Name
+ if (cNames[Sorting][I] = UpperName) then //Found Name
begin
Result := true;
break; //Break For Loop
@@ -171,16 +178,18 @@ begin
end;
//Returns the Filename of a Cover
-function TCatCovers.GetCover(Sorting: integer; Name: string): string;
+function TCatCovers.GetCover(Sorting: integer; const Name: UTF8String): IPath;
var
I: Integer;
+ UpperName: UTF8String;
+ NoCoverPath: IPath;
begin
- Result := '';
- Name := Uppercase(Name);
+ Result := PATH_NONE;
+ UpperName := UTF8Uppercase(Name);
for I := 0 to high(cNames[Sorting]) do
begin
- if cNames[Sorting][I] = Name then
+ if cNames[Sorting][I] = UpperName then
begin
Result := cFiles[Sorting][I];
Break;
@@ -188,13 +197,14 @@ begin
end;
//No Cover
- if (Result = '') then
+ if (Result.IsUnset) then
begin
for I := 0 to CoverPaths.Count-1 do
begin
- if (FileExists(CoverPaths[I] + 'NoCover.jpg')) then
+ NoCoverPath := (CoverPaths[I] as IPath).Append('NoCover.jpg');
+ if (NoCoverPath.IsFile) then
begin
- Result := CoverPaths[I] + 'NoCover.jpg';
+ Result := NoCoverPath;
Break;
end;
end;
diff --git a/unicode/src/base/UCommandLine.pas b/unicode/src/base/UCommandLine.pas
index 281a480d..ac0db2c2 100644
--- a/unicode/src/base/UCommandLine.pas
+++ b/unicode/src/base/UCommandLine.pas
@@ -33,6 +33,9 @@ interface
{$I switches.inc}
+uses
+ UPath;
+
type
TScreenMode = (scmDefault, scmFullscreen, scmWindowed);
@@ -64,9 +67,9 @@ type
Screens: integer;
// some strings set when reading infos {Length=0: Not Set}
- SongPath: string;
- ConfigFile: string;
- ScoreFile: string;
+ SongPath: IPath;
+ ConfigFile: IPath;
+ ScoreFile: IPath;
// pseudo integer values
property Language: integer read GetLanguage;
@@ -144,9 +147,9 @@ begin
Screens := -1;
// some strings set when reading infos {Length=0 Not Set}
- SongPath := '';
- ConfigFile := '';
- ScoreFile := '';
+ SongPath := PATH_NONE;
+ ConfigFile := PATH_NONE;
+ ScoreFile := PATH_NONE;
end;
{**
@@ -248,7 +251,7 @@ begin
if (PCount > I) then
begin
// write value to string
- SongPath := ParamStr(I + 1);
+ SongPath := Path(ParamStr(I + 1));
end;
end
@@ -258,11 +261,11 @@ begin
if (PCount > I) then
begin
// write value to string
- ConfigFile := ParamStr(I + 1);
+ ConfigFile := Path(ParamStr(I + 1));
// is this a relative path -> then add gamepath
- if Not ((Length(ConfigFile) > 2) AND (ConfigFile[2] = ':')) then
- ConfigFile := ExtractFilePath(ParamStr(0)) + Configfile;
+ if (not ConfigFile.IsAbsolute) then
+ ConfigFile := Platform.GetExecutionDir().Append(ConfigFile);
end;
end
@@ -272,7 +275,7 @@ begin
if (PCount > I) then
begin
// write value to string
- ScoreFile := ParamStr(I + 1);
+ ScoreFile := Path(ParamStr(I + 1));
end;
end;
diff --git a/unicode/src/base/UCommon.pas b/unicode/src/base/UCommon.pas
index d7c36196..c0a98815 100644
--- a/unicode/src/base/UCommon.pas
+++ b/unicode/src/base/UCommon.pas
@@ -41,7 +41,8 @@ uses
{$ENDIF}
sdl,
UConfig,
- ULog;
+ ULog,
+ UPath;
type
TMessageType = (mtInfo, mtError);
@@ -65,8 +66,16 @@ procedure RestoreNumericLocale();
function MakeLong(a, b: word): longint;
{$ENDIF}
-function AdaptFilePaths(const aPath: widestring): widestring;
-function FileExistsInsensitive(var FileName: string): boolean;
+type
+ TDirectoryEntry = record
+ Name: IPath;
+ IsDirectory: boolean;
+ IsFile: boolean;
+ end;
+
+ TDirectoryEntryArray = array of TDirectoryEntry;
+
+function DirectoryFindFiles(Dir: IPath; Filter: UTF8String; ReturnAllSubDirs: boolean): TDirectoryEntryArray;
// A stable alternative to TList.Sort() (use TList.Sort() if applicable, see below)
procedure MergeSort(List: TList; CompareFunc: TListSortCompare);
@@ -82,6 +91,7 @@ uses
{$IFDEF Delphi}
Dialogs,
{$ENDIF}
+ UFilesystem,
UMain,
UUnicodeUtils;
@@ -206,12 +216,6 @@ begin
exOverflow, exUnderflow, exPrecision]);
end;
-function AdaptFilePaths(const aPath: WideString): WideString;
-begin
- result := StringReplaceW(aPath, '\', PathDelim);//, [rfReplaceAll]);
-end;
-
-
{$IFNDEF MSWINDOWS}
procedure ZeroMemory(Destination: pointer; Length: dword);
begin
@@ -225,42 +229,44 @@ end;
{$ENDIF}
-{ TODO: REMOVE }
-// Checks if a regular files or directory with the given name exists.
-// The comparison is case insensitive.
-function FileExistsInsensitive(var FileName: string): boolean;
+function DirectoryFindFiles(Dir: IPath; Filter: UTF8String; ReturnAllSubDirs: Boolean): TDirectoryEntryArray;
var
- FilePath, LocalFileName: string;
- SearchInfo: TSearchRec;
+ i: integer;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
+ FileName: IPath;
+ Attrib: integer;
begin
-{$IF Defined(Linux) or Defined(FreeBSD)}
- // speed up standard case
- if FileExists(FileName) then
- begin
- Result := true;
- exit;
- end;
+ i := 0;
+ Filter := UTF8LowerCase(Filter);
- Result := false;
-
- FilePath := ExtractFilePath(FileName);
- if (FindFirst(FilePath + '*', faAnyFile, SearchInfo) = 0) then
+ // search for all files and directories
+ Iter := FileSystem.FileFind(Dir.Append('*'), faAnyFile);
+ while (Iter.HasNext) do
begin
- LocalFileName := ExtractFileName(FileName);
- repeat
- if (AnsiSameText(LocalFileName, SearchInfo.Name)) then
+ FileInfo := Iter.Next;
+ FileName := FileInfo.Name;
+ if (not FileName.Equals('.')) and (not FileName.Equals('..')) then
+ begin
+ Attrib := Dir.Append(FileName).GetAttr();
+ if ReturnAllSubDirs and ((Attrib and faDirectory) <> 0) then
begin
- FileName := FilePath + SearchInfo.Name;
- Result := true;
- break;
+ SetLength(Result, i + 1);
+ Result[i].Name := FileName;
+ Result[i].IsDirectory := true;
+ Result[i].IsFile := false;
+ i := i + 1;
+ end
+ else if (Filter = '') or (Pos(Filter, LowerCase(FileName.ToUTF8)) > 0) then
+ begin
+ SetLength(Result, i + 1);
+ Result[i].Name := FileName;
+ Result[i].IsDirectory := false;
+ Result[i].IsFile := true;
+ i := i + 1;
end;
- until (FindNext(SearchInfo) <> 0);
+ end;
end;
- FindClose(SearchInfo);
-{$ELSE}
- // Windows and Mac OS X do not have case sensitive file systems
- Result := FileExists(FileName);
-{$IFEND}
end;
// +++++++++++++++++++++ helpers for RWOpsFromStream() +++++++++++++++
diff --git a/unicode/src/base/UConfig.pas b/unicode/src/base/UConfig.pas
index 1214f36f..f6dc69a5 100644
--- a/unicode/src/base/UConfig.pas
+++ b/unicode/src/base/UConfig.pas
@@ -90,7 +90,7 @@ interface
{$I switches.inc}
uses
- Sysutils;
+ SysUtils;
const
// IMPORTANT:
@@ -156,6 +156,12 @@ const
(FPC_RELEASE * VERSION_MINOR) +
(FPC_PATCH * VERSION_RELEASE);
+ // FPC 2.2.0 unicode support is very buggy. The cwstring unit for example
+ // always crashes whenever UTF8ToAnsi() is called on a non UTF8 encoded string
+ // what is fixed in 2.2.2.
+ {$IF Defined(FPC) and (FPC_VERSION_INT < 2002002)} // < 2.2.2
+ {$MESSAGE FATAL 'FPC >= 2.2.2 required!'}
+ {$IFEND}
{$IFDEF HaveFFmpeg}
diff --git a/unicode/src/base/UCovers.pas b/unicode/src/base/UCovers.pas
index 8e7934b2..0dbe672a 100644
--- a/unicode/src/base/UCovers.pas
+++ b/unicode/src/base/UCovers.pas
@@ -50,7 +50,8 @@ uses
SysUtils,
Classes,
UImage,
- UTexture;
+ UTexture,
+ UPath;
type
ECoverDBException = class(Exception)
@@ -59,9 +60,9 @@ type
TCover = class
private
ID: int64;
- Filename: WideString;
+ Filename: IPath;
public
- constructor Create(ID: int64; Filename: WideString);
+ constructor Create(ID: int64; Filename: IPath);
function GetPreviewTexture(): TTexture;
function GetTexture(): TTexture;
end;
@@ -76,19 +77,19 @@ type
private
DB: TSQLiteDatabase;
procedure InitCoverDatabase();
- function CreateThumbnail(const Filename: WideString; var Info: TThumbnailInfo): PSDL_Surface;
+ function CreateThumbnail(const Filename: IPath; var Info: TThumbnailInfo): PSDL_Surface;
function LoadCover(CoverID: int64): TTexture;
procedure DeleteCover(CoverID: int64);
- function FindCoverIntern(const Filename: WideString): int64;
+ function FindCoverIntern(const Filename: IPath): int64;
procedure Open();
function GetVersion(): integer;
procedure SetVersion(Version: integer);
public
constructor Create();
destructor Destroy; override;
- function AddCover(const Filename: WideString): TCover;
- function FindCover(const Filename: WideString): TCover;
- function CoverExists(const Filename: WideString): boolean;
+ function AddCover(const Filename: IPath): TCover;
+ function FindCover(const Filename: IPath): TCover;
+ function CoverExists(const Filename: IPath): boolean;
function GetMaxCoverSize(): integer;
procedure SetMaxCoverSize(Size: integer);
end;
@@ -141,7 +142,7 @@ end;
{ TCover }
-constructor TCover.Create(ID: int64; Filename: WideString);
+constructor TCover.Create(ID: int64; Filename: IPath);
begin
Self.ID := ID;
Self.Filename := Filename;
@@ -210,11 +211,11 @@ end;
procedure TCoverDatabase.Open();
var
Version: integer;
- Filename: UTF8String;
+ Filename: IPath;
begin
- Filename := Platform.GetGameUserPath() + COVERDB_FILENAME;
+ Filename := Platform.GetGameUserPath().Append(COVERDB_FILENAME);
- DB := TSQLiteDatabase.Create(Filename);
+ DB := TSQLiteDatabase.Create(Filename.ToUTF8());
Version := GetVersion();
// check version, if version is too old/new, delete database file
@@ -223,10 +224,10 @@ begin
Log.LogInfo('Outdated cover-database file found', 'TCoverDatabase.Open');
// close and delete outdated file
DB.Free;
- if (not DeleteFile(Filename)) then
- raise ECoverDBException.Create('Could not delete ' + Filename);
+ if (not Filename.DeleteFile()) then
+ raise ECoverDBException.Create('Could not delete ' + Filename.ToNative);
// reopen
- DB := TSQLiteDatabase.Create(Filename);
+ DB := TSQLiteDatabase.Create(Filename.ToUTF8());
Version := 0;
end;
@@ -266,14 +267,14 @@ begin
')');
end;
-function TCoverDatabase.FindCoverIntern(const Filename: WideString): int64;
+function TCoverDatabase.FindCoverIntern(const Filename: IPath): int64;
begin
Result := DB.GetTableValue('SELECT [ID] FROM ['+COVER_TBL+'] ' +
'WHERE [Filename] = ?',
- [UTF8Encode(Filename)]);
+ [Filename.ToUTF8]);
end;
-function TCoverDatabase.FindCover(const Filename: WideString): TCover;
+function TCoverDatabase.FindCover(const Filename: IPath): TCover;
var
CoverID: int64;
begin
@@ -287,7 +288,7 @@ begin
end;
end;
-function TCoverDatabase.CoverExists(const Filename: WideString): boolean;
+function TCoverDatabase.CoverExists(const Filename: IPath): boolean;
begin
Result := false;
try
@@ -297,7 +298,7 @@ begin
end;
end;
-function TCoverDatabase.AddCover(const Filename: WideString): TCover;
+function TCoverDatabase.AddCover(const Filename: IPath): TCover;
var
CoverID: int64;
Thumbnail: PSDL_Surface;
@@ -329,7 +330,7 @@ begin
DB.ExecSQL('INSERT INTO ['+COVER_TBL+'] ' +
'([Filename], [Date], [Width], [Height]) VALUES' +
'(?, ?, ?, ?)',
- [UTF8Encode(Filename), DateTimeToUnixTime(FileDate),
+ [Filename.ToUTF8, DateTimeToUnixTime(FileDate),
Info.CoverWidth, Info.CoverHeight]);
// get auto-generated cover ID
@@ -358,7 +359,7 @@ var
PixelFmt: TImagePixelFmt;
Data: PChar;
DataSize: integer;
- Filename: WideString;
+ Filename: IPath;
Table: TSQLiteUniTable;
begin
Table := nil;
@@ -371,7 +372,7 @@ begin
'USING(ID) ' +
'WHERE [ID] = %d', [CoverID]));
- Filename := UTF8Decode(Table.FieldAsString(0));
+ Filename := Path(Table.FieldAsString(0));
PixelFmt := TImagePixelFmt(Table.FieldAsInteger(1));
Width := Table.FieldAsInteger(2);
Height := Table.FieldAsInteger(3);
@@ -403,7 +404,7 @@ end;
* Returns a pointer to an array of bytes containing the texture data in the
* requested size
*)
-function TCoverDatabase.CreateThumbnail(const Filename: WideString; var Info: TThumbnailInfo): PSDL_Surface;
+function TCoverDatabase.CreateThumbnail(const Filename: IPath; var Info: TThumbnailInfo): PSDL_Surface;
var
//TargetAspect, SourceAspect: double;
//TargetWidth, TargetHeight: integer;
@@ -417,7 +418,7 @@ begin
Thumbnail := LoadImage(Filename);
if (not assigned(Thumbnail)) then
begin
- Log.LogError('Could not load cover: "'+ Filename +'"', 'TCoverDatabase.AddCover');
+ Log.LogError('Could not load cover: "'+ Filename.ToNative +'"', 'TCoverDatabase.AddCover');
Exit;
end;
diff --git a/unicode/src/base/UDLLManager.pas b/unicode/src/base/UDLLManager.pas
index dd05d733..d5bb1480 100644
--- a/unicode/src/base/UDLLManager.pas
+++ b/unicode/src/base/UDLLManager.pas
@@ -35,7 +35,9 @@ interface
uses
ModiSDK,
- UFiles;
+ UFiles,
+ UPath,
+ UFilesystem;
type
TDLLMan = class
@@ -47,14 +49,14 @@ type
P_RData: pModi_RData;
public
Plugins: array of TPluginInfo;
- PluginPaths: array of string;
+ PluginPaths: array of IPath;
Selected: ^TPluginInfo;
constructor Create;
procedure GetPluginList;
procedure ClearPluginInfo(No: cardinal);
- function LoadPluginInfo(Filename: string; No: cardinal): boolean;
+ function LoadPluginInfo(const Filename: IPath; No: cardinal): boolean;
function LoadPlugin(No: cardinal): boolean;
procedure UnLoadPlugin;
@@ -107,27 +109,26 @@ end;
procedure TDLLMan.GetPluginList;
var
- SearchRecord: TSearchRec;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
begin
-
- if FindFirst(PluginPath + '*' + DLLExt, faAnyFile, SearchRecord) = 0 then
+ Iter := FileSystem.FileFind(PluginPath.Append('*' + DLLExt), 0);
+ while (Iter.HasNext) do
begin
- repeat
- SetLength(Plugins, Length(Plugins)+1);
- SetLength(PluginPaths, Length(Plugins));
+ SetLength(Plugins, Length(Plugins)+1);
+ SetLength(PluginPaths, Length(Plugins));
- if LoadPluginInfo(SearchRecord.Name, High(Plugins)) then // loaded succesful
- begin
- PluginPaths[High(PluginPaths)] := SearchRecord.Name;
- end
- else // error loading
- begin
- SetLength(Plugins, Length(Plugins)-1);
- SetLength(PluginPaths, Length(Plugins));
- end;
-
- until FindNext(SearchRecord) <> 0;
- FindClose(SearchRecord);
+ FileInfo := Iter.Next;
+
+ if LoadPluginInfo(FileInfo.Name, High(Plugins)) then // loaded succesful
+ begin
+ PluginPaths[High(PluginPaths)] := FileInfo.Name;
+ end
+ else // error loading
+ begin
+ SetLength(Plugins, Length(Plugins)-1);
+ SetLength(PluginPaths, Length(Plugins));
+ end;
end;
end;
@@ -164,7 +165,7 @@ begin
Plugins[No].EnLineBonus_O := true;
end;
-function TDLLMan.LoadPluginInfo(Filename: string; No: cardinal): boolean;
+function TDLLMan.LoadPluginInfo(const Filename: IPath; No: cardinal): boolean;
var
hLibg: THandle;
Info: pModi_PluginInfo;
@@ -182,7 +183,7 @@ begin
}
// load libary
- hLibg := LoadLibrary(PChar(PluginPath + Filename));
+ hLibg := LoadLibrary(PChar(PluginPath.Append(Filename).ToNative));
// if loaded
if (hLibg <> 0) then
begin
@@ -197,19 +198,19 @@ begin
Result := true;
end
else
- Log.LogError('Could not load plugin "' + Filename + '": Info procedure not found');
+ Log.LogError('Could not load plugin "' + Filename.ToNative + '": Info procedure not found');
FreeLibrary (hLibg);
end
else
- Log.LogError('Could not load plugin "' + Filename + '": Libary not loaded');
+ Log.LogError('Could not load plugin "' + Filename.ToNative + '": Libary not loaded');
end;
function TDLLMan.LoadPlugin(No: cardinal): boolean;
begin
Result := true;
// load libary
- hLib := LoadLibrary(PChar(PluginPath + PluginPaths[No]));
+ hLib := LoadLibrary(PChar(PluginPath.Append(PluginPaths[No]).ToNative));
// if loaded
if (hLib <> 0) then
begin
@@ -226,11 +227,11 @@ begin
end
else
begin
- Log.LogError('Could not load plugin "' + PluginPaths[No] + '": Procedures not found');
+ Log.LogError('Could not load plugin "' + PluginPaths[No].ToNative + '": Procedures not found');
end;
end
else
- Log.LogError('Could not load plugin "' + PluginPaths[No] + '": Libary not loaded');
+ Log.LogError('Could not load plugin "' + PluginPaths[No].ToNative + '": Libary not loaded');
end;
procedure TDLLMan.UnLoadPlugin;
diff --git a/unicode/src/base/UDataBase.pas b/unicode/src/base/UDataBase.pas
index 87e9519c..90cee974 100644
--- a/unicode/src/base/UDataBase.pas
+++ b/unicode/src/base/UDataBase.pas
@@ -34,10 +34,11 @@ interface
{$I switches.inc}
uses
+ Classes,
+ SQLiteTable3,
USongs,
USong,
- Classes,
- SQLiteTable3;
+ UPath;
//--------------------
//DataBaseSystem - Class including all DB Methods
@@ -88,16 +89,16 @@ type
TDataBaseSystem = class
private
ScoreDB: TSQLiteDatabase;
- fFilename: string;
+ fFilename: IPath;
function GetVersion(): integer;
procedure SetVersion(Version: integer);
public
- property Filename: string read fFilename;
+ property Filename: IPath read fFilename;
destructor Destroy; override;
- procedure Init(const Filename: string);
+ procedure Init(const Filename: IPath);
procedure ReadScore(Song: TSong);
procedure AddScore(Song: TSong; Level: integer; const Name: UTF8String; Score: integer);
procedure WriteScore(Song: TSong);
@@ -128,19 +129,19 @@ const
(**
* Opens Database and Create Tables if not Exist
*)
-procedure TDataBaseSystem.Init(const Filename: string);
+procedure TDataBaseSystem.Init(const Filename: IPath);
var
Version: integer;
begin
if Assigned(ScoreDB) then
Exit;
- Log.LogStatus('Initializing database: "'+Filename+'"', 'TDataBaseSystem.Init');
+ Log.LogStatus('Initializing database: "'+Filename.ToNative+'"', 'TDataBaseSystem.Init');
try
// Open Database
- ScoreDB := TSQLiteDatabase.Create(Filename);
+ ScoreDB := TSQLiteDatabase.Create(Filename.ToUTF8);
fFilename := Filename;
// Close and delete outdated file
@@ -150,10 +151,10 @@ begin
Log.LogInfo('Outdated cover-database file found', 'TDataBaseSystem.Init');
// Close and delete outdated file
ScoreDB.Free;
- if (not DeleteFile(Filename)) then
- raise Exception.Create('Could not delete ' + Filename);
+ if (not Filename.DeleteFile()) then
+ raise Exception.Create('Could not delete ' + Filename.ToNative);
// Reopen
- ScoreDB := TSQLiteDatabase.Create(Filename);
+ ScoreDB := TSQLiteDatabase.Create(Filename.ToUTF8);
Version := 0;
end;
diff --git a/unicode/src/base/UFilename.pas b/unicode/src/base/UFilename.pas
deleted file mode 100644
index c2ccaec8..00000000
--- a/unicode/src/base/UFilename.pas
+++ /dev/null
@@ -1,464 +0,0 @@
-{* UltraStar Deluxe - Karaoke Game
- *
- * UltraStar Deluxe is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *}
-
-unit UFilename;
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-interface
-
-uses
- {$IFDEF MSWINDOWS}
- TntClasses,
- {$ENDIF}
- Classes;
-
-type
- TPathEncoding = (
- // pencLossless,
- pencSystemUTF8, // use system encoding. Mac: UTF8, Linux: None, Win: UTF8
- // Note:
- // - On windows, this format is lossless but is not
- // supported direclty (UTF-16 only).
- // - This is the best format to store filenames as there is
- // no dataloss.
- // - Do not use with glPrint() or other display functions
- // as the resulting string is neither guaranteed to be
- // UTF-8 nor ANSI.
-
- pencSystemANSI, // use system encoding. Mac: UTF8, Linux: None, Win: ANSI
- // Note:
- // - On windows, the ANSI format may break filenames
- // that are not encoded in the active codepage.
- // - Use only if there is no equivalent WideString
- // filesystem function.
- // - Do not use with glPrint() or other display functions
- // as the resulting string is neither guaranteed to be
- // UTF-8 nor ANSI.
-
- // pencPrintable,
- pencUTF8 // tries to present the filename as UTF-8 encoded string
- // that can be used for printing etc.
- // Note:
- // - Some characters whose encodings are unknown are
- // represented either by '?' or as the representative of
- // a different encoding.
- // - On linux not all filenames can be represented
- // correclty in UTF-8 as it does not have filename
- // encodings (though most filenames are stored in UTF-8).
- // - Never use the result to store filenames or open files
- // as the filenames may break due to conversion.
- );
-
- IPath = interface;
-
- {$IFDEF MSWINDOWS}
- TUniFileStream = class(TTntFileStream)
- {$ELSE}
- TUniFileStream = class(TFileStream)
- {$ENDIF}
- public
- constructor Create(const FileName: IPath; Mode: Word);
- end;
-
- TUniMemoryStream = class(TMemoryStream)
- public
- procedure LoadFromFile(const FileName: IPath);
- procedure SaveToFile(const FileName: IPath);
- end;
-
- IPath = interface
- function ToString(Encoding: TPathEncoding = pencSystemUTF8): AnsiString;
- function ToWideString(): WideString;
-
- function Adjust(): boolean;
-
- function Expand(): IPath;
- {** File must be closed with FileClose(Handle) after usage }
- function CreateFile(): integer;
- function CreateDir(): boolean;
- {** File must be closed with FileClose(Handle) after usage }
- function Open(Mode: LongWord): integer;
- {** Stream must be freed with TUniFileStream.Free after usage }
- function OpenStream(Mode: Word): TUniFileStream;
- function GetFileAge(): integer; overload;
- function GetFileAge(out FileDateTime: TDateTime): boolean; overload;
- function Exists(): boolean;
- function IsFile(): boolean;
- function IsDirectory(): boolean;
- function GetAttr(): cardinal;
- function SetAttr(Attr: Integer): boolean;
- function IsReadOnly(): boolean;
- function SetReadOnly(ReadOnly: boolean): boolean;
- function ForceDirectories(): boolean; //-
- function FileSearch(const DirList: IPath): IPath; //-
- function Rename(const NewName: IPath): boolean;
- function DeleteFile(): boolean;
- function DeleteEmptyDir(): boolean;
- function CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
- end;
-
-function Path(const Name: AnsiString; Encoding: TPathEncoding = pencSystemANSI): IPath; overload;
-function Path(const Name: WideString): IPath; overload;
-function Path(PathComponents: array of const): IPath; overload;
-
-implementation
-
-uses
- UFilesystem,
- SysUtils;
-
-type
- TPathImpl = class(TInterfacedObject, IPath)
- private
- fName: AnsiString;
- public
- constructor Create(const Name: string);
- destructor Destroy(); override;
-
- function ToString(Encoding: TPathEncoding = pencSystemANSI): AnsiString;
- function ToWideString(): WideString;
-
- //function Append(const IPath): IPath;
- function Adjust(): boolean;
- {**
- * Removes trailing path-delimiter and replaces path-delimiters with '/'.
- *}
- procedure Unify();
- function Expand(): IPath;
-
- (*
- function IncludeTrailingPathDelimiter(): IPath;
- function ExcludeTrailingPathDelimiter(): IPath;
- function ChangeFileExt(const Extension: IPath): IPath;
- function ExtractFilePath(): IPath;
- function ExtractFileDir(): IPath;
- function ExtractFileDrive(): IPath;
- function ExtractFileName(): IPath;
- function ExtractFileExt(): IPath;
- function ExtractRelativePath(const BaseName: IPath): IPath;
- *)
-
- function CreateFile(): integer;
- function CreateDir(): boolean;
- function Open(Mode: LongWord): integer;
- function OpenStream(Mode: Word): TUniFileStream;
- function GetFileAge(): integer; overload;
- function GetFileAge(out FileDateTime: TDateTime): boolean; overload;
- function Exists(): boolean;
- function IsFile(): boolean;
- function IsDirectory(): boolean;
- function GetAttr(): cardinal;
- function SetAttr(Attr: Integer): boolean;
- function IsReadOnly(): boolean;
- function SetReadOnly(ReadOnly: boolean): boolean;
- function ForceDirectories(): boolean;
- function FileSearch(const DirList: IPath): IPath;
- function Rename(const NewName: IPath): boolean;
- function DeleteFile(): boolean;
- function DeleteEmptyDir(): boolean;
- function CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
- end;
-
- IPathIterator = interface
- function Next(): IPath;
- end;
-
- TPathIteratorImpl = class(TInterfacedObject, IPathIterator)
- private
- fPath: IPath;
- fPos: integer;
- public
- constructor Create(Path: IPath);
-
- function Next(): IPath;
- end;
-
-function Path(const Name: AnsiString; Encoding: TPathEncoding): IPath;
-begin
- {$IFDEF MSWINDOWS}
- case Encoding of
- pencUTF8:
- // TODO: Check if UTF8
- Result := TPathImpl.Create(Name);
- pencSystemANSI:
- Result := TPathImpl.Create(AnsiToUtf8(Name));
- else
- raise Exception.Create('Unhandled encoding');
- end;
- {$ELSE}
- Result := TPathImpl.Create(Name);
- {$ENDIF}
-end;
-
-function Path(const Name: WideString): IPath;
-begin
- Result := TPathImpl.Create(UTF8Encode(Name));
-end;
-
-function Path(PathComponents: array of const): IPath;
-var
- CompIndex: integer;
- Name: string;
-begin
- Name := '';
- for CompIndex := 0 to High(PathComponents) do
- begin
- with PathComponents[CompIndex] do
- begin
- case (VType) of
- vtString:
- Name := Name + VString^;
- vtAnsiString:
- Name := Name + AnsiString(VAnsiString);
- vtWideString:
- Name := Name + UTF8Encode(WideString(VWideString));
- vtObject:
- raise Exception.Create('Unhandled Object type');
- else
- raise Exception.Create('Unhandled Path type');
- end;
- end;
- Name := Name + PathDelim;
- end;
- Result := Path(Name);
-end;
-
-constructor TPathImpl.Create(const Name: string);
-begin
- inherited Create();
- fName := Name;
- Unify();
-end;
-
-destructor TPathImpl.Destroy();
-begin
- inherited;
-end;
-
-procedure TPathImpl.Unify();
-var
- I: integer;
-begin
- for I := 1 to Length(fName) do
- begin
- if (fName[I] in ['\', '/']) then
- fName[I] := PathDelim;
- end;
- fName := ExcludeTrailingPathDelimiter(fName);
-end;
-
-function TPathImpl.ToString(Encoding: TPathEncoding): AnsiString;
-begin
- {$IFDEF MSWINDOWS}
- case Encoding of
- pencUTF8:
- Result := fName;
- pencSystemANSI:
- Result := Utf8ToAnsi(fName);
- else
- raise Exception.Create('Unhandled encoding');
- end;
- {$ELSE}
- Result := fName;
- {$ENDIF}
-end;
-
-function TPathImpl.ToWideString(): WideString;
-begin
- Result := UTF8Decode(fName);
-end;
-
-function TPathImpl.Adjust(): boolean;
-begin
- Result := false; //TODO
-end;
-
-
-
-function TPathImpl.Expand(): IPath;
-begin
- Result := FileSystem.ExpandFileName(Self);
-end;
-
-function TPathImpl.CreateFile(): integer;
-begin
- Result := FileSystem.FileCreate(Self);
-end;
-
-function TPathImpl.CreateDir(): boolean;
-begin
- Result := FileSystem.DirectoryCreate(Self);
-end;
-
-function TPathImpl.Open(Mode: LongWord): integer;
-begin
- Result := FileSystem.FileOpen(Self, Mode);
-end;
-
-function TPathImpl.OpenStream(Mode: Word): TUniFileStream;
-begin
- Result := TUniFileStream.Create(Self, Mode);
-end;
-
-function TPathImpl.GetFileAge(): integer;
-begin
- Result := FileSystem.FileAge(Self);
-end;
-
-function TPathImpl.GetFileAge(out FileDateTime: TDateTime): boolean;
-begin
- Result := FileSystem.FileAge(Self, FileDateTime);
-end;
-
-function TPathImpl.Exists(): boolean;
-begin
- Result := IsFile() or IsDirectory();
-end;
-
-function TPathImpl.IsFile(): boolean;
-begin
- Result := FileSystem.FileExists(Self);
-end;
-
-function TPathImpl.IsDirectory(): boolean;
-begin
- Result := FileSystem.DirectoryExists(Self);
-end;
-
-function TPathImpl.GetAttr(): cardinal;
-begin
- Result := FileSystem.FileGetAttr(Self);
-end;
-
-function TPathImpl.SetAttr(Attr: Integer): boolean;
-begin
- Result := FileSystem.FileSetAttr(Self, Attr);
-end;
-
-function TPathImpl.IsReadOnly(): boolean;
-begin
- Result := FileSystem.FileIsReadOnly(Self);
-end;
-
-function TPathImpl.SetReadOnly(ReadOnly: boolean): boolean;
-begin
- Result := FileSystem.FileSetReadOnly(Self, ReadOnly);
-end;
-
-function TPathImpl.ForceDirectories(): boolean;
-begin
- Result := FileSystem.ForceDirectories(Self);
-end;
-
-function TPathImpl.FileSearch(const DirList: IPath): IPath;
-begin
- Result := FileSystem.FileSearch(Self, DirList);
-end;
-
-function TPathImpl.Rename(const NewName: IPath): boolean;
-begin
- Result := FileSystem.RenameFile(Self, NewName);
-end;
-
-function TPathImpl.DeleteFile(): boolean;
-begin
- Result := FileSystem.DeleteFile(Self);
-end;
-
-function TPathImpl.DeleteEmptyDir(): boolean;
-begin
- Result := FileSystem.RemoveDir(Self);
-end;
-
-function TPathImpl.CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
-begin
- Result := FileSystem.CopyFile(Self, Target, FailIfExists);
-end;
-
-
-
-{ TPathIteratorImpl }
-
-constructor TPathIteratorImpl.Create(Path: IPath);
-begin
- fPath := Path;
- fPos := -1;
-end;
-
-function TPathIteratorImpl.Next(): IPath;
-begin
-end;
-
-
-{ TUniFileStream }
-
-{$IFDEF MSWINDOWS}
-
-constructor TUniFileStream.Create(const FileName: IPath; Mode: Word);
-begin
- inherited Create(FileName.ToWideString(), Mode);
-end;
-
-{$ELSE}
-
-constructor TUniFileStream.Create(const FileName: IPath; Mode: Word);
-begin
- inherited Create(FileName.ToSystemString(), Mode);
-end;
-
-{$ENDIF}
-
-{ TUniMemoryStream }
-
-procedure TUniMemoryStream.LoadFromFile(const FileName: IPath);
-var
- Stream: TStream;
-begin
- Stream := TUniFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
- try
- LoadFromStream(Stream);
- finally
- Stream.Free;
- end;
-end;
-
-procedure TUniMemoryStream.SaveToFile(const FileName: IPath);
-var
- Stream: TStream;
-begin
- Stream := TUniFileStream.Create(FileName, fmCreate);
- try
- SaveToStream(Stream);
- finally
- Stream.Free;
- end;
-end;
-
-end.
diff --git a/unicode/src/base/UFiles.pas b/unicode/src/base/UFiles.pas
index bfcd63d2..9996eeb1 100644
--- a/unicode/src/base/UFiles.pas
+++ b/unicode/src/base/UFiles.pas
@@ -34,10 +34,12 @@ interface
uses
SysUtils,
+ Classes,
ULog,
UMusic,
USongs,
- USong;
+ USong,
+ UPath;
procedure ResetSingTemp;
@@ -48,7 +50,7 @@ type
* Throws a TEncodingException if the song's fields cannot be encoded in the
* requested encoding.
*}
-function SaveSong(const Song: TSong; const Lines: TLines; const Name: string; Relative: boolean): TSaveSongResult;
+function SaveSong(const Song: TSong; const Lines: TLines; const Name: IPath; Relative: boolean): TSaveSongResult;
implementation
@@ -81,7 +83,7 @@ end;
//--------------------
// Saves a Song
//--------------------
-function SaveSong(const Song: TSong; const Lines: TLines; const Name: string; Relative: boolean): TSaveSongResult;
+function SaveSong(const Song: TSong; const Lines: TLines; const Name: IPath; Relative: boolean): TSaveSongResult;
var
C: integer;
N: integer;
@@ -89,9 +91,9 @@ var
B: integer;
RelativeSubTime: integer;
NoteState: AnsiString;
- SongFile: TextFile;
+ SongFile: TTextFileStream;
- function EncodeToken(const Str: UTF8String): AnsiString;
+ function EncodeToken(const Str: UTF8String): RawByteString;
var
Success: boolean;
begin
@@ -100,89 +102,87 @@ var
SaveSong := ssrEncodingError;
end;
- function EncodeFilename(const Filename: WideString): AnsiString;
- begin
- // TODO: Unicode
- Result := Filename;
- end;
-
begin
// Relative := true; // override (idea - use shift+S to save with relative)
- AssignFile(SongFile, Name);
- Rewrite(SongFile);
-
Result := ssrOK;
+ SongFile := nil;
- if (Song.Encoding = encUTF8) then
- Write(SongFile, UTF8_BOM);
+ try
+ SongFile := TTextFileStream.Create(Name, fmCreate);
- Writeln(SongFile, '#ENCODING:' + EncodingName(Song.Encoding));
- Writeln(SongFile, '#TITLE:' + EncodeToken(Song.Title));
- Writeln(SongFile, '#ARTIST:' + EncodeToken(Song.Artist));
+ if (Song.Encoding = encUTF8) then
+ SongFile.Write(UTF8_BOM);
- if Song.Creator <> '' then Writeln(SongFile, '#CREATOR:' + EncodeToken(Song.Creator));
- if Song.Edition <> 'Unknown' then Writeln(SongFile, '#EDITION:' + EncodeToken(Song.Edition));
- if Song.Genre <> 'Unknown' then Writeln(SongFile, '#GENRE:' + EncodeToken(Song.Genre));
- if Song.Language <> 'Unknown' then Writeln(SongFile, '#LANGUAGE:' + EncodeToken(Song.Language));
+ SongFile.WriteLine('#ENCODING:' + EncodingName(Song.Encoding));
+ SongFile.WriteLine('#TITLE:' + EncodeToken(Song.Title));
+ SongFile.WriteLine('#ARTIST:' + EncodeToken(Song.Artist));
- Writeln(SongFile, '#MP3:' + EncodeFilename(Song.Mp3));
- if Song.Cover <> '' then Writeln(SongFile, '#COVER:' + EncodeFilename(Song.Cover));
- if Song.Background <> '' then Writeln(SongFile, '#BACKGROUND:' + EncodeFilename(Song.Background));
- if Song.Video <> '' then Writeln(SongFile, '#VIDEO:' + EncodeFilename(Song.Video));
+ if Song.Creator <> '' then SongFile.WriteLine('#CREATOR:' + EncodeToken(Song.Creator));
+ if Song.Edition <> 'Unknown' then SongFile.WriteLine('#EDITION:' + EncodeToken(Song.Edition));
+ if Song.Genre <> 'Unknown' then SongFile.WriteLine('#GENRE:' + EncodeToken(Song.Genre));
+ if Song.Language <> 'Unknown' then SongFile.WriteLine('#LANGUAGE:' + EncodeToken(Song.Language));
- if Song.VideoGAP <> 0 then Writeln(SongFile, '#VIDEOGAP:' + FloatToStr(Song.VideoGAP));
- if Song.Resolution <> 4 then Writeln(SongFile, '#RESOLUTION:' + IntToStr(Song.Resolution));
- if Song.NotesGAP <> 0 then Writeln(SongFile, '#NOTESGAP:' + IntToStr(Song.NotesGAP));
- if Song.Start <> 0 then Writeln(SongFile, '#START:' + FloatToStr(Song.Start));
- if Song.Finish <> 0 then Writeln(SongFile, '#END:' + IntToStr(Song.Finish));
- if Relative then Writeln(SongFile, '#RELATIVE:yes');
+ SongFile.WriteLine('#MP3:' + EncodeToken(Song.Mp3.ToUTF8));
+ if Song.Cover.IsSet then SongFile.WriteLine('#COVER:' + EncodeToken(Song.Cover.ToUTF8));
+ if Song.Background.IsSet then SongFile.WriteLine('#BACKGROUND:' + EncodeToken(Song.Background.ToUTF8));
+ if Song.Video.IsSet then SongFile.WriteLine('#VIDEO:' + EncodeToken(Song.Video.ToUTF8));
- Writeln(SongFile, '#BPM:' + FloatToStr(Song.BPM[0].BPM / 4));
- Writeln(SongFile, '#GAP:' + FloatToStr(Song.GAP));
+ if Song.VideoGAP <> 0 then SongFile.WriteLine('#VIDEOGAP:' + FloatToStr(Song.VideoGAP));
+ if Song.Resolution <> 4 then SongFile.WriteLine('#RESOLUTION:' + IntToStr(Song.Resolution));
+ if Song.NotesGAP <> 0 then SongFile.WriteLine('#NOTESGAP:' + IntToStr(Song.NotesGAP));
+ if Song.Start <> 0 then SongFile.WriteLine('#START:' + FloatToStr(Song.Start));
+ if Song.Finish <> 0 then SongFile.WriteLine('#END:' + IntToStr(Song.Finish));
+ if Relative then SongFile.WriteLine('#RELATIVE:yes');
- RelativeSubTime := 0;
- for B := 1 to High(Song.BPM) do
- Writeln(SongFile, 'B ' + FloatToStr(Song.BPM[B].StartBeat) + ' '
- + FloatToStr(Song.BPM[B].BPM/4));
+ SongFile.WriteLine('#BPM:' + FloatToStr(Song.BPM[0].BPM / 4));
+ SongFile.WriteLine('#GAP:' + FloatToStr(Song.GAP));
- for C := 0 to Lines.High do
- begin
- for N := 0 to Lines.Line[C].HighNote do
+ RelativeSubTime := 0;
+ for B := 1 to High(Song.BPM) do
+ SongFile.WriteLine('B ' + FloatToStr(Song.BPM[B].StartBeat) + ' '
+ + FloatToStr(Song.BPM[B].BPM/4));
+
+ for C := 0 to Lines.High do
begin
- with Lines.Line[C].Note[N] do
+ for N := 0 to Lines.Line[C].HighNote do
begin
- //Golden + Freestyle Note Patch
- case Lines.Line[C].Note[N].NoteType of
- ntFreestyle: NoteState := 'F ';
- ntNormal: NoteState := ': ';
- ntGolden: NoteState := '* ';
- end; // case
- S := NoteState + IntToStr(Start-RelativeSubTime) + ' '
- + IntToStr(Length) + ' '
- + IntToStr(Tone) + ' '
- + EncodeToken(Text);
-
- Writeln(SongFile, S);
- end; // with
- end; // N
-
- if C < Lines.High then // don't write end of last sentence
- begin
- if not Relative then
- S := '- ' + IntToStr(Lines.Line[C+1].Start)
- else
+ with Lines.Line[C].Note[N] do
+ begin
+ //Golden + Freestyle Note Patch
+ case Lines.Line[C].Note[N].NoteType of
+ ntFreestyle: NoteState := 'F ';
+ ntNormal: NoteState := ': ';
+ ntGolden: NoteState := '* ';
+ end; // case
+ S := NoteState + IntToStr(Start-RelativeSubTime) + ' '
+ + IntToStr(Length) + ' '
+ + IntToStr(Tone) + ' '
+ + EncodeToken(Text);
+
+ SongFile.WriteLine(S);
+ end; // with
+ end; // N
+
+ if C < Lines.High then // don't write end of last sentence
begin
- S := '- ' + IntToStr(Lines.Line[C+1].Start - RelativeSubTime) +
- ' ' + IntToStr(Lines.Line[C+1].Start - RelativeSubTime);
- RelativeSubTime := Lines.Line[C+1].Start;
+ if not Relative then
+ S := '- ' + IntToStr(Lines.Line[C+1].Start)
+ else
+ begin
+ S := '- ' + IntToStr(Lines.Line[C+1].Start - RelativeSubTime) +
+ ' ' + IntToStr(Lines.Line[C+1].Start - RelativeSubTime);
+ RelativeSubTime := Lines.Line[C+1].Start;
+ end;
+ SongFile.WriteLine(S);
end;
- Writeln(SongFile, S);
- end;
- end; // C
+ end; // C
- Writeln(SongFile, 'E');
+ SongFile.WriteLine('E');
+ except
+ Result := ssrFileError;
+ end;
- CloseFile(SongFile);
+ SongFile.Free;
end;
end.
diff --git a/unicode/src/base/UFilesystem.pas b/unicode/src/base/UFilesystem.pas
index 480d3376..1cfb6837 100644
--- a/unicode/src/base/UFilesystem.pas
+++ b/unicode/src/base/UFilesystem.pas
@@ -223,7 +223,7 @@ end;
function TFileSystemImpl.CreateFileStream(const FileName: IPath; Mode: Word): THandleStream;
begin
- Result := TUnicodeFileStream.Create(FileName, Mode);
+ Result := TBinaryFileStream.Create(FileName, Mode);
end;
function TFileSystemImpl.FileFind(const FilePattern: IPath; Attr: Integer): IFileIterator;
diff --git a/unicode/src/base/UFont.pas b/unicode/src/base/UFont.pas
index ce52ed96..d91dca59 100644
--- a/unicode/src/base/UFont.pas
+++ b/unicode/src/base/UFont.pas
@@ -47,13 +47,14 @@ uses
glext,
glu,
sdl,
+ Math,
+ Classes,
+ SysUtils,
UUnicodeUtils,
{$IFDEF BITMAP_FONT}
UTexture,
{$ENDIF}
- Math,
- Classes,
- SysUtils;
+ UPath;
type
@@ -506,7 +507,7 @@ type
procedure ResetIntern();
protected
- fFilename: AnsiString; //**< filename of the font-file
+ fFilename: IPath; //**< filename of the font-file
fSize: integer; //**< Font base size (in pixels)
fOutset: single; //**< size of outset extrusion (in pixels)
fFace: FT_Face; //**< Holds the height of the font
@@ -537,7 +538,7 @@ type
* @param LoadFlags flags passed to FT_Load_Glyph()
* @raises Exception if the font-file could not be loaded
*}
- constructor Create(const Filename: AnsiString;
+ constructor Create(const Filename: IPath;
Size: integer; Outset: single = 0.0;
LoadFlags: FT_Int32 = FT_LOAD_DEFAULT);
@@ -567,7 +568,7 @@ type
* The extrusion in pixels is Size*OutsetAmount
* (0.0 -> no extrusion, 0.1 -> 10%).
*}
- constructor Create(const Filename: AnsiString;
+ constructor Create(const Filename: IPath;
Size: integer; OutsetAmount: single = 0.0;
UseMipmaps: boolean = true);
@@ -585,7 +586,7 @@ type
*}
TFTOutlineFont = class(TFont)
private
- fFilename: AnsiString;
+ fFilename: IPath;
fSize: integer;
fOutset: single;
fInnerFont, fOutlineFont: TFTFont;
@@ -612,7 +613,7 @@ type
procedure SetReflectionPass(Enable: boolean); override;
public
- constructor Create(const Filename: AnsiString;
+ constructor Create(const Filename: IPath;
Size: integer; Outset: single;
LoadFlags: FT_Int32 = FT_LOAD_DEFAULT);
destructor Destroy; override;
@@ -646,7 +647,7 @@ type
function CreateMipmap(Level: integer; Scale: single): TFont; override;
public
- constructor Create(const Filename: AnsiString;
+ constructor Create(const Filename: IPath;
Size: integer; OutsetAmount: single;
UseMipmaps: boolean = true);
@@ -688,7 +689,7 @@ type
* @param InfoFile the name of the info (.dat) file
* @raises Exception if the file is corrupted
*}
- procedure LoadFontInfo(const InfoFile: AnsiString);
+ procedure LoadFontInfo(const InfoFile: IPath);
protected
procedure Render(const Text: UCS4String); override;
@@ -708,7 +709,7 @@ type
* (y-axis up) and from the lower edge of the glyphs bounding box)
* @param(Ascender pixels from baseline to top of highest glyph)
*}
- constructor Create(const Filename: AnsiString; Outline: integer;
+ constructor Create(const Filename: IPath; Outline: integer;
Baseline, Ascender, Descender: integer);
destructor Destroy(); override;
@@ -1406,7 +1407,7 @@ end;
*}
constructor TFTFont.Create(
- const Filename: AnsiString;
+ const Filename: IPath;
Size: integer; Outset: single;
LoadFlags: FT_Int32);
var
@@ -1422,8 +1423,8 @@ begin
fPart := fpNone;
// load font information
- if (FT_New_Face(TFreeType.GetLibrary(), PChar(Filename), 0, fFace) <> 0) then
- raise Exception.Create('FT_New_Face: Could not load font ''' + Filename + '''');
+ if (FT_New_Face(TFreeType.GetLibrary(), PChar(Filename.ToNative), 0, fFace) <> 0) then
+ raise Exception.Create('FT_New_Face: Could not load font ''' + Filename.ToNative + '''');
// support scalable fonts only
if (not FT_IS_SCALABLE(fFace)) then
@@ -1645,7 +1646,7 @@ end;
* TFTScalableFont
*}
-constructor TFTScalableFont.Create(const Filename: AnsiString;
+constructor TFTScalableFont.Create(const Filename: IPath;
Size: integer; OutsetAmount: single;
UseMipmaps: boolean);
var
@@ -1701,7 +1702,7 @@ end;
*}
constructor TFTOutlineFont.Create(
- const Filename: AnsiString;
+ const Filename: IPath;
Size: integer; Outset: single;
LoadFlags: FT_Int32);
begin
@@ -1893,7 +1894,7 @@ end;
*}
constructor TFTScalableOutlineFont.Create(
- const Filename: AnsiString;
+ const Filename: IPath;
Size: integer; OutsetAmount: single;
UseMipmaps: boolean);
var
@@ -2555,7 +2556,7 @@ end;
* TBitmapFont
*}
-constructor TBitmapFont.Create(const Filename: AnsiString; Outline: integer;
+constructor TBitmapFont.Create(const Filename: IPath; Outline: integer;
Baseline, Ascender, Descender: integer);
begin
inherited Create();
@@ -2567,7 +2568,7 @@ begin
fAscender := Ascender;
fDescender := Descender;
- LoadFontInfo(ChangeFileExt(Filename, '.dat'));
+ LoadFontInfo(Filename.SetExtension('.dat'));
ResetIntern();
end;
@@ -2597,18 +2598,18 @@ begin
fWidths[Count] := Round(fWidths[Count] * WidthMult) + WidthAdd;
end;
-procedure TBitmapFont.LoadFontInfo(const InfoFile: AnsiString);
+procedure TBitmapFont.LoadFontInfo(const InfoFile: IPath);
var
- Stream: TFileStream;
+ Stream: THandleStream;
begin
FillChar(fWidths[0], Length(fWidths), 0);
Stream := nil;
try
- Stream := TFileStream.Create(InfoFile, fmOpenRead);
+ Stream := TBinaryFileStream.Create(InfoFile, fmOpenRead);
Stream.Read(fWidths, 256);
except
- raise Exception.Create('Could not read font info file ''' + InfoFile + '''');
+ raise Exception.Create('Could not read font info file ''' + InfoFile.ToNative + '''');
end;
Stream.Free;
end;
diff --git a/unicode/src/base/UGraphic.pas b/unicode/src/base/UGraphic.pas
index 7c5b18fd..9c12d998 100644
--- a/unicode/src/base/UGraphic.pas
+++ b/unicode/src/base/UGraphic.pas
@@ -340,7 +340,7 @@ begin
Tex_Cursor_Unpressed := Texture.LoadTexture(Skin.GetTextureFileName('Cursor'), TEXTURE_TYPE_TRANSPARENT, 0);
- if (Skin.GetTextureFileName('Cursor_Pressed') <> '') then
+ if (Skin.GetTextureFileName('Cursor_Pressed').IsSet) then
Tex_Cursor_Pressed := Texture.LoadTexture(Skin.GetTextureFileName('Cursor_Pressed'), TEXTURE_TYPE_TRANSPARENT, 0)
else
Tex_Cursor_Pressed.TexNum := 0;
@@ -389,14 +389,14 @@ begin
End;
Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
- Tex_SingLineBonusBack[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('LineBonusBack')), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_SingLineBonusBack[P] := Texture.LoadTexture(Skin.GetTextureFileName('LineBonusBack'), TEXTURE_TYPE_COLORIZED, Col);
end;
//## backgrounds for the scores ##
for P := 0 to 5 do begin
LoadColor(R, G, B, 'P' + IntToStr(P+1) + 'Light');
Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
- Tex_ScoreBG[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreBG')), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_ScoreBG[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreBG'), TEXTURE_TYPE_COLORIZED, Col);
end;
@@ -411,23 +411,23 @@ begin
//NoteBar ScoreBar
LoadColor(R, G, B, 'P' + IntToStr(P) + 'Dark');
Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
- Tex_Score_NoteBarLevel_Dark[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Dark')), TEXTURE_TYPE_COLORIZED, Col);
- Tex_Score_NoteBarRound_Dark[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Dark_Round')), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_Score_NoteBarLevel_Dark[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Dark'), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_Score_NoteBarRound_Dark[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Dark_Round'), TEXTURE_TYPE_COLORIZED, Col);
//LineBonus ScoreBar
LoadColor(R, G, B, 'P' + IntToStr(P) + 'Light');
Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
- Tex_Score_NoteBarLevel_Light[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Light')), TEXTURE_TYPE_COLORIZED, Col);
- Tex_Score_NoteBarRound_Light[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Light_Round')), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_Score_NoteBarLevel_Light[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Light'), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_Score_NoteBarRound_Light[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Light_Round'), TEXTURE_TYPE_COLORIZED, Col);
//GoldenNotes ScoreBar
LoadColor(R, G, B, 'P' + IntToStr(P) + 'Lightest');
Col := $10000 * Round(R*255) + $100 * Round(G*255) + Round(B*255);
- Tex_Score_NoteBarLevel_Lightest[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Lightest')), TEXTURE_TYPE_COLORIZED, Col);
- Tex_Score_NoteBarRound_Lightest[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('ScoreLevel_Lightest_Round')), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_Score_NoteBarLevel_Lightest[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Lightest'), TEXTURE_TYPE_COLORIZED, Col);
+ Tex_Score_NoteBarRound_Lightest[P] := Texture.LoadTexture(Skin.GetTextureFileName('ScoreLevel_Lightest_Round'), TEXTURE_TYPE_COLORIZED, Col);
end;
//## rating pictures that show a picture according to your rate ##
for P := 0 to 7 do begin
- Tex_Score_Ratings[P] := Texture.LoadTexture(pchar(Skin.GetTextureFileName('Rating_'+IntToStr(P))), TEXTURE_TYPE_TRANSPARENT, 0);
+ Tex_Score_Ratings[P] := Texture.LoadTexture(Skin.GetTextureFileName('Rating_'+IntToStr(P)), TEXTURE_TYPE_TRANSPARENT, 0);
end;
Log.LogStatus('Loading Textures - Done', 'LoadTextures');
@@ -464,7 +464,7 @@ begin
end;
// load icon image (must be 32x32 for win32)
- Icon := LoadImage(ResourcesPath + WINDOW_ICON);
+ Icon := LoadImage(ResourcesPath.Append(WINDOW_ICON));
if (Icon <> nil) then
SDL_WM_SetIcon(Icon, 0);
diff --git a/unicode/src/base/UImage.pas b/unicode/src/base/UImage.pas
index 60b0a3a2..25b0d1e2 100644
--- a/unicode/src/base/UImage.pas
+++ b/unicode/src/base/UImage.pas
@@ -34,7 +34,8 @@ interface
{$I switches.inc}
uses
- SDL;
+ SDL,
+ UPath;
{$DEFINE HavePNG}
{$DEFINE HaveBMP}
@@ -131,20 +132,20 @@ type
*******************************************************)
{$IFDEF HavePNG}
-function WritePNGImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WritePNGImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
{$ENDIF}
{$IFDEF HaveBMP}
-function WriteBMPImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WriteBMPImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
{$ENDIF}
{$IFDEF HaveJPG}
-function WriteJPGImage(const FileName: string; Surface: PSDL_Surface; Quality: integer): boolean;
+function WriteJPGImage(const FileName: IPath; Surface: PSDL_Surface; Quality: integer): boolean;
{$ENDIF}
(*******************************************************
* Image loading
*******************************************************)
-function LoadImage(const Filename: string): PSDL_Surface;
+function LoadImage(const Filename: IPath): PSDL_Surface;
(*******************************************************
* Image manipulation
@@ -282,17 +283,17 @@ end;
procedure user_read_data(png_ptr: png_structp; data: png_bytep; length: png_size_t); cdecl;
var
- inFile: TFileStream;
+ inFile: THandleStream;
begin
- inFile := TFileStream(png_get_io_ptr(png_ptr));
+ inFile := THandleStream(png_get_io_ptr(png_ptr));
inFile.Read(data^, length);
end;
procedure user_write_data(png_ptr: png_structp; data: png_bytep; length: png_size_t); cdecl;
var
- outFile: TFileStream;
+ outFile: THandleStream;
begin
- outFile := TFileStream(png_get_io_ptr(png_ptr));
+ outFile := THandleStream(png_get_io_ptr(png_ptr));
outFile.Write(data^, length);
end;
@@ -323,11 +324,11 @@ end;
(*
* ImageData must be in RGB-format
*)
-function WritePNGImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WritePNGImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
var
png_ptr: png_structp;
info_ptr: png_infop;
- pngFile: TFileStream;
+ pngFile: THandleStream;
row: integer;
rowData: array of png_bytep;
// rowStride: integer;
@@ -339,9 +340,9 @@ begin
// open file for writing
try
- pngFile := TFileStream.Create(FileName, fmCreate);
+ pngFile := TBinaryFileStream.Create(FileName, fmCreate);
except
- Log.LogError('Could not open file: "' + FileName + '"', 'WritePngImage');
+ Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WritePngImage');
Exit;
end;
@@ -500,9 +501,9 @@ type
(*
* ImageData must be in BGR-format
*)
-function WriteBMPImage(const FileName: string; Surface: PSDL_Surface): boolean;
+function WriteBMPImage(const FileName: IPath; Surface: PSDL_Surface): boolean;
var
- bmpFile: TFileStream;
+ bmpFile: THandleStream;
FileInfo: BITMAPINFOHEADER;
FileHeader: BITMAPFILEHEADER;
Converted: boolean;
@@ -513,9 +514,9 @@ begin
// open file for writing
try
- bmpFile := TFileStream.Create(FileName, fmCreate);
+ bmpFile := TBinaryFileStream.Create(FileName, fmCreate);
except
- Log.LogError('Could not open file: "' + FileName + '"', 'WriteBMPImage');
+ Log.LogError('Could not open file: "' + FileName.ToNative + '"', 'WriteBMPImage');
Exit;
end;
@@ -579,7 +580,7 @@ begin
Result := true;
finally
- Log.LogError('Could not write file: "' + FileName + '"', 'WriteBMPImage');
+ Log.LogError('Could not write file: "' + FileName.ToNative + '"', 'WriteBMPImage');
end;
if (Converted) then
@@ -597,7 +598,7 @@ end;
{$IFDEF HaveJPG}
-function WriteJPGImage(const FileName: string; Surface: PSDL_Surface; Quality: integer): boolean;
+function WriteJPGImage(const FileName: IPath; Surface: PSDL_Surface; Quality: integer): boolean;
var
{$IFDEF Delphi}
Bitmap: TBitmap;
@@ -676,9 +677,9 @@ begin
try
// compress image (don't forget this line, otherwise it won't be compressed)
Jpeg.Compress();
- Jpeg.SaveToFile(FileName);
+ Jpeg.SaveToFile(FileName.ToNative);
except
- Log.LogError('Could not save file: "' + FileName + '"', 'WriteJPGImage');
+ Log.LogError('Could not save file: "' + FileName.ToNative + '"', 'WriteJPGImage');
Exit;
end;
Jpeg.Free;
@@ -763,27 +764,25 @@ end;
(*
* Loads an image from the given file
*)
-function LoadImage(const Filename: string): PSDL_Surface;
+function LoadImage(const Filename: IPath): PSDL_Surface;
var
- FilenameFound: string;
+ FilenameCaseAdj: IPath;
begin
- Result := nil;
+ Result := nil;
- // FileExistsInsensitive() requires a var-arg
- FilenameFound := Filename;
-
- // try to find the file case insensitive
- if (not FileExistsInsensitive(FilenameFound)) then
+ // try to adjust filename's case and check if it exists
+ FilenameCaseAdj := Filename.AdjustCase(false);
+ if (not FilenameCaseAdj.IsFile) then
begin
- Log.LogError('Image-File does not exist "'+FilenameFound+'"', 'LoadImage');
+ Log.LogError('Image-File does not exist "' + FilenameCaseAdj.ToNative + '"', 'LoadImage');
Exit;
end;
// load from file
try
- Result := IMG_Load(PChar(FilenameFound));
+ Result := IMG_Load(PChar(FilenameCaseAdj.ToNative));
except
- Log.LogError('Could not load from file "'+FilenameFound+'"', 'LoadImage');
+ Log.LogError('Could not load from file "' + FilenameCaseAdj.ToNative + '"', 'LoadImage');
Exit;
end;
end;
diff --git a/unicode/src/base/UIni.pas b/unicode/src/base/UIni.pas
index bf068f11..85f925ad 100644
--- a/unicode/src/base/UIni.pas
+++ b/unicode/src/base/UIni.pas
@@ -36,9 +36,11 @@ interface
uses
Classes,
IniFiles,
+ SysUtils,
ULog,
UTextEncoding,
- SysUtils;
+ UFilesystem,
+ UPath;
type
// TInputDeviceConfig stores the configuration for an input device.
@@ -71,11 +73,10 @@ type
TBackgroundMusicOption = (bmoOff, bmoOn);
TIni = class
private
- function RemoveFileExt(FullName: string): string;
function ExtractKeyIndex(const Key, Prefix, Suffix: string): integer;
function GetMaxKeyIndex(Keys: TStringList; const Prefix, Suffix: string): integer;
- function GetArrayIndex(const SearchArray: array of string; Value: string; CaseInsensitiv: boolean = false): integer;
- function ReadArrayIndex(const SearchArray: array of string; IniFile: TCustomIniFile;
+ function GetArrayIndex(const SearchArray: array of UTF8String; Value: string; CaseInsensitiv: boolean = false): integer;
+ function ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
IniSection: string; IniProperty: string; Default: integer): integer;
procedure LoadInputDeviceCfg(IniFile: TMemIniFile);
@@ -92,7 +93,7 @@ type
NameTemplate: array[0..11] of UTF8String;
//Filename of the opened iniFile
- Filename: string;
+ Filename: IPath;
// Game
Players: integer;
@@ -165,19 +166,19 @@ type
var
Ini: TIni;
- IResolution: array of string;
- ILanguage: array of string;
- ITheme: array of string;
- ISkin: array of string;
+ IResolution: array of UTF8String;
+ ILanguage: array of UTF8String;
+ ITheme: array of UTF8String;
+ ISkin: array of UTF8String;
const
- IPlayers: array[0..4] of string = ('1', '2', '3', '4', '6');
- IPlayersVals: array[0..4] of integer = ( 1 , 2 , 3 , 4 , 6 );
+ IPlayers: array[0..4] of UTF8String = ('1', '2', '3', '4', '6');
+ IPlayersVals: array[0..4] of integer = ( 1 , 2 , 3 , 4 , 6 );
- IDifficulty: array[0..2] of string = ('Easy', 'Medium', 'Hard');
- ITabs: array[0..1] of string = ('Off', 'On');
+ IDifficulty: array[0..2] of UTF8String = ('Easy', 'Medium', 'Hard');
+ ITabs: array[0..1] of UTF8String = ('Off', 'On');
- ISorting: array[0..7] of string = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Title2', 'Artist2');
+ ISorting: array[0..7] of UTF8String = ('Edition', 'Genre', 'Language', 'Folder', 'Title', 'Artist', 'Title2', 'Artist2');
sEdition = 0;
sGenre = 1;
sLanguage = 2;
@@ -187,71 +188,71 @@ const
sTitle2 = 6;
sArtist2 = 7;
- IDebug: array[0..1] of string = ('Off', 'On');
+ IDebug: array[0..1] of UTF8String = ('Off', 'On');
- IScreens: array[0..1] of string = ('1', '2');
- IFullScreen: array[0..1] of string = ('Off', 'On');
- IDepth: array[0..1] of string = ('16 bit', '32 bit');
- IVisualizer: array[0..2] of string = ('Off', 'WhenNoVideo','On');
+ IScreens: array[0..1] of UTF8String = ('1', '2');
+ IFullScreen: array[0..1] of UTF8String = ('Off', 'On');
+ IDepth: array[0..1] of UTF8String = ('16 bit', '32 bit');
+ IVisualizer: array[0..2] of UTF8String = ('Off', 'WhenNoVideo','On');
- IBackgroundMusic: array[0..1] of string = ('Off', 'On');
+ IBackgroundMusic: array[0..1] of UTF8String = ('Off', 'On');
- ITextureSize: array[0..3] of string = ('64', '128', '256', '512');
- ITextureSizeVals: array[0..3] of integer = ( 64, 128, 256, 512);
+ ITextureSize: array[0..3] of UTF8String = ('64', '128', '256', '512');
+ ITextureSizeVals: array[0..3] of integer = ( 64, 128, 256, 512);
- ISingWindow: array[0..1] of string = ('Small', 'Big');
+ ISingWindow: array[0..1] of UTF8String = ('Small', 'Big');
//SingBar Mod
- IOscilloscope: array[0..1] of string = ('Off', 'On');
+ IOscilloscope: array[0..1] of UTF8String = ('Off', 'On');
- ISpectrum: array[0..1] of string = ('Off', 'On');
- ISpectrograph: array[0..1] of string = ('Off', 'On');
- IMovieSize: array[0..2] of string = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+ ISpectrum: array[0..1] of UTF8String = ('Off', 'On');
+ ISpectrograph: array[0..1] of UTF8String = ('Off', 'On');
+ IMovieSize: array[0..2] of UTF8String = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
- IClickAssist: array[0..1] of string = ('Off', 'On');
- IBeatClick: array[0..1] of string = ('Off', 'On');
- ISavePlayback: array[0..1] of string = ('Off', 'On');
+ IClickAssist: array[0..1] of UTF8String = ('Off', 'On');
+ IBeatClick: array[0..1] of UTF8String = ('Off', 'On');
+ ISavePlayback: array[0..1] of UTF8String = ('Off', 'On');
- IThreshold: array[0..3] of string = ('5%', '10%', '15%', '20%');
+ IThreshold: array[0..3] of UTF8String = ('5%', '10%', '15%', '20%');
IThresholdVals: array[0..3] of single = (0.05, 0.10, 0.15, 0.20);
- IVoicePassthrough: array[0..1] of string = ('Off', 'On');
+ IVoicePassthrough: array[0..1] of UTF8String = ('Off', 'On');
- IAudioOutputBufferSize: array[0..9] of string = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
- IAudioOutputBufferSizeVals: array[0..9] of integer = ( 0, 256, 512 , 1024 , 2048 , 4096 , 8192 , 16384 , 32768 , 65536 );
+ IAudioOutputBufferSize: array[0..9] of UTF8String = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+ IAudioOutputBufferSizeVals: array[0..9] of integer = ( 0, 256, 512 , 1024 , 2048 , 4096 , 8192 , 16384 , 32768 , 65536 );
- IAudioInputBufferSize: array[0..9] of string = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
- IAudioInputBufferSizeVals: array[0..9] of integer = ( 0, 256, 512 , 1024 , 2048 , 4096 , 8192 , 16384 , 32768 , 65536 );
+ IAudioInputBufferSize: array[0..9] of UTF8String = ('Auto', '256', '512', '1024', '2048', '4096', '8192', '16384', '32768', '65536');
+ IAudioInputBufferSizeVals: array[0..9] of integer = ( 0, 256, 512 , 1024 , 2048 , 4096 , 8192 , 16384 , 32768 , 65536 );
//Song Preview
- IPreviewVolume: array[0..10] of string = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
- IPreviewVolumeVals: array[0..10] of single = ( 0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00 );
+ IPreviewVolume: array[0..10] of UTF8String = ('Off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%');
+ IPreviewVolumeVals: array[0..10] of single = ( 0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00 );
- IPreviewFading: array[0..5] of string = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
- IPreviewFadingVals: array[0..5] of integer = ( 0, 1, 2, 3, 4, 5 );
+ IPreviewFading: array[0..5] of UTF8String = ('Off', '1 Sec', '2 Secs', '3 Secs', '4 Secs', '5 Secs');
+ IPreviewFadingVals: array[0..5] of integer = ( 0, 1, 2, 3, 4, 5 );
- ILyricsFont: array[0..2] of string = ('Plain', 'OLine1', 'OLine2');
- ILyricsEffect: array[0..4] of string = ('Simple', 'Zoom', 'Slide', 'Ball', 'Shift');
- ISolmization: array[0..3] of string = ('Off', 'Euro', 'Jap', 'American');
- INoteLines: array[0..1] of string = ('Off', 'On');
+ ILyricsFont: array[0..2] of UTF8String = ('Plain', 'OLine1', 'OLine2');
+ ILyricsEffect: array[0..4] of UTF8String = ('Simple', 'Zoom', 'Slide', 'Ball', 'Shift');
+ ISolmization: array[0..3] of UTF8String = ('Off', 'Euro', 'Jap', 'American');
+ INoteLines: array[0..1] of UTF8String = ('Off', 'On');
- IColor: array[0..8] of string = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
+ IColor: array[0..8] of UTF8String = ('Blue', 'Green', 'Pink', 'Red', 'Violet', 'Orange', 'Yellow', 'Brown', 'Black');
// Advanced
- ILoadAnimation: array[0..1] of string = ('Off', 'On');
- IEffectSing: array[0..1] of string = ('Off', 'On');
- IScreenFade: array[0..1] of string = ('Off', 'On');
- IAskbeforeDel: array[0..1] of string = ('Off', 'On');
- IOnSongClick: array[0..2] of string = ('Sing', 'Select Players', 'Open Menu');
- ILineBonus: array[0..1] of string = ('Off', 'On');
- IPartyPopup: array[0..1] of string = ('Off', 'On');
+ ILoadAnimation: array[0..1] of UTF8String = ('Off', 'On');
+ IEffectSing: array[0..1] of UTF8String = ('Off', 'On');
+ IScreenFade: array[0..1] of UTF8String = ('Off', 'On');
+ IAskbeforeDel: array[0..1] of UTF8String = ('Off', 'On');
+ IOnSongClick: array[0..2] of UTF8String = ('Sing', 'Select Players', 'Open Menu');
+ ILineBonus: array[0..1] of UTF8String = ('Off', 'On');
+ IPartyPopup: array[0..1] of UTF8String = ('Off', 'On');
- IJoypad: array[0..1] of string = ('Off', 'On');
- IMouse: array[0..2] of string = ('Off', 'Hardware Cursor', 'Software Cursor');
+ IJoypad: array[0..1] of UTF8String = ('Off', 'On');
+ IMouse: array[0..2] of UTF8String = ('Off', 'Hardware Cursor', 'Software Cursor');
// Recording options
- IChannelPlayer: array[0..6] of string = ('Off', '1', '2', '3', '4', '5', '6');
- IMicBoost: array[0..3] of string = ('Off', '+6dB', '+12dB', '+18dB');
+ IChannelPlayer: array[0..6] of UTF8String = ('Off', '1', '2', '3', '4', '5', '6');
+ IMicBoost: array[0..3] of UTF8String = ('Off', '+6dB', '+12dB', '+18dB');
implementation
@@ -268,14 +269,6 @@ uses
UUnicodeUtils;
(**
- * Returns the filename without its fileextension
- *)
-function TIni.RemoveFileExt(FullName: string): string;
-begin
- Result := ChangeFileExt(FullName, '');
-end;
-
-(**
* Extracts an index of a key that is surrounded by a Prefix/Suffix pair.
* Example: ExtractKeyIndex('MyKey[1]', '[', ']') will return 1.
*)
@@ -325,7 +318,7 @@ end;
* Returns the index of Value in SearchArray
* or -1 if Value is not in SearchArray.
*)
-function TIni.GetArrayIndex(const SearchArray: array of string; Value: string;
+function TIni.GetArrayIndex(const SearchArray: array of UTF8String; Value: string;
CaseInsensitiv: boolean = false): integer;
var
i: integer;
@@ -349,7 +342,7 @@ end;
* If SearchArray does not contain the property value, the default value is
* returned.
*)
-function TIni.ReadArrayIndex(const SearchArray: array of string; IniFile: TCustomIniFile;
+function TIni.ReadArrayIndex(const SearchArray: array of UTF8String; IniFile: TCustomIniFile;
IniSection: string; IniProperty: string; Default: integer): integer;
var
StrValue: string;
@@ -464,7 +457,7 @@ begin
begin
if (Pos('SONGDIR', UpperCase(PathStrings[I])) = 1) then
begin
- AddSongPath(IniFile.ReadString('Directories', PathStrings[I], ''));
+ AddSongPath(Path(IniFile.ReadString('Directories', PathStrings[I], '')));
end;
end;
@@ -477,18 +470,23 @@ var
ThemeIni: TMemIniFile;
ThemeName: string;
I: integer;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
begin
// Theme
SetLength(ITheme, 0);
- Log.LogStatus('Searching for Theme : ' + ThemePath + '*.ini', 'Theme');
+ Log.LogStatus('Searching for Theme : ' + ThemePath.ToNative + '*.ini', 'Theme');
+
- FindFirst(ThemePath + '*.ini',faAnyFile, SearchResult);
- Repeat
- Log.LogStatus('Found Theme: ' + SearchResult.Name, 'Theme');
+ Iter := FileSystem.FileFind(ThemePath.Append('*.ini'), 0);
+ while (Iter.HasNext) do
+ begin
+ FileInfo := Iter.Next;
+ Log.LogStatus('Found Theme: ' + FileInfo.Name.ToNative, 'Theme');
//Read Themename from Theme
- ThemeIni := TMemIniFile.Create(SearchResult.Name);
- ThemeName := UpperCase(ThemeIni.ReadString('Theme','Name', RemoveFileExt(SearchResult.Name)));
+ ThemeIni := TMemIniFile.Create(FileInfo.Name.ToNative);
+ ThemeName := UpperCase(ThemeIni.ReadString('Theme','Name', FileInfo.Name.SetExtension('').ToNative));
ThemeIni.Free;
//Search for Skins for this Theme
@@ -497,12 +495,11 @@ begin
if UpperCase(Skin.Skin[I].Theme) = ThemeName then
begin
SetLength(ITheme, Length(ITheme)+1);
- ITheme[High(ITheme)] := RemoveFileExt(SearchResult.Name);
+ ITheme[High(ITheme)] := FileInfo.Name.SetExtension('').ToNative;
break;
end;
end;
- until FindNext(SearchResult) <> 0;
- FindClose(SearchResult);
+ end;
// No Theme Found
if (Length(ITheme) = 0) then
@@ -523,7 +520,7 @@ end;
procedure TIni.LoadScreenModes(IniFile: TCustomIniFile);
// swap two strings
- procedure swap(var s1, s2: string);
+ procedure swap(var s1, s2: UTF8String);
var
s3: string;
begin
@@ -631,19 +628,15 @@ var
begin
GamePath := Platform.GetGameUserPath;
- Log.LogStatus( 'GamePath : ' +GamePath , '' );
+ Log.LogStatus( 'GamePath : ' +GamePath.ToNative , '' );
- if (Params.ConfigFile <> '') then
- try
- FileName := Params.ConfigFile;
- except
- FileName := GamePath + 'config.ini';
- end
+ if (Params.ConfigFile.IsSet) then
+ FileName := Params.ConfigFile
else
- FileName := GamePath + 'config.ini';
+ FileName := GamePath.Append('config.ini');
- Log.LogStatus( 'Using config : ' + FileName , 'Ini');
- IniFile := TMemIniFile.Create( FileName );
+ Log.LogStatus('Using config : ' + FileName.ToNative, 'Ini');
+ IniFile := TMemIniFile.Create(FileName.ToNative);
// Name
for I := 0 to 11 do
@@ -784,13 +777,13 @@ procedure TIni.Save;
var
IniFile: TIniFile;
begin
- if (FileExists(Filename) and FileIsReadOnly(Filename)) then
+ if (Filename.IsFile and Filename.IsReadOnly) then
begin
Log.LogError('Config-file is read-only', 'TIni.Save');
Exit;
end;
- IniFile := TIniFile.Create(Filename);
+ IniFile := TIniFile.Create(Filename.ToNative);
// Players
IniFile.WriteString('Game', 'Players', IPlayers[Players]);
@@ -930,9 +923,9 @@ var
IniFile: TIniFile;
I: integer;
begin
- if not FileIsReadOnly(Filename) then
+ if not Filename.IsReadOnly() then
begin
- IniFile := TIniFile.Create(Filename);
+ IniFile := TIniFile.Create(Filename.ToNative);
//Name Templates for Names Mod
for I := 0 to High(Name) do
@@ -950,9 +943,9 @@ procedure TIni.SaveLevel;
var
IniFile: TIniFile;
begin
- if not FileIsReadOnly(Filename) then
+ if not Filename.IsReadOnly() then
begin
- IniFile := TIniFile.Create(Filename);
+ IniFile := TIniFile.Create(Filename.ToNative);
// Difficulty
IniFile.WriteString('Game', 'Difficulty', IDifficulty[Difficulty]);
diff --git a/unicode/src/base/ULanguage.pas b/unicode/src/base/ULanguage.pas
index 9571358e..88b6647f 100644
--- a/unicode/src/base/ULanguage.pas
+++ b/unicode/src/base/ULanguage.pas
@@ -79,6 +79,8 @@ uses
Classes,
SysUtils,
ULog,
+ UPath,
+ UFilesystem,
UPathUtils;
{**
@@ -129,23 +131,26 @@ end;
*}
procedure TLanguage.LoadList;
var
- SR: TSearchRec; // for parsing directory
+ Iter: IFileIterator;
+ IniInfo: TFileInfo;
+ LangName: string;
begin
SetLength(List, 0);
SetLength(ILanguage, 0);
- if FindFirst(LanguagesPath + '*.ini', 0, SR) = 0 then
+ Iter := FileSystem.FileFind(LanguagesPath.Append('*.ini'), 0);
+ while(Iter.HasNext) do
begin
- repeat
- SetLength(List, Length(List)+1);
- SetLength(ILanguage, Length(ILanguage)+1);
- SR.Name := ChangeFileExt(SR.Name, '');
-
- List[High(List)].Name := SR.Name;
- ILanguage[High(ILanguage)] := SR.Name;
- until (FindNext(SR) <> 0);
- SysUtils.FindClose(SR);
- end; // if FindFirst
+ IniInfo := Iter.Next;
+
+ LangName := IniInfo.Name.SetExtension('').ToUTF8;
+
+ SetLength(List, Length(List)+1);
+ List[High(List)].Name := LangName;
+
+ SetLength(ILanguage, Length(ILanguage)+1);
+ ILanguage[High(ILanguage)] := LangName;
+ end;
end;
{**
@@ -158,7 +163,7 @@ var
S: TStringList;
begin
SetLength(Entry, 0);
- IniFile := TIniFile.Create(LanguagesPath + Language + '.ini');
+ IniFile := TIniFile.Create(LanguagesPath.Append(Language + '.ini').ToNative);
S := TStringList.Create;
IniFile.ReadSectionValues('Text', S);
diff --git a/unicode/src/base/ULog.pas b/unicode/src/base/ULog.pas
index 6f7aa644..08a64e2b 100644
--- a/unicode/src/base/ULog.pas
+++ b/unicode/src/base/ULog.pas
@@ -34,7 +34,8 @@ interface
{$I switches.inc}
uses
- Classes;
+ Classes,
+ UPath;
(*
* LOG_LEVEL_[TYPE] defines the "minimum" index for logs of type TYPE. Each
@@ -198,7 +199,7 @@ begin
if not BenchmarkFileOpened then
begin
BenchmarkFileOpened := true;
- AssignFile(BenchmarkFile, LogPath + 'Benchmark.log');
+ AssignFile(BenchmarkFile, LogPath.Append('Benchmark.log').ToNative);
{$I-}
Rewrite(BenchmarkFile);
if IOResult = 0 then
@@ -270,7 +271,7 @@ procedure TLog.LogToFile(const Text: string);
begin
if (FileOutputEnabled and not LogFileOpened) then
begin
- AssignFile(LogFile, LogPath + 'Error.log');
+ AssignFile(LogFile, LogPath.Append('Error.log').ToNative);
{$I-}
Rewrite(LogFile);
if IOResult = 0 then
@@ -399,20 +400,19 @@ end;
procedure TLog.LogVoice(SoundNr: integer);
var
- FS: TFileStream;
- FileName: string;
+ FS: TBinaryFileStream;
+ Prefix: string;
+ FileName: IPath;
Num: integer;
begin
for Num := 1 to 9999 do begin
- FileName := IntToStr(Num);
- while Length(FileName) < 4 do
- FileName := '0' + FileName;
- FileName := LogPath + 'Voice' + FileName + '.raw';
- if not FileExists(FileName) then
+ Prefix := Format('Voice%.4d', [Num]);
+ FileName := LogPath.Append(Prefix + '.raw');
+ if not FileName.Exists() then
break
end;
- FS := TFileStream.Create(FileName, fmCreate);
+ FS := TBinaryFileStream.Create(FileName, fmCreate);
AudioInputProcessor.Sound[SoundNr].LogBuffer.Seek(0, soBeginning);
FS.CopyFrom(AudioInputProcessor.Sound[SoundNr].LogBuffer, AudioInputProcessor.Sound[SoundNr].LogBuffer.Size);
diff --git a/unicode/src/base/UMain.pas b/unicode/src/base/UMain.pas
index 5b07c9ae..6ab4e187 100644
--- a/unicode/src/base/UMain.pas
+++ b/unicode/src/base/UMain.pas
@@ -196,7 +196,7 @@ begin
// Theme
Log.BenchmarkStart(1);
Log.LogStatus('Load Themes', 'Initialization');
- Theme := TTheme.Create(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
+ Theme := TTheme.Create(ThemePath.Append(ITheme[Ini.Theme] + '.ini'), Ini.Color);
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading Themes', 1);
@@ -252,10 +252,10 @@ begin
Log.LogStatus('DataBase System', 'Initialization');
DataBase := TDataBaseSystem.Create;
- if (Params.ScoreFile = '') then
- DataBase.Init (Platform.GetGameUserPath + 'Ultrastar.db')
+ if (Params.ScoreFile.IsUnset) then
+ DataBase.Init(Platform.GetGameUserPath.Append('Ultrastar.db'))
else
- DataBase.Init (Params.ScoreFile);
+ DataBase.Init(Params.ScoreFile);
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading DataBase System', 1);
diff --git a/unicode/src/base/UMusic.pas b/unicode/src/base/UMusic.pas
index b959ea05..51759b6f 100644
--- a/unicode/src/base/UMusic.pas
+++ b/unicode/src/base/UMusic.pas
@@ -34,10 +34,11 @@ interface
{$I switches.inc}
uses
- UTime,
SysUtils,
Classes,
- UBeatTimer;
+ UTime,
+ UBeatTimer,
+ UPath;
type
TNoteType = (ntFreestyle, ntNormal, ntGolden);
@@ -315,7 +316,7 @@ type
// soundcard output-devices information
TAudioOutputDevice = class
public
- Name: string; // soundcard name
+ Name: UTF8String; // soundcard name
end;
TAudioOutputDeviceList = array of TAudioOutputDevice;
@@ -324,7 +325,7 @@ type
['{63A5EBC3-3F4D-4F23-8DFB-B5165FCE33DD}']
function GetName: String;
- function Open(const Filename: string): boolean; // true if succeed
+ function Open(const Filename: IPath): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -376,7 +377,7 @@ type
// nil-pointers is not neccessary anymore.
// PlaySound/StopSound will be removed then, OpenSound will be renamed to
// CreateSound.
- function OpenSound(const Filename: String): TAudioPlaybackStream;
+ function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure PlaySound(Stream: TAudioPlaybackStream);
procedure StopSound(Stream: TAudioPlaybackStream);
@@ -391,7 +392,7 @@ type
IGenericDecoder = Interface
['{557B0E9A-604D-47E4-B826-13769F3E10B7}']
- function GetName(): String;
+ function GetName(): string;
function InitializeDecoder(): boolean;
function FinalizeDecoder(): boolean;
//function IsSupported(const Filename: string): boolean;
@@ -406,7 +407,7 @@ type
IAudioDecoder = Interface( IGenericDecoder )
['{AB47B1B6-2AA9-4410-BF8C-EC79561B5478}']
- function Open(const Filename: string): TAudioDecodeStream;
+ function Open(const Filename: IPath): TAudioDecodeStream;
end;
IAudioInput = Interface
@@ -497,7 +498,7 @@ type
procedure StartBgMusic();
procedure PauseBgMusic();
// TODO
- //function AddSound(Filename: string): integer;
+ //function AddSound(Filename: IPath): integer;
//procedure RemoveSound(ID: integer);
//function GetSound(ID: integer): TAudioPlaybackStream;
//property Sound[ID: integer]: TAudioPlaybackStream read GetSound; default;
@@ -654,7 +655,7 @@ begin
FilterInterfaceList(IAudioDecoder, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- CurrentAudioDecoder := IAudioDecoder(InterfaceList[i]);
+ CurrentAudioDecoder := InterfaceList[i] as IAudioDecoder;
if (not CurrentAudioDecoder.InitializeDecoder()) then
begin
Log.LogError('Initialize failed, Removing - '+ CurrentAudioDecoder.GetName);
@@ -671,7 +672,7 @@ begin
FilterInterfaceList(IAudioPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- CurrentAudioPlayback := IAudioPlayback(InterfaceList[i]);
+ CurrentAudioPlayback := InterfaceList[i] as IAudioPlayback;
if (CurrentAudioPlayback.InitializePlayback()) then
begin
DefaultAudioPlayback := CurrentAudioPlayback;
@@ -686,7 +687,7 @@ begin
FilterInterfaceList(IAudioInput, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- CurrentAudioInput := IAudioInput(InterfaceList[i]);
+ CurrentAudioInput := InterfaceList[i] as IAudioInput;
if (CurrentAudioInput.InitializeRecord()) then
begin
DefaultAudioInput := CurrentAudioInput;
@@ -719,7 +720,7 @@ begin
FilterInterfaceList(IVideoPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- VideoInterface := IVideoPlayback(InterfaceList[i]);
+ VideoInterface := InterfaceList[i] as IVideoPlayback;
if (VideoInterface.Init()) then
begin
DefaultVideoPlayback := VideoInterface;
@@ -734,7 +735,7 @@ begin
FilterInterfaceList(IVideoVisualization, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
begin
- VisualInterface := IVideoVisualization(InterfaceList[i]);
+ VisualInterface := InterfaceList[i] as IVideoVisualization;
if (VisualInterface.Init()) then
begin
DefaultVisualization := VisualInterface;
@@ -748,7 +749,7 @@ begin
// now that we have all interfaces, we can dump them
// TODO: move this to another place
- if FindCmdLineSwitch( cMediaInterfaces ) then
+ if FindCmdLineSwitch(cMediaInterfaces) then
begin
DumpMediaInterfaces();
halt;
@@ -772,27 +773,27 @@ begin
// finalize audio playback interfaces (should be done before the decoders)
FilterInterfaceList(IAudioPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IAudioPlayback(InterfaceList[i]).FinalizePlayback();
+ (InterfaceList[i] as IAudioPlayback).FinalizePlayback();
// finalize audio input interfaces
FilterInterfaceList(IAudioInput, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IAudioInput(InterfaceList[i]).FinalizeRecord();
+ (InterfaceList[i] as IAudioInput).FinalizeRecord();
// finalize audio decoder interfaces
FilterInterfaceList(IAudioDecoder, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IAudioDecoder(InterfaceList[i]).FinalizeDecoder();
+ (InterfaceList[i] as IAudioDecoder).FinalizeDecoder();
// finalize video interfaces
FilterInterfaceList(IVideoPlayback, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IVideoPlayback(InterfaceList[i]).Finalize();
+ (InterfaceList[i] as IVideoPlayback).Finalize();
// finalize audio decoder interfaces
FilterInterfaceList(IVideoVisualization, MediaManager, InterfaceList);
for i := 0 to InterfaceList.Count-1 do
- IVideoVisualization(InterfaceList[i]).Finalize();
+ (InterfaceList[i] as IVideoVisualization).Finalize();
InterfaceList.Free;
@@ -855,14 +856,14 @@ procedure TSoundLibrary.LoadSounds();
begin
UnloadSounds();
- Start := AudioPlayback.OpenSound(SoundPath + 'Common start.mp3');
- Back := AudioPlayback.OpenSound(SoundPath + 'Common back.mp3');
- Swoosh := AudioPlayback.OpenSound(SoundPath + 'menu swoosh.mp3');
- Change := AudioPlayback.OpenSound(SoundPath + 'select music change music 50.mp3');
- Option := AudioPlayback.OpenSound(SoundPath + 'option change col.mp3');
- Click := AudioPlayback.OpenSound(SoundPath + 'rimshot022b.mp3');
+ Start := AudioPlayback.OpenSound(SoundPath.Append('Common start.mp3'));
+ Back := AudioPlayback.OpenSound(SoundPath.Append('Common back.mp3'));
+ Swoosh := AudioPlayback.OpenSound(SoundPath.Append('menu swoosh.mp3'));
+ Change := AudioPlayback.OpenSound(SoundPath.Append('select music change music 50.mp3'));
+ Option := AudioPlayback.OpenSound(SoundPath.Append('option change col.mp3'));
+ Click := AudioPlayback.OpenSound(SoundPath.Append('rimshot022b.mp3'));
- BGMusic := AudioPlayback.OpenSound(SoundPath + 'Bebeto_-_Loop010.mp3');
+ BGMusic := AudioPlayback.OpenSound(SoundPath.Append('Bebeto_-_Loop010.mp3'));
if (BGMusic <> nil) then
BGMusic.Loop := True;
diff --git a/unicode/src/base/UPath.pas b/unicode/src/base/UPath.pas
index 5203e7eb..fc8c028e 100644
--- a/unicode/src/base/UPath.pas
+++ b/unicode/src/base/UPath.pas
@@ -45,14 +45,17 @@ type
IPath = interface;
{**
- * TUnicodeFileStream
+ * TBinaryFileStream (inherited from THandleStream)
*}
{$IFDEF MSWINDOWS}
- TUnicodeFileStream = class(TTntFileStream)
+ TBinaryFileStream = class(TTntFileStream)
{$ELSE}
- TUnicodeFileStream = class(TFileStream)
+ TBinaryFileStream = class(TFileStream)
{$ENDIF}
public
+ {**
+ * @seealso TFileStream.Create for valid Mode parameters
+ *}
constructor Create(const FileName: IPath; Mode: Word);
end;
@@ -65,13 +68,28 @@ type
procedure SaveToFile(const FileName: IPath);
end;
+ TTextFileStream = class(TBinaryFileStream)
+ function ReadLine(var Line: UTF8String): boolean; overload;
+ function ReadLine(var Line: AnsiString): boolean; overload;
+ procedure Write(Str: RawByteString);
+ procedure WriteLine(Line: RawByteString = '');
+ end;
+
+ {**
+ * pdKeep: Keep path as is, neither remove or append a delimiter
+ * pdAppend: Append a delimiter if path does not have a trailing one
+ * pdRemove: Remove a trailing delimiter from the path
+ *}
+ TPathDelimOption = (pdKeep, pdAppend, pdRemove);
+
IPathDynArray = array of IPath;
-
+
{**
* IPath
* The Path's pathname is immutable and cannot be changed after creation.
*}
IPath = interface
+ ['{686BF103-CE43-4598-B85D-A2C3AF950897}']
{**
* Returns the path as an UTF8 encoded string.
* If UseNativeDelim is set to true, the native path delimiter ('\' on win32)
@@ -100,11 +118,6 @@ type
*}
function Open(Mode: LongWord): THandle;
- {**
- * Note: Stream must be freed with TUniFileStream.Free after usage
- *}
- function OpenStream(Mode: Word): TUnicodeFileStream;
-
{** @seealso SysUtils.ExtractFileDrive() *}
function GetDrive(): IPath;
@@ -125,7 +138,9 @@ type
* The file itself is not changed, use Rename() for this task.
* @seealso SysUtils.ChangeFileExt()
*}
- function SetExtension(const Extension: IPath): IPath;
+ function SetExtension(const Extension: IPath): IPath; overload;
+ function SetExtension(const Extension: RawByteString): IPath; overload;
+ function SetExtension(const Extension: WideString): IPath; overload;
{**
* Returns the representation of the path relative to Basename.
@@ -143,16 +158,19 @@ type
* end with a path delimiter one is inserted in front of the Child path.
* Example: Path('parent').Append(Path('child')) -> Path('parent/child')
*}
- function Append(const Child: IPath): IPath;
+ function Append(const Child: IPath; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+ function Append(const Child: RawByteString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
+ function Append(const Child: WideString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
{**
- * Splits the path into its components.
- * Example: C:\test\dir -> ['C:\', 'test\', 'dir']
+ * Splits the path into its components. Path delimiters are not removed from
+ * components.
+ * Example: C:\test\my\dir -> ['C:\', 'test\', 'my\', 'dir']
*}
function SplitDirs(): IPathDynArray;
{**
- * Returns the parent directory or PathNone if none exists.
+ * Returns the parent directory or PATH_NONE if none exists.
*}
function GetParent(): IPath;
@@ -171,10 +189,10 @@ type
function AdjustCase(AdjustAllLevels: boolean): IPath;
{** @seealso SysUtils.IncludeTrailingPathDelimiter() *}
- function IncludeTrailingPathDelimiter(): IPath;
+ function AppendPathDelim(): IPath;
{** @seealso SysUtils.ExcludeTrailingPathDelimiter() *}
- function ExcludeTrailingPathDelimiter(): IPath;
+ function RemovePathDelim(): IPath;
function Exists(): boolean;
function IsFile(): boolean;
@@ -188,12 +206,28 @@ type
function SetReadOnly(ReadOnly: boolean): boolean;
{**
+ * Checks if this path points to nothing, that means the path consists of
+ * the empty string '' and hence equals PATH_NONE.
+ * This is a shortcut for IPath.Equals('') or IPath.Equals(PATH_NONE).
+ * If IsUnset() returns true this path and PATH_NONE are equal but they must
+ * not be identical as the references might point to different objects.
+ *
+ * Example:
+ * Path('').Equals(PATH_EMPTY) -> true
+ * Path('') = PATH_EMPTY -> false
+ *}
+ function IsUnset(): boolean;
+ function IsSet(): boolean;
+
+ {**
* Compares this path with Other and returns true if both paths are
* equal. Both paths are expanded and trailing slashes excluded before
* comparison. If IgnoreCase is true, the case will be ignored on
* case-sensitive filesystems.
*}
- function Equals(const Other: IPath; IgnoreCase: boolean = false): boolean;
+ function Equals(const Other: IPath; IgnoreCase: boolean = false): boolean; overload;
+ function Equals(const Other: RawByteString; IgnoreCase: boolean = false): boolean; overload;
+ function Equals(const Other: WideString; IgnoreCase: boolean = false): boolean; overload;
{**
* Searches for a file in DirList. The Result is nil if the file was
@@ -222,17 +256,17 @@ type
* - On Apple only UTF8 is supported
* - Same applies to Unix with LC_CTYPE set to UTF8 encoding (default on newer systems)
*}
-function Path(const PathName: RawByteString): IPath; overload;
+function Path(const PathName: RawByteString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
{**
* Creates a new path with the given UTF-16 pathname.
*}
-function Path(const PathName: WideString): IPath; overload;
+function Path(const PathName: WideString; DelimOption: TPathDelimOption = pdKeep): IPath; overload;
{**
- * Returns a reference to a singleton with path simply set to ''.
+ * Returns a singleton for Path('').
*}
-function PathNone(): IPath;
+function PATH_NONE(): IPath;
implementation
@@ -247,7 +281,7 @@ type
{**
* Unifies the filename. Path-delimiters are replaced by '/'.
*}
- procedure Unify();
+ procedure Unify(DelimOption: TPathDelimOption);
{**
* Returns a copy of fName with path delimiters changed to '/'.
@@ -257,7 +291,7 @@ type
procedure AssertRefCount; inline;
public
- constructor Create(const Name: UTF8String);
+ constructor Create(const Name: UTF8String; DelimOption: TPathDelimOption);
destructor Destroy(); override;
function ToUTF8(UseNativeDelim: boolean): UTF8String;
@@ -265,27 +299,36 @@ type
function ToNative(): RawByteString;
function Open(Mode: LongWord): THandle;
- function OpenStream(Mode: Word): TUnicodeFileStream;
function GetDrive(): IPath;
function GetPath(): IPath;
function GetDir(): IPath;
function GetName(): IPath;
function GetExtension(): IPath;
- function SetExtension(const Extension: IPath): IPath;
+
+ function SetExtension(const Extension: IPath): IPath; overload;
+ function SetExtension(const Extension: RawByteString): IPath; overload;
+ function SetExtension(const Extension: WideString): IPath; overload;
+
function GetRelativePath(const BaseName: IPath): IPath;
function GetAbsolutePath(): IPath;
function GetParent(): IPath;
function SplitDirs(): IPathDynArray;
- function Append(const Child: IPath): IPath;
- function Equals(const Other: IPath; IgnoreCase: boolean): boolean;
+ function Append(const Child: IPath; DelimOption: TPathDelimOption): IPath; overload;
+ function Append(const Child: RawByteString; DelimOption: TPathDelimOption): IPath; overload;
+ function Append(const Child: WideString; DelimOption: TPathDelimOption): IPath; overload;
+
+ function Equals(const Other: IPath; IgnoreCase: boolean): boolean; overload;
+ function Equals(const Other: RawByteString; IgnoreCase: boolean): boolean; overload;
+ function Equals(const Other: WideString; IgnoreCase: boolean): boolean; overload;
+
function IsChildOf(const Parent: IPath; Direct: boolean): boolean;
function AdjustCase(AdjustAllLevels: boolean): IPath;
- function IncludeTrailingPathDelimiter(): IPath;
- function ExcludeTrailingPathDelimiter(): IPath;
+ function AppendPathDelim(): IPath;
+ function RemovePathDelim(): IPath;
function GetFileAge(): integer; overload;
function GetFileAge(out FileDateTime: TDateTime): boolean; overload;
@@ -297,7 +340,10 @@ type
function SetAttr(Attr: Integer): boolean;
function IsReadOnly(): boolean;
function SetReadOnly(ReadOnly: boolean): boolean;
-
+
+ function IsUnset(): boolean;
+ function IsSet(): boolean;
+
function FileSearch(const DirList: IPath): IPath;
function CreateFile(): THandle;
@@ -308,34 +354,36 @@ type
function CopyFile(const Target: IPath; FailIfExists: boolean): boolean;
end;
-function Path(const PathName: RawByteString): IPath;
+function Path(const PathName: RawByteString; DelimOption: TPathDelimOption): IPath;
begin
if (IsUTF8String(PathName)) then
- Result := TPathImpl.Create(PathName)
+ Result := TPathImpl.Create(PathName, DelimOption)
else if (IsNativeUTF8()) then
- Result := PathNone
+ Result := PATH_NONE
else
- Result := TPathImpl.Create(AnsiToUtf8(PathName));
+ Result := TPathImpl.Create(AnsiToUtf8(PathName), DelimOption);
end;
-function Path(const PathName: WideString): IPath;
+function Path(const PathName: WideString; DelimOption: TPathDelimOption): IPath;
begin
- Result := TPathImpl.Create(UTF8Encode(PathName));
+ Result := TPathImpl.Create(UTF8Encode(PathName), DelimOption);
end;
procedure TPathImpl.AssertRefCount;
begin
+ {$IFDEF FPC}
if (FRefCount <= 0) then
raise Exception.Create('RefCount error: ' + inttostr(FRefCount));
+ {$ENDIF}
end;
-constructor TPathImpl.Create(const Name: UTF8String);
+constructor TPathImpl.Create(const Name: UTF8String; DelimOption: TPathDelimOption);
begin
inherited Create();
fName := Name;
- Unify();
+ Unify(DelimOption);
end;
destructor TPathImpl.Destroy();
@@ -343,7 +391,7 @@ begin
inherited;
end;
-procedure TPathImpl.Unify();
+procedure TPathImpl.Unify(DelimOption: TPathDelimOption);
var
I: integer;
begin
@@ -353,6 +401,12 @@ begin
if (fName[I] in ['\', '/']) and (fName[I] <> PathDelim) then
fName[I] := PathDelim;
end;
+
+ // Include/ExcludeTrailingPathDelimiter need PathDelim as path delimiter
+ case DelimOption of
+ pdAppend: fName := IncludeTrailingPathDelimiter(fName);
+ pdRemove: fName := ExcludeTrailingPathDelimiter(fName);
+ end;
end;
function TPathImpl.GetPortableString(): UTF8String;
@@ -430,6 +484,16 @@ begin
Result := FileSystem.ChangeFileExt(Self, Extension);
end;
+function TPathImpl.SetExtension(const Extension: RawByteString): IPath;
+begin
+ Result := SetExtension(Path(Extension));
+end;
+
+function TPathImpl.SetExtension(const Extension: WideString): IPath;
+begin
+ Result := SetExtension(Path(Extension));
+end;
+
function TPathImpl.GetRelativePath(const BaseName: IPath): IPath;
begin
AssertRefCount;
@@ -448,9 +512,9 @@ var
begin
AssertRefCount;
- Result := PathNone;
+ Result := PATH_NONE;
- CurPath := Self.ExcludeTrailingPathDelimiter();
+ CurPath := Self.RemovePathDelim();
// check if current path has a parent (no further '/')
if (Pos(PathDelim, CurPath.ToUTF8()) = 0) then
Exit;
@@ -491,7 +555,7 @@ begin
// TODO: remove this workaround for FPC bug
TmpPath := CurPath;
CurPath := TmpPath.GetParent();
- until (CurPath = PathNone);
+ until (CurPath = PATH_NONE);
// reverse list
SetLength(Result, Length(Components));
@@ -499,28 +563,56 @@ begin
Result[I] := Components[High(Components)-I];
end;
-function TPathImpl.Append(const Child: IPath): IPath;
+function TPathImpl.Append(const Child: IPath; DelimOption: TPathDelimOption): IPath;
+var
+ TmpResult: IPath;
begin
AssertRefCount;
if (fName = '') then
- Result := Child
+ TmpResult := Child
else
- Result := Path(Self.IncludeTrailingPathDelimiter().ToUTF8() + Child.ToUTF8());
+ TmpResult := Path(Self.AppendPathDelim().ToUTF8() + Child.ToUTF8());
+
+ case DelimOption of
+ pdKeep: Result := TmpResult;
+ pdAppend: Result := TmpResult.AppendPathDelim;
+ pdRemove: Result := TmpResult.RemovePathDelim;
+ end;
+end;
+
+function TPathImpl.Append(const Child: RawByteString; DelimOption: TPathDelimOption): IPath;
+begin
+ Result := Append(Path(Child), DelimOption);
+end;
+
+function TPathImpl.Append(const Child: WideString; DelimOption: TPathDelimOption): IPath;
+begin
+ Result := Append(Path(Child), DelimOption);
end;
function TPathImpl.Equals(const Other: IPath; IgnoreCase: boolean): boolean;
var
SelfPath, OtherPath: UTF8String;
begin
- SelfPath := Self.GetAbsolutePath().ExcludeTrailingPathDelimiter().ToUTF8();
- OtherPath := Other.GetAbsolutePath().ExcludeTrailingPathDelimiter().ToUTF8();
+ SelfPath := Self.GetAbsolutePath().RemovePathDelim().ToUTF8();
+ OtherPath := Other.GetAbsolutePath().RemovePathDelim().ToUTF8();
if (FileSystem.IsCaseSensitive() and not IgnoreCase) then
Result := (CompareStr(SelfPath, OtherPath) = 0)
else
Result := (CompareText(SelfPath, OtherPath) = 0);
end;
+function TPathImpl.Equals(const Other: RawByteString; IgnoreCase: boolean): boolean;
+begin
+ Result := Equals(Path(Other), IgnoreCase);
+end;
+
+function TPathImpl.Equals(const Other: WideString; IgnoreCase: boolean): boolean;
+begin
+ Result := Equals(Path(Other), IgnoreCase);
+end;
+
function TPathImpl.IsChildOf(const Parent: IPath; Direct: boolean): boolean;
var
SelfPath, ParentPath: UTF8String;
@@ -533,11 +625,11 @@ begin
// TODO: remove workaround for fpc refcount bug
TmpPath := Self.GetParent();
TmpPath2 := TmpPath.GetAbsolutePath();
- SelfPath := TmpPath2.IncludeTrailingPathDelimiter().ToUTF8();
+ SelfPath := TmpPath2.AppendPathDelim().ToUTF8();
// TODO: remove workaround for fpc refcount bug
TmpPath := Parent.GetAbsolutePath();
- ParentPath := TmpPath.IncludeTrailingPathDelimiter().ToUTF8();
+ ParentPath := TmpPath.AppendPathDelim().ToUTF8();
// simply check if this paths parent path (SelfPath) equals ParentPath
Result := (SelfPath = ParentPath);
@@ -546,11 +638,11 @@ begin
begin
// TODO: remove workaround for fpc refcount bug
TmpPath := Self.GetAbsolutePath();
- SelfPath := TmpPath.IncludeTrailingPathDelimiter().ToUTF8();
+ SelfPath := TmpPath.AppendPathDelim().ToUTF8();
// TODO: remove workaround for fpc refcount bug
TmpPath := Parent.GetAbsolutePath();
- ParentPath := TmpPath.IncludeTrailingPathDelimiter().ToUTF8();
+ ParentPath := TmpPath.AppendPathDelim().ToUTF8();
if (Length(SelfPath) <= Length(ParentPath)) then
Exit;
@@ -583,12 +675,12 @@ begin
// extract name component of current path
// TODO: remove workaround for fpc refcount bug
- TmpPath := CurPath.ExcludeTrailingPathDelimiter();
+ TmpPath := CurPath.RemovePathDelim();
LocalName := TmpPath.GetName();
// try to adjust parent
OldParent := CurPath.GetParent();
- if (OldParent <> PathNone) then
+ if (OldParent <> PATH_NONE) then
begin
if (not AdjustAllLevels) then
begin
@@ -663,13 +755,13 @@ begin
end;
end;
-function TPathImpl.IncludeTrailingPathDelimiter(): IPath;
+function TPathImpl.AppendPathDelim(): IPath;
begin
AssertRefCount;
Result := FileSystem.IncludeTrailingPathDelimiter(Self);
end;
-function TPathImpl.ExcludeTrailingPathDelimiter(): IPath;
+function TPathImpl.RemovePathDelim(): IPath;
begin
AssertRefCount;
Result := FileSystem.ExcludeTrailingPathDelimiter(Self);
@@ -693,11 +785,6 @@ begin
Result := FileSystem.FileOpen(Self, Mode);
end;
-function TPathImpl.OpenStream(Mode: Word): TUnicodeFileStream;
-begin
- Result := TUnicodeFileStream.Create(Self, Mode);
-end;
-
function TPathImpl.GetFileAge(): integer;
begin
Result := FileSystem.FileAge(Self);
@@ -759,6 +846,16 @@ begin
Result := FileSystem.FileSetReadOnly(Self, ReadOnly);
end;
+function TPathImpl.IsUnset(): boolean;
+begin
+ Result := (fName = '');
+end;
+
+function TPathImpl.IsSet(): boolean;
+begin
+ Result := (fName <> '');
+end;
+
function TPathImpl.FileSearch(const DirList: IPath): IPath;
begin
AssertRefCount;
@@ -786,23 +883,38 @@ begin
end;
-{ TUnicodeFileStream }
+{ TBinaryFileStream }
+constructor TBinaryFileStream.Create(const FileName: IPath; Mode: Word);
+begin
{$IFDEF MSWINDOWS}
+ inherited Create(FileName.ToWide(), Mode);
+{$ELSE}
+ inherited Create(FileName.ToNative(), Mode);
+{$ENDIF}
+end;
+
+{ TTextFileStream }
-constructor TUnicodeFileStream.Create(const FileName: IPath; Mode: Word);
+function TTextFileStream.ReadLine(var Line: UTF8String): boolean;
begin
- inherited Create(FileName.ToWide(), Mode);
+ // TODO
end;
-{$ELSE}
+function TTextFileStream.ReadLine(var Line: AnsiString): boolean;
+begin
+ // TODO
+end;
-constructor TUnicodeFileStream.Create(const FileName: IPath; Mode: Word);
+procedure TTextFileStream.WriteLine(Line: RawByteString);
begin
- inherited Create(FileName.ToNative(), Mode);
+ Self.WriteBuffer(Line[1], Length(Line));
end;
-{$ENDIF}
+procedure TTextFileStream.Write(Str: RawByteString);
+begin
+ Self.WriteBuffer(Str[1], Length(Str));
+end;
{ TUnicodeMemoryStream }
@@ -810,7 +922,7 @@ procedure TUnicodeMemoryStream.LoadFromFile(const FileName: IPath);
var
Stream: TStream;
begin
- Stream := TUnicodeFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
+ Stream := TBinaryFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
@@ -822,7 +934,7 @@ procedure TUnicodeMemoryStream.SaveToFile(const FileName: IPath);
var
Stream: TStream;
begin
- Stream := TUnicodeFileStream.Create(FileName, fmCreate);
+ Stream := TBinaryFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
@@ -831,17 +943,17 @@ begin
end;
var
- PathNone_Singelton: IPath;
+ PATH_NONE_Singelton: IPath;
-function PathNone(): IPath;
+function PATH_NONE(): IPath;
begin
- Result := PathNone_Singelton;
+ Result := PATH_NONE_Singelton;
end;
initialization
- PathNone_Singelton := Path('');
+ PATH_NONE_Singelton := Path('');
finalization
- PathNone_Singelton := nil;
+ PATH_NONE_Singelton := nil;
end.
diff --git a/unicode/src/base/UPathUtils.pas b/unicode/src/base/UPathUtils.pas
index 4c4d3bc0..c2bcdd4b 100644
--- a/unicode/src/base/UPathUtils.pas
+++ b/unicode/src/base/UPathUtils.pas
@@ -35,28 +35,29 @@ interface
uses
SysUtils,
- Classes;
+ Classes,
+ UPath;
var
// Absolute Paths
- GamePath: string;
- SoundPath: string;
- SongPaths: TStringList;
- LogPath: string;
- ThemePath: string;
- SkinsPath: string;
- ScreenshotsPath: string;
- CoverPaths: TStringList;
- LanguagesPath: string;
- PluginPath: string;
- VisualsPath: string;
- FontPath: string;
- ResourcesPath: string;
- PlayListPath: string;
-
-function FindPath(out PathResult: string; const RequestedPath: string; NeedsWritePermission: boolean): boolean;
+ GamePath: IPath;
+ SoundPath: IPath;
+ SongPaths: IInterfaceList;
+ LogPath: IPath;
+ ThemePath: IPath;
+ SkinsPath: IPath;
+ ScreenshotsPath: IPath;
+ CoverPaths: IInterfaceList;
+ LanguagesPath: IPath;
+ PluginPath: IPath;
+ VisualsPath: IPath;
+ FontPath: IPath;
+ ResourcesPath: IPath;
+ PlaylistPath: IPath;
+
+function FindPath(out PathResult: IPath; const RequestedPath: IPath; NeedsWritePermission: boolean): boolean;
procedure InitializePaths;
-procedure AddSongPath(const Path: string);
+procedure AddSongPath(const Path: IPath);
implementation
@@ -66,33 +67,38 @@ uses
UCommandLine,
ULog;
-procedure AddSpecialPath(var PathList: TStringList; const Path: string);
+procedure AddSpecialPath(var PathList: IInterfaceList; const Path: IPath);
var
Index: integer;
- PathAbs, OldPathAbs: string;
+ PathAbs, PathTmp: IPath;
+ OldPath, OldPathAbs, OldPathTmp: IPath;
begin
if (PathList = nil) then
- PathList := TStringList.Create;
+ PathList := TInterfaceList.Create;
- if (Path = '') or not ForceDirectories(Path) then
+ if Path.Equals(PATH_NONE) or not Path.CreateDirectory(true) then
Exit;
- PathAbs := IncludeTrailingPathDelimiter(ExpandFileName(Path));
+ PathTmp := Path.GetAbsolutePath();
+ PathAbs := PathTmp.AppendPathDelim();
// check if path or a part of the path was already added
for Index := 0 to PathList.Count-1 do
begin
- OldPathAbs := IncludeTrailingPathDelimiter(ExpandFileName(PathList[Index]));
+ OldPath := PathList[Index] as IPath;
+ OldPathTmp := OldPath.GetAbsolutePath();
+ OldPathAbs := OldPathTmp.AppendPathDelim();
+
// check if the new directory is a sub-directory of a previously added one.
// This is also true, if both paths point to the same directories.
- if (AnsiStartsText(OldPathAbs, PathAbs)) then
+ if (OldPathAbs.IsChildOf(PathAbs, false) or OldPathAbs.Equals(PathAbs)) then
begin
// ignore the new path
Exit;
end;
// check if a previously added directory is a sub-directory of the new one.
- if (AnsiStartsText(PathAbs, OldPathAbs)) then
+ if (PathAbs.IsChildOf(OldPathAbs, false)) then
begin
// replace the old with the new one.
PathList[Index] := PathAbs;
@@ -103,12 +109,12 @@ begin
PathList.Add(PathAbs);
end;
-procedure AddSongPath(const Path: string);
+procedure AddSongPath(const Path: IPath);
begin
AddSpecialPath(SongPaths, Path);
end;
-procedure AddCoverPath(const Path: string);
+procedure AddCoverPath(const Path: IPath);
begin
AddSpecialPath(CoverPaths, Path);
end;
@@ -117,30 +123,27 @@ end;
* Initialize a path variable
* After setting paths, make sure that paths exist
*)
-function FindPath(out PathResult: string;
- const RequestedPath: string;
- NeedsWritePermission: boolean)
- : boolean;
+function FindPath(
+ out PathResult: IPath;
+ const RequestedPath: IPath;
+ NeedsWritePermission: boolean): boolean;
begin
Result := false;
- if (RequestedPath = '') then
+ if (RequestedPath.Equals(PATH_NONE)) then
Exit;
// Make sure the directory exists
- if (not ForceDirectories(RequestedPath)) then
+ if (not RequestedPath.CreateDirectory(true)) then
begin
- PathResult := '';
+ PathResult := PATH_NONE;
Exit;
end;
- PathResult := IncludeTrailingPathDelimiter(RequestedPath);
+ PathResult := RequestedPath.AppendPathDelim();
- if (NeedsWritePermission) and
- (FileIsReadOnly(RequestedPath)) then
- begin
+ if (NeedsWritePermission) and RequestedPath.IsReadOnly() then
Exit;
- end;
Result := true;
end;
@@ -149,40 +152,45 @@ end;
* Function sets all absolute paths e.g. song path and makes sure the directorys exist
*)
procedure InitializePaths;
+var
+ SharedPath, UserPath: IPath;
begin
// Log directory (must be writable)
if (not FindPath(LogPath, Platform.GetLogPath, true)) then
begin
Log.FileOutputEnabled := false;
- Log.LogWarn('Log directory "'+ Platform.GetLogPath +'" not available', 'InitializePaths');
+ Log.LogWarn('Log directory "'+ Platform.GetLogPath.ToNative +'" not available', 'InitializePaths');
end;
- FindPath(SoundPath, Platform.GetGameSharedPath + 'sounds', false);
- FindPath(ThemePath, Platform.GetGameSharedPath + 'themes', false);
- FindPath(SkinsPath, Platform.GetGameSharedPath + 'themes', false);
- FindPath(LanguagesPath, Platform.GetGameSharedPath + 'languages', false);
- FindPath(PluginPath, Platform.GetGameSharedPath + 'plugins', false);
- FindPath(VisualsPath, Platform.GetGameSharedPath + 'visuals', false);
- FindPath(FontPath, Platform.GetGameSharedPath + 'fonts', false);
- FindPath(ResourcesPath, Platform.GetGameSharedPath + 'resources', false);
+ SharedPath := Platform.GetGameSharedPath;
+ UserPath := Platform.GetGameUserPath;
+
+ FindPath(SoundPath, SharedPath.Append('sounds'), false);
+ FindPath(ThemePath, SharedPath.Append('themes'), false);
+ FindPath(SkinsPath, SharedPath.Append('themes'), false);
+ FindPath(LanguagesPath, SharedPath.Append('languages'), false);
+ FindPath(PluginPath, SharedPath.Append('plugins'), false);
+ FindPath(VisualsPath, SharedPath.Append('visuals'), false);
+ FindPath(FontPath, SharedPath.Append('fonts'), false);
+ FindPath(ResourcesPath, SharedPath.Append('resources'), false);
// Playlists are not shared as we need one directory to write too
- FindPath(PlaylistPath, Platform.GetGameUserPath + 'playlists', true);
+ FindPath(PlaylistPath, UserPath.Append('playlists'), true);
// Screenshot directory (must be writable)
- if (not FindPath(ScreenshotsPath, Platform.GetGameUserPath + 'screenshots', true)) then
+ if (not FindPath(ScreenshotsPath, UserPath.Append('screenshots'), true)) then
begin
- Log.LogWarn('Screenshot directory "'+ Platform.GetGameUserPath +'" not available', 'InitializePaths');
+ Log.LogWarn('Screenshot directory "'+ UserPath.ToNative +'" not available', 'InitializePaths');
end;
// Add song paths
AddSongPath(Params.SongPath);
- AddSongPath(Platform.GetGameSharedPath + 'songs');
- AddSongPath(Platform.GetGameUserPath + 'songs');
+ AddSongPath(SharedPath.Append('songs'));
+ AddSongPath(UserPath.Append('songs'));
// Add category cover paths
- AddCoverPath(Platform.GetGameSharedPath + 'covers');
- AddCoverPath(Platform.GetGameUserPath + 'covers');
+ AddCoverPath(SharedPath.Append('covers'));
+ AddCoverPath(UserPath.Append('covers'));
end;
end.
diff --git a/unicode/src/base/UPlatform.pas b/unicode/src/base/UPlatform.pas
index 6f13481c..11c67fa7 100644
--- a/unicode/src/base/UPlatform.pas
+++ b/unicode/src/base/UPlatform.pas
@@ -39,28 +39,20 @@ interface
{$I switches.inc}
uses
- Classes;
+ Classes,
+ UPath;
type
- TDirectoryEntry = record
- Name: WideString;
- IsDirectory: boolean;
- IsFile: boolean;
- end;
-
- TDirectoryEntryArray = array of TDirectoryEntry;
-
TPlatform = class
- function GetExecutionDir(): string;
+ function GetExecutionDir(): IPath;
procedure Init; virtual;
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray; virtual; abstract;
+
function TerminateIfAlreadyRunning(var WndTitle: string): boolean; virtual;
- function FindSongFile(Dir, Mask: WideString): WideString; virtual;
procedure Halt; virtual;
- function GetLogPath: WideString; virtual; abstract;
- function GetGameSharedPath: WideString; virtual; abstract;
- function GetGameUserPath: WideString; virtual; abstract;
- function CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean; virtual;
+
+ function GetLogPath: IPath; virtual; abstract;
+ function GetGameSharedPath: IPath; virtual; abstract;
+ function GetGameUserPath: IPath; virtual; abstract;
end;
function Platform(): TPlatform;
@@ -76,7 +68,9 @@ uses
{$ELSEIF Defined(UNIX)}
UPlatformLinux,
{$IFEND}
- ULog;
+ ULog,
+ UUnicodeUtils,
+ UFilesystem;
// I modified it to use the Platform_singleton in this location (in the implementation)
@@ -109,9 +103,13 @@ end;
{**
* Returns the directory of the executable
*}
-function TPlatform.GetExecutionDir(): string;
+function TPlatform.GetExecutionDir(): IPath;
+var
+ ExecName, ExecDir: IPath;
begin
- Result := ExpandFileName(ExtractFilePath(ParamStr(0)));
+ ExecName := Path(ParamStr(0));
+ ExecDir := ExecName.GetPath;
+ Result := ExecDir.GetAbsolutePath();
end;
(**
@@ -122,65 +120,6 @@ begin
Result := false;
end;
-(**
- * Default FindSongFile() implementation
- *)
-function TPlatform.FindSongFile(Dir, Mask: WideString): WideString;
-var
- SR: TSearchRec; // for parsing song directory
-begin
- Result := '';
- if SysUtils.FindFirst(Dir + Mask, faDirectory, SR) = 0 then
- begin
- Result := SR.Name;
- end;
- SysUtils.FindClose(SR);
-end;
-
-function TPlatform.CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean;
-const
- COPY_BUFFER_SIZE = 4096; // a good tradeoff between speed and memory consumption
-var
- SourceFile, TargetFile: TFileStream;
- FileCopyBuffer: array [0..COPY_BUFFER_SIZE-1] of byte; // temporary copy-buffer.
- NumberOfBytes: integer; // number of bytes read from SourceFile
-begin
- Result := false;
- SourceFile := nil;
- TargetFile := nil;
-
- // if overwrite is disabled return if the target file already exists
- if (FailIfExists and FileExists(Target)) then
- Exit;
-
- try
- try
- // open source and target file (might throw an exception on error)
- SourceFile := TFileStream.Create(Source, fmOpenRead);
- TargetFile := TFileStream.Create(Target, fmCreate or fmOpenWrite);
-
- while true do
- begin
- // read a block from the source file and check for errors or EOF
- NumberOfBytes := SourceFile.Read(FileCopyBuffer, SizeOf(FileCopyBuffer));
- if (NumberOfBytes <= 0) then
- Break;
- // write block to target file and check if everything was written
- if (TargetFile.Write(FileCopyBuffer, NumberOfBytes) <> NumberOfBytes) then
- Exit;
- end;
- except
- Exit;
- end;
- finally
- SourceFile.Free;
- TargetFile.Free;
- end;
-
- Result := true;
-end;
-
-
initialization
{$IF Defined(MSWINDOWS)}
Platform_singleton := TPlatformWindows.Create;
diff --git a/unicode/src/base/UPlatformLinux.pas b/unicode/src/base/UPlatformLinux.pas
index 7efeb963..f318d49d 100644
--- a/unicode/src/base/UPlatformLinux.pas
+++ b/unicode/src/base/UPlatformLinux.pas
@@ -44,15 +44,13 @@ type
UseLocalDirs: boolean;
procedure DetectLocalExecution();
- function GetHomeDir(): string;
+ function GetHomeDir(): IPath;
public
procedure Init; override;
-
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray; override;
-
- function GetLogPath : WideString; override;
- function GetGameSharedPath : WideString; override;
- function GetGameUserPath : WideString; override;
+
+ function GetLogPath : IPath; override;
+ function GetGameSharedPath : IPath; override;
+ function GetGameUserPath : IPath; override;
end;
implementation
@@ -60,9 +58,7 @@ implementation
uses
UCommandLine,
BaseUnix,
- {$IF FPC_VERSION_INT >= 2002002}
pwd,
- {$IFEND}
SysUtils,
ULog;
@@ -88,113 +84,65 @@ end;
*}
procedure TPlatformLinux.DetectLocalExecution();
var
- LocalDir: string;
+ LocalDir, LanguageDir: IPath;
begin
- LocalDir := GetExecutionDir();
-
// we just check if the 'languages' folder exists in the
// directory of the executable. If so -> local execution.
- UseLocalDirs := (DirectoryExists(LocalDir + 'languages'));
-end;
-
-function TPlatformLinux.DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray;
-var
- i: Integer;
- TheDir : pDir;
- ADirent : pDirent;
- lAttrib : integer;
-begin
- i := 0;
- Filter := LowerCase(Filter);
-
- TheDir := FpOpenDir(Dir);
- if Assigned(TheDir) 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 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;
+ LocalDir := GetExecutionDir();
+ LanguageDir := LocalDir.Append('languages');
+ UseLocalDirs := LanguageDir.IsDirectory;
end;
-function TPlatformLinux.GetLogPath: WideString;
+function TPlatformLinux.GetLogPath: IPath;
begin
if UseLocalDirs then
Result := GetExecutionDir()
else
- Result := GetGameUserPath() + 'logs/';
+ Result := GetGameUserPath().Append('logs', pdAppend);
// create non-existing directories
- ForceDirectories(Result);
+ Result.CreateDirectory(true);
end;
-function TPlatformLinux.GetGameSharedPath: WideString;
+function TPlatformLinux.GetGameSharedPath: IPath;
begin
if UseLocalDirs then
Result := GetExecutionDir()
else
- Result := IncludeTrailingPathDelimiter(INSTALL_DATADIR);
+ Result := Path(INSTALL_DATADIR, pdAppend);
end;
-function TPlatformLinux.GetGameUserPath: WideString;
+function TPlatformLinux.GetGameUserPath: IPath;
begin
if UseLocalDirs then
Result := GetExecutionDir()
else
- Result := GetHomeDir() + '.ultrastardx/';
+ Result := GetHomeDir().Append('.ultrastardx', pdAppend);
end;
{**
* Returns the user's home directory terminated by a path delimiter
*}
-function TPlatformLinux.GetHomeDir(): string;
-{$IF FPC_VERSION_INT >= 2002002}
+function TPlatformLinux.GetHomeDir(): IPath;
var
PasswdEntry: PPasswd;
-{$IFEND}
begin
- Result := '';
+ Result := PATH_NONE;
- {$IF FPC_VERSION_INT >= 2002002}
// try to retrieve the info from passwd
PasswdEntry := FpGetpwuid(FpGetuid());
if (PasswdEntry <> nil) then
- Result := PasswdEntry.pw_dir;
- {$IFEND}
+ Result := Path(PasswdEntry.pw_dir);
// fallback if passwd does not contain the path
- if (Result = '') then
- Result := GetEnvironmentVariable('HOME');
+ if (Result.IsUnset) then
+ Result := Path(GetEnvironmentVariable('HOME'));
// add trailing path delimiter (normally '/')
- if (Result <> '') then
- Result := IncludeTrailingPathDelimiter(Result);
+ if (Result.IsSet) then
+ Result := Result.AppendPathDelim();
- {$IF FPC_VERSION_INT >= 2002002}
// GetUserDir() is another function that returns a user path.
// It uses env-var HOME or a fallback to a temp-dir.
//Result := GetUserDir();
- {$IFEND}
end;
end.
diff --git a/unicode/src/base/UPlatformMacOSX.pas b/unicode/src/base/UPlatformMacOSX.pas
index 08ad247d..aa1eb7cf 100644
--- a/unicode/src/base/UPlatformMacOSX.pas
+++ b/unicode/src/base/UPlatformMacOSX.pas
@@ -36,7 +36,8 @@ interface
uses
Classes,
ULog,
- UPlatform;
+ UPlatform,
+ UPath;
type
{**
@@ -93,13 +94,13 @@ type
* GetBundlePath returns the path to the application bundle
* UltraStarDeluxe.app.
*}
- function GetBundlePath: WideString;
+ function GetBundlePath: IPath;
{**
* GetApplicationSupportPath returns the path to
* $HOME/Library/Application Support/UltraStarDeluxe.
*}
- function GetApplicationSupportPath: WideString;
+ function GetApplicationSupportPath: IPath;
{**
* see the description of @link(Init).
@@ -116,30 +117,24 @@ type
procedure Init; override;
{**
- * DirectoryFindFiles returns all entries of a folder with names and
- * booleans about their type, i.e. file or directory.
- *}
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray; override;
-
- {**
* GetLogPath returns the path for log messages. Currently it is set to
* $HOME/Library/Application Support/UltraStarDeluxe/Log.
*}
- function GetLogPath : WideString; override;
+ function GetLogPath : IPath; override;
{**
* GetGameSharedPath returns the path for shared resources. Currently it
* is set to /Library/Application Support/UltraStarDeluxe.
* However it is not used.
*}
- function GetGameSharedPath : WideString; override;
+ function GetGameSharedPath : IPath; override;
{**
* GetGameUserPath returns the path for user resources. Currently it is
* set to $HOME/Library/Application Support/UltraStarDeluxe.
* This is where a user can add songs, themes, ....
*}
- function GetGameUserPath : WideString; override;
+ function GetGameUserPath : IPath; override;
end;
implementation
@@ -248,87 +243,38 @@ begin
ChDir(OldBaseDir);
end;
-function TPlatformMacOSX.GetBundlePath: WideString;
+function TPlatformMacOSX.GetBundlePath: IPath;
var
- i, pos : integer;
+ TmpPath: IPath;
begin
// Mac applications are packaged in folders.
// Cutting the last two folders yields the application folder.
-
- Result := GetExecutionDir();
- for i := 1 to 2 do
- begin
- pos := Length(Result);
- repeat
- Delete(Result, pos, 1);
- pos := Length(Result);
- until (pos = 0) or (Result[pos] = '/');
- end;
+ TmpPath := GetExecutionDir().GetParent;
+ Result := TmpPath.GetParent;
end;
-function TPlatformMacOSX.GetApplicationSupportPath: WideString;
+function TPlatformMacOSX.GetApplicationSupportPath: IPath;
const
PathName : string = '/Library/Application Support/UltraStarDeluxe';
+ HomeDir: IPath;
begin
- Result := GetEnvironmentVariable('HOME') + PathName + '/';
+ HomeDir := GetEnvironmentVariable('HOME');
+ Result := HomeDir.Append(PathName, true);
end;
-function TPlatformMacOSX.GetLogPath: WideString;
+function TPlatformMacOSX.GetLogPath: IPath;
begin
- Result := GetApplicationSupportPath + 'Logs';
+ Result := GetApplicationSupportPath.Append('Logs');
end;
-function TPlatformMacOSX.GetGameSharedPath: WideString;
+function TPlatformMacOSX.GetGameSharedPath: IPath;
begin
Result := GetApplicationSupportPath;
end;
-function TPlatformMacOSX.GetGameUserPath: WideString;
+function TPlatformMacOSX.GetGameUserPath: IPath;
begin
Result := GetApplicationSupportPath;
end;
-{ TODO: REMOVE }
-function TPlatformMacOSX.DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: boolean): TDirectoryEntryArray;
-var
- i : integer;
- TheDir : pdir;
- ADirent : pDirent;
- lAttrib : integer;
-begin
- i := 0;
- Filter := LowerCase(Filter);
-
- TheDir := FpOpenDir(Dir);
- if Assigned(TheDir) 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 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;
-
end.
diff --git a/unicode/src/base/UPlatformWindows.pas b/unicode/src/base/UPlatformWindows.pas
index e198958a..2d0bd212 100644
--- a/unicode/src/base/UPlatformWindows.pas
+++ b/unicode/src/base/UPlatformWindows.pas
@@ -38,21 +38,19 @@ interface
uses
Classes,
- UPlatform;
+ UPlatform,
+ UPath;
type
TPlatformWindows = class(TPlatform)
private
- function GetSpecialPath(CSIDL: integer): WideString;
+ function GetSpecialPath(CSIDL: integer): IPath;
public
- function DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray; override;
function TerminateIfAlreadyRunning(var WndTitle: String): Boolean; override;
- function GetLogPath: WideString; override;
- function GetGameSharedPath: WideString; override;
- function GetGameUserPath: WideString; override;
-
- function CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean; override;
+ function GetLogPath: IPath; override;
+ function GetGameSharedPath: IPath; override;
+ function GetGameUserPath: IPath; override;
end;
implementation
@@ -63,62 +61,10 @@ uses
Windows,
UConfig;
-type
- TSearchRecW = record
- Time: Integer;
- Size: Integer;
- Attr: Integer;
- Name: WideString;
- ExcludeAttr: Integer;
- FindHandle: THandle;
- FindData: TWin32FindDataW;
- end;
-
-function FindFirstW(const Path: WideString; Attr: Integer; var F: TSearchRecW): Integer; forward;
-function FindNextW(var F: TSearchRecW): Integer; forward;
-procedure FindCloseW(var F: TSearchRecW); forward;
+(*
function FindMatchingFileW(var F: TSearchRecW): Integer; forward;
function DirectoryExistsW(const Directory: widestring): Boolean; forward;
-function FindFirstW(const Path: widestring; Attr: Integer; var F: TSearchRecW): Integer;
-const
- faSpecial = faHidden or faSysFile or faVolumeID or faDirectory;
-begin
- F.ExcludeAttr := not Attr and faSpecial;
-{$IFDEF Delphi}
- F.FindHandle := FindFirstFileW(PWideChar(Path), F.FindData);
-{$ELSE}
- F.FindHandle := FindFirstFileW(PWideChar(Path), @F.FindData);
-{$ENDIF}
- if F.FindHandle <> INVALID_HANDLE_VALUE then
- begin
- Result := FindMatchingFileW(F);
- if Result <> 0 then FindCloseW(F);
- end else
- Result := GetLastError;
-end;
-
-function FindNextW(var F: TSearchRecW): Integer;
-begin
-{$IFDEF Delphi}
- if FindNextFileW(F.FindHandle, F.FindData) then
-{$ELSE}
- if FindNextFileW(F.FindHandle, @F.FindData) then
-{$ENDIF}
- Result := FindMatchingFileW(F)
- else
- Result := GetLastError;
-end;
-
-procedure FindCloseW(var F: TSearchRecW);
-begin
- if F.FindHandle <> INVALID_HANDLE_VALUE then
- begin
- Windows.FindClose(F.FindHandle);
- F.FindHandle := INVALID_HANDLE_VALUE;
- end;
-end;
-
function FindMatchingFileW(var F: TSearchRecW): Integer;
var
LocalFileTime: TFileTime;
@@ -151,6 +97,7 @@ begin
Code := GetFileAttributesW(PWideChar(Directory));
Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end;
+*)
//------------------------------
//Start more than One Time Prevention
@@ -180,41 +127,6 @@ begin
end;
end;
-function TPlatformWindows.DirectoryFindFiles(Dir, Filter: WideString; ReturnAllSubDirs: Boolean): TDirectoryEntryArray;
-var
- i : Integer;
- SR : TSearchRecW;
- Attrib : Integer;
-begin
- i := 0;
- Filter := LowerCase(Filter);
-
- if FindFirstW(Dir + '*', faAnyFile or faDirectory, SR) = 0 then
- repeat
- if (SR.Name <> '.') and (SR.Name <> '..') then
- begin
- Attrib := FileGetAttr(Dir + SR.name);
- if ReturnAllSubDirs and ((Attrib and faDirectory) <> 0) then
- begin
- SetLength( Result, i + 1);
- Result[i].Name := SR.name;
- Result[i].IsDirectory := true;
- Result[i].IsFile := false;
- i := i + 1;
- end
- else if (Length(Filter) = 0) or (Pos( Filter, LowerCase(SR.Name)) > 0) then
- begin
- SetLength( Result, i + 1);
- Result[i].Name := SR.Name;
- Result[i].IsDirectory := false;
- Result[i].IsFile := true;
- i := i + 1;
- end;
- end;
- until FindNextW(SR) <> 0;
- FindCloseW(SR);
-end;
-
(**
* Returns the path of a special folder.
*
@@ -225,37 +137,30 @@ end;
* CSIDL_PERSONAL (e.g. C:\Documents and Settings\username\My Documents)
* CSIDL_MYMUSIC (e.g. C:\Documents and Settings\username\My Documents\My Music)
*)
-function TPlatformWindows.GetSpecialPath(CSIDL: integer): WideString;
+function TPlatformWindows.GetSpecialPath(CSIDL: integer): IPath;
var
Buffer: array [0..MAX_PATH-1] of WideChar;
begin
-{$IF Defined(Delphi) or (FPC_VERSION_INT >= 2002002)} // >= 2.2.2
if (SHGetSpecialFolderPathW(0, @Buffer, CSIDL, false)) then
- Result := Buffer
+ Result := Path(Buffer)
else
-{$IFEND}
- Result := '';
+ Result := PATH_NONE;
end;
-function TPlatformWindows.GetLogPath: WideString;
+function TPlatformWindows.GetLogPath: IPath;
begin
Result := GetExecutionDir();
end;
-function TPlatformWindows.GetGameSharedPath: WideString;
+function TPlatformWindows.GetGameSharedPath: IPath;
begin
Result := GetExecutionDir();
end;
-function TPlatformWindows.GetGameUserPath: WideString;
+function TPlatformWindows.GetGameUserPath: IPath;
begin
- //Result := GetSpecialPath(CSIDL_APPDATA) + PathDelim + 'UltraStarDX' + PathDelim;
+ //Result := GetSpecialPath(CSIDL_APPDATA).Append('UltraStarDX', pdAppend);
Result := GetExecutionDir();
end;
-function TPlatformWindows.CopyFile(const Source, Target: WideString; FailIfExists: boolean): boolean;
-begin
- Result := Windows.CopyFileW(PWideChar(Source), PWideChar(Target), FailIfExists);
-end;
-
end.
diff --git a/unicode/src/base/UPlaylist.pas b/unicode/src/base/UPlaylist.pas
index cc983a9e..09c196ef 100644
--- a/unicode/src/base/UPlaylist.pas
+++ b/unicode/src/base/UPlaylist.pas
@@ -34,7 +34,9 @@ interface
{$I switches.inc}
uses
+ Classes,
USong,
+ UPath,
UPathUtils;
type
@@ -47,8 +49,8 @@ type
APlaylistItem = array of TPlaylistItem;
TPlaylist = record
- Name: string;
- Filename: String;
+ Name: UTF8String;
+ Filename: IPath;
Items: APlaylistItem;
end;
@@ -68,20 +70,20 @@ type
Playlists: APlaylist;
constructor Create;
- Procedure LoadPlayLists;
- Function LoadPlayList(Index: Cardinal; const Filename: String): Boolean;
- Procedure SavePlayList(Index: Cardinal);
+ procedure LoadPlayLists;
+ function LoadPlayList(Index: Cardinal; const Filename: IPath): Boolean;
+ procedure SavePlayList(Index: Cardinal);
- Procedure SetPlayList(Index: Cardinal);
+ procedure SetPlayList(Index: Cardinal);
- Function AddPlaylist(const Name: string): Cardinal;
- Procedure DelPlaylist(const Index: Cardinal);
+ function AddPlaylist(const Name: UTF8String): Cardinal;
+ procedure DelPlaylist(const Index: Cardinal);
- Procedure AddItem(const SongID: Cardinal; const iPlaylist: Integer = -1);
- Procedure DelItem(const iItem: Cardinal; const iPlaylist: Integer = -1);
+ procedure AddItem(const SongID: Cardinal; const iPlaylist: Integer = -1);
+ procedure DelItem(const iItem: Cardinal; const iPlaylist: Integer = -1);
- Procedure GetNames(var PLNames: array of string);
- Function GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer = -1): Integer;
+ procedure GetNames(var PLNames: array of UTF8String);
+ function GetIndexbySongID(const SongID: Cardinal; const iPlaylist: Integer = -1): Integer;
end;
{Modes:
@@ -95,13 +97,15 @@ type
implementation
-uses USongs,
- ULog,
- UMain,
- //UFiles,
- UGraphic,
- UThemes,
- SysUtils;
+uses
+ SysUtils,
+ USongs,
+ ULog,
+ UMain,
+ UFilesystem,
+ UGraphic,
+ UThemes,
+ UUnicodeUtils;
//----------
//Create - Construct Class - Dummy for now
@@ -117,90 +121,90 @@ end;
//----------
Procedure TPlayListManager.LoadPlayLists;
var
- SR: TSearchRec;
Len: Integer;
PlayListBuffer: TPlayList;
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
begin
SetLength(Playlists, 0);
- if FindFirst(PlayListPath + '*.upl', 0, SR) = 0 then
+ Iter := FileSystem.FileFind(PlayListPath.Append('*.upl'), 0);
+ while (Iter.HasNext) do
begin
- repeat
- Len := Length(Playlists);
- SetLength(Playlists, Len +1);
+ Len := Length(Playlists);
+ SetLength(Playlists, Len + 1);
+
+ FileInfo := Iter.Next;
- if not LoadPlayList (Len, Sr.Name) then
- SetLength(Playlists, Len)
- else
+ if not LoadPlayList(Len, FileInfo.Name) then
+ SetLength(Playlists, Len)
+ else
+ begin
+ // Sort the Playlists - Insertion Sort
+ PlayListBuffer := Playlists[Len];
+ Dec(Len);
+ while (Len >= 0) AND (CompareText(Playlists[Len].Name, PlayListBuffer.Name) >= 0) do
begin
- // Sort the Playlists - Insertion Sort
- PlayListBuffer := Playlists[Len];
- Dec(Len);
- while (Len >= 0) AND (CompareText(Playlists[Len].Name, PlayListBuffer.Name) >= 0) do
- begin
- Playlists[Len+1] := Playlists[Len];
- Dec(Len);
- end;
- Playlists[Len+1] := PlayListBuffer;
+ Playlists[Len+1] := Playlists[Len];
+ Dec(Len);
end;
-
- until FindNext(SR) <> 0;
- FindClose(SR);
- end;
+ Playlists[Len+1] := PlayListBuffer;
+ end;
+ end;
end;
//----------
//LoadPlayList - Load a Playlist in the Array
//----------
-Function TPlayListManager.LoadPlayList(Index: Cardinal; const Filename: String): Boolean;
- var
- F: TextFile;
- Line: String;
- PosDelimiter: Integer;
- SongID: Integer;
- Len: Integer;
+function TPlayListManager.LoadPlayList(Index: Cardinal; const Filename: IPath): Boolean;
- Function FindSong(Artist, Title: UTF8String): Integer;
+ function FindSong(Artist, Title: UTF8String): Integer;
var I: Integer;
begin
Result := -1;
For I := low(CatSongs.Song) to high(CatSongs.Song) do
begin
- if (CatSongs.Song[I].Title = Title) AND (CatSongs.Song[I].Artist = Artist) then
+ if (CatSongs.Song[I].Title = Title) and (CatSongs.Song[I].Artist = Artist) then
begin
Result := I;
Break;
end;
end;
end;
+
+var
+ TextStream: TTextFileStream;
+ Line: UTF8String;
+ PosDelimiter: Integer;
+ SongID: Integer;
+ Len: Integer;
+ FilenameAbs: IPath;
begin
- if not FileExists(PlayListPath + Filename) then
- begin
- Log.LogError('Could not load Playlist: ' + Filename);
- Result := False;
- Exit;
+ //Load File
+ try
+ FilenameAbs := PlaylistPath.Append(Filename);
+ TextStream := TTextFileStream.Create(FilenameAbs, fmOpenRead);
+ except
+ begin
+ Log.LogError('Could not load Playlist: ' + FilenameAbs.ToNative);
+ Result := False;
+ Exit;
+ end;
end;
Result := True;
- //Load File
- AssignFile(F, PlayListPath + FileName);
- Reset(F);
-
//Set Filename
- PlayLists[Index].Filename := Filename;
- PlayLists[Index].Name := '';
+ Playlists[Index].Filename := Filename;
+ Playlists[Index].Name := '';
//Read Until End of File
- While not Eof(F) do
+ while TextStream.ReadLine(Line) do
begin
- //Read Curent Line
- Readln(F, Line);
-
if (Length(Line) > 0) then
begin
- PosDelimiter := Pos(':', Line);
- if (PosDelimiter <> 0) then
+ PosDelimiter := UTF8Pos(':', Line);
+ if (PosDelimiter <> 0) then
begin
//Comment or Name String
if (Line[1] = '#') then
@@ -224,7 +228,7 @@ begin
PlayLists[Index].Items[Len].Artist := Trim(copy(Line, 1, PosDelimiter - 1));
PlayLists[Index].Items[Len].Title := Trim(copy(Line, PosDelimiter + 1, Length(Line) - PosDelimiter));
end
- else Log.LogError('Could not find Song in Playlist: ' + PlayLists[Index].Filename + ', ' + Line);
+ else Log.LogError('Could not find Song in Playlist: ' + PlayLists[Index].Filename.ToNative + ', ' + Line);
end;
end;
end;
@@ -233,71 +237,70 @@ begin
//If no special name is given, use Filename
if PlayLists[Index].Name = '' then
begin
- PlayLists[Index].Name := ChangeFileExt(FileName, '');
+ PlayLists[Index].Name := FileName.SetExtension('').ToUTF8;
end;
//Finish (Close File)
- CloseFile(F);
+ TextStream.Free;
end;
-//----------
-//SavePlayList - Saves the specified Playlist
-//----------
-Procedure TPlayListManager.SavePlayList(Index: Cardinal);
+{**
+ * Saves the specified Playlist
+ *}
+procedure TPlayListManager.SavePlayList(Index: Cardinal);
var
- F: TextFile;
+ TextStream: TTextFileStream;
+ PlaylistFile: IPath;
I: Integer;
begin
- if (Not FileExists(PlaylistPath + Playlists[Index].Filename)) OR (Not FileisReadOnly(PlaylistPath + Playlists[Index].Filename)) then
- begin
+ PlaylistFile := PlaylistPath.Append(Playlists[Index].Filename);
- //open File for Rewriting
- AssignFile(F, PlaylistPath + Playlists[Index].Filename);
- try
- try
- Rewrite(F);
+ // cannot update read-only file
+ if PlaylistFile.IsFile() and PlaylistFile.IsReadOnly() then
+ Exit;
- //Write Version (not nessecary but helpful)
- WriteLn(F, '######################################');
- WriteLn(F, '#Ultrastar Deluxe Playlist Format v1.0');
- WriteLn(F, '#Playlist "' + Playlists[Index].Name + '" with ' + InttoStr(Length(Playlists[Index].Items)) + ' Songs.');
- WriteLn(F, '######################################');
+ // open file for rewriting
+ TextStream := TTextFileStream.Create(PlaylistFile, fmCreate);
+ try
+ // Write version (not nessecary but helpful)
+ TextStream.WriteLine('######################################');
+ TextStream.WriteLine('#Ultrastar Deluxe Playlist Format v1.0');
+ TextStream.WriteLine(Format('#Playlist %s with %d Songs.',
+ [ Playlists[Index].Name, Length(Playlists[Index].Items) ]));
+ TextStream.WriteLine('######################################');
- //Write Name Information
- WriteLn(F, '#Name: ' + Playlists[Index].Name);
+ // Write name information
+ TextStream.WriteLine('#Name: ' + Playlists[Index].Name);
- //Write Song Information
- WriteLn(F, '#Songs:');
+ // Write song information
+ TextStream.WriteLine('#Songs:');
- For I := 0 to high(Playlists[Index].Items) do
- begin
- WriteLn(F, Playlists[Index].Items[I].Artist + ' : ' + Playlists[Index].Items[I].Title);
- end;
- except
- log.LogError('Could not write Playlistfile "' + Playlists[Index].Name + '"');
- end;
- finally
- CloseFile(F);
+ for I := 0 to high(Playlists[Index].Items) do
+ begin
+ TextStream.WriteLine(Playlists[Index].Items[I].Artist + ' : ' + Playlists[Index].Items[I].Title);
end;
+ except
+ Log.LogError('Could not write Playlistfile "' + Playlists[Index].Name + '"');
end;
+ TextStream.Free;
end;
-//----------
-//SetPlayList - Display a Playlist in CatSongs
-//----------
-Procedure TPlayListManager.SetPlayList(Index: Cardinal);
+{**
+ * Display a Playlist in CatSongs
+ *}
+procedure TPlayListManager.SetPlayList(Index: Cardinal);
var
I: Integer;
begin
- If (Int(Index) > High(PlayLists)) then
+ if (Int(Index) > High(PlayLists)) then
exit;
//Hide all Songs
- For I := 0 to high(CatSongs.Song) do
+ for I := 0 to high(CatSongs.Song) do
CatSongs.Song[I].Visible := False;
//Show Songs in PL
- For I := 0 to high(PlayLists[Index].Items) do
+ for I := 0 to high(PlayLists[Index].Items) do
begin
CatSongs.Song[PlayLists[Index].Items[I].SongID].Visible := True;
end;
@@ -324,31 +327,30 @@ end;
//----------
//AddPlaylist - Adds a Playlist and Returns the Index
//----------
-Function TPlayListManager.AddPlaylist(const Name: string): Cardinal;
+function TPlayListManager.AddPlaylist(const Name: UTF8String): cardinal;
var
I: Integer;
+ PlaylistFile: IPath;
begin
Result := Length(Playlists);
SetLength(Playlists, Result + 1);
// Sort the Playlists - Insertion Sort
- while (Result > 0) AND (CompareText(Playlists[Result - 1].Name, Name) >= 0) do
+ while (Result > 0) and (CompareText(Playlists[Result - 1].Name, Name) >= 0) do
begin
Dec(Result);
Playlists[Result+1] := Playlists[Result];
end;
- Playlists[Result].Name := Name;
+ Playlists[Result].Name := Name;
I := 1;
- if (not FileExists(PlaylistPath + Name + '.upl')) then
- Playlists[Result].Filename := Name + '.upl'
- else
+ PlaylistFile := PlaylistPath.Append(Name + '.upl');
+ while (PlaylistFile.Exists) do
begin
- repeat
- Inc(I);
- until not FileExists(PlaylistPath + Name + InttoStr(I) + '.upl');
- Playlists[Result].Filename := Name + InttoStr(I) + '.upl';
+ Inc(I);
+ PlaylistFile := PlaylistPath.Append(Name + InttoStr(I) + '.upl');
end;
+ Playlists[Result].Filename := PlaylistFile;
//Save new Playlist
SavePlayList(Result);
@@ -357,28 +359,28 @@ end;
//----------
//DelPlaylist - Deletes a Playlist
//----------
-Procedure TPlayListManager.DelPlaylist(const Index: Cardinal);
+procedure TPlayListManager.DelPlaylist(const Index: Cardinal);
var
I: Integer;
- Filename: String;
+ Filename: IPath;
begin
- If Int(Index) > High(Playlists) then
+ if Int(Index) > High(Playlists) then
Exit;
- Filename := PlaylistPath + Playlists[Index].Filename;
+ Filename := PlaylistPath.Append(Playlists[Index].Filename);
//If not FileExists or File is not Writeable then exit
- If (Not FileExists(Filename)) OR (FileisReadOnly(Filename)) then
+ if (not Filename.IsFile()) or (Filename.IsReadOnly()) then
Exit;
//Delete Playlist from FileSystem
- if Not DeleteFile(Filename) then
+ if not Filename.DeleteFile() then
Exit;
//Delete Playlist from Array
//move all PLs to the Hole
- For I := Index to High(Playlists)-1 do
+ for I := Index to High(Playlists)-1 do
PlayLists[I] := PlayLists[I+1];
//Delete last Playlist
@@ -471,7 +473,7 @@ end;
//----------
//GetNames - Writes Playlist Names in a Array
//----------
-Procedure TPlayListManager.GetNames(var PLNames: array of String);
+procedure TPlayListManager.GetNames(var PLNames: array of UTF8String);
var
I: Integer;
Len: Integer;
diff --git a/unicode/src/base/USkins.pas b/unicode/src/base/USkins.pas
index a19b7546..6ef5c596 100644
--- a/unicode/src/base/USkins.pas
+++ b/unicode/src/base/USkins.pas
@@ -33,31 +33,34 @@ interface
{$I switches.inc}
+uses
+ UPath;
+
type
TSkinTexture = record
Name: string;
- FileName: string;
+ FileName: IPath;
end;
TSkinEntry = record
Theme: string;
Name: string;
- Path: string;
- FileName: string;
+ Path: IPath;
+ FileName: IPath;
Creator: string; // not used yet
end;
TSkin = class
Skin: array of TSkinEntry;
SkinTexture: array of TSkinTexture;
- SkinPath: string;
+ SkinPath: IPath;
Color: integer;
constructor Create;
procedure LoadList;
- procedure ParseDir(Dir: string);
- procedure LoadHeader(FileName: string);
+ procedure ParseDir(Dir: IPath);
+ procedure LoadHeader(FileName: IPath);
procedure LoadSkin(Name: string);
- function GetTextureFileName(TextureName: string): string;
+ function GetTextureFileName(TextureName: string): IPath;
function GetSkinNumber(Name: string): integer;
procedure onThemeChange;
end;
@@ -74,7 +77,8 @@ uses
UIni,
ULog,
UMain,
- UPathUtils;
+ UPathUtils,
+ UFileSystem;
constructor TSkin.Create;
begin
@@ -86,45 +90,43 @@ end;
procedure TSkin.LoadList;
var
- SR: TSearchRec;
+ Iter: IFileIterator;
+ DirInfo: TFileInfo;
begin
- if FindFirst(SkinsPath+'*', faDirectory, SR) = 0 then
+ Iter := FileSystem.FileFind(SkinsPath.Append('*'), faDirectory);
+ while Iter.HasNext do
begin
- repeat
- if (SR.Name <> '.') and (SR.Name <> '..') then
- ParseDir(SkinsPath + SR.Name + PathDelim);
- until FindNext(SR) <> 0;
- end; // if
- FindClose(SR);
+ DirInfo := Iter.Next();
+ if (not DirInfo.Name.Equals('.')) and (not DirInfo.Name.Equals('..')) then
+ ParseDir(SkinsPath.Append(DirInfo.Name, pdAppend));
+ end;
end;
-procedure TSkin.ParseDir(Dir: string);
+procedure TSkin.ParseDir(Dir: IPath);
var
- SR: TSearchRec;
+ Iter: IFileIterator;
+ IniInfo: TFileInfo;
begin
- if FindFirst(Dir + '*.ini', faAnyFile, SR) = 0 then
+ Iter := FileSystem.FileFind(Dir.Append('*.ini'), 0);
+ while Iter.HasNext do
begin
- repeat
-
- if (SR.Name <> '.') and (SR.Name <> '..') then
- LoadHeader(Dir + SR.Name);
-
- until FindNext(SR) <> 0;
+ IniInfo := Iter.Next;
+ LoadHeader(Dir.Append(IniInfo.Name));
end;
end;
-procedure TSkin.LoadHeader(FileName: string);
+procedure TSkin.LoadHeader(FileName: IPath);
var
SkinIni: TMemIniFile;
S: integer;
begin
- SkinIni := TMemIniFile.Create(FileName);
+ SkinIni := TMemIniFile.Create(FileName.ToNative);
S := Length(Skin);
SetLength(Skin, S+1);
- Skin[S].Path := IncludeTrailingPathDelimiter(ExtractFileDir(FileName));
- Skin[S].FileName := ExtractFileName(FileName);
+ Skin[S].Path := FileName.GetPath;
+ Skin[S].FileName := FileName.GetName;
Skin[S].Theme := SkinIni.ReadString('Skin', 'Theme', '');
Skin[S].Name := SkinIni.ReadString('Skin', 'Name', '');
Skin[S].Creator := SkinIni.ReadString('Skin', 'Creator', '');
@@ -142,7 +144,7 @@ begin
S := GetSkinNumber(Name);
SkinPath := Skin[S].Path;
- SkinIni := TMemIniFile.Create(SkinPath + Skin[S].FileName);
+ SkinIni := TMemIniFile.Create(SkinPath.Append(Skin[S].FileName).ToNative);
SL := TStringList.Create;
SkinIni.ReadSection('Textures', SL);
@@ -151,30 +153,29 @@ begin
for T := 0 to SL.Count-1 do
begin
SkinTexture[T].Name := SL.Strings[T];
- SkinTexture[T].FileName := SkinIni.ReadString('Textures', SL.Strings[T], '');
+ SkinTexture[T].FileName := Path(SkinIni.ReadString('Textures', SL.Strings[T], ''));
end;
SL.Free;
SkinIni.Free;
end;
-function TSkin.GetTextureFileName(TextureName: string): string;
+function TSkin.GetTextureFileName(TextureName: string): IPath;
var
T: integer;
begin
- Result := '';
+ Result := PATH_NONE;
for T := 0 to High(SkinTexture) do
begin
- if ( SkinTexture[T].Name = TextureName ) and
- ( SkinTexture[T].FileName <> '' ) then
+ if (SkinTexture[T].Name = TextureName) and
+ (SkinTexture[T].FileName.IsSet) then
begin
- Result := SkinPath + SkinTexture[T].FileName;
+ Result := SkinPath.Append(SkinTexture[T].FileName);
end;
end;
- if ( TextureName <> '' ) and
- ( Result <> '' ) then
+ if (TextureName <> '') and (Result.IsSet) then
begin
//Log.LogError('', '-----------------------------------------');
//Log.LogError(TextureName+' - '+ Result, 'TSkin.GetTextureFileName');
diff --git a/unicode/src/base/USong.pas b/unicode/src/base/USong.pas
index 86349359..203ff517 100644
--- a/unicode/src/base/USong.pas
+++ b/unicode/src/base/USong.pas
@@ -57,7 +57,9 @@ uses
{$ENDIF}
UCatCovers,
UXMLSong,
- UTextEncoding;
+ UTextEncoding,
+ UFilesystem,
+ UPath;
type
@@ -74,6 +76,7 @@ type
end;
TSong = class
+ private
FileLineNo : integer; // line, which is read last, for error reporting
function EncodeFilename(Filename: string): string;
@@ -81,19 +84,22 @@ type
procedure ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: UTF8String);
procedure NewSentence(LineNumberP: integer; Param1, Param2: integer);
- function ReadTXTHeader( const aFileName : WideString ): boolean;
- function ReadXMLHeader( const aFileName : WideString ): boolean;
+ function ReadTXTHeader(const aFileName: IPath): boolean;
+ function ReadXMLHeader(const aFileName: IPath): boolean;
+
+ function GetFolderCategory(const aFileName: IPath): UTF8String;
+ function FindSongFile(Dir: IPath; Mask: UTF8String): IPath;
+
public
- Path: WideString;
- Folder: WideString; // for sorting by folder
- fFileName,
- FileName: WideString;
+ Path: IPath; // kust path component of file (only set if file was found)
+ Folder: UTF8String; // for sorting by folder (only set if file was found)
+ FileName: IPath; // just name component of file (only set if file was found)
// filenames
- Cover: WideString;
- Mp3: WideString;
- Background: WideString;
- Video: WideString;
+ Cover: IPath;
+ Mp3: IPath;
+ Background: IPath;
+ Video: IPath;
// sorting methods
Genre: UTF8String;
@@ -127,7 +133,7 @@ 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 operate 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;
@@ -140,7 +146,7 @@ type
constructor Create(); overload;
- constructor Create( const aFileName : WideString ); overload;
+ constructor Create(const aFileName : IPath); overload;
function LoadSong: boolean;
function LoadXMLSong: boolean;
function Analyse(): boolean;
@@ -167,58 +173,61 @@ begin
inherited;
end;
-constructor TSong.Create( const aFileName: WideString );
- // This may be changed, when we rewrite song select code.
- // it is some kind of dirty, but imho the best possible
- // solution as we do atm not support nested categorys.
- // it works like the folder sorting in 1.0.1a
- // folder is set to the first folder under the songdir
- // so songs ~/.ultrastardx/songs/punk is in the same
- // category as songs in shared/ultrastardx/songs are.
- // note: folder is just the name of a category it has
- // nothing to do with the path used for file loading
- function GetFolderCategory: WideString;
- var
- I: Integer;
- P: Integer; //position of next path delimiter
- begin
- Result := 'Unknown'; //default folder category, if we can't locate the song dir
+// This may be changed, when we rewrite song select code.
+// it is some kind of dirty, but imho the best possible
+// solution as we do atm not support nested categorys.
+// it works like the folder sorting in 1.0.1a
+// folder is set to the first folder under the songdir
+// so songs ~/.ultrastardx/songs/punk is in the same
+// category as songs in shared/ultrastardx/songs are.
+// note: folder is just the name of a category it has
+// nothing to do with the path used for file loading
+function TSong.GetFolderCategory(const aFileName: IPath): UTF8String;
+var
+ I: Integer;
+ CurSongPath: IPath;
+ CurSongPathRel: IPath;
+begin
+ Result := 'Unknown'; //default folder category, if we can't locate the song dir
- for I := 0 to SongPaths.Count-1 do
- if (AnsiStartsText(SongPaths.Strings[I], aFilename)) then
+ for I := 0 to SongPaths.Count-1 do
+ begin
+ CurSongPath := SongPaths[I] as IPath;
+ if (aFileName.IsChildOf(CurSongPath, false)) then
+ begin
+ if (aFileName.IsChildOf(CurSongPath, true)) then
begin
- P := PosEx(PathDelim, aFilename, Length(SongPaths.Strings[I]) + 1);
-
- If (P > 0) then
- begin
- // we have found the category name => get it
- Result := copy(self.Path, Length(SongPaths.Strings[I]) + 1, P - Length(SongPaths.Strings[I]) - 1);
- end
- else
- begin
- // songs are in the "root" of the songdir => use songdir for the categorys name
- Result := SongPaths.Strings[I];
- end;
-
- Exit;
+ // songs are in the "root" of the songdir => use songdir for the categorys name
+ Result := CurSongPath.ToUTF8; // TODO: remove trailing path-delim?
+ end
+ else
+ begin
+ // use the first subdirectory below CurSongPath as the category name
+ CurSongPathRel := aFileName.GetRelativePath(CurSongPath.AppendPathDelim);
+ Result := CurSongPathRel.SplitDirs[0].RemovePathDelim.ToUTF8;
end;
+ Exit;
+ end;
end;
+end;
+
+constructor TSong.Create(const aFileName: IPath);
begin
inherited Create();
Mult := 1;
MultBPM := 4;
- fFileName := aFileName;
LastError := '';
- if fileexists( aFileName ) then
+ Self.Path := aFileName.GetPath;
+ Self.FileName := aFileName.GetName;
+ Self.Folder := GetFolderCategory(aFileName);
+
+ (*
+ if (aFileName.IsFile) then
begin
- self.Path := ExtractFilePath( aFileName );
- self.Folder := GetFolderCategory;
- self.FileName := ExtractFileName( aFileName );
- (*
- if ReadTXTHeader( aFileName ) then
+ if ReadTXTHeader(aFileName) then
begin
LoadSong();
end
@@ -227,8 +236,21 @@ begin
Log.LogError('Error Loading SongHeader, abort Song Loading');
Exit;
end;
- *)
end;
+ *)
+end;
+
+function TSong.FindSongFile(Dir: IPath; Mask: UTF8String): IPath;
+var
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
+ FileName: IPath;
+begin
+ Iter := FileSystem.FileFind(Dir.Append(Mask), faDirectory);
+ if (Iter.HasNext) then
+ Result := Iter.Next.Name
+ else
+ Result := PATH_NONE;
end;
function TSong.EncodeFilename(Filename: string): string;
@@ -247,7 +269,7 @@ end;
//Load TXT Song
function TSong.LoadSong(): boolean;
var
- TempC: char;
+ TempC: AnsiChar;
Text: UTF8String;
Count: integer;
Both: boolean;
@@ -256,15 +278,19 @@ var
Param3: integer;
ParamS: UTF8String;
I: integer;
+ NotesFound: boolean;
+ TextStream: TTextFileStream;
+ FileNamePath: IPath;
begin
Result := false;
LastError := '';
- if not FileExists(Path + PathDelim + FileName) then
+ FileNamePath := Path.Append(FileName);
+ if not FileNamePath.IsFile() then
begin
LastError := 'ERROR_CORRUPT_SONG_FILE_NOT_FOUND';
- Log.LogError('File not found: "' + Path + PathDelim + FileName + '"', 'TSong.LoadSong()');
- exit;
+ Log.LogError('File not found: "' + FileNamePath.ToNative + '"', 'TSong.LoadSong()');
+ Exit;
end;
MultBPM := 4; // multiply beat-count of note by 4
@@ -275,34 +301,42 @@ begin
if Length(Player) = 2 then
Both := true;
+ {$MESSAGE warn 'TODO: TSong.LoadSong'}
+
+ (*
try
// Open song file for reading.....
- FileMode := fmOpenRead;
- AssignFile(SongFile, fFileName);
- Reset(SongFile);
+ TextStream := nil;
+ TextStream := TBinaryFileStream.Create(FullFileName, fmOpenRead);
//Clear old Song Header
- if (self.Path = '') then
- self.Path := ExtractFilePath(FileName);
+ if (Self.Path.IsUnset) then
+ Self.Path := FullFileName.GetPath();
- if (self.FileName = '') then
- self.Filename := ExtractFileName(FileName);
+ if (Self.FileName.IsUnset) then
+ Self.Filename := FullFileName.GetName();
- FileLineNo := 0;
//Search for Note Begining
- repeat
- ReadLn(SongFile, Text);
+ FileLineNo := 0;
+ NotesFound := false;
+ while (TextStream.ReadLine(Text)) do
+ begin
Inc(FileLineNo);
-
- if (Eof(SongFile)) then
- begin //Song File Corrupted - No Notes
- CloseFile(SongFile);
- Log.LogError('Could not load txt File, no Notes found: ' + FileName);
- LastError := 'ERROR_CORRUPT_SONG_NO_NOTES';
- Exit;
+ if (Length(Text) > 0) and (Text[0] in [':', 'F', '*']) then
+ begin
+ TempC := Text[0];
+ NotesFound := true;
+ Break;
end;
- Read(SongFile, TempC);
- until ((TempC = ':') or (TempC = 'F') or (TempC = '*'));
+ end;
+
+ if (not NotesFound) then
+ begin //Song File Corrupted - No Notes
+ TextStream.Free;
+ Log.LogError('Could not load txt File, no Notes found: ' + FileName);
+ LastError := 'ERROR_CORRUPT_SONG_NO_NOTES';
+ Exit;
+ end;
SetLength(Lines, 2);
for Count := 0 to High(Lines) do
@@ -327,7 +361,7 @@ begin
while (TempC <> 'E') and (not EOF(SongFile)) do
begin
- if (TempC = ':') or (TempC = '*') or (TempC = 'F') then
+ if (TempC in [':', '*', 'F']) then
begin
// read notes
Read(SongFile, Param1);
@@ -398,7 +432,7 @@ begin
if (Length(Lines[I].Line) < 2) then
begin
LastError := 'ERROR_CORRUPT_SONG_NO_BREAKS';
- Log.LogError('Error Loading File, Can''t find any Linebreaks: "' + fFileName + '"');
+ Log.LogError('Error Loading File, Can''t find any Linebreaks: "' + FullFileName + '"');
exit;
end;
@@ -425,10 +459,11 @@ begin
end;
LastError := 'ERROR_CORRUPT_SONG_ERROR_IN_LINE';
- Log.LogError('Error Loading File: "' + fFileName + '" in Line ' + inttostr(FileLineNo));
+ Log.LogError('Error Loading File: "' + FullFileName + '" in Line ' + inttostr(FileLineNo));
exit;
end;
-
+ *)
+
Result := true;
end;
@@ -447,13 +482,15 @@ var
NoteType: char;
SentenceEnd, Rest, Time: integer;
Parser: TParser;
+ FileNamePath: IPath;
begin
Result := false;
LastError := '';
- if not FileExists(Path + PathDelim + FileName) then
+ FileNamePath := Path.Append(FileName);
+ if not FileNamePath.IsFile() then
begin
- Log.LogError('File not found: "' + Path + PathDelim + FileName + '"', 'TSong.LoadSong()');
+ Log.LogError('File not found: "' + FileNamePath.ToNative + '"', 'TSong.LoadSong()');
exit;
end;
@@ -491,7 +528,7 @@ begin
//Try to Parse the Song
- if Parser.ParseSong(Path + PathDelim + FileName) then
+ if Parser.ParseSong(FileNamePath) then
begin
//Writeln('XML Inputfile Parsed succesful');
@@ -558,7 +595,7 @@ begin
end
else
begin
- Log.LogError('Could not parse Inputfile: ' + Path + PathDelim + FileName);
+ Log.LogError('Could not parse Inputfile: ' + FileNamePath.ToNative);
exit;
end;
@@ -570,10 +607,11 @@ begin
Result := true;
end;
-function TSong.ReadXMLHeader(const aFileName : WideString): boolean;
+function TSong.ReadXMLHeader(const aFileName : IPath): boolean;
var
Done : byte;
Parser : TParser;
+ FileNamePath: IPath;
begin
Result := true;
Done := 0;
@@ -582,7 +620,8 @@ begin
Parser := TParser.Create;
Parser.Settings.DashReplacement := '~';
- if Parser.ParseSong(self.Path + self.FileName) then
+ FileNamePath := Self.Path.Append(Self.FileName);
+ if Parser.ParseSong(FileNamePath) then
begin
//-----------
//Required Attributes
@@ -601,9 +640,9 @@ begin
Done := Done or 2;
//MP3 File //Test if Exists
- self.Mp3 := platform.FindSongFile(Path, '*.mp3');
+ Self.Mp3 := FindSongFile(Self.Path, '*.mp3');
//Add Mp3 Flag to Done
- if (FileExists(self.Path + self.Mp3)) then
+ if (Self.Path.Append(Self.Mp3).IsFile()) then
Done := Done or 4;
//Beats per Minute
@@ -624,10 +663,10 @@ begin
self.GAP := Parser.SongInfo.Header.Gap;
//Cover Picture
- self.Cover := platform.FindSongFile(Path, '*[CO].jpg');
+ self.Cover := FindSongFile(Path, '*[CO].jpg');
//Background Picture
- self.Background := platform.FindSongFile(Path, '*[BG].jpg');
+ self.Background := FindSongFile(Path, '*[BG].jpg');
// Video File
// self.Video := Value
@@ -648,7 +687,7 @@ begin
self.Language := Parser.SongInfo.Header.Language;
end
else
- Log.LogError('File Incomplete or not SingStar XML (A): ' + aFileName);
+ Log.LogError('File Incomplete or not SingStar XML (A): ' + aFileName.ToNative);
Parser.Free;
@@ -657,36 +696,35 @@ begin
begin
Result := false;
if (Done and 8) = 0 then //No BPM Flag
- Log.LogError('BPM Tag Missing: ' + self.FileName)
+ Log.LogError('BPM Tag Missing: ' + self.FileName.ToNative)
else if (Done and 4) = 0 then //No MP3 Flag
- Log.LogError('MP3 Tag/File Missing: ' + self.FileName)
+ Log.LogError('MP3 Tag/File Missing: ' + self.FileName.ToNative)
else if (Done and 2) = 0 then //No Artist Flag
- Log.LogError('Artist Tag Missing: ' + self.FileName)
+ Log.LogError('Artist Tag Missing: ' + self.FileName.ToNative)
else if (Done and 1) = 0 then //No Title Flag
- Log.LogError('Title Tag Missing: ' + self.FileName)
+ Log.LogError('Title Tag Missing: ' + self.FileName.ToNative)
else //unknown Error
- Log.LogError('File Incomplete or not SingStar XML (B - '+ inttostr(Done) +'): ' + aFileName);
+ Log.LogError('File Incomplete or not SingStar XML (B - '+ inttostr(Done) +'): ' + aFileName.ToNative);
end;
end;
-function TSong.ReadTXTHeader(const aFileName : WideString): boolean;
-
- {**
- * "International" StrToFloat variant. Uses either ',' or '.' as decimal
- * separator.
- *}
- function StrToFloatI18n(const Value: string): extended;
- var
- TempValue : string;
- begin
- TempValue := Value;
- if (Pos(',', TempValue) <> 0) then
- TempValue[Pos(',', TempValue)] := '.';
- Result := StrToFloatDef(TempValue, 0);
- end;
+{**
+ * "International" StrToFloat variant. Uses either ',' or '.' as decimal
+ * separator.
+ *}
+function StrToFloatI18n(const Value: string): extended;
+var
+ TempValue : string;
+begin
+ TempValue := Value;
+ if (Pos(',', TempValue) <> 0) then
+ TempValue[Pos(',', TempValue)] := '.';
+ Result := StrToFloatDef(TempValue, 0);
+end;
+function TSong.ReadTXTHeader(const aFileName : IPath): boolean;
var
Line, Identifier: string;
Value: string;
@@ -697,6 +735,10 @@ begin
Result := true;
Done := 0;
+ {$message warn 'TSong.ReadTXTHeader'}
+
+ (*
+
//Read first Line
ReadLn (SongFile, Line);
@@ -913,7 +955,7 @@ begin
else //unknown Error
Log.LogError('File Incomplete or not Ultrastar TxT (B - '+ inttostr(Done) +'): ' + aFileName);
end;
-
+ *)
end;
function TSong.GetErrorLineNo: integer;
@@ -1034,7 +1076,8 @@ begin
end
else
begin //use old line if it there were no notes added since last call of NewSentence
- Log.LogError('Error loading Song, sentence w/o note found in line ' + InttoStr(FileLineNo) + ': ' + Filename);
+ Log.LogError('Error loading Song, sentence w/o note found in line ' +
+ InttoStr(FileLineNo) + ': ' + Filename.ToNative);
end;
Lines[LineNumberP].Line[Lines[LineNumberP].High].HighNote := -1;
@@ -1076,7 +1119,7 @@ begin
Encoding := DEFAULT_ENCODING;
//Required Information
- Mp3 := '';
+ Mp3 := PATH_NONE;
SetLength(BPM, 0);
GAP := 0;
@@ -1084,9 +1127,9 @@ begin
Finish := 0;
//Additional Information
- Background := '';
- Cover := '';
- Video := '';
+ Background := PATH_NONE;
+ Cover := PATH_NONE;
+ Video := PATH_NONE;
VideoGAP := 0;
NotesGAP := 0;
Resolution := 4;
@@ -1096,7 +1139,8 @@ begin
end;
function TSong.Analyse(): boolean;
-
+var
+ SongFile: TTextFileStream;
begin
Result := false;
@@ -1104,20 +1148,17 @@ begin
FileLineNo := 0;
//Open File and set File Pointer to the beginning
- AssignFile(SongFile, self.Path + self.FileName);
-
+ SongFile := TTextFileStream.Create(Self.Path.Append(Self.FileName), fmOpenRead);
try
- Reset(SongFile);
-
//Clear old Song Header
- self.clear;
+ Self.clear;
//Read Header
- Result := self.ReadTxTHeader( FileName )
+ Result := self.ReadTxTHeader(FileName)
//And Close File
finally
- CloseFile(SongFile);
+ SongFile.Free;
end;
end;
diff --git a/unicode/src/base/USongs.pas b/unicode/src/base/USongs.pas
index 2b2bcf49..55ddc5e9 100644
--- a/unicode/src/base/USongs.pas
+++ b/unicode/src/base/USongs.pas
@@ -40,28 +40,26 @@ interface
{$ENDIF}
uses
+ SysUtils,
+ Classes,
{$IFDEF MSWINDOWS}
Windows,
DirWatch,
{$ELSE}
{$IFNDEF DARWIN}
- syscall,
+ syscall,
{$ENDIF}
baseunix,
UnixType,
{$ENDIF}
- SysUtils,
- Classes,
UPlatform,
ULog,
UTexture,
UCommon,
- {$IFDEF DARWIN}
- cthreads,
- {$ENDIF}
{$IFDEF USE_PSEUDO_THREAD}
- PseudoThread,
+ PseudoThread,
{$ENDIF}
+ UPath,
USong,
UCatCovers;
@@ -107,11 +105,10 @@ type
procedure LoadSongList; // load all songs
- procedure BrowseDir(Dir: widestring); // should return number of songs in the future
- procedure BrowseTXTFiles(Dir: widestring);
- procedure BrowseXMLFiles(Dir: widestring);
+ procedure BrowseDir(Dir: IPath); // should return number of songs in the future
+ procedure BrowseTXTFiles(Dir: IPath);
+ procedure BrowseXMLFiles(Dir: IPath);
procedure Sort(Order: integer);
- function FindSongFile(Dir, Mask: widestring): widestring;
property Processing: boolean read fProcessing;
end;
@@ -165,6 +162,7 @@ uses
UIni,
UPathUtils,
UNote,
+ UFilesystem,
UUnicodeUtils;
constructor TSongs.Create();
@@ -239,7 +237,7 @@ begin
// browse directories
for I := 0 to SongPaths.Count-1 do
- BrowseDir(SongPaths[I]);
+ BrowseDir(SongPaths[I] as IPath);
if assigned(CatSongs) then
CatSongs.Refresh;
@@ -271,13 +269,13 @@ begin
Resume();
end;
-procedure TSongs.BrowseDir(Dir: widestring);
+procedure TSongs.BrowseDir(Dir: IPath);
begin
BrowseTXTFiles(Dir);
BrowseXMLFiles(Dir);
end;
-procedure TSongs.BrowseTXTFiles(Dir: widestring);
+procedure TSongs.BrowseTXTFiles(Dir: IPath);
var
i: integer;
Files: TDirectoryEntryArray;
@@ -285,27 +283,27 @@ var
begin
try
- Files := Platform.DirectoryFindFiles(Dir, '.txt', true)
+ Files := DirectoryFindFiles(Dir, '.txt', true)
except
- Log.LogError('Couldn''t deal with directory/file: ' + Dir + ' in TSongs.BrowseTXTFiles')
+ Log.LogError('Couldn''t deal with directory/file: ' + Dir.ToNative + ' in TSongs.BrowseTXTFiles')
end;
for i := 0 to Length(Files) - 1 do
begin
if Files[i].IsDirectory then
begin
- BrowseTXTFiles(Dir + Files[i].Name + PathDelim); //Recursive Call
+ BrowseTXTFiles(Dir.Append(Files[i].Name, pdAppend)); //Recursive Call
end
else
begin
- lSong := TSong.create(Dir + Files[i].Name);
+ lSong := TSong.Create(Dir.Append(Files[i].Name));
if lSong.Analyse then
SongList.add(lSong)
else
begin
- Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
- freeandnil(lSong);
+ Log.LogError('AnalyseFile failed for "' + Files[i].Name.ToNative + '".');
+ FreeAndNil(lSong);
end;
end;
@@ -314,7 +312,7 @@ begin
end;
-procedure TSongs.BrowseXMLFiles(Dir: widestring);
+procedure TSongs.BrowseXMLFiles(Dir: IPath);
var
i: integer;
Files: TDirectoryEntryArray;
@@ -322,26 +320,26 @@ var
begin
try
- Files := Platform.DirectoryFindFiles(Dir, '.xml', true)
+ Files := DirectoryFindFiles(Dir, '.xml', true)
except
- Log.LogError('Couldn''t deal with directory/file: ' + Dir + ' in TSongs.BrowseXMLFiles')
+ Log.LogError('Couldn''t deal with directory/file: ' + Dir.ToNative + ' in TSongs.BrowseXMLFiles')
end;
for i := 0 to Length(Files) - 1 do
begin
if Files[i].IsDirectory then
begin
- BrowseXMLFiles(Dir + Files[i].Name + PathDelim); // Recursive Call
+ BrowseXMLFiles(Dir.Append(Files[i].Name, pdAppend)); // Recursive Call
end
else
begin
- lSong := TSong.create(Dir + Files[i].Name);
+ lSong := TSong.Create(Dir.Append(Files[i].Name));
if lSong.AnalyseXML then
SongList.add(lSong)
else
begin
- Log.LogError('AnalyseFile failed for "' + Files[i].Name + '".');
+ Log.LogError('AnalyseFile failed for "' + Files[i].Name.ToNative + '".');
freeandnil(lSong);
end;
@@ -377,7 +375,7 @@ end;
function CompareByFolder(Song1, Song2: Pointer): integer;
begin
- Result := CompareText(TSong(Song1).Folder, TSong(Song2).Folder);
+ Result := UTF8CompareText(TSong(Song1).Folder, TSong(Song2).Folder);
end;
function CompareByLanguage(Song1, Song2: Pointer): integer;
@@ -419,18 +417,6 @@ begin
MergeSort(SongList, CompareFunc);
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.SortSongs();
begin
case Ini.Sorting of
@@ -603,7 +589,7 @@ begin
end;
sFolder: begin
- if (CompareText(CurCategory, CurSong.Folder) <> 0) then
+ if (UTF8CompareText(CurCategory, CurSong.Folder) <> 0) then
begin
CurCategory := CurSong.Folder;
// add folder tab
@@ -831,7 +817,7 @@ begin
begin
case Filter of
fltAll:
- TmpString := Song[I].Artist + ' ' + Song[i].Title + ' ' + UTF8Encode(Song[i].Folder);
+ TmpString := Song[I].Artist + ' ' + Song[i].Title + ' ' + Song[i].Folder;
fltTitle:
TmpString := Song[I].Title;
fltArtist:
diff --git a/unicode/src/base/UTextEncoding.pas b/unicode/src/base/UTextEncoding.pas
index 966064c0..a0d455dd 100644
--- a/unicode/src/base/UTextEncoding.pas
+++ b/unicode/src/base/UTextEncoding.pas
@@ -1,239 +1,239 @@
-{* UltraStar Deluxe - Karaoke Game
- *
- * UltraStar Deluxe is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/menu/UMenuText.pas $
- * $Id: UMenuText.pas 1485 2008-10-28 20:16:05Z tobigun $
- *}
-
-unit UTextEncoding;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- SysUtils;
-
-type
- TEncoding = (
- encLocale, // current locale (needs cwstring on linux)
- encUTF8, // UTF-8
- encCP1250, // Windows-1250 Central/Eastern Europe (used by Ultrastar)
- encCP1252 // Windows-1252 Western Europe (used by UltraStar Deluxe < 1.1)
- );
-
-const
- UTF8_BOM: UTF8String = #$EF#$BB#$BF;
-
-{**
- * Decodes Src encoded in SrcEncoding to a UTF-16 or UTF-8 encoded Dst string.
- * Returns true if the conversion was successful.
- *}
-function DecodeString(const Src: AnsiString; out Dst: WideString; SrcEncoding: TEncoding): boolean; overload;
-function DecodeString(const Src: AnsiString; SrcEncoding: TEncoding): WideString; overload;
-function DecodeStringUTF8(const Src: AnsiString; out Dst: UTF8String; SrcEncoding: TEncoding): boolean; overload;
-function DecodeStringUTF8(const Src: AnsiString; SrcEncoding: TEncoding): UTF8String; overload;
-
-{**
- * Encodes the UTF-16 or UTF-8 encoded Src string to Dst using DstEncoding
- * Returns true if the conversion was successful.
- *}
-function EncodeString(const Src: WideString; out Dst: AnsiString; DstEncoding: TEncoding): boolean; overload;
-function EncodeString(const Src: WideString; DstEncoding: TEncoding): AnsiString; overload;
-function EncodeStringUTF8(const Src: UTF8String; out Dst: AnsiString; DstEncoding: TEncoding): boolean; overload;
-function EncodeStringUTF8(const Src: UTF8String; DstEncoding: TEncoding): AnsiString; overload;
-
-{**
- * If Text starts with an UTF-8 BOM, the BOM is removed and true will
- * be returned.
- *}
-function CheckReplaceUTF8BOM(var Text: AnsiString): boolean;
-
-{**
- * Parses an encoding string to its TEncoding equivalent.
- * Surrounding whitespace and dashes ('-') are removed, the upper-cased
- * resulting value is then compared with TEncodingNames.
- * If the encoding was not found, the result is set to the Default encoding.
- *}
-function ParseEncoding(const EncodingStr: AnsiString; Default: TEncoding): TEncoding;
-
-{**
- * Returns the name of an encoding.
- *}
-function EncodingName(Encoding: TEncoding): AnsiString;
-
-implementation
-
-uses
- StrUtils,
- UUnicodeUtils;
-
-type
- IEncoder = interface
- function GetName(): AnsiString;
- function Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean;
- function Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean;
- end;
-
- TEncoder = class(TInterfacedObject, IEncoder)
- public
- function GetName(): AnsiString; virtual; abstract;
- function Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean; virtual; abstract;
- function Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean; virtual; abstract;
- end;
-
- TSingleByteEncoder = class(TEncoder)
- public
- function Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean; override;
- function Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean; override;
- function DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean; virtual; abstract;
- function EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean; virtual; abstract;
- end;
-
-const
- ERROR_CHAR = '?';
-
-var
- Encoders: array[TEncoding] of IEncoder;
-
-function TSingleByteEncoder.Encode(const InStr: UCS4String; out OutStr: AnsiString): boolean;
-var
- I: integer;
-begin
- SetLength(OutStr, LengthUCS4(InStr));
- Result := true;
- for I := 1 to Length(OutStr) do
- begin
- if (not EncodeChar(InStr[I-1], OutStr[I])) then
- Result := false;
- end;
-end;
-
-function TSingleByteEncoder.Decode(const InStr: AnsiString; out OutStr: UCS4String): boolean;
-var
- I: integer;
-begin
- SetLength(OutStr, Length(InStr)+1);
- Result := true;
- for I := 1 to Length(InStr) do
- begin
- if (not DecodeChar(InStr[I], OutStr[I-1])) then
- Result := false;
- end;
- OutStr[High(OutStr)] := 0;
-end;
-
-function DecodeString(const Src: AnsiString; out Dst: WideString; SrcEncoding: TEncoding): boolean;
-var
- DstUCS4: UCS4String;
-begin
- Result := Encoders[SrcEncoding].Decode(Src, DstUCS4);
- Dst := UCS4StringToWideString(DstUCS4);
-end;
-
-function DecodeString(const Src: AnsiString; SrcEncoding: TEncoding): WideString;
-begin
- DecodeString(Src, Result, SrcEncoding);
-end;
-
-function DecodeStringUTF8(const Src: AnsiString; out Dst: UTF8String; SrcEncoding: TEncoding): boolean;
-var
- DstUCS4: UCS4String;
-begin
- Result := Encoders[SrcEncoding].Decode(Src, DstUCS4);
- Dst := UCS4ToUTF8String(DstUCS4);
-end;
-
-function DecodeStringUTF8(const Src: AnsiString; SrcEncoding: TEncoding): UTF8String;
-begin
- DecodeStringUTF8(Src, Result, SrcEncoding);
-end;
-
-function EncodeString(const Src: WideString; out Dst: AnsiString; DstEncoding: TEncoding): boolean;
-begin
- Result := Encoders[DstEncoding].Encode(WideStringToUCS4String(Src), Dst);
-end;
-
-function EncodeString(const Src: WideString; DstEncoding: TEncoding): AnsiString;
-begin
- EncodeString(Src, Result, DstEncoding);
-end;
-
-function EncodeStringUTF8(const Src: UTF8String; out Dst: AnsiString; DstEncoding: TEncoding): boolean;
-begin
- Result := Encoders[DstEncoding].Encode(UTF8ToUCS4String(Src), Dst);
-end;
-
-function EncodeStringUTF8(const Src: UTF8String; DstEncoding: TEncoding): AnsiString;
-begin
- EncodeStringUTF8(Src, Result, DstEncoding);
-end;
-
-function CheckReplaceUTF8BOM(var Text: AnsiString): boolean;
-begin
- if AnsiStartsStr(UTF8_BOM, Text) then
- begin
- Text := Copy(Text, Length(UTF8_BOM)+1, Length(Text)-Length(UTF8_BOM));
- Result := true;
- Exit;
- end;
- Result := false;
-end;
-
-function ParseEncoding(const EncodingStr: AnsiString; Default: TEncoding): TEncoding;
-var
- PrepStr: AnsiString; // prepared encoding string
- Encoding: TEncoding;
-begin
- // remove surrounding whitespace, replace dashes, to upper case
- PrepStr := UpperCase(AnsiReplaceStr(Trim(EncodingStr), '-', ''));
- for Encoding := Low(TEncoding) to High(TEncoding) do
- begin
- if (Encoders[Encoding].GetName() = PrepStr) then
- begin
- Result := Encoding;
- Exit;
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/menu/UMenuText.pas $
+ * $Id: UMenuText.pas 1485 2008-10-28 20:16:05Z tobigun $
+ *}
+
+unit UTextEncoding;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ SysUtils,
+ UUnicodeUtils;
+
+type
+ TEncoding = (
+ encLocale, // current locale (needs cwstring on linux)
+ encUTF8, // UTF-8
+ encCP1250, // Windows-1250 Central/Eastern Europe (used by Ultrastar)
+ encCP1252 // Windows-1252 Western Europe (used by UltraStar Deluxe < 1.1)
+ );
+
+const
+ UTF8_BOM: UTF8String = #$EF#$BB#$BF;
+
+{**
+ * Decodes Src encoded in SrcEncoding to a UTF-16 or UTF-8 encoded Dst string.
+ * Returns true if the conversion was successful.
+ *}
+function DecodeString(const Src: RawByteString; out Dst: WideString; SrcEncoding: TEncoding): boolean; overload;
+function DecodeString(const Src: RawByteString; SrcEncoding: TEncoding): WideString; overload;
+function DecodeStringUTF8(const Src: RawByteString; out Dst: UTF8String; SrcEncoding: TEncoding): boolean; overload;
+function DecodeStringUTF8(const Src: RawByteString; SrcEncoding: TEncoding): UTF8String; overload;
+
+{**
+ * Encodes the UTF-16 or UTF-8 encoded Src string to Dst using DstEncoding
+ * Returns true if the conversion was successful.
+ *}
+function EncodeString(const Src: WideString; out Dst: RawByteString; DstEncoding: TEncoding): boolean; overload;
+function EncodeString(const Src: WideString; DstEncoding: TEncoding): RawByteString; overload;
+function EncodeStringUTF8(const Src: UTF8String; out Dst: RawByteString; DstEncoding: TEncoding): boolean; overload;
+function EncodeStringUTF8(const Src: UTF8String; DstEncoding: TEncoding): RawByteString; overload;
+
+{**
+ * If Text starts with an UTF-8 BOM, the BOM is removed and true will
+ * be returned.
+ *}
+function CheckReplaceUTF8BOM(var Text: RawByteString): boolean;
+
+{**
+ * Parses an encoding string to its TEncoding equivalent.
+ * Surrounding whitespace and dashes ('-') are removed, the upper-cased
+ * resulting value is then compared with TEncodingNames.
+ * If the encoding was not found, the result is set to the Default encoding.
+ *}
+function ParseEncoding(const EncodingStr: AnsiString; Default: TEncoding): TEncoding;
+
+{**
+ * Returns the name of an encoding.
+ *}
+function EncodingName(Encoding: TEncoding): AnsiString;
+
+implementation
+
+uses
+ StrUtils;
+
+type
+ IEncoder = interface
+ function GetName(): AnsiString;
+ function Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean;
+ function Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean;
+ end;
+
+ TEncoder = class(TInterfacedObject, IEncoder)
+ public
+ function GetName(): AnsiString; virtual; abstract;
+ function Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean; virtual; abstract;
+ function Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean; virtual; abstract;
+ end;
+
+ TSingleByteEncoder = class(TEncoder)
+ public
+ function Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean; override;
+ function Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean; override;
+ function DecodeChar(InChr: AnsiChar; out OutChr: UCS4Char): boolean; virtual; abstract;
+ function EncodeChar(InChr: UCS4Char; out OutChr: AnsiChar): boolean; virtual; abstract;
+ end;
+
+const
+ ERROR_CHAR = '?';
+
+var
+ Encoders: array[TEncoding] of IEncoder;
+
+function TSingleByteEncoder.Encode(const InStr: UCS4String; out OutStr: RawByteString): boolean;
+var
+ I: integer;
+begin
+ SetLength(OutStr, LengthUCS4(InStr));
+ Result := true;
+ for I := 1 to Length(OutStr) do
+ begin
+ if (not EncodeChar(InStr[I-1], OutStr[I])) then
+ Result := false;
+ end;
+end;
+
+function TSingleByteEncoder.Decode(const InStr: RawByteString; out OutStr: UCS4String): boolean;
+var
+ I: integer;
+begin
+ SetLength(OutStr, Length(InStr)+1);
+ Result := true;
+ for I := 1 to Length(InStr) do
+ begin
+ if (not DecodeChar(InStr[I], OutStr[I-1])) then
+ Result := false;
+ end;
+ OutStr[High(OutStr)] := 0;
+end;
+
+function DecodeString(const Src: RawByteString; out Dst: WideString; SrcEncoding: TEncoding): boolean;
+var
+ DstUCS4: UCS4String;
+begin
+ Result := Encoders[SrcEncoding].Decode(Src, DstUCS4);
+ Dst := UCS4StringToWideString(DstUCS4);
+end;
+
+function DecodeString(const Src: RawByteString; SrcEncoding: TEncoding): WideString;
+begin
+ DecodeString(Src, Result, SrcEncoding);
+end;
+
+function DecodeStringUTF8(const Src: RawByteString; out Dst: UTF8String; SrcEncoding: TEncoding): boolean;
+var
+ DstUCS4: UCS4String;
+begin
+ Result := Encoders[SrcEncoding].Decode(Src, DstUCS4);
+ Dst := UCS4ToUTF8String(DstUCS4);
+end;
+
+function DecodeStringUTF8(const Src: RawByteString; SrcEncoding: TEncoding): UTF8String;
+begin
+ DecodeStringUTF8(Src, Result, SrcEncoding);
+end;
+
+function EncodeString(const Src: WideString; out Dst: RawByteString; DstEncoding: TEncoding): boolean;
+begin
+ Result := Encoders[DstEncoding].Encode(WideStringToUCS4String(Src), Dst);
+end;
+
+function EncodeString(const Src: WideString; DstEncoding: TEncoding): RawByteString;
+begin
+ EncodeString(Src, Result, DstEncoding);
+end;
+
+function EncodeStringUTF8(const Src: UTF8String; out Dst: RawByteString; DstEncoding: TEncoding): boolean;
+begin
+ Result := Encoders[DstEncoding].Encode(UTF8ToUCS4String(Src), Dst);
+end;
+
+function EncodeStringUTF8(const Src: UTF8String; DstEncoding: TEncoding): RawByteString;
+begin
+ EncodeStringUTF8(Src, Result, DstEncoding);
+end;
+
+function CheckReplaceUTF8BOM(var Text: RawByteString): boolean;
+begin
+ if AnsiStartsStr(UTF8_BOM, Text) then
+ begin
+ Text := Copy(Text, Length(UTF8_BOM)+1, Length(Text)-Length(UTF8_BOM));
+ Result := true;
+ Exit;
+ end;
+ Result := false;
+end;
+
+function ParseEncoding(const EncodingStr: AnsiString; Default: TEncoding): TEncoding;
+var
+ PrepStr: AnsiString; // prepared encoding string
+ Encoding: TEncoding;
+begin
+ // remove surrounding whitespace, replace dashes, to upper case
+ PrepStr := UpperCase(AnsiReplaceStr(Trim(EncodingStr), '-', ''));
+ for Encoding := Low(TEncoding) to High(TEncoding) do
+ begin
+ if (Encoders[Encoding].GetName() = PrepStr) then
+ begin
+ Result := Encoding;
+ Exit;
end;
end;
- Result := Default;
-end;
-
-function EncodingName(Encoding: TEncoding): AnsiString;
-begin
- Result := Encoders[Encoding].GetName();
-end;
-
-{$I ../encoding/Locale.inc}
-{$I ../encoding/UTF8.inc}
-{$I ../encoding/CP1250.inc}
-{$I ../encoding/CP1252.inc}
-
-initialization
- Encoders[encLocale] := TEncoderLocale.Create;
- Encoders[encUTF8] := TEncoderUTF8.Create;
- Encoders[encCP1250] := TEncoderCP1250.Create;
- Encoders[encCP1252] := TEncoderCP1252.Create;
-
-end.
+ Result := Default;
+end;
+
+function EncodingName(Encoding: TEncoding): AnsiString;
+begin
+ Result := Encoders[Encoding].GetName();
+end;
+
+{$I ../encoding/Locale.inc}
+{$I ../encoding/UTF8.inc}
+{$I ../encoding/CP1250.inc}
+{$I ../encoding/CP1252.inc}
+
+initialization
+ Encoders[encLocale] := TEncoderLocale.Create;
+ Encoders[encUTF8] := TEncoderUTF8.Create;
+ Encoders[encCP1250] := TEncoderCP1250.Create;
+ Encoders[encCP1252] := TEncoderCP1252.Create;
+
+end.
diff --git a/unicode/src/base/UTexture.pas b/unicode/src/base/UTexture.pas
index 97f244fe..04badae4 100644
--- a/unicode/src/base/UTexture.pas
+++ b/unicode/src/base/UTexture.pas
@@ -40,6 +40,7 @@ uses
Classes,
SysUtils,
UCommon,
+ UPath,
SDL,
SDL_Image;
@@ -66,7 +67,7 @@ type
TexX2: real;
TexY2: real;
Alpha: real;
- Name: string; // experimental for handling cache images. maybe it's useful for dynamic skins
+ Name: IPath; // experimental for handling cache images. maybe it's useful for dynamic skins
end;
type
@@ -91,7 +92,7 @@ procedure AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType);
type
PTextureEntry = ^TTextureEntry;
TTextureEntry = record
- Name: string;
+ Name: IPath;
Typ: TTextureType;
Color: cardinal;
@@ -105,7 +106,7 @@ type
Texture: array of TTextureEntry;
public
procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean);
- function FindTexture(const Name: string; Typ: TTextureType; Color: cardinal): integer;
+ function FindTexture(const Name: IPath; Typ: TTextureType; Color: cardinal): integer;
end;
TTextureUnit = class
@@ -116,14 +117,14 @@ type
procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Cache: boolean = false); overload;
procedure AddTexture(var Tex: TTexture; Typ: TTextureType; Color: cardinal; Cache: boolean = false); overload;
- function GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean = false): TTexture; overload;
- function GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean = false): TTexture; overload;
- function LoadTexture(FromRegistry: boolean; const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; overload;
- function LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; overload;
- function LoadTexture(const Identifier: string): TTexture; overload;
- function CreateTexture(Data: PChar; const Name: string; Width, Height: word; BitsPerPixel: byte): TTexture;
- procedure UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean); overload;
- procedure UnloadTexture(const Name: string; Typ: TTextureType; Col: cardinal; FromCache: boolean); overload;
+ function GetTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean = false): TTexture; overload;
+ function GetTexture(const Name: IPath; Typ: TTextureType; Col: LongWord; FromCache: boolean = false): TTexture; overload;
+ function LoadTexture(FromRegistry: boolean; const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture; overload;
+ function LoadTexture(const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture; overload;
+ function LoadTexture(const Identifier: IPath): TTexture; overload;
+ function CreateTexture(Data: PChar; const Name: IPath; Width, Height: word; BitsPerPixel: byte): TTexture;
+ procedure UnloadTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean); overload;
+ procedure UnloadTexture(const Name: IPath; Typ: TTextureType; Col: cardinal; FromCache: boolean); overload;
//procedure FlushTextureDatabase();
constructor Create;
@@ -188,7 +189,7 @@ begin
Texture[TextureIndex].Texture := Tex;
end;
-function TTextureDatabase.FindTexture(const Name: string; Typ: TTextureType; Color: cardinal): integer;
+function TTextureDatabase.FindTexture(const Name: IPath; Typ: TTextureType; Color: cardinal): integer;
var
TextureIndex: integer;
CurrentTexture: PTextureEntry;
@@ -235,18 +236,18 @@ begin
TextureDatabase.AddTexture(Tex, Typ, Color, Cache);
end;
-function TTextureUnit.LoadTexture(FromRegistry: boolean; const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture;
+function TTextureUnit.LoadTexture(FromRegistry: boolean; const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture;
begin
// FIXME: what is the FromRegistry parameter supposed to do?
Result := LoadTexture(Identifier, Typ, Col);
end;
-function TTextureUnit.LoadTexture(const Identifier: string): TTexture;
+function TTextureUnit.LoadTexture(const Identifier: IPath): TTexture;
begin
Result := LoadTexture(Identifier, TEXTURE_TYPE_PLAIN, 0);
end;
-function TTextureUnit.LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture;
+function TTextureUnit.LoadTexture(const Identifier: IPath; Typ: TTextureType; Col: LongWord): TTexture;
var
TexSurface: PSDL_Surface;
newWidth, newHeight: integer;
@@ -260,7 +261,7 @@ begin
TexSurface := LoadImage(Identifier);
if not assigned(TexSurface) then
begin
- Log.LogError('Could not load texture: "' + Identifier +'" with type "'+ TextureTypeToStr(Typ) +'"',
+ Log.LogError('Could not load texture: "' + Identifier.ToNative +'" with type "'+ TextureTypeToStr(Typ) +'"',
'TTextureUnit.LoadTexture');
Exit;
end;
@@ -363,16 +364,16 @@ begin
SDL_FreeSurface(TexSurface);
end;
-function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean): TTexture;
+function TTextureUnit.GetTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean): TTexture;
begin
Result := GetTexture(Name, Typ, 0, FromCache);
end;
-function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture;
+function TTextureUnit.GetTexture(const Name: IPath; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture;
var
TextureIndex: integer;
begin
- if (Name = '') then
+ if (Name.IsUnset) then
begin
// zero texture data
FillChar(Result, SizeOf(Result), 0);
@@ -413,7 +414,7 @@ begin
Result := TextureDatabase.Texture[TextureIndex].Texture;
end;
-function TTextureUnit.CreateTexture(Data: PChar; const Name: string; Width, Height: word; BitsPerPixel: byte): TTexture;
+function TTextureUnit.CreateTexture(Data: PChar; const Name: IPath; Width, Height: word; BitsPerPixel: byte): TTexture;
var
//Error: integer;
ActTex: GLuint;
@@ -467,12 +468,12 @@ begin
Result.Name := Name;
end;
-procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean);
+procedure TTextureUnit.UnloadTexture(const Name: IPath; Typ: TTextureType; FromCache: boolean);
begin
UnloadTexture(Name, Typ, 0, FromCache);
end;
-procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; Col: cardinal; FromCache: boolean);
+procedure TTextureUnit.UnloadTexture(const Name: IPath; Typ: TTextureType; Col: cardinal; FromCache: boolean);
var
T: integer;
TexNum: GLuint;
diff --git a/unicode/src/base/UThemes.pas b/unicode/src/base/UThemes.pas
index 3fd77853..11ec746c 100644
--- a/unicode/src/base/UThemes.pas
+++ b/unicode/src/base/UThemes.pas
@@ -34,11 +34,12 @@ interface
{$I switches.inc}
uses
- ULog,
IniFiles,
SysUtils,
Classes,
- UTexture;
+ ULog,
+ UTexture,
+ UPath;
type
TRGB = record
@@ -531,10 +532,10 @@ type
TextFound: TThemeText;
//Translated Texts
- Songsfound: string;
- NoSongsfound: string;
- CatText: string;
- IType: array [0..2] of string;
+ Songsfound: UTF8String;
+ NoSongsfound: UTF8String;
+ CatText: UTF8String;
+ IType: array [0..2] of UTF8String;
end;
//Party Screens
@@ -761,11 +762,11 @@ type
Playlist: TThemePlaylist;
- ILevel: array[0..2] of string;
+ ILevel: array[0..2] of UTF8String;
- constructor Create(const FileName: string); overload; // Initialize theme system
- constructor Create(const FileName: string; Color: integer); overload; // Initialize theme system with color
- function LoadTheme(FileName: string; sColor: integer): boolean; // Load some theme settings from file
+ constructor Create(const FileName: IPath); overload; // Initialize theme system
+ constructor Create(const FileName: IPath; Color: integer); overload; // Initialize theme system with color
+ function LoadTheme(const FileName: IPath; sColor: integer): boolean; // Load some theme settings from file
procedure LoadColors;
@@ -845,12 +846,12 @@ begin
glColor4f(Color.R, Color.G, Color.B, Min(Color.A, Alpha));
end;
-constructor TTheme.Create(const FileName: string);
+constructor TTheme.Create(const FileName: IPath);
begin
Create(FileName, 0);
end;
-constructor TTheme.Create(const FileName: string; Color: integer);
+constructor TTheme.Create(const FileName: IPath; Color: integer);
begin
inherited Create();
@@ -893,7 +894,7 @@ begin
end;
-function TTheme.LoadTheme(FileName: string; sColor: integer): boolean;
+function TTheme.LoadTheme(const FileName: IPath; sColor: integer): boolean;
var
I: integer;
begin
@@ -901,23 +902,21 @@ begin
CreateThemeObjects();
- Log.LogStatus('Loading: '+ FileName, 'TTheme.LoadTheme');
-
- FileName := AdaptFilePaths(FileName);
+ Log.LogStatus('Loading: '+ FileName.ToNative, 'TTheme.LoadTheme');
- if not FileExists(FileName) then
+ if not FileName.IsFile() then
begin
- Log.LogError('Theme does not exist ('+ FileName +')', 'TTheme.LoadTheme');
+ Log.LogError('Theme does not exist ('+ FileName.ToNative +')', 'TTheme.LoadTheme');
end;
- if FileExists(FileName) then
+ if FileName.IsFile() then
begin
Result := true;
{$IFDEF THEMESAVE}
- ThemeIni := TIniFile.Create(FileName);
+ ThemeIni := TIniFile.Create(FileName.ToNative);
{$ELSE}
- ThemeIni := TMemIniFile.Create(FileName);
+ ThemeIni := TMemIniFile.Create(FileName.ToNative);
{$ENDIF}
if ThemeIni.ReadString('Theme', 'Name', '') <> '' then
diff --git a/unicode/src/base/UUnicodeUtils.pas b/unicode/src/base/UUnicodeUtils.pas
index ce1731b6..29be778a 100644
--- a/unicode/src/base/UUnicodeUtils.pas
+++ b/unicode/src/base/UUnicodeUtils.pas
@@ -149,6 +149,11 @@ function UCS4UpperCase(const str: UCS4String): UCS4String; overload;
function UCS4CharToString(ch: UCS4Char): UCS4String;
{**
+ * @seealso System.Pos()
+ *}
+function UTF8Pos(const substr: UTF8String; const str: UTF8String): Integer;
+
+{**
* Copies a segment of str starting with Index (1-based) with Count characters (not bytes).
*}
function UTF8Copy(const str: UTF8String; Index: Integer = 1; Count: Integer = -1): UTF8String;
@@ -520,6 +525,11 @@ begin
Result[1] := 0;
end;
+function UTF8Pos(const substr: UTF8String; const str: UTF8String): Integer;
+begin
+ Result := Pos(substr, str);
+end;
+
function UTF8Copy(const str: UTF8String; Index: Integer; Count: Integer): UTF8String;
begin
Result := UCS4ToUTF8String(UCS4Copy(UTF8ToUCS4String(str), Index-1, Count));
diff --git a/unicode/src/base/UXMLSong.pas b/unicode/src/base/UXMLSong.pas
index 58b48789..e8962539 100644
--- a/unicode/src/base/UXMLSong.pas
+++ b/unicode/src/base/UXMLSong.pas
@@ -34,7 +34,9 @@ interface
{$I switches.inc}
uses
- Classes;
+ Classes,
+ UPath,
+ UUnicodeUtils;
type
TNote = record
@@ -42,30 +44,30 @@ type
Duration: Cardinal;
Tone: Integer;
NoteTyp: Byte;
- Lyric: String;
+ Lyric: UTF8String;
end;
- ANote = Array of TNote;
+ ANote = array of TNote;
TSentence = record
Singer: Byte;
Duration: Cardinal;
Notes: ANote;
end;
- ASentence = Array of TSentence;
+ ASentence = array of TSentence;
- TSongInfo = Record
+ TSongInfo = record
ID: Cardinal;
DualChannel: Boolean;
- Header: Record
- Artist: String;
- Title: String;
+ Header: record
+ Artist: UTF8String;
+ Title: UTF8String;
Gap: Cardinal;
BPM: Real;
Resolution: Byte;
- Edition: String;
- Genre: String;
- Year: String;
- Language: String;
+ Edition: UTF8String;
+ Genre: UTF8String;
+ Year: UTF8String;
+ Language: UTF8String;
end;
CountSentences: Cardinal;
Sentences: ASentence;
@@ -81,23 +83,23 @@ type
BindLyrics: Boolean; //Should the Lyrics be bind to the last Word (no Space)
FirstNote: Boolean; //Is this the First Note found? For Gap calculating
- Function ParseLine(Line: String): Boolean;
+ function ParseLine(Line: RawByteString): Boolean;
public
SongInfo: TSongInfo;
- ErrorMessage: String;
- Edition: String;
- SingstarVersion: String;
+ ErrorMessage: string;
+ Edition: UTF8String;
+ SingstarVersion: string;
- Settings: Record
+ Settings: record
DashReplacement: Char;
end;
- Constructor Create;
+ constructor Create;
- Function ParseConfigforEdition(const Filename: String): String;
+ function ParseConfigForEdition(const Filename: IPath): String;
- Function ParseSongHeader(const Filename: String): Boolean; //Parse Song Header only
- Function ParseSong (const Filename: String): Boolean; //Parse whole Song
+ function ParseSongHeader(const Filename: IPath): Boolean; //Parse Song Header only
+ function ParseSong (const Filename: IPath): Boolean; //Parse whole Song
end;
const
@@ -114,9 +116,12 @@ const
DS_Both = 3;
implementation
-uses SysUtils, StrUtils;
-Constructor TParser.Create;
+uses
+ SysUtils,
+ StrUtils;
+
+constructor TParser.Create;
begin
inherited Create;
ErrorMessage := '';
@@ -124,19 +129,28 @@ begin
DecimalSeparator := '.';
end;
-Function TParser.ParseSong (const Filename: String): Boolean;
-var I: Integer;
+function TParser.ParseSong(const Filename: IPath): Boolean;
+var
+ I: Integer;
+ FileStream: TBinaryFileStream;
begin
+ {$message warn 'TODO: TParser.ParseSong'}
+
+(*
Result := False;
- if FileExists(Filename) then
+ if Filename.IsFile() then
begin
SSFile := TStringList.Create;
+ ErrorMessage := 'Can''t open melody.xml file';
+
try
- ErrorMessage := 'Can''t open melody.xml file';
- SSFile.LoadFromFile(Filename);
+ FileStream := TBinaryFileStream.Create(Filename);
+ SSFile.LoadFromStream(FileStream);
+
ErrorMessage := '';
Result := True;
+
I := 0;
SongInfo.CountSentences := 0;
@@ -153,7 +167,7 @@ begin
SetLength(SongInfo.Sentences, 0);
- While Result And (I < SSFile.Count) do
+ while Result and (I < SSFile.Count) do
begin
Result := ParseLine(SSFile.Strings[I]);
@@ -164,12 +178,16 @@ begin
SSFile.Free;
end;
end;
+ *)
end;
-Function TParser.ParseSongHeader (const Filename: String): Boolean;
+function TParser.ParseSongHeader (const Filename: IPath): Boolean;
var I: Integer;
begin
Result := False;
+
+ {$message warn 'TODO: TParser.ParseSong'}
+ (*
if FileExists(Filename) then
begin
SSFile := TStringList.Create;
@@ -211,6 +229,7 @@ begin
end
else
ErrorMessage := 'Can''t find melody.xml file';
+ *)
end;
Function TParser.ParseLine(Line: String): Boolean;
@@ -569,7 +588,7 @@ begin
Result := true;
end;
-Function TParser.ParseConfigforEdition(const Filename: String): String;
+Function TParser.ParseConfigForEdition(const Filename: IPath): String;
var
txt: TStringlist;
I: Integer;
@@ -578,6 +597,10 @@ var
begin
Result := '';
txt := TStringlist.Create;
+
+ {$message warn 'TODO: TParser.ParseConfigForEdition'}
+
+ (*
try
txt.LoadFromFile(Filename);
@@ -601,6 +624,7 @@ begin
finally
txt.Free;
end;
+ *)
end;
end.
diff --git a/unicode/src/lib/midi/MidiFile.pas b/unicode/src/lib/midi/MidiFile.pas
index 6b33c900..acf44c04 100644
--- a/unicode/src/lib/midi/MidiFile.pas
+++ b/unicode/src/lib/midi/MidiFile.pas
@@ -97,13 +97,13 @@ interface
uses
Windows,
- //Forms,
Messages,
Classes,
{$IFDEF FPC}
WinAllocation,
{$ENDIF}
- SysUtils;
+ SysUtils,
+ UPath;
type
TChunkType = (illegal, header, track);
@@ -162,7 +162,7 @@ type
procedure WndProc(var Msg : TMessage);
protected
{ Protected declarations }
- midiFile: file of byte;
+ midiFile: TBinaryFileStream;
chunkType: TChunkType;
chunkLength: integer;
chunkData: PByte;
@@ -177,7 +177,7 @@ type
FBpm: integer;
FBeatsPerMeasure: integer;
FusPerTick: double;
- FFilename: string;
+ FFilename: IPath;
Tracks: TList;
currentTrack: TMidiTrack;
@@ -191,7 +191,7 @@ type
currentPos: Double; // Current Position in ticks
procedure OnTrackReady;
- procedure setFilename(val: string);
+ procedure SetFilename(val: IPath);
procedure ReadChunkHeader;
procedure ReadChunkContent;
procedure ReadChunk;
@@ -221,7 +221,7 @@ type
function Ready: boolean;
published
{ Published declarations }
- property Filename: string read FFilename write setFilename;
+ property Filename: IPath read FFilename write SetFilename;
property NumberOfTracks: integer read numberTracks;
property TicksPerQuarter: integer read deltaTicks;
property FileFormat: TFileFormat read FFileFormat;
@@ -463,7 +463,7 @@ begin
result := Tracks.Items[index];
end;
-procedure TMidifile.setFilename(val: string);
+procedure TMidifile.SetFilename(val: IPath);
begin
FFilename := val;
// ReadFile;
@@ -586,7 +586,7 @@ procedure TMidifile.ReadChunkHeader;
var
theByte: array[0..7] of byte;
begin
- BlockRead(midiFile, theByte, 8);
+ midiFile.Read(theByte[0], 8);
if (theByte[0] = $4D) and (theByte[1] = $54) then
begin
if (theByte[2] = $68) and (theByte[3] = $64) then
@@ -608,7 +608,7 @@ begin
if not (chunkData = nil) then
FreeMem(chunkData);
GetMem(chunkData, chunkLength + 10);
- BlockRead(midiFile, chunkData^, chunkLength);
+ midiFile.Read(chunkData^, chunkLength);
chunkIndex := chunkData;
chunkEnd := PByte(integer(chunkIndex) + integer(chunkLength) - 1);
end;
@@ -848,12 +848,10 @@ begin
Tracks.Clear;
chunkType := illegal;
- AssignFile(midiFile, FFilename);
- FileMode := 0;
- Reset(midiFile);
- while not eof(midiFile) do
+ midiFile := TBinaryFileStream.Create(FFilename, fmOpenRead);
+ while (midiFile.Position < midiFile.Size) do
ReadChunk;
- CloseFile(midiFile);
+ FreeAndNil(midiFile);
numberTracks := Tracks.Count;
end;
diff --git a/unicode/src/media/UAudioCore_Bass.pas b/unicode/src/media/UAudioCore_Bass.pas
index 12623dc1..197f9760 100644
--- a/unicode/src/media/UAudioCore_Bass.pas
+++ b/unicode/src/media/UAudioCore_Bass.pas
@@ -44,6 +44,7 @@ type
public
constructor Create();
class function GetInstance(): TAudioCore_Bass;
+ function CheckVersion(): boolean;
function ErrorGetString(): string; overload;
function ErrorGetString(errCode: integer): string; overload;
function ConvertAudioFormatToBASSFlags(Format: TAudioSampleFormat; out Flags: DWORD): boolean;
@@ -56,6 +57,12 @@ uses
UMain,
ULog;
+const
+ // TODO: 2.4.2 is not ABI compatible with older versions
+ // as (BASS_RECORDINFO.driver was removed)
+ //BASS_MIN_REQUIRED_VERSION = $02040201;
+ BASS_MIN_REQUIRED_VERSION = $02000000;
+
var
Instance: TAudioCore_Bass;
@@ -71,6 +78,11 @@ begin
Result := Instance;
end;
+function TAudioCore_Bass.CheckVersion(): boolean;
+begin
+ Result := BASS_GetVersion() >= BASS_MIN_REQUIRED_VERSION;
+end;
+
function TAudioCore_Bass.ErrorGetString(): string;
begin
Result := ErrorGetString(BASS_ErrorGetCode());
diff --git a/unicode/src/media/UAudioDecoder_Bass.pas b/unicode/src/media/UAudioDecoder_Bass.pas
index 6bbdaeaa..d6d2425a 100644
--- a/unicode/src/media/UAudioDecoder_Bass.pas
+++ b/unicode/src/media/UAudioDecoder_Bass.pas
@@ -38,11 +38,12 @@ implementation
uses
Classes,
SysUtils,
+ bass,
UMain,
UMusic,
UAudioCore_Bass,
ULog,
- bass;
+ UPath;
type
TBassDecodeStream = class(TAudioDecodeStream)
@@ -75,7 +76,7 @@ type
function InitializeDecoder(): boolean;
function FinalizeDecoder(): boolean;
- function Open(const Filename: string): TAudioDecodeStream;
+ function Open(const Filename: IPath): TAudioDecodeStream;
end;
var
@@ -213,7 +214,10 @@ end;
function TAudioDecoder_Bass.InitializeDecoder(): boolean;
begin
+ Result := false;
BassCore := TAudioCore_Bass.GetInstance();
+ if not BassCore.CheckVersion then
+ Exit;
Result := true;
end;
@@ -222,7 +226,7 @@ begin
Result := true;
end;
-function TAudioDecoder_Bass.Open(const Filename: string): TAudioDecodeStream;
+function TAudioDecoder_Bass.Open(const Filename: IPath): TAudioDecodeStream;
var
Stream: HSTREAM;
ChannelInfo: BASS_CHANNELINFO;
@@ -237,7 +241,14 @@ begin
// TODO: use BASS_STREAM_PRESCAN for accurate seeking in VBR-files?
// disadvantage: seeking will slow down.
- Stream := BASS_StreamCreateFile(False, PAnsiChar(Filename), 0, 0, BASS_STREAM_DECODE);
+
+ {$IFDEF MSWINDOWS}
+ // Windows: Use UTF-16 version
+ Stream := BASS_StreamCreateFile(False, PWideChar(Filename.ToWide), 0, 0, BASS_STREAM_DECODE or BASS_UNICODE);
+ {$ELSE}
+ // Mac OS X: Use UTF8/ANSI version
+ Stream := BASS_StreamCreateFile(False, PAnsiChar(Filename.ToNative), 0, 0, BASS_STREAM_DECODE);
+ {$ENDIF}
if (Stream = 0) then
begin
//Log.LogError(BassCore.ErrorGetString(), 'TAudioDecoder_Bass.Open');
@@ -247,7 +258,7 @@ begin
// check if BASS opened some erroneously recognized file-formats
if BASS_ChannelGetInfo(Stream, channelInfo) then
begin
- fileExt := ExtractFileExt(Filename);
+ fileExt := Filename.GetExtension.ToUTF8;
// BASS opens FLV-files (maybe others too) although it cannot handle them.
// Setting BASS_CONFIG_VERIFY to the max. value (100000) does not help.
if ((fileExt = '.flv') and (channelInfo.ctype = BASS_CTYPE_STREAM_MP1)) then
diff --git a/unicode/src/media/UAudioDecoder_FFmpeg.pas b/unicode/src/media/UAudioDecoder_FFmpeg.pas
index 97d8a8df..aed4390c 100644
--- a/unicode/src/media/UAudioDecoder_FFmpeg.pas
+++ b/unicode/src/media/UAudioDecoder_FFmpeg.pas
@@ -56,23 +56,24 @@ interface
implementation
uses
+ SDL, // SDL redefines some base types -> include before SysUtils to ignore them
Classes,
Math,
- UMusic,
- UIni,
- UMain,
+ SysUtils,
avcodec,
avformat,
avutil,
avio,
mathematics, // used for av_rescale_q
rational,
- SDL,
- SysUtils,
+ UMusic,
+ UIni,
+ UMain,
UMediaCore_FFmpeg,
ULog,
UCommon,
- UConfig;
+ UConfig,
+ UPath;
const
MAX_AUDIOQ_SIZE = (5 * 16 * 1024);
@@ -138,7 +139,7 @@ type
AudioBufferSize: integer;
AudioBuffer: PByteArray;
- Filename: string;
+ Filename: IPath;
procedure SetPositionIntern(Time: real; Flush: boolean; Blocking: boolean);
procedure SetEOF(State: boolean); {$IFDEF HasInline}inline;{$ENDIF}
@@ -161,7 +162,7 @@ type
constructor Create();
destructor Destroy(); override;
- function Open(const Filename: string): boolean;
+ function Open(const Filename: IPath): boolean;
procedure Close(); override;
function GetLength(): real; override;
@@ -183,7 +184,7 @@ type
function InitializeDecoder(): boolean;
function FinalizeDecoder(): boolean;
- function Open(const Filename: string): TAudioDecodeStream;
+ function Open(const Filename: IPath): TAudioDecodeStream;
end;
var
@@ -270,7 +271,7 @@ begin
inherited;
end;
-function TFFmpegDecodeStream.Open(const Filename: string): boolean;
+function TFFmpegDecodeStream.Open(const Filename: IPath): boolean;
var
SampleFormat: TAudioSampleFormat;
AVResult: integer;
@@ -280,18 +281,18 @@ begin
Close();
Reset();
- if (not FileExists(Filename)) then
+ if (not Filename.IsFile) then
begin
- Log.LogError('Audio-file does not exist: "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('Audio-file does not exist: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Exit;
end;
Self.Filename := Filename;
- // open audio file
- if (av_open_input_file(FormatCtx, PAnsiChar(Filename), nil, 0, nil) <> 0) then
+ // open audio file (TODO: unicode support)
+ if (av_open_input_file(FormatCtx, PAnsiChar(Filename.ToNative), nil, 0, nil) <> 0) then
begin
- Log.LogError('av_open_input_file failed: "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('av_open_input_file failed: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Exit;
end;
@@ -301,7 +302,7 @@ begin
// retrieve stream information
if (av_find_stream_info(FormatCtx) < 0) then
begin
- Log.LogError('av_find_stream_info failed: "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('av_find_stream_info failed: "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Close();
Exit;
end;
@@ -310,13 +311,13 @@ begin
FormatCtx^.pb.eof_reached := 0;
{$IFDEF DebugFFmpegDecode}
- dump_format(FormatCtx, 0, PAnsiChar(Filename), 0);
+ dump_format(FormatCtx, 0, PAnsiChar(Filename.ToNative), 0);
{$ENDIF}
AudioStreamIndex := FFmpegCore.FindAudioStreamIndex(FormatCtx);
if (AudioStreamIndex < 0) then
begin
- Log.LogError('FindAudioStreamIndex: No Audio-stream found "' + Filename + '"', 'UAudio_FFmpeg');
+ Log.LogError('FindAudioStreamIndex: No Audio-stream found "' + Filename.ToNative + '"', 'UAudio_FFmpeg');
Close();
Exit;
end;
@@ -1117,7 +1118,7 @@ begin
Result := true;
end;
-function TAudioDecoder_FFmpeg.Open(const Filename: string): TAudioDecodeStream;
+function TAudioDecoder_FFmpeg.Open(const Filename: IPath): TAudioDecodeStream;
var
Stream: TFFmpegDecodeStream;
begin
diff --git a/unicode/src/media/UAudioInput_Bass.pas b/unicode/src/media/UAudioInput_Bass.pas
index ad6c3818..9d4417f1 100644
--- a/unicode/src/media/UAudioInput_Bass.pas
+++ b/unicode/src/media/UAudioInput_Bass.pas
@@ -489,6 +489,11 @@ end;
function TAudioInput_Bass.InitializeRecord(): boolean;
begin
BassCore := TAudioCore_Bass.GetInstance();
+ if not BassCore.CheckVersion then
+ begin
+ Result := false;
+ Exit;
+ end;
Result := EnumDevices();
end;
diff --git a/unicode/src/media/UAudioPlaybackBase.pas b/unicode/src/media/UAudioPlaybackBase.pas
index 7d143fdc..de2d5563 100644
--- a/unicode/src/media/UAudioPlaybackBase.pas
+++ b/unicode/src/media/UAudioPlaybackBase.pas
@@ -34,7 +34,8 @@ interface
{$I switches.inc}
uses
- UMusic;
+ UMusic,
+ UPath;
type
TAudioPlaybackBase = class(TInterfacedObject, IAudioPlayback)
@@ -46,12 +47,12 @@ type
function GetLatency(): double; virtual; abstract;
// open sound or music stream (used by Open() and OpenSound())
- function OpenStream(const Filename: string): TAudioPlaybackStream;
- function OpenDecodeStream(const Filename: string): TAudioDecodeStream;
+ function OpenStream(const Filename: IPath): TAudioPlaybackStream;
+ function OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
public
function GetName: string; virtual; abstract;
- function Open(const Filename: string): boolean; // true if succeed
+ function Open(const Filename: IPath): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -79,7 +80,7 @@ type
function Length: real;
// Sounds
- function OpenSound(const Filename: string): TAudioPlaybackStream;
+ function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure PlaySound(Stream: TAudioPlaybackStream);
procedure StopSound(Stream: TAudioPlaybackStream);
@@ -108,7 +109,7 @@ begin
Result := true;
end;
-function TAudioPlaybackBase.Open(const Filename: string): boolean;
+function TAudioPlaybackBase.Open(const Filename: IPath): boolean;
begin
// free old MusicStream
MusicStream.Free;
@@ -130,7 +131,7 @@ begin
FreeAndNil(MusicStream);
end;
-function TAudioPlaybackBase.OpenDecodeStream(const Filename: String): TAudioDecodeStream;
+function TAudioPlaybackBase.OpenDecodeStream(const Filename: IPath): TAudioDecodeStream;
var
i: integer;
begin
@@ -140,7 +141,7 @@ begin
if (assigned(Result)) then
begin
Log.LogInfo('Using decoder ' + IAudioDecoder(AudioDecoders[i]).GetName() +
- ' for "' + Filename + '"', 'TAudioPlaybackBase.OpenDecodeStream');
+ ' for "' + Filename.ToNative + '"', 'TAudioPlaybackBase.OpenDecodeStream');
Exit;
end;
end;
@@ -157,7 +158,7 @@ begin
SourceStream.Free;
end;
-function TAudioPlaybackBase.OpenStream(const Filename: string): TAudioPlaybackStream;
+function TAudioPlaybackBase.OpenStream(const Filename: IPath): TAudioPlaybackStream;
var
PlaybackStream: TAudioPlaybackStream;
DecodeStream: TAudioDecodeStream;
@@ -169,7 +170,7 @@ begin
DecodeStream := OpenDecodeStream(Filename);
if (not assigned(DecodeStream)) then
begin
- Log.LogStatus('Could not open "' + Filename + '"', 'TAudioPlayback_Bass.OpenStream');
+ Log.LogStatus('Could not open "' + Filename.ToNative + '"', 'TAudioPlayback_Bass.OpenStream');
Exit;
end;
@@ -283,7 +284,7 @@ begin
Result := 0;
end;
-function TAudioPlaybackBase.OpenSound(const Filename: string): TAudioPlaybackStream;
+function TAudioPlaybackBase.OpenSound(const Filename: IPath): TAudioPlaybackStream;
begin
Result := OpenStream(Filename);
end;
diff --git a/unicode/src/media/UAudioPlayback_Bass.pas b/unicode/src/media/UAudioPlayback_Bass.pas
index 923c1d7b..1d7a44dc 100644
--- a/unicode/src/media/UAudioPlayback_Bass.pas
+++ b/unicode/src/media/UAudioPlayback_Bass.pas
@@ -684,9 +684,11 @@ end;
function TAudioPlayback_Bass.InitializePlayback(): boolean;
begin
- result := false;
+ Result := false;
BassCore := TAudioCore_Bass.GetInstance();
+ if not BassCore.CheckVersion then
+ Exit;
EnumDevices();
@@ -706,7 +708,7 @@ begin
//BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, 10);
//BASS_SetConfig(BASS_CONFIG_BUFFER, 100);
- result := true;
+ Result := true;
end;
function TAudioPlayback_Bass.FinalizePlayback(): boolean;
diff --git a/unicode/src/media/UMedia_dummy.pas b/unicode/src/media/UMedia_dummy.pas
index 7558dd0b..25e94724 100644
--- a/unicode/src/media/UMedia_dummy.pas
+++ b/unicode/src/media/UMedia_dummy.pas
@@ -36,9 +36,10 @@ interface
implementation
uses
- SysUtils,
- math,
- UMusic;
+ SysUtils,
+ math,
+ UMusic,
+ UPath;
type
TMedia_dummy = class( TInterfacedObject, IVideoPlayback, IVideoVisualization, IAudioPlayback, IAudioInput )
@@ -51,7 +52,7 @@ type
function Init(): boolean;
function Finalize(): boolean;
- function Open(const aFileName : string): boolean; // true if succeed
+ function Open(const aFileName: IPath): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -88,7 +89,7 @@ type
function Finished: boolean;
function Length: real;
- function OpenSound(const Filename: string): TAudioPlaybackStream;
+ function OpenSound(const Filename: IPath): TAudioPlaybackStream;
procedure CloseSound(var PlaybackStream: TAudioPlaybackStream);
procedure PlaySound(stream: TAudioPlaybackStream);
procedure StopSound(stream: TAudioPlaybackStream);
@@ -125,7 +126,7 @@ begin
Result := true;
end;
-function TMedia_dummy.Open(const aFileName : string): boolean; // true if succeed
+function TMedia_dummy.Open(const aFileName : IPath): boolean; // true if succeed
begin
Result := false;
end;
@@ -236,7 +237,7 @@ begin
Result := 60;
end;
-function TMedia_dummy.OpenSound(const Filename: string): TAudioPlaybackStream;
+function TMedia_dummy.OpenSound(const Filename: IPath): TAudioPlaybackStream;
begin
Result := nil;
end;
diff --git a/unicode/src/media/UVideo.pas b/unicode/src/media/UVideo.pas
index f55690b2..de01fd68 100644
--- a/unicode/src/media/UVideo.pas
+++ b/unicode/src/media/UVideo.pas
@@ -69,8 +69,9 @@ type
implementation
uses
+ SysUtils,
+ Math,
SDL,
- textgl,
avcodec,
avformat,
avutil,
@@ -79,17 +80,17 @@ uses
{$IFDEF UseSWScale}
swscale,
{$ENDIF}
- UMediaCore_FFmpeg,
- math,
gl,
glext,
- SysUtils,
+ textgl,
+ UMediaCore_FFmpeg,
UCommon,
UConfig,
ULog,
UMusic,
UGraphicClasses,
- UGraphic;
+ UGraphic,
+ UPath;
const
{$IFDEF PIXEL_FMT_BGR}
@@ -154,7 +155,7 @@ type
function Init(): boolean;
function Finalize: boolean;
- function Open(const aFileName : string): boolean; // true if succeed
+ function Open(const FileName : IPath): boolean; // true if succeed
procedure Close;
procedure Play;
@@ -252,7 +253,7 @@ begin
fAspectCorrection := acoCrop;
end;
-function TVideoPlayback_FFmpeg.Open(const aFileName : string): boolean; // true if succeed
+function TVideoPlayback_FFmpeg.Open(const FileName : IPath): boolean; // true if succeed
var
errnum: Integer;
AudioStreamIndex: integer;
@@ -261,10 +262,10 @@ begin
Reset();
- errnum := av_open_input_file(fFormatContext, PChar(aFileName), nil, 0, nil);
+ errnum := av_open_input_file(fFormatContext, PChar(FileName.ToNative), nil, 0, nil);
if (errnum <> 0) then
begin
- Log.LogError('Failed to open file "'+aFileName+'" ('+FFmpegCore.GetErrorString(errnum)+')');
+ Log.LogError('Failed to open file "'+ FileName.ToNative +'" ('+FFmpegCore.GetErrorString(errnum)+')');
Exit;
end;
diff --git a/unicode/src/menu/UDisplay.pas b/unicode/src/menu/UDisplay.pas
index a4d16500..aded7f3f 100644
--- a/unicode/src/menu/UDisplay.pas
+++ b/unicode/src/menu/UDisplay.pas
@@ -36,10 +36,11 @@ interface
uses
UCommon,
SDL,
- UMenu,
gl,
glu,
- SysUtils;
+ SysUtils,
+ UMenu,
+ UPath;
type
TDisplay = class
@@ -504,47 +505,47 @@ end;
procedure TDisplay.SaveScreenShot;
var
Num: integer;
- FileName: string;
+ FileName: IPath;
+ Prefix: UTF8String;
ScreenData: PChar;
Surface: PSDL_Surface;
Success: boolean;
Align: integer;
RowSize: integer;
begin
-// Exit if Screenshot-path does not exist or read-only
- if (ScreenshotsPath = '') then
+ // Exit if Screenshot-path does not exist or read-only
+ if (ScreenshotsPath.IsUnset) then
Exit;
for Num := 1 to 9999 do
begin
- FileName := IntToStr(Num);
- while Length(FileName) < 4 do
- FileName := '0' + FileName;
- FileName := ScreenshotsPath + 'screenshot' + FileName + '.png';
- if not FileExists(FileName) then
- break
+ // fill prefix to 4 digits with leading '0', e.g. '0001'
+ Prefix := Format('screenshot%.4d', [Num]);
+ FileName := ScreenshotsPath.Append(Prefix + '.png');
+ if not FileName.Exists() then
+ break;
end;
-// we must take the row-alignment (4byte by default) into account
+ // we must take the row-alignment (4byte by default) into account
glGetIntegerv(GL_PACK_ALIGNMENT, @Align);
-// calc aligned row-size
+ // calc aligned row-size
RowSize := ((ScreenW*3 + (Align-1)) div Align) * Align;
GetMem(ScreenData, RowSize * ScreenH);
glReadPixels(0, 0, ScreenW, ScreenH, GL_RGB, GL_UNSIGNED_BYTE, ScreenData);
-// on big endian machines (powerpc) this may need to be changed to
-// Needs to be tests. KaMiSchi Sept 2008
-// in this case one may have to add " glext, " to the list of used units
-// glReadPixels(0, 0, ScreenW, ScreenH, GL_BGR, GL_UNSIGNED_BYTE, ScreenData);
+ // on big endian machines (powerpc) this may need to be changed to
+ // Needs to be tests. KaMiSchi Sept 2008
+ // in this case one may have to add " glext, " to the list of used units
+ // glReadPixels(0, 0, ScreenW, ScreenH, GL_BGR, GL_UNSIGNED_BYTE, ScreenData);
Surface := SDL_CreateRGBSurfaceFrom(
ScreenData, ScreenW, ScreenH, 24, RowSize,
$0000FF, $00FF00, $FF0000, 0);
-// Success := WriteJPGImage(FileName, Surface, 95);
-// Success := WriteBMPImage(FileName, Surface);
+ // Success := WriteJPGImage(FileName, Surface, 95);
+ // Success := WriteBMPImage(FileName, Surface);
Success := WritePNGImage(FileName, Surface);
if Success then
- ScreenPopupError.ShowPopup('Screenshot saved: ' + ExtractFileName(FileName))
+ ScreenPopupError.ShowPopup('Screenshot saved: ' + FileName.GetName.ToUTF8())
else
ScreenPopupError.ShowPopup('Screenshot failed');
@@ -559,7 +560,7 @@ procedure TDisplay.DrawDebugInformation;
var
Ticks: cardinal;
begin
-// Some White Background for information
+ // Some White Background for information
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 0.5);
@@ -571,13 +572,13 @@ begin
glEnd;
glDisable(GL_BLEND);
-// set font specs
+ // set font specs
SetFontStyle(0);
SetFontSize(21);
SetFontItalic(false);
glColor4f(0, 0, 0, 1);
-// calculate fps
+ // calculate fps
Ticks := SDL_GetTicks();
if (Ticks >= NextFPSSwap) then
begin
@@ -588,17 +589,17 @@ begin
Inc(FPSCounter);
-// draw text
+ // draw text
-// fps
+ // fps
SetFontPos(695, 0);
glPrint ('FPS: ' + InttoStr(LastFPS));
-// rspeed
+ // rspeed
SetFontPos(695, 13);
glPrint ('RSpeed: ' + InttoStr(Round(1000 * TimeMid)));
-// lasterror
+ // lasterror
SetFontPos(695, 26);
glColor4f(1, 0, 0, 1);
glPrint (OSD_LastError);
diff --git a/unicode/src/menu/UMenu.pas b/unicode/src/menu/UMenu.pas
index f7e98d32..6c01451c 100644
--- a/unicode/src/menu/UMenu.pas
+++ b/unicode/src/menu/UMenu.pas
@@ -38,6 +38,7 @@ uses
Math,
gl,
SDL,
+ UPath,
UMenuBackground,
UMenuButton,
UMenuButtonCollection,
@@ -96,13 +97,13 @@ type
// static
function AddStatic(ThemeStatic: TThemeStatic): integer; overload;
- function AddStatic(X, Y, W, H: real; const Name: string): integer; overload;
- function AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; overload;
- function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload;
- function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload;
- function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload;
- function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload;
- function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: boolean; ReflectionSpacing: real): integer; overload;
+ function AddStatic(X, Y, W, H: real; const TexName: IPath): integer; overload;
+ function AddStatic(X, Y, W, H: real; const TexName: IPath; Typ: TTextureType): integer; overload;
+ function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType): integer; overload;
+ function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType): integer; overload;
+ function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType; Color: integer): integer; overload;
+ function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const TexName: IPath; Typ: TTextureType; Color: integer): integer; overload;
+ function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const TexName: IPath; Typ: TTextureType; Color: integer; Reflection: boolean; ReflectionSpacing: real): integer; overload;
// text
function AddText(ThemeText: TThemeText): integer; overload;
@@ -113,9 +114,9 @@ type
// button
procedure SetButtonLength(Length: cardinal); //Function that Set Length of Button Array in one Step instead of register new Memory for every Button
function AddButton(ThemeButton: TThemeButton): integer; overload;
- function AddButton(X, Y, W, H: real; const Name: string): integer; overload;
- function AddButton(X, Y, W, H: real; const Name: string; Typ: TTextureType; Reflection: boolean): integer; overload;
- function AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; const Name: string; Typ: TTextureType; Reflection: boolean; ReflectionSpacing, DeSelectReflectionSpacing: real): integer; overload;
+ function AddButton(X, Y, W, H: real; const TexName: IPath): integer; overload;
+ function AddButton(X, Y, W, H: real; const TexName: IPath; Typ: TTextureType; Reflection: boolean): integer; overload;
+ function AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; const TexName: IPath; Typ: TTextureType; Reflection: boolean; ReflectionSpacing, DeSelectReflectionSpacing: real): integer; overload;
procedure ClearButtons;
procedure AddButtonText(AddX, AddY: real; const AddText: UTF8String); overload;
procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: UTF8String); overload;
@@ -123,16 +124,16 @@ type
procedure AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: UTF8String); overload;
// select slide
- function AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of string): integer; overload;
+ function AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of UTF8String): integer; overload;
function AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt,
TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt,
SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt,
STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real;
- const Name: string; Typ: TTextureType; const SBGName: string; SBGTyp: TTextureType;
+ const TexName: IPath; Typ: TTextureType; const SBGName: IPath; SBGTyp: TTextureType;
const Caption: UTF8String; var Data: integer): integer; overload;
procedure AddSelectSlideOption(const AddText: UTF8String); overload;
procedure AddSelectSlideOption(SelectNo: cardinal; const AddText: UTF8String); overload;
- procedure UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; const Values: array of string; var Data: integer);
+ procedure UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; const Values: array of UTF8String; var Data: integer);
// function AddWidget(X, Y : UInt16; WidgetSrc : PSDL_Surface): Int16;
// procedure ClearWidgets(MinNumber : Int16);
@@ -389,7 +390,7 @@ begin
begin
//At first some intelligent try to decide which BG to load
- FileExt := lowercase(ExtractFileExt(Skin.GetTextureFileName(ThemedSettings.Tex)));
+ FileExt := LowerCase(Skin.GetTextureFileName(ThemedSettings.Tex).GetExtension.ToUTF8);
if IsInArray(FileExt, SUPPORTED_EXTS_BACKGROUNDTEXTURE) then
TryBGCreate(TMenuBackgroundTexture)
@@ -597,29 +598,29 @@ begin
ThemeStatic.Typ, $FFFFFF, ThemeStatic.Reflection, ThemeStatic.Reflectionspacing);
end;
-function TMenu.AddStatic(X, Y, W, H: real; const Name: string): integer;
+function TMenu.AddStatic(X, Y, W, H: real; const TexName: IPath): integer;
begin
- Result := AddStatic(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN);
+ Result := AddStatic(X, Y, W, H, TexName, TEXTURE_TYPE_PLAIN);
end;
function TMenu.AddStatic(X, Y, W, H: real;
- ColR, ColG, ColB: real;
- const Name: string;
+ ColR, ColG, ColB: real;
+ const TexName: IPath;
Typ: TTextureType): integer;
begin
- Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, Name, Typ, $FFFFFF);
+ Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, TexName, Typ, $FFFFFF);
end;
function TMenu.AddStatic(X, Y, W, H, Z: real;
- ColR, ColG, ColB: real;
- const Name: string;
+ ColR, ColG, ColB: real;
+ const TexName: IPath;
Typ: TTextureType): integer;
begin
- Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, Name, Typ, $FFFFFF);
+ Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, TexName, Typ, $FFFFFF);
end;
function TMenu.AddStatic(X, Y, W, H: real;
- const Name: string;
+ const TexName: IPath;
Typ: TTextureType): integer;
var
StatNum: integer;
@@ -627,7 +628,7 @@ begin
// adds static
StatNum := Length(Static);
SetLength(Static, StatNum + 1);
- Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, $FF00FF)); // new skin
+ Static[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, $FF00FF)); // new skin
// configures static
Static[StatNum].Texture.X := X;
@@ -640,26 +641,26 @@ end;
function TMenu.AddStatic(X, Y, W, H: real;
ColR, ColG, ColB: real;
- const Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Color: integer): integer;
begin
- Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, Name, Typ, Color);
+ Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, TexName, Typ, Color);
end;
function TMenu.AddStatic(X, Y, W, H, Z: real;
ColR, ColG, ColB: real;
- const Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Color: integer): integer;
begin
- Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, Name, Typ, Color, false, 0);
+ Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, TexName, Typ, Color, false, 0);
end;
function TMenu.AddStatic(X, Y, W, H, Z: real;
ColR, ColG, ColB: real;
TexX1, TexY1, TexX2, TexY2: real;
- const Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Color: integer;
Reflection: boolean;
@@ -675,11 +676,11 @@ begin
if (Typ = TEXTURE_TYPE_COLORIZED) then
begin
// give encoded color to GetTexture()
- Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)));
+ Static[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB)));
end
else
begin
- Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, Color)); // new skin
+ Static[StatNum] := TStatic.Create(Texture.GetTexture(TexName, Typ, Color)); // new skin
end;
// configures static
@@ -841,18 +842,18 @@ begin
Log.LogBenchmark('====> Screen Options32', 6);
end;
-function TMenu.AddButton(X, Y, W, H: real; const Name: string): integer;
+function TMenu.AddButton(X, Y, W, H: real; const TexName: IPath): integer;
begin
- Result := AddButton(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN, false);
+ Result := AddButton(X, Y, W, H, TexName, TEXTURE_TYPE_PLAIN, false);
end;
-function TMenu.AddButton(X, Y, W, H: real; const Name: string; Typ: TTextureType; Reflection: boolean): integer;
+function TMenu.AddButton(X, Y, W, H: real; const TexName: IPath; Typ: TTextureType; Reflection: boolean): integer;
begin
- Result := AddButton(X, Y, W, H, 1, 1, 1, 1, 1, 1, 1, 0.5, Name, TEXTURE_TYPE_PLAIN, Reflection, 15, 15);
+ Result := AddButton(X, Y, W, H, 1, 1, 1, 1, 1, 1, 1, 0.5, TexName, TEXTURE_TYPE_PLAIN, Reflection, 15, 15);
end;
function TMenu.AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real;
- const Name: string;
+ const TexName: IPath;
Typ: TTextureType;
Reflection: boolean;
ReflectionSpacing, DeSelectReflectionSpacing: real): integer;
@@ -874,12 +875,12 @@ begin
if (Typ = TEXTURE_TYPE_COLORIZED) then
begin
// give encoded color to GetTexture()
- Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)),
- Texture.GetTexture(Name, Typ, RGBFloatToInt(DColR, DColG, DColB)));
+ Button[Result] := TButton.Create(Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB)),
+ Texture.GetTexture(TexName, Typ, RGBFloatToInt(DColR, DColG, DColB)));
end
else
begin
- Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ));
+ Button[Result] := TButton.Create(Texture.GetTexture(TexName, Typ));
end;
// configures button
@@ -1264,7 +1265,7 @@ begin
end;
end;
-function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of string): integer;
+function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; const Values: array of UTF8String): integer;
var
SO: integer;
begin
@@ -1301,7 +1302,7 @@ function TMenu.AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DC
TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt,
SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt,
STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real;
- const Name: string; Typ: TTextureType; const SBGName: string; SBGTyp: TTextureType;
+ const TexName: IPath; Typ: TTextureType; const SBGName: IPath; SBGTyp: TTextureType;
const Caption: UTF8String; var Data: integer): integer;
var
S: integer;
@@ -1312,9 +1313,9 @@ begin
SelectsS[S] := TSelectSlide.Create;
if (Typ = TEXTURE_TYPE_COLORIZED) then
- SelectsS[S].Texture := Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB))
+ SelectsS[S].Texture := Texture.GetTexture(TexName, Typ, RGBFloatToInt(ColR, ColG, ColB))
else
- SelectsS[S].Texture := Texture.GetTexture(Name, Typ);
+ SelectsS[S].Texture := Texture.GetTexture(TexName, Typ);
SelectsS[S].X := X;
SelectsS[S].Y := Y;
SelectsS[S].W := W;
@@ -1453,7 +1454,8 @@ begin
}
end;
-procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; const Values: array of string; var Data: integer);
+procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide;
+ SelectNum: integer; const Values: array of UTF8String; var Data: integer);
var
SO: integer;
begin
diff --git a/unicode/src/menu/UMenuBackgroundColor.pas b/unicode/src/menu/UMenuBackgroundColor.pas
index a5c2a70a..45b58c1e 100644
--- a/unicode/src/menu/UMenuBackgroundColor.pas
+++ b/unicode/src/menu/UMenuBackgroundColor.pas
@@ -1,73 +1,73 @@
-{* UltraStar Deluxe - Karaoke Game
- *
- * UltraStar Deluxe is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *}
-
-unit UMenuBackgroundColor;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- UThemes,
- UMenuBackground;
-
-//TMenuBackgroundColor - Background Color
-//--------
-
-type
- TMenuBackgroundColor = class (TMenuBackground)
- private
- Color: TRGB;
- public
- constructor Create(const ThemedSettings: TThemeBackground); override;
- procedure Draw; override;
- end;
-
-implementation
-uses
- gl,
- glext,
- UGraphic;
-
-constructor TMenuBackgroundColor.Create(const ThemedSettings: TThemeBackground);
-begin
- inherited;
- Color := ThemedSettings.Color;
-end;
-
-procedure TMenuBackgroundColor.Draw;
-begin
- if (ScreenAct = 1) then
- begin //just clear once, even when using two screens
- glClearColor(Color.R, Color.G, Color.B, 0);
- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
- end;
-end;
-
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundColor;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ UThemes,
+ UMenuBackground;
+
+//TMenuBackgroundColor - Background Color
+//--------
+
+type
+ TMenuBackgroundColor = class (TMenuBackground)
+ private
+ Color: TRGB;
+ public
+ constructor Create(const ThemedSettings: TThemeBackground); override;
+ procedure Draw; override;
+ end;
+
+implementation
+uses
+ gl,
+ glext,
+ UGraphic;
+
+constructor TMenuBackgroundColor.Create(const ThemedSettings: TThemeBackground);
+begin
+ inherited;
+ Color := ThemedSettings.Color;
+end;
+
+procedure TMenuBackgroundColor.Draw;
+begin
+ if (ScreenAct = 1) then
+ begin //just clear once, even when using two screens
+ glClearColor(Color.R, Color.G, Color.B, 0);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+ end;
+end;
+
end. \ No newline at end of file
diff --git a/unicode/src/menu/UMenuBackgroundFade.pas b/unicode/src/menu/UMenuBackgroundFade.pas
index b61a4542..6fef063f 100644
--- a/unicode/src/menu/UMenuBackgroundFade.pas
+++ b/unicode/src/menu/UMenuBackgroundFade.pas
@@ -36,7 +36,8 @@ interface
uses
UThemes,
UTexture,
- UMenuBackground;
+ UMenuBackground,
+ UPath;
//TMenuBackgroundFade - Background Fade In for Overlay screens
//--------
@@ -72,7 +73,7 @@ uses
constructor TMenuBackgroundFade.Create(const ThemedSettings: TThemeBackground);
var
- texFilename: string;
+ texFilename: IPath;
begin
inherited;
FadeTime := 0;
@@ -82,7 +83,6 @@ begin
if (Length(ThemedSettings.Tex) > 0) then
begin
texFilename := Skin.GetTextureFileName(ThemedSettings.Tex);
- texFilename := AdaptFilePaths(texFilename);
Tex := Texture.GetTexture(texFilename, TEXTURE_TYPE_PLAIN);
UseTexture := (Tex.TexNum <> 0);
diff --git a/unicode/src/menu/UMenuBackgroundNone.pas b/unicode/src/menu/UMenuBackgroundNone.pas
index 1fccc007..c64f3023 100644
--- a/unicode/src/menu/UMenuBackgroundNone.pas
+++ b/unicode/src/menu/UMenuBackgroundNone.pas
@@ -1,70 +1,70 @@
-{* UltraStar Deluxe - Karaoke Game
- *
- * UltraStar Deluxe is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *}
-
-unit UMenuBackgroundNone;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- UThemes,
- UMenuBackground;
-
-//TMenuBackgroundNone - Just no Background (e.g. for Overlays)
-//--------
-
-type
- TMenuBackgroundNone = class (TMenuBackground)
- private
-
- public
- constructor Create(const ThemedSettings: TThemeBackground); override;
- procedure Draw; override;
- end;
-
-implementation
-uses
- gl,
- glext,
- UGraphic;
-
-constructor TMenuBackgroundNone.Create(const ThemedSettings: TThemeBackground);
-begin
- inherited;
-end;
-
-procedure TMenuBackgroundNone.Draw;
-begin
- //Do just nothing in here!
- If (ScreenAct = 1) then //Clear just once when in dual screen mode
- glClear(GL_DEPTH_BUFFER_BIT);
-end;
-
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UMenuBackgroundNone;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ UThemes,
+ UMenuBackground;
+
+//TMenuBackgroundNone - Just no Background (e.g. for Overlays)
+//--------
+
+type
+ TMenuBackgroundNone = class (TMenuBackground)
+ private
+
+ public
+ constructor Create(const ThemedSettings: TThemeBackground); override;
+ procedure Draw; override;
+ end;
+
+implementation
+uses
+ gl,
+ glext,
+ UGraphic;
+
+constructor TMenuBackgroundNone.Create(const ThemedSettings: TThemeBackground);
+begin
+ inherited;
+end;
+
+procedure TMenuBackgroundNone.Draw;
+begin
+ //Do just nothing in here!
+ If (ScreenAct = 1) then //Clear just once when in dual screen mode
+ glClear(GL_DEPTH_BUFFER_BIT);
+end;
+
end. \ No newline at end of file
diff --git a/unicode/src/menu/UMenuBackgroundTexture.pas b/unicode/src/menu/UMenuBackgroundTexture.pas
index a1b9e88a..91ea6503 100644
--- a/unicode/src/menu/UMenuBackgroundTexture.pas
+++ b/unicode/src/menu/UMenuBackgroundTexture.pas
@@ -36,7 +36,8 @@ interface
uses
UThemes,
UTexture,
- UMenuBackground;
+ UMenuBackground,
+ UPath;
//TMenuBackgroundColor - Background Color
//--------
@@ -65,7 +66,8 @@ uses
UGraphic;
constructor TMenuBackgroundTexture.Create(const ThemedSettings: TThemeBackground);
-var texFilename: string;
+var
+ texFilename: IPath;
begin
inherited;
@@ -75,7 +77,6 @@ begin
Color := ThemedSettings.Color;
texFilename := Skin.GetTextureFileName(ThemedSettings.Tex);
- texFilename := AdaptFilePaths(texFilename);
Tex := Texture.GetTexture(texFilename, TEXTURE_TYPE_PLAIN);
if (Tex.TexNum = 0) then
diff --git a/unicode/src/menu/UMenuBackgroundVideo.pas b/unicode/src/menu/UMenuBackgroundVideo.pas
index d1ce0f09..0e0a2bff 100644
--- a/unicode/src/menu/UMenuBackgroundVideo.pas
+++ b/unicode/src/menu/UMenuBackgroundVideo.pas
@@ -36,7 +36,8 @@ interface
uses
UThemes,
UMenuBackground,
- UVideo;
+ UVideo,
+ UPath;
//TMenuBackgroundColor - Background Color
//--------
@@ -82,7 +83,7 @@ type
type }
TMenuBackgroundVideo = class (TMenuBackground)
private
- fFilename: string;
+ fFilename: IPath;
public
constructor Create(const ThemedSettings: TThemeBackground); override;
procedure OnShow; override;
@@ -115,15 +116,13 @@ begin
raise EMenuBackgroundError.Create('TMenuBackgroundVideo: No video filename present');
fFileName := Skin.GetTextureFileName(ThemedSettings.Tex);
- fFileName := AdaptFilePaths( fFileName );
-
- if fileexists(fFilename) AND VideoPlayback.Open( fFileName ) then
+ if fFilename.IsFile and VideoPlayback.Open(fFileName) then
begin
VideoBGTimer.SetTime(0);
VideoPlayback.Play;
end
else
- raise EMenuBackgroundError.Create('TMenuBackgroundVideo: Can''t load background video: ' + fFilename);
+ raise EMenuBackgroundError.Create('TMenuBackgroundVideo: Can''t load background video: ' + fFilename.ToNative);
end;
destructor TMenuBackgroundVideo.Destroy;
diff --git a/unicode/src/screens/UScreenCredits.pas b/unicode/src/screens/UScreenCredits.pas
index af1eea53..4e1dc5f1 100644
--- a/unicode/src/screens/UScreenCredits.pas
+++ b/unicode/src/screens/UScreenCredits.pas
@@ -35,15 +35,16 @@ interface
uses
SysUtils,
- UMenu,
SDL,
SDL_Image,
+ gl,
+ UMenu,
UDisplay,
UTexture,
- gl,
UMusic,
UFiles,
UThemes,
+ UPath,
UGraphicClasses;
type
@@ -204,38 +205,38 @@ end;
constructor TScreenCredits.Create;
var
- CreditsPath: string;
+ CreditsPath: IPath;
begin
inherited Create;
- CreditsPath := ResourcesPath + 'credits/';
-
- credits_bg_tex := Texture.LoadTexture(CreditsPath + CRDTS_BG_FILE, TEXTURE_TYPE_PLAIN, 0);
- credits_bg_ovl := Texture.LoadTexture(CreditsPath + CRDTS_OVL_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
-
- credits_blindguard := Texture.LoadTexture(CreditsPath + CRDTS_blindguard_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_blindy := Texture.LoadTexture(CreditsPath + CRDTS_blindy_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_canni := Texture.LoadTexture(CreditsPath + CRDTS_canni_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_commandio := Texture.LoadTexture(CreditsPath + CRDTS_commandio_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_lazyjoker := Texture.LoadTexture(CreditsPath + CRDTS_lazyjoker_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_mog := Texture.LoadTexture(CreditsPath + CRDTS_mog_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_mota := Texture.LoadTexture(CreditsPath + CRDTS_mota_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_skillmaster := Texture.LoadTexture(CreditsPath + CRDTS_skillmaster_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- credits_whiteshark := Texture.LoadTexture(CreditsPath + CRDTS_whiteshark_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
-
- intro_layer01 := Texture.LoadTexture(CreditsPath + INTRO_L01_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer02 := Texture.LoadTexture(CreditsPath + INTRO_L02_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer03 := Texture.LoadTexture(CreditsPath + INTRO_L03_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer04 := Texture.LoadTexture(CreditsPath + INTRO_L04_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer05 := Texture.LoadTexture(CreditsPath + INTRO_L05_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer06 := Texture.LoadTexture(CreditsPath + INTRO_L06_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer07 := Texture.LoadTexture(CreditsPath + INTRO_L07_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer08 := Texture.LoadTexture(CreditsPath + INTRO_L08_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- intro_layer09 := Texture.LoadTexture(CreditsPath + INTRO_L09_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
-
- outro_bg := Texture.LoadTexture(CreditsPath + OUTRO_BG_FILE, TEXTURE_TYPE_PLAIN, 0);
- outro_esc := Texture.LoadTexture(CreditsPath + OUTRO_ESC_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
- outro_exd := Texture.LoadTexture(CreditsPath + OUTRO_EXD_FILE, TEXTURE_TYPE_TRANSPARENT, 0);
+ CreditsPath := ResourcesPath.Append('credits', pdAppend);
+
+ credits_bg_tex := Texture.LoadTexture(CreditsPath.Append(CRDTS_BG_FILE), TEXTURE_TYPE_PLAIN, 0);
+ credits_bg_ovl := Texture.LoadTexture(CreditsPath.Append(CRDTS_OVL_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+ credits_blindguard := Texture.LoadTexture(CreditsPath.Append(CRDTS_blindguard_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_blindy := Texture.LoadTexture(CreditsPath.Append(CRDTS_blindy_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_canni := Texture.LoadTexture(CreditsPath.Append(CRDTS_canni_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_commandio := Texture.LoadTexture(CreditsPath.Append(CRDTS_commandio_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_lazyjoker := Texture.LoadTexture(CreditsPath.Append(CRDTS_lazyjoker_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_mog := Texture.LoadTexture(CreditsPath.Append(CRDTS_mog_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_mota := Texture.LoadTexture(CreditsPath.Append(CRDTS_mota_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_skillmaster := Texture.LoadTexture(CreditsPath.Append(CRDTS_skillmaster_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ credits_whiteshark := Texture.LoadTexture(CreditsPath.Append(CRDTS_whiteshark_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+ intro_layer01 := Texture.LoadTexture(CreditsPath.Append(INTRO_L01_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer02 := Texture.LoadTexture(CreditsPath.Append(INTRO_L02_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer03 := Texture.LoadTexture(CreditsPath.Append(INTRO_L03_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer04 := Texture.LoadTexture(CreditsPath.Append(INTRO_L04_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer05 := Texture.LoadTexture(CreditsPath.Append(INTRO_L05_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer06 := Texture.LoadTexture(CreditsPath.Append(INTRO_L06_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer07 := Texture.LoadTexture(CreditsPath.Append(INTRO_L07_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer08 := Texture.LoadTexture(CreditsPath.Append(INTRO_L08_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ intro_layer09 := Texture.LoadTexture(CreditsPath.Append(INTRO_L09_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+
+ outro_bg := Texture.LoadTexture(CreditsPath.Append(OUTRO_BG_FILE), TEXTURE_TYPE_PLAIN, 0);
+ outro_esc := Texture.LoadTexture(CreditsPath.Append(OUTRO_ESC_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
+ outro_exd := Texture.LoadTexture(CreditsPath.Append(OUTRO_EXD_FILE), TEXTURE_TYPE_TRANSPARENT, 0);
CRDTS_Stage:=InitialDelay;
end;
@@ -255,7 +256,7 @@ begin
deluxe_slidein := 0;
Credits_Alpha := 0;
// Music.SetLoop(true); loop loops not, shit
- AudioPlayback.Open(soundpath + 'wome-credits-tune.mp3'); // thank you wetue
+ AudioPlayback.Open(soundpath.Append('wome-credits-tune.mp3')); // thank you wetue
// Music.Play;
CTime := 0;
// setlength(CTime_hold,0);
@@ -1386,7 +1387,7 @@ begin
begin
CTime_hold := 0;
AudioPlayback.Stop;
- AudioPlayback.Open(soundpath + 'credits-outro-tune.mp3');
+ AudioPlayback.Open(SoundPath.Append('credits-outro-tune.mp3'));
AudioPlayback.SetVolume(0.2);
AudioPlayback.SetLoop(true);
AudioPlayback.Play;
diff --git a/unicode/src/screens/UScreenEditConvert.pas b/unicode/src/screens/UScreenEditConvert.pas
index 5dfa3b43..28182097 100644
--- a/unicode/src/screens/UScreenEditConvert.pas
+++ b/unicode/src/screens/UScreenEditConvert.pas
@@ -55,7 +55,8 @@ uses
USongs,
USong,
UMusic,
- UThemes;
+ UThemes,
+ UPath;
type
TMidiNote = record
@@ -128,7 +129,7 @@ type
end;
var
- ConversionFileName: string;
+ ConversionFileName: IPath;
implementation
@@ -220,7 +221,7 @@ begin
if CountSelectedTracks > 0 then
begin
Extract;
- SResult := SaveSong(Song, Lines, ChangeFileExt(ConversionFileName, '.txt'),
+ SResult := SaveSong(Song, Lines, ConversionFileName.SetExtension('.txt'),
false);
if (SResult <> ssrOK) then
begin
@@ -499,7 +500,7 @@ begin
AddButton(500, 20, 100, 40, Skin.GetTextureFileName('ButtonF'));
AddButtonText(20, 5, 0, 0, 0, 'Save');
- ConversionFileName := 'D:/daten/africa.mid';//GamePath + 'file.mid';
+ ConversionFileName := GamePath.Append('file.mid');
for P := 0 to 100 do
begin
@@ -525,7 +526,7 @@ begin
MidiOut.Open;
MidiFile := nil;
- if FileExists(ConversionFileName) then
+ if ConversionFileName.Exists then
begin
MidiFile := TMidiFile.Create(nil);
MidiFile.Filename := ConversionFileName;
diff --git a/unicode/src/screens/UScreenEditHeader.pas b/unicode/src/screens/UScreenEditHeader.pas
index d57f69f7..0ca98ca6 100644
--- a/unicode/src/screens/UScreenEditHeader.pas
+++ b/unicode/src/screens/UScreenEditHeader.pas
@@ -38,6 +38,7 @@ uses
SDL,
USongs,
USong,
+ UPath,
UThemes;
type
@@ -224,18 +225,18 @@ begin
TextGAP := AddText(340, 110 + 13*30, 0, 30, 0, 0, 0, '');
TextBPM := AddText(340, 110 + 14*30, 0, 30, 0, 0, 0, '');
- StaticTitle := AddStatic(130, 115 + 0*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticArtist := AddStatic(130, 115 + 1*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticMp3 := AddStatic(130, 115 + 2*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticBackground := AddStatic(130, 115 + 4*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticVideo := AddStatic(130, 115 + 5*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticVideoGAP := AddStatic(130, 115 + 6*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticRelative := AddStatic(130, 115 + 8*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticResolution := AddStatic(130, 115 + 9*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticNotesGAP := AddStatic(130, 115 + 10*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticStart := AddStatic(130, 115 + 12*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticGAP := AddStatic(130, 115 + 13*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
- StaticBPM := AddStatic(130, 115 + 14*30, 20, 20, 1, 1, 1, 'RoundButton', TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticTitle := AddStatic(130, 115 + 0*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticArtist := AddStatic(130, 115 + 1*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticMp3 := AddStatic(130, 115 + 2*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticBackground := AddStatic(130, 115 + 4*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticVideo := AddStatic(130, 115 + 5*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticVideoGAP := AddStatic(130, 115 + 6*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticRelative := AddStatic(130, 115 + 8*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticResolution := AddStatic(130, 115 + 9*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticNotesGAP := AddStatic(130, 115 + 10*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticStart := AddStatic(130, 115 + 12*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticGAP := AddStatic(130, 115 + 13*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
+ StaticBPM := AddStatic(130, 115 + 14*30, 20, 20, 1, 1, 1, Path('RoundButton'), TEXTURE_TYPE_TRANSPARENT, $FF00FF);
AddInteraction(iText, TextTitle);
AddInteraction(iText, TextArtist);
diff --git a/unicode/src/screens/UScreenEditSub.pas b/unicode/src/screens/UScreenEditSub.pas
index 6bf9ea51..1d0649b4 100644
--- a/unicode/src/screens/UScreenEditSub.pas
+++ b/unicode/src/screens/UScreenEditSub.pas
@@ -132,7 +132,8 @@ uses
USkins,
ULanguage,
UTextEncoding,
- UUnicodeUtils;
+ UUnicodeUtils,
+ UPath;
procedure OnSaveEncodingError(Value: boolean; Data: Pointer);
@@ -142,7 +143,7 @@ begin
if (Value) then
begin
CurrentSong.Encoding := encUTF8;
- SResult := SaveSong(CurrentSong, Lines[0], CurrentSong.Path + CurrentSong.FileName,
+ SResult := SaveSong(CurrentSong, Lines[0], CurrentSong.Path.Append(CurrentSong.FileName),
boolean(Data));
end;
end;
@@ -179,7 +180,7 @@ begin
Ord('S'):
begin
// Save Song
- SResult := SaveSong(CurrentSong, Lines[0], CurrentSong.Path + CurrentSong.FileName,
+ SResult := SaveSong(CurrentSong, Lines[0], CurrentSong.Path.Append(CurrentSong.FileName),
(SDL_ModState = KMOD_LSHIFT));
if (SResult = ssrEncodingError) then
begin
@@ -1258,6 +1259,8 @@ begin
end;
procedure TScreenEditSub.onShow;
+var
+ FileExt: IPath;
begin
inherited;
@@ -1267,11 +1270,12 @@ begin
ResetSingTemp;
try
- //Check if File is XML
- if copy(CurrentSong.FileName,length(CurrentSong.FileName)-3,4) = '.xml' then
- Error := not CurrentSong.LoadXMLSong()
- else
- Error := not CurrentSong.LoadSong();
+ //Check if File is XML
+ FileExt := CurrentSong.FileName.GetExtension;
+ if FileExt.ToUTF8 = '.xml' then
+ Error := not CurrentSong.LoadXMLSong()
+ else
+ Error := not CurrentSong.LoadSong();
except
Error := true;
end;
@@ -1293,12 +1297,12 @@ begin
{$ENDIF}
Text[TextTitle].Text := CurrentSong.Title;
Text[TextArtist].Text := CurrentSong.Artist;
- Text[TextMp3].Text := CurrentSong.Mp3;
+ Text[TextMp3].Text := CurrentSong.Mp3.ToUTF8;
Lines[0].Current := 0;
CurrentNote := 0;
Lines[0].Line[0].Note[0].Color := 1;
- AudioPlayback.Open(CurrentSong.Path + CurrentSong.Mp3);
+ AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3));
//Set Down Music Volume for Better hearability of Midi Sounds
//Music.SetVolume(0.4);
diff --git a/unicode/src/screens/UScreenOpen.pas b/unicode/src/screens/UScreenOpen.pas
index a25356ec..08024a22 100644
--- a/unicode/src/screens/UScreenOpen.pas
+++ b/unicode/src/screens/UScreenOpen.pas
@@ -34,10 +34,13 @@ interface
{$I switches.inc}
uses
+ Math,
+ SysUtils,
+ gl,
+ SDL,
+ UPath,
UMenu,
UMusic,
- SDL,
- SysUtils,
UFiles,
UTime,
USongs,
@@ -46,8 +49,6 @@ uses
UTexture,
UMenuText,
ULyrics,
- Math,
- gl,
UThemes;
type
@@ -55,10 +56,10 @@ type
private
TextF: array[0..1] of integer;
TextN: integer;
+ fPath: IPath;
public
Tex_Background: TTexture;
FadeOut: boolean;
- Path: string;
BackScreen: pointer;
procedure AddBox(X, Y, W, H: real);
constructor Create; override;
@@ -107,7 +108,7 @@ begin
SDLK_ESCAPE:
begin
//Empty Filename and go to last Screen
- ConversionFileName := '';
+ ConversionFileName := PATH_NONE;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(BackScreen);
end;
@@ -117,14 +118,14 @@ begin
if (Interaction = 2) then
begin
//Update Filename and go to last Screen
- ConversionFileName := Text[TextN].Text;
+ ConversionFileName := Path(Text[TextN].Text);
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(BackScreen);
end
else if (Interaction = 1) then
begin
//Empty Filename and go to last Screen
- ConversionFileName := '';
+ ConversionFileName := PATH_NONE;
AudioPlayback.PlaySound(SoundLib.Back);
FadeTo(BackScreen);
end;
@@ -176,7 +177,7 @@ begin
// file name
AddBox(20, 540, 500, 40);
- TextN := AddText(50, 548, 0, 24, 0, 0, 0, ConversionFileName);
+ TextN := AddText(50, 548, 0, 24, 0, 0, 0, ConversionFileName.ToUTF8);
AddInteraction(iText, TextN);
// buttons
diff --git a/unicode/src/screens/UScreenOptionsRecord.pas b/unicode/src/screens/UScreenOptionsRecord.pas
index cdacd5f6..d1b62e2b 100644
--- a/unicode/src/screens/UScreenOptionsRecord.pas
+++ b/unicode/src/screens/UScreenOptionsRecord.pas
@@ -61,8 +61,8 @@ type
PreviewDeviceIndex: integer;
// string arrays for select-slide options
- InputSourceNames: array of string;
- InputDeviceNames: array of string;
+ InputSourceNames: array of UTF8String;
+ InputDeviceNames: array of UTF8String;
// dynamic generated themes for channel select-sliders
SelectSlideChannelTheme: array of TThemeSelectSlide;
diff --git a/unicode/src/screens/UScreenOptionsThemes.pas b/unicode/src/screens/UScreenOptionsThemes.pas
index 163d8af9..e40ba664 100644
--- a/unicode/src/screens/UScreenOptionsThemes.pas
+++ b/unicode/src/screens/UScreenOptionsThemes.pas
@@ -136,7 +136,7 @@ begin
if (SelInteraction = 0) then
begin
Skin.OnThemeChange;
- UpdateSelectSlideOptions (Theme.OptionsThemes.SelectSkin, SkinSelect, ISkin, Ini.SkinNo);
+ UpdateSelectSlideOptions(Theme.OptionsThemes.SelectSkin, SkinSelect, ISkin, Ini.SkinNo);
end;
ReloadTheme();
@@ -188,7 +188,7 @@ end;
procedure TScreenOptionsThemes.ReloadTheme;
begin
- Theme.LoadTheme(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
+ Theme.LoadTheme(ThemePath.Append(ITheme[Ini.Theme] + '.ini'), Ini.Color);
ScreenOptionsThemes := TScreenOptionsThemes.create();
ScreenOptionsThemes.onshow;
diff --git a/unicode/src/screens/UScreenPartyOptions.pas b/unicode/src/screens/UScreenPartyOptions.pas
index b7226a5e..007956d6 100644
--- a/unicode/src/screens/UScreenPartyOptions.pas
+++ b/unicode/src/screens/UScreenPartyOptions.pas
@@ -68,13 +68,13 @@ type
end;
var
- IPlaylist: array[0..2] of string;
- IPlaylist2: array of string;
+ IPlaylist: array[0..2] of UTF8String;
+ IPlaylist2: array of UTF8String;
const
- ITeams: array[0..1] of string = ('2', '3');
- IPlayers: array[0..3] of string = ('1', '2', '3', '4');
- IRounds: array[0..5] of string = ('2', '3', '4', '5', '6', '7');
+ ITeams: array[0..1] of UTF8String = ('2', '3');
+ IPlayers: array[0..3] of UTF8String = ('1', '2', '3', '4');
+ IRounds: array[0..5] of UTF8String = ('2', '3', '4', '5', '6', '7');
implementation
@@ -240,14 +240,14 @@ begin
//Load Screen From Theme
LoadFromTheme(Theme.PartyOptions);
- SelectLevel := AddSelectSlide (Theme.PartyOptions.SelectLevel, Ini.Difficulty, Theme.ILevel);
- SelectPlayList := AddSelectSlide (Theme.PartyOptions.SelectPlayList, PlayList, IPlaylist);
- SelectPlayList2 := AddSelectSlide (Theme.PartyOptions.SelectPlayList2, PlayList2, IPlaylist2);
- SelectRounds := AddSelectSlide (Theme.PartyOptions.SelectRounds, Rounds, IRounds);
- SelectTeams := AddSelectSlide (Theme.PartyOptions.SelectTeams, NumTeams, ITeams);
- SelectPlayers1 := AddSelectSlide (Theme.PartyOptions.SelectPlayers1, NumPlayer1, IPlayers);
- SelectPlayers2 := AddSelectSlide (Theme.PartyOptions.SelectPlayers2, NumPlayer2, IPlayers);
- SelectPlayers3 := AddSelectSlide (Theme.PartyOptions.SelectPlayers3, NumPlayer3, IPlayers);
+ SelectLevel := AddSelectSlide(Theme.PartyOptions.SelectLevel, Ini.Difficulty, Theme.ILevel);
+ SelectPlayList := AddSelectSlide(Theme.PartyOptions.SelectPlayList, PlayList, IPlaylist);
+ SelectPlayList2 := AddSelectSlide(Theme.PartyOptions.SelectPlayList2, PlayList2, IPlaylist2);
+ SelectRounds := AddSelectSlide(Theme.PartyOptions.SelectRounds, Rounds, IRounds);
+ SelectTeams := AddSelectSlide(Theme.PartyOptions.SelectTeams, NumTeams, ITeams);
+ SelectPlayers1 := AddSelectSlide(Theme.PartyOptions.SelectPlayers1, NumPlayer1, IPlayers);
+ SelectPlayers2 := AddSelectSlide(Theme.PartyOptions.SelectPlayers2, NumPlayer2, IPlayers);
+ SelectPlayers3 := AddSelectSlide(Theme.PartyOptions.SelectPlayers3, NumPlayer3, IPlayers);
Interaction := 0;
diff --git a/unicode/src/screens/UScreenPartyScore.pas b/unicode/src/screens/UScreenPartyScore.pas
index 6b6d98e6..9e090715 100644
--- a/unicode/src/screens/UScreenPartyScore.pas
+++ b/unicode/src/screens/UScreenPartyScore.pas
@@ -166,7 +166,9 @@ begin
DecoColor[0].B := B;
//Load Texture
- Tex := Texture.LoadTexture(pchar(Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.FirstTexture)), Theme.PartyScore.DecoTextures.FirstTyp, Color);
+ Tex := Texture.LoadTexture(
+ Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.FirstTexture),
+ Theme.PartyScore.DecoTextures.FirstTyp, Color);
DecoTex[0] := Tex.TexNum;
//Get Second Color
@@ -177,7 +179,9 @@ begin
DecoColor[1].B := B;
//Load Second Texture
- Tex := Texture.LoadTexture(pchar(Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.SecondTexture)), Theme.PartyScore.DecoTextures.SecondTyp, Color);
+ Tex := Texture.LoadTexture(
+ Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.SecondTexture),
+ Theme.PartyScore.DecoTextures.SecondTyp, Color);
DecoTex[1] := Tex.TexNum;
//Get Third Color
@@ -188,7 +192,9 @@ begin
DecoColor[2].B := B;
//Load Third Texture
- Tex := Texture.LoadTexture(pchar(Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.ThirdTexture)), Theme.PartyScore.DecoTextures.ThirdTyp, Color);
+ Tex := Texture.LoadTexture(
+ Skin.GetTextureFileName(Theme.PartyScore.DecoTextures.ThirdTexture),
+ Theme.PartyScore.DecoTextures.ThirdTyp, Color);
DecoTex[2] := Tex.TexNum;
end;
diff --git a/unicode/src/screens/UScreenPopup.pas b/unicode/src/screens/UScreenPopup.pas
index 906335e7..2f6d981d 100644
--- a/unicode/src/screens/UScreenPopup.pas
+++ b/unicode/src/screens/UScreenPopup.pas
@@ -55,7 +55,7 @@ type
constructor Create; override;
function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
procedure OnShow; override;
- procedure ShowPopup(Msg: string; Handler: TPopupCheckHandler;
+ procedure ShowPopup(const Msg: UTF8String; Handler: TPopupCheckHandler;
HandlerData: Pointer; DefaultValue: boolean = false);
function Draw: boolean; override;
end;
@@ -73,7 +73,7 @@ type
function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
procedure OnShow; override;
procedure OnHide; override;
- procedure ShowPopup(msg: string);
+ procedure ShowPopup(const Msg: UTF8String);
function Draw: boolean; override;
end;
@@ -165,7 +165,7 @@ begin
inherited;
end;
-procedure TScreenPopupCheck.ShowPopup(Msg: string; Handler: TPopupCheckHandler;
+procedure TScreenPopupCheck.ShowPopup(const Msg: UTF8String; Handler: TPopupCheckHandler;
HandlerData: Pointer; DefaultValue: boolean);
begin
if (DefaultValue) then
@@ -253,7 +253,7 @@ procedure TScreenPopupError.onHide;
begin
end;
-procedure TScreenPopupError.ShowPopup(msg: string);
+procedure TScreenPopupError.ShowPopup(const Msg: UTF8String);
begin
Interaction := 0; //Reset Interaction
Visible := true; //Set Visible
diff --git a/unicode/src/screens/UScreenSing.pas b/unicode/src/screens/UScreenSing.pas
index dc3d5f5f..b8d0d9b7 100644
--- a/unicode/src/screens/UScreenSing.pas
+++ b/unicode/src/screens/UScreenSing.pas
@@ -49,6 +49,7 @@ uses
USongs,
UTexture,
UThemes,
+ UPath,
UTime;
type
@@ -217,6 +218,8 @@ end;
// pause mod
procedure TScreenSing.Pause;
+var
+ VideoFile: IPath;
begin
if (not Paused) then // enable pause
begin
@@ -229,8 +232,8 @@ begin
AudioPlayback.Pause;
// pause video
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path +
- CurrentSong.Video) then
+ VideoFile := CurrentSong.Path.Append(CurrentSong.Video);
+ if (CurrentSong.Video.IsSet) and VideoFile.Exists then
fCurrentVideoPlaybackEngine.Pause;
end
@@ -242,8 +245,8 @@ begin
AudioPlayback.Play;
// video
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path +
- CurrentSong.Video) then
+ VideoFile := CurrentSong.Path.Append(CurrentSong.Video);
+ if (CurrentSong.Video.IsSet) and VideoFile.Exists then
fCurrentVideoPlaybackEngine.Pause;
Paused := false;
@@ -318,7 +321,7 @@ var
V2M: boolean;
V3R: boolean;
Color: TRGB;
-
+ VideoFile, BgFile: IPath;
success: boolean;
begin
inherited;
@@ -424,7 +427,7 @@ begin
// FIXME: bad style, put the try-except into loadsong() and not here
try
// check if file is xml
- if copy(CurrentSong.FileName, length(CurrentSong.FileName) - 3, 4) = '.xml' then
+ if CurrentSong.FileName.GetExtension.ToUTF8 = '.xml' then
success := CurrentSong.LoadXMLSong()
else
success := CurrentSong.LoadSong();
@@ -468,9 +471,10 @@ begin
*}
VideoLoaded := false;
fShowVisualization := false;
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then
+ VideoFile := CurrentSong.Path.Append(CurrentSong.Video);
+ if (CurrentSong.Video.IsSet) and VideoFile.IsFile then
begin
- if (fCurrentVideoPlaybackEngine.Open(CurrentSong.Path + CurrentSong.Video)) then
+ if (fCurrentVideoPlaybackEngine.Open(VideoFile)) then
begin
fShowVisualization := false;
fCurrentVideoPlaybackEngine := VideoPlayback;
@@ -483,15 +487,17 @@ begin
{*
* set background to: picture
*}
- if (CurrentSong.Background <> '') and (VideoLoaded = false)
+ if (CurrentSong.Background.IsSet) and (VideoLoaded = false)
and (TVisualizerOption(Ini.VisualizerOption) = voOff) then
+ begin
+ BgFile := CurrentSong.Path.Append(CurrentSong.Background);
try
- Tex_Background := Texture.LoadTexture(CurrentSong.Path + CurrentSong.Background);
+ Tex_Background := Texture.LoadTexture(BgFile);
except
- Log.LogError('Background could not be loaded: ' + CurrentSong.Path +
- CurrentSong.Background);
+ Log.LogError('Background could not be loaded: ' + BgFile.ToNative);
Tex_Background.TexNum := 0;
end
+ end
else
begin
Tex_Background.TexNum := 0;
diff --git a/unicode/src/screens/UScreenSingModi.pas b/unicode/src/screens/UScreenSingModi.pas
index d361943e..ad116a62 100644
--- a/unicode/src/screens/UScreenSingModi.pas
+++ b/unicode/src/screens/UScreenSingModi.pas
@@ -47,7 +47,7 @@ uses
ULyrics,
TextGL,
gl,
-
+ UPath,
UThemes,
UScreenSing,
ModiSDK;
@@ -71,7 +71,7 @@ type
type
TCustomSoundEntry = record
- Filename : string;
+ Filename : IPath;
Stream : TAudioPlaybackStream;
end;
@@ -503,19 +503,20 @@ end;
function LoadTex(const Name: PChar; Typ: TTextureType): TsmallTexture;
var
- Texname, EXT: string;
+ TexName: IPath;
+ Ext: UTF8String;
Tex: TTexture;
begin
//Get texture Name
TexName := Skin.GetTextureFileName(string(Name));
//Get File Typ
- Ext := ExtractFileExt(TexName);
- if (uppercase(Ext) = '.JPG') then
+ Ext := TexName.GetExtension().ToUTF8;
+ if (UpperCase(Ext) = '.JPG') then
Ext := 'JPG'
else
Ext := 'BMP';
- Tex := Texture.LoadTexture(false, PChar(TexName), UTEXTURE.TTextureType(Typ), 0);
+ Tex := Texture.LoadTexture(false, TexName, UTexture.TTextureType(Typ), 0);
Result.TexNum := Tex.TexNum;
Result.W := Tex.W;
@@ -544,20 +545,21 @@ function LoadSound(const Name: PChar): cardinal;
var
Stream: TAudioPlaybackStream;
i: integer;
- Filename: string;
+ Filename: IPath;
+ SoundFile: IPath;
begin
//Search for Sound in already loaded Sounds
- Filename := UpperCase(SoundPath + Name);
+ SoundFile := SoundPath.Append(Name);
for i := 0 to High(CustomSounds) do
begin
- if (UpperCase(CustomSounds[i].Filename) = Filename) then
+ if (SoundFile.Equals(CustomSounds[i].Filename, true)) then
begin
Result := i;
Exit;
end;
end;
- Stream := AudioPlayback.OpenSound(SoundPath + string(Name));
+ Stream := AudioPlayback.OpenSound(SoundFile);
if (Stream = nil) then
begin
Result := 0;
diff --git a/unicode/src/screens/UScreenSong.pas b/unicode/src/screens/UScreenSong.pas
index 00d90930..60938887 100644
--- a/unicode/src/screens/UScreenSong.pas
+++ b/unicode/src/screens/UScreenSong.pas
@@ -38,6 +38,7 @@ uses
SDL,
UCommon,
UDisplay,
+ UPath,
UFiles,
UIni,
ULanguage,
@@ -842,9 +843,9 @@ var
I: integer;
CoverButtonIndex: integer;
CoverButton: TButton;
- CoverName: string;
CoverTexture: TTexture;
Cover: TCover;
+ CoverFile: IPath;
Song: TSong;
begin
if (Length(CatSongs.Song) <= 0) then
@@ -859,7 +860,7 @@ begin
CoverButton := nil;
// create a clickable cover
- CoverButtonIndex := AddButton(300 + I*250, 140, 200, 200, '', TEXTURE_TYPE_PLAIN, Theme.Song.Cover.Reflections);
+ CoverButtonIndex := AddButton(300 + I*250, 140, 200, 200, PATH_NONE, TEXTURE_TYPE_PLAIN, Theme.Song.Cover.Reflections);
if (CoverButtonIndex > -1) then
CoverButton := Button[CoverButtonIndex];
if (CoverButton = nil) then
@@ -868,18 +869,16 @@ begin
Song := CatSongs.Song[I];
// if cover-image is not found then show 'no cover'
- if (not FileExists(Song.Path + Song.Cover)) then
- Song.Cover := '';
-
- if (Song.Cover = '') then
- CoverName := Skin.GetTextureFileName('SongCover')
- else
- CoverName := Song.Path + Song.Cover;
+ CoverFile := Song.Path.Append(Song.Cover);
+ if (not CoverFile.IsFile()) then
+ Song.Cover := PATH_NONE;
+ if (Song.Cover.IsUnset) then
+ CoverFile := Skin.GetTextureFileName('SongCover');
// load cover and cache its texture
- Cover := Covers.FindCover(CoverName);
+ Cover := Covers.FindCover(CoverFile);
if (Cover = nil) then
- Cover := Covers.AddCover(CoverName);
+ Cover := Covers.AddCover(CoverFile);
// use the cached texture
// TODO: this is a workaround until the new song-loading works.
@@ -919,7 +918,7 @@ begin
end;
// Set visibility of video icon
- Static[VideoIcon].Visible := (CatSongs.Song[Interaction].Video <> '');
+ Static[VideoIcon].Visible := CatSongs.Song[Interaction].Video.IsSet;
// Set texts
Text[TextArtist].Text := CatSongs.Song[Interaction].Artist;
@@ -1472,7 +1471,7 @@ begin
// if preview is deactivated: load musicfile now
if (IPreviewVolumeVals[Ini.PreviewVolume] = 0) then
- AudioPlayback.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3);
+ AudioPlayback.Open(CatSongs.Song[Interaction].Path.Append(CatSongs.Song[Interaction].Mp3));
// if hide then stop music (for party mode popup on exit)
if (Display.NextScreen <> @ScreenSing) and
@@ -1651,7 +1650,7 @@ begin
if not assigned(Song) then
Exit;
- if AudioPlayback.Open(Song.Path + Song.Mp3) then
+ if AudioPlayback.Open(Song.Path.Append(Song.Mp3)) then
begin
AudioPlayback.Position := AudioPlayback.Length / 4;
// set preview volume
diff --git a/unicode/src/screens/UScreenSongMenu.pas b/unicode/src/screens/UScreenSongMenu.pas
index e09dd9b5..788611a1 100644
--- a/unicode/src/screens/UScreenSongMenu.pas
+++ b/unicode/src/screens/UScreenSongMenu.pas
@@ -73,7 +73,7 @@ const
SM_Party_Joker = 128 or 2;
var
- ISelections: array of string;
+ ISelections: array of UTF8String;
SelectValue: integer;
implementation
diff --git a/unicode/src/screens/UScreenStatMain.pas b/unicode/src/screens/UScreenStatMain.pas
index 6d4d3f5b..17810cd6 100644
--- a/unicode/src/screens/UScreenStatMain.pas
+++ b/unicode/src/screens/UScreenStatMain.pas
@@ -166,7 +166,7 @@ begin
//Set Songs with Vid
SongsWithVid := 0;
for I := 0 to Songs.SongList.Count -1 do
- if (TSong(Songs.SongList[I]).Video <> '') then
+ if (TSong(Songs.SongList[I]).Video.IsSet) then
Inc(SongsWithVid);
end;
diff --git a/unicode/src/ultrastardx.dpr b/unicode/src/ultrastardx.dpr
index ea701a37..0ac212a1 100644
--- a/unicode/src/ultrastardx.dpr
+++ b/unicode/src/ultrastardx.dpr
@@ -210,8 +210,8 @@ uses
UFont in 'base\UFont.pas',
UTextEncoding in 'base\UTextEncoding.pas',
- //UFilename in 'base\UFilename.pas',
- //UFilesystem in 'base\UFilesystem.pas',
+ UPath in 'base\UPath.pas',
+ UFilesystem in 'base\UFilesystem.pas',
//------------------------------
//Includes - Plugin Support