// 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 #include #include #include #include #include
#include // subsystem includes #include #include #include
#include
#include #include #include #include #include #include #include #include #include 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 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 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 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