[FSX/P3D] Simplified listener

* removed inner SimConnect_CallDispatch loop/CApplication::processEventsFor
* keep connection open, and check dispatch queue
This commit is contained in:
Klaus Basan
2020-04-25 02:15:24 +02:00
committed by Mat Sutcliffe
parent 32605cd557
commit 114b36e611
3 changed files with 72 additions and 31 deletions

View File

@@ -2816,6 +2816,7 @@ namespace BlackSimPlugin
void CSimulatorFsxCommonListener::stopImpl() void CSimulatorFsxCommonListener::stopImpl()
{ {
m_timer.stop(); m_timer.stop();
this->disconnectFromSimulator();
} }
void CSimulatorFsxCommonListener::checkImpl() void CSimulatorFsxCommonListener::checkImpl()
@@ -2842,53 +2843,64 @@ namespace BlackSimPlugin
void CSimulatorFsxCommonListener::checkConnection() void CSimulatorFsxCommonListener::checkConnection()
{ {
if (this->isShuttingDown()) { return; }
QElapsedTimer t; t.start();
Q_ASSERT_X(!CThreadUtils::isCurrentThreadApplicationThread(), Q_FUNC_INFO, "Expect to run in background"); 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; bool check = false;
if (isOk(result)) do
{ {
// if we can connect, but not dispatch, it can mean a previously started FSX/P3D // if we can connect, but not dispatch, it can mean a previously started FSX/P3D
// blocks remote calls -> RESTART // 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()) this->stopImpl();
{ return;
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 if (isFailure(result)) { break; } // means serious failure
check = this->checkVersionAndSimulator(); check = this->checkVersionAndSimulator();
if (!check && sApp) { CApplication::processEventsFor(500); }
}
}
SimConnect_Close(hSimConnect);
}
while (false);
this->adjustTimerInterval(t.elapsed());
if (check) if (check)
{ {
emit this->simulatorStarted(this->getPluginInfo()); 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))
{ {
const int newIntervalMs = qRound(1.5 * elapsed); const QString sim = this->getPluginInfo().getSimulatorInfo().toQString(true);
CLogMessage(this).debug(u"Check for simulator sim.'%1' connection in %2ms, too slow. Setting %3ms") << sim << elapsed << newIntervalMs; CLogMessage(this).debug(u"Checked sim.'%1' connection in %2ms") << sim << checkTimeMs;
if (checkTimeMs > qRound(1.25 * MinQueryIntervalMs))
{
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); } if (m_timer.interval() != newIntervalMs) { m_timer.setInterval(newIntervalMs); }
} }
else else
{ {
if (m_timer.interval() != MinQueryIntervalMs) { m_timer.setInterval(MinQueryIntervalMs); } if (m_timer.interval() != MinQueryIntervalMs) { m_timer.setInterval(MinQueryIntervalMs); }
} }
// restart
m_timer.start();
} }
bool CSimulatorFsxCommonListener::checkVersionAndSimulator() const bool CSimulatorFsxCommonListener::checkVersionAndSimulator() const
@@ -2917,6 +2929,24 @@ namespace BlackSimPlugin
return true; 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) void CSimulatorFsxCommonListener::SimConnectProc(SIMCONNECT_RECV *pData, DWORD cbData, void *pContext)
{ {
Q_UNUSED(cbData) Q_UNUSED(cbData)

View File

@@ -657,6 +657,7 @@ namespace BlackSimPlugin
//! \copydoc BlackCore::ISimulatorListener::checkImpl //! \copydoc BlackCore::ISimulatorListener::checkImpl
virtual void checkImpl() override; virtual void checkImpl() override;
private:
//! Test if connection can be established //! Test if connection can be established
void checkConnection(); void checkConnection();
@@ -666,7 +667,15 @@ namespace BlackSimPlugin
//! Check the simconnect.dll //! Check the simconnect.dll
bool checkSimConnectDll() const; 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 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 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_simConnectVersion;
QString m_simulatorName; QString m_simulatorName;
QString m_simulatorDetails; 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 BlackMisc::CStatusMessage m_lastMessage; //!< last listener message
//! SimConnect Callback (simplified version for listener) //! SimConnect Callback (simplified version for listener)

View File

@@ -1482,7 +1482,7 @@ namespace BlackSimPlugin
via = "P2P"; 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() void CSimulatorXPlaneListener::checkConnectionViaSessionBus()