aboutsummaryrefslogtreecommitdiffstats
path: root/src/classes/UPlatform.pas
blob: 1dcdb5b9e103721dde18e66c420554044ce67116 (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
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,
  {$IFDEF MSWINDOWS}
  UPlatformWindows,
  {$ENDIF}
  {$IFDEF LINUX}
  UPlatformLinux,
  {$ENDIF}
  {$IFDEF DARWIN}
  UPlatformMacOSX,
  {$ENDIF}
  ULog;


// I have modified it to use the Platform_singleton in this location ( in the implementaiton )
// 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 := 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
{$IFDEF MSWINDOWS}
  Platform_singleton := TPlatformWindows.Create;
{$ENDIF}
{$IFDEF LINUX}
  Platform_singleton := TPlatformLinux.Create;
{$ENDIF}
{$IFDEF DARWIN}
  Platform_singleton := TPlatformMacOSX.Create;
{$ENDIF}

finalization
  Platform_singleton.Free;

end.