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;