From 195c909ca0d0e3e750f404c6610b44c4ffefe159 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sun, 16 Nov 2014 01:09:01 +0000 Subject: [PATCH] refs #334 FS9 DirectPlay peer classes using CContinuousWorker. --- src/plugins/simulator/fs9/directplay_peer.cpp | 4 +- src/plugins/simulator/fs9/directplay_peer.h | 12 +-- src/plugins/simulator/fs9/fs9_client.cpp | 32 ++++---- src/plugins/simulator/fs9/fs9_client.h | 22 ++---- src/plugins/simulator/fs9/fs9_host.cpp | 65 ++++++++-------- src/plugins/simulator/fs9/fs9_host.h | 26 ++++--- src/plugins/simulator/fs9/simulator_fs9.cpp | 77 ++++--------------- src/plugins/simulator/fs9/simulator_fs9.h | 9 +-- 8 files changed, 93 insertions(+), 154 deletions(-) diff --git a/src/plugins/simulator/fs9/directplay_peer.cpp b/src/plugins/simulator/fs9/directplay_peer.cpp index f50585f7b..c9a8e5ed2 100644 --- a/src/plugins/simulator/fs9/directplay_peer.cpp +++ b/src/plugins/simulator/fs9/directplay_peer.cpp @@ -21,8 +21,8 @@ namespace BlackSimPlugin { namespace Fs9 { - CDirectPlayPeer::CDirectPlayPeer(const QString &callsign, QObject *parent) - : QObject(parent), + CDirectPlayPeer::CDirectPlayPeer(QObject *owner, const QString &callsign) + : CContinuousWorker(owner, "peer_" + callsign), m_callsign(callsign), m_mutexHostList(QMutex::Recursive), m_callbackWrapper(this, &CDirectPlayPeer::directPlayMessageHandler) diff --git a/src/plugins/simulator/fs9/directplay_peer.h b/src/plugins/simulator/fs9/directplay_peer.h index 7c44f3da4..bbc95e450 100644 --- a/src/plugins/simulator/fs9/directplay_peer.h +++ b/src/plugins/simulator/fs9/directplay_peer.h @@ -13,6 +13,7 @@ #include "fs9.h" #include "host_node.h" #include "callback_wrapper.h" +#include "blackmisc/worker.h" #include #include #include @@ -26,14 +27,13 @@ namespace BlackSimPlugin namespace Fs9 { //! DirectPlay peer implementation - class CDirectPlayPeer : public QObject + class CDirectPlayPeer : public BlackMisc::CContinuousWorker { Q_OBJECT public: - //! Constructor - CDirectPlayPeer(const QString &callsign, QObject *parent = nullptr); + CDirectPlayPeer(QObject *owner, const QString &callsign); //! Destructor virtual ~CDirectPlayPeer(); @@ -45,20 +45,14 @@ namespace BlackSimPlugin void setPlayerUserId(DPNID id) { m_playerUser = id; } public slots: - - //! Initialize DirectPlay host - virtual void init() = 0; - //! Send a custom DirectPlay message HRESULT sendMessage(const QByteArray &data); signals: - //! Received custom FS9 packet void customPacketReceived(const QByteArray &data); protected: - //! DirectPlay message handler HRESULT directPlayMessageHandler(DWORD messageId, void *msgBuffer); diff --git a/src/plugins/simulator/fs9/fs9_client.cpp b/src/plugins/simulator/fs9/fs9_client.cpp index 0538a3c5a..8e20a50cd 100644 --- a/src/plugins/simulator/fs9/fs9_client.cpp +++ b/src/plugins/simulator/fs9/fs9_client.cpp @@ -17,6 +17,7 @@ #include "blackmisc/coordinategeodetic.h" #include +using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::PhysicalQuantities; @@ -24,8 +25,8 @@ namespace BlackSimPlugin { namespace Fs9 { - CFs9Client::CFs9Client(const QString &callsign, const CTime &updateInterval, QObject *parent) : - CDirectPlayPeer(callsign, parent), + CFs9Client::CFs9Client(QObject *owner, const QString &callsign, const CTime &updateInterval) : + CDirectPlayPeer(owner, callsign), m_updateInterval(updateInterval) { } @@ -36,14 +37,6 @@ namespace BlackSimPlugin m_hostAddress = nullptr; } - void CFs9Client::init() - { - initDirectPlay(); - createDeviceAddress(); - //enumDirectPlayHosts(); - connectToSession(m_callsign); - } - void CFs9Client::sendTextMessage(const QString &textMessage) { MPChatText mpChatText; @@ -55,11 +48,6 @@ namespace BlackSimPlugin sendMessage(message); } - void CFs9Client::disconnectFrom() - { - closeConnection(); - } - void CFs9Client::setHostAddress(const QString &hostAddress) { HRESULT hr = S_OK; @@ -120,6 +108,19 @@ namespace BlackSimPlugin } } + void CFs9Client::initialize() + { + initDirectPlay(); + createDeviceAddress(); + //enumDirectPlayHosts(); + connectToSession(m_callsign); + } + + void CFs9Client::cleanup() + { + closeConnection(); + } + HRESULT CFs9Client::enumDirectPlayHosts() { HRESULT hr = S_OK; @@ -251,6 +252,7 @@ namespace BlackSimPlugin MultiPlayerPacketParser::writeType(message, CFs9Sdk::MULTIPLAYER_PACKET_ID_CHANGE_PLAYER_PLANE); MultiPlayerPacketParser::writeSize(message, mpChangePlayerPlane.size()); message = MultiPlayerPacketParser::writeMessage(message, mpChangePlayerPlane); + CLogMessage(this).debug() << m_callsign << " connected to session."; sendMessage(message); m_timerId = startTimer(m_updateInterval.value(CTimeUnit::ms())); diff --git a/src/plugins/simulator/fs9/fs9_client.h b/src/plugins/simulator/fs9/fs9_client.h index 3a7fa0008..15e858ea5 100644 --- a/src/plugins/simulator/fs9/fs9_client.h +++ b/src/plugins/simulator/fs9/fs9_client.h @@ -30,7 +30,6 @@ namespace BlackSimPlugin Q_OBJECT public: - //! Connection status enum ClientStatus { @@ -38,10 +37,8 @@ namespace BlackSimPlugin Disconnected }; - //! Constructor - CFs9Client(const QString &callsign, const BlackMisc::PhysicalQuantities::CTime &updateInterval, - QObject *parent = nullptr); + CFs9Client(QObject *owner, const QString &callsign, const BlackMisc::PhysicalQuantities::CTime &updateInterval); //! Destructor virtual ~CFs9Client(); @@ -53,28 +50,25 @@ namespace BlackSimPlugin void addAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); public slots: - - //! \copydoc CDirectPlayPeer::init - virtual void init() override; - //! Send new text message void sendTextMessage(const QString &textMessage); - //! Disconnect client from session - void disconnectFrom(); - signals: - //! Client status changed void statusChanged(const QString &callsign, BlackSimPlugin::Fs9::CFs9Client::ClientStatus); protected slots: - //! Timer event slot virtual void timerEvent(QTimerEvent *event) override; - private: + protected: + //! \copydoc CContinuousWorker::initialize + virtual void initialize() override; + //! \copydoc CContinuousWorker::cleanup + virtual void cleanup() override; + + private: /*! * Enumerate all FS9 session hosts * \todo Ideally host enumeration is required only once (if ever). diff --git a/src/plugins/simulator/fs9/fs9_host.cpp b/src/plugins/simulator/fs9/fs9_host.cpp index d27139ae1..b3d0b941a 100644 --- a/src/plugins/simulator/fs9/fs9_host.cpp +++ b/src/plugins/simulator/fs9/fs9_host.cpp @@ -23,8 +23,8 @@ namespace BlackSimPlugin { namespace Fs9 { - CFs9Host::CFs9Host(QObject *parent) : - CDirectPlayPeer(CProject::systemNameAndVersion(), parent) + CFs9Host::CFs9Host(QObject *owner) : + CDirectPlayPeer(owner, CProject::systemNameAndVersion()) { } @@ -63,39 +63,6 @@ namespace BlackSimPlugin return address; } - void CFs9Host::init() - { - initDirectPlay(); - createHostAddress(); - startHosting(CProject::systemNameAndVersion(), m_callsign); - } - - HRESULT CFs9Host::stopHosting() - { - HRESULT hr = S_OK; - - if (m_hostStatus == Terminated) return hr; - - qDebug() << "Terminating host"; - - if (FAILED(hr = m_directPlayPeer->TerminateSession(nullptr, 0, 0))) - { - qWarning() << "Failed to terminate session!"; - return hr; - } - - if (FAILED(hr = m_directPlayPeer->Close(0))) - { - qWarning() << "Failed to close peer!"; - return hr; - } - - m_hostStatus = Terminated; - - emit statusChanged(m_hostStatus); - return hr; - } - void CFs9Host::sendTextMessage(const QString &textMessage) { MPChatText mpChatText; @@ -107,6 +74,19 @@ namespace BlackSimPlugin sendMessage(message); } + void CFs9Host::initialize() + { + initDirectPlay(); + createHostAddress(); + startHosting(CProject::systemNameAndVersion(), m_callsign); + } + + void CFs9Host::cleanup() + { + stopHosting(); + } + + HRESULT CFs9Host::startHosting(const QString &session, const QString &callsign) { HRESULT hr = S_OK; @@ -170,5 +150,20 @@ namespace BlackSimPlugin emit statusChanged(m_hostStatus); return hr; } + + HRESULT CFs9Host::stopHosting() + { + HRESULT hr = S_OK; + + if (m_hostStatus == Terminated) return hr; + + qDebug() << "Terminating host"; + hr = m_directPlayPeer->TerminateSession(nullptr, 0, 0); + hr = m_directPlayPeer->Close(0); + m_hostStatus = Terminated; + + emit statusChanged(m_hostStatus); + return hr; + } } } diff --git a/src/plugins/simulator/fs9/fs9_host.h b/src/plugins/simulator/fs9/fs9_host.h index e2e5a0598..ff152bca0 100644 --- a/src/plugins/simulator/fs9/fs9_host.h +++ b/src/plugins/simulator/fs9/fs9_host.h @@ -24,7 +24,6 @@ namespace BlackSimPlugin Q_OBJECT public: - //! Connection status enum HostStatus { @@ -33,7 +32,10 @@ namespace BlackSimPlugin }; //! Constructor - CFs9Host(QObject *parent = nullptr); + CFs9Host(QObject *owner); + + //! Destructor + virtual ~CFs9Host() {} //! Returns true if the users simulator is connected bool isConnected() const { return m_playerUser != 0; } @@ -42,28 +44,28 @@ namespace BlackSimPlugin QString getHostAddress(); public slots: - - //! \copydoc CDirectPlayPeer::init - virtual void init() override; - - //! Terminate a current active hosting session - HRESULT stopHosting(); - //! Send new text message void sendTextMessage(const QString &textMessage); signals: - //! Hosting status changed void statusChanged(BlackSimPlugin::Fs9::CFs9Host::HostStatus); - private: + protected: + //! \copydoc CContinuousWorker::initialize + virtual void initialize() override; + //! \copydoc CContinuousWorker::cleanup + virtual void cleanup() override; + + private: //! Start host session HRESULT startHosting(const QString &session, const QString &callsign); - HostStatus m_hostStatus = Terminated; + //! Terminate a current active hosting session + HRESULT stopHosting(); + HostStatus m_hostStatus = Terminated; }; } } diff --git a/src/plugins/simulator/fs9/simulator_fs9.cpp b/src/plugins/simulator/fs9/simulator_fs9.cpp index 1e090b3f1..215d10630 100644 --- a/src/plugins/simulator/fs9/simulator_fs9.cpp +++ b/src/plugins/simulator/fs9/simulator_fs9.cpp @@ -19,6 +19,7 @@ #include #include +using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Geo; @@ -42,30 +43,19 @@ namespace BlackSimPlugin CSimulatorFs9::CSimulatorFs9(QObject *parent) : ISimulator(parent), - m_fs9Host(new CFs9Host), - m_hostThread(this), + m_fs9Host(new CFs9Host(this)), m_lobbyClient(new CLobbyClient(this)), m_simulatorInfo(CSimulatorInfo::FS9()), m_fsuipc(new FsCommon::CFsuipc()) { - // We move the host thread already in the constructor - m_fs9Host->moveToThread(&m_hostThread); - connect(&m_hostThread, &QThread::started, m_fs9Host, &CFs9Host::init); - connect(m_fs9Host, &CFs9Host::customPacketReceived, this, &CSimulatorFs9::ps_processFs9Message); - connect(m_fs9Host, &CFs9Host::statusChanged, this, &CSimulatorFs9::ps_changeHostStatus); - connect(&m_hostThread, &QThread::finished, m_fs9Host, &CFs9Host::deleteLater); - connect(&m_hostThread, &QThread::finished, &m_hostThread, &QThread::deleteLater); - m_hostThread.start(); + connect(m_fs9Host.data(), &CFs9Host::customPacketReceived, this, &CSimulatorFs9::ps_processFs9Message); + connect(m_fs9Host.data(), &CFs9Host::statusChanged, this, &CSimulatorFs9::ps_changeHostStatus); + m_fs9Host->start(); } CSimulatorFs9::~CSimulatorFs9() { - disconnectFrom(); - m_hostThread.quit(); - m_hostThread.wait(1000); - - QList clientThreads = m_fs9ClientThreads.values(); - for (QThread *clientThread : clientThreads) clientThread->wait(); + Q_ASSERT(!m_isHosting); } bool CSimulatorFs9::isConnected() const @@ -95,29 +85,23 @@ namespace BlackSimPlugin { disconnectAllClients(); - // We tell the host to terminate and stop the thread afterwards - QMetaObject::invokeMethod(m_fs9Host, "stopHosting"); emit connectionStatusChanged(ISimulator::Disconnected); + if (m_fs9Host) { m_fs9Host->quit(); } m_fsuipc->disconnect(); - return false; + m_isHosting = false; + + return true; } void CSimulatorFs9::addRemoteAircraft(const CCallsign &callsign, const BlackMisc::Aviation::CAircraftSituation &initialSituation) { - - // Create a new client thread, set update frequency to 25 ms and start it - QThread *clientThread = new QThread(this); - CFs9Client *client = new CFs9Client(callsign.toQString(), CTime(25, CTimeUnit::ms())); + CFs9Client *client = new CFs9Client(this, callsign.toQString(), CTime(25, CTimeUnit::ms())); client->setHostAddress(m_fs9Host->getHostAddress()); client->setPlayerUserId(m_fs9Host->getPlayerUserId()); - client->moveToThread(clientThread); - connect(clientThread, &QThread::started, client, &CFs9Client::init); - connect(client, &CFs9Client::statusChanged, this, &CSimulatorFs9::ps_changeClientStatus); - m_fs9ClientThreads.insert(client, clientThread); + client->start(); m_hashFs9Clients.insert(callsign, client); - clientThread->start(); addAircraftSituation(callsign, initialSituation); } @@ -137,10 +121,11 @@ namespace BlackSimPlugin { if(!m_hashFs9Clients.contains(callsign)) return; - CFs9Client *fs9Client = m_hashFs9Clients.value(callsign); + auto fs9Client = m_hashFs9Clients.value(callsign); - // Send an async disconnect signal. When finished we will clean up - QMetaObject::invokeMethod(fs9Client, "disconnectFrom"); + fs9Client->quit(); + + m_hashFs9Clients.remove(callsign); } bool CSimulatorFs9::updateOwnSimulatorCockpit(const CAircraft &ownAircraft) @@ -294,10 +279,6 @@ namespace BlackSimPlugin } case CFs9Host::Terminated: { - m_fs9Host->deleteLater(); - qDebug() << "Quitting thread"; - connect(&m_hostThread, &QThread::finished, &m_hostThread, &QThread::deleteLater); - m_hostThread.quit(); m_isHosting = false; emit connectionStatusChanged(Disconnected); break; @@ -307,30 +288,6 @@ namespace BlackSimPlugin } } - void CSimulatorFs9::ps_changeClientStatus(const QString &callsign, CFs9Client::ClientStatus status) - { - switch (status) - { - case CFs9Client::Disconnected: - { - CFs9Client *client = m_hashFs9Clients.value(callsign); - Q_ASSERT(m_fs9ClientThreads.contains(client)); - QThread *clientThread = m_fs9ClientThreads.value(client); - - // Cleanup - client->deleteLater(); - connect(clientThread, &QThread::finished, clientThread, &QThread::deleteLater); - clientThread->quit(); - - m_fs9ClientThreads.remove(client); - m_hashFs9Clients.remove(callsign); - break; - } - default: - break; - } - } - void CSimulatorFs9::updateOwnAircraftFromSim(const CAircraft &ownAircraft) { m_ownAircraft.setCom1System(ownAircraft.getCom1System()); @@ -340,7 +297,7 @@ namespace BlackSimPlugin void CSimulatorFs9::disconnectAllClients() { - // Stop all FS9 client threads + // Stop all FS9 client tasks for (auto fs9Client : m_hashFs9Clients.keys()) { removeRemoteAircraft(fs9Client); diff --git a/src/plugins/simulator/fs9/simulator_fs9.h b/src/plugins/simulator/fs9/simulator_fs9.h index d00d5614f..5e46d2ad0 100644 --- a/src/plugins/simulator/fs9/simulator_fs9.h +++ b/src/plugins/simulator/fs9/simulator_fs9.h @@ -142,9 +142,6 @@ namespace BlackSimPlugin //! Change DirectPlay host status void ps_changeHostStatus(BlackSimPlugin::Fs9::CFs9Host::HostStatus status); - //! Change client status for callsign - void ps_changeClientStatus(const QString &callsign, BlackSimPlugin::Fs9::CFs9Client::ClientStatus status); - private: //! Called when data about our own aircraft are received @@ -153,16 +150,14 @@ namespace BlackSimPlugin void disconnectAllClients(); // DirectPlay object handling - CFs9Host *m_fs9Host = nullptr; - QThread m_hostThread; + QPointer m_fs9Host; bool m_isHosting = false; //!< Is sim connected bool m_startedLobbyConnection = false; bool m_syncTime = false; //!< Time synchronized? int m_syncDeferredCounter = 0; //!< Set when synchronized, used to wait some time bool m_simPaused = false; //!< Simulator paused? - QHash m_hashFs9Clients; - QHash m_fs9ClientThreads; + QHash> m_hashFs9Clients; CLobbyClient *m_lobbyClient;