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