-void writeAxisProperties(fstream &fs, int control,int joystick, int axis) {
-
- char jsDesc[25];
- snprintf(jsDesc,25,"--prop:/input/js%d/axis%d",joystick,axis);
- fs << jsDesc << "/control=" << axes_propnames[control] << endl;
-
- fs << jsDesc << "/dead-band=0.02" << endl;
-
- if( half_range[control] == true) {
- fs << jsDesc << "/offset=-1.0" << endl;
- fs << jsDesc << "/factor=0.5" << endl;
- } else {
- fs << jsDesc << "/offset=0.0" << endl;
- fs << jsDesc << "/factor=1.0" << endl;
- }
- fs << endl;
-}
-
-void writeButtonProperties(fstream &fs, int property,int joystick, int button) {
-
- char jsDesc[25];
- snprintf(jsDesc,25,"--prop:/input/js%d/button%d",joystick,button);
-
- fs << jsDesc << "/action=adjust" << endl;
- fs << jsDesc << "/control=" << button_propnames[property] << endl;
- fs << jsDesc << "/step=" << button_step[property] << endl;
- fs << jsDesc << "/repeatable=" << button_repeat[property] << endl;
- fs << endl;
-}
-
-
-
-
-int main(void) {
- jsSuper *jss=new jsSuper();
- jsInput *jsi=new jsInput(jss);
- jsi->displayValues(false);
- int i;
- int control=0;
-
-
- cout << "Found " << jss->getNumJoysticks() << " joystick(s)" << endl;
-
- if(jss->getNumJoysticks() <= 0) {
- cout << "Can't find any joysticks ..." << endl;
- exit(1);
- }
-
- jss->firstJoystick();
- do {
- cout << "Joystick " << jss->getCurrentJoystickId() << " has "
- << jss->getJoystick()->getNumAxes() << " axes" << endl;
- } while( jss->nextJoystick() );
-
- fstream fs("fgfsrc.js",ios::out);
-
-
- for(control=0;control<=7;control++) {
- cout << "Move the control you wish to use for " << axes_humannames[control]
- << endl;
- fflush( stdout );
- jsi->getInput();
-
- if(jsi->getInputAxis() != -1) {
- cout << endl << "Assigned axis " << jsi->getInputAxis()
- << " on joystick " << jsi->getInputJoystick()
- << " to control " << axes_humannames[control]
- << endl;
-
- writeAxisProperties( fs, control, jsi->getInputJoystick(),
- jsi->getInputAxis() );
- } else {
- cout << "Skipping Axis" << endl;
- }
-
- cout << "Press any button for next control" << endl;
-
- waitForButton(jss,500);
- cout << endl;
- }
-
- for(control=0;control<=6;control++) {
- cout << "Press the button you wish to use to "
- << button_humannames[control]
- << endl;
- fflush( stdout );
- jsi->getInput();
- if(jsi->getInputButton() != -1) {
-
- cout << endl << "Assigned button " << jsi->getInputButton()
- << " on joystick " << jsi->getInputJoystick()
- << " to control " << button_humannames[control]
- << endl;
-
- writeButtonProperties( fs, control, jsi->getInputJoystick(),
- jsi->getInputButton() );
- } else {
- cout << "Skipping..." << endl;
- }
-
- cout << "Press any button for next axis" << endl;
-
- waitForButton(jss,500);
- cout << endl;
- }
-
-
- delete jsi;
- delete jss;
-
- cout << "Your joystick settings are in the file fgfsrc.js" << endl;
- cout << "Check and edit as desired (especially important if you are"
- << " using a hat switch" << endl;
- cout << "as this program will, most likely, not get those right). ";
-
- cout << "Once you are happy, " << endl
- << "append its contents to your .fgfsrc or system.fgfsrc" << endl;
-
- return 1;
-}
-
+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 if (strncmp("--fg-root=", argv[i], 10) == 0) {
+ // used later
+ } 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 ();
+ }
+
+ PropertyList axes = templatetree->getChildren("axis");
+ for(PropertyList::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;
+ }
+
+ PropertyList buttons = templatetree->getChildren("button");
+ for(PropertyList::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;
+ delete[] jstree;
+
+ return 1;
+}
+
+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_INPUT, SG_INFO, "Scanning command line for: " << option );