]> git.mxchange.org Git - flightgear.git/blob - src/Main/subsystemFactory.cxx
ATIS upgrade
[flightgear.git] / src / Main / subsystemFactory.cxx
1 // subsystemFactory.cxx - factory for subsystems
2 //
3 // Copyright (C) 2012 James Turner  zakalawe@mac.com
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
19 #ifdef HAVE_CONFIG_H
20     #include "config.h"
21 #endif
22
23 #include "subsystemFactory.hxx"
24
25 #include <simgear/structure/subsystem_mgr.hxx>
26 #include <simgear/structure/exception.hxx>
27 #include <simgear/debug/logstream.hxx>
28 #include <simgear/structure/commands.hxx>
29 #include <simgear/structure/event_mgr.hxx>
30
31 #include <Main/globals.hxx>
32 #include <Sound/soundmanager.hxx>
33
34 // subsystem includes
35 #include <Aircraft/controls.hxx>
36 #include <simgear/misc/interpolator.hxx>
37 #include <Main/fg_props.hxx>
38 #include <Main/fg_io.hxx>
39 #include <FDM/fdm_shell.hxx>
40 #include <Environment/environment_mgr.hxx>
41 #include <Environment/ephemeris.hxx>
42 #include <Instrumentation/instrument_mgr.hxx>
43 #include <Instrumentation/HUD/HUD.hxx>
44 #include <Systems/system_mgr.hxx>
45 #include <Autopilot/route_mgr.hxx>
46 #include <Autopilot/autopilotgroup.hxx>
47 #include <Traffic/TrafficMgr.hxx>
48
49 using std::vector;
50
51 namespace flightgear
52 {
53   
54 SGSubsystem* createSubsystemByName(const std::string& name)
55 {
56 #define MAKE_SUB(cl, n) \
57     if (name == n) return new cl;
58     
59     MAKE_SUB(FGControls, "controls");  
60     MAKE_SUB(FGSoundManager, "sound");
61     MAKE_SUB(SGInterpolator, "interpolator");
62     MAKE_SUB(FGProperties, "properties");
63     MAKE_SUB(FDMShell, "fdm");
64     MAKE_SUB(FGEnvironmentMgr, "environment");
65     MAKE_SUB(Ephemeris, "ephemeris");
66     MAKE_SUB(FGSystemMgr, "aircraft-systems");
67     MAKE_SUB(FGInstrumentMgr, "instruments");
68     MAKE_SUB(HUD, "hud");
69     MAKE_SUB(FGIO, "io");
70     MAKE_SUB(FGRouteMgr, "route-manager");
71   
72     MAKE_SUB(FGTrafficManager, "traffic-manager");
73   
74 #undef MAKE_SUB
75     
76     throw sg_range_exception("unknown subsystem:" + name);
77 }
78
79 SGSubsystemMgr::GroupType mapGroupNameToType(const std::string& s)
80 {
81     if (s == "init")        return SGSubsystemMgr::INIT;
82     if (s == "general")     return SGSubsystemMgr::GENERAL;
83     if (s == "fdm")         return SGSubsystemMgr::FDM;
84     if (s == "post-fdm")    return SGSubsystemMgr::POST_FDM;
85     if (s == "display")     return SGSubsystemMgr::DISPLAY;
86     if (s == "sound")       return SGSubsystemMgr::SOUND;
87     
88     SG_LOG(SG_GENERAL, SG_ALERT, "unrecognized subsystem group:" << s);
89     return SGSubsystemMgr::GENERAL;
90 }
91
92 static bool
93 do_add_subsystem (const SGPropertyNode * arg)
94 {
95     std::string subsystem(arg->getStringValue("subsystem"));
96     std::string name = arg->getStringValue("name");
97     if (subsystem.empty() || name.empty()) {
98         SG_LOG(SG_GENERAL, SG_ALERT, "do_add_subsystem:" 
99             << "no subsystem/name supplied");
100         return false;
101     }
102     
103     if (globals->get_subsystem_mgr()->get_subsystem(name)) {
104         SG_LOG(SG_GENERAL, SG_ALERT, "do_add_subsystem:" 
105             << "duplicate subsystem name:" << name);
106       return false;
107     }
108     
109     std::string groupname = arg->getStringValue("group");
110     SGSubsystemMgr::GroupType group = SGSubsystemMgr::GENERAL;
111     if (!groupname.empty()) {
112         group = mapGroupNameToType(groupname);
113     }
114     
115     SGSubsystem* instance = NULL;
116     try {
117         instance = createSubsystemByName(subsystem);
118     } catch (sg_exception& e) {
119         SG_LOG(SG_GENERAL, SG_ALERT, "subsystem creation failed:" <<
120             name << ":" << e.getFormattedMessage());
121         return false;
122     }
123     
124     bool doInit = arg->getBoolValue("do-bind-init", false);
125     if (doInit) {
126         instance->bind();
127         instance->init();
128     }
129     
130     double minTime = arg->getDoubleValue("min-time-sec", 0.0);
131     globals->get_subsystem_mgr()->add(name.c_str(), instance,
132         group, minTime);
133     
134     return true;
135 }
136
137 static bool do_remove_subsystem(const SGPropertyNode * arg)
138 {
139   std::string name = arg->getStringValue("subsystem");
140   
141   SGSubsystem* instance = globals->get_subsystem_mgr()->get_subsystem(name);
142   if (!instance) {
143     SG_LOG(SG_GENERAL, SG_ALERT, "do_remove_subsystem: unknown subsytem:" << name);
144     return false;
145   }
146   
147   // is it safe to always call these? let's assume so!
148   instance->shutdown();
149   instance->unbind();
150
151   // unplug from the manager
152   globals->get_subsystem_mgr()->remove(name.c_str());
153   
154   // and finally kill off the instance.
155   delete instance;
156   
157   return true;
158 }
159   
160 /**
161  * Built-in command: reinitialize one or more subsystems.
162  *
163  * subsystem[*]: the name(s) of the subsystem(s) to reinitialize; if
164  * none is specified, reinitialize all of them.
165  */
166 static bool
167 do_reinit (const SGPropertyNode * arg)
168 {
169     bool result = true;
170
171     vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
172     if (subsystems.size() == 0) {
173         globals->get_subsystem_mgr()->reinit();
174     } else {
175         for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
176             const char * name = subsystems[i]->getStringValue();
177             SGSubsystem * subsystem = globals->get_subsystem(name);
178             if (subsystem == 0) {
179                 result = false;
180                 SG_LOG( SG_GENERAL, SG_ALERT,
181                         "Subsystem " << name << " not found" );
182             } else {
183                 subsystem->reinit();
184             }
185         }
186     }
187
188     globals->get_event_mgr()->reinit();
189
190     return result;
191 }
192
193 /**
194  * Built-in command: suspend one or more subsystems.
195  *
196  * subsystem[*] - the name(s) of the subsystem(s) to suspend.
197  */
198 static bool
199 do_suspend (const SGPropertyNode * arg)
200 {
201     bool result = true;
202
203     vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
204     for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
205         const char * name = subsystems[i]->getStringValue();
206         SGSubsystem * subsystem = globals->get_subsystem(name);
207         if (subsystem == 0) {
208             result = false;
209             SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
210         } else {
211             subsystem->suspend();
212         }
213     }
214     return result;
215 }
216
217 /**
218  * Built-in command: suspend one or more subsystems.
219  *
220  * subsystem[*] - the name(s) of the subsystem(s) to suspend.
221  */
222 static bool
223 do_resume (const SGPropertyNode * arg)
224 {
225     bool result = true;
226
227     vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
228     for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
229         const char * name = subsystems[i]->getStringValue();
230         SGSubsystem * subsystem = globals->get_subsystem(name);
231         if (subsystem == 0) {
232             result = false;
233             SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
234         } else {
235             subsystem->resume();
236         }
237     }
238     return result;
239 }
240
241 static struct {
242   const char * name;
243   SGCommandMgr::command_t command;
244 } built_ins [] = {
245     { "add-subsystem", do_add_subsystem },
246     { "remove-subsystem", do_remove_subsystem },
247     { "reinit", do_reinit },
248     { "suspend", do_suspend },
249     { "resume", do_resume },
250     { 0, 0 }                    // zero-terminated
251 };
252
253 void registerSubsystemCommands(SGCommandMgr* cmdMgr)
254 {
255     for (int i = 0; built_ins[i].name != 0; i++) {
256       cmdMgr->addCommand(built_ins[i].name, built_ins[i].command);
257     }
258 }
259
260 } // of namepace flightgear