From 84aeb8daa273ff6ff1b8752c3065ba57341b3509 Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Wed, 4 Jan 2012 22:22:51 +0000 Subject: [PATCH] Fixed LEDs not changing color Implemented landing/instrument lights and parking brake functions --- G940LEDControl/Forms/MainFrm.dfm | 12 +-- G940LEDControl/Forms/MainFrm.pas | 14 ++- G940LEDControl/Units/FSXLEDStateProvider.pas | 85 +++++++++++++++++-- G940LEDControl/Units/G940LEDStateConsumer.pas | 39 +++++++-- G940LEDControl/Units/LEDStateConsumer.pas | 21 ++++- 5 files changed, 151 insertions(+), 20 deletions(-) diff --git a/G940LEDControl/Forms/MainFrm.dfm b/G940LEDControl/Forms/MainFrm.dfm index 03501ef..f006fba 100644 --- a/G940LEDControl/Forms/MainFrm.dfm +++ b/G940LEDControl/Forms/MainFrm.dfm @@ -137,9 +137,9 @@ object MainForm: TMainForm ItemHeight = 13 ItemIndex = 0 TabOrder = 1 - Text = '' + Text = 'Parking brake' Items.Strings = ( - '') + 'Parking brake') end object cmbFSXP3: TComboBox Left = 69 @@ -152,9 +152,9 @@ object MainForm: TMainForm ItemHeight = 13 ItemIndex = 0 TabOrder = 2 - Text = '' + Text = 'Landing lights' Items.Strings = ( - '') + 'Landing lights') end object cmbFSXP4: TComboBox Left = 69 @@ -212,9 +212,9 @@ object MainForm: TMainForm ItemHeight = 13 ItemIndex = 0 TabOrder = 6 - Text = '' + Text = 'Instrument lights' Items.Strings = ( - '') + 'Instrument lights') end object cmbFSXP8: TComboBox Left = 69 diff --git a/G940LEDControl/Forms/MainFrm.pas b/G940LEDControl/Forms/MainFrm.pas index 4bff79c..4d85258 100644 --- a/G940LEDControl/Forms/MainFrm.pas +++ b/G940LEDControl/Forms/MainFrm.pas @@ -77,6 +77,7 @@ type procedure EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage); procedure HandleDeviceStateMessage(ATask: IOmniTaskControl; AMessage: TOmniMessage); + procedure HandleRunInMainThreadMessage(ATask: IOmniTaskControl; AMessage: TOmniMessage); property EventMonitor: TOmniEventMonitor read FEventMonitor; property StateConsumerTask: IOmniTaskControl read FStateConsumerTask; @@ -133,6 +134,7 @@ begin FinalizeStateProvider; StateConsumerTask.Terminate; + StateConsumerTask.WaitFor(INFINITE); FStateConsumerTask := nil; end; @@ -221,14 +223,18 @@ end; procedure TMainForm.UpdateMappingFSX; begin + TLEDStateConsumer.SetFunction(StateConsumerTask, 1, FUNCTION_FSX_PARKINGBRAKE); + TLEDStateConsumer.SetFunction(StateConsumerTask, 2, FUNCTION_FSX_LANDINGLIGHTS); TLEDStateConsumer.SetFunction(StateConsumerTask, 3, FUNCTION_FSX_GEAR); + TLEDStateConsumer.SetFunction(StateConsumerTask, 6, FUNCTION_FSX_INSTRUMENTLIGHTS); end; procedure TMainForm.EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage); begin case msg.MsgID of - MSG_NOTIFY_DEVICESTATE: HandleDeviceStateMessage(task, msg); + MSG_NOTIFY_DEVICESTATE: HandleDeviceStateMessage(task, msg); + MSG_RUN_IN_MAINTHREAD: HandleRunInMainThreadMessage(task, msg); end; end; @@ -251,6 +257,12 @@ begin end; +procedure TMainForm.HandleRunInMainThreadMessage(ATask: IOmniTaskControl; AMessage: TOmniMessage); +begin + (AMessage.MsgData.AsInterface as IRunInMainThread).Execute; +end; + + procedure TMainForm.btnFSXConnectClick(Sender: TObject); begin InitializeStateProvider(TFSXLEDStateProvider); diff --git a/G940LEDControl/Units/FSXLEDStateProvider.pas b/G940LEDControl/Units/FSXLEDStateProvider.pas index e5da18f..45d7b58 100644 --- a/G940LEDControl/Units/FSXLEDStateProvider.pas +++ b/G940LEDControl/Units/FSXLEDStateProvider.pas @@ -1,5 +1,7 @@ unit FSXLEDStateProvider; +// ToDo check has gear (react to sim start, aircraft change, etc) + interface uses Classes, @@ -12,6 +14,9 @@ uses const FUNCTION_FSX_GEAR = 1; + FUNCTION_FSX_LANDINGLIGHTS = 2; + FUNCTION_FSX_INSTRUMENTLIGHTS = 3; + FUNCTION_FSX_PARKINGBRAKE = 4; EXIT_ERROR_INITSIMCONNECT = 1; EXIT_ERROR_CONNECT = 2; @@ -29,6 +34,7 @@ type procedure UpdateMap; procedure HandleDispatch(AData: PSimConnectRecv); + function GetDataBoolean(var AData: Cardinal): Boolean; function GetDataDouble(var AData: Cardinal): Double; property SimConnectHandle: THandle read FSimConnectHandle; @@ -52,12 +58,21 @@ const READY_TIMEOUT = 5000; DEFINITION_GEAR = 1; - REQUEST_GEAR = 1; - + DEFINITION_LIGHTS = 2; + DEFINITION_INSTRUMENTLIGHTS = 3; + DEFINITION_PARKINGBRAKE = 4; FSX_VARIABLE_GEARTOTALPCTEXTENDED = 'GEAR TOTAL PCT EXTENDED'; + FSX_VARIABLE_LIGHTONSTATES = 'LIGHT ON STATES'; + FSX_VARIABLE_PARKINGBRAKE = 'BRAKE PARKING INDICATOR'; FSX_UNIT_PERCENT = 'percent'; + FSX_UNIT_MASK = 'mask'; + FSX_UNIT_BOOL = 'bool'; + + FSX_LIGHTON_LANDING = $0004; + FSX_LIGHTON_PANEL = $0020; + FSX_LIGHTON_CABIN = $0200; { TFSXLEDStateProvider } @@ -117,16 +132,47 @@ begin if FUseFunctionGear then SimConnect_ClearDataDefinition(SimConnectHandle, DEFINITION_GEAR); - FUseFunctionGear := Consumer.FunctionMap.HasFunction(FUNCTION_FSX_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, + SimConnect_RequestDataOnSimObject(SimConnectHandle, DEFINITION_GEAR, DEFINITION_GEAR, SIMCONNECT_OBJECT_ID_USER, - SIMCONNECT_PERIOD_SECOND, + SIMCONNECT_PERIOD_SIM_FRAME, + SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); + end; + +// ToDo for other vars too! +// if FUseFunctionGear then +// SimConnect_ClearDataDefinition(SimConnectHandle, DEFINITION_GEAR); + + if Consumer.FunctionMap.HasFunction(FUNCTION_FSX_LANDINGLIGHTS) or + Consumer.FunctionMap.HasFunction(FUNCTION_FSX_INSTRUMENTLIGHTS) then + begin + SimConnect_AddToDataDefinition(SimConnectHandle, DEFINITION_LIGHTS, + FSX_VARIABLE_LIGHTONSTATES, + FSX_UNIT_MASK, + SIMCONNECT_DATATYPE_INT32); + SimConnect_RequestDataOnSimObject(SimConnectHandle, DEFINITION_LIGHTS, + DEFINITION_LIGHTS, + SIMCONNECT_OBJECT_ID_USER, + SIMCONNECT_PERIOD_SIM_FRAME, + SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); + end; + + if Consumer.FunctionMap.HasFunction(FUNCTION_FSX_PARKINGBRAKE) then + begin + SimConnect_AddToDataDefinition(SimConnectHandle, DEFINITION_PARKINGBRAKE, + FSX_VARIABLE_PARKINGBRAKE, + FSX_UNIT_BOOL, + SIMCONNECT_DATATYPE_INT32); + SimConnect_RequestDataOnSimObject(SimConnectHandle, DEFINITION_PARKINGBRAKE, + DEFINITION_PARKINGBRAKE, + SIMCONNECT_OBJECT_ID_USER, + SIMCONNECT_PERIOD_SIM_FRAME, SIMCONNECT_DATA_REQUEST_FLAG_CHANGED); end; end; @@ -135,6 +181,7 @@ end; procedure TFSXLEDStateProvider.HandleDispatch(AData: PSimConnectRecv); var simObjectData: PSimConnectRecvSimObjectData; + states: Cardinal; begin case SIMCONNECT_RECV_ID(AData^.dwID) of @@ -143,7 +190,7 @@ begin simObjectData := PSimConnectRecvSimObjectData(AData); case simObjectData^.dwRequestID of - REQUEST_GEAR: + DEFINITION_GEAR: begin case Trunc(GetDataDouble(simObjectData^.dwData) * 100) of 0: Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsRed); @@ -151,6 +198,26 @@ begin else Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsAmber); end; end; + + DEFINITION_LIGHTS: + begin + states := simObjectData^.dwData; + if (states and FSX_LIGHTON_LANDING) <> 0 then + Consumer.SetStateByFunction(FUNCTION_FSX_LANDINGLIGHTS, lsGreen) + else + Consumer.SetStateByFunction(FUNCTION_FSX_LANDINGLIGHTS, lsRed); + + if (states and FSX_LIGHTON_PANEL) <> 0 then + Consumer.SetStateByFunction(FUNCTION_FSX_INSTRUMENTLIGHTS, lsGreen) + else + Consumer.SetStateByFunction(FUNCTION_FSX_INSTRUMENTLIGHTS, lsRed); + end; + + DEFINITION_PARKINGBRAKE: + if GetDataBoolean(simObjectData^.dwData) then + Consumer.SetStateByFunction(FUNCTION_FSX_PARKINGBRAKE, lsRed) + else + Consumer.SetStateByFunction(FUNCTION_FSX_PARKINGBRAKE, lsGreen); end; end; @@ -160,6 +227,12 @@ begin end; +function TFSXLEDStateProvider.GetDataBoolean(var AData: Cardinal): Boolean; +begin + Result := (AData <> 0); +end; + + function TFSXLEDStateProvider.GetDataDouble(var AData: Cardinal): Double; begin Result := PDouble(@AData)^; diff --git a/G940LEDControl/Units/G940LEDStateConsumer.pas b/G940LEDControl/Units/G940LEDStateConsumer.pas index 7f46f71..332e9cb 100644 --- a/G940LEDControl/Units/G940LEDStateConsumer.pas +++ b/G940LEDControl/Units/G940LEDStateConsumer.pas @@ -14,8 +14,8 @@ uses const MSG_FINDTHROTTLEDEVICE = MSG_CONSUMER_OFFSET + 1; + MSG_NOTIFY_DEVICESTATE = MSG_CONSUMER_OFFSET + 2; - type TG940LEDStateConsumer = class(TLEDStateConsumer) private @@ -38,8 +38,6 @@ type const - MSG_NOTIFY_DEVICESTATE = 1; - DEVICESTATE_SEARCHING = 0; DEVICESTATE_FOUND = 1; DEVICESTATE_NOTFOUND = 2; @@ -56,6 +54,19 @@ uses LogiJoystickDLL; +type + TRunInMainThreadSetButtonColor = class(TInterfacedObject, IRunInMainThread) + private + FDevice: IDirectInputDevice8; + FButton: TLogiPanelButton; + FColor: TLogiColor; + protected + procedure Execute; + public + constructor Create(device: IDirectInputDevice8; button: TLogiPanelButton; color: TLogiColor); + end; + + function EnumDevicesProc(var lpddi: TDIDeviceInstanceA; pvRef: Pointer): BOOL; stdcall; var vendorID: Word; @@ -109,6 +120,7 @@ end; procedure TG940LEDStateConsumer.LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); var color: TLogiColor; +// msg: TMsg; begin // ToDo SetLEDs gebruiken (vereist override van SetStateByFunction om te groeperen) @@ -127,8 +139,8 @@ begin lsError: color := LOGI_RED; end; - SetButtonColor(ThrottleDevice, TLogiPanelButton(ALEDIndex), color); - ProcessMessages; + { Logitech SDK will not change the color outside of the main thread } + RunInMainThread(TRunInMainThreadSetButtonColor.Create(ThrottleDevice, TLogiPanelButton(ALEDIndex), color)); end; end; @@ -187,4 +199,21 @@ end; // end; //end; + +{ TRunInMainThreadSetButtonColor } +constructor TRunInMainThreadSetButtonColor.Create(device: IDirectInputDevice8; button: TLogiPanelButton; color: TLogiColor); +begin + inherited Create; + + FDevice := device; + FButton := button; + FColor := color; +end; + + +procedure TRunInMainThreadSetButtonColor.Execute; +begin + SetButtonColor(FDevice, FButton, FColor); +end; + end. diff --git a/G940LEDControl/Units/LEDStateConsumer.pas b/G940LEDControl/Units/LEDStateConsumer.pas index 7b474b8..3099a66 100644 --- a/G940LEDControl/Units/LEDStateConsumer.pas +++ b/G940LEDControl/Units/LEDStateConsumer.pas @@ -16,12 +16,21 @@ const MSG_FINALIZE_PROVIDER = 4; MSG_PROCESS_MESSAGES = 5; - MSG_CONSUMER_OFFSET = MSG_PROCESS_MESSAGES; + MSG_RUN_IN_MAINTHREAD = 6; + + MSG_CONSUMER_OFFSET = MSG_RUN_IN_MAINTHREAD; TIMER_PROCESSMESSAGES = 1; type + { This interface name made me giggle. Because it's true. } + IRunInMainThread = interface + ['{68B8F2F7-ED40-4078-9D99-503D7AFA068B}'] + procedure Execute; + end; + + TLEDStateConsumer = class(TOmniWorker, ILEDStateConsumer) private FFunctionMap: TLEDFunctionMap; @@ -38,6 +47,7 @@ type procedure InitializeProvider(AProviderClass: TLEDStateProviderClass); procedure FinalizeProvider; + procedure RunInMainThread(AExecutor: IRunInMainThread); procedure LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); virtual; { ILEDStateConsumer } @@ -62,6 +72,7 @@ type implementation uses SysUtils, + Windows, OtlCommon; @@ -146,7 +157,7 @@ begin FinalizeProvider; FProvider := AProviderClass.Create(Self); - // ToDo exception handlign + // ToDo exception handling Provider.Initialize; if Provider.ProcessMessagesInterval > -1 then @@ -174,6 +185,12 @@ begin end; +procedure TLEDStateConsumer.RunInMainThread(AExecutor: IRunInMainThread); +begin + Task.Comm.Send(MSG_RUN_IN_MAINTHREAD, AExecutor); +end; + + procedure TLEDStateConsumer.LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); begin end;