]> git.mxchange.org Git - flightgear.git/blob - src/Input/FGEventInput.cxx
bf041367113ce8302a60e2e4f00a8cf83b4e9c2d
[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 #include "FGEventInput.hxx"
24 #include <Main/fg_props.hxx>
25 #include <simgear/io/sg_file.hxx>
26 #include <poll.h>
27 #include <linux/input.h>
28
29 static inline bool StartsWith( string & s, const char * cp )
30 {
31   return s.compare( 0, strlen(cp), cp ) == 0;
32 }
33
34 FGInputEvent * FGInputEvent::NewObject( SGPropertyNode_ptr node )
35 {
36   string name = node->getStringValue( "name" );
37   if( StartsWith( name, "button-" ) )
38     return new FGButtonEvent( node );
39
40   if( StartsWith( name, "rel-" ) )
41     return new FGAxisEvent( node );
42
43   if( StartsWith( name, "abs-" ) )
44     return new FGAxisEvent( node );
45
46   return NULL;
47 }
48
49 FGInputEvent::FGInputEvent( SGPropertyNode_ptr node ) :
50   lastDt(0.0)
51 {
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 );
57 }
58
59 FGInputEvent::~FGInputEvent()
60 {
61 }
62
63 void FGInputEvent::fire( FGEventData & eventData )
64 {
65   lastDt += eventData.dt;
66   if( lastDt >= intervalSec ) {
67
68     for( binding_list_t::iterator it = bindings[KEYMOD_NONE].begin(); it != bindings[KEYMOD_NONE].end(); it++ )
69       (*it)->fire( eventData.value, 1.0 );
70
71     lastDt -= intervalSec;
72   }
73 }
74
75 FGAxisEvent::FGAxisEvent( SGPropertyNode_ptr node ) :
76   FGInputEvent( node )
77 {
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);
85   lastValue = 9999999;
86 }
87
88 void FGAxisEvent::fire( FGEventData & eventData )
89 {
90   if (fabs( eventData.value - lastValue) < tolerance)
91     return;
92   lastValue = eventData.value;
93   FGInputEvent::fire( eventData );
94 }
95
96 FGButtonEvent::FGButtonEvent( SGPropertyNode_ptr node ) :
97   FGInputEvent( node )
98 {
99 }
100
101 void FGButtonEvent::fire( FGEventData & eventData )
102 {
103   FGInputEvent::fire( eventData );
104 }
105
106 FGInputDevice::~FGInputDevice()
107 {
108
109
110 void FGInputDevice::HandleEvent( FGEventData & eventData )
111 {
112   string eventName = TranslateEventName( eventData );  
113   cout << GetName() << " has event " << eventName << endl;
114   if( handledEvents.count( eventName ) > 0 ) {
115     handledEvents[ eventName ]->fire( eventData );
116   }
117 }
118
119 void FGInputDevice::SetName( string name )
120 {
121   this->name = name; 
122 }
123
124 const char * FGEventInput::PROPERTY_ROOT = "/input/event";
125
126 FGEventInput::FGEventInput() : 
127   configMap( "Input/Event", fgGetNode( PROPERTY_ROOT, true ), "device-named" )
128 {
129 }
130
131 FGEventInput::~FGEventInput()
132 {
133   for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); it++ )
134     delete (*it).second;
135   input_devices.clear();
136 }
137
138 void FGEventInput::init( )
139 {
140   SG_LOG(SG_INPUT, SG_DEBUG, "Initializing event bindings");
141   SGPropertyNode * base = fgGetNode("/input/event", true);
142
143 }
144
145 void FGEventInput::postinit ()
146 {
147 }
148
149 void FGEventInput::AddDevice( FGInputDevice * inputDevice )
150 {
151   SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
152   SGPropertyNode_ptr deviceNode = NULL;
153
154   // look for configuration in the device map
155   if( configMap.count( inputDevice->GetName() ) > 0 ) {
156     // found - copy to /input/event/device[n]
157
158     // find a free index
159     unsigned index;
160     for( index = 0; index < 1000; index++ )
161       if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
162         break;
163
164     if( index == 1000 ) {
165       SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
166       return;
167     }
168
169     // create this node 
170     deviceNode = baseNode->getNode( "device", index, true );
171
172     // and copy the properties from the configuration tree
173     copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
174   }
175
176   if( deviceNode == NULL ) {
177     SG_LOG(SG_INPUT, SG_WARN, "No configuration found for device " << inputDevice->GetName() );
178     return;
179   }
180
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 );
184     if( p == NULL ) {
185       SG_LOG(SG_INPUT, SG_WARN, "Unhandled event/name in " << inputDevice->GetName()  );
186       continue;
187     }
188     inputDevice->AddHandledEvent( p );
189   }
190
191   // TODO:
192   // add nodes for the last event:
193   // last-event/name [string]
194   // last-event/value [double]
195   
196   try { 
197     inputDevice->Open();
198     input_devices[ deviceNode->getIndex() ] = inputDevice;
199   }
200   catch( ... ) {
201     SG_LOG(SG_INPUT, SG_WARN, "can't open InputDevice " << inputDevice->GetName()  );
202   }
203 }