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.
23 #include "FGEventInput.hxx"
24 #include <Main/fg_props.hxx>
25 #include <simgear/io/sg_file.hxx>
27 #include <linux/input.h>
29 static inline bool StartsWith( string & s, const char * cp )
31 return s.compare( 0, strlen(cp), cp ) == 0;
34 FGInputEvent * FGInputEvent::NewObject( SGPropertyNode_ptr node )
36 string name = node->getStringValue( "name" );
37 if( StartsWith( name, "button-" ) )
38 return new FGButtonEvent( node );
40 if( StartsWith( name, "rel-" ) )
41 return new FGAxisEvent( node );
43 if( StartsWith( name, "abs-" ) )
44 return new FGAxisEvent( node );
49 FGInputEvent::FGInputEvent( SGPropertyNode_ptr node ) :
52 name = node->getStringValue( "name" );
53 desc = node->getStringValue( "desc" );
54 intervalSec = node->getDoubleValue("interval-sec",0.0);
55 string module = "event";
56 read_bindings( node, bindings, KEYMOD_NONE, module );
59 FGInputEvent::~FGInputEvent()
63 void FGInputEvent::fire( FGEventData & eventData )
65 lastDt += eventData.dt;
66 if( lastDt >= intervalSec ) {
68 for( binding_list_t::iterator it = bindings[KEYMOD_NONE].begin(); it != bindings[KEYMOD_NONE].end(); it++ )
69 (*it)->fire( eventData.value, 1.0 );
71 lastDt -= intervalSec;
75 FGAxisEvent::FGAxisEvent( SGPropertyNode_ptr node ) :
78 tolerance = node->getDoubleValue("tolerance", 0.002);
79 minRange = node->getDoubleValue("min-range", -1024.0);
80 maxRange = node->getDoubleValue("max-range", 1024.0);
81 center = node->getDoubleValue("center", 0.0);
82 deadband = node->getDoubleValue("dead-band", 0.0);
83 lowThreshold = node->getDoubleValue("low-threshold", -0.9);
84 highThreshold = node->getDoubleValue("high-threshold", 0.9);
88 void FGAxisEvent::fire( FGEventData & eventData )
90 if (fabs( eventData.value - lastValue) < tolerance)
92 lastValue = eventData.value;
93 FGInputEvent::fire( eventData );
96 FGButtonEvent::FGButtonEvent( SGPropertyNode_ptr node ) :
101 void FGButtonEvent::fire( FGEventData & eventData )
103 FGInputEvent::fire( eventData );
106 FGInputDevice::~FGInputDevice()
110 void FGInputDevice::HandleEvent( FGEventData & eventData )
112 string eventName = TranslateEventName( eventData );
113 cout << GetName() << " has event " << eventName << endl;
114 if( handledEvents.count( eventName ) > 0 ) {
115 handledEvents[ eventName ]->fire( eventData );
119 void FGInputDevice::SetName( string name )
124 const char * FGEventInput::PROPERTY_ROOT = "/input/event";
126 FGEventInput::FGEventInput() :
127 configMap( "Input/Event", fgGetNode( PROPERTY_ROOT, true ), "device-named" )
131 FGEventInput::~FGEventInput()
133 for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); it++ )
135 input_devices.clear();
138 void FGEventInput::init( )
140 SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings");
141 SGPropertyNode * base = fgGetNode("/input/event", true);
145 void FGEventInput::postinit ()
149 void FGEventInput::AddDevice( FGInputDevice * inputDevice )
151 SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
152 SGPropertyNode_ptr deviceNode = NULL;
154 // look for configuration in the device map
155 if( configMap.count( inputDevice->GetName() ) > 0 ) {
156 // found - copy to /input/event/device[n]
160 for( index = 0; index < 1000; index++ )
161 if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
164 if( index == 1000 ) {
165 SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
170 deviceNode = baseNode->getNode( "device", index, true );
172 // and copy the properties from the configuration tree
173 copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
176 if( deviceNode == NULL ) {
177 SG_LOG(SG_INPUT, SG_WARN, "No configuration found for device " << inputDevice->GetName() );
181 vector<SGPropertyNode_ptr> eventNodes = deviceNode->getChildren( "event" );
182 for( vector<SGPropertyNode_ptr>::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ ) {
183 FGInputEvent * p = FGInputEvent::NewObject( *it );
185 SG_LOG(SG_INPUT, SG_WARN, "Unhandled event/name in " << inputDevice->GetName() );
188 inputDevice->AddHandledEvent( p );
192 // add nodes for the last event:
193 // last-event/name [string]
194 // last-event/value [double]
198 input_devices[ deviceNode->getIndex() ] = inputDevice;
201 SG_LOG(SG_INPUT, SG_WARN, "can't open InputDevice " << inputDevice->GetName() );