6 #include <QApplication>
18 using namespace swift::misc::aviation;
19 using namespace swift::misc::physical_quantities;
20 using namespace swift::misc::geo;
21 using namespace swift::misc::network;
22 using namespace swift::misc::math;
23 using namespace swift::misc::simulation;
24 using namespace swift::misc::simulation::settings;
26 using namespace swift::core::context;
28 namespace swift::simplugin::emulated
33 : CSimulatorPluginCommon(info, ownAircraftProvider, remoteAircraftProvider, clientProvider, parent)
38 this->onSettingsChanged();
43 connect(qApp, &QApplication::aboutToQuit,
this, &CSimulatorEmulated::closeMonitor);
44 connect(
sGui, &CGuiApplication::aboutToShutdown,
this, &CSimulatorEmulated::closeMonitor, Qt::QueuedConnection);
45 connect(&m_interpolatorFetchTimer, &QTimer::timeout,
this, &CSimulatorEmulated::updateRemoteAircraft);
48 this->connectOwnSignals();
56 m_monitorWidget->close();
57 m_monitorWidget->deleteLater();
58 m_monitorWidget.clear();
64 const QPointer<CSimulatorEmulated> myself(
this);
67 this->emitSimulatorCombinedStatus();
68 m_monitorWidget->show();
69 CGuiApplication::modalWindowToFront();
72 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
78 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
79 m_renderedAircraft.
clear();
80 return CSimulatorPluginCommon::disconnectFrom();
85 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
86 CSimulatorPluginCommon::unload();
91 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, remoteAircraft.
toQString()); }
92 return ISimulator::logicallyAddRemoteAircraft(remoteAircraft);
97 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, callsign.
toQString()); }
98 return ISimulator::logicallyRemoveRemoteAircraft(callsign);
103 if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, callsigns.
toQString());
104 return ISimulator::physicallyRemoveMultipleRemoteAircraft(callsigns);
109 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, aircraft.
toQString()); }
110 return ISimulator::changeRemoteAircraftEnabled(aircraft);
115 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, aircraft.
toQString()); }
116 return ISimulator::changeRemoteAircraftEnabled(aircraft);
124 m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, aircraft.
toQString(), originator.
toQString());
126 if (originator ==
identifier()) {
return false; }
147 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, selcal.
toQString(), originator.
toQString()); }
148 if (originator ==
identifier()) {
return false; }
149 if (m_myAircraft.
getSelcal() == selcal) {
return false; }
157 if (!canDisplay()) {
return; }
158 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, message.
toQString()); }
159 m_monitorWidget->displayStatusMessage(message);
164 if (!canDisplay()) {
return; }
165 if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, message.
toQString());
166 m_monitorWidget->displayTextMessage(message);
171 if (canLog()) m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, callsign.
toQString());
177 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
183 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
201 const bool hasRequested = CSimulatorPluginCommon::requestElevation(reference, callsign);
209 const double elvRnd = CMathUtils::randomDouble(1000);
210 const CAltitude alt(elvRnd, CLengthUnit::ft());
215 QPointer<CSimulatorEmulated> myself(
this);
217 if (!myself) {
return; }
220 ISimulator::callbackReceivedRequestedElevation(elv, callsign,
false);
229 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, commandLine, originator.
toQString()); }
230 return CSimulatorPluginCommon::parseCommandLine(commandLine, originator);
235 if (CSimpleCommandParser::registered(
"swift::simplugin::emulated::CSimulatorEmulated")) {
return; }
236 CSimpleCommandParser::registerCommand({
".drv",
"alias: .driver .plugin" });
237 CSimpleCommandParser::registerCommand({
".drv show",
"show emulated driver window" });
238 CSimpleCommandParser::registerCommand({
".drv hide",
"hide emulated driver window" });
243 m_connected = connected;
244 m_simulating = simulating;
251 return m_pluginSettings.
get().getEmulatedSimulator();
256 bool changed =
false;
262 if (!changed) {
return false; }
269 if (m_myAircraft.
getComSystem(unit) == comSystem) {
return false; }
278 if (m_myAircraft.
getSelcal() == selcal) {
return false; }
285 if (m_myAircraft.
getSituation() == situation) {
return false; }
293 if (m_myAircraft.
getParts() == parts) {
return false; }
300 if (timeMs < 1) { m_interpolatorFetchTimer.stop(); }
301 else { m_interpolatorFetchTimer.start(timeMs); }
302 return m_interpolatorFetchTimer.isActive();
309 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
315 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
321 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
327 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, remoteAircraft.
toQString()); }
331 m_interpolators.insert(
342 Q_UNUSED(networkModel)
343 Q_UNUSED(currentModel)
350 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO, callsign.
toQString()); }
351 m_interpolators.remove(callsign);
354 CSimulatorPluginCommon::physicallyRemoveRemoteAircraft(callsign);
360 if (canLog()) { m_monitorWidget->appendReceivingCall(Q_FUNC_INFO); }
361 return ISimulator::physicallyRemoveAllRemoteAircraft();
370 m_monitorWidget->show();
375 m_monitorWidget->hide();
379 return CSimulatorPluginCommon::parseDetails(parser);
382 void CSimulatorEmulated::setObjectName(
const CSimulatorInfo &info)
384 QObject::setObjectName(
"Emulated driver for " + info.
toQString());
385 m_interpolatorFetchTimer.setObjectName(this->objectName() +
":interpolatorFetchTimer");
388 bool CSimulatorEmulated::canLog()
const {
return this->canDisplay() && m_log; }
390 bool CSimulatorEmulated::canDisplay()
const {
return sApp && !
sApp->
isShuttingDown() && m_monitorWidget; }
392 void CSimulatorEmulated::closeMonitor()
394 if (m_monitorWidget) { m_monitorWidget->close(); }
397 void CSimulatorEmulated::onSettingsChanged()
401 m_log = settings.isLoggingFunctionCalls();
407 simulator = CSimulatorInfo::guessDefaultSimulator();
423 const QString sn = simulator.
toQString(
true);
426 QStringLiteral(
"Emulated, but uninstalled '%1'").arg(sn),
false);
432 this->setObjectName(simulator);
435 if (m_monitorWidget) { m_monitorWidget->updateWindowTitleAndUiValues(simulator); }
438 void CSimulatorEmulated::connectOwnSignals()
441 m_connectionGuard.
append(connect(
442 this, &ISimulator::simulatorStatusChanged,
this,
443 [=](SimulatorStatus status) {
444 if (!m_monitorWidget)
return;
445 m_monitorWidget->appendSendingCall(
"simulatorStatusChanged",
448 Qt::QueuedConnection));
450 m_connectionGuard.
append(connect(
451 this, &ISimulator::ownAircraftModelChanged,
this,
453 if (!m_monitorWidget)
return;
454 m_monitorWidget->appendSendingCall(
"ownAircraftModelChanged", model.
toQString());
456 Qt::QueuedConnection));
458 m_connectionGuard.
append(connect(
459 this, &ISimulator::renderRestrictionsChanged,
this,
460 [=](
bool restricted,
bool enabled,
int maxAircraft,
const CLength &maxRenderedDistance) {
461 if (!m_monitorWidget)
return;
462 static const QString params(
"restricted: %1 enabled: %2 max aircraft: %3");
463 m_monitorWidget->appendSendingCall(
464 "renderRestrictionsChanged",
468 Qt::QueuedConnection));
470 m_connectionGuard.
append(connect(
471 this, &ISimulator::interpolationAndRenderingSetupChanged,
this,
473 if (!m_monitorWidget)
return;
474 m_monitorWidget->appendSendingCall(
"interpolationAndRenderingSetupChanged");
476 Qt::QueuedConnection));
478 m_connectionGuard.
append(connect(
479 this, &ISimulator::aircraftRenderingChanged,
this,
481 if (!m_monitorWidget)
return;
482 m_monitorWidget->appendSendingCall(
"aircraftRenderingChanged", aircraft.
toQString());
484 Qt::QueuedConnection));
486 m_connectionGuard.
append(connect(
487 this, &ISimulator::physicallyAddingRemoteModelFailed,
this,
489 if (!m_monitorWidget)
return;
490 m_monitorWidget->appendSendingCall(
"physicallyAddingRemoteModelFailed", aircraft.
toQString());
492 Qt::QueuedConnection));
494 m_connectionGuard.
append(connect(
495 this, &ISimulator::airspaceSnapshotHandled,
this,
497 if (!m_monitorWidget)
return;
498 m_monitorWidget->appendSendingCall(
"airspaceSnapshotHandled");
500 Qt::QueuedConnection));
503 void CSimulatorEmulated::updateRemoteAircraft()
505 const qint64 now = QDateTime::currentMSecsSinceEpoch();
507 uint32_t aircraftNumber = 0;
512 if (!m_interpolators.contains(callsign)) {
continue; }
516 Q_ASSERT_X(im, Q_FUNC_INFO,
"interpolator missing");
520 m_countInterpolatedParts++;
521 m_countInterpolatedSituations++;
535 const QPointer<CSimulatorEmulatedListener> myself(
this);
537 if (!myself) {
return; }
538 Q_ASSERT_X(this->
getPluginInfo().isValid(), Q_FUNC_INFO,
"Invalid plugin");
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
static QString statusToString(SimulatorStatus status)
Status to string.
swift::misc::simulation::settings::CMultiSimulatorSettings m_multiSettings
simulator settings for all simulators
swift::misc::aviation::CAltitude m_pseudoElevation
pseudo elevation for testing purposes
bool updateOwnSituationAndGroundElevation(const swift::misc::aviation::CAircraftSituation &situation)
Update own aircraft position and if suitable use it to update ground elevation.
bool isUpdateAllRemoteAircraft(qint64 currentTimestamp=-1) const
Do update all remote aircraft?
void requestedElevation(const swift::misc::aviation::CCallsign &callsign)
Requested elevation, call pending.
void finishUpdateRemoteAircraftAndSetStatistics(qint64 startTime, bool limited=false)
Update stats and flags.
void emitSimulatorCombinedStatus(SimulatorStatus oldStatus=Unspecified)
Emit the combined status.
void logAddingAircraftModel(const swift::misc::simulation::CSimulatedAircraft &aircraft) const
Unified qeeing aircraft message.
swift::misc::simulation::CInterpolationAndRenderingSetupPerCallsign getInterpolationSetupConsolidated(const swift::misc::aviation::CCallsign &callsign, bool forceFullUpdate) const
Consolidate setup with other data like from swift::misc::simulation::IRemoteAircraftProvider.
swift::misc::simulation::CInterpolationLogger m_interpolationLogger
log.interpolation
void aircraftRenderingChanged(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft rendering changed.
bool m_enablePseudoElevation
return faked elevations (testing)
Interface to a simulator listener.
const swift::misc::simulation::CSimulatorPluginInfo & getPluginInfo() const
Corresponding info.
void simulatorStarted(const swift::misc::simulation::CSimulatorPluginInfo &info)
Emitted when the listener discovers the simulator running.
virtual bool isShuttingDown() const
Overall (swift) application shutting down.
virtual swift::misc::simulation::CSimulatorPluginInfoList getAvailableSimulatorPlugins() const =0
Return list of available simulator plugins.
static QWidget * mainApplicationWidget()
Main application window widget.
T get() const
Get a copy of the current value.
bool append(const QMetaObject::Connection &connection)
Add connection.
const CIdentifier & identifier() const
Get identifier.
Value object encapsulating information identifying a component of a modular distributed swift process...
Class for emitting a log message.
Derived & validationError(const char16_t(&format)[N])
Set the severity to error, providing a format string, and adding the validation category.
void push_back(const T &value)
Appends an element at the end of the sequence.
void clear()
Removes all elements in the sequence.
Utility methods for simple line parsing used with the command line.
bool matchesPart(int index, const QString &toMatch, Qt::CaseSensitivity cs=Qt::CaseInsensitive) const
Matches given part.
bool isKnownCommand() const
Known command?
Streamable status message, e.g.
Status messages, e.g. from Core -> GUI.
Value object encapsulating information of aircraft's parts.
Value object encapsulating information of an aircraft's situation.
Altitude as used in aviation, can be AGL or MSL altitude.
Value object encapsulating information of a callsign.
Value object for a set of callsigns.
void setFrequencyStandby(const physical_quantities::CFrequency &frequency)
Set active frequency.
void setFrequencyActive(const physical_quantities::CFrequency &frequency)
Set active frequency.
swift::misc::physical_quantities::CFrequency getFrequencyStandby() const
Standby frequency.
swift::misc::physical_quantities::CFrequency getFrequencyActive() const
Active frequency.
int removeByCallsign(const CCallsign &callsign)
Remove all objects with callsign.
swift::misc::aviation::CCallsignSet getCallsigns() const
All callsigns.
bool containsCallsign(const CCallsign &callsign) const
Contains callsign?
void setGeodeticHeight(const aviation::CAltitude &height)
Set height (ellipsoidal or geodetic height)
Plane of same elevation, can be a single point or larger area (e.g. airport)
Geodetic coordinate, a position in 3D space relative to the reference geoid.
QString toQString(bool i18n=false) const
Cast as QString.
Value object encapsulating information of a text message.
Direct in memory access to client (network client) data.
Physical unit length (length)
bool isNull() const
Is quantity null?
QString valueRoundedWithUnit(const MU &unit, int digits=-1, bool withGroupSeparator=false, bool i18n=false) const
Value to QString with the given unit, e.g. "5.00m".
Aircraft model (used by another pilot, my models on disk)
InterpolatorMode getInterpolatorMode() const
Interpolator mode.
Value object for interpolator and rendering per callsign.
Multiplexed interpolator which allows switching between modes at runtime.
CInterpolationResult getInterpolation(qint64 currentTimeSinceEpoch, const CInterpolationAndRenderingSetupPerCallsign &setup, uint32_t aircraftNumber)
Get interpolated situation.
CInterpolatorMulti which can be used with QMap/QHash.
bool updateOwnParts(const aviation::CAircraftParts &parts)
Update own parts.
bool updateOwnModel(const swift::misc::simulation::CAircraftModel &model)
Update model.
bool updateCockpit(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
bool updateSelcal(const aviation::CSelcal &selcal, const swift::misc::CIdentifier &originator)
Update cockpit, but only send signals when applicable.
CSimulatedAircraft getOwnAircraft() const
Own aircraft.
IRemoteAircraftProvider * getRemoteAircraftProvider() const
Get the aircraft provider.
bool updateAircraftRendered(const aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
Comprehensive information of an aircraft.
const aviation::CSelcal getSelcal() const
SELCAL.
const aviation::CAircraftSituation & getSituation() const
Get situation.
void setCockpit(const CSimulatedAircraft &aircraft)
Set COM unit (all values + transponder and SELCAL)
const aviation::CComSystem & getCom2System() const
Get COM2 system.
const aviation::CTransponder & getTransponder() const
Get transponder.
void setSelcal(const aviation::CSelcal &selcal)
Own SELCAL code.
bool setRendered(bool rendered)
Rendered?
void setSituation(const aviation::CAircraftSituation &situation)
Set situation. Won't overwrite the velocity unless it held the default value.
void setCom1System(const aviation::CComSystem &comSystem)
Set COM1 system.
const simulation::CAircraftModel & getNetworkModel() const
Get network model.
const aviation::CCallsign & getCallsign() const
Get callsign.
void setComSystem(const aviation::CComSystem &com, aviation::CComSystem::ComUnit unit)
Set COM unit.
const simulation::CAircraftModel & getModel() const
Get model (model used for mapping)
aviation::CComSystem getComSystem(aviation::CComSystem::ComUnit unit) const
Get COM unit.
void setParts(const aviation::CAircraftParts &parts)
Set aircraft parts.
void setCom2System(const aviation::CComSystem &comSystem)
Set COM2 system.
const aviation::CComSystem & getCom1System() const
Get COM1 system.
const aviation::CAircraftParts & getParts() const
Get aircraft parts.
int setAircraftSituation(const aviation::CCallsign &callsign, const aviation::CAircraftSituation &situation, bool onlyFirst=true)
Set aircraft situation.
int setAircraftPartsSynchronized(const aviation::CCallsign &callsign, const aviation::CAircraftParts &parts, bool onlyFirst=true)
Set aircraft parts and mark as synchronized.
Simple hardcoded info about the corresponding simulator.
bool isSingleSimulator() const
Single simulator selected.
Describing a simulator plugin.
bool isValid() const
Check if the provided plugin metadata is valid. Simulator plugin (driver) has to meet the following r...
Value object encapsulating a list of SimulatorInfo objects.
CSimulatorPluginInfo findBySimulator(const swift::misc::simulation::CSimulatorInfo &simulator) const
Find by simulator.
CInterpolationAndRenderingSetupPerCallsign getInterpolationSetupPerCallsignOrDefault(const aviation::CCallsign &callsign) const
Get the setup for callsign, if not existing the global setup.
Direct threadsafe in memory access to own aircraft.
Direct thread safe in memory access to remote aircraft.
void setNewPluginInfo(const CSimulatorPluginInfo &info, const settings::CSimulatorSettings &settings, const CAircraftModel &defaultModel)
New plugin info and default model.
CSimulatorSettings getSettings(const CSimulatorInfo &simulator) const
Settings per simulator.
virtual bool updateOwnSimulatorSelcal(const swift::misc::aviation::CSelcal &selcal, const swift::misc::CIdentifier &originator)
Update own aircraft cockpit (usually from context)
bool isInterpolatorFetching() const
Is fetching from interpolator.
virtual bool testSendSituationAndParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftSituation &situation, const swift::misc::aviation::CAircraftParts &parts)
Send situation/parts for testing.
virtual bool changeRemoteAircraftModel(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Change remote aircraft per property.
swift::misc::simulation::CSimulatorInfo getEmulatedSimulator() const
The emulated simulated simulator.
virtual bool disconnectFrom()
Disconnect from simulator.
virtual bool physicallyAddRemoteAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
Add new remote aircraft physically to the simulator.
void internalAircraftChanged()
Internal aircraft changed.
virtual swift::misc::aviation::CCallsignSet physicallyRenderedAircraft() const
Physically rendered (displayed in simulator) This shall only return aircraft handled in the simulator...
virtual bool connectTo()
Connect to simulator.
virtual bool updateOwnSimulatorCockpit(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
Update own aircraft cockpit (usually from context)
virtual swift::misc::CStatusMessageList getInterpolationMessages(const swift::misc::aviation::CCallsign &callsign) const
Interpolation messages for callsign.
virtual bool logicallyRemoveRemoteAircraft(const swift::misc::aviation::CCallsign &callsign)
Logically remove remote aircraft from simulator. Depending on max. aircraft, enabled status etc....
virtual bool requestElevation(const swift::misc::geo::ICoordinateGeodetic &reference, const swift::misc::aviation::CCallsign &callsign)
Request elevation, there is no guarantee the requested elevation will be available in the provider.
bool changeInternalSituation(const swift::misc::aviation::CAircraftSituation &situation)
Simulator internal change of situation.
friend class CSimulatorEmulatedMonitorDialog
the monitor widget represents the simulator and needs access to internals (i.e.
virtual void displayTextMessage(const swift::misc::network::CTextMessage &message) const
Display a text message.
bool changeInternalCom(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Simulator internal change of COM values.
virtual bool isSimulating() const
Simulator running?
bool setInterpolatorFetchTime(int timeMs)
Interpolator fetch time, <=0 stops.
virtual void unload()
Driver will be unloaded.
virtual bool parseDetails(const swift::misc::CSimpleCommandParser &parser)
Parsed in derived classes.
static void registerHelp()
Register help.
bool changeInternalParts(const swift::misc::aviation::CAircraftParts &parts)
Simulator internal change of parts.
virtual ~CSimulatorEmulated()
Destructor.
virtual int physicallyRemoveMultipleRemoteAircraft(const swift::misc::aviation::CCallsignSet &callsigns)
Remove remote aircraft from simulator.
bool changeInternalSelcal(const swift::misc::aviation::CSelcal &selcal)
Simulator internal change of SELCAL.
virtual bool changeRemoteAircraftEnabled(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft got enabled / disabled.
virtual bool logicallyAddRemoteAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
Logically add a new aircraft. Depending on max. aircraft, enabled status etc. it will physically adde...
virtual bool physicallyRemoveRemoteAircraft(const swift::misc::aviation::CCallsign &callsign)
Remove remote aircraft from simulator.
virtual bool isConnected() const
Are we connected to the simulator?
virtual bool isPaused() const
Simulator paused?
virtual bool isPhysicallyRenderedAircraft(const swift::misc::aviation::CCallsign &callsign) const
Is the aircraft rendered (displayed in simulator)? This shall only return true if the aircraft is rea...
virtual void displayStatusMessage(const swift::misc::CStatusMessage &message) const
Display a status message in the simulator.
void setCombinedStatus(bool connected, bool simulating, bool paused)
UI setter.
virtual int physicallyRemoveAllRemoteAircraft()
Remove all remote aircraft and their data via ISimulator::clearAllRemoteAircraftData.
virtual void startImpl()
Plugin specific implementation to start listener.
CSimulatorEmulatedListener(const swift::misc::simulation::CSimulatorPluginInfo &info)
Constructor.
virtual void checkImpl()
Plugin specific implementation to stop listener.
virtual void stopImpl()
Plugin specific implementation to stop listener.
virtual bool parseCommandLine(const QString &commandLine, const swift::misc::CIdentifier &originator)
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Backend services of the swift project, like dealing with the network or the simulators.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
const std::string & boolToYesNo(bool t)
Yes/no from bool.