mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 20:07:04 +08:00
refs #334 FS9 DirectPlay peer classes using CContinuousWorker.
This commit is contained in:
committed by
Roland Winklmeier
parent
2a1541786a
commit
195c909ca0
@@ -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)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "fs9.h"
|
||||
#include "host_node.h"
|
||||
#include "callback_wrapper.h"
|
||||
#include "blackmisc/worker.h"
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QMutex>
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "blackmisc/coordinategeodetic.h"
|
||||
#include <QScopedArrayPointer>
|
||||
|
||||
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()));
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <QTimer>
|
||||
#include <algorithm>
|
||||
|
||||
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<QThread *> 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);
|
||||
|
||||
@@ -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<CFs9Host> 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<BlackMisc::Aviation::CCallsign, CFs9Client *> m_hashFs9Clients;
|
||||
QHash<CFs9Client *, QThread *> m_fs9ClientThreads;
|
||||
QHash<BlackMisc::Aviation::CCallsign, QPointer<CFs9Client>> m_hashFs9Clients;
|
||||
|
||||
CLobbyClient *m_lobbyClient;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user