mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-02 15:15:50 +08:00
Up to now, CPluginManagerSimulator::getListener was allocating a listener automatically in the background which was not always the desired behaviour. For example in case simulators are stopped, it is unnecessary to allocate all listeners and call stop on them. It is enough to stop the existing ones. In order to achieve the correct behaviour the creation part is moved to CPluginManagerSimulator::createListener. refs #606
593 lines
23 KiB
C++
593 lines
23 KiB
C++
/* Copyright (C) 2013
|
|
* swift Project Community / Contributors
|
|
*
|
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
|
* contained in the LICENSE file.
|
|
*/
|
|
|
|
#include "contextsimulatorimpl.h"
|
|
#include "contextownaircraftimpl.h"
|
|
#include "contextownaircraft.h"
|
|
#include "contextapplication.h"
|
|
#include "contextnetworkimpl.h"
|
|
#include "pluginmanagersimulator.h"
|
|
#include "contextruntime.h"
|
|
#include "blackcore/registermetadata.h"
|
|
#include "blackmisc/propertyindexvariantmap.h"
|
|
#include "blackmisc/logmessage.h"
|
|
#include "blackmisc/loghandler.h"
|
|
#include "blackmisc/threadutils.h"
|
|
#include <QPluginLoader>
|
|
#include <QLibrary>
|
|
|
|
using namespace BlackMisc;
|
|
using namespace BlackMisc::PhysicalQuantities;
|
|
using namespace BlackMisc::Aviation;
|
|
using namespace BlackMisc::Network;
|
|
using namespace BlackMisc::Simulation;
|
|
using namespace BlackMisc::Geo;
|
|
using namespace BlackMisc::Simulation;
|
|
|
|
namespace BlackCore
|
|
{
|
|
CContextSimulator::CContextSimulator(CRuntimeConfig::ContextMode mode, CRuntime *runtime) :
|
|
IContextSimulator(mode, runtime),
|
|
m_plugins(new CPluginManagerSimulator(this))
|
|
{
|
|
this->setObjectName("CContextSimulator");
|
|
m_plugins->collectPlugins();
|
|
}
|
|
|
|
CContextSimulator::~CContextSimulator()
|
|
{
|
|
this->gracefulShutdown();
|
|
}
|
|
|
|
void CContextSimulator::gracefulShutdown()
|
|
{
|
|
this->disconnect();
|
|
this->unloadSimulatorPlugin();
|
|
}
|
|
|
|
CSimulatorPluginInfoList CContextSimulator::getAvailableSimulatorPlugins() const
|
|
{
|
|
return m_plugins->getAvailableSimulatorPlugins();
|
|
}
|
|
|
|
bool CContextSimulator::startSimulatorPlugin(const CSimulatorPluginInfo &simulatorInfo)
|
|
{
|
|
return this->loadSimulatorPlugin(simulatorInfo, true);
|
|
}
|
|
|
|
void CContextSimulator::stopSimulatorPlugin(const CSimulatorPluginInfo &simulatorInfo)
|
|
{
|
|
if (!m_simulatorPlugin.first.isUnspecified() && m_simulatorPlugin.first == simulatorInfo)
|
|
{
|
|
this->unloadSimulatorPlugin();
|
|
}
|
|
|
|
ISimulatorListener *listener = m_plugins->getListener(simulatorInfo.getIdentifier());
|
|
Q_ASSERT(listener);
|
|
QMetaObject::invokeMethod(listener, "stop");
|
|
}
|
|
|
|
int CContextSimulator::getSimulatorStatus() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return 0; }
|
|
|
|
Q_ASSERT_X(m_simulatorPlugin.second, Q_FUNC_INFO, "Missing simulator");
|
|
return m_simulatorPlugin.second->getSimulatorStatus();
|
|
}
|
|
|
|
BlackMisc::Simulation::CSimulatorPluginInfo CContextSimulator::getSimulatorPluginInfo() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return BlackMisc::Simulation::CSimulatorPluginInfo(); }
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.first;
|
|
}
|
|
|
|
CSimulatorSetup CContextSimulator::getSimulatorSetup() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return BlackMisc::Simulation::CSimulatorSetup();
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getSimulatorSetup();
|
|
}
|
|
|
|
CAirportList CContextSimulator::getAirportsInRange() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
// If no ISimulator object is available, return a dummy.
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return CAirportList();
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getAirportsInRange();
|
|
}
|
|
|
|
CAircraftModelList CContextSimulator::getInstalledModels() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
// If no ISimulator object is available, return a dummy.
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return CAircraftModelList();
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getInstalledModels();
|
|
}
|
|
|
|
int CContextSimulator::getInstalledModelsCount() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return 0; }
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getInstalledModels().size();
|
|
}
|
|
|
|
CAircraftModelList CContextSimulator::getInstalledModelsStartingWith(const QString modelString) const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << modelString; }
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return CAircraftModelList();
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getInstalledModels().findModelsStartingWith(modelString);
|
|
}
|
|
|
|
void CContextSimulator::reloadInstalledModels()
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return;
|
|
}
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->reloadInstalledModels();
|
|
}
|
|
|
|
bool CContextSimulator::setTimeSynchronization(bool enable, const CTime &offset)
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return false; }
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
bool c = m_simulatorPlugin.second->setTimeSynchronization(enable, offset);
|
|
if (!c) { return false; }
|
|
|
|
CLogMessage(this).info(enable ? QStringLiteral("Set time syncronization to %1").arg(offset.toQString()) : QStringLiteral("Disabled time syncrhonization"));
|
|
return true;
|
|
}
|
|
|
|
bool CContextSimulator::isTimeSynchronized() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return false; }
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->isTimeSynchronized();
|
|
}
|
|
|
|
int CContextSimulator::getMaxRenderedAircraft() const
|
|
{
|
|
if (m_debugEnabled) {CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return 0; }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getMaxRenderedAircraft();
|
|
}
|
|
|
|
void CContextSimulator::setMaxRenderedAircraft(int number)
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << number; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return; }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->setMaxRenderedAircraft(number);
|
|
|
|
}
|
|
|
|
void CContextSimulator::setMaxRenderedDistance(const CLength &distance)
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << distance; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return; }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->setMaxRenderedDistance(distance);
|
|
}
|
|
|
|
QString CContextSimulator::getRenderRestrictionText() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return ""; }
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
if (!m_simulatorPlugin.second->isRenderingRestricted()) { return "none"; }
|
|
QString rt;
|
|
if (m_simulatorPlugin.second->isMaxAircraftRestricted())
|
|
{
|
|
rt.append(QString::number(m_simulatorPlugin.second->getMaxRenderedAircraft())).append(" A/C");
|
|
}
|
|
if (m_simulatorPlugin.second->isMaxDistanceRestricted())
|
|
{
|
|
if (!rt.isEmpty()) { rt.append(" ");}
|
|
rt.append(m_simulatorPlugin.second->getMaxRenderedDistance().valueRoundedWithUnit(CLengthUnit::NM(), 0));
|
|
}
|
|
return rt;
|
|
}
|
|
|
|
CLength CContextSimulator::getMaxRenderedDistance() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return CLength(0, CLengthUnit::nullUnit()); }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getMaxRenderedDistance();
|
|
}
|
|
|
|
CLength CContextSimulator::getRenderedDistanceBoundary() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return CLength(20.0, CLengthUnit::NM());
|
|
}
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getRenderedDistanceBoundary();
|
|
}
|
|
|
|
void CContextSimulator::deleteAllRenderingRestrictions()
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (!m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->deleteAllRenderingRestrictions();
|
|
}
|
|
}
|
|
|
|
bool CContextSimulator::isRenderingRestricted() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return false; }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->isRenderingRestricted();
|
|
}
|
|
|
|
bool CContextSimulator::isRenderingEnabled() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return false; }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->isRenderingEnabled();
|
|
}
|
|
|
|
CTime CContextSimulator::getTimeSynchronizationOffset() const
|
|
{
|
|
if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return CTime(0, CTimeUnit::hrmin()); }
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
return m_simulatorPlugin.second->getTimeSynchronizationOffset();
|
|
}
|
|
|
|
bool CContextSimulator::loadSimulatorPlugin(const CSimulatorPluginInfo &simulatorInfo, bool withListener)
|
|
{
|
|
Q_ASSERT(getIContextApplication());
|
|
Q_ASSERT(getIContextApplication()->isUsingImplementingObject());
|
|
Q_ASSERT(!simulatorInfo.isUnspecified());
|
|
Q_ASSERT(CThreadUtils::isCurrentThreadApplicationThread()); // only run in main thread
|
|
|
|
if (!simulatorInfo.isValid())
|
|
{
|
|
CLogMessage(this).error("Illegal plugin");
|
|
return false;
|
|
}
|
|
|
|
// Is the plugin already loaded?
|
|
if (!m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
unloadSimulatorPlugin(); // old plugin unloaded
|
|
|
|
// now we have a state where no driver is loaded
|
|
if (withListener)
|
|
{
|
|
this->listenForSimulator(simulatorInfo);
|
|
return false; // not a plugin yet, just listener
|
|
}
|
|
|
|
if (!simulatorInfo.isValid() || simulatorInfo.isUnspecified())
|
|
{
|
|
CLogMessage(this).error("Illegal plugin");
|
|
return false;
|
|
}
|
|
|
|
ISimulatorFactory *factory = m_plugins->getFactory(simulatorInfo.getIdentifier());
|
|
Q_ASSERT_X(factory, Q_FUNC_INFO, "no factory");
|
|
|
|
// We assume we run in the same process as the own aircraft context
|
|
// Hence we pass in memory reference to own aircraft object
|
|
Q_ASSERT(this->getIContextOwnAircraft()->isUsingImplementingObject());
|
|
Q_ASSERT(this->getIContextNetwork()->isUsingImplementingObject());
|
|
IOwnAircraftProvider *ownAircraftProvider = this->getRuntime()->getCContextOwnAircraft();
|
|
IRemoteAircraftProvider *renderedAircraftProvider = this->getRuntime()->getCContextNetwork();
|
|
ISimulator *simulator = factory->create(simulatorInfo, ownAircraftProvider, renderedAircraftProvider, m_plugins);
|
|
Q_ASSERT_X(simulator, Q_FUNC_INFO, "no simulator driver can be created");
|
|
|
|
bool c = connect(simulator, &ISimulator::simulatorStatusChanged, this, &CContextSimulator::ps_onSimulatorStatusChanged);
|
|
Q_ASSERT(c);
|
|
c = connect(simulator, &ISimulator::ownAircraftModelChanged, this, &IContextSimulator::ownAircraftModelChanged);
|
|
Q_ASSERT(c);
|
|
c = connect(simulator, &ISimulator::modelMatchingCompleted, this, &IContextSimulator::modelMatchingCompleted);
|
|
Q_ASSERT(c);
|
|
c = connect(simulator, &ISimulator::installedAircraftModelsChanged, this, &IContextSimulator::installedAircraftModelsChanged);
|
|
Q_ASSERT(c);
|
|
c = connect(simulator, &ISimulator::renderRestrictionsChanged, this, &IContextSimulator::renderRestrictionsChanged);
|
|
Q_ASSERT(c);
|
|
c = connect(simulator, &ISimulator::airspaceSnapshotHandled, this, &IContextSimulator::airspaceSnapshotHandled);
|
|
Q_ASSERT(c);
|
|
|
|
// log from context to simulator
|
|
c = connect(CLogHandler::instance(), &CLogHandler::localMessageLogged, simulator, &ISimulator::displayStatusMessage);
|
|
Q_ASSERT(c);
|
|
c = connect(CLogHandler::instance(), &CLogHandler::remoteMessageLogged, simulator, &ISimulator::displayStatusMessage);
|
|
Q_ASSERT(c);
|
|
Q_UNUSED(c);
|
|
|
|
// use network to initally add aircraft
|
|
IContextNetwork *networkContext = this->getIContextNetwork();
|
|
Q_ASSERT(networkContext);
|
|
Q_ASSERT(networkContext->isLocalObject());
|
|
|
|
// initially add aircraft
|
|
for (const CSimulatedAircraft &simulatedAircraft : networkContext->getAircraftInRange())
|
|
{
|
|
Q_ASSERT(!simulatedAircraft.getCallsign().isEmpty());
|
|
simulator->logicallyAddRemoteAircraft(simulatedAircraft);
|
|
}
|
|
|
|
// when everything is set up connected, update the current plugin info
|
|
m_simulatorPlugin.first = simulatorInfo;
|
|
m_simulatorPlugin.second = simulator;
|
|
|
|
// try to connect to simulator
|
|
simulator->connectTo();
|
|
emit simulatorPluginChanged(simulatorInfo);
|
|
CLogMessage(this).info("Simulator plugin loaded: %1") << simulatorInfo.toQString(true);
|
|
|
|
return true;
|
|
}
|
|
|
|
void CContextSimulator::listenForSimulator(const CSimulatorPluginInfo &simulatorInfo)
|
|
{
|
|
Q_ASSERT(this->getIContextApplication());
|
|
Q_ASSERT(this->getIContextApplication()->isUsingImplementingObject());
|
|
Q_ASSERT(!simulatorInfo.isUnspecified());
|
|
|
|
ISimulator::SimulatorStatus simStatus = getSimulatorStatusEnum();
|
|
if (!m_simulatorPlugin.first.isUnspecified() &&
|
|
m_simulatorPlugin.first == simulatorInfo && simStatus.testFlag(ISimulator::Connected))
|
|
{
|
|
// the simulator is already connected and running
|
|
return;
|
|
}
|
|
|
|
if (!m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
// wrong or disconnected plugin, we start from the scratch
|
|
this->unloadSimulatorPlugin();
|
|
}
|
|
|
|
if (!m_listenersThread.isRunning())
|
|
{
|
|
m_listenersThread.setObjectName("CContextSimulator:Thread for listeners");
|
|
m_listenersThread.start(QThread::LowPriority);
|
|
}
|
|
|
|
ISimulatorListener *listener = m_plugins->createListener(simulatorInfo.getIdentifier());
|
|
Q_ASSERT_X(listener, Q_FUNC_INFO, "No listener");
|
|
|
|
if (listener->thread() != &m_listenersThread)
|
|
{
|
|
bool c = connect(listener, &ISimulatorListener::simulatorStarted, this, &CContextSimulator::ps_simulatorStarted);
|
|
if (!c)
|
|
{
|
|
CLogMessage(this).error("Unable to use '%1'") << simulatorInfo.toQString();
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT_X(!listener->parent(), Q_FUNC_INFO, "Objects with parent cannot be moved to thread");
|
|
listener->setProperty("isInitialized", true);
|
|
listener->moveToThread(&m_listenersThread);
|
|
}
|
|
|
|
bool s = QMetaObject::invokeMethod(listener, "start", Qt::QueuedConnection);
|
|
Q_ASSERT_X(s, Q_FUNC_INFO, "cannot invoke method");
|
|
Q_UNUSED(s);
|
|
}
|
|
|
|
void CContextSimulator::listenForAllSimulators()
|
|
{
|
|
auto plugins = getAvailableSimulatorPlugins();
|
|
for (const CSimulatorPluginInfo &p : plugins)
|
|
{
|
|
Q_ASSERT(!p.isUnspecified());
|
|
|
|
if (p.isValid())
|
|
{
|
|
listenForSimulator(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CContextSimulator::unloadSimulatorPlugin()
|
|
{
|
|
if (!m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
ISimulator *sim = m_simulatorPlugin.second;
|
|
m_simulatorPlugin.second = nullptr;
|
|
m_simulatorPlugin.first = CSimulatorPluginInfo();
|
|
|
|
Q_ASSERT(this->getIContextNetwork());
|
|
Q_ASSERT(this->getIContextNetwork()->isLocalObject());
|
|
|
|
// unload and disconnect
|
|
if (sim)
|
|
{
|
|
// disconnect signals and delete
|
|
sim->unload();
|
|
this->disconnect(sim);
|
|
sim->deleteLater();
|
|
emit simulatorPluginChanged(CSimulatorPluginInfo());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CContextSimulator::ps_addRemoteAircraft(const CSimulatedAircraft &remoteAircraft)
|
|
{
|
|
// todo:
|
|
// This was previously an assert and it should be one again in the future.
|
|
// This slot should not even be called when no simulator is available.
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
// Do something if no simulator is running
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
Q_ASSERT(!remoteAircraft.getCallsign().isEmpty());
|
|
|
|
m_simulatorPlugin.second->logicallyAddRemoteAircraft(remoteAircraft);
|
|
}
|
|
|
|
void CContextSimulator::ps_removedRemoteAircraft(const CCallsign &callsign)
|
|
{
|
|
// \fixme: This was previously an assert and it should be one again in the future.
|
|
// This slot should not even be called when no simulator is available.
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
// Do something if no simulator is running
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->logicallyRemoveRemoteAircraft(callsign);
|
|
}
|
|
|
|
void CContextSimulator::ps_onSimulatorStatusChanged(int status)
|
|
{
|
|
ISimulator::SimulatorStatus statusEnum = ISimulator::statusToEnum(status);
|
|
if (!statusEnum.testFlag(ISimulator::Connected))
|
|
{
|
|
// we got disconnected, plugin no longer needed
|
|
unloadSimulatorPlugin();
|
|
}
|
|
emit simulatorStatusChanged(status);
|
|
}
|
|
|
|
void CContextSimulator::ps_textMessagesReceived(const Network::CTextMessageList &textMessages)
|
|
{
|
|
// todo:
|
|
// This was previously an assert and it should be one again in the future.
|
|
// This slot should not even be called when no simulator is available.
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
// Do something if no simulator is running
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
for (const auto &tm : textMessages)
|
|
{
|
|
m_simulatorPlugin.second->displayTextMessage(tm);
|
|
}
|
|
}
|
|
|
|
void CContextSimulator::ps_cockpitChangedFromSimulator(const CSimulatedAircraft &ownAircraft)
|
|
{
|
|
Q_ASSERT(getIContextOwnAircraft());
|
|
getIContextOwnAircraft()->changedAircraftCockpit(ownAircraft, IContextSimulator::InterfaceName());
|
|
}
|
|
|
|
void CContextSimulator::ps_changedRemoteAircraftModel(const CSimulatedAircraft &aircraft, const CIdentifier &originator)
|
|
{
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->changeRemoteAircraftModel(aircraft, originator);
|
|
}
|
|
|
|
void CContextSimulator::ps_changedRemoteAircraftEnabled(const CSimulatedAircraft &aircraft, const CIdentifier &originator)
|
|
{
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->changeRemoteAircraftEnabled(aircraft, originator);
|
|
}
|
|
|
|
void CContextSimulator::ps_updateSimulatorCockpitFromContext(const CSimulatedAircraft &ownAircraft, const CIdentifier &originator)
|
|
{
|
|
// todo:
|
|
// This was previously an assert and it should be one again in the future.
|
|
// This slot should not even be called when no simulator is available.
|
|
if (m_simulatorPlugin.first.isUnspecified())
|
|
{
|
|
// Do something if no simulator is running
|
|
return;
|
|
}
|
|
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
|
|
// avoid loops
|
|
if (originator.getName().isEmpty() || originator == IContextSimulator::InterfaceName()) { return; }
|
|
|
|
// update
|
|
m_simulatorPlugin.second->updateOwnSimulatorCockpit(ownAircraft, originator);
|
|
}
|
|
|
|
CPixmap CContextSimulator::iconForModel(const QString &modelString) const
|
|
{
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return CPixmap(); }
|
|
Q_ASSERT_X(m_simulatorPlugin.second, Q_FUNC_INFO, "Missing simulator");
|
|
return m_simulatorPlugin.second->iconForModel(modelString);
|
|
}
|
|
|
|
void CContextSimulator::enableDebugMessages(bool driver, bool interpolator)
|
|
{
|
|
if (m_simulatorPlugin.first.isUnspecified()) { return; }
|
|
Q_ASSERT_X(m_simulatorPlugin.second, Q_FUNC_INFO, "Missing simulator");
|
|
return m_simulatorPlugin.second->enableDebugMessages(driver, interpolator);
|
|
}
|
|
|
|
void CContextSimulator::highlightAircraft(const CSimulatedAircraft &aircraftToHighlight, bool enableHighlight, const CTime &displayTime)
|
|
{
|
|
Q_ASSERT(m_simulatorPlugin.second);
|
|
m_simulatorPlugin.second->highlightAircraft(aircraftToHighlight, enableHighlight, displayTime);
|
|
}
|
|
|
|
void CContextSimulator::ps_simulatorStarted(const CSimulatorPluginInfo &info)
|
|
{
|
|
stopSimulatorListeners();
|
|
loadSimulatorPlugin(info, false);
|
|
}
|
|
|
|
void CContextSimulator::stopSimulatorListeners()
|
|
{
|
|
for (const auto &info : getAvailableSimulatorPlugins())
|
|
{
|
|
ISimulatorListener *listener = m_plugins->getListener(info.getIdentifier());
|
|
if(listener) { QMetaObject::invokeMethod(listener, "stop"); }
|
|
}
|
|
}
|
|
|
|
} // namespace
|