mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-23 15:25:35 +08:00
529 lines
23 KiB
C++
529 lines
23 KiB
C++
// SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
|
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
|
|
|
|
#include "core/corefacade.h"
|
|
|
|
#include <QDBusConnection>
|
|
#include <QElapsedTimer>
|
|
#include <QMap>
|
|
#include <QObject>
|
|
#include <QString>
|
|
#include <QStringBuilder>
|
|
#include <QtGlobal>
|
|
|
|
#include "core/airspacemonitor.h"
|
|
#include "core/context/contextapplication.h"
|
|
#include "core/context/contextapplicationimpl.h"
|
|
#include "core/context/contextapplicationproxy.h"
|
|
#include "core/context/contextaudio.h"
|
|
#include "core/context/contextaudioimpl.h"
|
|
#include "core/context/contextnetwork.h"
|
|
#include "core/context/contextnetworkimpl.h"
|
|
#include "core/context/contextownaircraft.h"
|
|
#include "core/context/contextownaircraftimpl.h"
|
|
#include "core/context/contextsimulator.h"
|
|
#include "core/context/contextsimulatorimpl.h"
|
|
#include "core/corefacadeconfig.h"
|
|
#include "core/data/launchersetup.h"
|
|
#include "core/registermetadata.h"
|
|
#include "misc/dbusserver.h"
|
|
#include "misc/identifier.h"
|
|
#include "misc/loghistory.h"
|
|
#include "misc/logmessage.h"
|
|
#include "misc/registermetadata.h"
|
|
#include "misc/sharedstate/datalinkdbus.h"
|
|
#include "misc/statusmessage.h"
|
|
#include "misc/stringutils.h"
|
|
#include "misc/verify.h"
|
|
|
|
using namespace swift::misc;
|
|
using namespace swift::misc::aviation;
|
|
using namespace swift::misc::simulation;
|
|
using namespace swift::core::data;
|
|
using namespace swift::core::context;
|
|
|
|
namespace swift::core
|
|
{
|
|
CCoreFacade::CCoreFacade(const CCoreFacadeConfig &config, QObject *parent) : QObject(parent), m_config(config)
|
|
{
|
|
this->init();
|
|
}
|
|
|
|
CStatusMessage CCoreFacade::tryToReconnectWithDBus()
|
|
{
|
|
if (m_shuttingDown) { return CStatusMessage(this, CStatusMessage::SeverityInfo, u"Shutdown"); }
|
|
if (!m_config.requiresDBusConnection())
|
|
{
|
|
return CStatusMessage(this, CStatusMessage::SeverityInfo, u"Not DBus based");
|
|
}
|
|
const QString dBusAddress = this->getDBusAddress();
|
|
if (dBusAddress.isEmpty())
|
|
{
|
|
return CStatusMessage(this, CStatusMessage::SeverityInfo, u"Not DBus based, no address");
|
|
}
|
|
QString connectMsg;
|
|
if (!CContextApplicationProxy::isContextResponsive(dBusAddress, connectMsg))
|
|
{
|
|
return CStatusMessage(this, CStatusMessage::SeverityError,
|
|
u"Cannot connect DBus at '" % dBusAddress % u"', reason: " % connectMsg);
|
|
}
|
|
|
|
// re-init
|
|
m_initalized = false;
|
|
this->init();
|
|
|
|
// success
|
|
return CStatusMessage(this, CStatusMessage::SeverityInfo, u"Re-initialized via '%1'") << dBusAddress;
|
|
}
|
|
|
|
void CCoreFacade::init()
|
|
{
|
|
if (m_initalized || m_shuttingDown) { return; }
|
|
|
|
QMap<QString, qint64> times;
|
|
QElapsedTimer time;
|
|
CCoreFacade::registerMetadata();
|
|
|
|
// either use explicit setting or last value
|
|
const QString dbusAddress = this->getDBusAddress();
|
|
m_launcherSetup.setProperty(CLauncherSetup::IndexDBusAddress, dbusAddress);
|
|
|
|
// DBus
|
|
time.start();
|
|
if (m_config.requiresDBusSever()) { this->initDBusServer(dbusAddress); }
|
|
if (m_config.requiresDBusConnection())
|
|
{
|
|
this->initDBusConnection(dbusAddress);
|
|
if (!m_dbusConnection.isConnected())
|
|
{
|
|
const QString e = m_dbusConnection.lastError().message();
|
|
SWIFT_VERIFY_X(false, "CRuntime::init DBus problem", e.toUtf8().constData());
|
|
CLogMessage(this).error(u"DBus connection failed: '%1'") << e;
|
|
return;
|
|
}
|
|
}
|
|
times.insert("DBus", time.restart());
|
|
|
|
// shared state infrastructure
|
|
m_dataLinkDBus = new shared_state::CDataLinkDBus(this);
|
|
switch (m_config.getMode())
|
|
{
|
|
case CCoreFacadeConfig::NotUsed:
|
|
case CCoreFacadeConfig::Local: m_dataLinkDBus->initializeLocal(nullptr); break;
|
|
case CCoreFacadeConfig::LocalInDBusServer: m_dataLinkDBus->initializeLocal(m_dbusServer); break;
|
|
case CCoreFacadeConfig::Remote:
|
|
m_dataLinkDBus->initializeRemote(m_dbusConnection, CDBusServer::coreServiceName(m_dbusConnection));
|
|
break;
|
|
default: qFatal("Invalid application context mode");
|
|
}
|
|
|
|
// shared log history
|
|
m_logHistorySource = new CLogHistorySource(this);
|
|
m_logHistorySource->initialize(m_dataLinkDBus);
|
|
if (m_config.getMode() == CCoreFacadeConfig::Local ||
|
|
m_config.getMode() == CCoreFacadeConfig::LocalInDBusServer)
|
|
{
|
|
m_logHistory = new CLogHistory(this);
|
|
m_logHistory->initialize(m_dataLinkDBus);
|
|
}
|
|
|
|
if (m_config.getMode() == CCoreFacadeConfig::NotUsed)
|
|
{
|
|
m_initalized = true;
|
|
return;
|
|
}
|
|
|
|
// contexts
|
|
if (m_contextApplication) { m_contextApplication->deleteLater(); }
|
|
m_contextApplication = IContextApplication::create(this, m_config.getMode(), m_dbusServer, m_dbusConnection);
|
|
times.insert("Application", time.restart());
|
|
|
|
if (m_contextAudio) { m_contextAudio->deleteLater(); }
|
|
m_contextAudio = qobject_cast<CContextAudioBase *>(
|
|
IContextAudio::create(this, m_config.getMode(), m_dbusServer, m_dbusConnection));
|
|
times.insert("Audio", time.restart());
|
|
|
|
if (m_contextOwnAircraft) { m_contextOwnAircraft->deleteLater(); }
|
|
m_contextOwnAircraft = IContextOwnAircraft::create(this, m_config.getMode(), m_dbusServer, m_dbusConnection);
|
|
times.insert("Own aircraft", time.restart());
|
|
|
|
if (m_contextSimulator) { m_contextSimulator->deleteLater(); }
|
|
m_contextSimulator = IContextSimulator::create(this, m_config.getMode(), m_dbusServer, m_dbusConnection);
|
|
times.insert("Simulator", time.restart());
|
|
|
|
// depends on own aircraft and simulator context, which is bad style
|
|
if (m_contextNetwork) { m_contextNetwork->deleteLater(); }
|
|
m_contextNetwork = IContextNetwork::create(this, m_config.getMode(), m_dbusServer, m_dbusConnection);
|
|
times.insert("Network", time.restart());
|
|
|
|
// checks --------------
|
|
// 1. own aircraft and simulator should reside in same location
|
|
Q_ASSERT(!m_contextSimulator || (m_contextOwnAircraft->isUsingImplementingObject() ==
|
|
m_contextSimulator->isUsingImplementingObject()));
|
|
|
|
// 2. own aircraft and network should reside in same location
|
|
Q_ASSERT(!m_contextNetwork ||
|
|
(m_contextOwnAircraft->isUsingImplementingObject() == m_contextNetwork->isUsingImplementingObject()));
|
|
|
|
// post inits, wiring things among context (e.g. signal slots)
|
|
time.restart();
|
|
this->initPostSetup(times);
|
|
times.insert("Post setup", time.restart());
|
|
CLogMessage(this).info(u"Init times: %1") << qmapToString(times);
|
|
|
|
// flag
|
|
m_initalized = true;
|
|
}
|
|
|
|
void CCoreFacade::registerMetadata()
|
|
{
|
|
swift::misc::registerMetadata();
|
|
swift::core::registerMetadata();
|
|
}
|
|
|
|
bool CCoreFacade::parseCommandLine(const QString &commandLine, const CIdentifier &originator)
|
|
{
|
|
bool handled = false;
|
|
// audio can be empty depending on whre it runs
|
|
if (this->getIContextAudio() && !this->getIContextAudio()->isEmptyObject())
|
|
{
|
|
handled = handled || this->getIContextAudio()->parseCommandLine(commandLine, originator);
|
|
}
|
|
if (this->getIContextNetwork())
|
|
{
|
|
handled = handled || this->getIContextNetwork()->parseCommandLine(commandLine, originator);
|
|
}
|
|
if (this->getIContextOwnAircraft())
|
|
{
|
|
handled = handled || this->getIContextOwnAircraft()->parseCommandLine(commandLine, originator);
|
|
}
|
|
if (this->getIContextSimulator())
|
|
{
|
|
handled = handled || this->getIContextSimulator()->parseCommandLine(commandLine, originator);
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
void CCoreFacade::initDBusServer(const QString &dBusAddress)
|
|
{
|
|
Q_ASSERT(!dBusAddress.isEmpty());
|
|
if (m_dbusServer) { m_dbusServer->deleteLater(); } // delete if there was an existing one
|
|
m_dbusServer = new CDBusServer(dBusAddress, this);
|
|
CLogMessage(this).info(u"DBus server on address: '%1'") << dBusAddress;
|
|
}
|
|
|
|
void CCoreFacade::initPostSetup(QMap<QString, qint64> ×)
|
|
{
|
|
bool c = false;
|
|
Q_UNUSED(c) // for release version
|
|
QElapsedTimer time;
|
|
time.start();
|
|
|
|
times.insert("Post setup, connects first", time.restart());
|
|
|
|
// local simulator?
|
|
if (m_contextSimulator && m_contextSimulator->isUsingImplementingObject())
|
|
{
|
|
// only connect if network runs locally, no round trips
|
|
// remark: from a design perspective it would be nice if those could be avoided (seperation of concerns)
|
|
// those connects here reprent cross context dependencies
|
|
if (m_contextNetwork && m_contextNetwork->isUsingImplementingObject())
|
|
{
|
|
Q_ASSERT_X(this->getCContextNetwork(), Q_FUNC_INFO, "No local network object");
|
|
Q_ASSERT_X(this->getCContextNetwork()->airspace(), Q_FUNC_INFO, "No airspace object");
|
|
|
|
c = connect(m_contextNetwork, &IContextNetwork::textMessagesReceived, this->getCContextSimulator(),
|
|
&CContextSimulator::xCtxTextMessagesReceived, Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
|
|
// use readyForModelMatching instead of CAirspaceMonitor::addedAircraft, as it contains client
|
|
// information ready for model matching is sent delayed when all information are available
|
|
c = connect(m_contextNetwork, &IContextNetwork::readyForModelMatching, this->getCContextSimulator(),
|
|
&CContextSimulator::xCtxAddedRemoteAircraftReadyForModelMatching, Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(m_contextNetwork, &IContextNetwork::removedAircraft, this->getCContextSimulator(),
|
|
&CContextSimulator::xCtxRemovedRemoteAircraft, Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(m_contextNetwork, &IContextNetwork::changedRemoteAircraftModel,
|
|
this->getCContextSimulator(), &CContextSimulator::xCtxChangedRemoteAircraftModel,
|
|
Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(m_contextNetwork, &IContextNetwork::changedRemoteAircraftEnabled,
|
|
this->getCContextSimulator(), &CContextSimulator::xCtxChangedRemoteAircraftEnabled,
|
|
Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(m_contextNetwork, &IContextNetwork::connectionStatusChanged, this->getCContextSimulator(),
|
|
&CContextSimulator::xCtxNetworkConnectionStatusChanged, Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(this->getCContextNetwork()->airspace(), &CAirspaceMonitor::requestedNewAircraft,
|
|
this->getCContextSimulator(), &CContextSimulator::xCtxNetworkRequestedNewAircraft,
|
|
Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(this->getCContextSimulator(), &CContextSimulator::renderRestrictionsChanged,
|
|
this->getCContextNetwork(), &CContextNetwork::xCtxSimulatorRenderRestrictionsChanged,
|
|
Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
c = connect(this->getCContextSimulator(), &CContextSimulator::simulatorStatusChanged,
|
|
this->getCContextNetwork(), &CContextNetwork::xCtxSimulatorStatusChanged,
|
|
Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
|
|
// set provider
|
|
this->getCContextNetwork()->setSimulationEnvironmentProvider(this->getCContextSimulator()->simulator());
|
|
}
|
|
|
|
// only if own aircraft runs locally
|
|
if (m_contextOwnAircraft && m_contextOwnAircraft->isUsingImplementingObject())
|
|
{
|
|
c = connect(m_contextOwnAircraft, &IContextOwnAircraft::changedAircraftCockpit,
|
|
this->getCContextSimulator(), &CContextSimulator::xCtxUpdateSimulatorCockpitFromContext);
|
|
Q_ASSERT(c);
|
|
c = connect(m_contextOwnAircraft, &IContextOwnAircraft::changedSelcal, this->getCContextSimulator(),
|
|
&CContextSimulator::xCtxUpdateSimulatorSelcalFromContext);
|
|
Q_ASSERT(c);
|
|
|
|
// relay changed aircraft to own aircraft provider but with identifier
|
|
// identifier is needed because own aircraft context also reports changed aircraft to
|
|
// xCtxChangedOwnAircraftModel and we avoid roundtrips
|
|
c = connect(this->getCContextSimulator(), &CContextSimulator::ownAircraftModelChanged,
|
|
this->getCContextOwnAircraft(), [=](const CAircraftModel &changedModel) {
|
|
if (!this->getIContextOwnAircraft()) { return; }
|
|
if (!this->getCContextSimulator()) { return; }
|
|
this->getCContextOwnAircraft()->xCtxChangedSimulatorModel(
|
|
changedModel, this->getCContextSimulator()->identifier());
|
|
});
|
|
|
|
Q_ASSERT(c);
|
|
c = connect(this->getCContextSimulator(), &CContextSimulator::simulatorStatusChanged,
|
|
this->getCContextOwnAircraft(), &CContextOwnAircraft::xCtxChangedSimulatorStatus);
|
|
Q_ASSERT(c);
|
|
|
|
// this is used if the value in own aircraft is changed, to callback simulator
|
|
c = connect(this->getCContextOwnAircraft(), &CContextOwnAircraft::ps_changedModel,
|
|
this->getCContextSimulator(), &CContextSimulator::xCtxChangedOwnAircraftModel);
|
|
Q_ASSERT(c);
|
|
}
|
|
|
|
// times
|
|
times.insert("Post setup, sim.connects", time.restart());
|
|
}
|
|
|
|
// connection status of network changed
|
|
// with AFV no longer use m_contextAudio->isUsingImplementingObject() as audio can run on both sides
|
|
if (this->getCContextAudioBase() && m_contextNetwork)
|
|
{
|
|
Q_ASSERT(m_contextApplication);
|
|
c = connect(m_contextNetwork, &IContextNetwork::connectionStatusChanged, this->getCContextAudioBase(),
|
|
&CContextAudio::xCtxNetworkConnectionStatusChanged, Qt::QueuedConnection);
|
|
Q_ASSERT(c);
|
|
times.insert("Post setup, connects audio", time.restart());
|
|
}
|
|
}
|
|
|
|
QString CCoreFacade::getDBusAddress() const
|
|
{
|
|
QString dbusAddress;
|
|
if (m_config.hasDBusAddress()) { dbusAddress = m_config.getDBusAddress(); }
|
|
else
|
|
{
|
|
const CLauncherSetup setup = m_launcherSetup.get();
|
|
dbusAddress = setup.getDBusAddress();
|
|
}
|
|
return dbusAddress;
|
|
}
|
|
|
|
void CCoreFacade::gracefulShutdown()
|
|
{
|
|
if (!m_initalized) { return; }
|
|
if (m_shuttingDown) { return; }
|
|
m_shuttingDown = true;
|
|
|
|
// disable all signals towards runtime
|
|
disconnect(this);
|
|
|
|
// tear down shared state infrastructure
|
|
delete m_logHistory;
|
|
m_logHistory = nullptr;
|
|
delete m_logHistorySource;
|
|
m_logHistorySource = nullptr;
|
|
delete m_dataLinkDBus;
|
|
m_dataLinkDBus = nullptr;
|
|
|
|
// unregister all from DBus
|
|
if (m_dbusServer) { m_dbusServer->removeAllObjects(); }
|
|
|
|
// handle contexts
|
|
|
|
if (this->getCContextAudioBase())
|
|
{
|
|
// there is no empty audio context since AFV
|
|
disconnect(this->getCContextAudioBase());
|
|
this->getCContextAudioBase()->gracefulShutdown();
|
|
this->getIContextAudio()->deleteLater();
|
|
m_contextAudio = nullptr;
|
|
}
|
|
|
|
// log off from network, if connected
|
|
if (this->getIContextNetwork())
|
|
{
|
|
disconnect(this->getIContextNetwork());
|
|
this->getIContextNetwork()->disconnectFromNetwork();
|
|
if (m_contextNetwork->isUsingImplementingObject())
|
|
{
|
|
this->getCContextNetwork()->gracefulShutdown(); // for threads
|
|
}
|
|
this->getIContextNetwork()->deleteLater();
|
|
// replace by dummy object avoiding nullptr issues during shutdown phase
|
|
QDBusConnection defaultConnection("default");
|
|
m_contextNetwork = IContextNetwork::create(this, CCoreFacadeConfig::NotUsed, nullptr, defaultConnection);
|
|
}
|
|
|
|
if (this->getIContextSimulator())
|
|
{
|
|
disconnect(this->getIContextSimulator());
|
|
if (this->getIContextSimulator()->isUsingImplementingObject())
|
|
{
|
|
// shutdown the plugins
|
|
this->getCContextSimulator()->gracefulShutdown();
|
|
}
|
|
this->getIContextSimulator()->deleteLater();
|
|
QDBusConnection defaultConnection("default");
|
|
m_contextSimulator =
|
|
IContextSimulator::create(this, CCoreFacadeConfig::NotUsed, nullptr, defaultConnection);
|
|
}
|
|
|
|
if (this->getIContextOwnAircraft())
|
|
{
|
|
disconnect(this->getIContextOwnAircraft());
|
|
this->getIContextOwnAircraft()->deleteLater();
|
|
QDBusConnection defaultConnection("default");
|
|
m_contextOwnAircraft =
|
|
IContextOwnAircraft::create(this, CCoreFacadeConfig::NotUsed, nullptr, defaultConnection);
|
|
}
|
|
|
|
if (this->getIContextApplication())
|
|
{
|
|
disconnect(this->getIContextApplication());
|
|
this->getIContextApplication()->deleteLater();
|
|
QDBusConnection defaultConnection("default");
|
|
m_contextApplication =
|
|
IContextApplication::create(this, CCoreFacadeConfig::NotUsed, nullptr, defaultConnection);
|
|
}
|
|
}
|
|
|
|
void CCoreFacade::initDBusConnection(const QString &address)
|
|
{
|
|
if (m_initDBusConnection) { return; }
|
|
if (address.isEmpty() || address == CDBusServer::sessionBusAddress())
|
|
{
|
|
QDBusConnection::disconnectFromBus(m_dbusConnection.name());
|
|
m_dbusConnection = QDBusConnection::sessionBus();
|
|
}
|
|
else if (address == CDBusServer::systemBusAddress())
|
|
{
|
|
QDBusConnection::disconnectFromBus(m_dbusConnection.name());
|
|
m_dbusConnection = QDBusConnection::systemBus();
|
|
}
|
|
else
|
|
{
|
|
const QString name(CDBusServer::p2pConnectionName() + " " + address);
|
|
QDBusConnection::disconnectFromPeer(name);
|
|
m_dbusConnection = QDBusConnection::connectToPeer(address, name);
|
|
}
|
|
}
|
|
|
|
const IContextApplication *CCoreFacade::getIContextApplication() const { return m_contextApplication; }
|
|
|
|
IContextApplication *CCoreFacade::getIContextApplication() { return m_contextApplication; }
|
|
|
|
IContextAudio *CCoreFacade::getIContextAudio() { return m_contextAudio; }
|
|
|
|
const IContextAudio *CCoreFacade::getIContextAudio() const { return m_contextAudio; }
|
|
|
|
CContextAudioBase *CCoreFacade::getCContextAudioBase() { return m_contextAudio; }
|
|
|
|
const CContextAudioBase *CCoreFacade::getCContextAudioBase() const { return m_contextAudio; }
|
|
|
|
IContextNetwork *CCoreFacade::getIContextNetwork() { return m_contextNetwork; }
|
|
|
|
const IContextNetwork *CCoreFacade::getIContextNetwork() const { return m_contextNetwork; }
|
|
|
|
IContextOwnAircraft *CCoreFacade::getIContextOwnAircraft() { return m_contextOwnAircraft; }
|
|
|
|
const IContextOwnAircraft *CCoreFacade::getIContextOwnAircraft() const { return m_contextOwnAircraft; }
|
|
|
|
const IContextSimulator *CCoreFacade::getIContextSimulator() const { return m_contextSimulator; }
|
|
|
|
IContextSimulator *CCoreFacade::getIContextSimulator() { return m_contextSimulator; }
|
|
|
|
CContextAudio *CCoreFacade::getCContextAudio()
|
|
{
|
|
Q_ASSERT_X(m_contextAudio && m_contextAudio->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextAudio *>(m_contextAudio);
|
|
}
|
|
|
|
const CContextAudio *CCoreFacade::getCContextAudio() const
|
|
{
|
|
Q_ASSERT_X(m_contextAudio && m_contextAudio->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextAudio *>(m_contextAudio);
|
|
}
|
|
|
|
CContextApplication *CCoreFacade::getCContextApplication()
|
|
{
|
|
Q_ASSERT_X(m_contextApplication && m_contextApplication->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextApplication *>(m_contextApplication);
|
|
}
|
|
|
|
const CContextApplication *CCoreFacade::getCContextApplication() const
|
|
{
|
|
Q_ASSERT_X(m_contextApplication && m_contextApplication->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextApplication *>(m_contextApplication);
|
|
}
|
|
|
|
CContextNetwork *CCoreFacade::getCContextNetwork()
|
|
{
|
|
Q_ASSERT_X(m_contextNetwork && m_contextNetwork->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextNetwork *>(m_contextNetwork);
|
|
}
|
|
|
|
const CContextNetwork *CCoreFacade::getCContextNetwork() const
|
|
{
|
|
Q_ASSERT_X(m_contextNetwork && m_contextNetwork->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextNetwork *>(m_contextNetwork);
|
|
}
|
|
|
|
CContextOwnAircraft *CCoreFacade::getCContextOwnAircraft()
|
|
{
|
|
Q_ASSERT_X(m_contextOwnAircraft && m_contextOwnAircraft->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextOwnAircraft *>(m_contextOwnAircraft);
|
|
}
|
|
|
|
const CContextOwnAircraft *CCoreFacade::getCContextOwnAircraft() const
|
|
{
|
|
Q_ASSERT_X(m_contextOwnAircraft && m_contextOwnAircraft->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextOwnAircraft *>(m_contextOwnAircraft);
|
|
}
|
|
|
|
CContextSimulator *CCoreFacade::getCContextSimulator()
|
|
{
|
|
Q_ASSERT_X(m_contextSimulator && m_contextSimulator->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextSimulator *>(m_contextSimulator);
|
|
}
|
|
|
|
const CContextSimulator *CCoreFacade::getCContextSimulator() const
|
|
{
|
|
Q_ASSERT_X(m_contextSimulator && m_contextSimulator->isUsingImplementingObject(), "CCoreRuntime",
|
|
"Cannot downcast to local object");
|
|
return static_cast<CContextSimulator *>(m_contextSimulator);
|
|
}
|
|
} // namespace swift::core
|