aboutsummaryrefslogtreecommitdiffstats
path: root/ServiceBasedPlugins/src/pluginsupport
diff options
context:
space:
mode:
Diffstat (limited to 'ServiceBasedPlugins/src/pluginsupport')
-rw-r--r--ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas38
-rw-r--r--ServiceBasedPlugins/src/pluginsupport/UPlugin.pas137
-rw-r--r--ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas273
-rw-r--r--ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas181
-rw-r--r--ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas38
-rw-r--r--ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas174
6 files changed, 841 insertions, 0 deletions
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas b/ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas
new file mode 100644
index 00000000..87e9531f
--- /dev/null
+++ b/ServiceBasedPlugins/src/pluginsupport/UPartyDefines.pas
@@ -0,0 +1,38 @@
+{* 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 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPartyDefines;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+end. \ No newline at end of file
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPlugin.pas b/ServiceBasedPlugins/src/pluginsupport/UPlugin.pas
new file mode 100644
index 00000000..19c23999
--- /dev/null
+++ b/ServiceBasedPlugins/src/pluginsupport/UPlugin.pas
@@ -0,0 +1,137 @@
+{* 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 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPlugin;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses UPluginDefines;
+
+// a basic implementation of IPlugin
+type
+ TPlugin = class(TInterfacedObject, IUS_Plugin)
+ protected
+ Status: TUS_PluginStatus;
+ Handle: TUS_Handle;
+ UniqueID: TUS_Handle;
+ Filename: WideString;
+ ErrorReason: WideString;
+
+ procedure OnChangeStatus(Status: TUS_PluginStatus); virtual;
+ public
+ constructor Create(Handle: TUS_Handle; Filename: WideString); virtual;
+
+ function GetStatus: TUS_PluginStatus; virtual;
+ procedure SetStatus(Status: TUS_PluginStatus); virtual;
+
+ function GetHandle: TUS_Handle; virtual;
+ function GetUniqueID: TUS_Handle; virtual;
+ function GetFilename: WideString; virtual;
+
+ procedure Init; virtual;
+ procedure DeInit; virtual;
+
+ procedure SetError(Reason: WideString); virtual;
+ function GetErrorReason: WideString; virtual;
+ end;
+
+implementation
+uses UPluginManager, ULog;
+
+constructor TPlugin.Create(Handle: TUS_Handle; Filename: WideString);
+begin
+ inherited Create;
+
+ Self.Handle := Handle;
+ Self.Filename := Filename;
+ Self.Status := psNone;
+
+ Self.UniqueID := CalculateUSHash(Filename); //< this should be done another way ;) just for testing purposes
+end;
+
+function TPlugin.GetStatus: TUS_PluginStatus;
+begin
+ Result := Status;
+end;
+
+procedure TPlugin.SetStatus(Status: TUS_PluginStatus);
+begin
+ // OnChangeStatus has to change the status attribut
+ OnChangeStatus(Status);
+end;
+
+function TPlugin.GetHandle: TUS_Handle;
+begin
+ Result := Handle;
+end;
+
+function TPlugin.GetUniqueID: TUS_Handle;
+begin
+ Result := UniqueID;
+end;
+
+function TPlugin.GetFilename: WideString;
+begin
+ Result := Filename;
+end;
+
+procedure TPlugin.Init;
+begin
+ if (Status = psWaitingInit) then
+ SetStatus(psInited);
+end;
+
+procedure TPlugin.DeInit;
+begin
+ if (Status = psInited) then
+ SetStatus(psDeInited);
+end;
+
+procedure TPlugin.SetError(Reason: WideString);
+begin
+ ErrorReason := Reason;
+ SetStatus(psError);
+ PluginManager.ReportError(Handle);
+ Log.LogError(Filename + ': ' + Reason);
+end;
+
+function TPlugin.GetErrorReason: WideString;
+begin
+ Result := ErrorReason;
+end;
+
+procedure TPlugin.OnChangeStatus(Status: TUS_PluginStatus);
+begin
+ //do nothing here
+ //should be overwritten by the child classes
+end;
+
+end. \ No newline at end of file
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas
new file mode 100644
index 00000000..5a042f1a
--- /dev/null
+++ b/ServiceBasedPlugins/src/pluginsupport/UPluginDefines.pas
@@ -0,0 +1,273 @@
+{* 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
+ SDK_Version = 0001000000000000; //< identifies the used SDK version (1.0.0.0)
+
+type
+ { this type is used for all version ints in this SDK }
+ TUS_Version = LongInt;
+
+ { this type is used for all plugin handles in this SDK }
+ TUS_Handle = LongInt;
+
+const
+ US_HANDLE_CORE = 137; //handle of core, also first defined handle
+ US_HANDLE_UNDEFINED = 0; //undefined handle, used to indicate errors
+
+ { 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 onced 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; stdcall;
+
+ { 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; stdcall;
+
+ { 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; Version: TUS_Version; Buffer: PWideChar; BufferLength: LongInt): LongInt; stdcall;
+
+ { 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 (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; stdcall;
+
+ { 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 (ID: TUS_Identifier; Version: TUS_Version; Buffer: Pointer; BufferLength: LongInt): LongInt; stdcall;
+
+ { 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; stdcall;
+
+ { 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; stdcall;
+
+ { 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, psWaitingIdentify, 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 GetStatus: TUS_PluginStatus;
+ procedure SetStatus(status: TUS_PluginStatus);
+
+ function GetHandle: TUS_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;
+
+ 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 }
+ TUS_Func_OnEvent = function(data: pointer; breakable: boolean): integer;
+ TUS_cFunc_OnEvent = function(data: pointer; breakable: boolean): 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): TUS_Handle;
+ function cHook(proc: TUS_cFunc_OnEvent; Parent: TUS_Handle): 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
+
+{ this function converts an errorcode to its textual expression }
+function USErrortoString(Code: LongInt): 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;
+
+{ 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.
+
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas
new file mode 100644
index 00000000..b143cd2a
--- /dev/null
+++ b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_DLL.pas
@@ -0,0 +1,181 @@
+{* 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 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPluginLoader_DLL;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses UPluginDefines, UPlugin;
+
+type
+ TPluginLoader_DLL = class
+ protected
+ PluginDir: WideString;
+ public
+ constructor Create(PluginDir: WideString);
+ procedure Browse(Dir: WideString);
+ end;
+
+ TPlugin_DLL = class (TPlugin)
+ protected
+ hLib: THandle; //< handle of loaded library
+ Lib_Proc_Init: TUS_Plugin_Proc_Init;
+ Lib_OnChangeStatus: TUS_Plugin_OnChangeStatus;
+
+ procedure OnChangeStatus(Status: TUS_PluginStatus); override;
+ public
+ constructor Create(Handle: TUS_Handle; Filename: WideString); override;
+ destructor Destroy; override;
+ end;
+
+const
+ {$IF Defined(MSWINDOWS)}
+ DLLExt = '.dll';
+ {$ELSEIF Defined(DARWIN)}
+ DLLExt = '.dylib';
+ {$ELSEIF Defined(UNIX)}
+ DLLExt = '.so';
+ {$IFEND}
+
+implementation
+uses
+ {$IFDEF MSWINDOWS}
+ windows,
+ {$ELSE}
+ dynlibs,
+ {$ENDIF}
+ SysUtils, Dialogs,
+ UPluginManager,
+ UPlatform;
+
+{ implementation of TPluginLoader_DLL }
+constructor TPluginLoader_DLL.Create(PluginDir: WideString);
+begin
+ Self.PluginDir := PluginDir;
+ Browse(PluginDir);
+end;
+
+procedure TPluginLoader_DLL.Browse(Dir: WideString);
+ var
+ Files: TDirectoryEntryArray;
+ I: Integer;
+begin
+ Showmessage(Dir + ' - ' + DLLExt);
+ Files := Platform.DirectoryFindFiles(Dir, DLLExt, True);
+
+ for I := 0 to High(Files) do
+ begin
+ ShowMessage(Dir + Files[I].Name);
+ if (Files[I].IsDirectory) then
+ Browse(Dir + Files[I].Name + PathDelim)
+ else if (Files[I].IsFile) then
+ PluginManager.AddPlugin(TPlugin_DLL.Create(PluginManager.GetHandle, Dir + Files[I].Name));
+ end;
+end;
+
+{ implementation of TPlugin_DLL }
+constructor TPlugin_DLL.Create(Handle: TUS_Handle; Filename: WideString);
+begin
+ inherited;
+
+ hLib := 0;
+ Lib_Proc_Init := nil;
+ Lib_OnChangeStatus := nil;
+
+ //try to load the library
+ SetStatus(psWaitingInit);
+end;
+
+destructor TPlugin_DLL.Destroy;
+begin
+
+ inherited;
+end;
+
+procedure TPlugin_DLL.OnChangeStatus(Status: TUS_PluginStatus);
+begin
+ Case Status of
+ psWaitingInit: begin
+ //we have to try to load the plugin here
+ hLib := LoadLibrary(PChar(AnsiString(Filename)));
+ if (hlib <> 0) then
+ begin
+ @Lib_Proc_Init := GetProcAddress(hLib, PChar('Proc_Init'));
+
+ If (not Assigned(Lib_Proc_Init)) then
+ begin
+ FreeLibrary(hLib);
+
+ {$IFDEF MSWINDOWS}
+ SetError('Can''t export Proc_Init procedure from library. Windows reports: ' + SysErrorMessage(GetLastError));
+ {$ELSE}
+ SetError('Can''t export Proc_Init procedure from library.');
+ {$ENDIF}
+ Exit;
+ end;
+
+ @Lib_OnChangeStatus := GetProcAddress(hLib, PChar('OnChangeStatus'));
+
+ If (not Assigned(Lib_OnChangeStatus)) then
+ begin
+ FreeLibrary(hLib);
+
+ {$IFDEF MSWINDOWS}
+ SetError('Can''t export OnChangeStatus procedure from library. Windows reports: ' + SysErrorMessage(GetLastError));
+ {$ELSE}
+ SetError('Can''t export OnChangeStatus procedure from library.');
+ {$ENDIF}
+ Exit;
+ end;
+
+ end
+ else
+ begin
+ {$IFDEF MSWINDOWS}
+ SetError('Error loading library. Windows reports: ' + SysErrorMessage(GetLastError));
+ {$ELSE}
+ SetError('Error loading library.');
+ {$ENDIF}
+ Exit;
+ end;
+
+ end;
+
+ end;
+
+ //call plugins OnChangeStatus procedure
+ If assigned(Lib_OnChangeStatus) then
+ Lib_OnChangeStatus(Self.Handle, Status);
+
+ Self.Status := Status;
+end;
+
+end. \ No newline at end of file
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas
new file mode 100644
index 00000000..df7b2f74
--- /dev/null
+++ b/ServiceBasedPlugins/src/pluginsupport/UPluginLoader_Included.pas
@@ -0,0 +1,38 @@
+{* 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 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+
+unit UPluginLoader_Included;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+implementation
+
+end.
diff --git a/ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas b/ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas
new file mode 100644
index 00000000..6c7f5056
--- /dev/null
+++ b/ServiceBasedPlugins/src/pluginsupport/UPluginManager.pas
@@ -0,0 +1,174 @@
+{* 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 1629 2009-03-07 22:30:04Z k-m_schindler $
+ *}
+unit UPluginManager;
+
+{ this class manages all loaded plugins }
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses Classes, UPluginDefines;
+
+type
+ TPluginManager = class
+ private
+ NextHandle: TUS_Handle;
+
+ Plugins: TInterfaceList;
+ Events: TInterfaceList;
+ Interfaces: TInterfaceList;
+
+ public
+ constructor Create;
+
+ //returns a unique handle to use e.g. w/ a pluginloader
+ function GetHandle: TUS_Handle;
+
+ //returns the plugin w/ the specified handle
+ function GetPluginbyHandle(Handle: TUS_Handle): IUS_Plugin;
+
+ //just adds a plugin to the pluginlist
+ //it will be inited on next call of init
+ function AddPlugin(Plugin: IInterface): TUS_Handle;
+
+ procedure Init; //< inits all plugins w/ status psWaitingInit
+ procedure DeInit; //< deinits all plugins w/ status psInited
+
+ //called by plugins if they change to status psError
+ //removes all saved data and callbacks by this handle
+ procedure ReportError(Handle: TUS_Handle);
+
+ destructor Destroy;
+ end;
+
+var
+ PluginManager: TPluginManager;
+
+implementation
+uses SysUtils;
+
+constructor TPluginManager.Create;
+begin
+ NextHandle := US_HANDLE_CORE + 1;
+
+ Plugins := TInterfaceList.Create;
+ Events := TInterfaceList.Create;
+ Interfaces := TInterfaceList.Create;
+end;
+
+destructor TPluginManager.Destroy;
+begin
+ DeInit;
+
+ Plugins.Destroy;
+ Events.Destroy;
+ Interfaces.Destroy;
+end;
+
+// returns a unique handle to use e.g. w/ a pluginloader
+function TPluginManager.GetHandle: TUS_Handle;
+begin
+ Result := NextHandle;
+ Inc(NextHandle);
+end;
+
+//returns the plugin w/ the specified handle
+function TPluginManager.GetPluginbyHandle(Handle: TUS_Handle): IUS_Plugin;
+ var
+ I: integer;
+ Plugin: IUS_Plugin;
+begin
+ Result := nil;
+ for I := 0 to Plugins.Count-1 do
+ begin
+ Plugin := IUS_Plugin(Plugins.Items[I]);
+ If (Plugin.GetHandle = Handle) then
+ begin
+ Result := Plugin;
+ Exit;
+ end;
+ end;
+end;
+
+// just adds a plugin to the pluginlist
+// it will be inited on next call of init
+function TPluginManager.AddPlugin(Plugin: IInterface): TUS_Handle;
+begin
+ If Supports(Plugin, IUS_Plugin) then
+ Plugins.Add(Plugin);
+end;
+
+// inits all plugins w/ status psWaitingInit
+procedure TPluginManager.Init;
+ var
+ I: integer;
+ Plugin: IUS_Plugin;
+begin
+ for I := 0 to Plugins.Count-1 do
+ begin
+ Plugin := IUS_Plugin(Plugins.Items[I]);
+ If (Plugin.GetStatus = psWaitingInit) then
+ begin
+ Plugin.Init;
+ end;
+ end;
+end;
+
+// deinits all plugins w/ status psInited
+procedure TPluginManager.DeInit;
+ var
+ I: integer;
+ Plugin: IUS_Plugin;
+begin
+ for I := 0 to Plugins.Count-1 do
+ begin
+ Plugin := IUS_Plugin(Plugins.Items[I]);
+ If (Plugin.GetStatus = psInited) then
+ begin
+ Plugin.DeInit;
+ end;
+ end;
+end;
+
+//called by plugins if they change to errorstate
+//removes all saved data and callbacks by this handle
+procedure TPluginManager.ReportError(Handle: TUS_Handle);
+ var
+ I: integer;
+ Event: IUS_HookableEvent;
+begin
+ for I := 0 to Events.Count-1 do
+ begin
+ Event := IUS_HookableEvent(Events.Items[I]);
+ Event.UnHookbyParent(Handle);
+ end;
+end;
+
+end. \ No newline at end of file