feat: Add support for FSD mute packet

Fixes #254
This commit is contained in:
Lars Toenning
2024-03-10 16:48:23 +01:00
parent 33123cbba9
commit 26bea26e6d
10 changed files with 135 additions and 2 deletions

View File

@@ -152,6 +152,8 @@ add_library(core SHARED
fsd/pilotdataupdate.cpp
fsd/ping.cpp
fsd/messagebase.cpp
fsd/mute.cpp
fsd/mute.h
fsd/enums.h
fsd/deleteatc.h
fsd/clientidentification.h

View File

@@ -114,9 +114,17 @@ namespace BlackCore::Afv::Clients
{
if (m_connectedWithContext) { return; }
if (!hasContexts()) { return; }
this->disconnect(sApp->getIContextOwnAircraft());
sApp->getIContextOwnAircraft()->disconnect(this);
// Disconnect all previously connect signals between the AfvClient and the required contexts
for (auto context : QVector<QObject *> { sApp->getIContextOwnAircraft(), sApp->getIContextNetwork() })
{
this->disconnect(context);
context->disconnect(this);
}
connect(sApp->getIContextOwnAircraft(), &IContextOwnAircraft::changedAircraftCockpit, this, &CAfvClient::onUpdateTransceiversFromContext, Qt::QueuedConnection);
connect(sApp->getIContextNetwork(), &IContextNetwork::muteRequestReceived, this, &CAfvClient::toggleTransmissionCapability, Qt::QueuedConnection);
m_connectedWithContext = true;
}
@@ -678,6 +686,12 @@ namespace BlackCore::Afv::Clients
return;
}
if (active && m_disableTransmissionCapability)
{
// Block transmissions
return;
}
if (m_transmit == active) { return; }
m_transmit = active;
@@ -1305,6 +1319,18 @@ namespace BlackCore::Afv::Clients
});
}
void CAfvClient::toggleTransmissionCapability(bool disableTransmission)
{
if (m_disableTransmissionCapability == disableTransmission) { return; }
m_disableTransmissionCapability = disableTransmission;
if (disableTransmission)
{
// Stop current transmissions
setPtt(false);
}
}
QVector<StationDto> CAfvClient::getAliasedStations() const
{
QMutexLocker lock(&m_mutex);

View File

@@ -339,6 +339,10 @@ namespace BlackCore::Afv::Clients
//! Connect again in given ms
void reconnectTo(const QString &cid, const QString &password, const QString &callsign, const QString &client, int delayMs, const BlackMisc::CStatusMessage &msg);
//! Toggle (enable/disable) the transmission capability.
//! This is triggered by the #MU FSD packet to mute the user remotely.
void toggleTransmissionCapability(bool disableTransmission);
//! @{
//! All aliased stations
//! \threadsafe
@@ -385,6 +389,7 @@ namespace BlackCore::Afv::Clients
std::atomic_bool m_transmit { false };
std::atomic_bool m_transmitHistory { false };
std::atomic_bool m_disableTransmissionCapability { false }; //!< whether the user should be unable to transmit
QVector<TxTransceiverDto> m_transmittingTransceivers;
QVector<TransceiverDto> m_transceivers;
QSet<quint16> m_enabledTransceivers;

View File

@@ -145,6 +145,9 @@ namespace BlackCore::Context
//! Network error
void severeNetworkError(const QString &errorMessage);
//! Mute request received
void muteRequestReceived(bool mute);
//! Connection status changed
//! \sa IContextNetwork::connectedServerChanged
void connectionStatusChanged(const BlackMisc::Network::CConnectionStatus &from, const BlackMisc::Network::CConnectionStatus &to);

View File

@@ -69,6 +69,7 @@ namespace BlackCore::Context
connect(m_fsdClient, &CFSDClient::textMessagesReceived, this, &CContextNetwork::onTextMessagesReceived, Qt::QueuedConnection);
connect(m_fsdClient, &CFSDClient::textMessageSent, this, &CContextNetwork::onTextMessageSent, Qt::QueuedConnection);
connect(m_fsdClient, &CFSDClient::severeNetworkError, this, &CContextNetwork::severeNetworkError, Qt::QueuedConnection);
connect(m_fsdClient, &CFSDClient::muteRequestReceived, this, &CContextNetwork::muteRequestReceived, Qt::QueuedConnection);
// 2. Update timer for data (network data such as frequency)
// we use 2 timers so we can query at different times (not too many queirs at once)

View File

@@ -35,6 +35,7 @@
#include "blackcore/fsd/planeinformationfsinn.h"
#include "blackcore/fsd/revbclientparts.h"
#include "blackcore/fsd/rehost.h"
#include "blackcore/fsd/mute.h"
#include "blackmisc/aviation/flightplan.h"
#include "blackmisc/network/rawfsdmessage.h"
@@ -1086,6 +1087,7 @@ namespace BlackCore::Fsd
m_messageTypeMapping["#TM"] = MessageType::TextMessage;
m_messageTypeMapping["#SB"] = MessageType::PilotClientCom;
m_messageTypeMapping["$XX"] = MessageType::Rehost;
m_messageTypeMapping["#MU"] = MessageType::Mute;
// Euroscope
m_messageTypeMapping["SIMDATA"] = MessageType::EuroscopeSimData;
@@ -1664,6 +1666,13 @@ namespace BlackCore::Fsd
initiateConnection(rehostingSocket, rehost.m_hostname);
}
void CFSDClient::handleMute(const QStringList &tokens)
{
const Mute mute = Mute::fromTokens(tokens);
if (mute.receiver() != m_ownCallsign.asString()) { return; }
emit muteRequestReceived(mute.m_mute);
}
void CFSDClient::initiateConnection(std::shared_ptr<QTcpSocket> rehostingSocket, const QString &rehostingHost)
{
const CServer server = this->getServer();
@@ -2306,6 +2315,7 @@ namespace BlackCore::Fsd
case MessageType::VisualPilotDataToggle: handleVisualPilotDataToggle(tokens); break;
case MessageType::EuroscopeSimData: handleEuroscopeSimData(tokens); break;
case MessageType::Rehost: handleRehost(tokens); break;
case MessageType::Mute: handleMute(tokens); break;
// normally we should not get here
default:

View File

@@ -291,6 +291,7 @@ namespace BlackCore::Fsd
void rawFsdMessage(const BlackMisc::Network::CRawFsdMessage &rawFsdMessage);
void planeInformationFsinnReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineIcaoDesignator, const QString &aircraftDesignator, const QString &combinedAircraftType, const QString &modelString);
void revbAircraftConfigReceived(const QString &sender, const QString &config, qint64 currentOffsetTimeMs);
void muteRequestReceived(bool mute);
//! @}
@@ -442,6 +443,7 @@ namespace BlackCore::Fsd
void handleFsdIdentification(const QStringList &tokens);
void handleRevBClientPartsPacket(const QStringList &tokens);
void handleRehost(const QStringList &tokens);
void handleMute(const QStringList &tokens);
//
void handleUnknownPacket(const QString &line);

View File

@@ -48,6 +48,7 @@ enum class MessageType
RevBClientParts, // IVAO only
RevBPilotDescription, // -PD IVAO only not handled in swift
Rehost,
Mute,
};
namespace BlackCore::Fsd

View File

@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright (C) swift Project Community / Contributors
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
#include "blackcore/fsd/mute.h"
#include "blackmisc/logmessage.h"
namespace BlackCore::Fsd
{
Mute::Mute(const QString &sender, const QString &receiver, bool mute)
: MessageBase(sender, receiver),
m_mute(mute)
{}
QStringList Mute::toTokens() const
{
QStringList tokens;
tokens.push_back(m_sender);
tokens.push_back(m_receiver);
tokens.push_back(QString::number(m_mute ? 1 : 0));
return tokens;
}
Mute Mute::fromTokens(const QStringList &tokens)
{
if (tokens.size() < 3)
{
BlackMisc::CLogMessage(static_cast<Mute *>(nullptr)).debug(u"Wrong number of arguments.");
return {};
};
return Mute(tokens[0], tokens[1], tokens[2] == QStringLiteral("1"));
}
}

50
src/blackcore/fsd/mute.h Normal file
View File

@@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: Copyright (C) swift Project Community / Contributors
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
//! \file
#ifndef BLACKCORE_FSD_MUTE_H
#define BLACKCORE_FSD_MUTE_H
#include "blackcore/fsd/messagebase.h"
namespace BlackCore::Fsd
{
//! Mute the user for AFV
class BLACKCORE_EXPORT Mute : public MessageBase
{
public:
//! Constructor
Mute(const QString &sender, const QString &receiver, bool mute);
//! Message converted to tokens
QStringList toTokens() const;
//! Construct from tokens
static Mute fromTokens(const QStringList &tokens);
//! PDU identifier
static QString pdu() { return "#MU"; }
bool m_mute = false; //!< Flag whether the user should be muted/unmuted
private:
Mute() = default;
};
//! Equal to operator
inline bool operator==(const Mute &lhs, const Mute &rhs)
{
return lhs.sender() == rhs.sender() &&
lhs.receiver() == rhs.receiver() &&
lhs.m_mute == rhs.m_mute;
}
//! Not equal to operator
inline bool operator!=(const Mute &lhs, const Mute &rhs)
{
return !(lhs == rhs);
}
}
#endif // guard