Refactored: ILEDColor to ILEDStateColor (to prevent conflicts with the TLEDColor enum)
Reanimated: LEDStateConsumer and G940LEDStateConsumer; all LED state colors (including flashing) work and update properly after changing the profile - FSX functions crash horribly
This commit is contained in:
parent
b66659cd95
commit
f1b9a63fda
@ -19,9 +19,7 @@ uses
|
|||||||
pngimage,
|
pngimage,
|
||||||
X2UtPersistIntf,
|
X2UtPersistIntf,
|
||||||
|
|
||||||
LEDFunctionMap,
|
|
||||||
LEDStateConsumer,
|
LEDStateConsumer,
|
||||||
LEDStateProvider,
|
|
||||||
Profile;
|
Profile;
|
||||||
|
|
||||||
|
|
||||||
@ -95,7 +93,6 @@ type
|
|||||||
procedure FormCreate(Sender: TObject);
|
procedure FormCreate(Sender: TObject);
|
||||||
procedure btnRetryClick(Sender: TObject);
|
procedure btnRetryClick(Sender: TObject);
|
||||||
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
|
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
|
||||||
procedure FunctionComboBoxChange(Sender: TObject);
|
|
||||||
procedure lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType);
|
procedure lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType);
|
||||||
procedure btnCheckUpdatesClick(Sender: TObject);
|
procedure btnCheckUpdatesClick(Sender: TObject);
|
||||||
procedure LEDButtonClick(Sender: TObject);
|
procedure LEDButtonClick(Sender: TObject);
|
||||||
@ -109,15 +106,8 @@ type
|
|||||||
FProfiles: TProfileList;
|
FProfiles: TProfileList;
|
||||||
FActiveProfile: TProfile;
|
FActiveProfile: TProfile;
|
||||||
FLoadingProfiles: Boolean;
|
FLoadingProfiles: Boolean;
|
||||||
// FStateConsumerTask: IOmniTaskControl;
|
FStateConsumerTask: IOmniTaskControl;
|
||||||
protected
|
protected
|
||||||
// procedure ReadFunctions(AReader: IX2PersistReader; AComboBoxes: TComboBoxArray);
|
|
||||||
// procedure ReadFSXExtra(AReader: IX2PersistReader);
|
|
||||||
// procedure ReadAutoUpdate(AReader: IX2PersistReader);
|
|
||||||
// procedure WriteFunctions(AWriter: IX2PersistWriter; AComboBoxes: TComboBoxArray);
|
|
||||||
// procedure WriteFSXExtra(AWriter: IX2PersistWriter);
|
|
||||||
// procedure WriteAutoUpdate(AWriter: IX2PersistWriter);
|
|
||||||
|
|
||||||
procedure FindLEDControls;
|
procedure FindLEDControls;
|
||||||
procedure LoadProfiles;
|
procedure LoadProfiles;
|
||||||
procedure SaveProfiles;
|
procedure SaveProfiles;
|
||||||
@ -129,11 +119,6 @@ type
|
|||||||
procedure SetDeviceState(const AMessage: string; AFound: Boolean);
|
procedure SetDeviceState(const AMessage: string; AFound: Boolean);
|
||||||
// procedure SetFSXToggleZoomButton(const ADeviceGUID: TGUID; AButtonIndex: Integer; const ADisplayText: string);
|
// procedure SetFSXToggleZoomButton(const ADeviceGUID: TGUID; AButtonIndex: Integer; const ADisplayText: string);
|
||||||
|
|
||||||
// procedure InitializeStateProvider(AProviderClass: TLEDStateProviderClass);
|
|
||||||
// procedure FinalizeStateProvider;
|
|
||||||
|
|
||||||
// procedure UpdateMapping;
|
|
||||||
|
|
||||||
procedure CheckForUpdatesThread(const ATask: IOmniTask);
|
procedure CheckForUpdatesThread(const ATask: IOmniTask);
|
||||||
procedure CheckForUpdates(AReportNoUpdates: Boolean);
|
procedure CheckForUpdates(AReportNoUpdates: Boolean);
|
||||||
|
|
||||||
@ -150,7 +135,7 @@ type
|
|||||||
property ActiveProfile: TProfile read FActiveProfile;
|
property ActiveProfile: TProfile read FActiveProfile;
|
||||||
property EventMonitor: TOmniEventMonitor read FEventMonitor;
|
property EventMonitor: TOmniEventMonitor read FEventMonitor;
|
||||||
property Profiles: TProfileList read FProfiles;
|
property Profiles: TProfileList read FProfiles;
|
||||||
// property StateConsumerTask: IOmniTaskControl read FStateConsumerTask;
|
property StateConsumerTask: IOmniTaskControl read FStateConsumerTask;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -170,7 +155,6 @@ uses
|
|||||||
|
|
||||||
ButtonFunctionFrm,
|
ButtonFunctionFrm,
|
||||||
ConfigConversion,
|
ConfigConversion,
|
||||||
FSXLEDStateProvider,
|
|
||||||
G940LEDStateConsumer,
|
G940LEDStateConsumer,
|
||||||
LEDColorIntf,
|
LEDColorIntf,
|
||||||
LEDFunctionIntf,
|
LEDFunctionIntf,
|
||||||
@ -193,28 +177,13 @@ const
|
|||||||
TEXT_STATE_FOUND = 'Connected';
|
TEXT_STATE_FOUND = 'Connected';
|
||||||
|
|
||||||
|
|
||||||
type
|
|
||||||
TComboBoxFunctionConsumer = class(TInterfacedObject, IFunctionConsumer)
|
|
||||||
private
|
|
||||||
FComboBox: TComboBoxEx;
|
|
||||||
protected
|
|
||||||
{ IFunctionConsumer }
|
|
||||||
procedure SetCategory(const ACategory: string);
|
|
||||||
procedure AddFunction(AFunction: Integer; const ADescription: string);
|
|
||||||
|
|
||||||
property ComboBox: TComboBoxEx read FComboBox;
|
|
||||||
public
|
|
||||||
constructor Create(AComboBox: TComboBoxEx);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{ TMainForm }
|
{ TMainForm }
|
||||||
procedure TMainForm.FormCreate(Sender: TObject);
|
procedure TMainForm.FormCreate(Sender: TObject);
|
||||||
//var
|
var
|
||||||
// consumer: IOmniWorker;
|
consumer: IOmniWorker;
|
||||||
//
|
|
||||||
begin
|
begin
|
||||||
lblVersion.Caption := App.Version.FormatVersion(False);
|
lblVersion.Caption := App.Version.FormatVersion(False);
|
||||||
|
|
||||||
@ -222,12 +191,12 @@ begin
|
|||||||
|
|
||||||
FEventMonitor := TOmniEventMonitor.Create(Self);
|
FEventMonitor := TOmniEventMonitor.Create(Self);
|
||||||
|
|
||||||
// consumer := TG940LEDStateConsumer.Create;
|
consumer := TG940LEDStateConsumer.Create;
|
||||||
// FStateConsumerTask := FEventMonitor.Monitor(CreateTask(consumer)).MsgWait;
|
FStateConsumerTask := FEventMonitor.Monitor(CreateTask(consumer)).MsgWait;
|
||||||
|
|
||||||
EventMonitor.OnTaskMessage := EventMonitorMessage;
|
EventMonitor.OnTaskMessage := EventMonitorMessage;
|
||||||
EventMonitor.OnTaskTerminated := EventMonitorTerminated;
|
EventMonitor.OnTaskTerminated := EventMonitorTerminated;
|
||||||
// StateConsumerTask.Run;
|
StateConsumerTask.Run;
|
||||||
|
|
||||||
FindLEDControls;
|
FindLEDControls;
|
||||||
|
|
||||||
@ -235,6 +204,7 @@ begin
|
|||||||
FProfiles := TProfileList.Create(True);
|
FProfiles := TProfileList.Create(True);
|
||||||
LoadProfiles;
|
LoadProfiles;
|
||||||
|
|
||||||
|
FStateConsumerTask.Comm.Send(TM_LOADPROFILE, ActiveProfile);
|
||||||
// LoadFunctions(TFSXLEDStateProvider, FFSXComboBoxes);
|
// LoadFunctions(TFSXLEDStateProvider, FFSXComboBoxes);
|
||||||
// LoadDefaultProfile;
|
// LoadDefaultProfile;
|
||||||
end;
|
end;
|
||||||
@ -549,6 +519,7 @@ begin
|
|||||||
if TButtonFunctionForm.Execute(ActiveProfile, buttonIndex) then
|
if TButtonFunctionForm.Execute(ActiveProfile, buttonIndex) then
|
||||||
begin
|
begin
|
||||||
UpdateButton(ActiveProfile, buttonIndex);
|
UpdateButton(ActiveProfile, buttonIndex);
|
||||||
|
FStateConsumerTask.Comm.Send(TM_LOADPROFILE, ActiveProfile);
|
||||||
SaveProfiles;
|
SaveProfiles;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -657,20 +628,20 @@ end;
|
|||||||
procedure TMainForm.EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
|
procedure TMainForm.EventMonitorMessage(const task: IOmniTaskControl; const msg: TOmniMessage);
|
||||||
begin
|
begin
|
||||||
case msg.MsgID of
|
case msg.MsgID of
|
||||||
MSG_NOTIFY_DEVICESTATE: HandleDeviceStateMessage(task, msg);
|
TM_NOTIFY_DEVICESTATE: HandleDeviceStateMessage(task, msg);
|
||||||
MSG_RUN_IN_MAINTHREAD: HandleRunInMainThreadMessage(task, msg);
|
// MSG_RUN_IN_MAINTHREAD: HandleRunInMainThreadMessage(task, msg);
|
||||||
MSG_PROVIDER_KILLED: HandleProviderKilled(task, msg);
|
// MSG_PROVIDER_KILLED: HandleProviderKilled(task, msg);
|
||||||
|
|
||||||
MSG_UPDATE:
|
MSG_UPDATE:
|
||||||
if MessageBox(Self.Handle, 'An update is available on the G940 LED Control website.'#13#10'Do you want to go there now?',
|
if MessageBox(Self.Handle, 'An update is available on the G940 LED Control website.'#13#10'Do you want to go there now?',
|
||||||
'Update available', MB_YESNO or MB_ICONINFORMATION) = ID_YES then
|
'Update available', MB_YESNO or MB_ICONINFORMATION) = ID_YES then
|
||||||
ShellExecute(Self.Handle, 'open', PChar('http://g940.x2software.net/#download'), nil, nil, SW_SHOWNORMAL);
|
ShellExecute(Self.Handle, 'open', PChar('http://g940.x2software.net/#download'), nil, nil, SW_SHOWNORMAL);
|
||||||
|
|
||||||
MSG_NOUPDATE:
|
// MSG_NOUPDATE:
|
||||||
if msg.MsgData.AsBoolean then
|
// if msg.MsgData.AsBoolean then
|
||||||
MessageBox(Self.Handle, 'You are using the latest version.', 'No update available', MB_OK or MB_ICONINFORMATION)
|
// MessageBox(Self.Handle, 'You are using the latest version.', 'No update available', MB_OK or MB_ICONINFORMATION)
|
||||||
else
|
// else
|
||||||
MessageBox(Self.Handle, 'Failed to check for updates. Maybe try again later?', 'Uh-oh', MB_OK or MB_ICONWARNING);
|
// MessageBox(Self.Handle, 'Failed to check for updates. Maybe try again later?', 'Uh-oh', MB_OK or MB_ICONWARNING);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -748,53 +719,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMainForm.FunctionComboBoxChange(Sender: TObject);
|
|
||||||
var
|
|
||||||
comboBox: TComboBoxEx;
|
|
||||||
|
|
||||||
begin
|
|
||||||
comboBox := TComboBoxEx(Sender);
|
|
||||||
if comboBox.ItemIndex > -1 then
|
|
||||||
begin
|
|
||||||
if not Assigned(comboBox.ItemsEx[comboBox.ItemIndex].Data) then
|
|
||||||
comboBox.ItemIndex := Succ(comboBox.ItemIndex);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TMainForm.lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType);
|
procedure TMainForm.lblLinkLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType);
|
||||||
begin
|
begin
|
||||||
ShellExecute(Self.Handle, 'open', PChar(Link), nil, nil, SW_SHOWNORMAL);
|
ShellExecute(Self.Handle, 'open', PChar(Link), nil, nil, SW_SHOWNORMAL);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TComboBoxFunctionConsumer }
|
|
||||||
constructor TComboBoxFunctionConsumer.Create(AComboBox: TComboBoxEx);
|
|
||||||
begin
|
|
||||||
inherited Create;
|
|
||||||
|
|
||||||
FComboBox := AComboBox;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TComboBoxFunctionConsumer.SetCategory(const ACategory: string);
|
|
||||||
begin
|
|
||||||
with ComboBox.ItemsEx.Add do
|
|
||||||
begin
|
|
||||||
Caption := ACategory;
|
|
||||||
Data := nil;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TComboBoxFunctionConsumer.AddFunction(AFunction: Integer; const ADescription: string);
|
|
||||||
begin
|
|
||||||
with ComboBox.ItemsEx.Add do
|
|
||||||
begin
|
|
||||||
Caption := ADescription;
|
|
||||||
Indent := 1;
|
|
||||||
Data := Pointer(AFunction);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -5,11 +5,8 @@ uses
|
|||||||
MainFrm in 'Forms\MainFrm.pas' {MainForm},
|
MainFrm in 'Forms\MainFrm.pas' {MainForm},
|
||||||
LogiJoystickDLL in '..\Shared\LogiJoystickDLL.pas',
|
LogiJoystickDLL in '..\Shared\LogiJoystickDLL.pas',
|
||||||
SimConnect in '..\Shared\SimConnect.pas',
|
SimConnect in '..\Shared\SimConnect.pas',
|
||||||
FSXLEDStateProvider in 'Units\FSXLEDStateProvider.pas',
|
|
||||||
G940LEDStateConsumer in 'Units\G940LEDStateConsumer.pas',
|
G940LEDStateConsumer in 'Units\G940LEDStateConsumer.pas',
|
||||||
LEDFunctionMap in 'Units\LEDFunctionMap.pas',
|
|
||||||
LEDStateConsumer in 'Units\LEDStateConsumer.pas',
|
LEDStateConsumer in 'Units\LEDStateConsumer.pas',
|
||||||
LEDStateProvider in 'Units\LEDStateProvider.pas',
|
|
||||||
LEDColorIntf in 'Units\LEDColorIntf.pas',
|
LEDColorIntf in 'Units\LEDColorIntf.pas',
|
||||||
LEDColor in 'Units\LEDColor.pas',
|
LEDColor in 'Units\LEDColor.pas',
|
||||||
LEDFunctionIntf in 'Units\LEDFunctionIntf.pas',
|
LEDFunctionIntf in 'Units\LEDFunctionIntf.pas',
|
||||||
|
@ -165,11 +165,8 @@
|
|||||||
</DCCReference>
|
</DCCReference>
|
||||||
<DCCReference Include="..\Shared\LogiJoystickDLL.pas"/>
|
<DCCReference Include="..\Shared\LogiJoystickDLL.pas"/>
|
||||||
<DCCReference Include="..\Shared\SimConnect.pas"/>
|
<DCCReference Include="..\Shared\SimConnect.pas"/>
|
||||||
<DCCReference Include="Units\FSXLEDStateProvider.pas"/>
|
|
||||||
<DCCReference Include="Units\G940LEDStateConsumer.pas"/>
|
<DCCReference Include="Units\G940LEDStateConsumer.pas"/>
|
||||||
<DCCReference Include="Units\LEDFunctionMap.pas"/>
|
|
||||||
<DCCReference Include="Units\LEDStateConsumer.pas"/>
|
<DCCReference Include="Units\LEDStateConsumer.pas"/>
|
||||||
<DCCReference Include="Units\LEDStateProvider.pas"/>
|
|
||||||
<DCCReference Include="Units\LEDColorIntf.pas"/>
|
<DCCReference Include="Units\LEDColorIntf.pas"/>
|
||||||
<DCCReference Include="Units\LEDColor.pas"/>
|
<DCCReference Include="Units\LEDColor.pas"/>
|
||||||
<DCCReference Include="Units\LEDFunctionIntf.pas"/>
|
<DCCReference Include="Units\LEDFunctionIntf.pas"/>
|
||||||
|
@ -12,23 +12,24 @@ const
|
|||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TLEDColorDynArray = array of TLEDColor;
|
TStaticLEDColorDynArray = array of TStaticLEDColor;
|
||||||
|
|
||||||
|
|
||||||
TDynamicLEDColor = class(TCustomDynamicLEDColor)
|
TDynamicLEDColor = class(TCustomLEDStateDynamicColor)
|
||||||
private
|
private
|
||||||
FCycleColors: TLEDColorDynArray;
|
FCycleColors: TStaticLEDColorDynArray;
|
||||||
FCycleIndex: Integer;
|
FCycleIndex: Integer;
|
||||||
FTickInterval: Integer;
|
FTickInterval: Integer;
|
||||||
FTickCount: Integer;
|
FTickCount: Integer;
|
||||||
protected
|
protected
|
||||||
{ ILEDState }
|
{ ILEDState }
|
||||||
function GetColor: TLEDColor; override;
|
function GetCurrentColor: TStaticLEDColor; override;
|
||||||
|
|
||||||
{ ITickLEDState }
|
{ ITickLEDState }
|
||||||
|
procedure Reset; override;
|
||||||
procedure Tick; override;
|
procedure Tick; override;
|
||||||
public
|
public
|
||||||
constructor Create(ACycleColors: TLEDColorDynArray; ATickInterval: Integer = TICKINTERVAL_NORMAL);
|
constructor Create(ACycleColors: TStaticLEDColorDynArray; ATickInterval: Integer = TICKINTERVAL_NORMAL);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ uses
|
|||||||
|
|
||||||
|
|
||||||
{ TDynamicLEDState }
|
{ TDynamicLEDState }
|
||||||
constructor TDynamicLEDColor.Create(ACycleColors: TLEDColorDynArray; ATickInterval: Integer);
|
constructor TDynamicLEDColor.Create(ACycleColors: TStaticLEDColorDynArray; ATickInterval: Integer);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
|
||||||
@ -49,16 +50,22 @@ begin
|
|||||||
FCycleColors := ACycleColors;
|
FCycleColors := ACycleColors;
|
||||||
FCycleIndex := Low(FCycleColors);
|
FCycleIndex := Low(FCycleColors);
|
||||||
FTickInterval := ATickInterval;
|
FTickInterval := ATickInterval;
|
||||||
FTickCount := 0;
|
Reset;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TDynamicLEDColor.GetColor: TLEDColor;
|
function TDynamicLEDColor.GetCurrentColor: TStaticLEDColor;
|
||||||
begin
|
begin
|
||||||
Result := FCycleColors[FCycleIndex];
|
Result := FCycleColors[FCycleIndex];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDynamicLEDColor.Reset;
|
||||||
|
begin
|
||||||
|
FCycleIndex := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TDynamicLEDColor.Tick;
|
procedure TDynamicLEDColor.Tick;
|
||||||
begin
|
begin
|
||||||
Inc(FTickCount);
|
Inc(FTickCount);
|
||||||
|
@ -8,46 +8,31 @@ uses
|
|||||||
OtlComm,
|
OtlComm,
|
||||||
OtlTaskControl,
|
OtlTaskControl,
|
||||||
|
|
||||||
LEDFunctionMap,
|
LEDStateConsumer;
|
||||||
LEDStateConsumer,
|
|
||||||
LEDStateProvider;
|
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
MSG_FINDTHROTTLEDEVICE = MSG_CONSUMER_OFFSET + 1;
|
TM_FINDTHROTTLEDEVICE = 2001;
|
||||||
MSG_NOTIFY_DEVICESTATE = MSG_CONSUMER_OFFSET + 2;
|
TM_NOTIFY_DEVICESTATE = 2002;
|
||||||
MSG_TIMER_BLINK = MSG_CONSUMER_OFFSET + 3;
|
|
||||||
|
|
||||||
TIMER_BLINK = TIMER_CONSUMER_OFFSET + 1;
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TG940LEDStateConsumer = class(TLEDStateConsumer)
|
TG940LEDStateConsumer = class(TLEDStateConsumer)
|
||||||
private
|
private
|
||||||
FDirectInput: IDirectInput8;
|
FDirectInput: IDirectInput8;
|
||||||
FThrottleDevice: IDirectInputDevice8;
|
FThrottleDevice: IDirectInputDevice8;
|
||||||
|
|
||||||
FRed: Byte;
|
|
||||||
FGreen: Byte;
|
|
||||||
|
|
||||||
FBlinkTimerStarted: Boolean;
|
|
||||||
FBlinkCounter: Integer;
|
|
||||||
protected
|
protected
|
||||||
procedure MsgFindThrottleDevice(var msg: TOmniMessage); message MSG_FINDTHROTTLEDEVICE;
|
procedure MsgFindThrottleDevice(var msg: TOmniMessage); message TM_FINDTHROTTLEDEVICE;
|
||||||
procedure MsgTimerBlink(var msg: TOmniMessage); message MSG_TIMER_BLINK;
|
|
||||||
protected
|
protected
|
||||||
function Initialize: Boolean; override;
|
function Initialize: Boolean; override;
|
||||||
procedure ResetLEDState; override;
|
|
||||||
procedure LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); override;
|
|
||||||
procedure Changed; override;
|
|
||||||
|
|
||||||
procedure StartBlinkTimer;
|
|
||||||
procedure StopBlinkTimer;
|
|
||||||
|
|
||||||
procedure FindThrottleDevice;
|
procedure FindThrottleDevice;
|
||||||
procedure FoundThrottleDevice(ADeviceGUID: TGUID);
|
procedure FoundThrottleDevice(ADeviceGUID: TGUID);
|
||||||
|
|
||||||
procedure SetDeviceState(AState: Integer);
|
procedure SetDeviceState(AState: Integer);
|
||||||
|
|
||||||
|
procedure Update; override;
|
||||||
|
|
||||||
property DirectInput: IDirectInput8 read FDirectInput;
|
property DirectInput: IDirectInput8 read FDirectInput;
|
||||||
property ThrottleDevice: IDirectInputDevice8 read FThrottleDevice;
|
property ThrottleDevice: IDirectInputDevice8 read FThrottleDevice;
|
||||||
end;
|
end;
|
||||||
@ -58,8 +43,8 @@ const
|
|||||||
DEVICESTATE_FOUND = 1;
|
DEVICESTATE_FOUND = 1;
|
||||||
DEVICESTATE_NOTFOUND = 2;
|
DEVICESTATE_NOTFOUND = 2;
|
||||||
|
|
||||||
EXIT_ERROR_LOGIJOYSTICKDLL = EXIT_CONSUMER_OFFSET + 1;
|
EXIT_ERROR_LOGIJOYSTICKDLL = 9001;
|
||||||
EXIT_ERROR_DIRECTINPUT = EXIT_CONSUMER_OFFSET + 2;
|
EXIT_ERROR_DIRECTINPUT = 9002;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -68,15 +53,18 @@ uses
|
|||||||
Windows,
|
Windows,
|
||||||
|
|
||||||
OtlCommon,
|
OtlCommon,
|
||||||
|
OtlTask,
|
||||||
|
|
||||||
|
LEDColorIntf,
|
||||||
LogiJoystickDLL;
|
LogiJoystickDLL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
BLINK_INTERVAL = 500;
|
G940_BUTTONCOUNT = 8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(*
|
||||||
type
|
type
|
||||||
TRunInMainThreadSetLEDs = class(TOmniWaitableValue, IRunInMainThread)
|
TRunInMainThreadSetLEDs = class(TOmniWaitableValue, IRunInMainThread)
|
||||||
private
|
private
|
||||||
@ -89,6 +77,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(ADevice: IDirectInputDevice8; ARed, AGreen: Byte);
|
constructor Create(ADevice: IDirectInputDevice8; ARed, AGreen: Byte);
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
|
|
||||||
function EnumDevicesProc(var lpddi: TDIDeviceInstanceW; pvRef: Pointer): BOOL; stdcall;
|
function EnumDevicesProc(var lpddi: TDIDeviceInstanceW; pvRef: Pointer): BOOL; stdcall;
|
||||||
@ -134,10 +123,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Result := True;
|
Result := True;
|
||||||
Task.Comm.OtherEndpoint.Send(MSG_FINDTHROTTLEDEVICE);
|
Task.Comm.OtherEndpoint.Send(TM_FINDTHROTTLEDEVICE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
procedure TG940LEDStateConsumer.ResetLEDState;
|
procedure TG940LEDStateConsumer.ResetLEDState;
|
||||||
begin
|
begin
|
||||||
FRed := 0;
|
FRed := 0;
|
||||||
@ -200,36 +190,18 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
procedure TG940LEDStateConsumer.Changed;
|
procedure TG940LEDStateConsumer.Changed;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
|
|
||||||
if Assigned(ThrottleDevice) then
|
if Assigned(ThrottleDevice) then
|
||||||
{ Logitech SDK will not change the color outside of the main thread }
|
{ Logitech SDK will not change the color outside of the main thread
|
||||||
RunInMainThread(TRunInMainThreadSetLEDs.Create(ThrottleDevice, FRed, FGreen), Destroying);
|
RunInMainThread(TRunInMainThreadSetLEDs.Create(ThrottleDevice, FRed, FGreen), Destroying);
|
||||||
end;
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
procedure TG940LEDStateConsumer.StartBlinkTimer;
|
|
||||||
begin
|
|
||||||
if FBlinkTimerStarted then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
FBlinkCounter := 0;
|
|
||||||
Task.SetTimer(TIMER_BLINK, BLINK_INTERVAL, MSG_TIMER_BLINK);
|
|
||||||
FBlinkTimerStarted := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TG940LEDStateConsumer.StopBlinkTimer;
|
|
||||||
begin
|
|
||||||
if not FBlinkTimerStarted then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
Task.ClearTimer(TIMER_BLINK);
|
|
||||||
FBlinkTimerStarted := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TG940LEDStateConsumer.FindThrottleDevice;
|
procedure TG940LEDStateConsumer.FindThrottleDevice;
|
||||||
@ -243,7 +215,7 @@ begin
|
|||||||
if not Assigned(ThrottleDevice) then
|
if not Assigned(ThrottleDevice) then
|
||||||
SetDeviceState(DEVICESTATE_NOTFOUND)
|
SetDeviceState(DEVICESTATE_NOTFOUND)
|
||||||
else
|
else
|
||||||
Changed;
|
Update;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -256,7 +228,54 @@ end;
|
|||||||
|
|
||||||
procedure TG940LEDStateConsumer.SetDeviceState(AState: Integer);
|
procedure TG940LEDStateConsumer.SetDeviceState(AState: Integer);
|
||||||
begin
|
begin
|
||||||
Task.Comm.Send(MSG_NOTIFY_DEVICESTATE, AState);
|
Task.Comm.Send(TM_NOTIFY_DEVICESTATE, AState);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TG940LEDStateConsumer.Update;
|
||||||
|
|
||||||
|
procedure SetBit(var AMask: Byte; ABit: Integer); inline;
|
||||||
|
begin
|
||||||
|
AMask := AMask or (1 shl ABit)
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
var
|
||||||
|
red: Byte;
|
||||||
|
green: Byte;
|
||||||
|
buttonIndex: Integer;
|
||||||
|
buttonColor: TStaticLEDColor;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if not Assigned(ThrottleDevice) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
red := 0;
|
||||||
|
green := 0;
|
||||||
|
|
||||||
|
for buttonIndex := 0 to Pred(G940_BUTTONCOUNT) do
|
||||||
|
begin
|
||||||
|
if buttonIndex >= ButtonColors.Count then
|
||||||
|
buttonColor := lcOff
|
||||||
|
else
|
||||||
|
buttonColor := (ButtonColors[buttonIndex] as ILEDStateColor).GetCurrentColor;
|
||||||
|
|
||||||
|
case buttonColor of
|
||||||
|
lcGreen:
|
||||||
|
SetBit(green, buttonIndex);
|
||||||
|
|
||||||
|
lcAmber:
|
||||||
|
begin
|
||||||
|
SetBit(green, buttonIndex);
|
||||||
|
SetBit(red, buttonIndex);
|
||||||
|
end;
|
||||||
|
|
||||||
|
lcRed:
|
||||||
|
SetBit(red, buttonIndex);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
SetLEDs(ThrottleDevice, red, green);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -266,52 +285,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TG940LEDStateConsumer.MsgTimerBlink(var msg: TOmniMessage);
|
|
||||||
var
|
|
||||||
warningState: TLEDState;
|
|
||||||
errorState: TLEDState;
|
|
||||||
ledIndex: Integer;
|
|
||||||
state: TLEDState;
|
|
||||||
|
|
||||||
begin
|
|
||||||
Inc(FBlinkCounter);
|
|
||||||
if FBlinkCounter > 3 then
|
|
||||||
FBlinkCounter := 0;
|
|
||||||
|
|
||||||
warningState := lsOff;
|
|
||||||
errorState := lsOff;
|
|
||||||
|
|
||||||
{ Error lights blink twice as fast }
|
|
||||||
if (FBlinkCounter in [0, 1]) then
|
|
||||||
warningState := lsAmber;
|
|
||||||
|
|
||||||
if (FBlinkCounter in [0, 2]) then
|
|
||||||
errorState := lsRed;
|
|
||||||
|
|
||||||
if StateMap.FindFirst([lsWarning, lsError], ledIndex, state) then
|
|
||||||
begin
|
|
||||||
BeginUpdate;
|
|
||||||
try
|
|
||||||
repeat
|
|
||||||
case state of
|
|
||||||
lsWarning:
|
|
||||||
if StateMap.GetState(ledIndex) <> warningState then
|
|
||||||
LEDStateChanged(ledIndex, warningState);
|
|
||||||
|
|
||||||
lsError:
|
|
||||||
if StateMap.GetState(ledIndex) <> errorState then
|
|
||||||
LEDStateChanged(ledIndex, errorState);
|
|
||||||
end;
|
|
||||||
until not StateMap.FindNext([lsWarning, lsError], ledIndex, state);
|
|
||||||
finally
|
|
||||||
EndUpdate;
|
|
||||||
end;
|
|
||||||
end else
|
|
||||||
StopBlinkTimer;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{ TRunInMainThreadSetLEDs }
|
{ TRunInMainThreadSetLEDs }
|
||||||
|
(*
|
||||||
constructor TRunInMainThreadSetLEDs.Create(ADevice: IDirectInputDevice8; ARed, AGreen: Byte);
|
constructor TRunInMainThreadSetLEDs.Create(ADevice: IDirectInputDevice8; ARed, AGreen: Byte);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
@ -326,5 +301,6 @@ procedure TRunInMainThreadSetLEDs.Execute;
|
|||||||
begin
|
begin
|
||||||
SetLEDs(FDevice, FRed, FGreen);
|
SetLEDs(FDevice, FRed, FGreen);
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -8,16 +8,17 @@ uses
|
|||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TCustomLEDColor = class(TInterfacedObject, ILEDColor)
|
TCustomLEDStateColor = class(TInterfacedObject, ILEDStateColor)
|
||||||
protected
|
protected
|
||||||
{ ILEDState }
|
{ ILEDState }
|
||||||
function GetColor: TLEDColor; virtual; abstract;
|
function GetCurrentColor: TStaticLEDColor; virtual; abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
TCustomDynamicLEDColor = class(TCustomLEDColor, IDynamicLEDColor)
|
TCustomLEDStateDynamicColor = class(TCustomLEDStateColor, ILEDStateDynamicColor)
|
||||||
protected
|
protected
|
||||||
{ ITickLEDState }
|
{ ITickLEDState }
|
||||||
|
procedure Reset; virtual; abstract;
|
||||||
procedure Tick; virtual; abstract;
|
procedure Tick; virtual; abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -11,14 +11,15 @@ type
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ILEDColor = interface
|
ILEDStateColor = interface
|
||||||
['{B40DF462-B660-4002-A6B9-DD30AC69E8DB}']
|
['{B40DF462-B660-4002-A6B9-DD30AC69E8DB}']
|
||||||
function GetColor: TLEDColor;
|
function GetCurrentColor: TStaticLEDColor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
IDynamicLEDColor = interface(ILEDColor)
|
ILEDStateDynamicColor = interface(ILEDStateColor)
|
||||||
['{9770E851-580D-4803-9979-0C608CB108A0}']
|
['{9770E851-580D-4803-9979-0C608CB108A0}']
|
||||||
|
procedure Reset;
|
||||||
procedure Tick;
|
procedure Tick;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -8,13 +8,13 @@ uses
|
|||||||
type
|
type
|
||||||
TLEDColorPool = class(TObject)
|
TLEDColorPool = class(TObject)
|
||||||
private
|
private
|
||||||
FStates: array[TLEDColor] of ILEDColor;
|
FStates: array[TLEDColor] of ILEDStateColor;
|
||||||
protected
|
protected
|
||||||
class function Instance: TLEDColorPool;
|
class function Instance: TLEDColorPool;
|
||||||
|
|
||||||
function DoGetColor(AColor: TLEDColor): ILEDColor;
|
function DoGetColor(AColor: TLEDColor): ILEDStateColor;
|
||||||
public
|
public
|
||||||
class function GetColor(AColor: TLEDColor): ILEDColor; overload;
|
class function GetColor(AColor: TLEDColor): ILEDStateColor; overload;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ var
|
|||||||
|
|
||||||
|
|
||||||
{ TLEDStatePool }
|
{ TLEDStatePool }
|
||||||
class function TLEDColorPool.GetColor(AColor: TLEDColor): ILEDColor;
|
class function TLEDColorPool.GetColor(AColor: TLEDColor): ILEDStateColor;
|
||||||
begin
|
begin
|
||||||
Result := Instance.DoGetColor(AColor);
|
Result := Instance.DoGetColor(AColor);
|
||||||
end;
|
end;
|
||||||
@ -46,9 +46,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TLEDColorPool.DoGetColor(AColor: TLEDColor): ILEDColor;
|
function TLEDColorPool.DoGetColor(AColor: TLEDColor): ILEDStateColor;
|
||||||
|
|
||||||
function GetFlashingCycle(AColor: TLEDColor): TLEDColorDynArray;
|
function GetFlashingCycle(AColor: TLEDColor): TStaticLEDColorDynArray;
|
||||||
begin
|
begin
|
||||||
SetLength(Result, 2);
|
SetLength(Result, 2);
|
||||||
Result[0] := AColor;
|
Result[0] := AColor;
|
||||||
@ -56,16 +56,16 @@ function TLEDColorPool.DoGetColor(AColor: TLEDColor): ILEDColor;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
state: ILEDColor;
|
state: ILEDStateColor;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if not Assigned(FStates[AColor]) then
|
if not Assigned(FStates[AColor]) then
|
||||||
begin
|
begin
|
||||||
case AColor of
|
case AColor of
|
||||||
lcOff: state := TStaticLEDColor.Create(lcOff);
|
lcOff: state := TLEDStateStaticColor.Create(lcOff);
|
||||||
lcGreen: state := TStaticLEDColor.Create(lcGreen);
|
lcGreen: state := TLEDStateStaticColor.Create(lcGreen);
|
||||||
lcAmber: state := TStaticLEDColor.Create(lcAmber);
|
lcAmber: state := TLEDStateStaticColor.Create(lcAmber);
|
||||||
lcRed: state := TStaticLEDColor.Create(lcRed);
|
lcRed: state := TLEDStateStaticColor.Create(lcRed);
|
||||||
|
|
||||||
lcFlashingGreenFast: state := TDynamicLEDColor.Create(GetFlashingCycle(lcGreen), TICKINTERVAL_FAST);
|
lcFlashingGreenFast: state := TDynamicLEDColor.Create(GetFlashingCycle(lcGreen), TICKINTERVAL_FAST);
|
||||||
lcFlashingGreenNormal: state := TDynamicLEDColor.Create(GetFlashingCycle(lcGreen), TICKINTERVAL_NORMAL);
|
lcFlashingGreenNormal: state := TDynamicLEDColor.Create(GetFlashingCycle(lcGreen), TICKINTERVAL_NORMAL);
|
||||||
|
@ -1,228 +0,0 @@
|
|||||||
unit LEDFunctionMap;
|
|
||||||
|
|
||||||
interface
|
|
||||||
uses
|
|
||||||
Classes,
|
|
||||||
SyncObjs,
|
|
||||||
|
|
||||||
X2UtHashes;
|
|
||||||
|
|
||||||
|
|
||||||
type
|
|
||||||
TLEDState = (lsOff, lsGreen, lsAmber, lsRed, lsWarning, lsError);
|
|
||||||
TLEDStateSet = set of TLEDState;
|
|
||||||
|
|
||||||
|
|
||||||
TLEDFunctionMap = class(TObject)
|
|
||||||
private
|
|
||||||
FFunctions: TX2IIHash;
|
|
||||||
public
|
|
||||||
constructor Create;
|
|
||||||
destructor Destroy; override;
|
|
||||||
|
|
||||||
procedure Clear;
|
|
||||||
|
|
||||||
procedure SetFunction(ALEDIndex, AFunction: Integer);
|
|
||||||
function GetFunction(ALEDIndex: Integer): Integer;
|
|
||||||
|
|
||||||
function HasFunction(AFunction: Integer): Boolean; overload;
|
|
||||||
function HasFunction(AFunctions: array of Integer): Boolean; overload;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
function HasStates(AStates: TLEDStateSet): Boolean;
|
|
||||||
function FindFirst(AStates: TLEDStateSet; out ALEDIndex: Integer; out AState: TLEDState): Boolean;
|
|
||||||
function FindNext(AStates: TLEDStateSet; out ALEDIndex: Integer; out AState: TLEDState): Boolean;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
const
|
|
||||||
FUNCTION_NONE = 0;
|
|
||||||
FUNCTION_OFF = 1;
|
|
||||||
FUNCTION_RED = 2;
|
|
||||||
FUNCTION_AMBER = 3;
|
|
||||||
FUNCTION_GREEN = 4;
|
|
||||||
|
|
||||||
{ Note: if this offset ever changes, make sure to write a conversion for
|
|
||||||
existing configurations. And probably reserve a bit more. }
|
|
||||||
FUNCTION_PROVIDER_OFFSET = FUNCTION_GREEN;
|
|
||||||
|
|
||||||
|
|
||||||
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(AFunctions: array of Integer): Boolean;
|
|
||||||
var
|
|
||||||
functionNo: Integer;
|
|
||||||
|
|
||||||
begin
|
|
||||||
Result := False;
|
|
||||||
|
|
||||||
for functionNo in AFunctions do
|
|
||||||
begin
|
|
||||||
Result := HasFunction(functionNo);
|
|
||||||
if Result then
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
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 := FindNext(AFunction, ALEDIndex);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function TLEDFunctionMap.FindNext(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;
|
|
||||||
|
|
||||||
|
|
||||||
function TLEDStateMap.HasStates(AStates: TLEDStateSet): Boolean;
|
|
||||||
var
|
|
||||||
ledIndex: Integer;
|
|
||||||
state: TLEDState;
|
|
||||||
|
|
||||||
begin
|
|
||||||
Result := FindFirst(AStates, ledIndex, state);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function TLEDStateMap.FindFirst(AStates: TLEDStateSet; out ALEDIndex: Integer; out AState: TLEDState): Boolean;
|
|
||||||
begin
|
|
||||||
FStates.First;
|
|
||||||
Result := FindNext(AStates, ALEDIndex, AState);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function TLEDStateMap.FindNext(AStates: TLEDStateSet; out ALEDIndex: Integer; out AState: TLEDState): Boolean;
|
|
||||||
begin
|
|
||||||
Result := False;
|
|
||||||
|
|
||||||
while FStates.Next do
|
|
||||||
if TLEDState(FStates.CurrentValue) in AStates then
|
|
||||||
begin
|
|
||||||
ALEDIndex := FStates.CurrentKey;
|
|
||||||
AState := TLEDState(FStates.CurrentValue);
|
|
||||||
Result := True;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
@ -33,12 +33,12 @@ type
|
|||||||
|
|
||||||
TLEDStateWorker = class(TCustomLEDState, ILEDStateWorker)
|
TLEDStateWorker = class(TCustomLEDState, ILEDStateWorker)
|
||||||
private
|
private
|
||||||
FColor: ILEDColor;
|
FColor: ILEDStateColor;
|
||||||
protected
|
protected
|
||||||
{ ILEDStateWorker }
|
{ ILEDStateWorker }
|
||||||
function GetColor: ILEDColor;
|
function GetColor: ILEDStateColor;
|
||||||
public
|
public
|
||||||
constructor Create(const AUID: string; AColor: ILEDColor);
|
constructor Create(const AUID: string; AColor: ILEDStateColor);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
{ TLEDStateWorker }
|
{ TLEDStateWorker }
|
||||||
constructor TLEDStateWorker.Create(const AUID: string; AColor: ILEDColor);
|
constructor TLEDStateWorker.Create(const AUID: string; AColor: ILEDStateColor);
|
||||||
begin
|
begin
|
||||||
inherited Create(AUID);
|
inherited Create(AUID);
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TLEDStateWorker.GetColor: ILEDColor;
|
function TLEDStateWorker.GetColor: ILEDStateColor;
|
||||||
begin
|
begin
|
||||||
Result := FColor;
|
Result := FColor;
|
||||||
end;
|
end;
|
||||||
|
@ -2,29 +2,22 @@ unit LEDStateConsumer;
|
|||||||
|
|
||||||
interface
|
interface
|
||||||
uses
|
uses
|
||||||
|
System.Classes,
|
||||||
|
|
||||||
OtlComm,
|
OtlComm,
|
||||||
OtlCommon,
|
OtlCommon,
|
||||||
OtlTaskControl,
|
OtlTaskControl,
|
||||||
|
|
||||||
LEDFunctionMap,
|
LEDColorIntf,
|
||||||
LEDStateProvider;
|
LEDFunctionIntf,
|
||||||
|
Profile;
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
MSG_CLEAR_FUNCTIONS = 1001;
|
TM_LOADPROFILE = 1001;
|
||||||
MSG_SET_FUNCTION = 1002;
|
TM_TICK = 1002;
|
||||||
MSG_INITIALIZE_PROVIDER = 1003;
|
|
||||||
MSG_FINALIZE_PROVIDER = 1004;
|
|
||||||
MSG_PROCESS_MESSAGES = 1005;
|
|
||||||
MSG_FINALIZE = 1006;
|
|
||||||
|
|
||||||
MSG_PROVIDER_KILLED = 1007;
|
TIMER_TICK = 101;
|
||||||
MSG_RUN_IN_MAINTHREAD = 1008;
|
|
||||||
|
|
||||||
MSG_CONSUMER_OFFSET = MSG_RUN_IN_MAINTHREAD;
|
|
||||||
|
|
||||||
TIMER_PROCESSMESSAGES = 1001;
|
|
||||||
TIMER_CONSUMER_OFFSET = TIMER_PROCESSMESSAGES;
|
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -34,318 +27,217 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
TLEDStateConsumer = class(TOmniWorker, ILEDStateConsumer)
|
TLEDStateConsumer = class(TOmniWorker)
|
||||||
private
|
private
|
||||||
FFunctionMap: TLEDFunctionMap;
|
FButtonWorkers: TInterfaceList;
|
||||||
FStateMap: TLEDStateMap;
|
FButtonColors: TInterfaceList;
|
||||||
FProvider: TLEDStateProvider;
|
FHasTickTimer: Boolean;
|
||||||
FTimerSet: Boolean;
|
|
||||||
FChanged: Boolean;
|
|
||||||
FUpdateCount: Integer;
|
|
||||||
FDestroying: Boolean;
|
|
||||||
protected
|
protected
|
||||||
procedure MsgClearFunctions(var msg: TOmniMessage); message MSG_CLEAR_FUNCTIONS;
|
function Initialize: Boolean; override;
|
||||||
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 MsgFinalize(var msg: TOmniMessage); message MSG_FINALIZE;
|
|
||||||
|
|
||||||
procedure Cleanup; override;
|
procedure Cleanup; override;
|
||||||
|
|
||||||
procedure InitializeProvider(AProviderClass: TLEDStateProviderClass);
|
function CreateWorker(AProfileButton: TProfileButton): ILEDFunctionWorker;
|
||||||
procedure FinalizeProvider;
|
|
||||||
|
|
||||||
procedure RunInMainThread(AExecutor: IRunInMainThread; AWait: Boolean = False);
|
property ButtonWorkers: TInterfaceList read FButtonWorkers;
|
||||||
procedure InitializeLEDState; virtual;
|
property ButtonColors: TInterfaceList read FButtonColors;
|
||||||
procedure ResetLEDState; virtual;
|
property HasTickTimer: Boolean read FHasTickTimer;
|
||||||
procedure LEDStateChanged(ALEDIndex: Integer; AState: TLEDState); virtual;
|
protected
|
||||||
procedure Changed; virtual;
|
procedure Changed; virtual;
|
||||||
|
procedure Update; virtual; abstract;
|
||||||
{ ILEDStateConsumer }
|
protected
|
||||||
function GetFunctionMap: TLEDFunctionMap;
|
procedure TMLoadProfile(var Msg: TOmniMessage); message TM_LOADPROFILE;
|
||||||
procedure SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
procedure TMTick(var Msg: TOmniMessage); message TM_TICK;
|
||||||
|
|
||||||
property Destroying: Boolean read FDestroying;
|
|
||||||
property FunctionMap: TLEDFunctionMap read GetFunctionMap;
|
|
||||||
property StateMap: TLEDStateMap read FStateMap;
|
|
||||||
property Provider: TLEDStateProvider read FProvider;
|
|
||||||
property UpdateCount: Integer read FUpdateCount write FUpdateCount;
|
|
||||||
public
|
|
||||||
constructor Create;
|
|
||||||
|
|
||||||
procedure BeginUpdate;
|
|
||||||
procedure EndUpdate;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure ClearFunctions(AConsumer: IOmniTaskControl);
|
|
||||||
procedure SetFunction(AConsumer: IOmniTaskControl; ALEDIndex, AFunction: Integer);
|
|
||||||
procedure InitializeStateProvider(AConsumer: IOmniTaskControl; AProviderClass: TLEDStateProviderClass);
|
|
||||||
procedure FinalizeStateProvider(AConsumer: IOmniTaskControl);
|
|
||||||
procedure Finalize(AConsumer: IOmniTaskControl);
|
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
SysUtils,
|
System.SysUtils,
|
||||||
Windows;
|
Winapi.Windows,
|
||||||
|
|
||||||
|
LEDFunctionRegistry,
|
||||||
|
LEDStateIntf;
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
G940_LED_COUNT = 8;
|
INTERVAL_TICK = 500;
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
TProfileButtonWorkerSettings = class(TInterfacedObject, ILEDFunctionWorkerSettings)
|
||||||
|
private
|
||||||
|
FProfileButton: TProfileButton;
|
||||||
|
protected
|
||||||
|
{ ILEDFunctionWorkerSettings }
|
||||||
|
function GetStateColor(const AUID: string; out AColor: TLEDColor): Boolean;
|
||||||
|
|
||||||
|
property ProfileButton: TProfileButton read FProfileButton;
|
||||||
|
public
|
||||||
|
constructor Create(AProfileButton: TProfileButton);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TLEDStateConsumer }
|
{ TLEDStateConsumer }
|
||||||
constructor TLEDStateConsumer.Create;
|
function TLEDStateConsumer.Initialize: Boolean;
|
||||||
begin
|
begin
|
||||||
inherited;
|
Result := inherited Initialize;
|
||||||
|
if not Result then
|
||||||
|
exit;
|
||||||
|
|
||||||
FFunctionMap := TLEDFunctionMap.Create;
|
FButtonWorkers := TInterfaceList.Create;
|
||||||
FStateMap := TLEDStateMap.Create;
|
FButtonColors := TInterfaceList.Create;
|
||||||
|
|
||||||
InitializeLEDState;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.Cleanup;
|
procedure TLEDStateConsumer.Cleanup;
|
||||||
begin
|
begin
|
||||||
inherited;
|
FreeAndNil(FButtonColors);
|
||||||
|
FreeAndNil(FButtonWorkers);
|
||||||
|
|
||||||
FreeAndNil(FStateMap);
|
inherited Cleanup;
|
||||||
FreeAndNil(FFunctionMap);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.BeginUpdate;
|
function TLEDStateConsumer.CreateWorker(AProfileButton: TProfileButton): ILEDFunctionWorker;
|
||||||
begin
|
|
||||||
if FUpdateCount = 0 then
|
|
||||||
FChanged := False;
|
|
||||||
|
|
||||||
Inc(FUpdateCount);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.EndUpdate;
|
|
||||||
begin
|
|
||||||
if FUpdateCount > 0 then
|
|
||||||
Dec(FUpdateCount);
|
|
||||||
|
|
||||||
if (FUpdateCount = 0) and FChanged then
|
|
||||||
Changed;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function TLEDStateConsumer.GetFunctionMap: TLEDFunctionMap;
|
|
||||||
begin
|
|
||||||
Result := FFunctionMap;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
|
||||||
var
|
var
|
||||||
ledIndex: Integer;
|
provider: ILEDFunctionProvider;
|
||||||
|
ledFunction: ILEDFunction;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if FunctionMap.FindFirst(AFunction, ledIndex) then
|
Result := nil;
|
||||||
repeat
|
|
||||||
if StateMap.SetState(ledIndex, AState) then
|
|
||||||
LEDStateChanged(ledIndex, AState);
|
|
||||||
until not FunctionMap.FindNext(AFunction, ledIndex);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
provider := TLEDFunctionRegistry.Find(AProfileButton.ProviderUID);
|
||||||
|
if Assigned(provider) then
|
||||||
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
|
|
||||||
BeginUpdate;
|
|
||||||
try
|
|
||||||
Provider.ProcessMessages;
|
|
||||||
|
|
||||||
if Provider.Terminated then
|
|
||||||
begin
|
|
||||||
FinalizeProvider;
|
|
||||||
Task.Comm.Send(MSG_PROVIDER_KILLED, '');
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
EndUpdate;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.MsgFinalize(var msg: TOmniMessage);
|
|
||||||
begin
|
|
||||||
FDestroying := True;
|
|
||||||
FinalizeProvider;
|
|
||||||
Task.Terminate;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.InitializeProvider(AProviderClass: TLEDStateProviderClass);
|
|
||||||
begin
|
|
||||||
FinalizeProvider;
|
|
||||||
|
|
||||||
FProvider := AProviderClass.Create(Self);
|
|
||||||
try
|
|
||||||
Provider.Initialize;
|
|
||||||
|
|
||||||
if Provider.ProcessMessagesInterval > -1 then
|
|
||||||
begin
|
|
||||||
Task.SetTimer(TIMER_PROCESSMESSAGES, Provider.ProcessMessagesInterval, MSG_PROCESS_MESSAGES);
|
|
||||||
FTimerSet := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
InitializeLEDState;
|
|
||||||
except
|
|
||||||
on E:Exception do
|
|
||||||
begin
|
|
||||||
FProvider := nil;
|
|
||||||
Task.Comm.Send(MSG_PROVIDER_KILLED, E.Message);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.FinalizeProvider;
|
|
||||||
begin
|
|
||||||
if Assigned(Provider) then
|
|
||||||
begin
|
begin
|
||||||
if FTimerSet then
|
ledFunction := provider.Find(AProfileButton.FunctionUID);
|
||||||
begin
|
if Assigned(ledFunction) then
|
||||||
Task.ClearTimer(TIMER_PROCESSMESSAGES);
|
Result := ledFunction.CreateWorker(TProfileButtonWorkerSettings.Create(AProfileButton));
|
||||||
FTimerSet := False;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Provider.Terminate;
|
|
||||||
Provider.Finalize;
|
|
||||||
FreeAndNil(FProvider);
|
|
||||||
|
|
||||||
StateMap.Clear;
|
|
||||||
ResetLEDState;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.RunInMainThread(AExecutor: IRunInMainThread; AWait: Boolean);
|
|
||||||
begin
|
|
||||||
Task.Comm.Send(MSG_RUN_IN_MAINTHREAD, AExecutor);
|
|
||||||
if AWait then
|
|
||||||
AExecutor.WaitFor(INFINITE);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.InitializeLEDState;
|
|
||||||
var
|
|
||||||
ledIndex: Integer;
|
|
||||||
state: TLEDState;
|
|
||||||
newState: TLEDState;
|
|
||||||
|
|
||||||
begin
|
|
||||||
BeginUpdate;
|
|
||||||
try
|
|
||||||
ResetLEDState;
|
|
||||||
|
|
||||||
for ledIndex := 0 to Pred(G940_LED_COUNT) do
|
|
||||||
begin
|
|
||||||
state := StateMap.GetState(ledIndex, lsGreen);
|
|
||||||
newState := state;
|
|
||||||
|
|
||||||
case FunctionMap.GetFunction(ledIndex) of
|
|
||||||
FUNCTION_OFF: newState := lsOff;
|
|
||||||
FUNCTION_RED: newState := lsRed;
|
|
||||||
FUNCTION_AMBER: newState := lsAmber;
|
|
||||||
FUNCTION_GREEN: newState := lsGreen;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if state <> newState then
|
|
||||||
LEDStateChanged(ledIndex, newState);
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
EndUpdate;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.ResetLEDState;
|
|
||||||
begin
|
|
||||||
if UpdateCount = 0 then
|
|
||||||
Changed
|
|
||||||
else
|
|
||||||
FChanged := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.LEDStateChanged(ALEDIndex: Integer; AState: TLEDState);
|
|
||||||
begin
|
|
||||||
if UpdateCount = 0 then
|
|
||||||
Changed
|
|
||||||
else
|
|
||||||
FChanged := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TLEDStateConsumer.Changed;
|
procedure TLEDStateConsumer.Changed;
|
||||||
|
var
|
||||||
|
hasDynamicColors: Boolean;
|
||||||
|
buttonIndex: Integer;
|
||||||
|
state: ILEDStateWorker;
|
||||||
|
color: ILEDStateColor;
|
||||||
|
dynamicColor: ILEDStateDynamicColor;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FChanged := False;
|
hasDynamicColors := False;
|
||||||
|
ButtonColors.Clear;
|
||||||
|
|
||||||
|
for buttonIndex := 0 to Pred(ButtonWorkers.Count) do
|
||||||
|
begin
|
||||||
|
color := nil;
|
||||||
|
|
||||||
|
if Assigned(ButtonWorkers[buttonIndex]) then
|
||||||
|
begin
|
||||||
|
state := (ButtonWorkers[buttonIndex] as ILEDFunctionWorker).GetCurrentState;
|
||||||
|
if Assigned(state) then
|
||||||
|
begin
|
||||||
|
color := state.GetColor;
|
||||||
|
if Assigned(color) then
|
||||||
|
begin
|
||||||
|
if (hasDynamicColors = False) and Supports(color, ILEDStateDynamicColor, dynamicColor) then
|
||||||
|
begin
|
||||||
|
{ If the tick timer isn't currently running, there were no
|
||||||
|
dynamic colors before. Reset each dynamic colors now. }
|
||||||
|
if not HasTickTimer then
|
||||||
|
dynamicColor.Reset;
|
||||||
|
|
||||||
|
hasDynamicColors := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ButtonColors.Add(color as ILEDStateColor);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Assigned(color) then
|
||||||
|
ButtonColors.Add(nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if hasDynamicColors <> HasTickTimer then
|
||||||
|
begin
|
||||||
|
if hasDynamicColors then
|
||||||
|
Task.SetTimer(TIMER_TICK, INTERVAL_TICK, TM_TICK)
|
||||||
|
else
|
||||||
|
Task.ClearTimer(TIMER_TICK);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Update;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ Helpers }
|
procedure TLEDStateConsumer.TMLoadProfile(var Msg: TOmniMessage);
|
||||||
procedure ClearFunctions(AConsumer: IOmniTaskControl);
|
var
|
||||||
|
profile: TProfile;
|
||||||
|
buttonIndex: Integer;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
AConsumer.Comm.Send(MSG_CLEAR_FUNCTIONS);
|
profile := Msg.MsgData;
|
||||||
|
ButtonWorkers.Clear;
|
||||||
|
|
||||||
|
for buttonIndex := 0 to Pred(profile.ButtonCount) do
|
||||||
|
begin
|
||||||
|
if profile.HasButton(buttonIndex) then
|
||||||
|
ButtonWorkers.Add(CreateWorker(profile.Buttons[buttonIndex]) as ILEDFunctionWorker)
|
||||||
|
else
|
||||||
|
ButtonWorkers.Add(nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Changed;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure SetFunction(AConsumer: IOmniTaskControl; ALEDIndex, AFunction: Integer);
|
procedure TLEDStateConsumer.TMTick(var Msg: TOmniMessage);
|
||||||
|
var
|
||||||
|
buttonIndex: Integer;
|
||||||
|
checkButtonIndex: Integer;
|
||||||
|
alreadyTicked: Boolean;
|
||||||
|
color: ILEDStateColor;
|
||||||
|
dynamicColor: ILEDStateDynamicColor;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
AConsumer.Comm.Send(MSG_SET_FUNCTION, [ALEDIndex, AFunction]);
|
// (MvR) 19-2-2013: I could pass a tick count to Tick() so that they can all use modulus to blink synchronously... think about it.
|
||||||
|
|
||||||
|
for buttonIndex := 0 to Pred(ButtonColors.Count) do
|
||||||
|
begin
|
||||||
|
alreadyTicked := False;
|
||||||
|
color := (ButtonColors[buttonIndex] as ILEDStateColor);
|
||||||
|
|
||||||
|
if Supports(color, ILEDStateDynamicColor, dynamicColor) then
|
||||||
|
begin
|
||||||
|
{ Check if this color has already been ticked }
|
||||||
|
for checkButtonIndex := Pred(buttonIndex) downto 0 do
|
||||||
|
if (ButtonColors[checkButtonIndex] as ILEDStateColor) = color then
|
||||||
|
begin
|
||||||
|
alreadyTicked := True;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not alreadyTicked then
|
||||||
|
dynamicColor.Tick;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Update;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure InitializeStateProvider(AConsumer: IOmniTaskControl; AProviderClass: TLEDStateProviderClass);
|
{ TProfileButtonWorkerSettings }
|
||||||
|
constructor TProfileButtonWorkerSettings.Create(AProfileButton: TProfileButton);
|
||||||
begin
|
begin
|
||||||
AConsumer.Comm.Send(MSG_INITIALIZE_PROVIDER, Pointer(AProviderClass));
|
inherited Create;
|
||||||
|
|
||||||
|
FProfileButton := AProfileButton;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TProfileButtonWorkerSettings.GetStateColor(const AUID: string; out AColor: TLEDColor): Boolean;
|
||||||
procedure FinalizeStateProvider(AConsumer: IOmniTaskControl);
|
|
||||||
begin
|
begin
|
||||||
AConsumer.Comm.Send(MSG_FINALIZE_PROVIDER);
|
Result := ProfileButton.GetStateColor(AUID, AColor);
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure Finalize(AConsumer: IOmniTaskControl);
|
|
||||||
begin
|
|
||||||
AConsumer.Comm.Send(MSG_FINALIZE);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -21,7 +21,7 @@ type
|
|||||||
|
|
||||||
ILEDStateWorker = interface(ICustomLEDState)
|
ILEDStateWorker = interface(ICustomLEDState)
|
||||||
['{0361CBD5-E64E-4972-A8A4-D5FE0B0DFB1C}']
|
['{0361CBD5-E64E-4972-A8A4-D5FE0B0DFB1C}']
|
||||||
function GetColor: ILEDColor;
|
function GetColor: ILEDStateColor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
unit LEDStateProvider;
|
|
||||||
|
|
||||||
interface
|
|
||||||
uses
|
|
||||||
Classes,
|
|
||||||
SyncObjs,
|
|
||||||
SysUtils,
|
|
||||||
|
|
||||||
LEDFunctionMap;
|
|
||||||
|
|
||||||
type
|
|
||||||
EInitializeError = class(Exception);
|
|
||||||
|
|
||||||
ILEDStateConsumer = interface
|
|
||||||
['{6E630C92-7C5C-4D16-8BED-AE27559FA584}']
|
|
||||||
function GetFunctionMap: TLEDFunctionMap;
|
|
||||||
procedure SetStateByFunction(AFunction: Integer; AState: TLEDState);
|
|
||||||
|
|
||||||
property FunctionMap: TLEDFunctionMap read GetFunctionMap;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
IFunctionConsumer = interface
|
|
||||||
['{97B47A29-BA7F-4C48-934D-EB66D2741647}']
|
|
||||||
procedure SetCategory(const ACategory: string);
|
|
||||||
procedure AddFunction(AFunction: Integer; const ADescription: string);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
TLEDStateProvider = class(TObject)
|
|
||||||
private
|
|
||||||
FConsumer: ILEDStateConsumer;
|
|
||||||
FTerminated: Boolean;
|
|
||||||
protected
|
|
||||||
procedure Execute; virtual; abstract;
|
|
||||||
|
|
||||||
function GetProcessMessagesInterval: Integer; virtual;
|
|
||||||
|
|
||||||
property Consumer: ILEDStateConsumer read FConsumer;
|
|
||||||
public
|
|
||||||
class procedure EnumFunctions(AConsumer: IFunctionConsumer); virtual;
|
|
||||||
|
|
||||||
constructor Create(AConsumer: ILEDStateConsumer); virtual;
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
const
|
|
||||||
EXIT_SUCCESS = 0;
|
|
||||||
EXIT_ERROR = 1;
|
|
||||||
|
|
||||||
EXIT_CONSUMER_OFFSET = 100;
|
|
||||||
EXIT_PROVIDER_OFFSET = 200;
|
|
||||||
|
|
||||||
implementation
|
|
||||||
const
|
|
||||||
CATEGORY_STATIC = 'Static';
|
|
||||||
|
|
||||||
FUNCTION_DESC_OFF = 'Light off';
|
|
||||||
FUNCTION_DESC_GREEN = 'Green';
|
|
||||||
FUNCTION_DESC_AMBER = 'Amber';
|
|
||||||
FUNCTION_DESC_RED = 'Red';
|
|
||||||
|
|
||||||
|
|
||||||
{ TCustomLEDStateProvider }
|
|
||||||
class procedure TLEDStateProvider.EnumFunctions(AConsumer: IFunctionConsumer);
|
|
||||||
begin
|
|
||||||
AConsumer.SetCategory(CATEGORY_STATIC);
|
|
||||||
AConsumer.AddFunction(FUNCTION_OFF, FUNCTION_DESC_OFF);
|
|
||||||
AConsumer.AddFunction(FUNCTION_GREEN, FUNCTION_DESC_GREEN);
|
|
||||||
AConsumer.AddFunction(FUNCTION_AMBER, FUNCTION_DESC_AMBER);
|
|
||||||
AConsumer.AddFunction(FUNCTION_RED, FUNCTION_DESC_RED);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
end.
|
|
@ -3,6 +3,7 @@ unit Profile;
|
|||||||
interface
|
interface
|
||||||
uses
|
uses
|
||||||
Generics.Collections,
|
Generics.Collections,
|
||||||
|
System.Classes,
|
||||||
|
|
||||||
X2UtPersistIntf,
|
X2UtPersistIntf,
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ uses
|
|||||||
type
|
type
|
||||||
TProfileButtonStateColors = TDictionary<string,TLEDColor>;
|
TProfileButtonStateColors = TDictionary<string,TLEDColor>;
|
||||||
|
|
||||||
TProfileButton = class(TObject)
|
TProfileButton = class(TPersistent)
|
||||||
private
|
private
|
||||||
FProviderUID: string;
|
FProviderUID: string;
|
||||||
FFunctionUID: string;
|
FFunctionUID: string;
|
||||||
@ -39,7 +40,7 @@ type
|
|||||||
TProfileButtonList = class(TObjectList<TProfileButton>);
|
TProfileButtonList = class(TObjectList<TProfileButton>);
|
||||||
|
|
||||||
|
|
||||||
TProfile = class(TObject)
|
TProfile = class(TPersistent)
|
||||||
private
|
private
|
||||||
FName: string;
|
FName: string;
|
||||||
FButtons: TProfileButtonList;
|
FButtons: TProfileButtonList;
|
||||||
@ -71,8 +72,7 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
Classes,
|
System.SysUtils,
|
||||||
SysUtils,
|
|
||||||
|
|
||||||
LEDResources;
|
LEDResources;
|
||||||
|
|
||||||
|
@ -7,13 +7,13 @@ uses
|
|||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TStaticLEDColor = class(TCustomLEDColor)
|
TLEDStateStaticColor = class(TCustomLEDStateColor)
|
||||||
private
|
private
|
||||||
FColor: TLEDColor;
|
FColor: TStaticLEDColor;
|
||||||
protected
|
protected
|
||||||
function GetColor: TLEDColor; override;
|
function GetCurrentColor: TStaticLEDColor; override;
|
||||||
public
|
public
|
||||||
constructor Create(AColor: TLEDColor);
|
constructor Create(AColor: TStaticLEDColor);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ implementation
|
|||||||
|
|
||||||
|
|
||||||
{ TStaticLEDState }
|
{ TStaticLEDState }
|
||||||
constructor TStaticLEDColor.Create(AColor: TLEDColor);
|
constructor TLEDStateStaticColor.Create(AColor: TStaticLEDColor);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TStaticLEDColor.GetColor: TLEDColor;
|
function TLEDStateStaticColor.GetCurrentColor: TStaticLEDColor;
|
||||||
begin
|
begin
|
||||||
Result := FColor;
|
Result := FColor;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user