]> git.mxchange.org Git - flightgear.git/commitdiff
Initial work on dynamic subsystem creation.
authorJames Turner <zakalawe@mac.com>
Sun, 30 Sep 2012 15:34:51 +0000 (16:34 +0100)
committerJames Turner <zakalawe@mac.com>
Sun, 30 Sep 2012 15:34:51 +0000 (16:34 +0100)
Make subsystems create-able and removable from commands. Only some subsystems are supported so far, since many have non-default constructors or other complexities.

With this, change, it's possible to dynamically add and remove the traffic-manager at runtime, for example: fgcommand("add-subsystem", props.Node.new({ "subsystem": "traffic-manager", "name":"traffic-manager", "do-bind-init":1}));

src/Main/CMakeLists.txt
src/Main/fg_commands.cxx
src/Main/main.cxx
src/Main/subsystemFactory.cxx [new file with mode: 0644]
src/Main/subsystemFactory.hxx [new file with mode: 0644]

index 8a8769cd3f9b0a55897d2cbd0ec153d70295852d..507c7beb578915ea5c8b27504eddafa617b97d42 100644 (file)
@@ -21,6 +21,7 @@ set(SOURCES
        options.cxx
        util.cxx
     positioninit.cxx
+    subsystemFactory.cxx
        ${RESOURCE_FILE}
        )
 
@@ -36,6 +37,7 @@ set(HEADERS
        options.hxx
        util.hxx
     positioninit.hxx
+    subsystemFactory.hxx
        )
 
 get_property(FG_SOURCES GLOBAL PROPERTY FG_SOURCES)
index 5611cbf10c471f0e548348da1bee9d280f5b19d5..92bdea7c041c1dc65b6d31f3c4b0e778d48b8423 100644 (file)
@@ -206,95 +206,6 @@ do_reset (const SGPropertyNode * arg)
     return true;
 }
 
-
-/**
- * Built-in command: reinitialize one or more subsystems.
- *
- * subsystem[*]: the name(s) of the subsystem(s) to reinitialize; if
- * none is specified, reinitialize all of them.
- */
-static bool
-do_reinit (const SGPropertyNode * arg)
-{
-    bool result = true;
-
-    vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
-    if (subsystems.size() == 0) {
-        globals->get_subsystem_mgr()->reinit();
-    } else {
-        for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
-            const char * name = subsystems[i]->getStringValue();
-            SGSubsystem * subsystem = globals->get_subsystem(name);
-            if (subsystem == 0) {
-                result = false;
-                SG_LOG( SG_GENERAL, SG_ALERT,
-                        "Subsystem " << name << " not found" );
-            } else {
-                subsystem->reinit();
-            }
-        }
-    }
-
-    globals->get_event_mgr()->reinit();
-
-    return result;
-}
-
-#if 0
-  //
-  // these routines look useful ??? but are never used in the code ???
-  //
-
-/**
- * Built-in command: suspend one or more subsystems.
- *
- * subsystem[*] - the name(s) of the subsystem(s) to suspend.
- */
-static bool
-do_suspend (const SGPropertyNode * arg)
-{
-    bool result = true;
-
-    vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
-    for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
-        const char * name = subsystems[i]->getStringValue();
-        SGSubsystem * subsystem = globals->get_subsystem(name);
-        if (subsystem == 0) {
-            result = false;
-            SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
-        } else {
-            subsystem->suspend();
-        }
-    }
-    return result;
-}
-
-/**
- * Built-in command: suspend one or more subsystems.
- *
- * subsystem[*] - the name(s) of the subsystem(s) to suspend.
- */
-static bool
-do_resume (const SGPropertyNode * arg)
-{
-    bool result = true;
-
-    vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
-    for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
-        const char * name = subsystems[i]->getStringValue();
-        SGSubsystem * subsystem = globals->get_subsystem(name);
-        if (subsystem == 0) {
-            result = false;
-            SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
-        } else {
-            subsystem->resume();
-        }
-    }
-    return result;
-}
-
-#endif
-
 /**
  * Built-in command: replay the FDR buffer
  */
@@ -1526,9 +1437,6 @@ static struct {
     { "nasal", do_nasal },
     { "exit", do_exit },
     { "reset", do_reset },
-    { "reinit", do_reinit },
-    { "suspend", do_reinit },
-    { "resume", do_reinit },
     { "pause", do_pause },
     { "load", do_load },
     { "save", do_save },
index 8bbb456484a55e425a53f01d23e0f6cc77abd3f3..c7d2a0db2ef15d32ab494347aead947bb6075401 100644 (file)
@@ -62,6 +62,7 @@
 #include "fg_os.hxx"
 #include "fg_props.hxx"
 #include "positioninit.hxx"
+#include "subsystemFactory.hxx"
 
 using namespace flightgear;
 
@@ -156,6 +157,8 @@ static void fgIdleFunction ( void ) {
         ////////////////////////////////////////////////////////////////////
         fgInitCommands();
 
+        flightgear::registerSubsystemCommands(globals->get_commands());
+
         ////////////////////////////////////////////////////////////////////
         // Initialize the material manager
         ////////////////////////////////////////////////////////////////////
diff --git a/src/Main/subsystemFactory.cxx b/src/Main/subsystemFactory.cxx
new file mode 100644 (file)
index 0000000..3e63779
--- /dev/null
@@ -0,0 +1,260 @@
+// subsystemFactory.cxx - factory for subsystems
+//
+// Copyright (C) 2012 James Turner  zakalawe@mac.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+    #include "config.h"
+#endif
+
+#include "subsystemFactory.hxx"
+
+#include <simgear/structure/subsystem_mgr.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/commands.hxx>
+#include <simgear/structure/event_mgr.hxx>
+
+#include <Main/globals.hxx>
+#include <Sound/soundmanager.hxx>
+
+// subsystem includes
+#include <Aircraft/controls.hxx>
+#include <simgear/misc/interpolator.hxx>
+#include <Main/fg_props.hxx>
+#include <Main/fg_io.hxx>
+#include <FDM/fdm_shell.hxx>
+#include <Environment/environment_mgr.hxx>
+#include <Environment/ephemeris.hxx>
+#include <Instrumentation/instrument_mgr.hxx>
+#include <Instrumentation/HUD/HUD.hxx>
+#include <Systems/system_mgr.hxx>
+#include <Autopilot/route_mgr.hxx>
+#include <Autopilot/autopilotgroup.hxx>
+#include <Traffic/TrafficMgr.hxx>
+
+using std::vector;
+
+namespace flightgear
+{
+  
+SGSubsystem* createSubsystemByName(const std::string& name)
+{
+#define MAKE_SUB(cl, n) \
+    if (name == n) return new cl;
+    
+    MAKE_SUB(FGControls, "controls");  
+    MAKE_SUB(FGSoundManager, "sound");
+    MAKE_SUB(SGInterpolator, "interpolator");
+    MAKE_SUB(FGProperties, "properties");
+    MAKE_SUB(FDMShell, "fdm");
+    MAKE_SUB(FGEnvironmentMgr, "environment");
+    MAKE_SUB(Ephemeris, "ephemeris");
+    MAKE_SUB(FGSystemMgr, "aircraft-systems");
+    MAKE_SUB(FGInstrumentMgr, "instruments");
+    MAKE_SUB(HUD, "hud");
+    MAKE_SUB(FGIO, "io");
+    MAKE_SUB(FGRouteMgr, "route-manager");
+  
+    MAKE_SUB(FGTrafficManager, "traffic-manager");
+  
+#undef MAKE_SUB
+    
+    throw sg_range_exception("unknown subsystem:" + name);
+}
+
+SGSubsystemMgr::GroupType mapGroupNameToType(const std::string& s)
+{
+    if (s == "init")        return SGSubsystemMgr::INIT;
+    if (s == "general")     return SGSubsystemMgr::GENERAL;
+    if (s == "fdm")         return SGSubsystemMgr::FDM;
+    if (s == "post-fdm")    return SGSubsystemMgr::POST_FDM;
+    if (s == "display")     return SGSubsystemMgr::DISPLAY;
+    if (s == "sound")       return SGSubsystemMgr::SOUND;
+    
+    SG_LOG(SG_GENERAL, SG_ALERT, "unrecognized subsystem group:" << s);
+    return SGSubsystemMgr::GENERAL;
+}
+
+static bool
+do_add_subsystem (const SGPropertyNode * arg)
+{
+    std::string subsystem(arg->getStringValue("subsystem"));
+    std::string name = arg->getStringValue("name");
+    if (subsystem.empty() || name.empty()) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "do_add_subsystem:" 
+            << "no subsystem/name supplied");
+        return false;
+    }
+    
+    if (globals->get_subsystem_mgr()->get_subsystem(name)) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "do_add_subsystem:" 
+            << "duplicate subsystem name:" << name);
+      return false;
+    }
+    
+    std::string groupname = arg->getStringValue("group");
+    SGSubsystemMgr::GroupType group = SGSubsystemMgr::GENERAL;
+    if (!groupname.empty()) {
+        group = mapGroupNameToType(groupname);
+    }
+    
+    SGSubsystem* instance = NULL;
+    try {
+        instance = createSubsystemByName(subsystem);
+    } catch (sg_exception& e) {
+        SG_LOG(SG_GENERAL, SG_ALERT, "subsystem creation failed:" <<
+            name << ":" << e.getFormattedMessage());
+        return false;
+    }
+    
+    bool doInit = arg->getBoolValue("do-bind-init", false);
+    if (doInit) {
+        instance->bind();
+        instance->init();
+    }
+    
+    double minTime = arg->getDoubleValue("min-time-sec", 0.0);
+    globals->get_subsystem_mgr()->add(name.c_str(), instance,
+        group, minTime);
+    
+    return true;
+}
+
+static bool do_remove_subsystem(const SGPropertyNode * arg)
+{
+  std::string name = arg->getStringValue("subsystem");
+  
+  SGSubsystem* instance = globals->get_subsystem_mgr()->get_subsystem(name);
+  if (!instance) {
+    SG_LOG(SG_GENERAL, SG_ALERT, "do_remove_subsystem: unknown subsytem:" << name);
+    return false;
+  }
+  
+  // is it safe to always call these? let's assume so!
+  instance->shutdown();
+  instance->unbind();
+
+  // unplug from the manager
+  globals->get_subsystem_mgr()->remove(name.c_str());
+  
+  // and finally kill off the instance.
+  delete instance;
+  
+  return true;
+}
+  
+/**
+ * Built-in command: reinitialize one or more subsystems.
+ *
+ * subsystem[*]: the name(s) of the subsystem(s) to reinitialize; if
+ * none is specified, reinitialize all of them.
+ */
+static bool
+do_reinit (const SGPropertyNode * arg)
+{
+    bool result = true;
+
+    vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
+    if (subsystems.size() == 0) {
+        globals->get_subsystem_mgr()->reinit();
+    } else {
+        for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
+            const char * name = subsystems[i]->getStringValue();
+            SGSubsystem * subsystem = globals->get_subsystem(name);
+            if (subsystem == 0) {
+                result = false;
+                SG_LOG( SG_GENERAL, SG_ALERT,
+                        "Subsystem " << name << " not found" );
+            } else {
+                subsystem->reinit();
+            }
+        }
+    }
+
+    globals->get_event_mgr()->reinit();
+
+    return result;
+}
+
+/**
+ * Built-in command: suspend one or more subsystems.
+ *
+ * subsystem[*] - the name(s) of the subsystem(s) to suspend.
+ */
+static bool
+do_suspend (const SGPropertyNode * arg)
+{
+    bool result = true;
+
+    vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
+    for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
+        const char * name = subsystems[i]->getStringValue();
+        SGSubsystem * subsystem = globals->get_subsystem(name);
+        if (subsystem == 0) {
+            result = false;
+            SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
+        } else {
+            subsystem->suspend();
+        }
+    }
+    return result;
+}
+
+/**
+ * Built-in command: suspend one or more subsystems.
+ *
+ * subsystem[*] - the name(s) of the subsystem(s) to suspend.
+ */
+static bool
+do_resume (const SGPropertyNode * arg)
+{
+    bool result = true;
+
+    vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
+    for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
+        const char * name = subsystems[i]->getStringValue();
+        SGSubsystem * subsystem = globals->get_subsystem(name);
+        if (subsystem == 0) {
+            result = false;
+            SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
+        } else {
+            subsystem->resume();
+        }
+    }
+    return result;
+}
+
+static struct {
+  const char * name;
+  SGCommandMgr::command_t command;
+} built_ins [] = {
+    { "add-subsystem", do_add_subsystem },
+    { "remove-subsystem", do_remove_subsystem },
+    { "reinit", do_reinit },
+    { "suspend", do_suspend },
+    { "resume", do_resume },
+    { 0, 0 }                   // zero-terminated
+};
+
+void registerSubsystemCommands(SGCommandMgr* cmdMgr)
+{
+    for (int i = 0; built_ins[i].name != 0; i++) {
+      cmdMgr->addCommand(built_ins[i].name, built_ins[i].command);
+    }
+}
+
+} // of namepace flightgear
diff --git a/src/Main/subsystemFactory.hxx b/src/Main/subsystemFactory.hxx
new file mode 100644 (file)
index 0000000..cba14ab
--- /dev/null
@@ -0,0 +1,44 @@
+// subsystemFactory.hxx - factory for subsystems
+//
+// Copyright (C) 2012 James Turner  zakalawe@mac.com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+
+#ifndef FG_SUBSYSTEM_FACTORY_HXX
+#define FG_SUBSYSTEM_FACTORY_HXX
+
+#include <string>
+
+// forward decls
+class SGCommandMgr;
+class SGSubsystem;
+
+namespace flightgear
+{
+
+/**
+ * create a subsystem by name, and return it.
+ * Will throw an exception if the subsytem name is invalid, or
+ * if the subsytem could not be created for some other reason.
+ * ownership of the subsystem passes to the caller
+ */    
+SGSubsystem* createSubsystemByName(const std::string& name);
+
+void registerSubsystemCommands(SGCommandMgr* cmdMgr);
+
+} // of namespace flightgear
+
+#endif // of FG_POSITION_INIT_HXX