]> git.mxchange.org Git - flightgear.git/blob - src/Main/subsystemFactory.cxx
Document that property write-protection is not a security measure
[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 <Aircraft/FlightHistory.hxx>
37 #include <Main/fg_props.hxx>
38 #include <Main/FGInterpolator.hxx>
39 #include <Main/fg_io.hxx>
40 #include <FDM/fdm_shell.hxx>
41 #include <Environment/environment_mgr.hxx>
42 #include <Environment/ephemeris.hxx>
43 #include <Instrumentation/instrument_mgr.hxx>
44 #include <Instrumentation/HUD/HUD.hxx>
45 #include <Systems/system_mgr.hxx>
46 #include <Autopilot/route_mgr.hxx>
47 #include <Autopilot/autopilotgroup.hxx>
48 #include <Traffic/TrafficMgr.hxx>
49 #include <Network/fgcom.hxx>
50 #include <Network/HTTPClient.hxx>
51 #include <Cockpit/cockpitDisplayManager.hxx>
52 #include <GUI/new_gui.hxx>
53 #include <Main/logger.hxx>
54 #include <ATC/atc_mgr.hxx>
55 #include <AIModel/AIManager.hxx>
56 #include <MultiPlayer/multiplaymgr.hxx>
57 #include <AIModel/submodel.hxx>
58 #include <Aircraft/controls.hxx>
59 #include <Input/input.hxx>
60 #include <Aircraft/replay.hxx>
61 #include <Sound/voice.hxx>
62 #include <Canvas/canvas_mgr.hxx>
63 #include <Canvas/gui_mgr.hxx>
64 #include <Time/light.hxx>
65 #include <Viewer/viewmgr.hxx>
66 #include <Model/acmodel.hxx>
67 #include <Model/modelmgr.hxx>
68
69 using std::vector;
70
71 namespace flightgear
72 {
73   
74 SGSubsystem* createSubsystemByName(const std::string& name)
75 {
76 #define MAKE_SUB(cl, n) \
77     if (name == n) return new cl;
78
79     MAKE_SUB(FGSoundManager, "sound");
80     MAKE_SUB(FGInterpolator, "prop-interpolator")
81     MAKE_SUB(FGProperties, "properties");
82     MAKE_SUB(FGHTTPClient, "http");
83     MAKE_SUB(FDMShell, "flight");
84     MAKE_SUB(FGEnvironmentMgr, "environment");
85     MAKE_SUB(Ephemeris, "ephemeris");
86     MAKE_SUB(FGSystemMgr, "systems");
87     MAKE_SUB(FGInstrumentMgr, "instrumentation");
88     MAKE_SUB(HUD, "hud");
89     MAKE_SUB(flightgear::CockpitDisplayManager, "cockpit-displays");
90     MAKE_SUB(FGRouteMgr, "route-manager");
91     MAKE_SUB(FGIO, "io");
92     MAKE_SUB(FGLogger, "logger");
93     MAKE_SUB(NewGUI, "gui");
94     MAKE_SUB(CanvasMgr, "Canvas");
95     MAKE_SUB(GUIMgr, "CanvasGUI");
96     MAKE_SUB(FGATCManager, "ATC");
97     MAKE_SUB(FGMultiplayMgr, "mp");
98     MAKE_SUB(FGAIManager, "ai-model");
99     MAKE_SUB(FGSubmodelMgr, "submodel-mgr");
100     MAKE_SUB(FGTrafficManager, "traffic-manager");
101     MAKE_SUB(FGControls, "controls");
102     MAKE_SUB(FGInput, "input");
103     MAKE_SUB(FGReplay, "replay");
104     MAKE_SUB(FGFlightHistory, "history");
105 #ifdef ENABLE_AUDIO_SUPPORT
106     MAKE_SUB(FGVoiceMgr, "voice");
107 #endif
108 #ifdef ENABLE_IAX
109     MAKE_SUB(FGCom, "fgcom");
110 #endif
111     MAKE_SUB(FGLight, "lighting");
112     MAKE_SUB(FGAircraftModel, "aircraft-model");
113     MAKE_SUB(FGModelMgr, "model-manager");
114     MAKE_SUB(FGViewMgr, "view-manager");
115 #undef MAKE_SUB
116
117     throw sg_range_exception("unknown subsystem:" + name);
118 }
119
120 SGSubsystemMgr::GroupType mapGroupNameToType(const std::string& s)
121 {
122     if (s == "init")        return SGSubsystemMgr::INIT;
123     if (s == "general")     return SGSubsystemMgr::GENERAL;
124     if (s == "fdm")         return SGSubsystemMgr::FDM;
125     if (s == "post-fdm")    return SGSubsystemMgr::POST_FDM;
126     if (s == "display")     return SGSubsystemMgr::DISPLAY;
127     if (s == "sound")       return SGSubsystemMgr::SOUND;
128     
129     SG_LOG(SG_GENERAL, SG_ALERT, "unrecognized subsystem group:" << s);
130     return SGSubsystemMgr::GENERAL;
131 }
132
133 static SGSubsystem* getSubsystem(const SGPropertyNode* arg, bool create)
134 {
135   std::string subsystem(arg->getStringValue("subsystem"));
136   std::string name = arg->getStringValue("name");
137
138   if (name.empty()) {
139     // default name is simply the subsytem's name
140     name = subsystem;
141   }
142
143   SGSubsystem* sys = globals->get_subsystem_mgr()->get_subsystem(name);
144   if (!create)
145     return sys;
146
147   if( subsystem.empty() ) {
148     SG_LOG( SG_GENERAL,
149             SG_ALERT,
150             "do_add_subsystem: no subsystem/name supplied" );
151     return 0;
152   }
153
154   if (sys) {
155     SG_LOG( SG_GENERAL,
156             SG_ALERT,
157             "do_add_subsystem: duplicate subsystem name:" << name );
158     return 0;
159   }
160
161   std::string groupname = arg->getStringValue("group");
162   SGSubsystemMgr::GroupType group = SGSubsystemMgr::GENERAL;
163   if (!groupname.empty()) {
164     group = mapGroupNameToType(groupname);
165   }
166
167   try {
168     sys = createSubsystemByName(subsystem);
169   } catch (sg_exception& e) {
170     SG_LOG( SG_GENERAL,
171             SG_ALERT,
172             "subsystem creation failed:" << name
173                                   << ":" << e.getFormattedMessage() );
174     return 0;
175   }
176
177   bool doInit = arg->getBoolValue("do-bind-init", false);
178   if (doInit) {
179     sys->bind();
180     sys->init();
181   }
182
183   double minTime = arg->getDoubleValue("min-time-sec", 0.0);
184   globals->get_subsystem_mgr()
185          ->add(name.c_str(), sys, group, minTime);
186
187   return sys;
188 }
189
190 static bool
191 do_check_subsystem_running(const SGPropertyNode* arg)
192 {
193   return getSubsystem(arg, false) != 0;
194 }
195
196 static bool
197 do_add_subsystem (const SGPropertyNode * arg)
198 {
199   return getSubsystem(arg, true) != 0;
200 }
201
202 static bool do_remove_subsystem(const SGPropertyNode * arg)
203 {
204   std::string name = arg->getStringValue("subsystem");
205   
206   SGSubsystem* instance = globals->get_subsystem_mgr()->get_subsystem(name);
207   if (!instance) {
208     SG_LOG(SG_GENERAL, SG_ALERT, "do_remove_subsystem: unknown subsytem:" << name);
209     return false;
210   }
211   
212   // is it safe to always call these? let's assume so!
213   instance->shutdown();
214   instance->unbind();
215
216   // unplug from the manager
217   globals->get_subsystem_mgr()->remove(name.c_str());
218   
219   // and finally kill off the instance.
220   delete instance;
221   
222   return true;
223 }
224   
225 /**
226  * Built-in command: reinitialize one or more subsystems.
227  *
228  * subsystem[*]: the name(s) of the subsystem(s) to reinitialize; if
229  * none is specified, reinitialize all of them.
230  */
231 static bool
232 do_reinit (const SGPropertyNode * arg)
233 {
234     bool result = true;
235
236     vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
237     if (subsystems.empty()) {
238         globals->get_subsystem_mgr()->reinit();
239     } else {
240         for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
241             const char * name = subsystems[i]->getStringValue();
242             SGSubsystem * subsystem = globals->get_subsystem(name);
243             if (subsystem == 0) {
244                 result = false;
245                 SG_LOG( SG_GENERAL, SG_ALERT,
246                         "Subsystem " << name << " not found" );
247             } else {
248                 subsystem->reinit();
249             }
250         }
251     }
252
253     globals->get_event_mgr()->reinit();
254
255     return result;
256 }
257
258 /**
259  * Built-in command: suspend one or more subsystems.
260  *
261  * subsystem[*] - the name(s) of the subsystem(s) to suspend.
262  */
263 static bool
264 do_suspend (const SGPropertyNode * arg)
265 {
266     bool result = true;
267
268     vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
269     for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
270         const char * name = subsystems[i]->getStringValue();
271         SGSubsystem * subsystem = globals->get_subsystem(name);
272         if (subsystem == 0) {
273             result = false;
274             SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
275         } else {
276             subsystem->suspend();
277         }
278     }
279     return result;
280 }
281
282 /**
283  * Built-in command: suspend one or more subsystems.
284  *
285  * subsystem[*] - the name(s) of the subsystem(s) to suspend.
286  */
287 static bool
288 do_resume (const SGPropertyNode * arg)
289 {
290     bool result = true;
291
292     vector<SGPropertyNode_ptr> subsystems = arg->getChildren("subsystem");
293     for ( unsigned int i = 0; i < subsystems.size(); i++ ) {
294         const char * name = subsystems[i]->getStringValue();
295         SGSubsystem * subsystem = globals->get_subsystem(name);
296         if (subsystem == 0) {
297             result = false;
298             SG_LOG(SG_GENERAL, SG_ALERT, "Subsystem " << name << " not found");
299         } else {
300             subsystem->resume();
301         }
302     }
303     return result;
304 }
305
306 static struct {
307   const char * name;
308   SGCommandMgr::command_t command;
309 } built_ins [] = {
310     { "add-subsystem", do_add_subsystem },
311     { "remove-subsystem", do_remove_subsystem },
312     { "subsystem-running", do_check_subsystem_running },
313     { "reinit", do_reinit },
314     { "suspend", do_suspend },
315     { "resume", do_resume },
316     { 0, 0 }                    // zero-terminated
317 };
318
319 void registerSubsystemCommands(SGCommandMgr* cmdMgr)
320 {
321     for (int i = 0; built_ins[i].name != 0; i++) {
322       cmdMgr->addCommand(built_ins[i].name, built_ins[i].command);
323     }
324 }
325
326 } // of namepace flightgear