]> git.mxchange.org Git - flightgear.git/blob - src/Input/FGEventInput.cxx
AIGroundVehicle from Vivian Meazza
[flightgear.git] / src / Input / FGEventInput.cxx
1 // FGEventInput.cxx -- 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 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include "FGEventInput.hxx"
28 #include <Main/fg_props.hxx>
29 #include <simgear/io/sg_file.hxx>
30 #include <poll.h>
31 #include <linux/input.h>
32
33 FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
34   value(0.0)
35 {
36   SGPropertyNode_ptr n;
37
38   if( (n = base->getNode( "value" )) != NULL ) {  
39     valueNode = NULL;
40     value = n->getDoubleValue();
41   } else {
42     n = base->getNode( "property" );
43     if( n == NULL ) {
44       SG_LOG( SG_INPUT, SG_WARN, "Neither <value> nor <property> defined for event setting." );
45     } else {
46       valueNode = fgGetNode( n->getStringValue(), true );
47     }
48   }
49
50   if( (n = base->getChild("condition")) != NULL )
51     condition = sgReadCondition(base, n);
52   else
53     SG_LOG( SG_INPUT, SG_ALERT, "No condition for event setting." );
54 }
55
56 double FGEventSetting::GetValue()
57 {
58   return valueNode == NULL ? value : valueNode->getDoubleValue();
59 }
60
61 bool FGEventSetting::Test()
62 {
63   return condition == NULL ? true : condition->test();
64 }
65
66 static inline bool StartsWith( string & s, const char * cp )
67 {
68   return s.compare( 0, strlen(cp), cp ) == 0;
69 }
70
71 FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_ptr node )
72 {
73   string name = node->getStringValue( "name", "" );
74   if( StartsWith( name, "button-" ) )
75     return new FGButtonEvent( device, node );
76
77   if( StartsWith( name, "rel-" ) )
78     return new FGAxisEvent( device, node );
79
80   if( StartsWith( name, "abs-" ) )
81     return new FGAxisEvent( device, node );
82
83   return new FGInputEvent( device, node );
84 }
85
86 FGInputEvent::FGInputEvent( FGInputDevice * aDevice, SGPropertyNode_ptr node ) :
87   device( aDevice ),
88   lastDt(0.0), 
89   lastSettingValue(std::numeric_limits<float>::quiet_NaN())
90 {
91   name = node->getStringValue( "name", "" );
92   desc = node->getStringValue( "desc", "" );
93   intervalSec = node->getDoubleValue("interval-sec",0.0);
94   string module = "event";
95   
96   read_bindings( node, bindings, KEYMOD_NONE, module );
97
98   vector<SGPropertyNode_ptr> settingNodes = node->getChildren("setting");
99   for( vector<SGPropertyNode_ptr>::iterator it = settingNodes.begin(); it != settingNodes.end(); it++ )
100     settings.push_back( new FGEventSetting( *it ) );
101 }
102
103 FGInputEvent::~FGInputEvent()
104 {
105 }
106
107 void FGInputEvent::update( double dt )
108 {
109   for( setting_list_t::iterator it = settings.begin(); it != settings.end(); it++ ) {
110     if( (*it)->Test() ) {
111       double value = (*it)->GetValue();
112       if( value != lastSettingValue ) {
113         device->Send( GetName(), (*it)->GetValue() );
114         lastSettingValue = value;
115       }
116     }
117   }
118 }
119
120 void FGInputEvent::fire( FGEventData & eventData )
121 {
122   lastDt += eventData.dt;
123   if( lastDt >= intervalSec ) {
124
125     for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ )
126       (*it)->fire( eventData.value, 1.0 );
127
128     lastDt -= intervalSec;
129   }
130 }
131
132 FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
133   FGInputEvent( device, node )
134 {
135   tolerance = node->getDoubleValue("tolerance", 0.002);
136   minRange = node->getDoubleValue("min-range", -1024.0);
137   maxRange = node->getDoubleValue("max-range", 1024.0);
138   center = node->getDoubleValue("center", 0.0);
139   deadband = node->getDoubleValue("dead-band", 0.0);
140   lowThreshold = node->getDoubleValue("low-threshold", -0.9);
141   highThreshold = node->getDoubleValue("high-threshold", 0.9);
142   lastValue = 9999999;
143 }
144
145 void FGAxisEvent::fire( FGEventData & eventData )
146 {
147   if (fabs( eventData.value - lastValue) < tolerance)
148     return;
149   lastValue = eventData.value;
150   FGInputEvent::fire( eventData );
151 }
152
153 FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
154   FGInputEvent( device, node ),
155   repeatable(false),
156   lastState(false)
157 {
158   repeatable = node->getBoolValue("repeatable", repeatable);
159 }
160
161 void FGButtonEvent::fire( FGEventData & eventData )
162 {
163   bool pressed = eventData.value > 0.0;
164   if (pressed) {
165     // The press event may be repeated.
166     if (!lastState || repeatable) {
167       SG_LOG( SG_INPUT, SG_DEBUG, "Button has been pressed" );
168       FGInputEvent::fire( eventData );
169     }
170   } else {
171     // The release event is never repeated.
172     if (lastState) {
173       SG_LOG( SG_INPUT, SG_DEBUG, "Button has been released" );
174       eventData.modifiers|=KEYMOD_RELEASED;
175       FGInputEvent::fire( eventData );
176     }
177   }
178           
179   lastState = pressed;
180 }
181
182 FGInputDevice::~FGInputDevice()
183 {
184
185
186 void FGInputDevice::update( double dt )
187 {
188   for( map<string,FGInputEvent_ptr>::iterator it = handledEvents.begin(); it != handledEvents.end(); it++ )
189     (*it).second->update( dt );
190 }
191
192 void FGInputDevice::HandleEvent( FGEventData & eventData )
193 {
194   string eventName = TranslateEventName( eventData );  
195   if( debugEvents )
196     cout << GetName() << " has event " << 
197     eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value << endl;
198
199   if( handledEvents.count( eventName ) > 0 ) {
200     handledEvents[ eventName ]->fire( eventData );
201   }
202 }
203
204 void FGInputDevice::SetName( string name )
205 {
206   this->name = name; 
207 }
208
209 const char * FGEventInput::PROPERTY_ROOT = "/input/event";
210
211 FGEventInput::FGEventInput() : 
212   configMap( "Input/Event", fgGetNode( PROPERTY_ROOT, true ), "device-named" )
213 {
214 }
215
216 FGEventInput::~FGEventInput()
217 {
218   for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); it++ )
219     delete (*it).second;
220   input_devices.clear();
221 }
222
223 void FGEventInput::init( )
224 {
225   SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings");
226 //  SGPropertyNode * base = fgGetNode("/input/event", true);
227
228 }
229
230 void FGEventInput::postinit ()
231 {
232 }
233
234 void FGEventInput::update( double dt )
235 {
236   // call each associated device's update() method
237   for( map<int,FGInputDevice*>::iterator it =  input_devices.begin(); it != input_devices.end(); it++ )
238     (*it).second->update( dt );
239 }
240
241 void FGEventInput::AddDevice( FGInputDevice * inputDevice )
242 {
243   SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
244   SGPropertyNode_ptr deviceNode = NULL;
245
246   // look for configuration in the device map
247   if( configMap.count( inputDevice->GetName() ) > 0 ) {
248     // found - copy to /input/event/device[n]
249
250     // find a free index
251     unsigned index;
252     for( index = 0; index < 1000; index++ )
253       if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
254         break;
255
256     if( index == 1000 ) {
257       SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
258       return;
259     }
260
261     // create this node 
262     deviceNode = baseNode->getNode( "device", index, true );
263
264     // and copy the properties from the configuration tree
265     copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
266   }
267
268   if( deviceNode == NULL ) {
269     SG_LOG(SG_INPUT, SG_DEBUG, "No configuration found for device " << inputDevice->GetName() );
270     delete  inputDevice;
271     return;
272   }
273
274   vector<SGPropertyNode_ptr> eventNodes = deviceNode->getChildren( "event" );
275   for( vector<SGPropertyNode_ptr>::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ )
276     inputDevice->AddHandledEvent( FGInputEvent::NewObject( inputDevice, *it ) );
277
278   inputDevice->SetDebugEvents( deviceNode->getBoolValue("debug-events", inputDevice->GetDebugEvents() ));
279   inputDevice->SetGrab( deviceNode->getBoolValue("grab", inputDevice->GetGrab() ));
280
281   // TODO:
282   // add nodes for the last event:
283   // last-event/name [string]
284   // last-event/value [double]
285   
286   try { 
287     inputDevice->Open();
288     input_devices[ deviceNode->getIndex() ] = inputDevice;
289   }
290   catch( ... ) {
291     delete  inputDevice;
292     SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetName()  );
293   }
294
295   SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName()  );
296 }