1
0
mirror of synced 2024-09-28 21:16:09 +00:00

Fixed crashes on shutdown due to Lua API being unloaded before the last TLua instance is destroyed

This commit is contained in:
Mark van Renswoude 2017-06-01 20:19:19 +02:00
parent 197349f515
commit 6dbea6f211
7 changed files with 166 additions and 172 deletions

View File

@ -263,13 +263,14 @@ object ButtonFunctionForm: TButtonFunctionForm
TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages] TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages]
TreeOptions.SelectionOptions = [toFullRowSelect] TreeOptions.SelectionOptions = [toFullRowSelect]
OnFocusChanged = vstFunctionsFocusChanged OnFocusChanged = vstFunctionsFocusChanged
OnFreeNode = vstFunctionsFreeNode
OnGetText = vstFunctionsGetText OnGetText = vstFunctionsGetText
OnPaintText = vstFunctionsPaintText OnPaintText = vstFunctionsPaintText
OnIncrementalSearch = vstFunctionsIncrementalSearch OnIncrementalSearch = vstFunctionsIncrementalSearch
Columns = < Columns = <
item item
Position = 0 Position = 0
Width = 253 Width = 257
WideText = 'Available functions' WideText = 'Available functions'
end> end>
end end

View File

@ -15,6 +15,7 @@ uses
LEDColorIntf, LEDColorIntf,
LEDFunctionIntf, LEDFunctionIntf,
LEDFunctionRegistry,
LEDStateIntf, LEDStateIntf,
Profile, Vcl.ActnList; Profile, Vcl.ActnList;
@ -60,6 +61,7 @@ type
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char); procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure FormShow(Sender: TObject); procedure FormShow(Sender: TObject);
procedure vstFunctionsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure vstFunctionsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure vstFunctionsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
procedure vstFunctionsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure vstFunctionsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
procedure vstFunctionsIncrementalSearch(Sender: TBaseVirtualTree; Node: PVirtualNode; const SearchText: string; var Result: Integer); procedure vstFunctionsIncrementalSearch(Sender: TBaseVirtualTree; Node: PVirtualNode; const SearchText: string; var Result: Integer);
@ -73,8 +75,9 @@ type
FSelectedProvider: ILEDFunctionProvider; FSelectedProvider: ILEDFunctionProvider;
FSelectedFunction: ILEDFunction; FSelectedFunction: ILEDFunction;
FStateControls: TStateControlInfoList; FStateControls: TStateControlInfoList;
FFunctionRegistry: TLEDFunctionRegistry;
protected protected
procedure Initialize(AProfile: TProfile; AButtonIndex: Integer); procedure Initialize(AFunctionRegistry: TLEDFunctionRegistry; AProfile: TProfile; AButtonIndex: Integer);
procedure LoadFunctions; procedure LoadFunctions;
procedure ApplyFilter(const AFilter: string); procedure ApplyFilter(const AFilter: string);
@ -91,8 +94,9 @@ type
property Profile: TProfile read FProfile; property Profile: TProfile read FProfile;
property ButtonIndex: Integer read FButtonIndex; property ButtonIndex: Integer read FButtonIndex;
property FunctionRegistry: TLEDFunctionRegistry read FFunctionRegistry;
public public
class function Execute(AProfile: TProfile; AButtonIndex: Integer): Boolean; class function Execute(AFunctionRegistry: TLEDFunctionRegistry; AProfile: TProfile; AButtonIndex: Integer): Boolean;
end; end;
@ -118,7 +122,6 @@ uses
System.SysUtils, System.SysUtils,
Winapi.Windows, Winapi.Windows,
LEDFunctionRegistry,
LEDResources; LEDResources;
@ -150,11 +153,11 @@ const
{ TButtonFunctionForm } { TButtonFunctionForm }
class function TButtonFunctionForm.Execute(AProfile: TProfile; AButtonIndex: Integer): Boolean; class function TButtonFunctionForm.Execute(AFunctionRegistry: TLEDFunctionRegistry; AProfile: TProfile; AButtonIndex: Integer): Boolean;
begin begin
with Self.Create(nil) do with Self.Create(nil) do
try try
Initialize(AProfile, AButtonIndex); Initialize(AFunctionRegistry, AProfile, AButtonIndex);
Result := (ShowModal = mrOk); Result := (ShowModal = mrOk);
finally finally
Free; Free;
@ -247,7 +250,7 @@ begin
categoryNodes := TDictionary<string, PVirtualNode>.Create; categoryNodes := TDictionary<string, PVirtualNode>.Create;
try try
for provider in TLEDFunctionRegistry.Providers do for provider in FunctionRegistry.Providers do
begin begin
isCurrentProvider := Assigned(CurrentProvider) and (provider.GetUID = CurrentProvider.GetUID); isCurrentProvider := Assigned(CurrentProvider) and (provider.GetUID = CurrentProvider.GetUID);
@ -371,8 +374,9 @@ begin
end; end;
procedure TButtonFunctionForm.Initialize(AProfile: TProfile; AButtonIndex: Integer); procedure TButtonFunctionForm.Initialize(AFunctionRegistry: TLEDFunctionRegistry; AProfile: TProfile; AButtonIndex: Integer);
begin begin
FFunctionRegistry := AFunctionRegistry;
FProfile := AProfile; FProfile := AProfile;
FButtonIndex := AButtonIndex; FButtonIndex := AButtonIndex;
FButton := nil; FButton := nil;
@ -384,7 +388,7 @@ begin
if Profile.HasButton(ButtonIndex) then if Profile.HasButton(ButtonIndex) then
begin begin
FButton := Profile.Buttons[ButtonIndex]; FButton := Profile.Buttons[ButtonIndex];
FCurrentProvider := TLEDFunctionRegistry.Find(Button.ProviderUID); FCurrentProvider := FunctionRegistry.Find(Button.ProviderUID);
if Assigned(CurrentProvider) then if Assigned(CurrentProvider) then
FCurrentFunction := CurrentProvider.Find(Button.FunctionUID); FCurrentFunction := CurrentProvider.Find(Button.FunctionUID);
@ -519,6 +523,16 @@ begin
end; end;
procedure TButtonFunctionForm.vstFunctionsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
nodeData: PFunctionNodeData;
begin
nodeData := Sender.GetNodeData(Node);
Finalize(nodeData^);
end;
procedure TButtonFunctionForm.vstFunctionsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure TButtonFunctionForm.vstFunctionsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
var var
nodeData: PFunctionNodeData; nodeData: PFunctionNodeData;

View File

@ -24,6 +24,7 @@ uses
X2UtPersistIntf, X2UtPersistIntf,
ControlIntf, ControlIntf,
LEDFunctionRegistry,
FSXSimConnectIntf, FSXSimConnectIntf,
LEDStateConsumer, LEDStateConsumer,
Profile, Profile,
@ -163,6 +164,8 @@ type
FSettingsFileName: string; FSettingsFileName: string;
FSettings: TSettings; FSettings: TSettings;
FLoadingSettings: Boolean; FLoadingSettings: Boolean;
FFunctionRegistry: TLEDFunctionRegistry;
protected protected
procedure RegisterDeviceArrival; procedure RegisterDeviceArrival;
procedure UnregisterDeviceArrival; procedure UnregisterDeviceArrival;
@ -219,6 +222,7 @@ type
property StateConsumerTask: IOmniTaskControl read FStateConsumerTask; property StateConsumerTask: IOmniTaskControl read FStateConsumerTask;
property Log: IX2Log read FLog; property Log: IX2Log read FLog;
property FunctionRegistry: TLEDFunctionRegistry read FFunctionRegistry;
end; end;
@ -249,7 +253,6 @@ uses
G940LEDStateConsumer, G940LEDStateConsumer,
LEDColorIntf, LEDColorIntf,
LEDFunctionIntf, LEDFunctionIntf,
LEDFunctionRegistry,
StaticLEDFunction, StaticLEDFunction,
StaticResources; StaticResources;
@ -324,19 +327,20 @@ begin
SetFSXState(TextFSXDisconnected, False); SetFSXState(TextFSXDisconnected, False);
TLEDFunctionRegistry.Register(TStaticLEDFunctionProvider.Create); FFunctionRegistry := TLEDFunctionRegistry.Create;
FunctionRegistry.Register(TStaticLEDFunctionProvider.Create);
SetLength(scriptPaths, 2); SetLength(scriptPaths, 2);
scriptPaths[0] := App.Path + FSXScriptsPath; scriptPaths[0] := App.Path + FSXScriptsPath;
scriptPaths[1] := App.UserPath + UserDataPath + FSXScriptsPath; scriptPaths[1] := App.UserPath + UserDataPath + FSXScriptsPath;
TLEDFunctionRegistry.Register(TFSXLEDFunctionProvider.Create(scriptPaths)); FunctionRegistry.Register(TFSXLEDFunctionProvider.Create(scriptPaths));
FEventMonitor := TOmniEventMonitor.Create(Self); FEventMonitor := TOmniEventMonitor.Create(Self);
Log.Info('Starting G940 LED state consumer thread'); Log.Info('Starting G940 LED state consumer thread');
worker := TG940LEDStateConsumer.Create(TX2GlobalLog.Category('G940 LED state consumer')); worker := TG940LEDStateConsumer.Create(TX2GlobalLog.Category('G940 LED state consumer'), FunctionRegistry);
FStateConsumerTask := EventMonitor.Monitor(CreateTask(worker)); FStateConsumerTask := EventMonitor.Monitor(CreateTask(worker));
EventMonitor.OnTaskMessage := EventMonitorMessage; EventMonitor.OnTaskMessage := EventMonitorMessage;
@ -379,6 +383,14 @@ begin
TX2LogObserverMonitorForm.CloseInstance(TX2GlobalLog.Instance); TX2LogObserverMonitorForm.CloseInstance(TX2GlobalLog.Instance);
TX2LogObserverMonitorForm.UnlockInstance(TX2GlobalLog.Instance); TX2LogObserverMonitorForm.UnlockInstance(TX2GlobalLog.Instance);
if Assigned(StateConsumerTask) then
begin
StateConsumerTask.Stop;
StateConsumerTask.WaitFor(INFINITE);
end;
FreeAndNil(FFunctionRegistry);
end; end;
@ -726,7 +738,7 @@ begin
end; end;
buttonFunction := nil; buttonFunction := nil;
provider := TLEDFunctionRegistry.Find(providerUID); provider := FunctionRegistry.Find(providerUID);
if Assigned(provider) then if Assigned(provider) then
buttonFunction := provider.Find(functionUID); buttonFunction := provider.Find(functionUID);
@ -925,7 +937,7 @@ begin
end; end;
buttonIndex := (Sender as TComponent).Tag; buttonIndex := (Sender as TComponent).Tag;
if TButtonFunctionForm.Execute(profile, buttonIndex) then if TButtonFunctionForm.Execute(FunctionRegistry, profile, buttonIndex) then
begin begin
if newProfile then if newProfile then
AddProfile(profile); AddProfile(profile);
@ -1308,7 +1320,7 @@ var
fsxProvider: IFSXLEDFunctionProvider; fsxProvider: IFSXLEDFunctionProvider;
begin begin
if Supports(TLEDFunctionRegistry.Find(FSXProviderUID), IFSXLEDFunctionProvider, fsxProvider) then if Supports(FunctionRegistry.Find(FSXProviderUID), IFSXLEDFunctionProvider, fsxProvider) then
fsxProvider.SetProfileMenu(Settings.ProfileMenu, Settings.ProfileMenuCascaded); fsxProvider.SetProfileMenu(Settings.ProfileMenu, Settings.ProfileMenuCascaded);
end; end;
@ -1318,7 +1330,7 @@ var
fsxProvider: IFSXLEDFunctionProvider; fsxProvider: IFSXLEDFunctionProvider;
begin begin
if Supports(TLEDFunctionRegistry.Find(FSXProviderUID), IFSXLEDFunctionProvider, fsxProvider) then if Supports(FunctionRegistry.Find(FSXProviderUID), IFSXLEDFunctionProvider, fsxProvider) then
fsxProvider.SetProfileMenu(False, False); fsxProvider.SetProfileMenu(False, False);
end; end;

View File

@ -181,10 +181,10 @@ end;
destructor TFSXLEDFunctionProvider.Destroy; destructor TFSXLEDFunctionProvider.Destroy;
begin begin
inherited Destroy;
FreeAndNil(FScriptSimConnect); FreeAndNil(FScriptSimConnect);
FreeAndNil(FSimConnectLock); FreeAndNil(FSimConnectLock);
inherited Destroy;
end; end;

View File

@ -13,24 +13,16 @@ type
TLEDFunctionRegistry = class(TObject) TLEDFunctionRegistry = class(TObject)
private private
FProviders: TLEDFunctionProviderList; FProviders: TLEDFunctionProviderList;
protected
class function Instance: TLEDFunctionRegistry;
procedure DoRegister(AProvider: ILEDFunctionProvider);
procedure DoUnregister(AProvider: ILEDFunctionProvider);
function DoFind(const AUID: string): ILEDFunctionProvider;
function GetProviders: TLEDFunctionProviderList;
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
class procedure Register(AProvider: ILEDFunctionProvider); procedure Register(AProvider: ILEDFunctionProvider);
class procedure Unregister(AProvider: ILEDFunctionProvider); procedure Unregister(AProvider: ILEDFunctionProvider);
class function Find(const AUID: string): ILEDFunctionProvider; function Find(const AUID: string): ILEDFunctionProvider;
class function Providers: TLEDFunctionProviderList; function Providers: TLEDFunctionProviderList;
end; end;
@ -64,44 +56,7 @@ uses
SysUtils; SysUtils;
var
RegistryInstance: TLEDFunctionRegistry;
{ TLEDFunctionRegistry } { TLEDFunctionRegistry }
class procedure TLEDFunctionRegistry.Register(AProvider: ILEDFunctionProvider);
begin
Instance.DoRegister(AProvider);
end;
class procedure TLEDFunctionRegistry.Unregister(AProvider: ILEDFunctionProvider);
begin
Instance.DoUnregister(AProvider);
end;
class function TLEDFunctionRegistry.Find(const AUID: string): ILEDFunctionProvider;
begin
Result := Instance.DoFind(AUID);
end;
class function TLEDFunctionRegistry.Providers: TLEDFunctionProviderList;
begin
Result := Instance.GetProviders;
end;
class function TLEDFunctionRegistry.Instance: TLEDFunctionRegistry;
begin
if not Assigned(RegistryInstance) then
RegistryInstance := TLEDFunctionRegistry.Create;
Result := RegistryInstance;
end;
constructor TLEDFunctionRegistry.Create; constructor TLEDFunctionRegistry.Create;
begin begin
inherited Create; inherited Create;
@ -118,25 +73,25 @@ begin
end; end;
procedure TLEDFunctionRegistry.DoRegister(AProvider: ILEDFunctionProvider); procedure TLEDFunctionRegistry.Register(AProvider: ILEDFunctionProvider);
begin begin
FProviders.Add(AProvider); FProviders.Add(AProvider);
end; end;
procedure TLEDFunctionRegistry.DoUnregister(AProvider: ILEDFunctionProvider); procedure TLEDFunctionRegistry.Unregister(AProvider: ILEDFunctionProvider);
begin begin
FProviders.Remove(AProvider); FProviders.Remove(AProvider);
end; end;
function TLEDFunctionRegistry.DoFind(const AUID: string): ILEDFunctionProvider; function TLEDFunctionRegistry.Find(const AUID: string): ILEDFunctionProvider;
begin begin
Result := FProviders.Find(AUID); Result := FProviders.Find(AUID);
end; end;
function TLEDFunctionRegistry.GetProviders: TLEDFunctionProviderList; function TLEDFunctionRegistry.Providers: TLEDFunctionProviderList;
begin begin
Result := FProviders; Result := FProviders;
end; end;
@ -208,9 +163,4 @@ begin
Result := ((inherited GetCurrent) as ILEDFunctionProvider); Result := ((inherited GetCurrent) as ILEDFunctionProvider);
end; end;
initialization
finalization
FreeAndNil(RegistryInstance);
end. end.

View File

@ -11,6 +11,7 @@ uses
LEDColorIntf, LEDColorIntf,
LEDFunctionIntf, LEDFunctionIntf,
LEDFunctionRegistry,
Profile; Profile;
@ -28,6 +29,7 @@ type
FButtonColors: TInterfaceList; FButtonColors: TInterfaceList;
FHasTickTimer: Boolean; FHasTickTimer: Boolean;
FLog: IX2Log; FLog: IX2Log;
FFunctionRegistry: TLEDFunctionRegistry;
protected protected
function Initialize: Boolean; override; function Initialize: Boolean; override;
procedure Cleanup; override; procedure Cleanup; override;
@ -45,11 +47,12 @@ type
procedure Update; virtual; abstract; procedure Update; virtual; abstract;
property Log: IX2Log read FLog; property Log: IX2Log read FLog;
property FunctionRegistry: TLEDFunctionRegistry read FFunctionRegistry;
protected protected
procedure TMLoadProfile(var Msg: TOmniMessage); message TM_LOADPROFILE; procedure TMLoadProfile(var Msg: TOmniMessage); message TM_LOADPROFILE;
procedure TMTick(var Msg: TOmniMessage); message TM_TICK; procedure TMTick(var Msg: TOmniMessage); message TM_TICK;
public public
constructor Create(ALog: IX2Log); constructor Create(ALog: IX2Log; AFunctionRegistry: TLEDFunctionRegistry);
end; end;
@ -59,7 +62,6 @@ uses
System.SysUtils, System.SysUtils,
Winapi.Windows, Winapi.Windows,
LEDFunctionRegistry,
LEDStateIntf; LEDStateIntf;
@ -82,11 +84,12 @@ type
{ TLEDStateConsumer } { TLEDStateConsumer }
constructor TLEDStateConsumer.Create(ALog: IX2Log); constructor TLEDStateConsumer.Create(ALog: IX2Log; AFunctionRegistry: TLEDFunctionRegistry);
begin begin
inherited Create; inherited Create;
FLog := ALog; FLog := ALog;
FFunctionRegistry := AFunctionRegistry;
end; end;
@ -118,7 +121,7 @@ var
begin begin
Result := nil; Result := nil;
provider := TLEDFunctionRegistry.Find(AProfileButton.ProviderUID); provider := FunctionRegistry.Find(AProfileButton.ProviderUID);
if Assigned(provider) then if Assigned(provider) then
begin begin
ledFunction := provider.Find(AProfileButton.FunctionUID); ledFunction := provider.Find(AProfileButton.FunctionUID);

View File

@ -6,6 +6,8 @@ uses
System.SysUtils, System.SysUtils,
System.Types, System.Types,
X2Log.Intf,
LEDFunction, LEDFunction,
LEDFunctionIntf, LEDFunctionIntf,
LEDStateIntf, LEDStateIntf,
@ -50,6 +52,12 @@ type
protected protected
function CreateLuaLEDFunction(AInfo: ILuaTable; ASetup: ILuaFunction): TCustomLuaLEDFunction; virtual; abstract; function CreateLuaLEDFunction(AInfo: ILuaTable; ASetup: ILuaFunction): TCustomLuaLEDFunction; virtual; abstract;
procedure AppendVariable(ABuilder: TStringBuilder; AVariable: ILuaVariable);
procedure AppendTable(ABuilder: TStringBuilder; ATable: ILuaTable);
procedure DoLog(AContext: ILuaContext; ALevel: TX2LogLevel);
procedure DoLogMessage(AContext: ILuaContext; ALevel: TX2LogLevel; const AMessage: string);
procedure ScriptRegisterFunction(Context: ILuaContext); procedure ScriptRegisterFunction(Context: ILuaContext);
procedure ScriptSetState(Context: ILuaContext); procedure ScriptSetState(Context: ILuaContext);
@ -91,7 +99,6 @@ uses
System.IOUtils, System.IOUtils,
Lua.API, Lua.API,
X2Log.Intf,
X2Log.Global, X2Log.Global,
LEDColorIntf, LEDColorIntf,
@ -99,18 +106,15 @@ uses
type type
TLuaLogProc = reference to procedure(AContext: ILuaContext; ALevel: TX2LogLevel);
TLuaLog = class(TPersistent) TLuaLog = class(TPersistent)
private private
FInterpreter: TLua; FOnLog: TLuaLogProc;
protected protected
procedure AppendVariable(ABuilder: TStringBuilder; AVariable: ILuaVariable); property OnLog: TLuaLogProc read FOnLog;
procedure AppendTable(ABuilder: TStringBuilder; ATable: ILuaTable);
procedure Log(AContext: ILuaContext; ALevel: TX2LogLevel);
property Interpreter: TLua read FInterpreter;
public public
constructor Create(AInterpreter: TLua); constructor Create(AOnLog: TLuaLogProc);
published published
procedure Verbose(Context: ILuaContext); procedure Verbose(Context: ILuaContext);
procedure Info(Context: ILuaContext); procedure Info(Context: ILuaContext);
@ -149,7 +153,7 @@ begin
FWorkers := TDictionary<string, TCustomLuaLEDFunctionWorker>.Create; FWorkers := TDictionary<string, TCustomLuaLEDFunctionWorker>.Create;
FInterpreter := TLua.Create; FInterpreter := TLua.Create;
FScriptFolders := AScriptFolders; FScriptFolders := AScriptFolders;
FScriptLog := TLuaLog.Create(FInterpreter); FScriptLog := TLuaLog.Create(DoLog);
InitInterpreter; InitInterpreter;
@ -159,11 +163,11 @@ end;
destructor TCustomLuaLEDFunctionProvider.Destroy; destructor TCustomLuaLEDFunctionProvider.Destroy;
begin begin
inherited Destroy;
FreeAndNil(FInterpreter); FreeAndNil(FInterpreter);
FreeAndNil(FScriptLog); FreeAndNil(FScriptLog);
FreeAndNil(FWorkers); FreeAndNil(FWorkers);
inherited Destroy;
end; end;
@ -189,6 +193,87 @@ begin
end; end;
procedure TCustomLuaLEDFunctionProvider.AppendVariable(ABuilder: TStringBuilder; AVariable: ILuaVariable);
begin
case AVariable.VariableType of
VariableBoolean:
if AVariable.AsBoolean then
ABuilder.Append('true')
else
ABuilder.Append('false');
VariableTable:
AppendTable(ABuilder, AVariable.AsTable);
else
ABuilder.Append(AVariable.AsString);
end;
end;
procedure TCustomLuaLEDFunctionProvider.AppendTable(ABuilder: TStringBuilder; ATable: ILuaTable);
var
firstItem: Boolean;
item: TLuaKeyValuePair;
begin
ABuilder.Append('{ ');
firstItem := True;
for item in ATable do
begin
if firstItem then
firstItem := False
else
ABuilder.Append(', ');
AppendVariable(ABuilder, item.Key);
ABuilder.Append(' = ');
AppendVariable(ABuilder, item.Value);
end;
ABuilder.Append(' }');
end;
procedure TCustomLuaLEDFunctionProvider.DoLog(AContext: ILuaContext; ALevel: TX2LogLevel);
var
msg: TStringBuilder;
parameter: ILuaVariable;
begin
msg := TStringBuilder.Create;
try
for parameter in AContext.Parameters do
begin
AppendVariable(msg, parameter);
msg.Append(' ');
end;
DoLogMessage(AContext, ALevel, msg.ToString);
finally
FreeAndNil(msg);
end;
end;
procedure TCustomLuaLEDFunctionProvider.DoLogMessage(AContext: ILuaContext; ALevel: TX2LogLevel; const AMessage: string);
var
debug: lua_Debug;
fileName: string;
begin
fileName := 'Lua';
if Interpreter.HasState and (lua_getstack(Interpreter.State, 1, debug) <> 0) then
begin
lua_getinfo(Interpreter.State, 'Sl', debug);
fileName := fileName + ' - ' + string(debug.source)
end;
TX2GlobalLog.Log(ALevel, AMessage, filename);
end;
procedure TCustomLuaLEDFunctionProvider.ScriptRegisterFunction(Context: ILuaContext); procedure TCustomLuaLEDFunctionProvider.ScriptRegisterFunction(Context: ILuaContext);
var var
info: ILuaTable; info: ILuaTable;
@ -210,6 +295,7 @@ begin
if not info.HasValue('uid') then if not info.HasValue('uid') then
raise ELuaScriptError.Create('"uid" value is required for RegisterFunction parameter 1'); raise ELuaScriptError.Create('"uid" value is required for RegisterFunction parameter 1');
DoLogMessage(Context, TX2LogLevel.Info, Format('Registering function: %s', [info.GetValue('uid').AsString]));
RegisterFunction(CreateLuaLEDFunction(info, setup)); RegisterFunction(CreateLuaLEDFunction(info, setup));
end; end;
@ -237,6 +323,7 @@ begin
if not Assigned(worker) then if not Assigned(worker) then
raise ELuaScriptError.Create('Context expected for SetState parameter 1'); raise ELuaScriptError.Create('Context expected for SetState parameter 1');
DoLogMessage(Context, TX2LogLevel.Info, Format('Setting state for %s to: %s', [worker.GetFunctionUID, stateUID]));
worker.SetCurrentState(stateUID); worker.SetCurrentState(stateUID);
end; end;
@ -397,108 +484,35 @@ end;
{ TLuaLog } { TLuaLog }
constructor TLuaLog.Create(AInterpreter: TLua); constructor TLuaLog.Create(AOnLog: TLuaLogProc);
begin begin
inherited Create; inherited Create;
FInterpreter := AInterpreter; FOnLog := AOnLog;
end;
procedure TLuaLog.AppendVariable(ABuilder: TStringBuilder; AVariable: ILuaVariable);
begin
case AVariable.VariableType of
VariableBoolean:
if AVariable.AsBoolean then
ABuilder.Append('true')
else
ABuilder.Append('false');
VariableTable:
AppendTable(ABuilder, AVariable.AsTable);
else
ABuilder.Append(AVariable.AsString);
end;
end;
procedure TLuaLog.AppendTable(ABuilder: TStringBuilder; ATable: ILuaTable);
var
firstItem: Boolean;
item: TLuaKeyValuePair;
begin
ABuilder.Append('{ ');
firstItem := True;
for item in ATable do
begin
if firstItem then
firstItem := False
else
ABuilder.Append(', ');
AppendVariable(ABuilder, item.Key);
ABuilder.Append(' = ');
AppendVariable(ABuilder, item.Value);
end;
ABuilder.Append(' }');
end;
procedure TLuaLog.Log(AContext: ILuaContext; ALevel: TX2LogLevel);
var
debug: lua_Debug;
fileName: string;
msg: TStringBuilder;
parameter: ILuaVariable;
begin
fileName := 'Lua';
if Interpreter.HasState and (lua_getstack(Interpreter.State, 1, debug) <> 0) then
begin
lua_getinfo(Interpreter.State, 'Sl', debug);
fileName := fileName + ' - ' + string(debug.source)
end;
msg := TStringBuilder.Create;
try
for parameter in AContext.Parameters do
begin
AppendVariable(msg, parameter);
msg.Append(' ');
end;
TX2GlobalLog.Log(ALevel, msg.ToString, fileName);
finally
FreeAndNil(msg);
end;
end; end;
procedure TLuaLog.Verbose(Context: ILuaContext); procedure TLuaLog.Verbose(Context: ILuaContext);
begin begin
Log(Context, TX2LogLevel.Verbose); OnLog(Context, TX2LogLevel.Verbose);
end; end;
procedure TLuaLog.Info(Context: ILuaContext); procedure TLuaLog.Info(Context: ILuaContext);
begin begin
Log(Context, TX2LogLevel.Info); OnLog(Context, TX2LogLevel.Info);
end; end;
procedure TLuaLog.Warning(Context: ILuaContext); procedure TLuaLog.Warning(Context: ILuaContext);
begin begin
Log(Context, TX2LogLevel.Warning); OnLog(Context, TX2LogLevel.Warning);
end; end;
procedure TLuaLog.Error(Context: ILuaContext); procedure TLuaLog.Error(Context: ILuaContext);
begin begin
Log(Context, TX2LogLevel.Error); OnLog(Context, TX2LogLevel.Error);
end; end;
end. end.