aboutsummaryrefslogtreecommitdiffstats
path: root/cmake/src/base/UPlatform.pas
blob: 6f13481c65d53d29764d451928172dbe406baf20 (plain) (blame)
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.