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