1 // FGEventInput.hxx -- handle event driven input devices
2 //
3 // Written by Torsten Dreyer, started July 2009
4 //
5 // Copyright (C) 2009 Torsten Dreyer, Torsten (at) t3r _dot_ de
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22 
23 #ifndef __FGEVENTINPUT_HXX
24 #define __FGEVENTINPUT_HXX
25 
26 #include "FGCommonInput.hxx"
27 
28 #include <vector>
29 #include <memory>
30 
31 #include "FGButton.hxx"
32 #include "FGDeviceConfigurationMap.hxx"
33 #include <simgear/structure/subsystem_mgr.hxx>
34 
35 // forward decls
36 class SGInterpTable;
37 
38 /*
39  * A base structure for event data.
40  * To be extended for O/S specific implementation data
41  */
42 struct FGEventData {
FGEventDataFGEventData43     FGEventData( double aValue, double aDt, int aModifiers ) : modifiers(aModifiers), value(aValue), dt(aDt) {}
44     int modifiers;
45     double value;
46     double dt;
47 };
48 
49 class FGEventSetting : public SGReferenced
50 {
51 public:
52     FGEventSetting( SGPropertyNode_ptr base );
53 
54     bool Test();
55 
56     /*
57      * access for the value property
58      */
59     double GetValue();
60 
61 protected:
62     double value;
63     SGPropertyNode_ptr valueNode;
64     SGSharedPtr<const SGCondition> condition;
65 };
66 
67 typedef SGSharedPtr<FGEventSetting> FGEventSetting_ptr;
68 typedef std::vector<FGEventSetting_ptr> setting_list_t;
69 
70 class FGReportSetting : public SGReferenced,
71                         public SGPropertyChangeListener
72 {
73 public:
74     FGReportSetting( SGPropertyNode_ptr base );
75 
getReportId() const76     unsigned int getReportId() const
77     {
78         return reportId;
79     }
80 
getNasalFunctionName() const81     std::string getNasalFunctionName() const
82     {
83         return nasalFunction;
84     }
85 
86     bool Test();
87 
88     std::string reportBytes(const std::string& moduleName) const;
89 
90     virtual void valueChanged(SGPropertyNode * node);
91 
92 protected:
93     unsigned int reportId;
94     std::string nasalFunction;
95     bool dirty;
96 };
97 
98 typedef SGSharedPtr<FGReportSetting> FGReportSetting_ptr;
99 typedef std::vector<FGReportSetting_ptr> report_setting_list_t;
100 
101 /*
102  * A wrapper class for a configured event.
103  *
104  * <event>
105  *   <desc>Change the view pitch</desc>
106  *   <name>rel-x-rotate</name>
107  *   <binding>
108  *     <command>property-adjust</command>
109  *     <property>sim/current-view/pitch-offset-deg</property>
110  *     <factor type="double">0.01</factor>
111  *     <min type="double">-90.0</min>
112  *     <max type="double">90.0</max>
113  *     <wrap type="bool">false</wrap>
114  *   </binding>
115  *   <mod-xyz>
116  *    <binding>
117  *      ...
118  *    </binding>
119  *   </mod-xyz>
120  * </event>
121  */
122 class FGInputDevice;
123 class FGInputEvent : public SGReferenced,
124                      FGCommonInput
125 {
126 public:
127     /*
128      * Constructor for the class. The arg node shall point
129      * to the property corresponding to the <event>  node
130      */
131     FGInputEvent( FGInputDevice * device, SGPropertyNode_ptr node );
132     virtual ~FGInputEvent();
133 
134     /*
135      * dispatch the event value through all bindings
136      */
137     virtual void fire( FGEventData & eventData );
138 
139     /*
140      * access for the name property
141      */
GetName() const142     std::string GetName() const { return name; }
143 
144     /*
145      * access for the description property
146      */
GetDescription() const147     std::string GetDescription() const { return desc; }
148 
149     virtual void update( double dt );
150 
151     static FGInputEvent * NewObject( FGInputDevice * device, SGPropertyNode_ptr node );
152 
153 protected:
154     virtual void fire( SGBinding * binding, FGEventData & eventData );
155     /* A more or less meaningfull description of the event */
156     std::string desc;
157 
158     /* One of the predefined names of the event */
159     std::string name;
160 
161     /* A list of SGBinding objects */
162     binding_list_t bindings[KEYMOD_MAX];
163 
164     /* A list of FGEventSetting objects */
165     setting_list_t settings;
166 
167     /* A pointer to the associated device */
168     FGInputDevice * device;
169 
170     double lastDt;
171     double intervalSec;
172     double lastSettingValue;
173 };
174 
175 class FGButtonEvent : public FGInputEvent
176 {
177 public:
178     FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node );
179     virtual void fire( FGEventData & eventData );
180 
181   void update( double dt ) override;
182 protected:
183     bool repeatable;
184     bool lastState;
185 };
186 
187 class FGAxisEvent : public FGInputEvent
188 {
189 public:
190     FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node );
191     ~FGAxisEvent();
192 
SetMaxRange(double value)193     void SetMaxRange( double value ) { maxRange = value; }
SetMinRange(double value)194     void SetMinRange( double value ) { minRange = value; }
SetRange(double min,double max)195     void SetRange( double min, double max ) { minRange = min; maxRange = max; }
196 
197 protected:
198     virtual void fire( FGEventData & eventData );
199     double tolerance;
200     double minRange;
201     double maxRange;
202     double center;
203     double deadband;
204     double lowThreshold;
205     double highThreshold;
206     double lastValue;
207     std::unique_ptr<SGInterpTable> interpolater;
208     bool mirrorInterpolater = false;
209 };
210 
211 class FGRelAxisEvent : public FGAxisEvent
212 {
213 public:
214     FGRelAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node );
215 
216 protected:
217     virtual void fire( SGBinding * binding, FGEventData & eventData );
218 };
219 
220 class FGAbsAxisEvent : public FGAxisEvent
221 {
222 public:
FGAbsAxisEvent(FGInputDevice * device,SGPropertyNode_ptr node)223     FGAbsAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) : FGAxisEvent( device, node ) {}
224 
225 protected:
226     virtual void fire( SGBinding * binding, FGEventData & eventData );
227 };
228 
229 typedef class SGSharedPtr<FGInputEvent> FGInputEvent_ptr;
230 
231 /*
232  * A abstract class implementing basic functionality of input devices for
233  * all operating systems. This is the base class for the O/S-specific
234  * implementation of input device handlers
235  */
236 class FGInputDevice : public SGReferenced
237 {
238 public:
FGInputDevice()239     FGInputDevice() {}
FGInputDevice(std::string aName,std::string aSerial={} )240     FGInputDevice( std::string aName, std::string aSerial = {} ) :
241         name(aName), serialNumber(aSerial) {}
242 
243     virtual ~FGInputDevice();
244 
245     virtual bool Open() = 0;
246     virtual void Close() = 0;
247 
248     virtual void Send( const char * eventName, double value ) = 0;
249 
Send(const std::string & eventName,double value)250     inline void Send( const std::string & eventName, double value ) {
251         Send( eventName.c_str(), value );
252     }
253 
254     virtual void SendFeatureReport(unsigned int reportId, const std::string& data);
255 
256     virtual const char * TranslateEventName( FGEventData & eventData ) = 0;
257 
258 
259     void SetName( std::string name );
GetName()260     std::string & GetName() { return name; }
261 
262     void SetUniqueName(const std::string& name);
GetUniqueName() const263     const std::string GetUniqueName() const
264     { return _uniqueName; }
265 
266     void SetSerialNumber( std::string serial );
GetSerialNumber()267     std::string& GetSerialNumber() { return serialNumber; }
268 
269     void HandleEvent( FGEventData & eventData );
270 
271     virtual void AddHandledEvent( FGInputEvent_ptr handledEvent );
272 
273     virtual void Configure( SGPropertyNode_ptr deviceNode );
274 
275     virtual void update( double dt );
276 
GetDebugEvents() const277     bool GetDebugEvents () const { return debugEvents; }
278 
GetGrab() const279     bool GetGrab() const { return grab; }
280 
GetNasalModule() const281     const std::string & GetNasalModule() const { return nasalModule; }
282 
283 protected:
284     // A map of events, this device handles
285     std::map<std::string,FGInputEvent_ptr> handledEvents;
286 
287     // the device has a name to be recognized
288     std::string name;
289 
290     // serial number string to disambiguate multiple instances
291     // of the same device
292     std::string serialNumber;
293 
294     // print out events comming in from the device
295     // if true
296     bool debugEvents = false;
297 
298     // grab the device exclusively, if O/S supports this
299     // so events are not sent to other applications
300     bool grab = false;
301 
302     SGPropertyNode_ptr deviceNode;
303     std::string nasalModule;
304 
305     report_setting_list_t reportSettings;
306 
307   /// name, but with suffix / serial appended. This is important
308   /// when loading the device multiple times, to ensure the Nasal
309   /// module is unique
310   std::string _uniqueName;
311 };
312 
313 typedef SGSharedPtr<FGInputDevice> FGInputDevice_ptr;
314 
315 
316 /*
317  * The Subsystem for the event input device
318  */
319 class FGEventInput : public SGSubsystem,
320                      FGCommonInput
321 {
322 public:
323     FGEventInput();
324     virtual ~FGEventInput();
325 
326     // Subsystem API.
327     void init() override;
328     void postinit() override;
329     void shutdown() override;
330     void update(double dt) override;
331 
332     const static unsigned MAX_DEVICES = 1000;
333     const static unsigned INVALID_DEVICE_INDEX = MAX_DEVICES + 1;
334 
335 protected:
336     static const char * PROPERTY_ROOT;
337 
338     unsigned AddDevice( FGInputDevice * inputDevice );
339     void RemoveDevice( unsigned index );
340 
341     std::map<int,FGInputDevice*> input_devices;
342     FGDeviceConfigurationMap configMap;
343 
344     SGPropertyNode_ptr nasalClose;
345 
346 private:
347     std::string computeDeviceIndexName(FGInputDevice *dev) const;
348 };
349 
350 #endif
351