]> git.mxchange.org Git - flightgear.git/blobdiff - src/Input/FGEventInput.cxx
Document that property write-protection is not a security measure
[flightgear.git] / src / Input / FGEventInput.cxx
index 5731bc463968d8f09a8ca243cc5ebe51b33e1c8c..29bdc6e1d128a8d40337405b0f50c5fd3aa59938 100644 (file)
 #  include <config.h>
 #endif
 
+#include <cstring>
 #include "FGEventInput.hxx"
 #include <Main/fg_props.hxx>
 #include <simgear/io/sg_file.hxx>
-#include <poll.h>
-#include <linux/input.h>
+#include <simgear/props/props_io.hxx>
+#include <simgear/math/SGMath.hxx>
+#include <Scripting/NasalSys.hxx>
+
+using simgear::PropertyList;
+using std::cout;
+using std::endl;
+using std::map;
+using std::string;
 
 FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
   value(0.0)
@@ -65,7 +73,7 @@ bool FGEventSetting::Test()
 
 static inline bool StartsWith( string & s, const char * cp )
 {
-  return s.compare( 0, strlen(cp), cp ) == 0;
+  return s.find( cp ) == 0;
 }
 
 FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_ptr node )
@@ -75,10 +83,10 @@ FGInputEvent * FGInputEvent::NewObject( FGInputDevice * device, SGPropertyNode_p
     return new FGButtonEvent( device, node );
 
   if( StartsWith( name, "rel-" ) )
-    return new FGAxisEvent( device, node );
+    return new FGRelAxisEvent( device, node );
 
   if( StartsWith( name, "abs-" ) )
-    return new FGAxisEvent( device, node );
+    return new FGAbsAxisEvent( device, node );
 
   return new FGInputEvent( device, node );
 }
@@ -91,12 +99,11 @@ FGInputEvent::FGInputEvent( FGInputDevice * aDevice, SGPropertyNode_ptr node ) :
   name = node->getStringValue( "name", "" );
   desc = node->getStringValue( "desc", "" );
   intervalSec = node->getDoubleValue("interval-sec",0.0);
-  string module = "event";
   
-  read_bindings( node, bindings, KEYMOD_NONE, module );
+  read_bindings( node, bindings, KEYMOD_NONE, device->GetNasalModule() );
 
-  vector<SGPropertyNode_ptr> settingNodes = node->getChildren("setting");
-  for( vector<SGPropertyNode_ptr>::iterator it = settingNodes.begin(); it != settingNodes.end(); it++ )
+  PropertyList settingNodes = node->getChildren("setting");
+  for( PropertyList::iterator it = settingNodes.begin(); it != settingNodes.end(); ++it )
     settings.push_back( new FGEventSetting( *it ) );
 }
 
@@ -106,7 +113,7 @@ FGInputEvent::~FGInputEvent()
 
 void FGInputEvent::update( double dt )
 {
-  for( setting_list_t::iterator it = settings.begin(); it != settings.end(); it++ ) {
+  for( setting_list_t::iterator it = settings.begin(); it != settings.end(); ++it ) {
     if( (*it)->Test() ) {
       double value = (*it)->GetValue();
       if( value != lastSettingValue ) {
@@ -122,19 +129,26 @@ void FGInputEvent::fire( FGEventData & eventData )
   lastDt += eventData.dt;
   if( lastDt >= intervalSec ) {
 
-    for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); it++ )
-      (*it)->fire( eventData.value, 1.0 );
+    for( binding_list_t::iterator it = bindings[eventData.modifiers].begin(); it != bindings[eventData.modifiers].end(); ++it )
+      fire( *it, eventData );
 
     lastDt -= intervalSec;
   }
 }
 
+void FGInputEvent::fire( SGBinding * binding, FGEventData & eventData )
+{
+  binding->fire();
+}
+
+
+
 FGAxisEvent::FGAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
   FGInputEvent( device, node )
 {
   tolerance = node->getDoubleValue("tolerance", 0.002);
-  minRange = node->getDoubleValue("min-range", -1024.0);
-  maxRange = node->getDoubleValue("max-range", 1024.0);
+  minRange = node->getDoubleValue("min-range", 0.0 );
+  maxRange = node->getDoubleValue("max-range", 0.0 );
   center = node->getDoubleValue("center", 0.0);
   deadband = node->getDoubleValue("dead-band", 0.0);
   lowThreshold = node->getDoubleValue("low-threshold", -0.9);
@@ -147,7 +161,36 @@ void FGAxisEvent::fire( FGEventData & eventData )
   if (fabs( eventData.value - lastValue) < tolerance)
     return;
   lastValue = eventData.value;
-  FGInputEvent::fire( eventData );
+
+  // We need a copy of the  FGEventData struct to set the new value and to avoid side effects
+  FGEventData ed = eventData;
+
+  if( fabs(ed.value) < deadband )
+    ed.value = 0.0;
+
+  if( minRange != maxRange )
+    ed.value = 2.0*(eventData.value-minRange)/(maxRange-minRange)-1.0;
+
+  FGInputEvent::fire( ed );
+}
+
+void FGAbsAxisEvent::fire( SGBinding * binding, FGEventData & eventData )
+{
+  // sets the "setting" node
+  binding->fire( eventData.value );
+}
+
+FGRelAxisEvent::FGRelAxisEvent( FGInputDevice * device, SGPropertyNode_ptr node ) : 
+  FGAxisEvent( device, node ) 
+{
+  // relative axes can't use tolerance
+  tolerance = 0.0;
+}
+
+void FGRelAxisEvent::fire( SGBinding * binding, FGEventData & eventData )
+{
+  // sets the "offset" node
+  binding->fire( eventData.value, 1.0 );
 }
 
 FGButtonEvent::FGButtonEvent( FGInputDevice * device, SGPropertyNode_ptr node ) :
@@ -181,8 +224,51 @@ void FGButtonEvent::fire( FGEventData & eventData )
 
 FGInputDevice::~FGInputDevice()
 {
+  FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
+  if (nas && deviceNode ) {
+    SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
+    if( nasal ) {
+      SGPropertyNode_ptr nasalClose = nasal->getNode("close");
+      if (nasalClose) {
+        const string s = nasalClose->getStringValue();
+        nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
+      }
+    }
+    nas->deleteModule(nasalModule.c_str());
+  }
 } 
 
+void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
+{
+  deviceNode = aDeviceNode;
+
+  nasalModule = string("__event:") + GetName();
+
+  PropertyList eventNodes = deviceNode->getChildren( "event" );
+  for( PropertyList::iterator it = eventNodes.begin(); it != eventNodes.end(); ++it )
+    AddHandledEvent( FGInputEvent::NewObject( this, *it ) );
+
+  debugEvents = deviceNode->getBoolValue("debug-events", debugEvents );
+  grab = deviceNode->getBoolValue("grab", grab );
+
+  // TODO:
+  // add nodes for the last event:
+  // last-event/name [string]
+  // last-event/value [double]
+
+  SGPropertyNode_ptr nasal = deviceNode->getNode("nasal");
+  if (nasal) {
+    SGPropertyNode_ptr open = nasal->getNode("open");
+    if (open) {
+      const string s = open->getStringValue();
+      FGNasalSys *nas = (FGNasalSys *)globals->get_subsystem("nasal");
+      if (nas)
+        nas->createModule(nasalModule.c_str(), nasalModule.c_str(), s.c_str(), s.length(), deviceNode );
+    }
+  }
+
+}
+
 void FGInputDevice::update( double dt )
 {
   for( map<string,FGInputEvent_ptr>::iterator it = handledEvents.begin(); it != handledEvents.end(); it++ )
@@ -209,13 +295,13 @@ void FGInputDevice::SetName( string name )
 const char * FGEventInput::PROPERTY_ROOT = "/input/event";
 
 FGEventInput::FGEventInput() : 
-  configMap( "Input/Event", fgGetNode( PROPERTY_ROOT, true ), "device-named" )
+  configMap( "Input/Event", fgGetNode(PROPERTY_ROOT, true), "device-named")
 {
 }
 
 FGEventInput::~FGEventInput()
 {
-  for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); it++ )
+  for( map<int,FGInputDevice*>::iterator it = input_devices.begin(); it != input_devices.end(); ++it )
     delete (*it).second;
   input_devices.clear();
 }
@@ -234,54 +320,46 @@ void FGEventInput::postinit ()
 void FGEventInput::update( double dt )
 {
   // call each associated device's update() method
-  for( map<int,FGInputDevice*>::iterator it =  input_devices.begin(); it != input_devices.end(); it++ )
+  for( map<int,FGInputDevice*>::iterator it =  input_devices.begin(); it != input_devices.end(); ++it )
     (*it).second->update( dt );
 }
 
-void FGEventInput::AddDevice( FGInputDevice * inputDevice )
+unsigned FGEventInput::AddDevice( FGInputDevice * inputDevice )
 {
   SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
   SGPropertyNode_ptr deviceNode = NULL;
 
   // look for configuration in the device map
-  if( configMap.count( inputDevice->GetName() ) > 0 ) {
+  if ( configMap.hasConfiguration( inputDevice->GetName() ) ) {
     // found - copy to /input/event/device[n]
 
     // find a free index
     unsigned index;
-    for( index = 0; index < 1000; index++ )
+    for( index = 0; index < MAX_DEVICES; index++ )
       if( (deviceNode = baseNode->getNode( "device", index, false ) ) == NULL )
         break;
 
-    if( index == 1000 ) {
+    if( index == MAX_DEVICES ) {
       SG_LOG(SG_INPUT, SG_WARN, "To many event devices - ignoring " << inputDevice->GetName() );
-      return;
+      return INVALID_DEVICE_INDEX;
     }
 
     // create this node 
     deviceNode = baseNode->getNode( "device", index, true );
 
     // and copy the properties from the configuration tree
-    copyProperties( configMap[ inputDevice->GetName() ], deviceNode );
+    copyProperties( configMap.configurationForDeviceName(inputDevice->GetName()), deviceNode );
+
   }
 
   if( deviceNode == NULL ) {
     SG_LOG(SG_INPUT, SG_DEBUG, "No configuration found for device " << inputDevice->GetName() );
     delete  inputDevice;
-    return;
+    return INVALID_DEVICE_INDEX;
   }
 
-  vector<SGPropertyNode_ptr> eventNodes = deviceNode->getChildren( "event" );
-  for( vector<SGPropertyNode_ptr>::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ )
-    inputDevice->AddHandledEvent( FGInputEvent::NewObject( inputDevice, *it ) );
-
-  inputDevice->SetDebugEvents( deviceNode->getBoolValue("debug-events", inputDevice->GetDebugEvents() ));
+  inputDevice->Configure( deviceNode );
 
-  // TODO:
-  // add nodes for the last event:
-  // last-event/name [string]
-  // last-event/value [double]
-  
   try {        
     inputDevice->Open();
     input_devices[ deviceNode->getIndex() ] = inputDevice;
@@ -289,7 +367,25 @@ void FGEventInput::AddDevice( FGInputDevice * inputDevice )
   catch( ... ) {
     delete  inputDevice;
     SG_LOG(SG_INPUT, SG_ALERT, "can't open InputDevice " << inputDevice->GetName()  );
+    return INVALID_DEVICE_INDEX;
   }
 
   SG_LOG(SG_INPUT, SG_DEBUG, "using InputDevice " << inputDevice->GetName()  );
+  return deviceNode->getIndex();
 }
+
+void FGEventInput::RemoveDevice( unsigned index )
+{
+  // not fully implemented yet
+  SGPropertyNode_ptr baseNode = fgGetNode( PROPERTY_ROOT, true );
+  SGPropertyNode_ptr deviceNode = NULL;
+
+  FGInputDevice *inputDevice = input_devices[index];
+  if (inputDevice) {
+    input_devices.erase(index);
+    delete inputDevice;
+    
+  }
+  deviceNode = baseNode->removeChild("device", index);
+}
+