From 114b36e6114d86d01c666292fd76577c6812f71c Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 25 Apr 2020 02:15:24 +0200 Subject: [PATCH] [FSX/P3D] Simplified listener * removed inner SimConnect_CallDispatch loop/CApplication::processEventsFor * keep connection open, and check dispatch queue --- .../fsxcommon/simulatorfsxcommon.cpp | 88 +++++++++++++------ .../simulator/fsxcommon/simulatorfsxcommon.h | 13 ++- .../simulator/xplane/simulatorxplane.cpp | 2 +- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp index 57737ef55..11ca0bcf0 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.cpp @@ -123,9 +123,9 @@ namespace BlackSimPlugin bool CSimulatorFsxCommon::disconnectFrom() { if (!m_simConnected) { return true; } - m_simSimulating = false; // thread as stopped, just setting the flag here avoids overhead of on onSimStopped + m_simSimulating = false; // thread as stopped, just setting the flag here avoids overhead of on onSimStopped m_traceAutoUntilTs = -1; - m_traceSendId = false; + m_traceSendId = false; this->reset(); // mark as disconnected and reset all values if (m_hSimConnect) @@ -2816,11 +2816,12 @@ namespace BlackSimPlugin void CSimulatorFsxCommonListener::stopImpl() { m_timer.stop(); + this->disconnectFromSimulator(); } void CSimulatorFsxCommonListener::checkImpl() { - if (!m_timer.isActive()) { return; } + if (!m_timer.isActive()) { return; } if (this->isShuttingDown()) { return; } QPointer myself(this); @@ -2842,53 +2843,64 @@ namespace BlackSimPlugin void CSimulatorFsxCommonListener::checkConnection() { - if (this->isShuttingDown()) { return; } - QElapsedTimer t; t.start(); Q_ASSERT_X(!CThreadUtils::isCurrentThreadApplicationThread(), Q_FUNC_INFO, "Expect to run in background"); - HANDLE hSimConnect; - HRESULT result = SimConnect_Open(&hSimConnect, sApp->swiftVersionChar(), nullptr, 0, nullptr, 0); + + // check before we access the sim. connection + if (this->isShuttingDown() || this->thread()->isInterruptionRequested()) + { + this->stopImpl(); + return; + } + + QElapsedTimer t; t.start(); bool check = false; - if (isOk(result)) + do { // if we can connect, but not dispatch, it can mean a previously started FSX/P3D // blocks remote calls -> RESTART - for (int i = 0; !check && i < 3 && !this->isShuttingDown(); i++) + if (!this->connectToSimulator()) { break; } + + // check if we have the right sim. + // this check on a remote FSX/P3D not running/existing might TAKE LONG! + const HRESULT result = SimConnect_CallDispatch(m_hSimConnect, CSimulatorFsxCommonListener::SimConnectProc, this); + + // make sure we did not stop in meantime + if (this->isShuttingDown() || this->thread()->isInterruptionRequested()) { - if (this->thread()->isInterruptionRequested()) - { - m_timer.stop(); - check = false; - break; - } - - // result not always in first dispatch as we first have to obtain simulator name - result = SimConnect_CallDispatch(hSimConnect, CSimulatorFsxCommonListener::SimConnectProc, this); - if (isFailure(result)) { break; } // means serious failure - check = this->checkVersionAndSimulator(); - if (!check && sApp) { CApplication::processEventsFor(500); } + this->stopImpl(); + return; } - } - SimConnect_Close(hSimConnect); + if (isFailure(result)) { break; } // means serious failure + check = this->checkVersionAndSimulator(); + + } + while (false); + + this->adjustTimerInterval(t.elapsed()); if (check) { emit this->simulatorStarted(this->getPluginInfo()); } + } - const qint64 elapsed = t.elapsed(); + void CSimulatorFsxCommonListener::adjustTimerInterval(qint64 checkTimeMs) + { const QString sim = this->getPluginInfo().getSimulatorInfo().toQString(true); - CLogMessage(this).debug(u"Checked sim.'%1' connection in %1ms") << elapsed; - - if (elapsed > qRound(1.25 * MinQueryIntervalMs)) + CLogMessage(this).debug(u"Checked sim.'%1' connection in %2ms") << sim << checkTimeMs; + if (checkTimeMs > qRound(1.25 * MinQueryIntervalMs)) { - const int newIntervalMs = qRound(1.5 * elapsed); - CLogMessage(this).debug(u"Check for simulator sim.'%1' connection in %2ms, too slow. Setting %3ms") << sim << elapsed << newIntervalMs; + const int newIntervalMs = qRound(1.2 * checkTimeMs / 1000.0) * 1000; + CLogMessage(this).debug(u"Check for simulator sim.'%1' connection in %2ms, too slow. Setting %3ms") << sim << checkTimeMs << newIntervalMs; if (m_timer.interval() != newIntervalMs) { m_timer.setInterval(newIntervalMs); } } else { if (m_timer.interval() != MinQueryIntervalMs) { m_timer.setInterval(MinQueryIntervalMs); } } + + // restart + m_timer.start(); } bool CSimulatorFsxCommonListener::checkVersionAndSimulator() const @@ -2917,6 +2929,24 @@ namespace BlackSimPlugin return true; } + bool CSimulatorFsxCommonListener::connectToSimulator() + { + if (m_simConnected) { return true; } + const HRESULT result = SimConnect_Open(&m_hSimConnect, sApp->swiftVersionChar(), nullptr, 0, nullptr, 0); + const bool ok = isOk(result); + m_simConnected = ok; + return ok; + } + + bool CSimulatorFsxCommonListener::disconnectFromSimulator() + { + if (!m_simConnected) { return false; } + SimConnect_Close(m_hSimConnect); + m_hSimConnect = nullptr; + m_simConnected = false; + return true; + } + void CSimulatorFsxCommonListener::SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext) { Q_UNUSED(cbData) diff --git a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h index 2ff1d9ee5..de4f65381 100644 --- a/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h +++ b/src/plugins/simulator/fsxcommon/simulatorfsxcommon.h @@ -657,6 +657,7 @@ namespace BlackSimPlugin //! \copydoc BlackCore::ISimulatorListener::checkImpl virtual void checkImpl() override; + private: //! Test if connection can be established void checkConnection(); @@ -666,7 +667,15 @@ namespace BlackSimPlugin //! Check the simconnect.dll bool checkSimConnectDll() const; - private: + //! Connect to simulator (if not already) + bool connectToSimulator(); + + //! Disconnect from simulator + bool disconnectFromSimulator(); + + //! Adjust the timer interval + void adjustTimerInterval(qint64 checkTimeMs); + static constexpr int MinQueryIntervalMs = 5 * 1000; // 5 seconds QTimer m_timer { this }; //!< timer, "this" is needed otherwise I get warnings when move to new thread @@ -674,6 +683,8 @@ namespace BlackSimPlugin QString m_simConnectVersion; QString m_simulatorName; QString m_simulatorDetails; + HANDLE m_hSimConnect; + bool m_simConnected = false; //!< SimConnect is connected, does not mean to the correct sim. BlackMisc::CStatusMessage m_lastMessage; //!< last listener message //! SimConnect Callback (simplified version for listener) diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index ed0f813dc..a9303d822 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -1482,7 +1482,7 @@ namespace BlackSimPlugin via = "P2P"; } - CLogMessage(this).debug(u"Checked sim. 'XPLANE' via '%2' connection in %1ms") << via << t.elapsed(); + CLogMessage(this).debug(u"Checked sim. 'XPLANE' via '%1' connection in %2ms") << via << t.elapsed(); } void CSimulatorXPlaneListener::checkConnectionViaSessionBus()