aboutsummaryrefslogtreecommitdiffstats
path: root/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas
blob: 4d053ad05ab2c63993fb50d0eca6f84d408ad965 (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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
{* 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/base/UMain.pas $
 * $Id: UMain.pas 1485 2008-10-28 20:16:05Z tobigun $
 *}
{*
  some defines that are used by usdx and plugins
*}
unit UPluginDefines;

interface

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

{$I switches.inc}

const
  US_VERSION_SHMAJOR = 20;
  US_VERSION_SHMINOR = 10;
  US_VERSION_SHFIX   = 0;

  SDK_Version = 1 shl US_VERSION_SHMAJOR; //< identifies the used SDK version (1.0.0.0)

type
  { this type is used for all version ints in this SDK
    the versions are structured as follows
    0 ... 11| 12 ... 21| 22 ... 31
      major |   minor  | bugfix, etc.
    e.g. 1  .     0    .     0        =  1 shl 20 }

  TUS_Version = LongInt;

  { this type is used for all plugin handles in this SDK }
  TUS_Handle = LongInt;

  PInterface = ^IInterface;

const
  US_HANDLE_CORE = 137;     //< handle of core, also first defined handle
  US_HANDLE_UNDEFINED = 0;  //< undefined handle, used to indicate errors
  US_VERSION_UNDEFINED = 0; //< defines an unset version, used by core,
                            //  should not be used by Plugins

  { this type is used for all id strings in this SDK }
const
  MaxLength_TUS_Identifier = 32;  //max length of identifier strings, has to be multiply of 4

type
  TUS_Identifier = String[MaxLength_TUS_Identifier];

  { this record is used to offer some information about this plugin to the core }
  TUS_PluginInfo = packed record
    Name       : Array [1..32] of Char;   //name of the plugin
    Author     : Array [1..32] of Char;   //plugins author
    PluginDesc : Array [1..64] of Char;   //some further explentation
    Version    : TUS_Version;
  end;
  PUS_PluginInfo = ^TUS_PluginInfo;

  { this function reads the plugins information from a TUS_PluginInfo record,
    and saves it. Can be called once per plugin.
    Version is the SDK_Version used by the plugin
    BufferLength is the size of buffer in bytes }
  TUS_Func_Identify     = function (Handle: TUS_Handle; Version: TUS_Version; Buffer: PUS_PluginInfo; BufferLength: LongInt): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { this plugin is used for selfshutdown by the plugin on an error
    case.
    Reason should be used to describe the reason for the shutdown
    OnChangeStatus(psDeInited) is called when old status was psInited }
  TUS_Func_Error = function (Handle: TUS_Handle; Reason: PWideChar): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { this function writes the plugins filename including its path ,
    to buffer. A call with Buffer=nil or Len<=0 returns the actual
    length of the path.
    BufferLength is the size of buffer in bytes
    Filename is used to identify duplicate load of one plugin
    so it should even set when plugin is not loaded from file}
  TUS_Func_GetFilename  = function (Handle: TUS_Handle; Buffer: PWideChar; BufferLength: LongInt): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { this function writes an interface, identified by 'ID', to the
    buffer.
    Version is the version of the interface that is used
    BufferLength is the size of buffer in bytes}
  TUS_Func_GetInterface = function (IID: TGUID; Buffer: PInterface): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { this function reads an interface, identified by 'ID', from the
    buffer, to offer it to calls of GetInterface.
    version is the version of the interface
    BufferLength is the size of buffer in bytes }
  TUS_Func_SetInterface = function (IID: TGUID; Buffer: PInterface): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { this function writes a record or some other data,
    identified by 'ID', to the buffer.
    Version is the version of the data that is used
    BufferLength is the size of buffer in bytes}
  TUS_Func_GetData = function (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { this function reads a record or some other data,
    identified by 'ID', from the buffer, to offer it
    to calls of GetData.
    version is the version of the record
    BufferLength is the size of buffer in bytes }
  TUS_Func_SetData = function (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; 
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}

  { a record w/ some useful methods for plugins }
  TUS_PluginInterface = packed record
    Version     : TUS_Version;     //SDK_Version
    Handle      : LongInt;         //the plugins handle

    Identify    : TUS_Func_Identify;
    Error       : TUS_Func_Error;
    GetFilename : TUS_Func_GetFilename;

    GetInterface: TUS_Func_GetInterface;
    SetInterface: TUS_Func_SetInterface;

    GetData     : TUS_Func_GetData;
    SetData     : TUS_Func_SetData;
  end;
  PUS_PluginInterface = ^TUS_PluginInterface;

  { this function writes the PluginInterface to the buffer }
  TUS_Func_InitInterface = function (Handle: TUS_Handle; Version: TUS_Version; Buffer: PUS_PluginInterface; BufferSize: LongInt): LongInt;
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}


  { this function is called by core, in the WaitingInit status
    it offers the plugin the possibility to load its plugininterface
    and to check it's sdk version against the cores.
    It has to be implemented by plugins loaded as library }
  TUS_Plugin_Proc_Init = procedure (Handle: TUS_Handle; CoreVersion: TUS_Version; InitInterface: TUS_Func_InitInterface);
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}


  TUS_PluginStatus = (psNone, psWaitingInit, psInited, psDeInited, psError);

  { this function is called everytime tbe plugins status changes
    status is the new status.
    it has to be implemented by plugins loaded as library }
  TUS_Plugin_OnChangeStatus = procedure (Handle: TUS_Handle; Status: TUS_PluginStatus);
  {$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}  


  { this interface represents a loaded plugin, it eitber has to
    be implemented by the pluginloader, e.g. for libs or by the
    plugin itself in the case of integrated plugins }
  IUS_Plugin = Interface
    ['{23F7B722-D979-4402-9953-C6B229A6E888}']
    function GetLoader: LongInt; //< Returns id of this plugins loader

    function GetStatus: TUS_PluginStatus; //< Returns current pluginstatus
    procedure SetStatus(status: TUS_PluginStatus); //< set current pluginstatus, calls OnChangeStatus,
                                                   //  status may not be updated in case of an error

    function GetInfo: TUS_PluginInfo;                 //< Returns TUS_Plugininfo record for this plugin
    function Identify(Info: TUS_PluginInfo): boolean; //< Sets TUS_Plugininfo record for this plugin, can only be called once

    function GetHandle: TUS_Handle;   //< Returns plugins handle
    function GetUniqueID: TUS_Handle; //< This ID is unique for the given plugin it may be a hash of the plugins code or s/t like that. used to identify plugins laoded twice
    function GetFilename: WideString; //< Returns plugins filename

    Procedure Init;
    Procedure DeInit;

    Procedure SetError(Reason: WideString);
    Function GetErrorReason: WideString;
  end;

  { this function will be called when a hookable event is spawn
    data is a pointer to a struct that can contain any data
    defined by the event creator. if there is no data this should
    be nil.
    breakable is true if the hook chain can be interupted by
    returning US_HOOK_BREAK or US_HOOK_UNHOOKME_BREAK
    by returning US_HOOK_UNHOOKME the callback will immediately
    be removed from the chain
    UserID is the value that the UserID had when hook was called.
    can be used to store user defined data, e.g. to use one hook procedure for different hooks }
  TUS_Func_OnEvent = function(data: pointer; breakable: boolean; UserID: LongInt): integer;
  TUS_cFunc_OnEvent = function(data: pointer; breakable: boolean; UserID: LongInt): integer of object;

  { this interface represents an event that can be hooked by
    e.g. the core or other}
  IUS_HookableEvent = Interface
    // this GID has to be changed if we change this interface
    ['{FFC6F09D-EC0B-41E2-87F6-70EC6F055C0E}']
    function GetIdentifier: TUS_Identifier;
    function GetHash: LongInt;

    //adds the callback to the top of the events hook chain
    //proc is the callback function
    //parent is the plugins handle, or US_HANDLE_CORE if called by core
    //returns hook-handle on succes or US_HANDLE_UNDEFINED on failure
    function Hook(proc: TUS_Func_OnEvent; Parent: TUS_Handle; UserID: LongInt): TUS_Handle;
    function cHook(proc: TUS_cFunc_OnEvent; Parent: TUS_Handle; UserID: LongInt): TUS_Handle;

    //removes a callback from the chain using the handle returned
    //by the hook function
    //returns an US_ERROR code
    function UnHook(Handle: TUS_Handle): byte;

    //removes all callbacks of a specified parent (plugin)
    procedure UnHookbyParent(Parent: TUS_Handle);
  end;


const
  { some errorcodes that are returned by functions using this SDK }
  US_ERROR_None = 0;            //< indicates success ;)
  US_ERROR_VersionMismatch = 1; //< returned when the version the plugin wants to use is not supported
  US_ERROR_SizeMismatch = 2;    //< returned when the wanted data does not fit the buffersize
  US_ERROR_WrongHandle = 3;     //< returned when the given handle is not
  US_ERROR_WrongID = 4;         //< returned when the given id does not exist
  US_ERROR_NameExists = 5;      //< returned when the given name already exists

  US_ERROR_Unknown = 255;       //< returned when an unknown error occured

  { return values for hook function }
  US_HOOK_BREAK = High(integer);              //this will break the hook chain
  US_HOOK_UNHOOKME = High(integer) - 2;       //this will remove the callback from the hooks chain
  US_HOOK_UNHOOKME_BREAK = High(integer) - 1; //this will do both explained above

  US_LOADER_UNDEFINED = 0;
  US_LOADER_LIBRARY   = 100;
  US_LOADER_INCLUDED  = 200;

{ this function converts an errorcode to its textual expression }
function USErrortoString(Code: LongInt): String;

{ this function converts a TUS_PluginStatus to its textual expression }
function USPluginStatustoString(Status: TUS_PluginStatus): String;

{ this funtion creates a hash for an TUS_Identifier
  the hash is not guaranteed to be unique, it is just
  for a fast search of an identifier }
function CalculateUSHash(Identifier: TUS_Identifier): LongInt;

implementation

{ this function converts an errorcode to its textual expression }
Function USErrortoString(Code: LongInt): String;
begin
  Case Code of
    US_Error_None:            Result := 'success, no error occured';
    US_Error_VersionMismatch: Result := 'version mismatch';
    US_Error_SizeMismatch:    Result := 'size mismatch';
    US_Error_WrongHandle:     Result := 'handle does not exist';
    US_Error_WrongID:         Result := 'id does not exist';
    US_Error_NameExists:      Result := 'another item with this name does already exist';

    Else Result := 'unknown error';
  end;
end;

function USPluginStatustoString(Status: TUS_PluginStatus): String;
begin
  Case Status of
    psNone:         Result := 'none';
    psWaitingInit:  Result := 'waiting init';
    psInited:       Result := 'inited';
    psDeinited:     Result := 'deinited';
    psError:        Result := 'error';

    Else Result := 'unknown';
  end;
end;

{ this funtion creates a hash for an TUS_Identifier
  the hash is not guaranteed to be unique, it is just
  for a fast search of an identifier }
function CalculateUSHash(Identifier: TUS_Identifier): LongInt;
  var
    L: Integer;
    I: Integer;

  const
    StartHash = -1337456101;
begin
  // fill the unused chars of the identifier w/ zeros
  L := Length(Identifier);
  if (L < MaxLength_TUS_Identifier) then
  FillChar(Identifier[L+1], MaxLength_TUS_Identifier - L, 0);

  // calculate the hash
  // this is done by just adding respectively 4 bytes of the string
  // to the hash (longint)
  Result := StartHash;
  for I := 1 to (MaxLength_TUS_Identifier div 4) do
    Result := Result + LongInt(Identifier[I*4]); 
end;

end.