From f9f6680e40b3d9b905d2905c8cb1719d0f78a339 Mon Sep 17 00:00:00 2001 From: utak3r Date: Wed, 27 Jun 2007 22:45:40 +0000 Subject: [PATCH] Initial version --- 2.10/Source/varGenericPlugin.pas | 366 +++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 2.10/Source/varGenericPlugin.pas diff --git a/2.10/Source/varGenericPlugin.pas b/2.10/Source/varGenericPlugin.pas new file mode 100644 index 0000000..5e72147 --- /dev/null +++ b/2.10/Source/varGenericPlugin.pas @@ -0,0 +1,366 @@ +{ + Apophysis Copyright (C) 2001-2004 Mark Townsend + Apophysis Copyright (C) 2005-2006 Ronald Hordijk, Piotr Borys, Peter Sdobnov + Apophysis Copyright (C) 2007 Piotr Borys, Peter Sdobnov + + 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; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +} +{ + Variation Plugin DLL support for Apophysis: + Generic Plugin Support Unit + Started by Jed Kelsey, June 2007 +} + +unit varGenericPlugin; + +interface + +uses + BaseVariation, XFormMan, + Classes, //TStrings/TStringList + SysUtils, //FindFirst/FindNext/FindClose + Dialogs; //ShowMessage + +type + TPluginVarGetName = function : PChar; cdecl; + TPluginVarGetNrVariables = function : Integer; cdecl; + TPluginVarGetVariableNameAt = function(const Index: integer): PChar; cdecl; + + TPluginVarCreate = function : Pointer; cdecl; + TPluginVarDestroy = function(var MyVariation : Pointer) : LongBool; cdecl; + TPluginVarInit = function(MyVariation, FPx, FPy, FTx, FTy: Pointer; vvar: double) : LongBool; cdecl; + TPluginVarPrepare = function(MyVariation : Pointer) : LongBool; cdecl; + TPluginVarCalc = function(MyVariation : Pointer) : LongBool; cdecl; + TPluginVarGetVariable = function(MyVariation:Pointer; const Name: PChar; var value: double) : LongBool; cdecl; + TPluginVarSetVariable = function(MyVariation:Pointer; const Name: PChar; var value: double) : LongBool; cdecl; + + TPluginVariationClass = class of TPluginVariation; + + TPluginData = record + Instance : Integer; + PluginHandle : THandle; + PluginClass : TPluginVariationClass; + + PluginVarGetName : TPluginVarGetName; + PluginVarGetNrVariables : TPluginVarGetNrVariables; + PluginVarGetVariableNameAt: TPluginVarGetVariableNameAt; + + PluginVarCreate : TPluginVarCreate; + PluginVarDestroy : TPluginVarDestroy; + PluginVarInit : TPluginVarInit; + PluginVarPrepare : TPluginVarPrepare; + PluginVarCalc : TPluginVarCalc; + PluginVarGetVariable : TPluginVarGetVariable; + PluginVarSetVariable : TPluginVarSetVariable; + end; + PPluginData = ^TPluginData; + + // This class serves as a proxy for the plugin variations. + TPluginVariation = class(TBaseVariation) + + private + MyVariation : Pointer; + + public + constructor Create; + destructor Destroy; override; + + class function GetName: string; override; + class function GetInstance: TBaseVariation; override; + + class function GetNrVariables: integer; override; + class function GetVariableNameAt(const Index: integer): string; override; + + function SetVariable(const Name: string; var value: double): boolean; override; + function GetVariable(const Name: string; var value: double): boolean; override; + + procedure Prepare; override; + procedure CalcFunction; override; + + class function GetPluginData : PPluginData; virtual; + end; + + ////////////////////////////////////////////////////////////////////// + { Derive a number of classes from the base TPluginVariation class and + ensure a unique PluginData record for each derived class (each plugin), + and override a class function to return the appropriate PluginData. + There's got to be a much more straightforward way to do this, taking + advantage of Delphi's late (run-time) binding to make it work with an + arbitrary number of class "instances" and build them on the fly, + but I'm new to Delphi & not sure what it is :) Suggestions anyone? } + + TPluginVariation0 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation1 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation2 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation3 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation4 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation5 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation6 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation7 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation8 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + + TPluginVariation9 = class(TPluginVariation) + class function GetPluginData : PPluginData; override; + end; + ////////////////////////////////////////////////////////////////////// + + var + //PluginVariationClasses : array of TPluginVariationClass; + PluginData : array of TPluginData; + NumPlugins : Integer; + +implementation + +uses + Windows, //LoadLibrary + Math; + +{ TPluginVariation } + +/////////////////////////////////////////////////////////////////////////////// + +{ These overridden functions are explicitly defined here to ensure that they + return the appropriate data record for the class (need to have one per + derived class so that class methods for multiple plugins get executed + correctly. Again, I'm sure there's a much better way around this, but being + new to Delphi, I don't know what it is. } + +class function TPluginVariation.GetPluginData : PPluginData; +begin + Result := @(PluginData[0]); // As the base class, this shouldn't get called... +end; + +class function TPluginVariation0.GetPluginData : PPluginData; +begin + Result := @(PluginData[0]); +end; + +class function TPluginVariation1.GetPluginData : PPluginData; +begin + Result := @(PluginData[1]); +end; + +class function TPluginVariation2.GetPluginData : PPluginData; +begin + Result := @(PluginData[2]); +end; + +class function TPluginVariation3.GetPluginData : PPluginData; +begin + Result := @(PluginData[3]); +end; + +class function TPluginVariation4.GetPluginData : PPluginData; +begin + Result := @(PluginData[4]); +end; + +class function TPluginVariation5.GetPluginData : PPluginData; +begin + Result := @(PluginData[5]); +end; + +class function TPluginVariation6.GetPluginData : PPluginData; +begin + Result := @(PluginData[6]); +end; + +class function TPluginVariation7.GetPluginData : PPluginData; +begin + Result := @(PluginData[7]); +end; + +class function TPluginVariation8.GetPluginData : PPluginData; +begin + Result := @(PluginData[8]); +end; + +class function TPluginVariation9.GetPluginData : PPluginData; +begin + Result := @(PluginData[9]); +end; + +//////////// ////////// //////////// + +procedure TPluginVariation.Prepare; +begin + GetPluginData.PluginVarInit(MyVariation, Pointer(FPX), Pointer(FPy), Pointer(FTx), Pointer(FTy), vvar); + GetPluginData.PluginVarPrepare(MyVariation); +end; + +/////////////////////////////////////////////////////////////////////////////// +procedure TPluginVariation.CalcFunction; +begin + GetPluginData.PluginVarInit(MyVariation, Pointer(FPX), Pointer(FPy), Pointer(FTx), Pointer(FTy), vvar); + GetPluginData.PluginVarCalc(MyVariation); +end; + +/////////////////////////////////////////////////////////////////////////////// +constructor TPluginVariation.Create; +begin + MyVariation := GetPluginData.PluginVarCreate; +end; + +/////////////////////////////////////////////////////////////////////////////// +destructor TPluginVariation.Destroy; +begin + GetPluginData.PluginVarDestroy(MyVariation); + inherited; +end; + +/////////////////////////////////////////////////////////////////////////////// +class function TPluginVariation.GetInstance: TBaseVariation; +begin + //Result := TPluginVariation.Create; // Want derived class's constructor! + Result := Self.Create; //So the derived class type gets preserved... +end; + +/////////////////////////////////////////////////////////////////////////////// +class function TPluginVariation.GetName: string; +begin + Result := String(GetPluginData.PluginVarGetName()); +end; + +/////////////////////////////////////////////////////////////////////////////// +class function TPluginVariation.GetNrVariables: integer; +begin + Result := GetPluginData.PluginVarGetNrVariables(); +end; + +/////////////////////////////////////////////////////////////////////////////// +class function TPluginVariation.GetVariableNameAt(const Index: integer): string; +begin + Result := String(GetPluginData.PluginVarGetVariableNameAt(Index)); +end; + +/////////////////////////////////////////////////////////////////////////////// +function TPluginVariation.SetVariable(const Name: string; var value: double): boolean; +begin + Result := GetPluginData.PluginVarSetVariable(MyVariation,PChar(Name),value); +end; + +/////////////////////////////////////////////////////////////////////////////// +function TPluginVariation.GetVariable(const Name: string; var value: double): boolean; +begin + Result := GetPluginData.PluginVarGetVariable(MyVariation,PChar(Name),value); +end; + +/////////////////////////////////////////////////////////////////////////////// +procedure InitializePlugins; +var + searchResult : TSearchRec; +begin + NumPlugins := 0; + // Try to find regular files matching *.dll in the plugins dir + if FindFirst('.\Plugins\*.dll', faAnyFile, searchResult) = 0 then + begin + repeat + //ShowMessage('Found plugin: '+searchResult.Name+' ('+IntToStr(searchResult.Size)+' bytes)'); + // Work with PluginData for the derived class (would be returned by GetPluginData) + with PluginData[NumPlugins] do begin + //Load DLL and initialize plugins! + PluginHandle := LoadLibrary(PChar('.\Plugins\'+searchResult.Name)); + if PluginHandle<>0 then begin + @PluginVarGetName := GetProcAddress(PluginHandle,'PluginVarGetName'); + if @PluginVarGetName = nil then begin // Must not be a valid plugin! + FreeLibrary(PluginHandle); + ShowMessage('Invalid Plugin: Could not find PluginVarGetName in '+searchResult.Name); + end else begin + @PluginVarGetNrVariables := GetProcAddress(PluginHandle,'PluginVarGetNrVariables'); + @PluginVarGetVariableNameAt := GetProcAddress(PluginHandle,'PluginVarGetVariableNameAt'); + @PluginVarCreate := GetProcAddress(PluginHandle,'PluginVarCreate'); + @PluginVarDestroy := GetProcAddress(PluginHandle,'PluginVarDestroy'); + @PluginVarInit := GetProcAddress(PluginHandle,'PluginVarInit'); + @PluginVarPrepare := GetProcAddress(PluginHandle,'PluginVarPrepare'); + @PluginVarCalc := GetProcAddress(PluginHandle,'PluginVarCalc'); + @PluginVarGetVariable := GetProcAddress(PluginHandle,'PluginVarGetVariable'); + @PluginVarSetVariable := GetProcAddress(PluginHandle,'PluginVarSetVariable'); + Instance := NumPlugins+1; + + RegisterVariation(PluginClass); + + Inc(NumPlugins); + if NumPlugins >= Length(PluginData) then + break; + end; + end else + ShowMessage('Could not load a plugin: '+searchResult.Name); + end; + until (FindNext(searchResult) <> 0); + SysUtils.FindClose(searchResult); //Since we use Windows unit (LoadLibrary) + end; +end; + +/////////////////////////////////////////////////////////////////////////////// +procedure FinalizePlugins; +var + I : Integer; +begin + for I := 0 to NumPlugins - 1 do begin + if PluginData[NumPlugins].PluginHandle<>0 then begin + FreeLibrary(PluginData[NumPlugins].PluginHandle); + end; + end; +end; + +/////////////////////////////////////////////////////////////////////////////// +initialization + SetLength(PluginData,10); + + PluginData[0].PluginClass := TPluginVariation0; + PluginData[1].PluginClass := TPluginVariation1; + PluginData[2].PluginClass := TPluginVariation2; + PluginData[3].PluginClass := TPluginVariation3; + PluginData[4].PluginClass := TPluginVariation4; + PluginData[5].PluginClass := TPluginVariation5; + PluginData[6].PluginClass := TPluginVariation6; + PluginData[7].PluginClass := TPluginVariation7; + PluginData[8].PluginClass := TPluginVariation8; + PluginData[9].PluginClass := TPluginVariation9; + + InitializePlugins; + + +finalization + //Release all loaded plugin(s) + FinalizePlugins; +end. +