10#include <simgear/compiler.h>
11#include <simgear/props/props_io.hxx>
16#include <osg/GraphicsContext>
17#include <osgDB/Registry>
21#include <simgear/canvas/VGInitOperation.hxx>
22#include <simgear/debug/logdelta.hxx>
23#include <simgear/emesary/Emesary.hxx>
24#include <simgear/emesary/notifications.hxx>
25#include <simgear/io/raw_socket.hxx>
26#include <simgear/math/SGMath.hxx>
27#include <simgear/math/sg_random.hxx>
28#include <simgear/misc/strutils.hxx>
29#include <simgear/nasal/NasalEmesaryInterface.hxx>
30#include <simgear/props/AtomicChangeListener.hxx>
31#include <simgear/props/props.hxx>
32#include <simgear/scene/material/Effect.hxx>
33#include <simgear/scene/material/matlib.hxx>
34#include <simgear/scene/model/modellib.hxx>
35#include <simgear/scene/tsync/terrasync.hxx>
36#include <simgear/structure/commands.hxx>
37#include <simgear/timing/sg_time.hxx>
67#include <simgear/embedded_resources/EmbeddedResourceManager.hxx>
68#include <EmbeddedResources/FlightGear-resources.hxx>
75#include <sys/resource.h>
89#ifdef NASAL_BACKGROUND_GC_THREAD
90static SGPropertyNode_ptr nasal_gc_threaded;
91static SGPropertyNode_ptr nasal_gc_threaded_wait;
92static SGSharedPtr<simgear::Notifications::MainLoopNotification> mln_begin(
new simgear::Notifications::MainLoopNotification(simgear::Notifications::MainLoopNotification::Type::Begin));
93static SGSharedPtr<simgear::Notifications::MainLoopNotification> mln_end(
new simgear::Notifications::MainLoopNotification(simgear::Notifications::MainLoopNotification::Type::End));
94static SGSharedPtr<simgear::Notifications::MainLoopNotification> mln_started(
new simgear::Notifications::MainLoopNotification(simgear::Notifications::MainLoopNotification::Type::Started));
95static SGSharedPtr<simgear::Notifications::MainLoopNotification> mln_stopped(
new simgear::Notifications::MainLoopNotification(simgear::Notifications::MainLoopNotification::Type::Stopped));
96static SGSharedPtr<simgear::Notifications::NasalGarbageCollectionConfigurationNotification> ngccn;
102#ifdef NASAL_BACKGROUND_GC_THREAD
120 auto use_threaded_gc = nasal_gc_threaded->getBoolValue();
121 auto threaded_wait = nasal_gc_threaded_wait->getBoolValue();
122 bool notify_gc_config =
false;
123 notify_gc_config = ngccn->SetActive(use_threaded_gc);
124 notify_gc_config |= ngccn->SetWait(threaded_wait);
125 if (notify_gc_config)
126 simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(ngccn);
128 simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(mln_begin);
131 if (sglog().has_popup()) {
132 std::string s = sglog().get_popup();
139 auto mgr =
globals->get_subsystem_mgr();
143 double sim_dt, real_dt;
144 mgr->get_subsystem<
TimeManager>()->computeTimeDeltas(sim_dt, real_dt);
150 SGCommandMgr::instance()->executedQueuedCommands();
151 simgear::AtomicChangeListener::fireChangeListeners();
153#ifdef NASAL_BACKGROUND_GC_THREAD
154 simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(mln_end);
162 SGPath terraSyncDir(
globals->get_terrasync_dir());
163 globals->append_data_path(terraSyncDir,
false );
165 if (
fgGetBool(
"/sim/fghome-readonly",
false)) {
166 SG_LOG(SG_GENERAL, SG_ALERT,
"initTerrasync() failing because /sim/fghome-readonly is true");
172 fgSetString(
"/sim/terrasync/installation-dir", (
globals->get_fg_root() /
"Scenery").utf8Str());
174 auto terra_sync =
globals->get_subsystem_mgr()->add<simgear::SGTerraSync>();
175 terra_sync->setRoot(
globals->get_props());
180 if (
fgGetBool(
"/sim/terrasync/enabled")) {
187 SGPath userDataPath =
globals->get_fg_home();
188 SGPath autosaveFile =
globals->autosaveFilePath(userDataPath);
189 if (autosaveFile.exists())
return;
191 std::string vendor =
fgGetString(
"/sim/rendering/gl-info/gl-vendor");
192 SGPath path(
globals->get_fg_root());
193 path.append(
"Video");
197 std::string renderer =
fgGetString(
"/sim/rendering/gl-info/gl-renderer");
198 size_t pos = renderer.find(
"x86/");
199 if (pos == std::string::npos) {
200 pos = renderer.find(
'/');
202 if (pos == std::string::npos) {
203 pos = renderer.find(
" (");
205 if (pos != std::string::npos) {
206 renderer = renderer.substr(0, pos);
208 path.append(renderer+
".xml");
210 SG_LOG(SG_INPUT, SG_INFO,
"Reading video settings from " << path);
212 SGPropertyNode *r_prop =
fgGetNode(
"/sim/rendering");
213 readProperties(path, r_prop);
214 }
catch (sg_exception& e) {
215 SG_LOG(SG_INPUT, SG_WARN,
"failed to read video settings:" << e.getMessage()
216 <<
"(from " << e.getOrigin() <<
")");
236 std::string versionString(
fgGetString(
"/sim/rendering/gl-info/gl-version"));
237 string_list parts = simgear::strutils::split(versionString);
238 if (parts.size() == 3) {
239 if (parts[1].find(
"NVIDIA") != std::string::npos) {
241 string_list driverVersion = simgear::strutils::split(parts[2],
".");
242 if (!driverVersion.empty()) {
243 int majorDriverVersion = simgear::strutils::to_int(driverVersion[0]);
244 if (majorDriverVersion < 300) {
245 std::ostringstream ss;
246 ss <<
"Please upgrade to at least version 300 of the nVidia drivers (installed version is " << parts[2] <<
")";
249 "FlightGear has detected outdated drivers for your graphics card.",
264#ifdef NASAL_BACKGROUND_GC_THREAD
265 nasal_gc_threaded =
fgGetNode(
"/sim/nasal-gc-threaded",
true);
266 nasal_gc_threaded_wait =
fgGetNode(
"/sim/nasal-gc-threaded-wait",
true);
269 nasal::initMainLoopRecipient();
276 nasal::shutdownMainLoopRecipient();
278#ifdef NASAL_BACKGROUND_GC_THREAD
279 nasal_gc_threaded.reset();
280 nasal_gc_threaded_wait.reset();
301 auto mgr =
globals->get_subsystem_mgr();
304 if (
globals->get_renderer()->runInitOperation()) {
309 fgSetBool(
"/sim/rendering/initialized",
true);
331 throw sg_exception(
"General initialization failed");
348 globals->set_matlib(
new SGMaterialLib );
354 simgear::SGModelLib::init(
globals->get_fg_root().utf8Str(),
globals->get_props());
356 auto timeManager = mgr->get_subsystem<
TimeManager>();
376 }
catch (std::exception& e) {
383 SG_LOG(SG_GENERAL, SG_INFO,
"Creating subsystems took:" << st.elapsedMSec());
391 SG_LOG(SG_GENERAL, SG_INFO,
"Binding subsystems took:" << st.elapsedMSec());
395 SGSubsystem::InitStatus
status = mgr->incrementalInit();
396 if (
status == SGSubsystem::INIT_DONE) {
411 globals->get_renderer()->setupView();
416 new simgear::canvas::VGInitOperation());
418 int session =
fgGetInt(
"/sim/session",0);
424 sglog().setStartupLoggingEnabled(
false);
431#ifdef NASAL_BACKGROUND_GC_THREAD
432 ngccn =
new simgear::Notifications::NasalGarbageCollectionConfigurationNotification(nasal_gc_threaded->getBoolValue(), nasal_gc_threaded_wait->getBoolValue());
433 simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(ngccn);
434 simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(mln_started);
454 bool secureMode =
true;
456 SG_LOG(SG_GENERAL, SG_MANDATORY_INFO,
"\n!! Network connections allowed to use Nasal !!\n"
457 "Network connections will be allowed full access to the simulator \n"
458 "including running arbitrary scripts. Ensure you have adequate security\n"
459 "(such as a firewall which blocks external connections).\n");
466 SGPropertyNode_ptr secureFlag =
fgGetNode(
"/sim/secure-flag",
true);
467 secureFlag->setBoolValue(secureMode);
468 secureFlag->setAttributes(SGPropertyNode::READ |
469 SGPropertyNode::PRESERVE |
470 SGPropertyNode::PROTECTED);
474#if defined(SG_WINDOWS)
476 _declspec(dllexport)
unsigned int NvOptimusEnablement = 0x00000001;
477 _declspec(dllexport)
int AmdPowerXpressRequestHighPerformance = 1;
483 const int maxLogCount = 10;
484 const auto homePath =
globals->get_fg_home();
486 for (
int i = maxLogCount;
i > 0; --
i) {
487 const auto name =
"fgfs_" + std::to_string(
i - 1) +
".log";
488 SGPath curLogFile = homePath /
name;
489 if (curLogFile.exists()) {
490 auto newName =
"fgfs_" + std::to_string(
i) +
".log";
491 curLogFile.rename(homePath / newName);
495 SGPath
p = homePath /
"fgfs.log";
498 SGPath log0Path = homePath /
"fgfs_0.log";
499 if (!
p.rename(log0Path)) {
500 std::cerr <<
"Failed to rename " <<
p.str() <<
" to " << log0Path.str() << std::endl;
506 sgDebugPriority fileLogLevel = SG_INFO;
510 fileLogLevel = std::min(fileLogLevel, logstream::priorityFromString(pri));
511 }
catch (std::exception& ) {
516 SGPath logPath =
globals->get_fg_home();
517 logPath.append(
"fgfs.log");
518 if (logPath.exists()) {
522 sglog().logToFile(logPath, SG_ALL, fileLogLevel);
529 std::string value = node->getStringValue();
530 std::cerr << __FILE__ <<
":" << __LINE__ <<
": sglogdeltas value=" << value <<
"\n";
531 logDeltaSet(value.c_str());
539 sglog().setLogLevels( SG_ALL, SG_WARN );
540 sglog().setStartupLoggingEnabled(
true);
546 "FlightGear was unable to create the lock file in FG_HOME");
557 showLauncher |= (::getenv(
"FG_LAUNCHER") !=
nullptr);
564 SG_LOG( SG_GENERAL, SG_MANDATORY_INFO,
"Deleting lock file at user request");
567 fgSetBool(
"/sim/fghome-readonly",
false);
575 SGPropertyNode* sglogdeltas =
globals->get_props()->getNode(
"/sim/sg-log-deltas",
true );
578 const char* sglogdeltas_value = getenv(
"SG_LOG_DELTAS");
579 if (sglogdeltas_value) {
580 sglogdeltas->setStringValue(sglogdeltas_value);
584 globals->get_props()->getNode(
"/sim",
true )->setAttribute(SGPropertyNode::VALUE_CHANGED_DOWN,
true);
587 SGPropertyNode* active =
globals->get_props()->getNode(
"/sim/property-locking/active",
true );
588 SGPropertyNode* verbose =
globals->get_props()->getNode(
"/sim/property-locking/verbose",
true );
589 SGPropertyNode* timing =
globals->get_props()->getNode(
"/sim/property-locking/timing",
true );
590 SGPropertyNode* parent_listeners =
globals->get_props()->getNode(
"/sim/property-locking/parent_listeners",
true );
591 SGPropertyLockControl(active, verbose, timing, parent_listeners);
594 const bool readOnlyFGHome =
fgGetBool(
"/sim/fghome-readonly");
595 if (!readOnlyFGHome) {
601 if (readOnlyFGHome) {
605 std::string version(FLIGHTGEAR_VERSION);
606 SG_LOG( SG_GENERAL, SG_INFO,
"FlightGear: Version " << version );
607 SG_LOG( SG_GENERAL, SG_INFO,
"FlightGear: Build Type " << FG_BUILD_TYPE );
608 SG_LOG( SG_GENERAL, SG_INFO,
"Built with " << SG_COMPILER_STR);
618 struct rlimit rlimit;
619 int e = getrlimit(RLIMIT_DATA, &rlimit);
621 SG_LOG( SG_GENERAL, SG_INFO,
"This is OpenBSD; getrlimit() failed: " << strerror(errno));
624 unsigned long long required = 4ULL * (1ULL<<30);
625 if (rlimit.rlim_cur < required) {
626 SG_LOG( SG_GENERAL, SG_POPUP,
""
627 <<
"Max data segment (" << rlimit.rlim_cur <<
"bytes) too small.\n"
628 <<
"This can cause Flightgear to crash due to SIGBUS.\n"
629 <<
"E.g. increase with 'ulimit -d " << required/1024 <<
"'."
640 globals->set_channel_options_list( col );
659 bool didUseLauncher =
false;
676 didUseLauncher =
true;
681 SG_LOG(SG_GENERAL, SG_ALERT,
"\n!Launcher requested, but FlightGear was compiled without Qt support!\n");
714 const auto& resMgr = simgear::EmbeddedResourceManager::createInstance();
715 initFlightGearEmbeddedResources();
717 const std::string locale =
globals->get_locale()->getPreferredLanguage();
719 resMgr->selectLocale(locale);
720 SG_LOG(SG_GENERAL, SG_INFO,
721 "EmbeddedResourceManager: selected locale '" << locale <<
"'");
723 if (
fgGetBool(
"/sim/autosave-migration/did-migrate",
false)) {
726 auto locale =
globals->get_locale();
727 const auto title = locale->getLocalizedString(
"settings-migration-title",
"sys",
"Settings migrated");
728 const auto msg = locale->getLocalizedString(
"settings-migration-text",
"sys",
729 "Saved settings were migrated from a previous version of FlightGear. "
730 "If you encounter any problems when using the system, try restoring "
731 "the default settings, before reporting a problem. "
732 "Saved settings can affect the appearance, performance and features of the simulator.");
736 globals->get_locale()->loadAircraftTranslations();
737 globals->get_locale()->loadAddonTranslations();
756 simgear::Socket::initSockets();
761 globals->get_renderer()->postinit();
775 const bool requestLauncherRestart =
fgGetBool(
"/sim/restart-launcher-on-exit");
777#ifdef NASAL_BACKGROUND_GC_THREAD
778 simgear::Emesary::GlobalTransmitter::instance()->NotifyAll(mln_stopped);
781 simgear::clearEffectCache();
782 simgear::canvas::vgShutdown();
794 if (requestLauncherRestart) {
796 for (
int arg = 1; arg < argc; ++arg) {
797 originalArgs.push_back(argv[arg]);
804 originalArgs.push_back(
"--launcher");
Bucket for subsystem pointers representing the sim's state.
void applyInitialPreset()
init() is called too late (after fgOSInit), so we call this method early, to load the initial preset ...
static NavDataCache * instance()
void setShouldLoadDefaultConfig(bool load)
when using the built-in launcher, we disable the default config files.
OptionResult processOptions()
apply option values to the simulation state (set properties, etc).
static bool checkForArgEnable(int argc, char *argv[], const std::string &checkArg)
Return true when user explicitly enabled boolean option, otherwise false.
static std::string getArgValue(int argc, char *argv[], const char *checkArg)
getArgValue - get the value of an argument if it exists, or an empty string otherwise
static Options * sharedInstance()
WindowVector windows
Vector of all the registered windows.
static WindowSystemAdapter * getWSA()
Get the global WindowSystemAdapter.
static const std::unique_ptr< AddonManager > & createInstance()
static const std::unique_ptr< AddonManager > & instance()
void fgInitCommands()
Initialize the default built-in commands.
void fgInitSceneCommands()
Initialize the default built-in commands.
void fgPostInitSubsystems()
bool fgInitNav()
Initialize vor/ndb/ils/fix list management and query systems (as well as simple airport db list) This...
int fgInitAircraft(bool reinit, bool didUseLauncher)
int fgInitConfig(int argc, char **argv, bool reinit)
void fgCreateSubsystems(bool duringReset)
void fgInitAircraftPaths(bool reinit)
InitHomeResult fgInitHome()
void fgOSResetProperties()
void fgRegisterIdleHandler(fgIdleHandler func)
void fgOSInit(int *argc, char **argv)
int fgGetInt(const char *name, int defaultValue)
Get an int value for a property.
std::string fgGetString(const char *name, const char *defaultValue)
Get a string value for a property.
bool fgSetInt(const char *name, int val)
Set an int value for a property.
std::vector< std::string > string_list
FlightGear Localization Support.
static void rotateOldLogFiles()
int fgMainInit(int argc, char **argv)
static void initTerrasync()
static SGPropertyNode_ptr frame_signal
static void fgMainLoop(void)
static void logToHome(const std::string &pri)
static void fgSetVideoOptions()
static SGLogDeltasListener s_sglogdeltas_listener
static void checkOpenGLVersion()
static void fgIdleFunction(void)
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
MessageBoxResult modalMessageBox(const std::string &caption, const std::string &msg, const std::string &moreText)
void startLaunchOnExit(const std::vector< std::string > &originalCommandLine)
@ brief helper to re-open the launcher once FLightGear exits cleanly
void initApp(int &argc, char **argv, bool doInitQSettings)
void unregisterMainLoopProperties()
void registerSubsystemCommands(SGCommandMgr *cmdMgr)
void addSentryBreadcrumb(const std::string &, const std::string &)
void addSentryTag(const char *, const char *)
void warnAboutGLVersion()
void sentryReportException(const std::string &, const std::string &)
void fatalMessageBoxThenExit(const std::string &caption, const std::string &msg, const std::string &moreText, int exitStatus, bool reportToSentry)
@ FG_OPTIONS_SHOW_AIRCRAFT
LockFileDialogResult showLockFileDialog()
bool fgGetBool(char const *name, bool def)
Get a bool value for a property.
bool fgSetBool(char const *name, bool val)
Set a bool value for a property.
bool fgSetString(char const *name, char const *str)
Set a string value for a property.
SGPropertyNode * fgGetNode(const char *path, bool create)
Get a property node.
bool fgPreliminaryGLVersionCheck()
Attempt to create an off-screen pixel buffer to check whether our target OpenGL version is available ...
void fgOSDisableScreensaver()
Attempt to disable the screensaver.
void fgSplashProgress(const char *identifier, unsigned int percent)
Set progress information.
void valueChanged(SGPropertyNode *node) override
void fgInitAllowedPaths()
Allowed paths here are absolute, and may contain one *, which matches any string.