1 // FGEventInput.cxx -- handle event driven input devices
3 // Written by Torsten Dreyer, started July 2009.
5 // Copyright (C) 2009 Torsten Dreyer, Torsten (at) t3r _dot_ de
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.
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.
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.
27 #include "FGEventInput.hxx"
28 #include <Main/fg_props.hxx>
29 #include <simgear/io/sg_file.hxx>
31 #include <linux/input.h>
33 FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
38 if( (n = base->getNode( "value" )) != NULL ) {
40 value = n->getDoubleValue();
42 n = base->getNode( "property" );
44 SG_LOG( SG_INPUT, SG_WARN, "Neither <value> nor <property> defined for event setting." );
46 valueNode = fgGetNode( n->getStringValue(), true );
50 if( (n = base->getChild("condition")) != NULL )
51 condition = sgReadCondition(base, n);
53 SG_LOG( SG_INPUT, SG_ALERT, "No condition for event setting." );
56 double FGEventSetting::GetValue()
58 return valueNode == NULL ? value : valueNode->getDoubleValue();
61 bool FGEventSetting::Test()
63 return condition == NULL ? true : condition->test();
66 static inline bool StartsWith( string & s, const char * cp )
68 return s.compare( 0, strlen(cp), cp ) == 0;
71 FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_ptr node )
73 string name = node->getStringValue( "name", "" );
74 if( StartsWith( name, "button-" ) )
75 return new FGButtonEvent( device, node );
77 if( StartsWith( name, "rel-" ) )
78 return new FGAxisEvent( device, node );
80 if( StartsWith( name, "abs-" ) )
81 return new FGAxisEvent( device, node );
83 return new FGInputEvent( device, node );
86 FGInputEvent::FGInputEvent( FGInputDevice * aDevice, SGPropertyNode_ptr node ) :
89 lastSettingValue(std::numeric_limits<float>::quiet_NaN())
91 name = node->getStringValue( "name", "" );
92 desc = node->getStringValue( "desc", "" );
93 intervalSec = node->getDoubleValue("interval-sec",0.0);
94 string module = "event";
96 read_bindings( node, bindings, KEYMOD_NONE, module );
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 ) );
103 FGInputEvent::~FGInputEvent()
107 void FGInputEvent::update( double dt )
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;
120 void FGInputEvent::fire( FGEventData & eventData )
122 lastDt += eventData.dt;
123 if( lastDt >= intervalSec ) {
125 for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ )
126 (*it)->fire( eventData.value, 1.0 );
128 lastDt -= intervalSec;
132 FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
133 FGInputEvent( device, node )
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);
145 void FGAxisEvent::fire( FGEventData & eventData )
147 if (fabs( eventData.value - lastValue) < tolerance)
149 lastValue = eventData.value;
150 FGInputEvent::fire( eventData );
153 FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
154 FGInputEvent( device, node ),
158 repeatable = node->getBoolValue("repeatable", repeatable);
161 void FGButtonEvent::fire( FGEventData & eventData )
163 bool pressed = eventData.value > 0.0;
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 );
171 // The release event is never repeated.
173 SG_LOG( SG_INPUT, SG_DEBUG, "Button has been released" );
174 eventData.modifiers|=KEYMOD_RELEASED;
175 FGInputEvent::fire( eventData );
182 FGInputDevice::~FGInputDevice()
186 void FGInputDevice::update( double dt )
188 for( map<string,FGInputEvent_ptr>::iterator it = handledEvents.begin(); it != handledEvents.end(); it++ )
189 (*it).second->update( dt );
192 void FGInputDevice::HandleEvent( FGEventData & eventData )
194 string eventName = TranslateEventName( eventData );
196 cout << GetName() << " has event " <<
197 eventName << " modifiers=" << eventData.modifiers << " value=" << eventData.value << endl;
199 if( handledEvents.count( eventName ) > 0 ) {
200 handledEvents[ eventName ]->fire( eventData );
204 void FGInputDevice::SetName( string name )
209 const char * FGEventInput::PROPERTY_ROOT = "/input/event";
211 FGEventInput::FGEventInput() :
212 configMap( "Input/Event", fgGetNode( PROPERTY_ROOT, true ), "device-named" )
216 FGEventInput::~FGEventInput()
218 for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); it++ )
220 input_devices.clear();
223 void FGEventInput::init( )
225 SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings");
226 // SGPropertyNode * base = fgGetNode("/input/event", true);
230 void FGEventInput::postinit ()
234 void FGEventInput::update( double dt )
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 );
241 void FGEventInput::AddDevice( FGInputDevice * inputDevice )
243 SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
244 SGPropertyNode_ptr deviceNode = NULL;
246 // look for configuration in the device map
247 if( configMap.count( inputDevice->GetName() ) > 0 ) {
248 // found - copy to /input/event/device[n]
252 for( index = 0; index < 1000; index++ )
253 if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
256 if( index == 1000 ) {
257 SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
262 deviceNode = baseNode->getNode( "device", index, true );
264 // and copy the properties from the configuration tree
265 copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
268 if( deviceNode == NULL ) {
269 SG_LOG(SG_INPUT, SG_DEBUG, "No configuration found for device " << inputDevice->GetName() );
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 ) );
278 inputDevice->SetDebugEvents( deviceNode->getBoolValue("debug-events", inputDevice->GetDebugEvents() ));
279 inputDevice->SetGrab( deviceNode->getBoolValue("grab", inputDevice->GetGrab() ));
282 // add nodes for the last event:
283 // last-event/name [string]
284 // last-event/value [double]
288 input_devices[ deviceNode->getIndex() ] = inputDevice;
292 SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetName() );
295 SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName() );