From f8bebf5ffa76765b652038463e80c18777433b94 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Fri, 20 Feb 2015 03:14:49 +0100 Subject: [PATCH] refs #386, performance issues * keep split per callsign map in IInterpolator (so it is available for all interpolators) * Interpolator using CWorker, so it can run in background * added signals to provider to add split situations / callsigns * adjustments to airspace / context for those signals * thread safe access to those from interpolator * renamed from rendered to remote aircraft as discussed * adjust samples * removed no longer required functions in timestampobjectlist * changed connectioStatusChanged from uint -> int --- samples/blackmisc/samplesperformance.cpp | 17 +- src/blackcore/airspace_monitor.cpp | 58 +++--- src/blackcore/airspace_monitor.h | 73 ++++--- src/blackcore/context_network.h | 2 +- src/blackcore/context_network_impl.cpp | 47 +++-- src/blackcore/context_network_impl.h | 53 +++-- src/blackcore/context_network_proxy.cpp | 2 +- src/blackcore/context_simulator_impl.cpp | 2 +- src/blackcore/interpolator.cpp | 174 +++++++++++++++++ src/blackcore/interpolator.h | 87 +++++++-- src/blackcore/interpolator_linear.cpp | 27 ++- src/blackcore/interpolator_linear.h | 14 +- src/blackcore/simulator.cpp | 4 +- src/blackcore/simulator.h | 8 +- src/blackgui/components/aircraftcomponent.cpp | 2 +- src/blackgui/components/aircraftcomponent.h | 2 +- src/blackmisc/avcallsignobjectlist.cpp | 4 +- src/blackmisc/avcallsignobjectlist.h | 4 +- .../simdirectaccessremoteaircraft.cpp | 86 +++++++++ .../simdirectaccessremoteaircraft.h | 149 ++++++++++++++ .../simdirectaccessrenderedaircraft.cpp | 85 -------- .../simdirectaccessrenderedaircraft.h | 126 ------------ src/blackmisc/timestampobjectlist.h | 181 ++++++------------ src/plugins/simulator/fs9/fs9_client.cpp | 17 +- src/plugins/simulator/fs9/fs9_client.h | 7 +- src/plugins/simulator/fs9/simulator_fs9.cpp | 21 +- src/plugins/simulator/fs9/simulator_fs9.h | 10 +- .../simulator/fscommon/simulator_fscommon.cpp | 2 +- .../simulator/fscommon/simulator_fscommon.h | 2 +- src/plugins/simulator/fsx/simulator_fsx.cpp | 108 ++++++----- src/plugins/simulator/fsx/simulator_fsx.h | 7 +- .../simulator/fsx/simulator_fsxfactory.cpp | 2 +- .../simulator/fsx/simulator_fsxfactory.h | 2 +- .../simulator/xplane/simulator_xplane.cpp | 18 +- .../simulator/xplane/simulator_xplane.h | 6 +- src/swiftgui_standard/swiftguistd.cpp | 3 +- src/swiftgui_standard/swiftguistd.h | 6 +- 37 files changed, 835 insertions(+), 583 deletions(-) create mode 100644 src/blackcore/interpolator.cpp create mode 100644 src/blackmisc/simulation/simdirectaccessremoteaircraft.cpp create mode 100644 src/blackmisc/simulation/simdirectaccessremoteaircraft.h delete mode 100644 src/blackmisc/simulation/simdirectaccessrenderedaircraft.cpp delete mode 100644 src/blackmisc/simulation/simdirectaccessrenderedaircraft.h diff --git a/samples/blackmisc/samplesperformance.cpp b/samples/blackmisc/samplesperformance.cpp index f410d879d..016d9736f 100644 --- a/samples/blackmisc/samplesperformance.cpp +++ b/samples/blackmisc/samplesperformance.cpp @@ -208,7 +208,7 @@ namespace BlackMiscTest out << "Reads by times / callsigns: " << timer.elapsed() << "ms" << endl; timer.start(); - QMap splitList = situations.splitPerCallsign(); + QHash splitList = situations.splitPerCallsign(); Q_ASSERT(splitList.size() == numberOfCallsigns); for (int t = 0; t < numberOfTimes; t++) { @@ -310,21 +310,8 @@ namespace BlackMiscTest } out << "Single, pre-sorted split by time upfront, then callsigns: " << timer.elapsed() << "ms" << endl; - situations.sortOldestFirst(); // eliminate impact of sort timer.start(); - split = situations.splitByTimeNoSortAscendingTimestamp(halfTime); - for (int cs = 0; cs < numberOfCallsigns; cs++) - { - CCallsign callsign("CS" + QString::number(cs)); - CAircraftSituationList csSituationsBefore = split[0].findByCallsign(callsign); - CAircraftSituationList csSituationsAfter = split[1].findByCallsign(callsign); - Q_UNUSED(csSituationsBefore); - Q_UNUSED(csSituationsAfter); - } - out << "Single, unsorted split by time upfront, then callsigns: " << timer.elapsed() << "ms" << endl; - - timer.start(); - QMap csSituations = situations.splitPerCallsign(); + QHash csSituations = situations.splitPerCallsign(); out << "Split by " << csSituations.size() << " callsigns, " << timer.elapsed() << "ms" << endl; timer.start(); diff --git a/src/blackcore/airspace_monitor.cpp b/src/blackcore/airspace_monitor.cpp index ddf3fe9f3..36da8afbe 100644 --- a/src/blackcore/airspace_monitor.cpp +++ b/src/blackcore/airspace_monitor.cpp @@ -27,7 +27,8 @@ namespace BlackCore { CAirspaceMonitor::CAirspaceMonitor(QObject *parent, const BlackMisc::Simulation::IOwnAircraftProviderReadOnly *ownAircraftProvider, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile) - : QObject(parent), COwnAircraftProviderSupportReadOnly(ownAircraftProvider), + : QObject(parent), + COwnAircraftProviderSupportReadOnly(ownAircraftProvider), m_network(network), m_vatsimBookingReader(bookings), m_vatsimDataFileReader(dataFile), m_atcWatchdog(this), m_aircraftWatchdog(this) { @@ -59,28 +60,28 @@ namespace BlackCore this->connect(&this->m_atcWatchdog, &CAirspaceWatchdog::timeout, this, &CAirspaceMonitor::ps_atcControllerDisconnected); } - const CSimulatedAircraftList &CAirspaceMonitor::renderedAircraft() const + const CSimulatedAircraftList &CAirspaceMonitor::remoteAircraft() const { // not thread safe, check Q_ASSERT(this->thread() == QThread::currentThread()); return m_aircraftInRange; } - CSimulatedAircraftList &CAirspaceMonitor::renderedAircraft() + CSimulatedAircraftList &CAirspaceMonitor::remoteAircraft() { // not thread safe, check Q_ASSERT(this->thread() == QThread::currentThread()); return m_aircraftInRange; } - const CAircraftSituationList &CAirspaceMonitor::renderedAircraftSituations() const + const CAircraftSituationList &CAirspaceMonitor::remoteAircraftSituations() const { // not thread safe, check Q_ASSERT(this->thread() == QThread::currentThread()); return m_aircraftSituations; } - CAircraftSituationList &CAirspaceMonitor::renderedAircraftSituations() + CAircraftSituationList &CAirspaceMonitor::remoteAircraftSituations() { // not thread safe, check Q_ASSERT(this->thread() == QThread::currentThread()); @@ -89,26 +90,18 @@ namespace BlackCore CAircraftSituationList CAirspaceMonitor::getRenderedAircraftSituations() const { - if (this->thread() == QThread::currentThread()) { return this->m_aircraftSituations; } - CAircraftSituationList situations; - bool s = QMetaObject::invokeMethod(const_cast(this), // strip away const, invoke will not change anything, - "getRenderedAircraftSituations", - Qt::BlockingQueuedConnection, - Q_RETURN_ARG(CAircraftSituationList, situations) - ); - Q_ASSERT(s); - Q_UNUSED(s); - return situations; + Q_ASSERT(this->thread() == QThread::currentThread()); + return this->m_aircraftSituations; } - const CAircraftPartsList &CAirspaceMonitor::renderedAircraftParts() const + const CAircraftPartsList &CAirspaceMonitor::remoteAircraftParts() const { // not thread safe, check Q_ASSERT(this->thread() == QThread::currentThread()); return m_aircraftParts; } - CAircraftPartsList &CAirspaceMonitor::renderedAircraftParts() + CAircraftPartsList &CAirspaceMonitor::remoteAircraftParts() { // not thread safe, check Q_ASSERT(this->thread() == QThread::currentThread()); @@ -117,16 +110,20 @@ namespace BlackCore CAircraftPartsList CAirspaceMonitor::getRenderedAircraftParts() const { - if (this->thread() == QThread::currentThread()) { return this->m_aircraftParts; } - CAircraftPartsList parts; - bool s = QMetaObject::invokeMethod(const_cast(this), // strip away const, invoke will not change anything - "getRenderedAircraftParts", - Qt::BlockingQueuedConnection, - Q_RETURN_ARG(CAircraftPartsList, parts) - ); - Q_ASSERT(s); - Q_UNUSED(s); - return parts; + Q_ASSERT(this->thread() == QThread::currentThread()); + return this->m_aircraftParts; + } + + bool CAirspaceMonitor::connectRemoteAircraftProviderSignals( + std::function situationSlot, + std::function partsSlot, + std::function removedAircraftSlot + ) + { + bool s1 = connect(this, &CAirspaceMonitor::addedRemoteAircraftSituation, situationSlot); + bool s2 = connect(this, &CAirspaceMonitor::addedRemoteAircraftParts, partsSlot); + bool s3 = connect(this, &CAirspaceMonitor::removedAircraft, removedAircraftSlot); + return s1 && s2 && s3; } bool CAirspaceMonitor::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRedering, const QString &originator) @@ -738,7 +735,7 @@ namespace BlackCore CAircraftSituation situationWithCallsign(situation); situationWithCallsign.setCallsign(callsign); this->m_aircraftSituations.insert(situationWithCallsign); - this->m_aircraftSituations.removeOlderThanNowMinusOffset(30000); + this->m_aircraftSituations.removeOlderThanNowMinusOffset(AircraftSituationsRemovedOffsetMs); bool exists = this->m_aircraftInRange.containsCallsign(callsign); if (!exists) @@ -811,6 +808,7 @@ namespace BlackCore this->m_aircraftWatchdog.resetCallsign(callsign); } + emit this->addedRemoteAircraftSituation(situationWithCallsign); emit this->changedAircraftInRange(); } @@ -852,13 +850,15 @@ namespace BlackCore CAircraftParts parts = m_aircraftParts.findBackByCallsign(callsign); parts.setCurrentUtcTime(); - parts.setCallsign(callsign); + parts.setCallsign(callsign); // for default values + // update QJsonObject config = applyIncrementalObject(parts.toJson(), incremental); parts.convertFromJson(config); // store part history this->m_aircraftParts.insert(parts); + emit this->addedRemoteAircraftParts(parts); CPropertyIndexVariantMap vm; vm.addValue(CAircraft::IndexParts, parts); diff --git a/src/blackcore/airspace_monitor.h b/src/blackcore/airspace_monitor.h index 2a0909a33..86f6c48ed 100644 --- a/src/blackcore/airspace_monitor.h +++ b/src/blackcore/airspace_monitor.h @@ -14,7 +14,7 @@ #include "blackmisc/simulation/simulatedaircraftlist.h" #include "blackmisc/simulation/simdirectaccessownaircraft.h" -#include "blackmisc/simulation/simdirectaccessrenderedaircraft.h" +#include "blackmisc/simulation/simdirectaccessremoteaircraft.h" #include "blackmisc/avatcstationlist.h" #include "blackmisc/avaircraftsituationlist.h" #include "blackmisc/nwclientlist.h" @@ -34,37 +34,38 @@ namespace BlackCore */ class CAirspaceMonitor : public QObject, - public BlackMisc::Simulation::COwnAircraftProviderSupportReadOnly, - public BlackMisc::Simulation::IRenderedAircraftProvider + public BlackMisc::Simulation::IRemoteAircraftProvider, // those data will be provided from the class CAirspaceMonitor + public BlackMisc::Simulation::COwnAircraftProviderSupportReadOnly // used to obtain in memory inofmration about own aircraft { Q_OBJECT + Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider) public: //! Constructor CAirspaceMonitor(QObject *parent, const BlackMisc::Simulation::IOwnAircraftProviderReadOnly *ownAircraft, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile); - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraft - virtual const BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() const override; + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + virtual const BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() const override; - //! \copydoc IRenderedAircraftProvider::renderedAircraft - virtual BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() override; + //! \copydoc IRemoteAircraftProvider::renderedAircraft + virtual BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() override; - //! \copydoc IRenderedAircraftProvider::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const override; + //! \copydoc IRemoteAircraftProvider::remoteAircraftSituations + virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override; - //! \copydoc IRenderedAircraftProvider::renderedAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() override; + //! \copydoc IRemoteAircraftProvider::remoteAircraftSituations + virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override; - //! \copydoc IRenderedAircraftProvider::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const override; + //! \copydoc IRemoteAircraftProvider::remoteAircraftParts + virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override; - //! \copydoc IRenderedAircraftProvider::renderedAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() override; + //! \copydoc IRemoteAircraftProvider::remoteAircraftParts + virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override; - //! \copydoc IRenderedAircraftProvider::renderedAircraftParts + //! \copydoc IRemoteAircraftProvider::remoteAircraftParts virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) override; - //! \copydoc IRenderedAircraftProvider::updateAircraftModel + //! \copydoc IRemoteAircraftProvider::updateAircraftModel virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator) override; //! Returns the list of users we know about @@ -107,14 +108,35 @@ namespace BlackCore //! Create dummy entries for performance tests void testCreateDummyOnlineAtcStations(int number); - public slots: - //! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const override; + //! Aircraft situations + virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const; - //! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const override; + //! Aircraft parts + virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const; + + //! \copydoc IRemoteAircraftProviderReadOnly::connectSignals + //! \copydoc IRemoteAircraftProviderReadOnly::connectSignals + virtual bool connectRemoteAircraftProviderSignals( + std::function situationSlot, + std::function partsSlot, + std::function removedAircraftSlot + ) override; + + const qint64 AircraftSituationsRemovedOffsetMs = 30 * 1000; //!< situations will be removed if older than signals: + + //--- signals for the provider, work locally only (not in DBus + + //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation + void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) override; + + //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart + void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts) override; + + //! \copydoc IRemoteAircraftProviderReadOnly::removedAircraft + void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override; + //! Online ATC stations were changed void changedAtcStationsOnline(); @@ -128,13 +150,10 @@ namespace BlackCore void changedAircraftInRange(); //! A new aircraft appeared - void addedAircraft(const BlackMisc::Simulation::CSimulatedAircraft &renderedAircraft); - - //! An aircraft disappeared - void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign); + void addedAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft); //! Read for model matching - void readyForModelMatching(const BlackMisc::Simulation::CSimulatedAircraft &renderedAircraft); + void readyForModelMatching(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft); private: BlackMisc::Aviation::CAtcStationList m_atcStationsOnline; diff --git a/src/blackcore/context_network.h b/src/blackcore/context_network.h index 52eafeaae..7f16f8eca 100644 --- a/src/blackcore/context_network.h +++ b/src/blackcore/context_network.h @@ -117,7 +117,7 @@ namespace BlackCore * \remarks If I use the enum, adaptor / interface are not created correctly * \see INetwork::ConnectionStatus */ - void connectionStatusChanged(uint from, uint to); + void connectionStatusChanged(int from, int to); //! Text messages received (also private chat messages, rfaio channel messages) void textMessagesReceived(const BlackMisc::Network::CTextMessageList &textMessages); diff --git a/src/blackcore/context_network_impl.cpp b/src/blackcore/context_network_impl.cpp index 6f905044e..30893a62f 100644 --- a/src/blackcore/context_network_impl.cpp +++ b/src/blackcore/context_network_impl.cpp @@ -78,6 +78,8 @@ namespace BlackCore connect(this->m_airspace, &CAirspaceMonitor::changedAircraftInRange, this, &CContextNetwork::changedAircraftInRange); connect(this->m_airspace, &CAirspaceMonitor::removedAircraft, this, &CContextNetwork::removedAircraft); connect(this->m_airspace, &CAirspaceMonitor::readyForModelMatching, this, &CContextNetwork::readyForModelMatching); + connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftParts, this, &CContextNetwork::addedRemoteAircraftParts); + connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftSituation, this, &CContextNetwork::addedRemoteAircraftSituation); } CContextNetwork::~CContextNetwork() @@ -85,52 +87,49 @@ namespace BlackCore this->gracefulShutdown(); } - const CSimulatedAircraftList &CContextNetwork::renderedAircraft() const + const CSimulatedAircraftList &CContextNetwork::remoteAircraft() const { Q_ASSERT(this->m_airspace); - return m_airspace->renderedAircraft(); + return m_airspace->remoteAircraft(); } - CSimulatedAircraftList &CContextNetwork::renderedAircraft() + CSimulatedAircraftList &CContextNetwork::remoteAircraft() { Q_ASSERT(this->m_airspace); - return m_airspace->renderedAircraft(); + return m_airspace->remoteAircraft(); } - CAircraftSituationList &CContextNetwork::renderedAircraftSituations() + CAircraftSituationList &CContextNetwork::remoteAircraftSituations() { Q_ASSERT(this->m_airspace); - return m_airspace->renderedAircraftSituations(); + return m_airspace->remoteAircraftSituations(); } - CAircraftSituationList CContextNetwork::getRenderedAircraftSituations() const + const CAircraftSituationList &CContextNetwork::remoteAircraftSituations() const { Q_ASSERT(this->m_airspace); - return m_airspace->getRenderedAircraftSituations(); + return m_airspace->remoteAircraftSituations(); } - const CAircraftSituationList &CContextNetwork::renderedAircraftSituations() const + const CAircraftPartsList &CContextNetwork::remoteAircraftParts() const { Q_ASSERT(this->m_airspace); - return m_airspace->renderedAircraftSituations(); + return m_airspace->remoteAircraftParts(); } - const CAircraftPartsList &CContextNetwork::renderedAircraftParts() const + CAircraftPartsList &CContextNetwork::remoteAircraftParts() { Q_ASSERT(this->m_airspace); - return m_airspace->renderedAircraftParts(); + return m_airspace->remoteAircraftParts(); } - CAircraftPartsList &CContextNetwork::renderedAircraftParts() + bool CContextNetwork::connectRemoteAircraftProviderSignals( + std::function situationSlot, + std::function partsSlot, + std::function removedAircraftSlot) { Q_ASSERT(this->m_airspace); - return m_airspace->renderedAircraftParts(); - } - - CAircraftPartsList CContextNetwork::getRenderedAircraftParts() const - { - Q_ASSERT(this->m_airspace); - return m_airspace->getRenderedAircraftParts(); + return this->m_airspace->connectRemoteAircraftProviderSignals(situationSlot, partsSlot, removedAircraftSlot); } void CContextNetwork::gracefulShutdown() @@ -359,13 +358,13 @@ namespace BlackCore CSimulatedAircraftList CContextNetwork::getAircraftInRange() const { BlackMisc::CLogMessage(this, BlackMisc::CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; - return this->m_airspace->renderedAircraft(); + return this->m_airspace->remoteAircraft(); } CSimulatedAircraft CContextNetwork::getAircraftForCallsign(const CCallsign &callsign) const { BlackMisc::CLogMessage(this, BlackMisc::CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign; - return this->m_airspace->renderedAircraft().findFirstByCallsign(callsign); + return this->m_airspace->remoteAircraft().findFirstByCallsign(callsign); } void CContextNetwork::ps_receivedBookings(const CAtcStationList &) @@ -400,7 +399,7 @@ namespace BlackCore bool c = this->m_airspace->updateAircraftEnabled(callsign, enabledForRedering, originator); if (c) { - emit this->changedAircraftEnabled(this->renderedAircraft().findFirstByCallsign(callsign), originator); + emit this->changedAircraftEnabled(this->remoteAircraft().findFirstByCallsign(callsign), originator); } return c; } @@ -411,7 +410,7 @@ namespace BlackCore bool c = this->m_airspace->updateAircraftModel(callsign, model, originator); if (c) { - emit this->changedRenderedAircraftModel(this->renderedAircraft().findFirstByCallsign(callsign), originator); + emit this->changedRenderedAircraftModel(this->remoteAircraft().findFirstByCallsign(callsign), originator); } return c; } diff --git a/src/blackcore/context_network_impl.h b/src/blackcore/context_network_impl.h index e117ad457..8f8cecbaa 100644 --- a/src/blackcore/context_network_impl.h +++ b/src/blackcore/context_network_impl.h @@ -15,7 +15,7 @@ #include "blackcore/context_network.h" #include "blackcore/context_settings.h" #include "blackcore/context_runtime.h" -#include "blackmisc/simulation/simdirectaccessrenderedaircraft.h" +#include "blackmisc/simulation/simdirectaccessremoteaircraft.h" #include "blackcore/dbus_server.h" #include "blackcore/network.h" #include "blackcore/airspace_monitor.h" @@ -37,10 +37,12 @@ namespace BlackCore //! Network context implementation class CContextNetwork : public IContextNetwork, - public BlackMisc::Simulation::IRenderedAircraftProvider + public BlackMisc::Simulation::IRemoteAircraftProvider { Q_OBJECT + Q_INTERFACES(BlackMisc::Simulation::IRemoteAircraftProvider) Q_CLASSINFO("D-Bus Interface", BLACKCORE_CONTEXTNETWORK_INTERFACENAME) + friend class IContextNetwork; friend class CRuntime; @@ -48,26 +50,45 @@ namespace BlackCore //! Destructor virtual ~CContextNetwork(); - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraft - virtual const BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() const override; + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + virtual const BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() const override; //! \copydoc IRenderedAircraftProvider::renderedAircraft - virtual BlackMisc::Simulation::CSimulatedAircraftList &renderedAircraft() override; + virtual BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() override; - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const override; + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations + virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override; - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() override; + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations + virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override; - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const override; + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts + virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override; //! \copydoc IRenderedAircraftProvider::renderedAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() override; + virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override; + + //! \copydoc IRemoteAircraftProviderReadOnly::connectSignals + virtual bool connectRemoteAircraftProviderSignals( + std::function situationSlot, + std::function partsSlot, + std::function removedAircraftSlot + ) override; + + signals: + // IRemoteAircraftProviderReadOnly must be implemented by concrete class + // must not prefixed virtual (though they are) -> warning + + //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation + void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) override; + + //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart + void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts) override; + + //! \copydoc IRemoteAircraftProviderReadOnly::removedAircraft + void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override; public slots: - //! \copydoc IContextNetwork::readAtcBookingsFromSource() virtual void readAtcBookingsFromSource() const override; @@ -83,12 +104,6 @@ namespace BlackCore //! \copydoc IContextNetwork::getAircraftForCallsign virtual BlackMisc::Simulation::CSimulatedAircraft getAircraftForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const override; - //! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const override; - - //! \copydoc IRenderedAircraftProviderReadOnly::getRenderedAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const override; - //! \copydoc IContextNetwork::connectToNetwork() virtual BlackMisc::CStatusMessage connectToNetwork(const BlackMisc::Network::CServer &server, uint mode) override; diff --git a/src/blackcore/context_network_proxy.cpp b/src/blackcore/context_network_proxy.cpp index b298e42ba..43c7995fc 100644 --- a/src/blackcore/context_network_proxy.cpp +++ b/src/blackcore/context_network_proxy.cpp @@ -37,7 +37,7 @@ namespace BlackCore void CContextNetworkProxy::relaySignals(const QString &serviceName, QDBusConnection &connection) { bool s = connection.connect(serviceName, IContextNetwork::ObjectPath(), IContextNetwork::InterfaceName(), - "connectionStatusChanged", this, SIGNAL(connectionStatusChanged(uint, uint))); + "connectionStatusChanged", this, SIGNAL(connectionStatusChanged(int, int))); Q_ASSERT(s); s = connection.connect(serviceName, IContextNetwork::ObjectPath(), IContextNetwork::InterfaceName(), "changedAtcStationsBooked", this, SIGNAL(changedAtcStationsBooked())); diff --git a/src/blackcore/context_simulator_impl.cpp b/src/blackcore/context_simulator_impl.cpp index d41fa0f3d..09a8abfd6 100644 --- a/src/blackcore/context_simulator_impl.cpp +++ b/src/blackcore/context_simulator_impl.cpp @@ -210,7 +210,7 @@ namespace BlackCore Q_ASSERT(this->getIContextOwnAircraft()->isUsingImplementingObject()); Q_ASSERT(this->getIContextNetwork()->isUsingImplementingObject()); IOwnAircraftProvider *ownAircraftProvider = this->getRuntime()->getCContextOwnAircraft(); - IRenderedAircraftProvider *renderedAircraftProvider = this->getRuntime()->getCContextNetwork(); + IRemoteAircraftProvider *renderedAircraftProvider = this->getRuntime()->getCContextNetwork(); ISimulator *newSimulator = factory->create(ownAircraftProvider, renderedAircraftProvider, this); Q_ASSERT(newSimulator); diff --git a/src/blackcore/interpolator.cpp b/src/blackcore/interpolator.cpp new file mode 100644 index 000000000..899a319e3 --- /dev/null +++ b/src/blackcore/interpolator.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2015 + * 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 "interpolator.h" +#include "blackmisc/logmessage.h" +#include + +using namespace BlackMisc; +using namespace BlackMisc::Aviation; +using namespace BlackMisc::Simulation; + + +namespace BlackCore +{ + + IInterpolator::IInterpolator(IRemoteAircraftProviderReadOnly *provider, const QString &workerName, QObject *parent) : + CContinuousWorker(parent, workerName), + CRemoteAircraftProviderSupportReadOnly(provider) + { + Q_ASSERT(provider); + this->m_situationsByCallsign = this->remoteAircraftSituations().splitPerCallsign(); + this->m_partsByCallsign = this->remoteAircraftParts().splitPerCallsign(); + bool c = provider->connectRemoteAircraftProviderSignals( + std::bind(&IInterpolator::ps_onAddedAircraftSituation, this, std::placeholders::_1), + std::bind(&IInterpolator::ps_onAddedAircraftParts, this, std::placeholders::_1), + std::bind(&IInterpolator::ps_onRemoveAircraft, this, std::placeholders::_1) + ); + Q_ASSERT(c); + Q_UNUSED(c); + } + + QList IInterpolator::getSituationsTimeSplit(const CCallsign &callsign, qint64 splitTimeMsSinceEpoch) const + { + QReadLocker l(&m_situationsLock); + static const QList empty({ CAircraftSituationList(), CAircraftSituationList() }); + if (!this->m_situationsByCallsign.contains(callsign)) { return empty; } + return this->m_situationsByCallsign[callsign].splitByTime(splitTimeMsSinceEpoch); + } + + bool IInterpolator::hasEnoughAircraftSituations(const CCallsign &callsign) const + { + QReadLocker l(&m_situationsLock); + if (!this->m_situationsByCallsign.contains(callsign)) { return false; } + return this->m_situationsByCallsign[callsign].findBeforeNowMinusOffset(TimeOffsetMs).size() > 0; + } + + CAircraftParts IInterpolator::getLatestPartsBeforeOffset(const CCallsign &callsign, qint64 timeOffset, bool *ok) const + { + QReadLocker l(&m_partsLock); + static const CAircraftParts empty; + if (ok) { *ok = false; } + if (this->m_partsByCallsign.contains(callsign)) { return empty; } + CAircraftPartsList partsList = this->m_partsByCallsign[callsign].findBeforeNowMinusOffset(timeOffset); + l.unlock(); + if (partsList.isEmpty()) { return empty; } + if (ok) { *ok = true; } + return partsList.latestValue(); + } + + void IInterpolator::requestSituationsCalculationsForAllCallsigns(int requestId) + { + QReadLocker l(&m_situationsLock); + Q_ASSERT(requestId >= 0); + const QHash situationsCopy = m_situationsByCallsign; + l.unlock(); + + CAircraftSituationList latestInterpolations; + for (const CCallsign &cs : situationsCopy.keys()) + { + bool ok; + CAircraftSituation situation = getCurrentInterpolatedSituation(situationsCopy, cs, &ok); + if (ok) + { + latestInterpolations.push_back(situation); + } + else + { + // not OK can mean not enough situations + // further logging could go here + } + } + + QWriteLocker wl(&m_requestedInterpolationsLock); + while (m_requestedInterpolations.size() >= MaxKeptInterpolationRequests - 1) + { + m_requestedInterpolations.erase(--m_requestedInterpolations.end()); + } + m_requestedInterpolations.insert(requestId, latestInterpolations); // new to old + + } + + QHash IInterpolator::getSituationsByCallsign() const + { + QReadLocker l(&m_requestedInterpolationsLock); + return m_situationsByCallsign; + } + + int IInterpolator::latestFinishedRequestId() const + { + QReadLocker l(&m_requestedInterpolationsLock); + if (m_requestedInterpolations.isEmpty()) { return -1; } + return m_requestedInterpolations.keys().first(); + } + + CAircraftSituationList IInterpolator::latestFinishedRequest() const + { + QReadLocker l(&m_requestedInterpolationsLock); + static const CAircraftSituationList empty; + if (m_requestedInterpolations.isEmpty()) { return empty; } + return m_requestedInterpolations.values().first(); + } + + CAircraftSituationList IInterpolator::getRequest(int requestId, bool *ok) const + { + QReadLocker l(&m_requestedInterpolationsLock); + static const CAircraftSituationList empty; + if (!m_requestedInterpolations.contains(requestId)) + { + if (ok) { *ok = false; } + return empty; + } + if (ok) { *ok = true; } + return m_requestedInterpolations[requestId]; + } + + void IInterpolator::ps_onAddedAircraftSituation(const CAircraftSituation &situation) + { + QWriteLocker lock(&m_situationsLock); + Q_ASSERT(!situation.getCallsign().isEmpty()); + if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << situation; } + + // list from new to old + CAircraftSituationList &l = this->m_situationsByCallsign[situation.getCallsign()]; + if (l.size() >= MaxSituationsPerCallsign - 1) + { + l.truncate(MaxSituationsPerCallsign - 1); + } + l.insert(situation); + } + + void IInterpolator::ps_onAddedAircraftParts(const CAircraftParts &parts) + { + QWriteLocker lock(&m_partsLock); + Q_ASSERT(!parts.getCallsign().isEmpty()); + if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << parts; } + + // list from new to old + CAircraftPartsList &l = this->m_partsByCallsign[parts.getCallsign()]; + if (l.size() >= MaxPartsPerCallsign - 1) + { + l.truncate(MaxPartsPerCallsign - 1); + } + l.insert(parts); + } + + void IInterpolator::ps_onRemoveAircraft(const CCallsign &callsign) + { + QWriteLocker ls(&m_situationsLock); + QWriteLocker lp(&m_partsLock); + Q_ASSERT(!callsign.isEmpty()); + if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign; } + + if (callsign.isEmpty()) { return; } + this->m_partsByCallsign.remove(callsign); + this->m_situationsByCallsign.remove(callsign); + } + +} // namespace diff --git a/src/blackcore/interpolator.h b/src/blackcore/interpolator.h index abb403bfc..84e601308 100644 --- a/src/blackcore/interpolator.h +++ b/src/blackcore/interpolator.h @@ -13,33 +13,98 @@ #define BLACKCORE_INTERPOLATOR_H #include "blackmisc/avaircraftsituation.h" +#include "blackmisc/simulation/simdirectaccessremoteaircraft.h" +#include "blackmisc/worker.h" #include "simulator.h" +#include +#include namespace BlackCore { //! Interpolator, calculation inbetween positions - class IInterpolator + class IInterpolator : + public BlackMisc::CContinuousWorker, + public BlackMisc::Simulation::CRemoteAircraftProviderSupportReadOnly { - public: + Q_OBJECT + public: //! Virtual destructor virtual ~IInterpolator() {} //! Has situations? - virtual bool hasEnoughAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const - { - Q_ASSERT(m_provider); - //! \todo Interpolator, it would be more efficient to directly getting the values and decide then - return m_provider->renderedAircraftSituations().findBeforeNowMinusOffset(6000).findByCallsign(callsign).size() > 1; - } + //! \deprecated Try no to use, it would be more efficient to directly getting the values and decide then + //! \threadsafe + virtual bool hasEnoughAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const; //! Current interpolated situation - virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + //! \threadsafe + virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const QHash &allSituations, const BlackMisc::Aviation::CCallsign &callsign, bool *ok = nullptr) const = 0; + + //! Latest parts before time - offset + //! \threadsafe + BlackMisc::Aviation::CAircraftParts getLatestPartsBeforeOffset(const BlackMisc::Aviation::CCallsign &callsign, qint64 timeOffset = TimeOffsetMs, bool *ok = nullptr) const; + + //! Do a complete calculation for all know callsigns in background. + //! Only use positive numbers. + //! \threadsafe + void requestSituationsCalculationsForAllCallsigns(int requestId); + + //! The situations per callsign + //! \threadsafe + QHash getSituationsByCallsign() const; + + //! Last finished request id, -1 means none + //! \threadsafe + int latestFinishedRequestId() const; + + //! Latest calculation + //! \threadsafe + BlackMisc::Aviation::CAircraftSituationList latestFinishedRequest() const; + + //! Calculation by id + //! \threadsafe + BlackMisc::Aviation::CAircraftSituationList getRequest(int requestId, bool *ok = nullptr) const; + + static const qint64 TimeOffsetMs = 6000; //!< offset for interpolation + static const int MaxSituationsPerCallsign = 6; //!< How many situations per callsign + static const int MaxPartsPerCallsign = 3; //!< How many parts per callsign + static const int MaxKeptInterpolationRequests = 3; //!< How many requests are stored + + private slots: + //! New situation got added + //! \threadsafe + void ps_onAddedAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + + //! Added aircraft parts + //! \threadsafe + void ps_onAddedAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts); + + //! Removed aircraft + //! \threadsafe + void ps_onRemoveAircraft(const BlackMisc::Aviation::CCallsign &callsign); protected: //! Constructor - IInterpolator(BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *provider) : m_provider(provider) { Q_ASSERT(provider);} - BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *m_provider = nullptr; //!< access to provider + IInterpolator(BlackMisc::Simulation::IRemoteAircraftProviderReadOnly *provider, const QString &workerName, QObject *parent = nullptr); + + //! Situations for times before / after + //! \sa ITimestampObjectList::splitByTime + //! \threadsafe + //! \deprecated For first version + QList getSituationsTimeSplit(const BlackMisc::Aviation::CCallsign &callsign, qint64 splitTimeMsSinceEpoch) const; + + bool m_withDebugMsg = true; + + private: + mutable QReadWriteLock m_situationsLock; + mutable QReadWriteLock m_partsLock; + mutable QReadWriteLock m_requestedInterpolationsLock; + + // hashs, because not sorted by key but keeping order + QHash m_situationsByCallsign; + QHash m_partsByCallsign; + QHash m_requestedInterpolations; }; } // namespace diff --git a/src/blackcore/interpolator_linear.cpp b/src/blackcore/interpolator_linear.cpp index 77db2ecb2..1001ae461 100644 --- a/src/blackcore/interpolator_linear.cpp +++ b/src/blackcore/interpolator_linear.cpp @@ -18,13 +18,18 @@ using namespace BlackMisc::Aviation; namespace BlackCore { - CAircraftSituation CInterpolatorLinear::getCurrentInterpolatedSituation(const CCallsign &callsign) const + CAircraftSituation CInterpolatorLinear::getCurrentInterpolatedSituation(const QHash &allSituations, const CCallsign &callsign, bool *ok) const { - QDateTime currentTime = QDateTime::currentDateTimeUtc().addSecs(-6); - CAircraftSituationList situationsBefore = renderedAircraftSituations().findBefore(currentTime).findByCallsign(callsign); - CAircraftSituationList situationsAfter = renderedAircraftSituations().findAfter(currentTime).findByCallsign(callsign); - - Q_ASSERT_X(!situationsBefore.isEmpty(), "CInterpolatorLinear::getCurrentSituation()", "List previous situations is empty!"); + const static CAircraftSituation empty; + qint64 splitTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch() - TimeOffsetMs; + QList splitSituations = allSituations[callsign].splitByTime(splitTimeMsSinceEpoch); + CAircraftSituationList &situationsBefore = splitSituations[0]; + CAircraftSituationList &situationsAfter = splitSituations[1]; + if (situationsBefore.isEmpty()) + { + if (ok) { *ok = false; } + return empty; + } CAircraftSituation beginSituation; CAircraftSituation endSituation; @@ -49,7 +54,7 @@ namespace BlackCore double deltaTime = beginSituation.msecsToAbs(endSituation); // Fraction of the deltaTime [0.0 - 1.0] - double simulationTimeFraction = beginSituation.getUtcTimestamp().msecsTo(currentTime) / deltaTime; + double simulationTimeFraction = (beginSituation.getMSecsSinceEpoch() - splitTimeMsSinceEpoch) / deltaTime; // Interpolate latitude: Lat = (LatB - LatA) * t + LatA currentPosition.setLatitude((endSituation.getPosition().latitude() - beginSituation.getPosition().latitude()) @@ -73,10 +78,14 @@ namespace BlackCore CHeading headingEnd = endSituation.getHeading(); if ((headingEnd - headingBegin).value(CAngleUnit::deg()) < -180) + { headingEnd += CHeading(360, CHeading::Magnetic, CAngleUnit::deg()); + } if ((headingEnd - headingBegin).value(CAngleUnit::deg()) > 180) + { headingEnd -= CHeading(360, CHeading::Magnetic, CAngleUnit::deg()); + } currentSituation.setHeading(CHeading((headingEnd - headingBegin) * simulationTimeFraction @@ -86,7 +95,6 @@ namespace BlackCore // Interpolate Pitch: Pitch = (PitchB - PitchA) * t + PitchA CAngle pitchBegin = beginSituation.getPitch(); CAngle pitchEnd = endSituation.getPitch(); - CAngle pitch = (pitchEnd - pitchBegin) * simulationTimeFraction + pitchBegin; // TODO: According to the specification, pitch above horizon should be negative. @@ -97,7 +105,6 @@ namespace BlackCore // Interpolate bank: Bank = (BankB - BankA) * t + BankA CAngle bankBegin = beginSituation.getBank(); CAngle bankEnd = endSituation.getBank(); - CAngle bank = (bankEnd - bankBegin) * simulationTimeFraction + bankBegin; // TODO: According to the specification, banks to the right should be negative. @@ -108,7 +115,7 @@ namespace BlackCore currentSituation.setGroundspeed((endSituation.getGroundSpeed() - beginSituation.getGroundSpeed()) * simulationTimeFraction + beginSituation.getGroundSpeed()); - + if (ok) { *ok = true; } return currentSituation; } diff --git a/src/blackcore/interpolator_linear.h b/src/blackcore/interpolator_linear.h index ca9d640be..561cf021a 100644 --- a/src/blackcore/interpolator_linear.h +++ b/src/blackcore/interpolator_linear.h @@ -20,19 +20,17 @@ namespace BlackCore { - //! \brief Linear interpolator, calculation inbetween positions - class CInterpolatorLinear : - public IInterpolator, - public BlackMisc::Simulation::CRenderedAircraftProviderSupportReadOnly + //! Linear interpolator, calculation inbetween positions + class CInterpolatorLinear : public IInterpolator { public: //! Constructor - CInterpolatorLinear(BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *provider) : - IInterpolator(provider), - BlackMisc::Simulation::CRenderedAircraftProviderSupportReadOnly(provider) {} + CInterpolatorLinear(BlackMisc::Simulation::IRemoteAircraftProviderReadOnly *provider, QObject *parent = nullptr) : + IInterpolator(provider, "CInterpolatorLinear", parent) + {} //! \copydoc IInterpolator::getCurrentInterpolatedSituation - virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const BlackMisc::Aviation::CCallsign &callsign) const override; + virtual BlackMisc::Aviation::CAircraftSituation getCurrentInterpolatedSituation(const QHash &allSituations, const BlackMisc::Aviation::CCallsign &callsign, bool *ok = nullptr) const override; }; } // namespace BlackCore diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index 03ae5e83b..282c931f8 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -19,8 +19,8 @@ namespace BlackCore emit simulatorStatusChanged(isConnected(), isSimulating(), isPaused()); } - CSimulatorCommon::CSimulatorCommon(const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) - : ISimulator(parent), COwnAircraftProviderSupport(ownAircraftProvider), CRenderedAircraftProviderSupport(renderedAircraftProvider), m_simulatorInfo(simInfo) + CSimulatorCommon::CSimulatorCommon(const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent) + : ISimulator(parent), COwnAircraftProviderSupport(ownAircraftProvider), CRemoteAircraftProviderSupport(remoteAircraftProvider), m_simulatorInfo(simInfo) { } int CSimulatorCommon::getMaxRenderedAircraft() const diff --git a/src/blackcore/simulator.h b/src/blackcore/simulator.h index 6334f9fa7..2f8be5716 100644 --- a/src/blackcore/simulator.h +++ b/src/blackcore/simulator.h @@ -16,7 +16,7 @@ #include "blackmisc/simulation/simulatedaircraftlist.h" #include "blackmisc/simulation/aircraftmodellist.h" #include "blackmisc/simulation/simdirectaccessownaircraft.h" -#include "blackmisc/simulation/simdirectaccessrenderedaircraft.h" +#include "blackmisc/simulation/simdirectaccessremoteaircraft.h" #include "blackmisc/statusmessagelist.h" #include "blackmisc/avairportlist.h" #include "blackmisc/nwtextmessage.h" @@ -177,7 +177,7 @@ namespace BlackCore //! virtual ISimulator *create( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent = nullptr) = 0; //! Simulator info @@ -188,7 +188,7 @@ namespace BlackCore class CSimulatorCommon : public BlackCore::ISimulator, public BlackMisc::Simulation::COwnAircraftProviderSupport, // gain access to in memor own aircraft data - public BlackMisc::Simulation::CRenderedAircraftProviderSupport // gain access to in memory rendered aircraft data + public BlackMisc::Simulation::CRemoteAircraftProviderSupport // gain access to in memory rendered aircraft data { public: @@ -206,7 +206,7 @@ namespace BlackCore CSimulatorCommon( const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent = nullptr); BlackSim::CSimulatorInfo m_simulatorInfo; //!< about the simulator diff --git a/src/blackgui/components/aircraftcomponent.cpp b/src/blackgui/components/aircraftcomponent.cpp index 73880123b..de9a485c6 100644 --- a/src/blackgui/components/aircraftcomponent.cpp +++ b/src/blackgui/components/aircraftcomponent.cpp @@ -110,7 +110,7 @@ namespace BlackGui this->tabBar()->setTabText(ap, aps); } - void CAircraftComponent::ps_connectionStatusChanged(uint from, uint to) + void CAircraftComponent::ps_connectionStatusChanged(int from, int to) { INetwork::ConnectionStatus fromStatus = static_cast(from); INetwork::ConnectionStatus toStatus = static_cast(to); diff --git a/src/blackgui/components/aircraftcomponent.h b/src/blackgui/components/aircraftcomponent.h index 01a93a455..43c03db88 100644 --- a/src/blackgui/components/aircraftcomponent.h +++ b/src/blackgui/components/aircraftcomponent.h @@ -74,7 +74,7 @@ namespace BlackGui void ps_onRowCountChanged(int count, bool withFilter); //! Connection status has been changed - void ps_connectionStatusChanged(uint from, uint to); + void ps_connectionStatusChanged(int from, int to); private: QScopedPointer ui; diff --git a/src/blackmisc/avcallsignobjectlist.cpp b/src/blackmisc/avcallsignobjectlist.cpp index 169e1477d..0bf54747b 100644 --- a/src/blackmisc/avcallsignobjectlist.cpp +++ b/src/blackmisc/avcallsignobjectlist.cpp @@ -100,11 +100,11 @@ namespace BlackMisc } template - QMap ICallsignObjectList::splitPerCallsign() const + QHash ICallsignObjectList::splitPerCallsign() const { CONTAINER copyContainer(getContainer()); copyContainer.sortByCallsign(); - QMap result; + QHash result; CCallsign cs; for (const OBJ &csObj : copyContainer) { diff --git a/src/blackmisc/avcallsignobjectlist.h b/src/blackmisc/avcallsignobjectlist.h index 92af08291..96eb27dd8 100644 --- a/src/blackmisc/avcallsignobjectlist.h +++ b/src/blackmisc/avcallsignobjectlist.h @@ -18,7 +18,7 @@ #include "blackmisc/propertyindexlist.h" #include "blackmisc/propertyindexvariantmap.h" #include -#include +#include namespace BlackMisc { @@ -58,7 +58,7 @@ namespace BlackMisc QMap getSuffixes() const; //! Split into 0..n containers as per callsign - QMap splitPerCallsign() const; + QHash splitPerCallsign() const; //! Sort by callsign void sortByCallsign(); diff --git a/src/blackmisc/simulation/simdirectaccessremoteaircraft.cpp b/src/blackmisc/simulation/simdirectaccessremoteaircraft.cpp new file mode 100644 index 000000000..e073defb8 --- /dev/null +++ b/src/blackmisc/simulation/simdirectaccessremoteaircraft.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2015 + * 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 "simdirectaccessremoteaircraft.h" + +using namespace BlackMisc::Aviation; + +namespace BlackMisc +{ + namespace Simulation + { + + const CSimulatedAircraftList &CRemoteAircraftProviderSupportReadOnly::remoteAircraft() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraft", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraft(); + } + + const Aviation::CAircraftSituationList &CRemoteAircraftProviderSupportReadOnly::remoteAircraftSituations() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftSituations", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituations(); + } + + const Aviation::CAircraftPartsList &CRemoteAircraftProviderSupportReadOnly::remoteAircraftParts() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftParts", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftParts(); + } + + const CSimulatedAircraftList &CRemoteAircraftProviderSupport::remoteAircraft() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraft", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraft(); + } + + CSimulatedAircraftList &CRemoteAircraftProviderSupport::remoteAircraft() + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraft", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraft(); + } + + const CAircraftSituationList &CRemoteAircraftProviderSupport::remoteAircraftSituations() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftSituations", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituations(); + } + + CAircraftSituationList &CRemoteAircraftProviderSupport::remoteAircraftSituations() + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftSituations", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituations(); + } + + const CAircraftPartsList &CRemoteAircraftProviderSupport::remoteAircraftParts() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftParts", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftParts(); + } + + CAircraftPartsList &CRemoteAircraftProviderSupport::remoteAircraftParts() + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftParts", "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftParts(); + } + + bool CRemoteAircraftProviderSupport::providerUpdateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const QString &originator) + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "providerUpdateAircraftModel", "No object available"); + return this->m_remoteAircraftProvider->updateAircraftModel(callsign, model, originator); + } + + bool CRemoteAircraftProviderSupport::providerUpdateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) + { + Q_ASSERT_X(this->m_remoteAircraftProvider, "providerUpdateAircraftEnabled", "No object available"); + return this->m_remoteAircraftProvider->updateAircraftEnabled(callsign, enabledForRedering, originator); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/simulation/simdirectaccessremoteaircraft.h b/src/blackmisc/simulation/simdirectaccessremoteaircraft.h new file mode 100644 index 000000000..8026aba67 --- /dev/null +++ b/src/blackmisc/simulation/simdirectaccessremoteaircraft.h @@ -0,0 +1,149 @@ +/* Copyright (C) 2015 + * 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. + */ + +//! \file + +#ifndef BLACKMISC_SIMDIRECTACCESSREMOTEAIRCRAFT_H +#define BLACKMISC_SIMDIRECTACCESSREMOTEAIRCRAFT_H + +#include "blackmisc/simulation/simulatedaircraftlist.h" +#include "blackmisc/avaircraftsituationlist.h" +#include "blackmisc/aviation/aircraftpartslist.h" +#include + +namespace BlackMisc +{ + namespace Simulation + { + //! Direct in memory access to remote aircraft + //! \note Can not be derived from QObject (as for the signals), as this would create multiple + //! inheritance. Hence Q_DECLARE_INTERFACE is used. + class IRemoteAircraftProviderReadOnly + { + public: + //! All rendered aircraft + virtual const CSimulatedAircraftList &remoteAircraft() const = 0; + + //! All situation (per callsign, time history) + virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const = 0; + + //! All parts (per callsign, time history) + virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const = 0; + + //! Destructor + virtual ~IRemoteAircraftProviderReadOnly() {} + + //! Connect signals to slot receiver. As the interface is no QObject, slots can not be connected directly. + virtual bool connectRemoteAircraftProviderSignals( + std::function situationSlot, + std::function partsSlot, + std::function removedAircraftSlot + ) = 0; + + // those signals have to be implemented by classes using the interface. + signals: + //! A new situation got added + virtual void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) = 0; + + //! New parts got added + virtual void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts) = 0; + + //! Aircraft was removed + virtual void removedAircraft(const BlackMisc::Aviation::CCallsign &callsign) = 0; + + }; + + //! Direct in memory access to own aircraft + class IRemoteAircraftProvider : public IRemoteAircraftProviderReadOnly + { + public: + //! All rendered aircraft + //! \note in memory reference, not thread safe + virtual CSimulatedAircraftList &remoteAircraft() = 0; + + //! Rendered aircraft situations (history) + virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() = 0; + + //! All parts (per callsign, time history) + //! \note in memory reference, not thread safe + virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() = 0; + + //! Enable/disable rendering + virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) = 0; + + //! Change model string + virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator) = 0; + }; + + //! Class which can be directly used providing access to such an interface + class CRemoteAircraftProviderSupportReadOnly + { + public: + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + virtual const CSimulatedAircraftList &remoteAircraft() const; + + //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations + virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const; + + //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts + virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const; + + //! Destructor + virtual ~CRemoteAircraftProviderSupportReadOnly() {} + + protected: + //! Constructor + CRemoteAircraftProviderSupportReadOnly(const IRemoteAircraftProviderReadOnly *remoteAircraftProvider) : m_remoteAircraftProvider(remoteAircraftProvider) {} + const IRemoteAircraftProviderReadOnly *m_remoteAircraftProvider = nullptr; //!< access to object + }; + + //! Delegating class which can be directly used providing access to such an interface + class CRemoteAircraftProviderSupport + { + public: + //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + virtual const CSimulatedAircraftList &remoteAircraft() const; + + //! \copydoc IRemoteAircraftProvider::renderedAircraft + virtual CSimulatedAircraftList &remoteAircraft(); + + //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations + virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const; + + //!\copydoc IRemoteAircraftProvider::remoteAircraftSituations + virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations(); + + //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts + virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const; + + //!\copydoc IRemoteAircraftProvider::remoteAircraftParts + virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts(); + + //! \copydoc IRemoteAircraftProvider::updateAircraftEnabled + virtual bool providerUpdateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator); + + //! \copydoc IRemoteAircraftProvider::updateAircraftModel + virtual bool providerUpdateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator); + + //! Destructor + virtual ~CRemoteAircraftProviderSupport() {} + + protected: + //! Constructor + CRemoteAircraftProviderSupport(IRemoteAircraftProvider *remoteAircraftProvider) : m_remoteAircraftProvider(remoteAircraftProvider) { Q_ASSERT(remoteAircraftProvider); } + IRemoteAircraftProvider *m_remoteAircraftProvider = nullptr; //!< access to object + }; + + } // namespace +} // namespace + +Q_DECLARE_INTERFACE(BlackMisc::Simulation::IRemoteAircraftProviderReadOnly, "IRemoteAircraftProviderReadOnly") +Q_DECLARE_INTERFACE(BlackMisc::Simulation::IRemoteAircraftProvider, "IRemoteAircraftProvider") + +#endif // guard diff --git a/src/blackmisc/simulation/simdirectaccessrenderedaircraft.cpp b/src/blackmisc/simulation/simdirectaccessrenderedaircraft.cpp deleted file mode 100644 index 8102b0401..000000000 --- a/src/blackmisc/simulation/simdirectaccessrenderedaircraft.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 2015 - * 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 "simdirectaccessrenderedaircraft.h" - -using namespace BlackMisc::Aviation; - -namespace BlackMisc -{ - namespace Simulation - { - const CSimulatedAircraftList &CRenderedAircraftProviderSupportReadOnly::renderedAircraft() const - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraft", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraft(); - } - - const Aviation::CAircraftSituationList &CRenderedAircraftProviderSupportReadOnly::renderedAircraftSituations() const - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraftSituations", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraftSituations(); - } - - const Aviation::CAircraftPartsList &CRenderedAircraftProviderSupportReadOnly::renderedAircraftParts() const - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraftParts", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraftParts(); - } - - const CSimulatedAircraftList &CRenderedAircraftProviderSupport::renderedAircraft() const - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraft", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraft(); - } - - CSimulatedAircraftList &CRenderedAircraftProviderSupport::renderedAircraft() - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraft", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraft(); - } - - const CAircraftSituationList &CRenderedAircraftProviderSupport::renderedAircraftSituations() const - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraftSituations", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraftSituations(); - } - - CAircraftSituationList &CRenderedAircraftProviderSupport::renderedAircraftSituations() - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraftSituations", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraftSituations(); - } - - const CAircraftPartsList &CRenderedAircraftProviderSupport::renderedAircraftParts() const - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraftParts", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraftParts(); - } - - CAircraftPartsList &CRenderedAircraftProviderSupport::renderedAircraftParts() - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "renderedAircraftParts", "No object available"); - return this->m_renderedAircraftProvider->renderedAircraftParts(); - } - - bool CRenderedAircraftProviderSupport::providerUpdateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const QString &originator) - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "providerUpdateAircraftModel", "No object available"); - return this->m_renderedAircraftProvider->updateAircraftModel(callsign, model, originator); - } - - bool CRenderedAircraftProviderSupport::providerUpdateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) - { - Q_ASSERT_X(this->m_renderedAircraftProvider, "providerUpdateAircraftEnabled", "No object available"); - return this->m_renderedAircraftProvider->updateAircraftEnabled(callsign, enabledForRedering, originator); - } - - } // namespace -} // namespace diff --git a/src/blackmisc/simulation/simdirectaccessrenderedaircraft.h b/src/blackmisc/simulation/simdirectaccessrenderedaircraft.h deleted file mode 100644 index 487cc693b..000000000 --- a/src/blackmisc/simulation/simdirectaccessrenderedaircraft.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2015 - * 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. - */ - -//! \file - -#ifndef BLACKMISC_SIMDIRECTACCESSRENDEREDAIRCRAFT_H -#define BLACKMISC_SIMDIRECTACCESSRENDEREDAIRCRAFT_H - -#include "blackmisc/simulation/simulatedaircraftlist.h" -#include "blackmisc/avaircraftsituationlist.h" -#include "blackmisc/aviation/aircraftpartslist.h" - -namespace BlackMisc -{ - namespace Simulation - { - //! Direct in memory access to rendered aircraft - class IRenderedAircraftProviderReadOnly - { - public: - //! All rendered aircraft - virtual const CSimulatedAircraftList &renderedAircraft() const = 0; - - //! All situation (per callsign, time history) - virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const = 0; - - //! Rendered aircraft situations (history) as copy - //! \threadsafe - virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const = 0; - - //! All parts (per callsign, time history) - virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const = 0; - - //! All parts (per callsign, time history) as copy - //! \threadsafe - virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const = 0; - - //! Destructor - virtual ~IRenderedAircraftProviderReadOnly() {} - }; - - //! Direct in memory access to own aircraft - class IRenderedAircraftProvider : public IRenderedAircraftProviderReadOnly - { - public: - //! All rendered aircraft - //! \note in memory reference, not thread safe - virtual CSimulatedAircraftList &renderedAircraft() = 0; - - //! Rendered aircraft situations (history) - virtual BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() = 0; - - //! All parts (per callsign, time history) - //! \note in memory reference, not thread safe - virtual BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() = 0; - - //! Enable/disable rendering - virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) = 0; - - //! Change model string - virtual bool updateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator) = 0; - }; - - //! Class which can be directly used providing access to such an interface - class CRenderedAircraftProviderSupportReadOnly - { - public: - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraft - virtual const CSimulatedAircraftList &renderedAircraft() const; - - //!\copydoc IRenderedAircraftProviderReadOnly::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const; - - //!\copydoc IRenderedAircraftProviderReadOnly::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const; - - protected: - //! Constructor - CRenderedAircraftProviderSupportReadOnly(const IRenderedAircraftProviderReadOnly *renderedAircraftProvider) : m_renderedAircraftProvider(renderedAircraftProvider) {} - const IRenderedAircraftProviderReadOnly *m_renderedAircraftProvider = nullptr; //!< access to object - }; - - //! Delegating class which can be directly used providing access to such an interface - class CRenderedAircraftProviderSupport - { - public: - //! \copydoc IRenderedAircraftProviderReadOnly::renderedAircraft - virtual const CSimulatedAircraftList &renderedAircraft() const; - - //! \copydoc IRenderedAircraftProvider::renderedAircraft - virtual CSimulatedAircraftList &renderedAircraft(); - - //!\copydoc IRenderedAircraftProviderReadOnly::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations() const; - - //!\copydoc IRenderedAircraftProvider::renderedAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &renderedAircraftSituations(); - - //!\copydoc IRenderedAircraftProviderReadOnly::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts() const; - - //!\copydoc IRenderedAircraftProvider::renderedAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &renderedAircraftParts(); - - //! \copydoc IRenderedAircraftProvider::updateAircraftEnabled - virtual bool providerUpdateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator); - - //! \copydoc IRenderedAircraftProvider::updateAircraftModel - virtual bool providerUpdateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator); - - protected: - //! Constructor - CRenderedAircraftProviderSupport(IRenderedAircraftProvider *renderedAircraftProvider) : m_renderedAircraftProvider(renderedAircraftProvider) { Q_ASSERT(renderedAircraftProvider); } - IRenderedAircraftProvider *m_renderedAircraftProvider = nullptr; //!< access to object - }; - - } // namespace -} // namespace - -#endif // guard diff --git a/src/blackmisc/timestampobjectlist.h b/src/blackmisc/timestampobjectlist.h index 9801276a2..60f721484 100644 --- a/src/blackmisc/timestampobjectlist.h +++ b/src/blackmisc/timestampobjectlist.h @@ -1,5 +1,5 @@ /* Copyright (C) 2015 - * swift Project Community / Contributors + * 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, @@ -7,146 +7,79 @@ * contained in the LICENSE file. */ -#include "blackmisc/timestampobjectlist.h" -#include "blackmisc/predicates.h" -#include "blackmisc/avaircraftsituationlist.h" -#include "blackmisc/aviation/aircraftpartslist.h" -#include -#include +//! \file + +#ifndef BLACKMISC_TIMESTAMPOBJECTLIST_H +#define BLACKMISC_TIMESTAMPOBJECTLIST_H + +#include "blackmisc/collection.h" +#include "blackmisc/sequence.h" +#include +#include namespace BlackMisc { - template - ITimestampObjectList::ITimestampObjectList() - { } - - template - CONTAINER ITimestampObjectList::findBefore(qint64 msSinceEpoch) const + //! List of objects with timestamp. + //! Such objects should implement \sa ITimestampBased + template + class ITimestampObjectList { - return this->container().findBy([&](const OBJ & obj) - { - return obj.isOlderThan(msSinceEpoch); - }); - } + public: - template - CONTAINER ITimestampObjectList::findBeforeNowMinusOffset(qint64 msOffset) const - { - return this->findBefore(QDateTime::currentMSecsSinceEpoch() - msOffset); - } + //! List of objects before dateTime + CONTAINER findBefore(const QDateTime &dateTime) const; - template - CONTAINER ITimestampObjectList::findBefore(const QDateTime &dateTime) const - { - return this->findBefore(dateTime.toMSecsSinceEpoch()); - } + //! List of objects before msSinceEpoch + CONTAINER findBefore(qint64 msSinceEpoch) const; - template - CONTAINER ITimestampObjectList::findAfter(qint64 msSinceEpoc) const - { - return this->container().findBy([&](const OBJ & obj) - { - return obj.isNewerThan(msSinceEpoc); - }); - } + //! List of objects before now - offset + CONTAINER findBeforeNowMinusOffset(qint64 msOffset) const; - template - QList ITimestampObjectList::splitByTime(qint64 msSinceEpoch) const - { - CONTAINER newer(this->container()); - newer.sortLatestFirst(); - CONTAINER older; - for (auto it = newer.begin(); it != newer.end(); ++it) - { - if (it->isOlderThan(msSinceEpoch)) - { - // better "move", ?? std::make_move_iterator - older.insert(CRange(it, newer.end())); - newer.erase(it, newer.end()); - break; - } - } + //! List of objects after dateTime + CONTAINER findAfter(const QDateTime &dateTime) const; - // before / after - return QList({newer, older}); - } + //! List of objects after msSinceEpoch + CONTAINER findAfter(qint64 msSinceEpoch) const; - template - OBJ ITimestampObjectList::latestValue() const - { - if (this->container().isEmpty()) { return OBJ(); } - CONTAINER container(container()); // copy - container.sortLatestFirst(); - return container.front(); - } + //! Split into 2 containers, [0] >= msSinceEpoch ("newer") [b] < msSinceEpoch ("older") + //! \note Sort order: latest elements first + QList splitByTime(qint64 msSinceEpoch) const; - template - OBJ ITimestampObjectList::oldestValue() const - { - if (this->container().isEmpty()) { return OBJ(); } - CONTAINER container(container()); // copy - container.sortLatestFirst(); - return container.back(); - } + //! Latest value + OBJ latestValue() const; - template - CONTAINER ITimestampObjectList::findAfter(const QDateTime &dateTime) const - { - return this->findAfter(dateTime.toMSecsSinceEpoch()); - } + //! Latest value + OBJ oldestValue() const; - template - void ITimestampObjectList::removeBefore(const QDateTime &dateTime) - { - this->removeBefore(dateTime.toMSecsSinceEpoch()); - } + //! Remove objects with timestamp before dateTime + void removeBefore(const QDateTime &dateTime); - template - void ITimestampObjectList::removeBefore(qint64 msSinceEpoc) - { - this->container().removeIf([&](const OBJ & obj) - { - return obj.isOlderThan(msSinceEpoc); - }); - } + //! Remove objects with timestamp before dateTime + void removeBefore(qint64 msSinceEpoch); - template - void ITimestampObjectList::removeOlderThanNowMinusOffset(int offsetMs) - { - const qint64 epoch = QDateTime::currentMSecsSinceEpoch() - offsetMs; - this->container().removeIf([&](const OBJ & obj) - { - return obj.isOlderThan(epoch); - }); - } + //! Remove objects older than seconds + void removeOlderThanNowMinusOffset(int offsetMs); - template - void ITimestampObjectList::sortLatestFirst() - { - this->container().sortOldestFirst(); - std::reverse(this->container().begin(), this->container().end()); - } + //! Sort by timestamp + void sortLatestFirst(); - template - void ITimestampObjectList::sortOldestFirst() - { - this->container().sort(BlackMisc::Predicates::MemberLess(&OBJ::getMSecsSinceEpoch)); - } + //! Sort by timestamp + void sortOldestFirst(); - template - void ITimestampObjectList::insertTimestampObject(const OBJ &object, int maxElements) - { - Q_ASSERT(maxElements > 1); - if (this->container().size() >= (maxElements - 1)) - { - this->container().truncate(maxElements - 1); - } - this->container().insert_front(object); - } + //! Inserts as first object by keeping max. elements + void insertTimestampObject(const OBJ &object, int maxElements); - // see here for the reason of thess forward instantiations - // http://www.parashift.com/c++-faq/separate-template-class-defn-from-decl.html - template class ITimestampObjectList; - template class ITimestampObjectList; + protected: + //! Constructor + ITimestampObjectList(); -} // namespace + //! Container + virtual const CONTAINER &container() const = 0; + + //! Container + virtual CONTAINER &container() = 0; + }; + +} //namespace + +#endif //guard diff --git a/src/plugins/simulator/fs9/fs9_client.cpp b/src/plugins/simulator/fs9/fs9_client.cpp index d102257fb..ab4027d67 100644 --- a/src/plugins/simulator/fs9/fs9_client.cpp +++ b/src/plugins/simulator/fs9/fs9_client.cpp @@ -29,10 +29,11 @@ namespace BlackSimPlugin namespace Fs9 { CFs9Client::CFs9Client( - IRenderedAircraftProviderReadOnly *renderedAircraftProvider, QObject *owner, const QString &callsign, const CTime &updateInterval) : + BlackCore::IInterpolator *interpolator, QObject *owner, const QString &callsign, const CTime &updateInterval) : CDirectPlayPeer(owner, callsign), - m_renderedAircraftProvider(renderedAircraftProvider), m_updateInterval(updateInterval) - { } + m_interpolator(interpolator), m_updateInterval(updateInterval) + { + } CFs9Client::~CFs9Client() { @@ -75,14 +76,14 @@ namespace BlackSimPlugin void CFs9Client::timerEvent(QTimerEvent *event) { Q_UNUSED(event); + Q_ASSERT(m_interpolator); + if (m_clientStatus == Disconnected) { return; } - QMutexLocker locker(&m_mutexInterpolator); - CInterpolatorLinear interpolator(m_renderedAircraftProvider); - if (!interpolator.hasEnoughAircraftSituations(this->m_callsign)) { return; } - - CAircraftSituation situation = interpolator.getCurrentInterpolatedSituation(m_callsign); + bool ok; + CAircraftSituation situation = this->m_interpolator->getCurrentInterpolatedSituation(this->m_interpolator->getSituationsByCallsign(), m_callsign, &ok); + if (!ok) { return; } MPPositionSlewMode positionSlewMode = aircraftSituationToFS9(situation); QByteArray positionMessage; diff --git a/src/plugins/simulator/fs9/fs9_client.h b/src/plugins/simulator/fs9/fs9_client.h index 2d8c2881b..3c77e6d40 100644 --- a/src/plugins/simulator/fs9/fs9_client.h +++ b/src/plugins/simulator/fs9/fs9_client.h @@ -11,7 +11,7 @@ #define DIRECTPLAY_CLIENT_H #include "directplay_peer.h" -#include "blackcore/interpolator_linear.h" +#include "blackcore/interpolator.h" #include "blackmisc/avaircraftsituation.h" #include "blackmisc/pqtime.h" #include @@ -38,7 +38,7 @@ namespace BlackSimPlugin }; //! Constructor - CFs9Client(BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *renderedAircraftProvider, QObject *owner, const QString &callsign, const BlackMisc::PhysicalQuantities::CTime &updateInterval); + CFs9Client(BlackCore::IInterpolator *interpolator, QObject *owner, const QString &callsign, const BlackMisc::PhysicalQuantities::CTime &updateInterval); //! Destructor virtual ~CFs9Client(); @@ -85,10 +85,9 @@ namespace BlackSimPlugin BlackMisc::Aviation::CAircraftSituation m_lastAircraftSituation; BlackMisc::PhysicalQuantities::CTime m_updateInterval; + BlackCore::IInterpolator *m_interpolator = nullptr; int m_timerId = 0; - QMutex m_mutexInterpolator; - BlackMisc::Simulation::IRenderedAircraftProviderReadOnly *m_renderedAircraftProvider = nullptr; IDirectPlay8Address *m_hostAddress = nullptr; ClientStatus m_clientStatus = Disconnected; diff --git a/src/plugins/simulator/fs9/simulator_fs9.cpp b/src/plugins/simulator/fs9/simulator_fs9.cpp index c176ccab1..e03d7617f 100644 --- a/src/plugins/simulator/fs9/simulator_fs9.cpp +++ b/src/plugins/simulator/fs9/simulator_fs9.cpp @@ -14,6 +14,7 @@ #include "fs9_client.h" #include "multiplayer_packets.h" #include "multiplayer_packet_parser.h" +#include "blackcore/interpolator_linear.h" #include "blacksim/simulatorinfo.h" #include "blackmisc/project.h" #include "blackmisc/logmessage.h" @@ -38,11 +39,11 @@ namespace BlackSimPlugin { BlackCore::ISimulator *CSimulatorFs9Factory::create( IOwnAircraftProvider *ownAircraftProvider, - IRenderedAircraftProvider *renderedAircraftProvider, + IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent) { registerMetadata(); - return new Fs9::CSimulatorFs9(ownAircraftProvider, renderedAircraftProvider, parent); + return new Fs9::CSimulatorFs9(ownAircraftProvider, remoteAircraftProvider, parent); } BlackSim::CSimulatorInfo CSimulatorFs9Factory::getSimulatorInfo() const @@ -50,13 +51,15 @@ namespace BlackSimPlugin return CSimulatorInfo::FS9(); } - CSimulatorFs9::CSimulatorFs9(IOwnAircraftProvider *ownAircraftProvider, IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) : - CSimulatorFsCommon(CSimulatorInfo::FS9(), ownAircraftProvider, renderedAircraftProvider, parent), + CSimulatorFs9::CSimulatorFs9(IOwnAircraftProvider *ownAircraftProvider, IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent) : + CSimulatorFsCommon(CSimulatorInfo::FS9(), ownAircraftProvider, remoteAircraftProvider, parent), m_fs9Host(new CFs9Host(this)), m_lobbyClient(new CLobbyClient(this)) { connect(m_fs9Host.data(), &CFs9Host::customPacketReceived, this, &CSimulatorFs9::ps_processFs9Message); connect(m_fs9Host.data(), &CFs9Host::statusChanged, this, &CSimulatorFs9::ps_changeHostStatus); m_fs9Host->start(); + this->m_interpolator = new BlackCore::CInterpolatorLinear(remoteAircraftProvider, this); + this->m_interpolator->start(); } CSimulatorFs9::~CSimulatorFs9() @@ -104,22 +107,22 @@ namespace BlackSimPlugin return true; } - bool CSimulatorFs9::addRemoteAircraft(const CSimulatedAircraft &remoteAircraft) + bool CSimulatorFs9::addRemoteAircraft(const CSimulatedAircraft &newRemoteAircraft) { - CCallsign callsign = remoteAircraft.getCallsign(); + CCallsign callsign = newRemoteAircraft.getCallsign(); if (m_hashFs9Clients.contains(callsign)) { // already exists, remove first this->removeRenderedAircraft(callsign); } - CFs9Client *client = new CFs9Client(this->m_renderedAircraftProvider, this, callsign.toQString(), CTime(25, CTimeUnit::ms())); + CFs9Client *client = new CFs9Client(m_interpolator, this, callsign.toQString(), CTime(25, CTimeUnit::ms())); client->setHostAddress(m_fs9Host->getHostAddress()); client->setPlayerUserId(m_fs9Host->getPlayerUserId()); client->start(); m_hashFs9Clients.insert(callsign, client); - renderedAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(true))); + remoteAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(true))); CLogMessage(this).info("FS9: Added aircraft %1") << callsign.toQString(); return true; } @@ -131,7 +134,7 @@ namespace BlackSimPlugin auto fs9Client = m_hashFs9Clients.value(callsign); fs9Client->quit(); m_hashFs9Clients.remove(callsign); - renderedAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); + remoteAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); CLogMessage(this).info("FS9: Removed aircraft %1") << callsign.toQString(); return true; } diff --git a/src/plugins/simulator/fs9/simulator_fs9.h b/src/plugins/simulator/fs9/simulator_fs9.h index 8ecf9c41b..eb3a8f87d 100644 --- a/src/plugins/simulator/fs9/simulator_fs9.h +++ b/src/plugins/simulator/fs9/simulator_fs9.h @@ -17,7 +17,7 @@ #include "lobby_client.h" #include "../fscommon/simulator_fscommon.h" #include "blackcore/simulator.h" -#include "blackcore/interpolator_linear.h" +#include "blackcore/interpolator.h" #include "blackmisc/simulation/aircraftmodel.h" #include "blackmisc/avaircraft.h" #include "blacksim/simulatorinfo.h" @@ -43,7 +43,7 @@ namespace BlackSimPlugin //! \copydoc BlackCore::ISimulatorFactory::create() virtual BlackCore::ISimulator *create( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent) override; //! Simulator info @@ -59,7 +59,7 @@ namespace BlackSimPlugin //! Constructor, parameters as in \sa BlackCore::ISimulatorFactory::create CSimulatorFs9( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraft, + BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent = nullptr); //! Destructor @@ -86,7 +86,7 @@ namespace BlackSimPlugin virtual bool disconnectFrom() override; //! \copydoc ISimulator::addRemoteAircraft() - virtual bool addRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft) override; + virtual bool addRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &newRemoteAircraft) override; //! \copydoc ISimulator::removeRemoteAircraft() virtual bool removeRenderedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override; @@ -128,6 +128,8 @@ namespace BlackSimPlugin bool m_startedLobbyConnection = false; QHash> m_hashFs9Clients; CLobbyClient *m_lobbyClient; + + BlackCore::IInterpolator *m_interpolator = nullptr; //!< interpolator instance }; } // namespace } // namespace diff --git a/src/plugins/simulator/fscommon/simulator_fscommon.cpp b/src/plugins/simulator/fscommon/simulator_fscommon.cpp index c5b206d01..f4b6f362f 100644 --- a/src/plugins/simulator/fscommon/simulator_fscommon.cpp +++ b/src/plugins/simulator/fscommon/simulator_fscommon.cpp @@ -26,7 +26,7 @@ namespace BlackSimPlugin { namespace FsCommon { - CSimulatorFsCommon::CSimulatorFsCommon(const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) : + CSimulatorFsCommon::CSimulatorFsCommon(const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent) : CSimulatorCommon(simInfo, ownAircraftProvider, renderedAircraftProvider, parent), m_fsuipc(new FsCommon::CFsuipc()) { diff --git a/src/plugins/simulator/fscommon/simulator_fscommon.h b/src/plugins/simulator/fscommon/simulator_fscommon.h index 4f20f9219..ef34c8f7e 100644 --- a/src/plugins/simulator/fscommon/simulator_fscommon.h +++ b/src/plugins/simulator/fscommon/simulator_fscommon.h @@ -84,7 +84,7 @@ namespace BlackSimPlugin CSimulatorFsCommon( const BlackSim::CSimulatorInfo &simInfo, BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent = nullptr); QString simulatorDetails; //!< describes version etc. diff --git a/src/plugins/simulator/fsx/simulator_fsx.cpp b/src/plugins/simulator/fsx/simulator_fsx.cpp index 6e6c86df6..d16e4c75c 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx.cpp @@ -34,19 +34,22 @@ using namespace BlackMisc::Simulation; using namespace BlackSim; using namespace BlackSim::FsCommon; using namespace BlackSim::Fsx; +using namespace BlackCore; namespace BlackSimPlugin { namespace Fsx { - CSimulatorFsx::CSimulatorFsx(IOwnAircraftProvider *ownAircraftProvider, IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) : - CSimulatorFsCommon(CSimulatorInfo::FSX(), ownAircraftProvider, renderedAircraftProvider, parent) + CSimulatorFsx::CSimulatorFsx(IOwnAircraftProvider *ownAircraftProvider, IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent) : + CSimulatorFsCommon(CSimulatorInfo::FSX(), ownAircraftProvider, remoteAircraftProvider, parent) { Q_ASSERT(ownAircraftProvider); - Q_ASSERT(renderedAircraftProvider); + Q_ASSERT(remoteAircraftProvider); CFsxSimulatorSetup setup; setup.init(); // this fetches important settings on local side m_useFsuipc = false; // do not use FSUIPC at the moment with FSX + this->m_interpolator = new CInterpolatorLinear(remoteAircraftProvider, this); + this->m_interpolator->start(); this->m_simulatorInfo.setSimulatorSetup(setup.getSettings()); } @@ -136,9 +139,9 @@ namespace BlackSimPlugin return connect; } - bool CSimulatorFsx::addRemoteAircraft(const Simulation::CSimulatedAircraft &remoteAircraft) + bool CSimulatorFsx::addRemoteAircraft(const Simulation::CSimulatedAircraft &newRemoteAircraft) { - CCallsign callsign = remoteAircraft.getCallsign(); + CCallsign callsign = newRemoteAircraft.getCallsign(); Q_ASSERT(!callsign.isEmpty()); if (callsign.isEmpty()) { return false; } @@ -150,7 +153,7 @@ namespace BlackSimPlugin Q_ASSERT(false); } - SIMCONNECT_DATA_INITPOSITION initialPosition = aircraftSituationToFsxInitPosition(remoteAircraft.getSituation()); + SIMCONNECT_DATA_INITPOSITION initialPosition = aircraftSituationToFsxInitPosition(newRemoteAircraft.getSituation()); initialPosition.Airspeed = 0; initialPosition.OnGround = 0; @@ -161,10 +164,10 @@ namespace BlackSimPlugin ++m_nextObjID; // matched models - CAircraftModel aircraftModel = modelMatching(remoteAircraft); - Q_ASSERT(remoteAircraft.getCallsign() == aircraftModel.getCallsign()); - providerUpdateAircraftModel(remoteAircraft.getCallsign(), aircraftModel, simulatorOriginator()); - CSimulatedAircraft aircraftAfterModelApplied = renderedAircraft().findFirstByCallsign(remoteAircraft.getCallsign()); + CAircraftModel aircraftModel = modelMatching(newRemoteAircraft); + Q_ASSERT(newRemoteAircraft.getCallsign() == aircraftModel.getCallsign()); + providerUpdateAircraftModel(newRemoteAircraft.getCallsign(), aircraftModel, simulatorOriginator()); + CSimulatedAircraft aircraftAfterModelApplied = remoteAircraft().findFirstByCallsign(newRemoteAircraft.getCallsign()); emit modelMatchingCompleted(aircraftAfterModelApplied); // create AI @@ -175,13 +178,13 @@ namespace BlackSimPlugin HRESULT hr = SimConnect_AICreateNonATCAircraft(m_hSimConnect, m.constData(), qPrintable(callsign.toQString().left(12)), initialPosition, simObj.getRequestId()); if (hr != S_OK) { CLogMessage(this).error("SimConnect, can not create AI traffic"); } m_simConnectObjects.insert(callsign, simObj); - renderedAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(true))); + remoteAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(true))); CLogMessage(this).info("FSX: Added aircraft %1") << callsign.toQString(); return true; } else { - renderedAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); + remoteAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); CLogMessage(this).warning("FSX: Not connected, not added aircraft %1") << callsign.toQString(); return false; } @@ -512,7 +515,7 @@ namespace BlackSimPlugin { SimConnect_AIRemoveObject(m_hSimConnect, simObject.getObjectId(), simObject.getRequestId()); m_simConnectObjects.remove(simObject.getCallsign()); - renderedAircraft().applyIfCallsign(simObject.getCallsign(), CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); + remoteAircraft().applyIfCallsign(simObject.getCallsign(), CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); CLogMessage(this).info("FSX: Removed aircraft %1") << simObject.getCallsign().toQString(); return true; } @@ -594,50 +597,69 @@ namespace BlackSimPlugin void CSimulatorFsx::updateOtherAircraft() { static_assert(sizeof(DataDefinitionRemoteAircraft) == 176, "DataDefinitionRemoteAircraft has an incorrect size."); - BlackCore::CInterpolatorLinear interpolator(this->m_renderedAircraftProvider); - for (const CSimConnectObject &simObj : m_simConnectObjects) + Q_ASSERT(this->m_interpolator); + Q_ASSERT_X(this->m_interpolator->thread() != this->thread(), "updateOtherAircraft", "interpolator should run in its own thread"); + + bool lastRequestAvailable; + CAircraftSituationList interpolations = m_interpolator->getRequest(m_interpolationRequest, &lastRequestAvailable); + if (!lastRequestAvailable) { - if (!interpolator.hasEnoughAircraftSituations(simObj.getCallsign())) { continue; } + m_interpolationsSkipped++; + return; + } - SIMCONNECT_DATA_INITPOSITION position = aircraftSituationToFsxInitPosition(interpolator.getCurrentInterpolatedSituation(simObj.getCallsign())); + // non blocking calculations in background + m_interpolator->requestSituationsCalculationsForAllCallsigns(m_interpolationsSkipped); - CAircraftParts parts; - if (renderedAircraftParts().findBeforeNowMinusOffset(6000).containsCallsign(simObj.getCallsign())) - parts = renderedAircraftParts().findBeforeNowMinusOffset(6000).latestValue(); - - position.OnGround = parts.isOnGround() ? 1 : 0; + // now send to sim + for (const CAircraftSituation ¤tSituation : interpolations) + { + bool hasParts; + const CCallsign callsign(currentSituation.getCallsign()); + const CSimConnectObject &simObj = m_simConnectObjects[callsign]; + SIMCONNECT_DATA_INITPOSITION position = aircraftSituationToFsxInitPosition(currentSituation); + CAircraftParts parts = m_interpolator->getLatestPartsBeforeOffset(callsign, IInterpolator::TimeOffsetMs, &hasParts); DataDefinitionRemoteAircraft ddRemoteAircraft; - ddRemoteAircraft.position = position; - ddRemoteAircraft.lightStrobe = parts.getLights().isStrobeOn() ? 1.0 : 0.0; - ddRemoteAircraft.lightLanding = parts.getLights().isLandingOn() ? 1.0 : 0.0; -// ddRemoteAircraft.lightTaxi = parts.getLights().isTaxiOn() ? 1.0 : 0.0; - ddRemoteAircraft.lightBeacon = parts.getLights().isBeaconOn() ? 1.0 : 0.0; - ddRemoteAircraft.lightNav = parts.getLights().isNavOn() ? 1.0 : 0.0; - ddRemoteAircraft.lightLogo = parts.getLights().isLogoOn() ? 1.0 : 0.0; - ddRemoteAircraft.flapsLeadingEdgeLeftPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraft.flapsLeadingEdgeRightPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraft.flapsTrailingEdgeLeftPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraft.flapsTrailingEdgeRightPercent = parts.getFlapsPercent() / 100.0; - ddRemoteAircraft.spoilersHandlePosition = parts.isSpoilersOut() ? 1.0 : 0.0; - ddRemoteAircraft.gearHandlePosition = parts.isGearDown() ? 1 : 0; - ddRemoteAircraft.engine1Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 1).frontOrDefault().isOn() ? 1 : 0; - ddRemoteAircraft.engine2Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 2).frontOrDefault().isOn() ? 1 : 0; - ddRemoteAircraft.engine3Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 3).frontOrDefault().isOn() ? 1 : 0; - ddRemoteAircraft.engine4Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 4).frontOrDefault().isOn() ? 1 : 0; + if (hasParts) + { + // we have parts + position.OnGround = parts.isOnGround() ? 1 : 0; + + ddRemoteAircraft.position = position; + ddRemoteAircraft.lightStrobe = parts.getLights().isStrobeOn() ? 1.0 : 0.0; + ddRemoteAircraft.lightLanding = parts.getLights().isLandingOn() ? 1.0 : 0.0; + // ddRemoteAircraft.lightTaxi = parts.getLights().isTaxiOn() ? 1.0 : 0.0; + ddRemoteAircraft.lightBeacon = parts.getLights().isBeaconOn() ? 1.0 : 0.0; + ddRemoteAircraft.lightNav = parts.getLights().isNavOn() ? 1.0 : 0.0; + ddRemoteAircraft.lightLogo = parts.getLights().isLogoOn() ? 1.0 : 0.0; + ddRemoteAircraft.flapsLeadingEdgeLeftPercent = parts.getFlapsPercent() / 100.0; + ddRemoteAircraft.flapsLeadingEdgeRightPercent = parts.getFlapsPercent() / 100.0; + ddRemoteAircraft.flapsTrailingEdgeLeftPercent = parts.getFlapsPercent() / 100.0; + ddRemoteAircraft.flapsTrailingEdgeRightPercent = parts.getFlapsPercent() / 100.0; + ddRemoteAircraft.spoilersHandlePosition = parts.isSpoilersOut() ? 1.0 : 0.0; + ddRemoteAircraft.gearHandlePosition = parts.isGearDown() ? 1 : 0; + ddRemoteAircraft.engine1Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 1).frontOrDefault().isOn() ? 1 : 0; + ddRemoteAircraft.engine2Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 2).frontOrDefault().isOn() ? 1 : 0; + ddRemoteAircraft.engine3Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 3).frontOrDefault().isOn() ? 1 : 0; + ddRemoteAircraft.engine4Combustion = parts.getEngines().findBy(&CAircraftEngine::getNumber, 4).frontOrDefault().isOn() ? 1 : 0; + } + else + { + //! \todo interpolator, set data without parts by educated guessing whatsoever + position.OnGround = parts.isOnGround() ? 1 : 0; + } if (simObj.getObjectId() != 0) { HRESULT hr = S_OK; - hr += SimConnect_SetDataOnSimObject(m_hSimConnect, CSimConnectDefinitions::DataRemoteAircraft, simObj.getObjectId(), 0, 0, sizeof(DataDefinitionRemoteAircraft), &ddRemoteAircraft); - if (hr != S_OK) CLogMessage(this).warning("Failed so set data on SimObject"); - + if (hr != S_OK) { CLogMessage(this).warning("Failed so set data on SimObject"); } } - } + } // ok, no parts } SIMCONNECT_DATA_INITPOSITION CSimulatorFsx::aircraftSituationToFsxInitPosition(const CAircraftSituation &situation) diff --git a/src/plugins/simulator/fsx/simulator_fsx.h b/src/plugins/simulator/fsx/simulator_fsx.h index 9ddf7f836..4bbd3e07e 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.h +++ b/src/plugins/simulator/fsx/simulator_fsx.h @@ -74,7 +74,7 @@ namespace BlackSimPlugin //! Constructor, parameters as in \sa BlackCore::ISimulatorFactory::create CSimulatorFsx( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent = nullptr); //! Destructor @@ -104,7 +104,7 @@ namespace BlackSimPlugin virtual bool disconnectFrom() override; //! \copydoc ISimulator::addRemoteAircraft() - virtual bool addRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft) override; + virtual bool addRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &newRemoteAircraft) override; //! \copydoc ISimulator::removeRenderedAircraft() virtual bool removeRenderedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override; @@ -181,9 +181,12 @@ namespace BlackSimPlugin int m_syncDeferredCounter = 0; //!< Set when synchronized, used to wait some time int m_simconnectTimerId = -1; //!< Timer identifier int m_skipCockpitUpdateCycles = 0; //!< Skip some update cycles to allow changes in simulator cockpit to be set + int m_interpolationRequest = 0; //!< current interpolation request + int m_interpolationsSkipped = 0; //!< number of skipped interpolation request HANDLE m_hSimConnect = nullptr; //!< Handle to SimConnect object uint m_nextObjID = 1; //!< object ID TODO: also used as request id, where to we place other request ids as for facilities BlackMisc::PhysicalQuantities::CTime m_syncTimeOffset; //!< Time offset (if synchronized) + BlackCore::IInterpolator *m_interpolator = nullptr; //!< interpolator instance QHash m_simConnectObjects; QFutureWatcher m_watcherConnect; }; diff --git a/src/plugins/simulator/fsx/simulator_fsxfactory.cpp b/src/plugins/simulator/fsx/simulator_fsxfactory.cpp index c8b04a805..b9bab696f 100644 --- a/src/plugins/simulator/fsx/simulator_fsxfactory.cpp +++ b/src/plugins/simulator/fsx/simulator_fsxfactory.cpp @@ -21,7 +21,7 @@ namespace BlackSimPlugin { namespace Fsx { - BlackCore::ISimulator *CSimulatorFsxFactory::create(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) + BlackCore::ISimulator *CSimulatorFsxFactory::create(BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent) { Q_ASSERT(ownAircraftProvider); return new CSimulatorFsx(ownAircraftProvider, renderedAircraftProvider, parent); diff --git a/src/plugins/simulator/fsx/simulator_fsxfactory.h b/src/plugins/simulator/fsx/simulator_fsxfactory.h index c6e19e803..5099ba315 100644 --- a/src/plugins/simulator/fsx/simulator_fsxfactory.h +++ b/src/plugins/simulator/fsx/simulator_fsxfactory.h @@ -35,7 +35,7 @@ namespace BlackSimPlugin //! \copydoc BlackCore::ISimulatorFactory::create virtual BlackCore::ISimulator *create( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent) override; //! \copydoc BlackCore::ISimulatorFactory::getSimulatorInfo diff --git a/src/plugins/simulator/xplane/simulator_xplane.cpp b/src/plugins/simulator/xplane/simulator_xplane.cpp index ea000f41d..01f184abd 100644 --- a/src/plugins/simulator/xplane/simulator_xplane.cpp +++ b/src/plugins/simulator/xplane/simulator_xplane.cpp @@ -28,8 +28,8 @@ namespace BlackSimPlugin namespace XPlane { - CSimulatorXPlane::CSimulatorXPlane(IOwnAircraftProvider *ownAircraftProvider, IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) : - CSimulatorCommon(CSimulatorInfo::XP(), ownAircraftProvider, renderedAircraftProvider, parent) + CSimulatorXPlane::CSimulatorXPlane(IOwnAircraftProvider *ownAircraftProvider, IRemoteAircraftProvider *remoteAircraftProvider, QObject *parent) : + CSimulatorCommon(CSimulatorInfo::XP(), ownAircraftProvider, remoteAircraftProvider, parent) { m_watcher = new QDBusServiceWatcher(this); m_watcher->setWatchMode(QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration); @@ -330,17 +330,17 @@ namespace BlackSimPlugin return false; } - bool CSimulatorXPlane::addRemoteAircraft(const CSimulatedAircraft &remoteAircraft) + bool CSimulatorXPlane::addRemoteAircraft(const CSimulatedAircraft &newRemoteAircraft) { if (!isConnected()) { return false; } //! \todo XPlane driver check if already exists, how? //! \todo XPlane driver set correct return value // KB: from what I can see here all data are available // Is there any model matching required ???? - CAircraftIcao icao = remoteAircraft.getIcaoInfo(); - m_traffic->addPlane(remoteAircraft.getCallsign().asString(), icao.getAircraftDesignator(), icao.getAirlineDesignator(), icao.getLivery()); - renderedAircraft().applyIfCallsign(remoteAircraft.getCallsign(), CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(true))); - CLogMessage(this).info("XP: Added aircraft %1") << remoteAircraft.getCallsign().toQString(); + CAircraftIcao icao = newRemoteAircraft.getIcaoInfo(); + m_traffic->addPlane(newRemoteAircraft.getCallsign().asString(), icao.getAircraftDesignator(), icao.getAirlineDesignator(), icao.getLivery()); + remoteAircraft().applyIfCallsign(newRemoteAircraft.getCallsign(), CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(true))); + CLogMessage(this).info("XP: Added aircraft %1") << newRemoteAircraft.getCallsign().toQString(); return true; } @@ -365,7 +365,7 @@ namespace BlackSimPlugin { if (! isConnected()) { return false; } m_traffic->removePlane(callsign.asString()); - renderedAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); + remoteAircraft().applyIfCallsign(callsign, CPropertyIndexVariantMap(CSimulatedAircraft::IndexRendered, CVariant::fromValue(false))); CLogMessage(this).info("XP: Removed aircraft %1") << callsign.toQString(); return true; } @@ -395,7 +395,7 @@ namespace BlackSimPlugin return true; } - BlackCore::ISimulator *CSimulatorXPlaneFactory::create(IOwnAircraftProvider *ownAircraftProvider, IRenderedAircraftProvider *renderedAircraftProvider, QObject *parent) + BlackCore::ISimulator *CSimulatorXPlaneFactory::create(IOwnAircraftProvider *ownAircraftProvider, IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent) { return new CSimulatorXPlane(ownAircraftProvider, renderedAircraftProvider, parent); } diff --git a/src/plugins/simulator/xplane/simulator_xplane.h b/src/plugins/simulator/xplane/simulator_xplane.h index 0d85fe594..fb250362e 100644 --- a/src/plugins/simulator/xplane/simulator_xplane.h +++ b/src/plugins/simulator/xplane/simulator_xplane.h @@ -37,7 +37,7 @@ namespace BlackSimPlugin //! Constructor, parameters as in \sa BlackCore::ISimulatorFactory::create CSimulatorXPlane( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraft, + BlackMisc::Simulation::IRemoteAircraftProvider *remoteAircraft, QObject *parent = nullptr); //! \copydoc BlackCore::ISimulator::isConnected @@ -69,7 +69,7 @@ namespace BlackSimPlugin virtual bool disconnectFrom() override; //! \copydoc ISimulator::addRemoteAircraft() - virtual bool addRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &remoteAircraft) override; + virtual bool addRemoteAircraft(const BlackMisc::Simulation::CSimulatedAircraft &newRemoteAircraft) override; //! \copydoc BlackCore::ISimulator::removeRemoteAircraft virtual bool removeRenderedAircraft(const BlackMisc::Aviation::CCallsign &callsign) override; @@ -172,7 +172,7 @@ namespace BlackSimPlugin //! \copydoc BlackCore::ISimulatorFactory::create() virtual BlackCore::ISimulator *create( BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider, - BlackMisc::Simulation::IRenderedAircraftProvider *renderedAircraftProvider, + BlackMisc::Simulation::IRemoteAircraftProvider *renderedAircraftProvider, QObject *parent) override; //! \copydoc BlackCore::ISimulatorFactory::getSimulatorInfo diff --git a/src/swiftgui_standard/swiftguistd.cpp b/src/swiftgui_standard/swiftguistd.cpp index 24a023609..e7c664552 100644 --- a/src/swiftgui_standard/swiftguistd.cpp +++ b/src/swiftgui_standard/swiftguistd.cpp @@ -216,8 +216,9 @@ void SwiftGuiStd::ps_onConnectionTerminated() /* * Connection status changed */ -void SwiftGuiStd::ps_onConnectionStatusChanged(uint /** from **/, uint to) +void SwiftGuiStd::ps_onConnectionStatusChanged(int from, int to) { + Q_UNUSED(from); this->updateGuiStatusInformation(); INetwork::ConnectionStatus newStatus = static_cast(to); diff --git a/src/swiftgui_standard/swiftguistd.h b/src/swiftgui_standard/swiftguistd.h index 3b4d70c72..37507b736 100644 --- a/src/swiftgui_standard/swiftguistd.h +++ b/src/swiftgui_standard/swiftguistd.h @@ -197,10 +197,10 @@ private slots: /*! * \brief Connection status changed - * \param from old status, as uint so it is compliant with DBus - * \param to new status, as uint so it is compliant with DBus + * \param from old status, as int so it is compliant with DBus + * \param to new status, as int so it is compliant with DBus */ - void ps_onConnectionStatusChanged(uint from, uint to); + void ps_onConnectionStatusChanged(int from, int to); // // GUI related slots