diff --git a/G940LEDControl/G940LEDControl.dpr b/G940LEDControl/G940LEDControl.dpr index 73926ad..313a0e4 100644 --- a/G940LEDControl/G940LEDControl.dpr +++ b/G940LEDControl/G940LEDControl.dpr @@ -13,7 +13,6 @@ uses LEDColorIntf in 'Units\LEDColorIntf.pas', LEDColor in 'Units\LEDColor.pas', LEDFunctionIntf in 'Units\LEDFunctionIntf.pas', - ObserverIntf in 'Units\ObserverIntf.pas', LEDFunction in 'Units\LEDFunction.pas', StaticLEDFunction in 'Units\StaticLEDFunction.pas', ConfigConversion in 'Units\ConfigConversion.pas', diff --git a/G940LEDControl/G940LEDControl.dproj b/G940LEDControl/G940LEDControl.dproj index 6e8807e..88044e5 100644 --- a/G940LEDControl/G940LEDControl.dproj +++ b/G940LEDControl/G940LEDControl.dproj @@ -173,7 +173,6 @@ - diff --git a/G940LEDControl/Units/FSXLEDFunction.pas b/G940LEDControl/Units/FSXLEDFunction.pas new file mode 100644 index 0000000..0f8c13c --- /dev/null +++ b/G940LEDControl/Units/FSXLEDFunction.pas @@ -0,0 +1,366 @@ +unit FSXLEDFunction; + +interface +uses + FSXLEDFunctionProvider, + LEDFunction, + LEDFunctionIntf; + + +type + { Base classes } + TFSXOnOffFunction = class(TCustomFSXFunction) + protected + procedure RegisterStates; override; + end; + + + { Function implementations } + TFSXEngineFunction = class(TCustomFSXFunction) + protected + procedure RegisterStates; override; + function GetWorkerClass: TCustomLEDFunctionWorkerClass; override; + end; + + TFSXGearFunction = class(TCustomFSXFunction) + protected + procedure RegisterStates; override; + function GetWorkerClass: TCustomLEDFunctionWorkerClass; override; + end; + + + TFSXLightFunction = class(TFSXOnOffFunction) + protected + function GetCategoryName: string; override; + + function GetWorkerClass: TCustomLEDFunctionWorkerClass; override; + function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; override; + protected + function GetLightMask: Integer; virtual; abstract; + end; + + TFSXLandingLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + TFSXInstrumentLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + TFSXBeaconLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + TFSXNavLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + TFSXStrobeLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + TFSXTaxiLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + TFSXRecognitionLightsFunction = class(TFSXLightFunction) + protected + function GetLightMask: Integer; override; + end; + + +implementation +uses + System.Math, + System.SysUtils, + + FSXSimConnectIntf, + FSXResources, + LEDColorIntf, + LEDState, + LEDStateIntf, + SimConnect; + + +type + { Worker implementations } + TFSXEngineFunctionWorker = class(TCustomFSXFunctionWorker) + protected + procedure RegisterVariables; override; + procedure HandleData(AData: Pointer); override; + end; + + TFSXGearFunctionWorker = class(TCustomFSXFunctionWorker) + protected + procedure RegisterVariables; override; + procedure HandleData(AData: Pointer); override; + end; + + TFSXLightStatesFunctionWorker = class(TCustomFSXFunctionWorker) + private + FStateMask: Integer; + protected + procedure RegisterVariables; override; + procedure HandleData(AData: Pointer); override; + public + property StateMask: Integer read FStateMask write FStateMask; + end; + + +{ TFSXOnOffFunction } +procedure TFSXOnOffFunction.RegisterStates; +begin + RegisterState(TLEDState.Create(FSXStateUIDOn, FSXStateDisplayNameOn, lcGreen)); + RegisterState(TLEDState.Create(FSXStateUIDOff, FSXStateDisplayNameOff, lcRed)); +end; + + +{ TFSXEngineFunction } +procedure TFSXEngineFunction.RegisterStates; +begin + RegisterState(TLEDState.Create(FSXStateUIDEngineNoEngines, FSXStateDisplayNameEngineNoEngines, lcOff)); + RegisterState(TLEDState.Create(FSXStateUIDEngineAllRunning, FSXStateDisplayNameEngineAllRunning, lcGreen)); + RegisterState(TLEDState.Create(FSXStateUIDEnginePartiallyRunning, FSXStateDisplayNameEnginePartiallyRunning, lcAmber)); + RegisterState(TLEDState.Create(FSXStateUIDEngineAllOff, FSXStateDisplayNameEngineAllOff, lcRed)); + RegisterState(TLEDState.Create(FSXStateUIDEngineFailed, FSXStateDisplayNameEngineFailed, lcFlashingRedNormal)); + RegisterState(TLEDState.Create(FSXStateUIDEngineOnFire, FSXStateDisplayNameEngineOnFire, lcFlashingRedFast)); +end; + + +function TFSXEngineFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass; +begin + Result := TFSXEngineFunctionWorker; +end; + + +{ TFSXEngineFunctionWorker } +procedure TFSXEngineFunctionWorker.RegisterVariables; +var + engineIndex: Integer; + +begin + Definition.AddVariable('NUMBER OF ENGINES', FSX_UNIT_NUMBER, SIMCONNECT_DATAType_INT32); + + for engineIndex := 1 to FSX_MAX_ENGINES do + Definition.AddVariable(Format('GENERAL ENG COMBUSTION:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32); + + for engineIndex := 1 to FSX_MAX_ENGINES do + Definition.AddVariable(Format('ENG FAILED:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32); + + for engineIndex := 1 to FSX_MAX_ENGINES do + Definition.AddVariable(Format('ENG ON FIRE:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32); +end; + + +procedure TFSXEngineFunctionWorker.HandleData(AData: Pointer); +type + PEngineData = ^TEngineData; + TEngineData = packed record + NumberOfEngines: Integer; + Combustion: array[1..FSX_MAX_ENGINES] of Integer; + Failed: array[1..FSX_MAX_ENGINES] of Integer; + OnFire: array[1..FSX_MAX_ENGINES] of Integer; + end; + +var + engineData: PEngineData; + engineCount: Integer; + engineIndex: Integer; + hasFire: Boolean; + hasFailure: Boolean; + runningCount: Integer; + +begin + engineData := AData; + + if engineData^.NumberOfEngines > 0 then + begin + engineCount := Min(engineData^.NumberOfEngines, FSX_MAX_ENGINES); + hasFire := False; + hasFailure := False; + runningCount := 0; + + for engineIndex := 1 to engineCount do + begin + if engineData^.OnFire[engineIndex] <> 0 then + hasFire := True; + + if engineData^.Failed[engineIndex] <> 0 then + hasFailure := True; + + if engineData^.Combustion[engineIndex] <> 0 then + Inc(runningCount); + end; + + if hasFire then + SetCurrentState(FSXStateUIDEngineOnFire) + + else if hasFailure then + SetCurrentState(FSXStateUIDEngineFailed) + + else if runningCount = 0 then + SetCurrentState(FSXStateUIDEngineAllOff) + + else if runningCount = engineCount then + SetCurrentState(FSXStateUIDEngineAllRunning) + + else + SetCurrentState(FSXStateUIDEnginePartiallyRunning); + end else + SetCurrentState(FSXStateUIDEngineNoEngines); +end; + + +{ TFSXGearFunction } +procedure TFSXGearFunction.RegisterStates; +begin + RegisterState(TLEDState.Create(FSXStateUIDGearNotRetractable, FSXStateDisplayNameGearNotRetractable, lcOff)); + RegisterState(TLEDState.Create(FSXStateUIDGearRetracted, FSXStateDisplayNameGearRetracted, lcRed)); + RegisterState(TLEDState.Create(FSXStateUIDGearBetween, FSXStateDisplayNameGearBetween, lcAmber)); + RegisterState(TLEDState.Create(FSXStateUIDGearExtended, FSXStateDisplayNameGearExtended, lcGreen)); + RegisterState(TLEDState.Create(FSXStateUIDGearSpeedExceeded, FSXStateDisplayNameGearSpeedExceeded, lcFlashingAmberNormal)); + RegisterState(TLEDState.Create(FSXStateUIDGearDamageBySpeed, FSXStateDisplayNameGearDamageBySpeed, lcFlashingRedFast)); +end; + + +function TFSXGearFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass; +begin + Result := TFSXGearFunctionWorker; +end; + + +{ TFSXGearFunctionWorker } +procedure TFSXGearFunctionWorker.RegisterVariables; +begin + Definition.AddVariable('IS GEAR RETRACTABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32); + Definition.AddVariable('GEAR TOTAL PCT EXTENDED', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64); + Definition.AddVariable('GEAR DAMAGE BY SPEED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32); + Definition.AddVariable('GEAR SPEED EXCEEDED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32); +end; + + +procedure TFSXGearFunctionWorker.HandleData(AData: Pointer); +type + PGearData = ^TGearData; + TGearData = packed record + IsGearRetractable: Cardinal; + TotalPctExtended: Double; + DamageBySpeed: Integer; + SpeedExceeded: Integer; + end; + +var + gearData: PGearData; + +begin + gearData := AData; + + if gearData^.DamageBySpeed <> 0 then + SetCurrentState(FSXStateUIDGearDamageBySpeed) + + else if gearData^.SpeedExceeded <> 0 then + SetCurrentState(FSXStateUIDGearSpeedExceeded) + + else if gearData^.IsGearRetractable <> 0 then + begin + case Trunc(gearData ^.TotalPctExtended * 100) of + 0: SetCurrentState(FSXStateUIDGearRetracted); + 95..100: SetCurrentState(FSXStateUIDGearExtended); + else SetCurrentState(FSXStateUIDGearBetween); + end; + end else + SetCurrentState(FSXStateUIDGearNotRetractable); +end; + + +{ TFSXLightFunction } +function TFSXLightFunction.GetCategoryName: string; +begin + Result := FSXCategoryLights; +end; + + +function TFSXLightFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass; +begin + Result := TFSXLightStatesFunctionWorker; +end; + + +function TFSXLightFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; +begin + Result := inherited DoCreateWorker(ASettings); + (Result as TFSXLightStatesFunctionWorker).StateMask := GetLightMask; +end; + + +{ TFSXLandingLightsFunction } +function TFSXLandingLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_LANDING; +end; + + +{ TFSXInstrumentLightsFunction } +function TFSXInstrumentLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_PANEL; +end; + + +{ TFSXBeaconLightsFunction } +function TFSXBeaconLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_BEACON; +end; + + +{ TFSXNavLightsFunction } +function TFSXNavLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_NAV; +end; + + +{ TFSXStrobeLightsFunction } +function TFSXStrobeLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_STROBE; +end; + + +{ TFSXTaxiLightsFunction } +function TFSXTaxiLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_TAXI; +end; + + +{ TFSXRecognitionLightsFunction } +function TFSXRecognitionLightsFunction.GetLightMask: Integer; +begin + Result := FSX_LIGHTON_RECOGNITION; +end; + + +{ TFSXLightStatesFunctionWorker } +procedure TFSXLightStatesFunctionWorker.RegisterVariables; +begin + Definition.AddVariable('LIGHT ON STATES', FSX_UNIT_MASK, SIMCONNECT_DATATYPE_INT32); +end; + + +procedure TFSXLightStatesFunctionWorker.HandleData(AData: Pointer); +begin + if (PCardinal(AData)^ and StateMask) <> 0 then + SetCurrentState(FSXStateUIDOn) + else + SetCurrentState(FSXStateUIDOff); +end; + +end. diff --git a/G940LEDControl/Units/FSXLEDFunctionProvider.pas b/G940LEDControl/Units/FSXLEDFunctionProvider.pas index c477692..19659e1 100644 --- a/G940LEDControl/Units/FSXLEDFunctionProvider.pas +++ b/G940LEDControl/Units/FSXLEDFunctionProvider.pas @@ -8,8 +8,7 @@ uses FSXSimConnectIntf, LEDFunction, LEDFunctionIntf, - LEDStateIntf, - ObserverIntf; + LEDStateIntf; type @@ -17,24 +16,21 @@ type TCustomFSXFunctionList = TObjectList; - TFSXLEDFunctionProvider = class(TCustomLEDFunctionProvider) + TFSXLEDFunctionProvider = class(TCustomLEDFunctionProvider, IFSXSimConnectObserver) private - FConnectedFunctions: TCustomFSXFunctionList; - FSimConnectHandle: THandle; - protected - procedure SimConnect; - procedure SimDisconnect; - - procedure Connect(AFunction: TCustomFSXFunction); virtual; - procedure Disconnect(AFunction: TCustomFSXFunction); virtual; - - property ConnectedFunctions: TCustomFSXFunctionList read FConnectedFunctions; - property SimConnectHandle: THandle read FSimConnectHandle; + FSimConnect: IFSXSimConnect; + FSimConnectLock: TCriticalSection; protected procedure RegisterFunctions; override; function GetUID: string; override; + protected + { IFSXSimConnectObserver } + procedure ObserveDestroy(Sender: IFSXSimConnect); public + constructor Create; + destructor Destroy; override; + function GetSimConnect: IFSXSimConnect; end; @@ -45,9 +41,6 @@ type FDisplayName: string; FUID: string; protected - procedure SimConnected; virtual; - procedure SimDisconnected; virtual; - property Provider: TFSXLEDFunctionProvider read FProvider; protected function GetCategoryName: string; override; @@ -58,7 +51,10 @@ type end; - TCustomFSXFunctionWorker = class(TCustomLEDFunctionWorker) + TCustomFSXFunctionClass = class of TCustomFSXFunction; + + + TCustomFSXFunctionWorker = class(TCustomLEDFunctionWorker, IFSXSimConnectDataHandler) private FSimConnect: IFSXSimConnect; FDefinition: IFSXSimConnectDefinition; @@ -73,6 +69,9 @@ type property SimConnect: IFSXSimConnect read FSimConnect; protected function GetCurrentState: ILEDStateWorker; override; + + { IFSXSimConnectDataHandler } + procedure HandleData(AData: Pointer); virtual; abstract; public constructor Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; ASimConnect: IFSXSimConnect); destructor Destroy; override; @@ -85,15 +84,63 @@ uses FSXLEDFunction, FSXResources, + FSXSimConnectClient, LEDFunctionRegistry, SimConnect; { TFSXLEDFunctionProvider } +constructor TFSXLEDFunctionProvider.Create; +begin + inherited Create; + + FSimConnectLock := TCriticalSection.Create; +end; + + +destructor TFSXLEDFunctionProvider.Destroy; +begin + FreeAndNil(FSimConnectLock); + + inherited Destroy; +end; + + procedure TFSXLEDFunctionProvider.RegisterFunctions; begin - RegisterFunction(TFSXGearFunction.Create(Self, FSXFunctionDisplayNameGear, FSXFunctionUIDGear)); + { + AConsumer.AddFunction(FUNCTION_FSX_CARBHEAT, 'Anti-ice'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT, 'Auto pilot (main)'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_AMBER, 'Auto pilot (main - off / amber)'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_ALTITUDE, 'Auto pilot - Altitude'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_APPROACH, 'Auto pilot - Approach'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_BACKCOURSE, 'Auto pilot - Backcourse'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_HEADING, 'Auto pilot - Heading'); + AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_NAV, 'Auto pilot - Nav'); + AConsumer.AddFunction(FUNCTION_FSX_AVIONICSMASTER, 'Avionics master switch'); + AConsumer.AddFunction(FUNCTION_FSX_BATTERYMASTER, 'Battery master switch'); + AConsumer.AddFunction(FUNCTION_FSX_ENGINE, 'Engine'); + AConsumer.AddFunction(FUNCTION_FSX_EXITDOOR, 'Exit door'); + AConsumer.AddFunction(FUNCTION_FSX_FLAPS, 'Flaps'); + AConsumer.AddFunction(FUNCTION_FSX_PARKINGBRAKE, 'Parking brake'); + AConsumer.AddFunction(FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH, 'Pressurization dump switch'); + AConsumer.AddFunction(FUNCTION_FSX_SPOILERS, 'Spoilers (air brake)'); + AConsumer.AddFunction(FUNCTION_FSX_TAILHOOK, 'Tail hook'); + } + + { Misc } + RegisterFunction(TFSXEngineFunction.Create( Self, FSXFunctionDisplayNameEngine, FSXFunctionUIDEngine)); + RegisterFunction(TFSXGearFunction.Create( Self, FSXFunctionDisplayNameGear, FSXFunctionUIDGear)); + + { Lights } + RegisterFunction(TFSXBeaconLightsFunction.Create( Self, FSXFunctionDisplayNameBeaconLights, FSXFunctionUIDBeaconLights)); + RegisterFunction(TFSXInstrumentLightsFunction.Create( Self, FSXFunctionDisplayNameInstrumentLights, FSXFunctionUIDInstrumentLights)); + RegisterFunction(TFSXLandingLightsFunction.Create( Self, FSXFunctionDisplayNameLandingLights, FSXFunctionUIDLandingLights)); + RegisterFunction(TFSXNavLightsFunction.Create( Self, FSXFunctionDisplayNameNavLights, FSXFunctionUIDNavLights)); + RegisterFunction(TFSXRecognitionLightsFunction.Create(Self, FSXFunctionDisplayNameRecognitionLights, FSXFunctionUIDRecognitionLights)); + RegisterFunction(TFSXStrobeLightsFunction.Create( Self, FSXFunctionDisplayNameStrobeLights, FSXFunctionUIDStrobeLights)); + RegisterFunction(TFSXTaxiLightsFunction.Create( Self, FSXFunctionDisplayNameTaxiLights, FSXFunctionUIDTaxiLights)); end; @@ -103,57 +150,34 @@ begin end; +procedure TFSXLEDFunctionProvider.ObserveDestroy(Sender: IFSXSimConnect); +begin + FSimConnectLock.Acquire; + try + FSimConnect := nil; + finally + FSimConnectLock.Release; + end; +end; + + function TFSXLEDFunctionProvider.GetSimConnect: IFSXSimConnect; begin - // TODO -end; + FSimConnectLock.Acquire; + try + if not Assigned(FSimConnect) then + begin + FSimConnect := TFSXSimConnectInterface.Create; + FSimConnect.Attach(Self); + end; - -procedure TFSXLEDFunctionProvider.SimConnect; -var - fsxFunction: TCustomFSXFunction; - -begin - if SimConnectHandle <> 0 then - exit; - -// FSimConnectHandle := - - if SimConnectHandle <> 0 then - begin - for fsxFunction in ConnectedFunctions do - fsxFunction.SimConnected; + Result := FSimConnect; + finally + FSimConnectLock.Release; end; end; -procedure TFSXLEDFunctionProvider.SimDisconnect; -begin - if SimConnectHandle = 0 then - exit; -end; - - -procedure TFSXLEDFunctionProvider.Connect(AFunction: TCustomFSXFunction); -begin - if ConnectedFunctions.IndexOf(AFunction) = -1 then - begin - ConnectedFunctions.Add(AFunction); - - if ConnectedFunctions.Count > 0 then - SimConnect; - end; -end; - -procedure TFSXLEDFunctionProvider.Disconnect(AFunction: TCustomFSXFunction); -begin - ConnectedFunctions.Remove(AFunction); - - if ConnectedFunctions.Count = 0 then - SimDisconnect; -end; - - { TCustomFSXFunction } constructor TCustomFSXFunction.Create(AProvider: TFSXLEDFunctionProvider; const ADisplayName, AUID: string); begin @@ -183,16 +207,6 @@ begin end; -procedure TCustomFSXFunction.SimConnected; -begin -end; - - -procedure TCustomFSXFunction.SimDisconnected; -begin -end; - - { TCustomFSXFunctionWorker } constructor TCustomFSXFunctionWorker.Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; ASimConnect: IFSXSimConnect); begin @@ -203,7 +217,9 @@ begin FDefinition := ASimConnect.CreateDefinition; RegisterVariables; - ASimConnect.AddDefinition(FDefinition); + + // TODO pass self as callback for this definition + ASimConnect.AddDefinition(FDefinition, Self); end; diff --git a/G940LEDControl/Units/FSXResources.pas b/G940LEDControl/Units/FSXResources.pas index 969913e..d1dad2a 100644 --- a/G940LEDControl/Units/FSXResources.pas +++ b/G940LEDControl/Units/FSXResources.pas @@ -3,18 +3,45 @@ unit FSXResources; interface const FSXProviderUID = 'fsx'; - FSXCategory = 'Flight Simulator X'; + FSXCategoryLights = FSXCategory + ' - Lights'; + + FSXStateUIDOn = 'on'; + FSXStateUIDOff = 'off'; + + FSXStateDisplayNameOn = 'On'; + FSXStateDisplayNameOff = 'Off'; + + + FSXFunctionUIDEngine = 'engine'; + FSXFunctionDisplayNameEngine = 'Engine'; + + FSXStateUIDEngineNoEngines = 'noEngines'; + FSXStateUIDEngineAllRunning = 'allRunning'; + FSXStateUIDEnginePartiallyRunning = 'partiallyRunning'; + FSXStateUIDEngineAllOff = 'allOff'; + FSXStateUIDEngineFailed = 'failed'; + FSXStateUIDEngineOnFire = 'onFire'; + + FSXStateDisplayNameEngineNoEngines = 'No engines'; + FSXStateDisplayNameEngineAllRunning = 'All running'; + FSXStateDisplayNameEnginePartiallyRunning = 'Partially running'; + FSXStateDisplayNameEngineAllOff = 'All off'; + FSXStateDisplayNameEngineFailed = 'Engine failure'; + FSXStateDisplayNameEngineOnFire = 'On fire'; + FSXFunctionUIDGear = 'gear'; FSXFunctionDisplayNameGear = 'Landing gear'; + FSXStateUIDGearNotRetractable = 'notRetractable'; FSXStateUIDGearRetracted = 'retracted'; FSXStateUIDGearBetween = 'between'; FSXStateUIDGearExtended = 'extended'; FSXStateUIDGearSpeedExceeded = 'speedExceeded'; FSXStateUIDGearDamageBySpeed = 'damageBySpeed'; + FSXStateDisplayNameGearNotRetractable = 'Not retractable'; FSXStateDisplayNameGearRetracted = 'Retracted'; FSXStateDisplayNameGearBetween = 'Extending / retracting'; FSXStateDisplayNameGearExtended = 'Extended'; @@ -22,6 +49,27 @@ const FSXStateDisplayNameGearDamageBySpeed = 'Damage by speed'; + FSXFunctionUIDLandingLights = 'landingLights'; + FSXFunctionDisplayNameLandingLights = 'Landing lights'; + + FSXFunctionUIDInstrumentLights = 'instrumentLights'; + FSXFunctionDisplayNameInstrumentLights = 'Instrument lights'; + + FSXFunctionUIDBeaconLights = 'beaconLights'; + FSXFunctionDisplayNameBeaconLights = 'Beacon lights'; + + FSXFunctionUIDNavLights = 'navLights'; + FSXFunctionDisplayNameNavLights = 'Nav lights'; + + FSXFunctionUIDStrobeLights = 'strobeLights'; + FSXFunctionDisplayNameStrobeLights = 'Strobe lights'; + + FSXFunctionUIDTaxiLights = 'taxiLights'; + FSXFunctionDisplayNameTaxiLights = 'Taxi lights'; + + FSXFunctionUIDRecognitionLights = 'recognitionLights'; + FSXFunctionDisplayNameRecognitionLights = 'Recognition lights'; + implementation diff --git a/G940LEDControl/Units/FSXSimConnectClient.pas b/G940LEDControl/Units/FSXSimConnectClient.pas index 4cb8fc8..e55d7e5 100644 --- a/G940LEDControl/Units/FSXSimConnectClient.pas +++ b/G940LEDControl/Units/FSXSimConnectClient.pas @@ -2,20 +2,29 @@ unit FSXSimConnectClient; interface uses + Classes, + OtlTaskControl, FSXSimConnectIntf; + type TFSXSimConnectInterface = class(TInterfacedObject, IFSXSimConnect) private FClient: IOmniTaskControl; + FObservers: TInterfaceList; protected property Client: IOmniTaskControl read FClient; + property Observers: TInterfaceList read FObservers; protected { IFSXSimConnect } + procedure Attach(AObserver: IFSXSimConnectObserver); + procedure Detach(AObserver: IFSXSimConnectObserver); + function CreateDefinition: IFSXSimConnectDefinition; - procedure AddDefinition(ADefinition: IFSXSimConnectDefinition); + procedure AddDefinition(ADefinition: IFSXSimConnectDefinition; ADataHandler: IFSXSimConnectDataHandler); + procedure RemoveDefinition(ADataHandler: IFSXSimConnectDataHandler); public constructor Create; destructor Destroy; override; @@ -29,6 +38,11 @@ uses SimConnect; +const + TM_ADDDEFINITION = 3001; + TM_REMOVEDEFINITION = 3002; + + type TFSXSimConnectClient = class(TOmniWorker) end; @@ -58,11 +72,15 @@ var begin worker := TFSXSimConnectClient.Create; FClient := CreateTask(worker); + + FObservers := TInterfaceList.Create; end; destructor TFSXSimConnectInterface.Destroy; begin + FreeAndNil(FObservers); + FClient.Terminate; FClient := nil; @@ -70,15 +88,34 @@ begin end; +procedure TFSXSimConnectInterface.Attach(AObserver: IFSXSimConnectObserver); +begin + Observers.Add(AObserver as IFSXSimConnectObserver); +end; + + +procedure TFSXSimConnectInterface.Detach(AObserver: IFSXSimConnectObserver); +begin + Observers.Remove(AObserver as IFSXSimConnectObserver); +end; + + function TFSXSimConnectInterface.CreateDefinition: IFSXSimConnectDefinition; begin Result := TFSXSimConnectDefinition.Create(Self); end; -procedure TFSXSimConnectInterface.AddDefinition(ADefinition: IFSXSimConnectDefinition); +procedure TFSXSimConnectInterface.AddDefinition(ADefinition: IFSXSimConnectDefinition; ADataHandler: IFSXSimConnectDataHandler); begin - // TODO + Client.Comm.Send(TM_ADDDEFINITION, [ADefinition, ADataHandler]); + // TODO pass to thread; if definition already exists (same variables), link to existing definition to avoid too many SimConnect definition +end; + + +procedure TFSXSimConnectInterface.RemoveDefinition(ADataHandler: IFSXSimConnectDataHandler); +begin + Client.Comm.Send(TM_REMOVEDEFINITION, ADataHandler); end; diff --git a/G940LEDControl/Units/FSXSimConnectIntf.pas b/G940LEDControl/Units/FSXSimConnectIntf.pas index 46704de..928a9d9 100644 --- a/G940LEDControl/Units/FSXSimConnectIntf.pas +++ b/G940LEDControl/Units/FSXSimConnectIntf.pas @@ -6,13 +6,30 @@ uses type + IFSXSimConnect = interface; IFSXSimConnectDefinition = interface; + IFSXSimConnectObserver = interface + ['{ACE8979A-D656-4F97-A332-A54BB615C4D1}'] + procedure ObserveDestroy(Sender: IFSXSimConnect); + end; + + + IFSXSimConnectDataHandler = interface + ['{29F00FB8-00AB-419F-83A3-A6AB3582599F}'] + procedure HandleData(AData: Pointer); + end; + + IFSXSimConnect = interface ['{B6BE3E7C-0804-43D6-84DE-8010C5728A07}'] + procedure Attach(AObserver: IFSXSimConnectObserver); + procedure Detach(AObserver: IFSXSimConnectObserver); + function CreateDefinition: IFSXSimConnectDefinition; - procedure AddDefinition(ADefinition: IFSXSimConnectDefinition); + procedure AddDefinition(ADefinition: IFSXSimConnectDefinition; ADataHandler: IFSXSimConnectDataHandler); + procedure RemoveDefinition(ADataHandler: IFSXSimConnectDataHandler); end; @@ -30,6 +47,16 @@ const FSX_UNIT_BOOL = 'bool'; FSX_UNIT_NUMBER = 'number'; + FSX_LIGHTON_NAV = $0001; + FSX_LIGHTON_BEACON = $0002; + FSX_LIGHTON_LANDING = $0004; + FSX_LIGHTON_TAXI = $0008; + FSX_LIGHTON_STROBE = $0010; + FSX_LIGHTON_PANEL = $0020; + FSX_LIGHTON_RECOGNITION = $0040; + FSX_LIGHTON_CABIN = $0200; + + FSX_MAX_ENGINES = 4; implementation diff --git a/G940LEDControl/Units/LEDFunction.pas b/G940LEDControl/Units/LEDFunction.pas index 7d9bdf2..247ced4 100644 --- a/G940LEDControl/Units/LEDFunction.pas +++ b/G940LEDControl/Units/LEDFunction.pas @@ -5,11 +5,14 @@ uses Classes, LEDFunctionIntf, - LEDStateIntf, - ObserverIntf; + LEDStateIntf; type + TCustomLEDFunctionWorker = class; + TCustomLEDFunctionWorkerClass = class of TCustomLEDFunctionWorker; + + TCustomLEDFunctionProvider = class(TInterfacedObject, ILEDFunctionProvider) private FFunctions: TInterfaceList; @@ -45,7 +48,12 @@ type protected procedure RegisterStates; virtual; abstract; function RegisterState(AState: ILEDState): ILEDState; virtual; + + function GetWorkerClass: TCustomLEDFunctionWorkerClass; virtual; abstract; + function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; virtual; protected + function CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker; override; + { ILEDMultiStateFunction } function GetEnumerator: ILEDStateEnumerator; virtual; public @@ -67,9 +75,9 @@ type property Observers: TInterfaceList read FObservers; property States: TInterfaceList read FStates; protected - { IObservable } - procedure Attach(AObserver: IObserver); virtual; - procedure Detach(AObserver: IObserver); virtual; + { ILEDFunctionWorker } + procedure Attach(AObserver: ILEDFunctionObserver); virtual; + procedure Detach(AObserver: ILEDFunctionObserver); virtual; function GetCurrentState: ILEDStateWorker; virtual; abstract; public @@ -147,6 +155,18 @@ begin end; +function TCustomMultiStateLEDFunction.CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker; +begin + Result := DoCreateWorker(ASettings); +end; + + +function TCustomMultiStateLEDFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; +begin + Result := GetWorkerClass.Create(Self, ASettings); +end; + + { TCustomLEDFunctionWorker } constructor TCustomLEDFunctionWorker.Create; begin @@ -174,16 +194,16 @@ begin end; -procedure TCustomLEDFunctionWorker.Attach(AObserver: IObserver); +procedure TCustomLEDFunctionWorker.Attach(AObserver: ILEDFunctionObserver); begin { TInterfaceList is thread-safe } - Observers.Add(AObserver as IObserver); + Observers.Add(AObserver as ILEDFunctionObserver); end; -procedure TCustomLEDFunctionWorker.Detach(AObserver: IObserver); +procedure TCustomLEDFunctionWorker.Detach(AObserver: ILEDFunctionObserver); begin - Observers.Remove(AObserver as IObserver); + Observers.Remove(AObserver as ILEDFunctionObserver); end; @@ -225,7 +245,7 @@ var begin for observer in Observers do - (observer as IObserver).Update(Self); + (observer as ILEDFunctionObserver).ObserveUpdate(Self); end; diff --git a/G940LEDControl/Units/LEDFunctionIntf.pas b/G940LEDControl/Units/LEDFunctionIntf.pas index 11394e9..81bba41 100644 --- a/G940LEDControl/Units/LEDFunctionIntf.pas +++ b/G940LEDControl/Units/LEDFunctionIntf.pas @@ -3,8 +3,7 @@ unit LEDFunctionIntf; interface uses LEDColorIntf, - LEDStateIntf, - ObserverIntf; + LEDStateIntf; type @@ -40,8 +39,17 @@ type end; - ILEDFunctionWorker = interface(IObservable) + ILEDFunctionObserver = interface + ['{B78415C9-9F64-4AF1-8983-BACE2B7225EF}'] + procedure ObserveUpdate(Sender: ILEDFunctionWorker); + end; + + + ILEDFunctionWorker = interface ['{5EF3230D-B52F-4BD6-8AD3-F3A035F155B1}'] + procedure Attach(AObserver: ILEDFunctionObserver); + procedure Detach(AObserver: ILEDFunctionObserver); + function GetCurrentState: ILEDStateWorker; end;