Refactored to single task
This commit is contained in:
parent
3b34cdef39
commit
caec794f3b
@ -15,7 +15,9 @@ uses
|
||||
OtlTaskControl,
|
||||
pngimage,
|
||||
|
||||
CustomLEDStateProvider;
|
||||
LEDFunctionMap,
|
||||
LEDStateConsumer,
|
||||
LEDStateProvider;
|
||||
|
||||
|
||||
type
|
||||
@ -59,10 +61,7 @@ type
|
||||
// procedure tmrG940InitTimer(Sender: TObject);
|
||||
private
|
||||
FEventMonitor: TOmniEventMonitor;
|
||||
FProviderConsumerChannel: IOmniTwoWayChannel;
|
||||
FStateConsumerTask: IOmniTaskControl;
|
||||
FStateProviderWorker: IOmniWorker;
|
||||
FStateProviderTask: IOmniTaskControl;
|
||||
|
||||
// FInitCounter: Integer;
|
||||
// FInitRedState: Byte;
|
||||
@ -70,20 +69,17 @@ type
|
||||
protected
|
||||
procedure SetDeviceState(const AMessage: string; AFound: Boolean);
|
||||
|
||||
procedure InitializeStateProvider(AProviderClass: TCustomLEDStateProviderClass);
|
||||
procedure InitializeStateProvider(AProviderClass: TLEDStateProviderClass);
|
||||
procedure FinalizeStateProvider;
|
||||
|
||||
procedure UpdateMapping;
|
||||
procedure UpdateMappingFSX(AFunctionMap: TLEDFunctionMap);
|
||||
procedure UpdateMappingFSX;
|
||||
|
||||
procedure EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
|
||||
procedure HandleDeviceStateMessage(ATask: IOmniTaskControl; AMessage: TOmniMessage);
|
||||
|
||||
property EventMonitor: TOmniEventMonitor read FEventMonitor;
|
||||
property ProviderConsumerChannel: IOmniTwoWayChannel read FProviderConsumerChannel;
|
||||
property StateConsumerTask: IOmniTaskControl read FStateConsumerTask;
|
||||
property StateProviderWorker: IOmniWorker read FStateProviderWorker;
|
||||
property StateProviderTask: IOmniTaskControl read FStateProviderTask;
|
||||
end;
|
||||
|
||||
|
||||
@ -96,7 +92,7 @@ uses
|
||||
OtlTask,
|
||||
|
||||
FSXLEDStateProvider,
|
||||
LEDStateConsumer;
|
||||
G940LEDStateConsumer;
|
||||
|
||||
|
||||
{$R *.dfm}
|
||||
@ -122,10 +118,9 @@ var
|
||||
|
||||
begin
|
||||
FEventMonitor := TOmniEventMonitor.Create(Self);
|
||||
FProviderConsumerChannel := CreateTwoWayChannel(1024);
|
||||
|
||||
consumer := TG940LEDStateConsumer.Create(ProviderConsumerChannel.Endpoint1);
|
||||
FStateConsumerTask := FEventMonitor.Monitor(CreateTask(consumer));
|
||||
consumer := TG940LEDStateConsumer.Create;
|
||||
FStateConsumerTask := FEventMonitor.Monitor(CreateTask(consumer)).MsgWait;
|
||||
|
||||
// ToDo handle OnTerminate, check exit code for initialization errors
|
||||
EventMonitor.OnTaskMessage := EventMonitorMessage;
|
||||
@ -201,55 +196,32 @@ end;
|
||||
*)
|
||||
|
||||
|
||||
procedure TMainForm.InitializeStateProvider(AProviderClass: TCustomLEDStateProviderClass);
|
||||
begin
|
||||
if Assigned(StateProviderTask) then
|
||||
FinalizeStateProvider;
|
||||
|
||||
FStateProviderWorker := AProviderClass.Create(ProviderConsumerChannel.Endpoint2);
|
||||
FStateProviderTask := CreateTask(StateProviderWorker);
|
||||
|
||||
StateProviderTask.Run;
|
||||
StateProviderTask.WaitForInit;
|
||||
|
||||
procedure TMainForm.InitializeStateProvider(AProviderClass: TLEDStateProviderClass);
|
||||
begin
|
||||
UpdateMapping;
|
||||
TLEDStateConsumer.InitializeStateProvider(StateConsumerTask, AProviderClass);
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.FinalizeStateProvider;
|
||||
begin
|
||||
FStateProviderWorker := nil;
|
||||
|
||||
if Assigned(StateProviderTask) then
|
||||
StateProviderTask.Terminate;
|
||||
|
||||
FStateProviderTask := nil;
|
||||
TLEDStateConsumer.FinalizeStateProvider(StateConsumerTask);
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.UpdateMapping;
|
||||
var
|
||||
provider: TCustomLEDStateProvider;
|
||||
functionMap: TLEDFunctionMap;
|
||||
|
||||
begin
|
||||
if not Assigned(StateProviderWorker) then
|
||||
if not Assigned(StateConsumerTask) then
|
||||
Exit;
|
||||
|
||||
provider := (StateProviderWorker.Implementor as TCustomLEDStateProvider);
|
||||
functionMap := provider.LockFunctionMap;
|
||||
try
|
||||
UpdateMappingFSX(functionMap);
|
||||
finally
|
||||
provider.UnlockFunctionMap;
|
||||
end;
|
||||
TLEDStateConsumer.ClearFunctions(StateConsumerTask);
|
||||
UpdateMappingFSX;
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.UpdateMappingFSX(AFunctionMap: TLEDFunctionMap);
|
||||
procedure TMainForm.UpdateMappingFSX;
|
||||
begin
|
||||
AFunctionMap.Clear;
|
||||
AFunctionMap.SetFunction(4, FUNCTION_FSX_GEAR);
|
||||
TLEDStateConsumer.SetFunction(StateConsumerTask, 3, FUNCTION_FSX_GEAR);
|
||||
end;
|
||||
|
||||
|
||||
@ -279,24 +251,6 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
(*
|
||||
procedure TMainForm.DoStateChange(Sender: TObject; ALEDPosition: Integer; AState: TLEDState);
|
||||
begin
|
||||
if not Assigned(ThrottleDevice) then
|
||||
exit;
|
||||
|
||||
// (MvR) 2-1-2012: dit moet slimmer zodra we lsWarning/lsError willen ondersteunen
|
||||
|
||||
case AState of
|
||||
lsOff: SetButtonColor(ThrottleDevice, TLogiPanelButton(Pred(ALEDPosition)), LOGI_OFF);
|
||||
lsGreen: SetButtonColor(ThrottleDevice, TLogiPanelButton(Pred(ALEDPosition)), LOGI_GREEN);
|
||||
lsAmber: SetButtonColor(ThrottleDevice, TLogiPanelButton(Pred(ALEDPosition)), LOGI_AMBER);
|
||||
lsRed: SetButtonColor(ThrottleDevice, TLogiPanelButton(Pred(ALEDPosition)), LOGI_RED);
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
|
||||
|
||||
procedure TMainForm.btnFSXConnectClick(Sender: TObject);
|
||||
begin
|
||||
InitializeStateProvider(TFSXLEDStateProvider);
|
||||
|
@ -3,9 +3,11 @@ program G940LEDControl;
|
||||
uses
|
||||
Forms,
|
||||
MainFrm in 'Forms\MainFrm.pas' {MainForm},
|
||||
CustomLEDStateProvider in 'Units\CustomLEDStateProvider.pas',
|
||||
FSXLEDStateProvider in 'Units\FSXLEDStateProvider.pas',
|
||||
LEDStateConsumer in 'Units\LEDStateConsumer.pas';
|
||||
LEDStateConsumer in 'Units\LEDStateConsumer.pas',
|
||||
LEDStateProvider in 'Units\LEDStateProvider.pas',
|
||||
LEDFunctionMap in 'Units\LEDFunctionMap.pas',
|
||||
G940LEDStateConsumer in 'Units\G940LEDStateConsumer.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
|
@ -33,106 +33,7 @@
|
||||
<Borland.Personality>Delphi.Personality</Borland.Personality>
|
||||
<Borland.ProjectType />
|
||||
<BorlandProject>
|
||||
<BorlandProject><Delphi.Personality><Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1043</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Source><Source Name="MainSource">G940LEDControl.dpr</Source></Source> <Excluded_Packages>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<BorlandProject><Delphi.Personality><Parameters><Parameters Name="UseLauncher">False</Parameters><Parameters Name="LoadAllSymbols">True</Parameters><Parameters Name="LoadUnspecifiedSymbols">False</Parameters></Parameters><VersionInfo><VersionInfo Name="IncludeVerInfo">False</VersionInfo><VersionInfo Name="AutoIncBuild">False</VersionInfo><VersionInfo Name="MajorVer">1</VersionInfo><VersionInfo Name="MinorVer">0</VersionInfo><VersionInfo Name="Release">0</VersionInfo><VersionInfo Name="Build">0</VersionInfo><VersionInfo Name="Debug">False</VersionInfo><VersionInfo Name="PreRelease">False</VersionInfo><VersionInfo Name="Special">False</VersionInfo><VersionInfo Name="Private">False</VersionInfo><VersionInfo Name="DLL">False</VersionInfo><VersionInfo Name="Locale">1043</VersionInfo><VersionInfo Name="CodePage">1252</VersionInfo></VersionInfo><VersionInfoKeys><VersionInfoKeys Name="CompanyName"></VersionInfoKeys><VersionInfoKeys Name="FileDescription"></VersionInfoKeys><VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="InternalName"></VersionInfoKeys><VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys><VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys><VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys><VersionInfoKeys Name="ProductName"></VersionInfoKeys><VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys><VersionInfoKeys Name="Comments"></VersionInfoKeys></VersionInfoKeys><Source><Source Name="MainSource">G940LEDControl.dpr</Source></Source><Excluded_Packages>
|
||||
|
||||
|
||||
|
||||
@ -508,8 +409,7 @@
|
||||
<Excluded_Packages Name="P:\algemeen\bin\D2007\wpViewPDF_D2007.bpl">WPViewPDF - PDFViewClass</Excluded_Packages>
|
||||
<Excluded_Packages Name="P:\algemeen\bin\D2007\madExceptVcl_.bpl">madExceptVcl 2.0c - www.madshi.net</Excluded_Packages>
|
||||
<Excluded_Packages Name="D:\Program Files\Developer Express.VCL\Library\Delphi11\dclcxPivotGridOLAPD11.bpl">ExpressPivotGrid 2 OLAP by Developer Express Inc.</Excluded_Packages>
|
||||
</Excluded_Packages>
|
||||
</Delphi.Personality></BorlandProject></BorlandProject>
|
||||
</Excluded_Packages></Delphi.Personality></BorlandProject></BorlandProject>
|
||||
</ProjectExtensions>
|
||||
<Import Project="$(MSBuildBinPath)\Borland.Delphi.Targets" />
|
||||
<ItemGroup>
|
||||
@ -519,8 +419,10 @@
|
||||
<DCCReference Include="Forms\MainFrm.pas">
|
||||
<Form>MainForm</Form>
|
||||
</DCCReference>
|
||||
<DCCReference Include="Units\CustomLEDStateProvider.pas" />
|
||||
<DCCReference Include="Units\FSXLEDStateProvider.pas" />
|
||||
<DCCReference Include="Units\G940LEDStateConsumer.pas" />
|
||||
<DCCReference Include="Units\LEDFunctionMap.pas" />
|
||||
<DCCReference Include="Units\LEDStateConsumer.pas" />
|
||||
<DCCReference Include="Units\LEDStateProvider.pas" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,158 +0,0 @@
|
||||
unit CustomLEDStateProvider;
|
||||
|
||||
interface
|
||||
uses
|
||||
Classes,
|
||||
SyncObjs,
|
||||
|
||||
OtlComm,
|
||||
OtlTaskControl;
|
||||
|
||||
const
|
||||
MAX_LEDS = 8;
|
||||
FUNCTION_NONE = 0;
|
||||
|
||||
|
||||
MSG_EXECUTE = 10;
|
||||
MSG_UPDATEFUNCTIONMAP = 11;
|
||||
MSG_SETSTATEBYFUNCTION = 12;
|
||||
|
||||
|
||||
type
|
||||
TLEDState = (lsOff, lsGreen, lsAmber, lsRed, lsWarning, lsError);
|
||||
|
||||
|
||||
// todo implement assign
|
||||
TLEDFunctionMap = class(TPersistent)
|
||||
private
|
||||
FFunctions: array[0..MAX_LEDS - 1] of Integer;
|
||||
|
||||
function GetCount: Integer;
|
||||
public
|
||||
procedure Clear;
|
||||
|
||||
procedure SetFunction(ALEDIndex, AFunction: Integer);
|
||||
function GetFunction(ALEDIndex: Integer): Integer;
|
||||
|
||||
property Count: Integer read GetCount;
|
||||
end;
|
||||
|
||||
|
||||
TCustomLEDStateProvider = class(TOmniWorker)
|
||||
private
|
||||
FConsumerChannel: IOmniCommunicationEndpoint;
|
||||
FFunctionMap: TLEDFunctionMap;
|
||||
FFunctionMapLock: TCriticalSection;
|
||||
FState: array[0..MAX_LEDS - 1] of TLEDState;
|
||||
protected
|
||||
procedure MsgExecute(var msg: TOmniMessage); message MSG_EXECUTE;
|
||||
protected
|
||||
function Initialize: Boolean; override;
|
||||
procedure Execute; virtual; abstract;
|
||||
|
||||
procedure SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
|
||||
property ConsumerChannel: IOmniCommunicationEndpoint read FConsumerChannel;
|
||||
public
|
||||
constructor Create(AConsumerChannel: IOmniCommunicationEndpoint);
|
||||
destructor Destroy; override;
|
||||
|
||||
function LockFunctionMap: TLEDFunctionMap;
|
||||
procedure UnlockFunctionMap;
|
||||
end;
|
||||
|
||||
TCustomLEDStateProviderClass = class of TCustomLEDStateProvider;
|
||||
|
||||
|
||||
implementation
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
|
||||
{ TCustomLEDStateProvider }
|
||||
constructor TCustomLEDStateProvider.Create(AConsumerChannel: IOmniCommunicationEndpoint);
|
||||
var
|
||||
ledIndex: Integer;
|
||||
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
FConsumerChannel := AConsumerChannel;
|
||||
|
||||
FFunctionMap := TLEDFunctionMap.Create;
|
||||
FFunctionMapLock := TCriticalSection.Create;
|
||||
|
||||
for ledIndex := Low(FState) to High(FState) do
|
||||
FState[ledIndex] := lsGreen;
|
||||
end;
|
||||
|
||||
|
||||
destructor TCustomLEDStateProvider.Destroy;
|
||||
begin
|
||||
FreeAndNil(FFunctionMap);
|
||||
FreeAndNil(FFunctionMapLock);
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TCustomLEDStateProvider.Initialize: Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
Task.Comm.OtherEndpoint.Send(MSG_EXECUTE);
|
||||
end;
|
||||
|
||||
function TCustomLEDStateProvider.LockFunctionMap: TLEDFunctionMap;
|
||||
begin
|
||||
FFunctionMapLock.Acquire;
|
||||
Result := FFunctionMap;
|
||||
end;
|
||||
|
||||
|
||||
procedure TCustomLEDStateProvider.UnlockFunctionMap;
|
||||
begin
|
||||
FFunctionMapLock.Release;
|
||||
Task.Comm.Send(MSG_UPDATEFUNCTIONMAP, Self);
|
||||
end;
|
||||
|
||||
|
||||
procedure TCustomLEDStateProvider.SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
begin
|
||||
ConsumerChannel.Send(MSG_SETSTATEBYFUNCTION, [AFunction, Ord(AState)]);
|
||||
end;
|
||||
|
||||
|
||||
procedure TCustomLEDStateProvider.MsgExecute(var msg: TOmniMessage);
|
||||
begin
|
||||
Execute;
|
||||
end;
|
||||
|
||||
|
||||
{ TLEDFunctionMap }
|
||||
procedure TLEDFunctionMap.Clear;
|
||||
var
|
||||
ledPosition: Integer;
|
||||
|
||||
begin
|
||||
for ledPosition := Low(FFunctions) to High(FFunctions) do
|
||||
FFunctions[ledPosition] := FUNCTION_NONE;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDFunctionMap.SetFunction(ALEDIndex, AFunction: Integer);
|
||||
begin
|
||||
FFunctions[ALEDIndex] := AFunction;
|
||||
end;
|
||||
|
||||
|
||||
function TLEDFunctionMap.GetFunction(ALEDIndex: Integer): Integer;
|
||||
begin
|
||||
Result := FFunctions[ALEDIndex];
|
||||
end;
|
||||
|
||||
|
||||
function TLEDFunctionMap.GetCount: Integer;
|
||||
begin
|
||||
Result := Length(FFunctions);
|
||||
end;
|
||||
|
||||
end.
|
@ -4,8 +4,9 @@ interface
|
||||
uses
|
||||
Classes,
|
||||
SyncObjs,
|
||||
|
||||
CustomLEDStateProvider,
|
||||
|
||||
LEDStateConsumer,
|
||||
LEDStateProvider,
|
||||
SimConnect;
|
||||
|
||||
|
||||
@ -17,25 +18,33 @@ const
|
||||
|
||||
|
||||
type
|
||||
TFSXLEDStateProvider = class(TCustomLEDStateProvider)
|
||||
TFSXLEDStateProvider = class(TLEDStateProvider)
|
||||
private
|
||||
FSimConnectHandle: THandle;
|
||||
FUseFunctionGear: Boolean;
|
||||
protected
|
||||
procedure Execute; override;
|
||||
function GetProcessMessagesInterval: Integer; override;
|
||||
|
||||
procedure UpdateMap(AConnection: THandle);
|
||||
procedure SetInitialState;
|
||||
procedure UpdateMap;
|
||||
procedure HandleDispatch(AData: PSimConnectRecv);
|
||||
|
||||
function GetDataDouble(var AData: Cardinal): Double;
|
||||
|
||||
property SimConnectHandle: THandle read FSimConnectHandle;
|
||||
public
|
||||
procedure Initialize; override;
|
||||
procedure Finalize; override;
|
||||
procedure ProcessMessages; override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
uses
|
||||
ComObj,
|
||||
SysUtils;
|
||||
SysUtils,
|
||||
|
||||
LEDFunctionMap;
|
||||
|
||||
|
||||
const
|
||||
@ -52,80 +61,73 @@ const
|
||||
|
||||
|
||||
{ TFSXLEDStateProvider }
|
||||
procedure TFSXLEDStateProvider.Execute;
|
||||
var
|
||||
connection: THandle;
|
||||
data: PSimConnectRecv;
|
||||
dataSize: Cardinal;
|
||||
|
||||
procedure TFSXLEDStateProvider.Initialize;
|
||||
begin
|
||||
if not InitSimConnect then
|
||||
raise EInitializeError.Create('SimConnect.dll could not be loaded', EXIT_ERROR_INITSIMCONNECT);
|
||||
|
||||
if SimConnect_Open(FSimConnectHandle, APPNAME, 0, 0, 0, 0) <> S_OK then
|
||||
raise EInitializeError.Create('Connection to Flight Simulator could not be established', EXIT_ERROR_CONNECT);
|
||||
|
||||
UpdateMap;
|
||||
SetInitialState;
|
||||
end;
|
||||
|
||||
|
||||
procedure TFSXLEDStateProvider.Finalize;
|
||||
begin
|
||||
inherited;
|
||||
|
||||
if SimConnectHandle <> 0 then
|
||||
begin
|
||||
Task.SetExitStatus(EXIT_ERROR_INITSIMCONNECT, 'SimConnect.dll could not be loaded');
|
||||
Task.Terminate;
|
||||
exit;
|
||||
end;
|
||||
|
||||
if SimConnect_Open(connection, APPNAME, 0, 0, 0, 0) = S_OK then
|
||||
try
|
||||
UpdateMap(connection);
|
||||
|
||||
while not Task.Terminated do
|
||||
begin
|
||||
if SimConnect_GetNextDispatch(connection, data, dataSize) = S_OK then
|
||||
HandleDispatch(data);
|
||||
|
||||
ProcessMessages;
|
||||
Sleep(1);
|
||||
end;
|
||||
finally
|
||||
SimConnect_Close(connection);
|
||||
end else
|
||||
begin
|
||||
Task.SetExitStatus(EXIT_ERROR_CONNECT, 'Connection to Flight Simulator could not be established');
|
||||
Task.Terminate;
|
||||
SimConnect_Close(SimConnectHandle);
|
||||
FSimConnectHandle := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TFSXLEDStateProvider.UpdateMap(AConnection: THandle);
|
||||
procedure TFSXLEDStateProvider.ProcessMessages;
|
||||
var
|
||||
functionMap: TLEDFunctionMap;
|
||||
data: PSimConnectRecv;
|
||||
dataSize: Cardinal;
|
||||
|
||||
function HasFunction(AFunction: Integer): Boolean;
|
||||
var
|
||||
ledIndex: Integer;
|
||||
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
for ledIndex := 0 to Pred(functionMap.Count) do
|
||||
if functionMap.GetFunction(ledIndex) = AFunction then
|
||||
begin
|
||||
Result := True;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
SimConnect_ClearDataDefinition(AConnection, DEFINITION_GEAR);
|
||||
inherited;
|
||||
|
||||
functionMap := LockFunctionMap;
|
||||
try
|
||||
if HasFunction(FUNCTION_FSX_GEAR) then
|
||||
begin
|
||||
SimConnect_AddToDataDefinition(AConnection, DEFINITION_GEAR,
|
||||
FSX_VARIABLE_GEARTOTALPCTEXTENDED,
|
||||
FSX_UNIT_PERCENT);
|
||||
SimConnect_RequestDataOnSimObject(AConnection, REQUEST_GEAR,
|
||||
DEFINITION_GEAR,
|
||||
SIMCONNECT_OBJECT_ID_USER,
|
||||
SIMCONNECT_PERIOD_SIM_FRAME,
|
||||
SIMCONNECT_DATA_REQUEST_FLAG_CHANGED);
|
||||
end;
|
||||
finally
|
||||
UnlockFunctionMap;
|
||||
while SimConnect_GetNextDispatch(SimConnectHandle, data, dataSize) = S_OK do
|
||||
HandleDispatch(data);
|
||||
end;
|
||||
|
||||
|
||||
procedure TFSXLEDStateProvider.SetInitialState;
|
||||
begin
|
||||
// if FUseFunctionGear then
|
||||
// begin
|
||||
// SimConnect_RequestDataOnSimObject(SimConnectHandle, REQUEST_GEAR,
|
||||
// DEFINITION_GEAR,
|
||||
// SIMCONNECT_OBJECT_ID_USER,
|
||||
// SIMCONNECT_PERIOD_ONCE,
|
||||
// SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT);
|
||||
// end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TFSXLEDStateProvider.UpdateMap;
|
||||
begin
|
||||
if FUseFunctionGear then
|
||||
SimConnect_ClearDataDefinition(SimConnectHandle, DEFINITION_GEAR);
|
||||
|
||||
FUseFunctionGear := Consumer.FunctionMap.HasFunction(FUNCTION_FSX_GEAR);
|
||||
if FUseFunctionGear then
|
||||
begin
|
||||
SimConnect_AddToDataDefinition(SimConnectHandle, DEFINITION_GEAR,
|
||||
FSX_VARIABLE_GEARTOTALPCTEXTENDED,
|
||||
FSX_UNIT_PERCENT);
|
||||
SimConnect_RequestDataOnSimObject(SimConnectHandle, REQUEST_GEAR,
|
||||
DEFINITION_GEAR,
|
||||
SIMCONNECT_OBJECT_ID_USER,
|
||||
SIMCONNECT_PERIOD_SECOND,
|
||||
SIMCONNECT_DATA_REQUEST_FLAG_CHANGED);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -144,16 +146,16 @@ begin
|
||||
REQUEST_GEAR:
|
||||
begin
|
||||
case Trunc(GetDataDouble(simObjectData^.dwData) * 100) of
|
||||
0: SetStateByFunction(FUNCTION_FSX_GEAR, lsRed);
|
||||
100: SetStateByFunction(FUNCTION_FSX_GEAR, lsGreen);
|
||||
else SetStateByFunction(FUNCTION_FSX_GEAR, lsAmber);
|
||||
0: Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsRed);
|
||||
100: Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsGreen);
|
||||
else Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsAmber);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
SIMCONNECT_RECV_ID_QUIT:
|
||||
Task.Terminate;
|
||||
Terminate;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -163,4 +165,10 @@ begin
|
||||
Result := PDouble(@AData)^;
|
||||
end;
|
||||
|
||||
|
||||
function TFSXLEDStateProvider.GetProcessMessagesInterval: Integer;
|
||||
begin
|
||||
Result := 50;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
190
G940LEDControl/Units/G940LEDStateConsumer.pas
Normal file
190
G940LEDControl/Units/G940LEDStateConsumer.pas
Normal file
@ -0,0 +1,190 @@
|
||||
unit G940LEDStateConsumer;
|
||||
|
||||
interface
|
||||
uses
|
||||
Classes,
|
||||
|
||||
DirectInput,
|
||||
OtlComm,
|
||||
OtlTaskControl,
|
||||
|
||||
LEDFunctionMap,
|
||||
LEDStateConsumer;
|
||||
|
||||
|
||||
const
|
||||
MSG_FINDTHROTTLEDEVICE = MSG_CONSUMER_OFFSET + 1;
|
||||
|
||||
|
||||
type
|
||||
TG940LEDStateConsumer = class(TLEDStateConsumer)
|
||||
private
|
||||
FDirectInput: IDirectInput8;
|
||||
FThrottleDevice: IDirectInputDevice8;
|
||||
protected
|
||||
procedure MsgFindThrottleDevice(var msg: TOmniMessage); message MSG_FINDTHROTTLEDEVICE;
|
||||
protected
|
||||
function Initialize: Boolean; override;
|
||||
procedure LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); override;
|
||||
|
||||
procedure FindThrottleDevice;
|
||||
procedure FoundThrottleDevice(ADeviceGUID: TGUID);
|
||||
|
||||
procedure SetDeviceState(AState: Integer);
|
||||
|
||||
property DirectInput: IDirectInput8 read FDirectInput;
|
||||
property ThrottleDevice: IDirectInputDevice8 read FThrottleDevice;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
MSG_NOTIFY_DEVICESTATE = 1;
|
||||
|
||||
DEVICESTATE_SEARCHING = 0;
|
||||
DEVICESTATE_FOUND = 1;
|
||||
DEVICESTATE_NOTFOUND = 2;
|
||||
|
||||
EXIT_ERROR_LOGIJOYSTICKDLL = 1;
|
||||
EXIT_ERROR_DIRECTINPUT = 2;
|
||||
|
||||
|
||||
implementation
|
||||
uses
|
||||
SysUtils,
|
||||
Windows,
|
||||
|
||||
LogiJoystickDLL;
|
||||
|
||||
|
||||
function EnumDevicesProc(var lpddi: TDIDeviceInstanceA; pvRef: Pointer): BOOL; stdcall;
|
||||
var
|
||||
vendorID: Word;
|
||||
productID: Word;
|
||||
|
||||
begin
|
||||
Result := True;
|
||||
|
||||
vendorID := LOWORD(lpddi.guidProduct.D1);
|
||||
productID := HIWORD(lpddi.guidProduct.D1);
|
||||
|
||||
if (vendorID = VENDOR_LOGITECH) and
|
||||
(productID = PRODUCT_G940_THROTTLE) then
|
||||
begin
|
||||
TG940LEDStateConsumer(pvRef).FoundThrottleDevice(lpddi.guidInstance);
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ TG940LEDStateConsumer }
|
||||
function TG940LEDStateConsumer.Initialize: Boolean;
|
||||
begin
|
||||
Result := inherited Initialize;
|
||||
if not Result then
|
||||
exit;
|
||||
|
||||
Result := False;
|
||||
|
||||
if not LogiJoystickDLLInitialized then
|
||||
begin
|
||||
Task.SetExitStatus(EXIT_ERROR_LOGIJOYSTICKDLL, 'Could not load LogiJoystickDLL.dll');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// btnRetry.Visible := False;
|
||||
// SetState(STATE_SEARCHING, False);
|
||||
|
||||
if DirectInput8Create(SysInit.HInstance, DIRECTINPUT_VERSION, IDirectInput8, FDirectInput, nil) <> S_OK then
|
||||
begin
|
||||
Task.SetExitStatus(EXIT_ERROR_DIRECTINPUT, 'Failed to initialize DirectInput');
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
Task.Comm.OtherEndpoint.Send(MSG_FINDTHROTTLEDEVICE);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.LEDStateChanged(ALEDIndex: Integer; AState: TLEDState);
|
||||
var
|
||||
color: TLogiColor;
|
||||
|
||||
begin
|
||||
// ToDo SetLEDs gebruiken (vereist override van SetStateByFunction om te groeperen)
|
||||
if Assigned(ThrottleDevice) then
|
||||
begin
|
||||
color := LOGI_GREEN;
|
||||
|
||||
case AState of
|
||||
lsOff: color := LOGI_OFF;
|
||||
lsGreen: color := LOGI_GREEN;
|
||||
lsAmber: color := LOGI_AMBER;
|
||||
lsRed: color := LOGI_RED;
|
||||
|
||||
// ToDo timers voor warning / error
|
||||
lsWarning: color := LOGI_RED;
|
||||
lsError: color := LOGI_RED;
|
||||
end;
|
||||
|
||||
SetButtonColor(ThrottleDevice, TLogiPanelButton(ALEDIndex), color);
|
||||
ProcessMessages;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.FindThrottleDevice;
|
||||
begin
|
||||
SetDeviceState(DEVICESTATE_SEARCHING);
|
||||
DirectInput.EnumDevices(DI8DEVCLASS_GAMECTRL,
|
||||
EnumDevicesProc,
|
||||
Pointer(Self),
|
||||
DIEDFL_ATTACHEDONLY);
|
||||
|
||||
if not Assigned(ThrottleDevice) then
|
||||
SetDeviceState(DEVICESTATE_NOTFOUND);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.FoundThrottleDevice(ADeviceGUID: TGUID);
|
||||
begin
|
||||
if DirectInput.CreateDevice(ADeviceGUID, FThrottleDevice, nil) = S_OK then
|
||||
SetDeviceState(DEVICESTATE_FOUND);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.SetDeviceState(AState: Integer);
|
||||
begin
|
||||
Task.Comm.Send(MSG_NOTIFY_DEVICESTATE, AState);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.MsgFindThrottleDevice(var msg: TOmniMessage);
|
||||
begin
|
||||
FindThrottleDevice;
|
||||
end;
|
||||
|
||||
|
||||
//procedure TCustomLEDStateProvider.SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
//var
|
||||
// functionMap: TLEDFunctionMap;
|
||||
// ledIndex: Integer;
|
||||
//
|
||||
//begin
|
||||
// functionMap := LockFunctionMap;
|
||||
// try
|
||||
// for ledIndex := 0 to Pred(functionMap.Count) do
|
||||
// if functionMap.GetFunction(ledIndex) = AFunction then
|
||||
// begin
|
||||
// if AState <> FState[ledIndex] then
|
||||
// begin
|
||||
// FState[ledIndex] := AState;
|
||||
// ConsumerChannel.Send(MSG_STATECHANGED, [ledIndex, Ord(AState)]);
|
||||
// end;
|
||||
// end;
|
||||
// finally
|
||||
// UnlockFunctionMap;
|
||||
// end;
|
||||
//end;
|
||||
|
||||
end.
|
174
G940LEDControl/Units/LEDFunctionMap.pas
Normal file
174
G940LEDControl/Units/LEDFunctionMap.pas
Normal file
@ -0,0 +1,174 @@
|
||||
unit LEDFunctionMap;
|
||||
|
||||
interface
|
||||
uses
|
||||
Classes,
|
||||
SyncObjs,
|
||||
|
||||
X2UtHashes;
|
||||
|
||||
|
||||
type
|
||||
TLEDState = (lsOff, lsGreen, lsAmber, lsRed, lsWarning, lsError);
|
||||
|
||||
TLEDFunctionMap = class(TObject)
|
||||
private
|
||||
FFunctions: TX2IIHash;
|
||||
protected
|
||||
function Find(AFunction: Integer; out ALEDIndex: Integer): Boolean;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Clear;
|
||||
|
||||
procedure SetFunction(ALEDIndex, AFunction: Integer);
|
||||
function GetFunction(ALEDIndex: Integer): Integer;
|
||||
|
||||
function HasFunction(AFunction: Integer): Boolean;
|
||||
|
||||
function FindFirst(AFunction: Integer; out ALEDIndex: Integer): Boolean;
|
||||
function FindNext(AFunction: Integer; out ALEDIndex: Integer): Boolean;
|
||||
end;
|
||||
|
||||
|
||||
TLEDStateMap = class(TObject)
|
||||
private
|
||||
FStates: TX2IIHash;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Clear;
|
||||
|
||||
function GetState(ALEDIndex: Integer; ADefault: TLEDState = lsGreen): TLEDState;
|
||||
function SetState(ALEDIndex: Integer; AState: TLEDState): Boolean;
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
FUNCTION_NONE = 0;
|
||||
|
||||
|
||||
implementation
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
|
||||
{ TLEDFunctionMap }
|
||||
constructor TLEDFunctionMap.Create;
|
||||
begin
|
||||
inherited;
|
||||
|
||||
FFunctions := TX2IIHash.Create;
|
||||
end;
|
||||
|
||||
|
||||
destructor TLEDFunctionMap.Destroy;
|
||||
begin
|
||||
FreeAndNil(FFunctions);
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDFunctionMap.Clear;
|
||||
begin
|
||||
FFunctions.Clear;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDFunctionMap.SetFunction(ALEDIndex, AFunction: Integer);
|
||||
begin
|
||||
FFunctions[ALEDIndex] := AFunction;
|
||||
end;
|
||||
|
||||
|
||||
function TLEDFunctionMap.GetFunction(ALEDIndex: Integer): Integer;
|
||||
begin
|
||||
Result := FFunctions[ALEDIndex];
|
||||
end;
|
||||
|
||||
|
||||
function TLEDFunctionMap.HasFunction(AFunction: Integer): Boolean;
|
||||
var
|
||||
ledIndex: Integer;
|
||||
|
||||
begin
|
||||
Result := FindFirst(AFunction, ledIndex);
|
||||
end;
|
||||
|
||||
|
||||
function TLEDFunctionMap.FindFirst(AFunction: Integer; out ALEDIndex: Integer): Boolean;
|
||||
begin
|
||||
FFunctions.First;
|
||||
Result := Find(AFunction, ALEDIndex);
|
||||
end;
|
||||
|
||||
|
||||
function TLEDFunctionMap.FindNext(AFunction: Integer; out ALEDIndex: Integer): Boolean;
|
||||
begin
|
||||
Result := Find(AFunction, ALEDIndex);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function TLEDFunctionMap.Find(AFunction: Integer; out ALEDIndex: Integer): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
while FFunctions.Next do
|
||||
begin
|
||||
if FFunctions.CurrentValue = AFunction then
|
||||
begin
|
||||
ALEDIndex := FFunctions.CurrentKey;
|
||||
Result := True;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ TLEDStateMap }
|
||||
constructor TLEDStateMap.Create;
|
||||
begin
|
||||
inherited;
|
||||
|
||||
FStates := TX2IIHash.Create;
|
||||
end;
|
||||
|
||||
|
||||
destructor TLEDStateMap.Destroy;
|
||||
begin
|
||||
FreeAndNil(FStates);
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateMap.Clear;
|
||||
begin
|
||||
FStates.Clear;
|
||||
end;
|
||||
|
||||
|
||||
function TLEDStateMap.GetState(ALEDIndex: Integer; ADefault: TLEDState): TLEDState;
|
||||
begin
|
||||
Result := ADefault;
|
||||
if FStates.Exists(ALEDIndex) then
|
||||
Result := TLEDState(FStates[ALEDIndex]);
|
||||
end;
|
||||
|
||||
|
||||
function TLEDStateMap.SetState(ALEDIndex: Integer; AState: TLEDState): Boolean;
|
||||
begin
|
||||
if FStates.Exists(ALEDIndex) then
|
||||
Result := (FStates[ALEDIndex] <> Ord(AState))
|
||||
else
|
||||
Result := True;
|
||||
|
||||
if Result then
|
||||
FStates[ALEDIndex] := Ord(AState);
|
||||
end;
|
||||
|
||||
end.
|
@ -2,202 +2,204 @@ unit LEDStateConsumer;
|
||||
|
||||
interface
|
||||
uses
|
||||
DirectInput,
|
||||
OtlComm,
|
||||
OtlTaskControl,
|
||||
|
||||
CustomLEDStateProvider;
|
||||
LEDFunctionMap,
|
||||
LEDStateProvider;
|
||||
|
||||
|
||||
const
|
||||
MSG_CLEAR_FUNCTIONS = 1;
|
||||
MSG_SET_FUNCTION = 2;
|
||||
MSG_INITIALIZE_PROVIDER = 3;
|
||||
MSG_FINALIZE_PROVIDER = 4;
|
||||
MSG_PROCESS_MESSAGES = 5;
|
||||
|
||||
MSG_CONSUMER_OFFSET = MSG_PROCESS_MESSAGES;
|
||||
|
||||
TIMER_PROCESSMESSAGES = 1;
|
||||
|
||||
|
||||
const
|
||||
MSG_FINDTHROTTLEDEVICE = 1;
|
||||
MSG_NOTIFY_DEVICESTATE = 2;
|
||||
|
||||
|
||||
type
|
||||
TG940LEDStateConsumer = class(TOmniWorker)
|
||||
TLEDStateConsumer = class(TOmniWorker, ILEDStateConsumer)
|
||||
private
|
||||
FProviderChannel: IOmniCommunicationEndpoint;
|
||||
FDirectInput: IDirectInput8;
|
||||
FThrottleDevice: IDirectInputDevice8;
|
||||
FFunctionMap: TLEDFunctionMap;
|
||||
FStateMap: TLEDStateMap;
|
||||
FProvider: TLEDStateProvider;
|
||||
FTimerSet: Boolean;
|
||||
protected
|
||||
procedure MsgFindThrottleDevice(var msg: TOmniMessage); message MSG_FINDTHROTTLEDEVICE;
|
||||
procedure MsgUpdateFunctionMap(var msg: TOmniMessage); message MSG_UPDATEFUNCTIONMAP;
|
||||
procedure MsgSetStateByFunction(var msg: TOmniMessage); message MSG_SETSTATEBYFUNCTION;
|
||||
protected
|
||||
function Initialize: Boolean; override;
|
||||
procedure MsgClearFunctions(var msg: TOmniMessage); message MSG_CLEAR_FUNCTIONS;
|
||||
procedure MsgSetFunction(var msg: TOmniMessage); message MSG_SET_FUNCTION;
|
||||
procedure MsgInitializeProvider(var msg: TOmniMessage); message MSG_INITIALIZE_PROVIDER;
|
||||
procedure MsgFinalizeProvider(var msg: TOmniMessage); message MSG_FINALIZE_PROVIDER;
|
||||
procedure MsgProcessMessages(var msg: TOmniMessage); message MSG_PROCESS_MESSAGES;
|
||||
|
||||
procedure FindThrottleDevice;
|
||||
procedure FoundThrottleDevice(ADeviceGUID: TGUID);
|
||||
procedure InitializeProvider(AProviderClass: TLEDStateProviderClass);
|
||||
procedure FinalizeProvider;
|
||||
|
||||
procedure SetDeviceState(AState: Integer);
|
||||
procedure LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); virtual;
|
||||
|
||||
property DirectInput: IDirectInput8 read FDirectInput;
|
||||
property ThrottleDevice: IDirectInputDevice8 read FThrottleDevice;
|
||||
{ ILEDStateConsumer }
|
||||
function GetFunctionMap: TLEDFunctionMap;
|
||||
procedure SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
|
||||
property FunctionMap: TLEDFunctionMap read GetFunctionMap;
|
||||
property StateMap: TLEDStateMap read FStateMap;
|
||||
property Provider: TLEDStateProvider read FProvider;
|
||||
public
|
||||
constructor Create(AProviderChannel: IOmniCommunicationEndpoint);
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
|
||||
class procedure ClearFunctions(AConsumer: IOmniTaskControl);
|
||||
class procedure SetFunction(AConsumer: IOmniTaskControl; ALEDIndex, AFunction: Integer);
|
||||
class procedure InitializeStateProvider(AConsumer: IOmniTaskControl; AProviderClass: TLEDStateProviderClass);
|
||||
class procedure FinalizeStateProvider(AConsumer: IOmniTaskControl);
|
||||
end;
|
||||
|
||||
|
||||
const
|
||||
EXIT_ERROR_LOGIJOYSTICKDLL = 1;
|
||||
EXIT_ERROR_DIRECTINPUT = 2;
|
||||
|
||||
|
||||
DEVICESTATE_SEARCHING = 0;
|
||||
DEVICESTATE_FOUND = 1;
|
||||
DEVICESTATE_NOTFOUND = 2;
|
||||
|
||||
|
||||
implementation
|
||||
uses
|
||||
SysUtils,
|
||||
Windows,
|
||||
|
||||
LogiJoystickDLL;
|
||||
OtlCommon;
|
||||
|
||||
|
||||
function EnumDevicesProc(var lpddi: TDIDeviceInstanceA; pvRef: Pointer): BOOL; stdcall;
|
||||
var
|
||||
vendorID: Word;
|
||||
productID: Word;
|
||||
|
||||
{ TLEDStateConsumer }
|
||||
constructor TLEDStateConsumer.Create;
|
||||
begin
|
||||
Result := True;
|
||||
inherited;
|
||||
|
||||
vendorID := LOWORD(lpddi.guidProduct.D1);
|
||||
productID := HIWORD(lpddi.guidProduct.D1);
|
||||
|
||||
if (vendorID = VENDOR_LOGITECH) and
|
||||
(productID = PRODUCT_G940_THROTTLE) then
|
||||
begin
|
||||
TG940LEDStateConsumer(pvRef).FoundThrottleDevice(lpddi.guidInstance);
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ TG940LEDStateConsumer }
|
||||
constructor TG940LEDStateConsumer.Create(AProviderChannel: IOmniCommunicationEndpoint);
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
FProviderChannel := AProviderChannel;
|
||||
FFunctionMap := TLEDFunctionMap.Create;
|
||||
FStateMap := TLEDStateMap.Create;
|
||||
end;
|
||||
|
||||
|
||||
destructor TG940LEDStateConsumer.Destroy;
|
||||
destructor TLEDStateConsumer.Destroy;
|
||||
begin
|
||||
FinalizeProvider;
|
||||
|
||||
FreeAndNil(FStateMap);
|
||||
FreeAndNil(FFunctionMap);
|
||||
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
function TG940LEDStateConsumer.Initialize: Boolean;
|
||||
function TLEDStateConsumer.GetFunctionMap: TLEDFunctionMap;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
if not LogiJoystickDLLInitialized then
|
||||
begin
|
||||
Task.SetExitStatus(EXIT_ERROR_LOGIJOYSTICKDLL, 'Could not load LogiJoystickDLL.dll');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// btnRetry.Visible := False;
|
||||
// SetState(STATE_SEARCHING, False);
|
||||
|
||||
if DirectInput8Create(SysInit.HInstance, DIRECTINPUT_VERSION, IDirectInput8, FDirectInput, nil) <> S_OK then
|
||||
begin
|
||||
Task.SetExitStatus(EXIT_ERROR_DIRECTINPUT, 'Failed to initialize DirectInput');
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := True;
|
||||
|
||||
Task.RegisterComm(FProviderChannel);
|
||||
FindThrottleDevice;
|
||||
Result := FFunctionMap;
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.FindThrottleDevice;
|
||||
begin
|
||||
SetDeviceState(DEVICESTATE_SEARCHING);
|
||||
DirectInput.EnumDevices(DI8DEVCLASS_GAMECTRL,
|
||||
EnumDevicesProc,
|
||||
Pointer(Self),
|
||||
DIEDFL_ATTACHEDONLY);
|
||||
|
||||
if not Assigned(ThrottleDevice) then
|
||||
SetDeviceState(DEVICESTATE_NOTFOUND);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.FoundThrottleDevice(ADeviceGUID: TGUID);
|
||||
begin
|
||||
if DirectInput.CreateDevice(ADeviceGUID, FThrottleDevice, nil) = S_OK then
|
||||
SetDeviceState(DEVICESTATE_FOUND);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.SetDeviceState(AState: Integer);
|
||||
begin
|
||||
Task.Comm.Send(MSG_NOTIFY_DEVICESTATE, AState);
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.MsgFindThrottleDevice(var msg: TOmniMessage);
|
||||
begin
|
||||
FindThrottleDevice;
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.MsgUpdateFunctionMap(var msg: TOmniMessage);
|
||||
procedure TLEDStateConsumer.SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
var
|
||||
provider: TCustomLEDStateProvider;
|
||||
functionMap: TLEDFunctionMap;
|
||||
ledIndex: Integer;
|
||||
|
||||
begin
|
||||
provider := (msg.MsgData.AsObject as TCustomLEDStateProvider);
|
||||
functionMap := provider.LockFunctionMap;
|
||||
try
|
||||
FFunctionMap.Assign(functionMap);
|
||||
finally
|
||||
provider.UnlockFunctionMap;
|
||||
if FunctionMap.FindFirst(AFunction, ledIndex) then
|
||||
repeat
|
||||
if StateMap.SetState(ledIndex, AState) then
|
||||
LEDStateChanged(ledIndex, AState);
|
||||
until not FunctionMap.FindNext(AFunction, ledIndex);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure TLEDStateConsumer.MsgClearFunctions(var msg: TOmniMessage);
|
||||
begin
|
||||
FunctionMap.Clear;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateConsumer.MsgSetFunction(var msg: TOmniMessage);
|
||||
var
|
||||
values: TOmniValueContainer;
|
||||
|
||||
begin
|
||||
values := msg.MsgData.AsArray;
|
||||
FunctionMap.SetFunction(values[0], values[1]);
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateConsumer.MsgInitializeProvider(var msg: TOmniMessage);
|
||||
begin
|
||||
InitializeProvider(TLEDStateProviderClass(msg.MsgData.AsPointer));
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateConsumer.MsgFinalizeProvider(var msg: TOmniMessage);
|
||||
begin
|
||||
FinalizeProvider;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateConsumer.MsgProcessMessages(var msg: TOmniMessage);
|
||||
begin
|
||||
Provider.ProcessMessages;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateConsumer.InitializeProvider(AProviderClass: TLEDStateProviderClass);
|
||||
begin
|
||||
FinalizeProvider;
|
||||
|
||||
FProvider := AProviderClass.Create(Self);
|
||||
// ToDo exception handlign
|
||||
Provider.Initialize;
|
||||
|
||||
if Provider.ProcessMessagesInterval > -1 then
|
||||
begin
|
||||
Task.SetTimer(TIMER_PROCESSMESSAGES, Provider.ProcessMessagesInterval, MSG_PROCESS_MESSAGES);
|
||||
FTimerSet := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TG940LEDStateConsumer.MsgSetStateByFunction(var msg: TOmniMessage);
|
||||
procedure TLEDStateConsumer.FinalizeProvider;
|
||||
begin
|
||||
//
|
||||
if Assigned(Provider) then
|
||||
begin
|
||||
if FTimerSet then
|
||||
begin
|
||||
Task.ClearTimer(TIMER_PROCESSMESSAGES);
|
||||
FTimerSet := False;
|
||||
end;
|
||||
|
||||
Provider.Terminate;
|
||||
Provider.Finalize;
|
||||
FreeAndNil(FProvider);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
//procedure TCustomLEDStateProvider.SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
//var
|
||||
// functionMap: TLEDFunctionMap;
|
||||
// ledIndex: Integer;
|
||||
//
|
||||
//begin
|
||||
// functionMap := LockFunctionMap;
|
||||
// try
|
||||
// for ledIndex := 0 to Pred(functionMap.Count) do
|
||||
// if functionMap.GetFunction(ledIndex) = AFunction then
|
||||
// begin
|
||||
// if AState <> FState[ledIndex] then
|
||||
// begin
|
||||
// FState[ledIndex] := AState;
|
||||
// ConsumerChannel.Send(MSG_STATECHANGED, [ledIndex, Ord(AState)]);
|
||||
// end;
|
||||
// end;
|
||||
// finally
|
||||
// UnlockFunctionMap;
|
||||
// end;
|
||||
//end;
|
||||
procedure TLEDStateConsumer.LEDStateChanged(ALEDIndex: Integer; AState: TLEDState);
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
class procedure TLEDStateConsumer.ClearFunctions(AConsumer: IOmniTaskControl);
|
||||
begin
|
||||
AConsumer.Comm.Send(MSG_CLEAR_FUNCTIONS);
|
||||
end;
|
||||
|
||||
|
||||
class procedure TLEDStateConsumer.SetFunction(AConsumer: IOmniTaskControl; ALEDIndex, AFunction: Integer);
|
||||
begin
|
||||
AConsumer.Comm.Send(MSG_SET_FUNCTION, [ALEDIndex, AFunction]);
|
||||
end;
|
||||
|
||||
|
||||
class procedure TLEDStateConsumer.InitializeStateProvider(AConsumer: IOmniTaskControl; AProviderClass: TLEDStateProviderClass);
|
||||
begin
|
||||
AConsumer.Comm.Send(MSG_INITIALIZE_PROVIDER, Pointer(AProviderClass));
|
||||
end;
|
||||
|
||||
|
||||
class procedure TLEDStateConsumer.FinalizeStateProvider(AConsumer: IOmniTaskControl);
|
||||
begin
|
||||
AConsumer.Comm.Send(MSG_FINALIZE_PROVIDER);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
111
G940LEDControl/Units/LEDStateProvider.pas
Normal file
111
G940LEDControl/Units/LEDStateProvider.pas
Normal file
@ -0,0 +1,111 @@
|
||||
unit LEDStateProvider;
|
||||
|
||||
interface
|
||||
uses
|
||||
Classes,
|
||||
SyncObjs,
|
||||
SysUtils,
|
||||
|
||||
LEDFunctionMap;
|
||||
|
||||
type
|
||||
EInitializeError = class(Exception)
|
||||
private
|
||||
FExitCode: Integer;
|
||||
public
|
||||
constructor Create(const Msg: string; ExitCode: Integer = 0);
|
||||
|
||||
property ExitCode: Integer read FExitCode write FExitCode;
|
||||
end;
|
||||
|
||||
|
||||
ILEDStateConsumer = interface
|
||||
['{6E630C92-7C5C-4D16-8BED-AE27559FA584}']
|
||||
function GetFunctionMap: TLEDFunctionMap;
|
||||
procedure SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
||||
|
||||
property FunctionMap: TLEDFunctionMap read GetFunctionMap;
|
||||
end;
|
||||
|
||||
|
||||
TLEDStateProvider = class(TObject)
|
||||
private
|
||||
FConsumer: ILEDStateConsumer;
|
||||
FTerminated: Boolean;
|
||||
protected
|
||||
procedure Execute; virtual; abstract;
|
||||
|
||||
function GetProcessMessagesInterval: Integer; virtual;
|
||||
|
||||
property Consumer: ILEDStateConsumer read FConsumer;
|
||||
public
|
||||
constructor Create(AConsumer: ILEDStateConsumer);
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure Initialize; virtual;
|
||||
procedure Finalize; virtual;
|
||||
procedure ProcessMessages; virtual;
|
||||
|
||||
procedure Terminate; virtual;
|
||||
|
||||
property ProcessMessagesInterval: Integer read GetProcessMessagesInterval;
|
||||
property Terminated: Boolean read FTerminated;
|
||||
end;
|
||||
|
||||
TLEDStateProviderClass = class of TLEDStateProvider;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{ TCustomLEDStateProvider }
|
||||
constructor TLEDStateProvider.Create(AConsumer: ILEDStateConsumer);
|
||||
begin
|
||||
inherited Create;
|
||||
|
||||
FConsumer := AConsumer;
|
||||
end;
|
||||
|
||||
|
||||
destructor TLEDStateProvider.Destroy;
|
||||
begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateProvider.Initialize;
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateProvider.Finalize;
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateProvider.ProcessMessages;
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TLEDStateProvider.Terminate;
|
||||
begin
|
||||
FTerminated := True;
|
||||
end;
|
||||
|
||||
|
||||
function TLEDStateProvider.GetProcessMessagesInterval: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
end;
|
||||
|
||||
|
||||
{ EInitializeError }
|
||||
constructor EInitializeError.Create(const Msg: string; ExitCode: Integer);
|
||||
begin
|
||||
inherited Create(Msg);
|
||||
|
||||
FExitCode := ExitCode;
|
||||
end;
|
||||
|
||||
end.
|
Loading…
Reference in New Issue
Block a user