1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
{* 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 UPlatform;
// Comment by Eddie:
// This unit defines an interface for platform specific utility functions.
// The Interface is implemented in separate files for each platform:
// UPlatformWindows, UPlatformLinux and UPlatformMacOSX.
interface
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
{$I switches.inc}
uses
Classes;
type
TDirectoryEntry = record
Name: WideString;
IsDirectory: boolean;
IsFile: boolean;
end;
TDirectoryEntryArray = array of TDirectoryEntry;
TPlatform = class
function GetExecutionDir(): string;
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;
end;
function Platform(): TPlatform;
implementation
uses
SysUtils,
{$IF Defined(MSWINDOWS)}
UPlatformWindows,
{$ELSEIF Defined(DARWIN)}
UPlatformMacOSX,
{$ELSEIF Defined(UNIX)}
UPlatformLinux,
{$IFEND}
ULog;
// I modified it to use the Platform_singleton in this location (in the implementation)
// so that this variable can NOT be overwritten from anywhere else in the application.
// the accessor function platform, emulates all previous calls to work the same way.
var
Platform_singleton: TPlatform;
function Platform: TPlatform;
begin
Result := Platform_singleton;
end;
(**
* Default Init() implementation
*)
procedure TPlatform.Init;
begin
end;
(**
* Default Halt() implementation
*)
procedure TPlatform.Halt;
begin
// Note: Application.terminate is NOT the same
System.Halt;
end;
{**
* Returns the directory of the executable
*}
function TPlatform.GetExecutionDir(): string;
begin
Result := ExpandFileName(ExtractFilePath(ParamStr(0)));
end;
(**
* Default TerminateIfAlreadyRunning() implementation
*)
function TPlatform.TerminateIfAlreadyRunning(var WndTitle: string): boolean;
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;
{$ELSEIF Defined(DARWIN)}
Platform_singleton := TPlatformMacOSX.Create;
{$ELSEIF Defined(UNIX)}
Platform_singleton := TPlatformLinux.Create;
{$IFEND}
finalization
Platform_singleton.Free;
end.
|