]> git.mxchange.org Git - flightgear.git/commitdiff
Stefan Seifert:
authormfranz <mfranz>
Tue, 4 Jul 2006 23:29:05 +0000 (23:29 +0000)
committermfranz <mfranz>
Tue, 4 Jul 2006 23:29:05 +0000 (23:29 +0000)
- read bindings from template
- automatic deadband detection

mf:
- write js name into output file
- poor man's progress bar during deadband detection
- fix header inclusion, fix mixed indentation

src/Input/Makefile.am
src/Input/fgjs.cxx
src/Input/jsinput.cxx
src/Input/jsinput.h

index 6671e74f09a4b15e5727684a6f003a84a2ee9a9e..b607855b7073fbbc43ef29ec486c9383606389d6 100644 (file)
@@ -1,3 +1,5 @@
+AM_CXXFLAGS = -DPKGLIBDIR=\"$(pkgdatadir)\"
+
 noinst_LIBRARIES = libInput.a
 
 libInput_a_SOURCES = input.cxx input.hxx
@@ -10,6 +12,7 @@ js_demo_LDADD = -lplibjs $(base_LIBS) $(joystick_LIBS) -lplibul
 
 fgjs_SOURCES = fgjs.cxx jsinput.cxx jsinput.h jssuper.cxx jssuper.h
 
-fgjs_LDADD = -lplibjs $(base_LIBS) $(joystick_LIBS) -lplibul
+fgjs_LDADD = -lplibjs $(base_LIBS) $(joystick_LIBS) -lplibul \
+       -lsgprops -lsgmisc -lsgio -lsgdebug -lsgstructure -lsgxml -lz
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/Main
index eec3eb6839f7f222bed3f8df4511c5984879e5da..e73266a63c18b0fc7b572d65958b87c21c66f67e 100644 (file)
@@ -6,6 +6,7 @@
 // Written by Tony Peden, started May 2001
 //
 // Copyright (C) 2001  Tony Peden (apeden@earthlink.net)
+// Copyright (C) 2006  Stefan Seifert
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -29,8 +30,6 @@
 #include STL_FSTREAM
 #include STL_STRING
 
-#include <jsinput.h>
-
 SG_USING_STD(fstream);
 SG_USING_STD(cout);
 SG_USING_STD(cin);
@@ -38,460 +37,336 @@ SG_USING_STD(endl);
 SG_USING_STD(ios);
 SG_USING_STD(string);
 
-string axes_humannames[8] = { "Aileron", "Elevator", "Rudder", "Throttle",
-                              "Mixture", "Pitch", "View Direction",
-                              "View Elevation"
-                            };
-
-string axes_propnames[8]={ "/controls/flight/aileron","/controls/flight/elevator",
-                           "/controls/flight/rudder","/controls/engines/engine[%d]/throttle",
-                           "/controls/engines/engine[%d]/mixture","/controls/engines/engine[%d]/pitch",
-                           "/sim/current-view/goal-heading-offset-deg",
-                           "/sim/current-view/goal-pitch-offset-deg"
-                         };
-
-string axis_posdir[8]= { "right", "down/forward", "right", "forward", "forward", "forward", "left", "upward" };
-
-
-bool half_range[8]={ false,false,false,true,true,true,false,false };
-
-bool repeatable[8]={ false,false,false,false,false,false,true,true };
-
-bool invert[8]= { false,false,false,false,false,false,false,false };
-
-string button_humannames[8]= { "Left Brake", "Right Brake",
-                               "Flaps Up", "Flaps Down",
-                               "Elevator Trim Forward", "Elevator Trim Backward",
-                               "Landing Gear Up", "Landing Gear Down"
-                             };
-
-string button_propnames[8]={ "/controls/gear/brake-left",
-                             "/controls/gear/brake-right",
-                             "/controls/flight/flaps",
-                             "/controls/flight/flaps",
-                             "/controls/flight/elevator-trim",
-                             "/controls/flight/elevator-trim",
-                             "/controls/gear/gear-down",
-                             "/controls/gear/gear-down"
-                           };
-
-bool button_modup[8]={ true,true,false,false,false,false,false,false };
-
-bool button_boolean[8]={ false,false,false,false,false,false,true,true };
-
-float button_step[8]={ 1.0, 1.0, -0.34, 0.34, 0.001, -0.001, 0.0, 1.0 };
-
-string button_repeat[8]={ "false", "false", "false", "false", "true", "true", "false", "false" };
-
-
-void writeAxisXML(fstream &fs, int control, int axis) {
-
-     char axisline[16];
-     snprintf(axisline,16," <axis n=\"%d\">",axis);
-
-     fs << axisline << endl;
-     fs << "  <desc>" << axes_humannames[control] << "</desc>" << endl;
-     if (half_range[control]) {
-       for (int i=0; i<=7; i++) {
-         fs << "  <binding>" << endl;
-         fs << "   <command>property-scale</command>" << endl;
-         char propertyline[256];
-         snprintf(propertyline,256,axes_propnames[control].c_str(),i);
-         fs << "   <property>" << propertyline << "</property>" << endl;
-         fs << "   <offset type=\"double\">-1.0</offset>" << endl;
-         fs << "   <factor type=\"double\">-0.5</factor>" << endl;
-         fs << "  </binding>" << endl;
-       }
-     } else if (repeatable[control]) {
-       fs << "  <low>" << endl;
-       fs << "   <repeatable>true</repeatable>" << endl;
-       fs << "   <binding>" << endl;
-       fs << "    <command>property-adjust</command>" << endl;
-       fs << "    <property>" << axes_propnames[control] << "</property>" << endl;
-       if (invert[control]) {
-         fs << "    <step type=\"double\">1.0</step>" << endl;
-       } else {
-         fs << "    <step type=\"double\">-1.0</step>" << endl;
-       }
-       fs << "   </binding>" << endl;
-       fs << "  </low>" << endl;
-       fs << "  <high>" << endl;
-       fs << "   <repeatable>true</repeatable>" << endl;
-       fs << "   <binding>" << endl;
-       fs << "    <command>property-adjust</command>" << endl;
-       fs << "    <property>" << axes_propnames[control] << "</property>" << endl;
-       if (invert[control]) {
-         fs << "    <step type=\"double\">-1.0</step>" << endl;
-       } else {
-         fs << "    <step type=\"double\">1.0</step>" << endl;
-       }
-       fs << "   </binding>" << endl;
-       fs << "  </high>" << endl;
-     } else {
-       fs << "  <binding>" << endl;
-       fs << "   <command>property-scale</command>" << endl;
-       fs << "   <property>" << axes_propnames[control] << "</property>" << endl;
-       fs << "   <dead-band type=\"double\">0.02</dead-band>" << endl;
-       fs << "   <offset type=\"double\">0.0</offset>" << endl;
-       if (invert[control]) {
-         fs << "   <factor type=\"double\">-1.0</factor>" << endl;
-       } else {
-         fs << "   <factor type=\"double\">1.0</factor>" << endl;
-       }
-       fs << "  </binding>" << endl;
-     }
-     fs << " </axis>" << endl << endl;
+#include <simgear/constants.h>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/misc/sg_path.hxx>
+#include <simgear/misc/sgstream.hxx>
+#include <simgear/structure/exception.hxx>
+
+#include <Main/fg_io.hxx>
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+
+#include "jsinput.h"
+
+
+bool confirmAnswer() {
+    char answer;
+    do {
+        cout << "Is this correct? (y/n) $ ";
+        cin >> answer;
+        cin.ignore(256, '\n');
+        if (answer == 'y')
+            return true;
+        if (answer == 'n')
+            return false;
+    } while (true);
 }
 
-void writeAxisProperties(fstream &fs, int control,int joystick, int axis) {
-
-     char jsDesc[80];
-     snprintf(jsDesc,80,"--prop:/input/joysticks/js[%d]/axis[%d]",joystick,axis);
-     if( half_range[control] == true) {
-       for (int i=0; i<=7; i++) {
-         char bindno[64];
-         snprintf(bindno,64,"/binding[%d]",i);
-         char propertyline[256];
-         snprintf(propertyline,256,axes_propnames[control].c_str(),i);
-         fs << jsDesc << bindno << "/command=property-scale" << endl;
-         fs << jsDesc << bindno << "/property=" << propertyline << endl;
-         fs << jsDesc << bindno << "/offset=-1.0" << endl;
-         fs << jsDesc << bindno << "/factor=-0.5" << endl;
-       }
-     } else if (repeatable[control]) {
-       fs << jsDesc << "/low/repeatable=true" << endl;
-       fs << jsDesc << "/low/binding/command=property-adjust" << endl;
-       fs << jsDesc << "/low/binding/property=" << axes_propnames[control] << endl;
-       if (invert[control]) {
-         fs << jsDesc << "/low/binding/step=1.0" << endl;
-       } else {
-         fs << jsDesc << "/low/binding/step=-1.0" << endl;
-       }
-       fs << jsDesc << "/high/repeatable=true" << endl;
-       fs << jsDesc << "/high/binding/command=property-adjust" << endl;
-       fs << jsDesc << "/high/binding/property=" << axes_propnames[control] << endl;
-       if (invert[control]) {
-         fs << jsDesc << "/high/binding/step=-1.0" << endl;
-       } else {
-         fs << jsDesc << "/high/binding/step=1.0" << endl;
-       }
-     } else {
-       fs << jsDesc << "/binding/command=property-scale" << endl;
-       fs << jsDesc << "/binding/property=" << axes_propnames[control] << endl;
-       fs << jsDesc << "/binding/dead-band=0.02" << endl;
-       fs << jsDesc << "/binding/offset=0.0" << endl;
-       if (invert[control]) {
-         fs << jsDesc << "/binding/factor=-1.0" << endl;
-       } else {
-         fs << jsDesc << "/binding/factor=1.0" << endl;
-       }
-     }
-     fs << endl;
-}
+string getFGRoot( int argc, char *argv[] );
+
+int main( int argc, char *argv[] ) {
+
+    for (int i = 1; i < argc; i++) {
+        if (strcmp("--help", argv[i]) == 0) {
+            cout << "Usage:" << endl;
+            cout << "  --help\t\t\tShow this help" << endl;
+            exit(0);
+        } else {
+            cout << "Unknown option \"" << argv[i] << "\"" << endl;
+            exit(0);
+        }
+    }
+
+    jsInit();
+
+    jsSuper *jss = new jsSuper();
+    jsInput *jsi = new jsInput(jss);
+    jsi->displayValues(false);
+
+    cout << "Found " << jss->getNumJoysticks() << " joystick(s)" << endl;
+
+    if(jss->getNumJoysticks() <= 0) {
+        cout << "Can't find any joysticks ..." << endl;
+        exit(1);
+    }
+    cout << endl << "Now measuring the dead band of your joystick. The dead band is the area " << endl
+                 << "where the joystick is centered and should not generate any input. Move all " << endl
+                 << "axes around in this dead zone during the ten seconds this test will take." << endl;
+    cout << "Press enter to continue." << endl;
+    cin.ignore(1024, '\n');
+    jsi->findDeadBand();
+    cout << endl << "Dead band calibration finished. Press enter to start control assignment." << endl;
+    cin.ignore(1024, '\n');
+
+    jss->firstJoystick();
+    fstream *xfs = new fstream[ jss->getNumJoysticks() ];
+    SGPropertyNode_ptr *jstree = new SGPropertyNode_ptr[ jss->getNumJoysticks() ];
+    do {
+        cout << "Joystick #" << jss->getCurrentJoystickId()
+             << " \"" << jss->getJoystick()->getName() << "\" has "
+             << jss->getJoystick()->getNumAxes() << " axes" << endl;
+
+        char filename[16];
+        snprintf(filename, 16, "js%i.xml", jss->getCurrentJoystickId());
+        xfs[ jss->getCurrentJoystickId() ].open(filename, ios::out);
+        jstree[ jss->getCurrentJoystickId() ] = new SGPropertyNode();
+    } while ( jss->nextJoystick() );
+
+    SGPath templatefile( getFGRoot(argc, argv) );
+    templatefile.append("Input");
+    templatefile.append("Joysticks");
+    templatefile.append("template.xml");
+
+    SGPropertyNode *templatetree = new SGPropertyNode();
+    try {
+        readProperties(templatefile.str().c_str(), templatetree);
+    } catch (sg_io_exception e) {
+        cout << e.getFormattedMessage ();
+    }
 
-void writeButtonXML(fstream &fs, int property, int button) {
-
-     char buttonline[32];
-     snprintf(buttonline,32," <button n=\"%d\">",button);
-
-     fs << buttonline << endl;
-     if (property==-2) {
-       fs << "  <desc>View Cycle</desc>" << endl;
-       fs << "  <repeatable>false</repeatable>" << endl;
-       fs << "  <binding>" << endl;
-       fs << "   <command>view-cycle</command>" << endl;
-       fs << "   <step type=\"double\">1</step>" << endl;
-       fs << "  </binding>" << endl;
-     } else if (property==-1) {
-       fs << "  <desc>Brakes</desc>" << endl;
-       fs << "  <binding>" << endl;
-       fs << "   <command>property-assign</command>" << endl;
-       fs << "   <property>" << button_propnames[0] << "</property>" << endl;
-       fs << "   <value type=\"double\">" << button_step[0] << "</value>" << endl;
-       fs << "  </binding>" << endl;
-       fs << "  <binding>" << endl;
-       fs << "   <command>property-assign</command>" << endl;
-       fs << "   <property>" << button_propnames[1] << "</property>" << endl;
-       fs << "   <value type=\"double\">" << button_step[1] << "</value>" << endl;
-       fs << "  </binding>" << endl;
-       fs << "  <mod-up>" << endl;
-       fs << "   <binding>" << endl;
-       fs << "    <command>property-assign</command>" << endl;
-       fs << "    <property>" << button_propnames[0] << "</property>" << endl;
-       fs << "    <value type=\"double\">0</value>" << endl;
-       fs << "   </binding>" << endl;
-       fs << "   <binding>" << endl;
-       fs << "    <command>property-assign</command>" << endl;
-       fs << "    <property>" << button_propnames[1] << "</property>" << endl;
-       fs << "    <value type=\"double\">0</value>" << endl;
-       fs << "   </binding>" << endl;
-       fs << "  </mod-up>" << endl;
-     } else {
-       fs << "  <desc>" << button_humannames[property] << "</desc>" << endl;
-       if (button_modup[property]) {
-         fs << "  <binding>" << endl;
-         fs << "   <command>property-assign</command>" << endl;
-         fs << "   <property>" << button_propnames[property] << "</property>" << endl;
-         fs << "   <value type=\"double\">" << button_step[property] << "</value>" << endl;
-         fs << "  </binding>" << endl;
-         fs << "  <mod-up>" << endl;
-         fs << "   <binding>" << endl;
-         fs << "    <command>property-assign</command>" << endl;
-         fs << "    <property>" << button_propnames[property] << "</property>" << endl;
-         fs << "    <value type=\"double\">0</value>" << endl;
-         fs << "   </binding>" << endl;
-         fs << "  </mod-up>" << endl;
-       } else if (button_boolean[property]) {
-         fs << "  <repeatable>" << button_repeat[property] << "</repeatable>" << endl;
-         fs << "  <binding>" << endl;
-         fs << "   <command>property-assign</command>" << endl;
-         fs << "   <property>" << button_propnames[property] << "</property>" << endl;
-         fs << "   <value type=\"bool\">";
-         if (button_step[property]==1) {
-           fs << "true";
-         } else {
-           fs << "false";
-         }
-         fs << "</value>" << endl;
-         fs << "  </binding>" << endl;
-       } else {
-         fs << "  <repeatable>" << button_repeat[property] << "</repeatable>" << endl;
-         fs << "  <binding>" << endl;
-         fs << "   <command>property-adjust</command>" << endl;
-         fs << "   <property>" << button_propnames[property] << "</property>" << endl;
-         fs << "   <step type=\"double\">" << button_step[property] << "</step>" << endl;
-         fs << "  </binding>" << endl;
-       }
-     }
-     fs << " </button>" << endl << endl;
+    vector<SGPropertyNode_ptr> axes = templatetree->getChildren("axis");
+    for(vector<SGPropertyNode_ptr>::iterator iter = axes.begin(); iter != axes.end(); iter++) {
+        cout << "Move the control you wish to use for " << (*iter)->getStringValue("desc")
+             << " " << (*iter)->getStringValue("direction") << endl;
+        cout << "Pressing a button skips this axis" << endl;
+        fflush( stdout );
+        jsi->getInput();
+        if (jsi->getInputAxis() != -1) {
+            cout << endl << "Assigned axis " << jsi->getInputAxis()
+                 << " on joystick " << jsi->getInputJoystick()
+                 << " to control " << (*iter)->getStringValue("desc") << endl;
+            if ( confirmAnswer() ) {
+                SGPropertyNode *axis = jstree[ jsi->getInputJoystick() ]->getChild("axis", jsi->getInputAxis(), true);
+                copyProperties(*iter, axis);
+                axis->setDoubleValue("dead-band", jss->getJoystick(jsi->getInputJoystick())
+                        ->getDeadBand(jsi->getInputAxis()));
+                axis->setDoubleValue("binding/factor", jsi->getInputAxisPositive() ? 1.0 : -1.0);
+            } else {
+                iter--;
+            }
+        } else {
+            cout << "Skipping control" << endl;
+            if ( ! confirmAnswer() )
+                iter--;
+        }
+        cout << endl;
+    }
+
+    vector<SGPropertyNode_ptr> buttons = templatetree->getChildren("button");
+    for(vector<SGPropertyNode_ptr>::iterator iter = buttons.begin(); iter != buttons.end(); iter++) {
+        cout << "Press the button you wish to use for " << (*iter)->getStringValue("desc") << endl;
+        cout << "Moving a joystick axis skips this button" << endl;
+        fflush( stdout );
+        jsi->getInput();
+        if (jsi->getInputButton() != -1) {
+            cout << endl << "Assigned button " << jsi->getInputButton()
+                 << " on joystick " << jsi->getInputJoystick()
+                 << " to control " << (*iter)->getStringValue("desc") << endl;
+            if ( confirmAnswer() ) {
+                SGPropertyNode *button = jstree[ jsi->getInputJoystick() ]->getChild("button", jsi->getInputButton(), true);
+                copyProperties(*iter, button);
+            } else {
+                iter--;
+            }
+        } else {
+            cout << "Skipping control" << endl;
+            if (! confirmAnswer())
+                iter--;
+        }
+        cout << endl;
+    }
+
+    cout << "Your joystick settings are in ";
+    for (int i = 0; i < jss->getNumJoysticks(); i++) {
+        try {
+            cout << "js" << i << ".xml";
+            if (i + 2 < jss->getNumJoysticks())
+                cout << ", ";
+            else if (i + 1 < jss->getNumJoysticks())
+                cout << " and ";
+
+            jstree[i]->setStringValue("name", jss->getJoystick(i)->getName());
+            writeProperties(xfs[i], jstree[i], true);
+        } catch (sg_io_exception e) {
+            cout << e.getFormattedMessage ();
+        }
+        xfs[i].close();
+    }
+    cout << "." << endl << "Check and edit as desired. Once you are happy," << endl
+         << "move relevant js<n>.xml files to $FG_ROOT/Input/Joysticks/ (if you didn't use" << endl
+         << "an attached controller, you don't need to move the corresponding file)" << endl;
+
+    delete jsi;
+    delete[] xfs;
+    delete jss;
+
+    return 1;
 }
 
-void writeButtonProperties(fstream &fs, int property,int joystick, int button) {
-
-     char jsDesc[80];
-     snprintf(jsDesc,80,"--prop:/input/joysticks/js[%d]/button[%d]",joystick,button);
-
-     if (property==-1) {
-       fs << jsDesc << "/binding[0]/command=property-assign" << endl; 
-       fs << jsDesc << "/binding[0]/property=" << button_propnames[0] << endl;
-       fs << jsDesc << "/binding[0]/value=" << button_step[0] << endl; 
-       fs << jsDesc << "/binding[1]/command=property-assign" << endl; 
-       fs << jsDesc << "/binding[1]/property=" << button_propnames[1] << endl;
-       fs << jsDesc << "/binding[1]/value=" << button_step[1] << endl; 
-       fs << jsDesc << "/mod-up/binding[0]/command=property-assign" << endl; 
-       fs << jsDesc << "/mod-up/binding[0]/property=" << button_propnames[0] << endl;
-       fs << jsDesc << "/mod-up/binding[0]/value=0" << endl; 
-       fs << jsDesc << "/mod-up/binding[1]/command=property-assign" << endl; 
-       fs << jsDesc << "/mod-up/binding[1]/property=" << button_propnames[1] << endl;
-       fs << jsDesc << "/mod-up/binding[1]/value=0" << endl; 
-       fs << endl; 
-     } else if (button_modup[property]) {
-       fs << jsDesc << "/binding/command=property-assign" << endl; 
-       fs << jsDesc << "/binding/property=" << button_propnames[property] << endl;
-       fs << jsDesc << "/binding/value=" << button_step[property] << endl; 
-       fs << jsDesc << "/mod-up/binding/command=property-assign" << endl; 
-       fs << jsDesc << "/mod-up/binding/property=" << button_propnames[property] << endl;
-       fs << jsDesc << "/mod-up/binding/value=0" << endl; 
-       fs << endl; 
-     } else if (button_boolean[property]) {
-       fs << jsDesc << "/repeatable=" << button_repeat[property] << endl;
-       fs << jsDesc << "/binding/command=property-assign" << endl; 
-       fs << jsDesc << "/binding/property=" << button_propnames[property] << endl;
-       fs << jsDesc << "/binding/value=";
-       if (button_step[property]==1) {
-         fs << "true";
-       } else {
-         fs << "false";
-       }
-       fs << endl << endl; 
-     } else {
-       fs << jsDesc << "/repeatable=" << button_repeat[property] << endl;
-       fs << jsDesc << "/binding/command=property-adjust" << endl; 
-       fs << jsDesc << "/binding/property=" << button_propnames[property] << endl;
-       fs << jsDesc << "/binding/step=" << button_step[property] << endl; 
-       fs << endl; 
-     }
+char *homedir = ::getenv( "HOME" );
+char *hostname = ::getenv( "HOSTNAME" );
+bool free_hostname = false;
+
+// Scan the command line options for the specified option and return
+// the value.
+static string fgScanForOption( const string& option, int argc, char **argv ) {
+    int i = 1;
+
+    if (hostname == NULL)
+    {
+        char _hostname[256];
+        gethostname(_hostname, 256);
+        hostname = strdup(_hostname);
+        free_hostname = true;
+    }
+
+    SG_LOG(SG_GENERAL, SG_INFO, "Scanning command line for: " << option );
+
+    int len = option.length();
+
+    while ( i < argc ) {
+        SG_LOG( SG_GENERAL, SG_DEBUG, "argv[" << i << "] = " << argv[i] );
+
+        string arg = argv[i];
+        if ( arg.find( option ) == 0 ) {
+            return arg.substr( len );
+        }
+
+        i++;
+    }
+
+    return "";
 }
 
-int main( int argc, char *argv[] ) {
+// Scan the user config files for the specified option and return
+// the value.
+static string fgScanForOption( const string& option, const string& path ) {
+    sg_gzifstream in( path );
+    if ( !in.is_open() ) {
+        return "";
+    }
+
+    SG_LOG( SG_GENERAL, SG_INFO, "Scanning " << path << " for: " << option );
+
+    int len = option.length();
+
+    in >> skipcomment;
+#ifndef __MWERKS__
+    while ( ! in.eof() ) {
+#else
+    char c = '\0';
+    while ( in.get(c) && c != '\0' ) {
+        in.putback(c);
+#endif
+        string line;
+
+#if defined( macintosh )
+        getline( in, line, '\r' );
+#else
+        getline( in, line, '\n' );
+#endif
+
+        // catch extraneous (DOS) line ending character
+        if ( line[line.length() - 1] < 32 ) {
+            line = line.substr( 0, line.length()-1 );
+        }
 
-  bool usexml=true;
-  float deadband=0;
-  char answer[128];
-  int btninit=-2;
-
-  for (int i=1; i<argc; i++) {
-    if (strcmp("--help",argv[i])==0) {
-      cout << "Usage:" << endl;
-      cout << "  --help\t\t\tShow this help" << endl;
-      cout << "  --prop\t\t\tOutput property list" << endl;
-      cout << "  --xml\t\t\t\tOutput xml (default)" << endl;
-      cout << "  --deadband <float>\t\tSet deadband (for this program only, useful" << endl;
-      cout << "\t\t\t\tfor 'twitchy' joysticks)" << endl;
-      exit(0);
-    } else if (strcmp("--prop",argv[i])==0) {
-      usexml=false;
-      btninit=-1;
-    } else if (strcmp("--deadband",argv[i])==0) {
-      i++;
-      deadband=atoi(argv[i]);
-      cout << "Deadband set to " << argv[i] << endl;
-    } else if (strcmp("--xml",argv[i])!=0) {
-      cout << "Unknown option \"" << argv[i] << "\"" << endl;
-      exit(0);
+        if ( line.find( option ) == 0 ) {
+            return line.substr( len );
+        }
+
+        in >> skipcomment;
     }
-  }
-
-  jsInit();
-
-  jsSuper *jss=new jsSuper();
-  jsInput *jsi=new jsInput(jss);
-  jsi->displayValues(false);
-  int control=0;
-
-  cout << "Found " << jss->getNumJoysticks() << " joystick(s)" << endl;
-
-  if(jss->getNumJoysticks() <= 0) { 
-    cout << "Can't find any joysticks ..." << endl;
-    exit(1);
-  }
-
-  fstream fs;
-  fstream *xfs = new fstream[jss->getNumJoysticks()];
-  if (!usexml) {
-    fs.open("fgfsrc.js",ios::out);
-  }
-
-  jss->firstJoystick();
-  do {
-    cout << "Joystick #" << jss->getCurrentJoystickId()
-         << " \"" << jss->getJoystick()->getName() << "\" has "
-         << jss->getJoystick()->getNumAxes() << " axes" << endl;
-    for (int i=0; i<jss->getJoystick()->getNumAxes(); i++) {
-      jss->getJoystick()->setDeadBand(i,deadband);
+
+    return "";
+}
+
+// Scan the user config files for the specified option and return
+// the value.
+static string fgScanForOption( const string& option ) {
+    string arg("");
+
+#if defined( unix ) || defined( __CYGWIN__ )
+    // Next check home directory for .fgfsrc.hostname file
+    if ( arg.empty() ) {
+        if ( homedir != NULL ) {
+            SGPath config( homedir );
+            config.append( ".fgfsrc" );
+            config.concat( "." );
+            config.concat( hostname );
+            arg = fgScanForOption( option, config.str() );
+        }
     }
-    if (usexml) {
-      char filename[16];
-      snprintf(filename,16,"js%i.xml",jss->getCurrentJoystickId());
-      xfs[jss->getCurrentJoystickId()].open(filename,ios::out);
-      xfs[jss->getCurrentJoystickId()] << "<?xml version=\"1.0\" ?>" << endl
-      << endl << "<PropertyList>" << endl << endl << " <name>"
-      << jss->getJoystick()->getName() << "</name>" << endl << endl;
+#endif
+
+    // Next check home directory for .fgfsrc file
+    if ( arg.empty() ) {
+        if ( homedir != NULL ) {
+            SGPath config( homedir );
+            config.append( ".fgfsrc" );
+            arg = fgScanForOption( option, config.str() );
+        }
     }
-  } while( jss->nextJoystick() ); 
-
-  for(control=0;control<=7;control++) {
-      cout << "Move the control you wish to use for " << axes_humannames[control]
-           << " " << axis_posdir[control] << endl;
-      cout << "Pressing a button skips this axis\n";
-      fflush( stdout );
-      jsi->getInput();
-
-      if(jsi->getInputAxis() != -1) {
-         cout << endl << "Assigned axis " << jsi->getInputAxis()
-              << " on joystick " << jsi->getInputJoystick()
-              << " to control " << axes_humannames[control]
-              << endl;
-         bool badanswer=true;
-         do {
-           cout << "Is this correct? (y/n) $ ";
-           cin >> answer;
-           if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
-         } while (badanswer);
-         if (strcmp(answer,"n")==0) {
-           control--;
-         } else {
-          invert[control]=!jsi->getInputAxisPositive();
-           if (usexml) {
-             writeAxisXML( xfs[jsi->getInputJoystick()], control, jsi->getInputAxis() );
-           } else {
-             writeAxisProperties( fs, control, jsi->getInputJoystick(), jsi->getInputAxis() );
-           }
-         }
-      } else {
-         cout << "Skipping control" << endl;
-         bool badanswer=true;
-         do {
-           cout << "Is this correct? (y/n) $ ";
-           cin >> answer;
-           if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
-         } while (badanswer);
-         if (strcmp(answer,"n")==0) { control--; }
-      }
-      cout << endl;
-  }
-
-  for(control=btninit;control<=7;control++) {
-      if ( control == -2 ) {
-        cout << "Press the button you wish to use for View Cycle" << endl;
-      } else if ( control == -1 ) {
-        cout << "Press the button you wish to use for Brakes" << endl;
-      } else {
-        cout << "Press the button you wish to use for " << button_humannames[control] << endl;
-      }
-      cout << "Moving a joystick axis skips this button\n";
-      fflush( stdout );
-      jsi->getInput();
-      if(jsi->getInputButton() != -1) {
-         cout << endl << "Assigned button " << jsi->getInputButton()
-              << " on joystick " << jsi->getInputJoystick()
-              << " to control ";
-         if ( control == -2 ) { cout << "View Cycle" << endl; }
-         else if ( control == -1 ) { cout << "Brakes" << endl; }
-         else { cout << button_humannames[control] << endl; }
-         bool badanswer=true;
-         do {
-           cout << "Is this correct? (y/n) $ ";
-           cin >> answer;
-           if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
-         } while (badanswer);
-         if (strcmp(answer,"n")==0) {
-           control--;
-         } else {
-           if (usexml) {
-             writeButtonXML( xfs[jsi->getInputJoystick()], control, jsi->getInputButton() );
-           } else {
-             writeButtonProperties( fs, control, jsi->getInputJoystick(), jsi->getInputButton() );
-           }
-         }
-      } else {
-         cout << "Skipping control" << endl;
-         bool badanswer=true;
-         do {
-           cout << "Is this correct? (y/n) $ ";
-           cin >> answer;
-           if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
-         } while (badanswer);
-         if (strcmp(answer,"n")==0) { control--; }
-      }
-
-      cout << endl;
-  }
-  if (usexml) {
-    for (int i=0; i<jss->getNumJoysticks(); i++) {
-      xfs[i] << "</PropertyList>" << endl << endl << "<!-- end of joystick.xml -->" << endl;
-      xfs[i].close();
+
+    return arg;
+}
+
+// Read in configuration (files and command line options) but only set
+// fg_root
+string getFGRoot ( int argc, char **argv ) {
+    string root;
+
+    // First parse command line options looking for --fg-root=, this
+    // will override anything specified in a config file
+    root = fgScanForOption( "--fg-root=", argc, argv);
+
+    // Check in one of the user configuration files.
+    if (root.empty() )
+        root = fgScanForOption( "--fg-root=" );
+
+    // Next check if fg-root is set as an env variable
+    if ( root.empty() ) {
+        char *envp = ::getenv( "FG_ROOT" );
+        if ( envp != NULL ) {
+            root = envp;
+        }
     }
-  } else {
-    fs.close();
-  }
-  delete jsi;
-  delete[] xfs;
-  delete jss;
-
-  cout << "Your joystick settings are in ";
-  if (usexml) {
-    cout << "js0.xml, js1.xml, etc. depending on how many" << endl << "devices you have." << endl;
-  } else {
-    cout << "fgfsrc.js" << endl;
-  }
-  cout << endl << "Check and edit as desired. Once you are happy," << endl;
-  if (usexml) {
-    cout << "move relevant js<n>.xml files to $FG_ROOT/Input/Joysticks/ (if you didn't use" << endl
-         << "an attached controller, you don't need to move the corresponding file)" << endl;
-  } else {
-    cout << "append its contents to your .fgfsrc or system.fgfsrc" << endl;
-  }
 
-  return 1;
+    // Otherwise, default to a random compiled-in location if we can't
+    // find fg-root any other way.
+    if ( root.empty() ) {
+#if defined( __CYGWIN__ )
+        root = "/FlightGear";
+#elif defined( WIN32 )
+        root = "\\FlightGear";
+#elif defined(OSX_BUNDLE)
+        /* the following code looks for the base package directly inside
+            the application bundle. This can be changed fairly easily by
+            fiddling with the code below. And yes, I know it's ugly and verbose.
+        */
+        CFBundleRef appBundle = CFBundleGetMainBundle();
+        CFURLRef appUrl = CFBundleCopyBundleURL(appBundle);
+        CFRelease(appBundle);
+
+        // look for a 'data' subdir directly inside the bundle : is there
+        // a better place? maybe in Resources? I don't know ...
+        CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent(NULL, appUrl, CFSTR("data"), true);
+
+        // now convert down to a path, and the a c-string
+        CFStringRef path = CFURLCopyFileSystemPath(dataDir, kCFURLPOSIXPathStyle);
+        root = CFStringGetCStringPtr(path, CFStringGetSystemEncoding());
+
+        // tidy up.
+        CFRelease(appBundle);
+        CFRelease(dataDir);
+        CFRelease(path);
+#else
+        root = PKGLIBDIR;
+#endif
+    }
+
+    SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root );
+
+    return root;
 }
index 1b10ba106b4da182a25e4a23541094479c6c65d8..ac7e4669f969ae1a581416ec6b62c9363427117b 100644 (file)
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
+#include <simgear/compiler.h>
+
+#include STL_IOSTREAM
+
+SG_USING_STD(cout);
+SG_USING_STD(cin);
+SG_USING_STD(endl);
+
 #include "jsinput.h"
 
 jsInput::jsInput(jsSuper *j) {
-  jss=j;
-  pretty_display=true;
-  joystick=axis=button=-1;
-  axis_threshold=0.2;
+    jss=j;
+    pretty_display=true;
+    joystick=axis=button=-1;
+    axis_threshold=0.2;
 }
 
 jsInput::~jsInput(void) {}
 
-int jsInput::getInput(){
-      
-      bool gotit=false;
-      
-      float delta;
-      int i, current_button = 0, button_bits = 0;
+int jsInput::getInput() {
+
+    bool gotit=false;
+
+    float delta;
+    int i, current_button = 0, button_bits = 0;
 
-      joystick=axis=button=-1;
-      axis_positive=false;
-      
-      if(pretty_display) {
-          printf ( "+----------------------------------------------\n" ) ;
-          printf ( "| Btns " ) ;
+    joystick=axis=button=-1;
+    axis_positive=false;
 
-          for ( i = 0 ; i < jss->getJoystick()->getNumAxes() ; i++ )
-            printf ( "Ax:%1d ", i ) ;
+    if(pretty_display) {
+        printf ( "+----------------------------------------------\n" ) ;
+        printf ( "| Btns " ) ;
 
-          for ( ; i < 8 ; i++ )
+        for ( i = 0 ; i < jss->getJoystick()->getNumAxes() ; i++ )
+            printf ( "Ax:%3d ", i ) ;
+
+        for ( ; i < 8 ; i++ )
             printf ( "     " ) ;
 
-          printf ( "|\n" ) ;
+        printf ( "|\n" ) ;
+
+        printf ( "+----------------------------------------------\n" ) ;
+    }
 
-          printf ( "+----------------------------------------------\n" ) ;
-      }
-      
 
-      jss->firstJoystick();
-      do {
+    jss->firstJoystick();
+    do {
         jss->getJoystick()->read ( &button_iv[jss->getCurrentJoystickId()],
-                                       axes_iv[jss->getCurrentJoystickId()] ) ;
-      } while( jss->nextJoystick() );  
-      
-      
-      
-      while(!gotit) {
+                axes_iv[jss->getCurrentJoystickId()] ) ;
+    } while( jss->nextJoystick() );
+
+
+
+    while(!gotit) {
         jss->firstJoystick();
         do {
 
-          jss->getJoystick()->read ( &current_button, axes ) ;
-
-          if(pretty_display) printf ( "| %04x ", current_button ) ;
-
-               for ( i = 0 ; i < jss->getJoystick()->getNumAxes(); i++ ) {
-
-            delta = axes[i] - axes_iv[jss->getCurrentJoystickId()][i]; 
-            if(pretty_display) printf ( "%+.1f ", delta ) ; 
-            if(!gotit) {
-              if( fabs(delta) > axis_threshold ) {
-                gotit=true;
-                joystick=jss->getCurrentJoystickId();
-                axis=i;
-               axis_positive=(delta>0);
-              } else if( current_button != 0 ) {
-                gotit=true;
-                joystick=jss->getCurrentJoystickId();  
-                button_bits=current_button;
-              } 
-            }            
-          }
-               
-          if(pretty_display) {
-            for ( ; i < 8 ; i++ )
-                   printf ( "  .  " ) ;
-          }
-
-
-        } while( jss->nextJoystick() && !gotit); 
+            jss->getJoystick()->read ( &current_button, axes ) ;
+
+            if(pretty_display) printf ( "| %04x ", current_button ) ;
+
+            for ( i = 0 ; i < jss->getJoystick()->getNumAxes(); i++ ) {
+
+                delta = axes[i] - axes_iv[jss->getCurrentJoystickId()][i];
+                if(pretty_display) printf ( "%+.3f ", delta ) ;
+                if(!gotit) {
+                    if( fabs(delta) > axis_threshold ) {
+                        gotit=true;
+                        joystick=jss->getCurrentJoystickId();
+                        axis=i;
+                        axis_positive=(delta>0);
+                    } else if( current_button != 0 ) {
+                        gotit=true;
+                        joystick=jss->getCurrentJoystickId();
+                        button_bits=current_button;
+                    }
+                }
+            }
+
+            if(pretty_display) {
+                for ( ; i < 8 ; i++ )
+                    printf ( "  .  " ) ;
+            }
+
+
+        } while( jss->nextJoystick() && !gotit);
         if(pretty_display) {
-          printf ( "|\r" ) ;
-          fflush ( stdout ) ;
+            printf ( "|\r" ) ;
+            fflush ( stdout ) ;
         }
 
         ulMilliSecondSleep(1);
-      }
-      if(button_bits != 0) {
+    }
+    if(button_bits != 0) {
         for(int i=0;i<=31;i++) {
-          if( ( button_bits & (1 << i) ) > 0 ) {
-             button=i;
-             break;
-          } 
-        }    
-      } 
-
-      return 0;
+            if( ( button_bits & (1 << i) ) > 0 ) {
+                button=i;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+void jsInput::findDeadBand() {
+
+    float delta;
+    int i;
+    float dead_band[MAX_JOYSTICKS][_JS_MAX_AXES];
+
+    jss->firstJoystick();
+    do {
+        jss->getJoystick()->read ( NULL,
+                axes_iv[jss->getCurrentJoystickId()] ) ;
+        for ( i = 0; i <  jss->getJoystick()->getNumAxes(); i++ ) {
+            dead_band[jss->getCurrentJoystickId()][i] = 0;
+        }
+    } while( jss->nextJoystick() );
+
+    ulClock clock;
+    cout << 10;
+    cout.flush();
+
+    for (int j = 9; j >= 0; j--) {
+        double start_time = clock.getAbsTime();
+        do {
+            jss->firstJoystick();
+            do {
+
+                jss->getJoystick()->read ( NULL, axes ) ;
+
+                for ( i = 0 ; i < jss->getJoystick()->getNumAxes(); i++ ) {
+
+                    delta = axes[i] - axes_iv[jss->getCurrentJoystickId()][i];
+                    if (fabs(delta) > dead_band[jss->getCurrentJoystickId()][i])
+                        dead_band[jss->getCurrentJoystickId()][i] = delta;
+                }
+
+            } while( jss->nextJoystick());
+
+            ulMilliSecondSleep(1);
+            clock.update();
+        } while (clock.getAbsTime() - start_time < 1.0);
+
+        cout << " - " << j;
+        cout.flush();
+    }
+    cout << endl << endl;
+
+    jss->firstJoystick();
+    do {
+        for ( i = 0; i <  jss->getJoystick()->getNumAxes(); i++ ) {
+            jss->getJoystick()->setDeadBand(i, dead_band[jss->getCurrentJoystickId()][i]);
+            printf("Joystick %i, axis %i: %f\n", jss->getCurrentJoystickId(), i, dead_band[jss->getCurrentJoystickId()][i]);
+        }
+    } while( jss->nextJoystick() );
 }
-  
index 6da58d35a6910388db4453b181ce93785ab70e25..73346e030afd6d294ef5cf9cf3789298c93d9e2a 100644 (file)
@@ -32,29 +32,30 @@ class jsInput {
     float axes[_JS_MAX_AXES];
     float axes_iv[MAX_JOYSTICKS][_JS_MAX_AXES];
     int button_iv[MAX_JOYSTICKS];
-    
+
     int joystick,axis,button;
     bool axis_positive;
-    
+
     float axis_threshold;
-    
+
   public:
     jsInput(jsSuper *jss);
-    ~jsInput(void); 
-    
+    ~jsInput(void);
+
     inline void displayValues(bool bb) { pretty_display=bb; }
-    
+
     int getInput(void);
-    
+    void findDeadBand(void);
+
     inline int getInputJoystick(void) { return joystick; }
     inline int getInputAxis(void)     { return axis; }
     inline int getInputButton(void)   { return button; }
     inline bool getInputAxisPositive(void) { return axis_positive; }
-    
+
     inline float getReturnThreshold(void) { return axis_threshold; }
-    inline void setReturnThreshold(float ff) 
+    inline void setReturnThreshold(float ff)
               { if(fabs(ff) <= 1.0) axis_threshold=ff; }
-};    
+};
 
 
 #endif