[AFV] Ref T739, audio can now be disabled from UI

This commit is contained in:
Klaus Basan
2019-10-26 02:54:11 +02:00
committed by Mat Sutcliffe
parent c8097cc899
commit 9447db00bc
10 changed files with 197 additions and 66 deletions

View File

@@ -186,13 +186,13 @@ namespace BlackCore
}
}
void CAfvClient::disconnectFrom()
void CAfvClient::disconnectFrom(bool stop)
{
if (QThread::currentThread() != thread())
{
// Method needs to be executed in the object thread since it will create new QObject children
QPointer<CAfvClient> myself(this);
QMetaObject::invokeMethod(this, [ = ]() { if (myself) disconnectFrom(); });
QMetaObject::invokeMethod(this, [ = ]() { if (myself) disconnectFrom(stop); });
return;
}
@@ -203,6 +203,8 @@ namespace BlackCore
m_connection->disconnectFrom();
}
emit connectionStatusChanged(Disconnected);
if (stop) { this->stopAudio(); }
}
QStringList CAfvClient::availableInputDevices() const

View File

@@ -94,7 +94,11 @@ namespace BlackCore
//! Disconnect from network
//! \threadsafe
//! \remark runs in thread of CAfvClient object and is ASYNC when called from another thread
Q_INVOKABLE void disconnectFrom();
//! @{
void disconnectFrom(bool stop);
Q_INVOKABLE void disconnectFrom() { this->disconnectFrom(false); }
void disconnectFromAndStop() { this->disconnectFrom(true); }
//! @}
//! Audio devices @{
Q_INVOKABLE QStringList availableInputDevices() const;

View File

@@ -30,9 +30,9 @@ namespace BlackCore
{
CLogMessage(this).debug(u"ClientConnection instantiated");
// connect(&m_apiServerConnection, &ApiServerConnection::authenticationFinished, this, &ClientConnection::apiConnectionFinished);
// connect(&m_apiServerConnection, &ApiServerConnection::addCallsignFinished, this, &ClientConnection::addCallsignFinished);
// connect(&m_apiServerConnection, &ApiServerConnection::removeCallsignFinished, this, &ClientConnection::removeCallsignFinished);
// connect(&m_apiServerConnection, &ApiServerConnection::authenticationFinished, this, &ClientConnection::apiConnectionFinished);
// connect(&m_apiServerConnection, &ApiServerConnection::addCallsignFinished, this, &ClientConnection::addCallsignFinished);
// connect(&m_apiServerConnection, &ApiServerConnection::removeCallsignFinished, this, &ClientConnection::removeCallsignFinished);
connect(m_voiceServerTimer, &QTimer::timeout, this, &CClientConnection::voiceServerHeartbeat);
connect(m_udpSocket, &QUdpSocket::readyRead, this, &CClientConnection::readPendingDatagrams);
@@ -69,7 +69,7 @@ namespace BlackCore
this->connectToVoiceServer();
// taskServerConnectionCheck.Start();
CLogMessage(this).debug(u"Connected: '%1'") << callsign;
CLogMessage(this).info(u"Connected: '%1' to voice server, socket open: ") << callsign << boolToYesNo(m_udpSocket->isOpen());
}
// callback of the calling parent
@@ -121,11 +121,11 @@ namespace BlackCore
void CClientConnection::connectToVoiceServer()
{
QHostAddress localAddress(QHostAddress::AnyIPv4);
const QHostAddress localAddress(QHostAddress::AnyIPv4);
m_udpSocket->bind(localAddress);
m_voiceServerTimer->start(3000);
CLogMessage(this).info(u"Connected to voice server '%1'") << m_connection.getTokens().VoiceServer.addressIpV4;
CLogMessage(this).info(u"Connected to voice server '%2'") << m_connection.getTokens().VoiceServer.addressIpV4;
}
void CClientConnection::disconnectFromVoiceServer()

View File

@@ -111,6 +111,32 @@ namespace BlackCore
CIdentifiable(this),
m_voiceClient(new CAfvClient(CVoiceSetup().getAfvVoiceServerUrl(), this))
{
this->initVoiceClient();
const CSettings as = m_audioSettings.getThreadLocal();
this->setVoiceOutputVolume(as.getOutVolume());
m_selcalPlayer = new CSelcalPlayer(CAudioDeviceInfo::getDefaultOutputDevice(), this);
this->changeDeviceSettings();
QPointer<CContextAudioBase> myself(this);
QTimer::singleShot(5000, this, [ = ]
{
if (!myself || !sApp || sApp->isShuttingDown()) { return; }
myself->onChangedAudioSettings();
});
}
CContextAudioBase::~CContextAudioBase()
{
this->gracefulShutdown();
}
void CContextAudioBase::initVoiceClient()
{
if (!m_voiceClient)
{
m_voiceClient = new CAfvClient(CVoiceSetup().getAfvVoiceServerUrl(), this);
}
const CVoiceSetup vs = m_voiceSettings.getThreadLocal();
m_voiceClient->updateVoiceServerUrl(vs.getAfvVoiceServerUrl());
@@ -144,33 +170,16 @@ namespace BlackCore
connect(m_voiceClient, &CAfvClient::startedAudio, this, &CContextAudioBase::startedAudio, Qt::QueuedConnection);
connect(m_voiceClient, &CAfvClient::stoppedAudio, this, &CContextAudioBase::stoppedAudio, Qt::QueuedConnection);
connect(m_voiceClient, &CAfvClient::ptt, this, &CContextAudioBase::ptt, Qt::QueuedConnection);
const CSettings as = m_audioSettings.getThreadLocal();
this->setVoiceOutputVolume(as.getOutVolume());
m_selcalPlayer = new CSelcalPlayer(CAudioDeviceInfo::getDefaultOutputDevice(), this);
this->changeDeviceSettings();
QPointer<CContextAudioBase> myself(this);
QTimer::singleShot(5000, this, [ = ]
{
if (!myself || !sApp || sApp->isShuttingDown()) { return; }
myself->onChangedAudioSettings();
});
}
CContextAudioBase::~CContextAudioBase()
{
gracefulShutdown();
}
void CContextAudioBase::gracefulShutdown()
void CContextAudioBase::terminateVoiceClient()
{
if (m_voiceClient)
{
m_voiceClient->gracefulShutdown();
Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(m_voiceClient), Q_FUNC_INFO, "Needs to be back in current thread");
m_voiceClient->deleteLater();
m_voiceClient = nullptr;
#ifdef Q_OS_WIN
if (m_winCoInitialized)
{
@@ -179,9 +188,23 @@ namespace BlackCore
}
#endif
}
}
void CContextAudioBase::gracefulShutdown()
{
this->terminateVoiceClient();
QObject::disconnect(this);
}
void CContextAudioBase::enableVoiceClientAndStart()
{
this->initVoiceClient();
if (m_voiceClient) {
m_voiceClient->startAudio();
this->connectAudioWithNetworkCredentials();
}
}
const CIdentifier &CContextAudioBase::audioRunsWhere() const
{
static const CIdentifier i("CContextAudioBaseImpl");
@@ -200,6 +223,28 @@ namespace BlackCore
return m_voiceClient->isTransmittingdComUnit(comUnit);
}
bool CContextAudioBase::connectAudioWithNetworkCredentials()
{
if (!m_voiceClient) { return false; }
if (!sApp || sApp->isShuttingDown() || !sApp->getIContextNetwork()) { return false; }
const CEcosystem ecoSystem = this->getIContextNetwork()->getConnectedServer().getEcosystem();
if (ecoSystem != CEcosystem::vatsim())
{
CLogMessage(this).info(u"Will not use AFV as ecosystem is '%1'") << ecoSystem.toQString(true);
return false;
}
const CVoiceSetup vs = m_voiceSettings.getThreadLocal();
m_voiceClient->updateVoiceServerUrl(vs.getAfvVoiceServerUrl());
const CUser connectedUser = this->getIContextNetwork()->getConnectedServer().getUser();
const QString client = "swift " % BlackConfig::CBuildConfig::getShortVersionString();
m_voiceClient->connectTo(connectedUser.getId(), connectedUser.getPassword(), connectedUser.getCallsign().asString(), client);
return true;
}
bool CContextAudioBase::isAudioConnected() const
{
return m_voiceClient && m_voiceClient->isConnected();
@@ -212,7 +257,7 @@ namespace BlackCore
QString CContextAudioBase::audioRunsWhereInfo() const
{
static const QString s = QStringLiteral("Audio on '%1', '%2'.").arg(audioRunsWhere().getMachineName(), audioRunsWhere().getProcessName());
const QString s = QStringLiteral("[%1] Audio on '%2', '%3'.").arg(boolToEnabledDisabled(this->isAudioStarted()), audioRunsWhere().getMachineName(), audioRunsWhere().getProcessName());
return s;
}
@@ -439,19 +484,7 @@ namespace BlackCore
// we only change network connection of AFC client here
if (to.isConnected() && this->getIContextNetwork())
{
const CEcosystem ecoSystem = this->getIContextNetwork()->getConnectedServer().getEcosystem();
if (ecoSystem != CEcosystem::vatsim())
{
CLogMessage(this).info(u"Will not use AFV as ecosystem is '%1'") << ecoSystem.toQString(true);
return;
}
const CVoiceSetup vs = m_voiceSettings.getThreadLocal();
m_voiceClient->updateVoiceServerUrl(vs.getAfvVoiceServerUrl());
const CUser connectedUser = this->getIContextNetwork()->getConnectedServer().getUser();
const QString client = "swift " % BlackConfig::CBuildConfig::getShortVersionString();
m_voiceClient->connectTo(connectedUser.getId(), connectedUser.getPassword(), connectedUser.getCallsign().asString(), client);
this->connectAudioWithNetworkCredentials();
}
else if (to.isDisconnected())
{

View File

@@ -41,7 +41,6 @@
// clazy:excludeall=const-signal-or-slot
//! \addtogroup dbus
//! @{
@@ -123,6 +122,12 @@ namespace BlackCore
//! Graceful shutdown
void gracefulShutdown();
//! Enable/disable @{
void enableVoiceClient() { this->initVoiceClient(); }
void enableVoiceClientAndStart();
void disableVoiceClient() { this->terminateVoiceClient(); }
//! @}
// -------- parts which can run in core and GUI, referring to local voice client ------------
//! Audio devices
@@ -177,12 +182,19 @@ namespace BlackCore
//! Is COM unit transmitting?
bool isTransmittingComUnit(BlackMisc::Aviation::CComSystem::ComUnit comUnit) const;
//! Connect to audio with network credentials
//! \remark if there is no network connection/credential this just returns
bool connectAudioWithNetworkCredentials();
//! Is audio connected?
bool isAudioConnected() const;
//! Is audio started?
bool isAudioStarted() const;
//! Is audio enabled?
bool isAudioEnabled() const { return m_voiceClient; }
//! \todo WORKAROUND to hide the "local signals"
Afv::Clients::CAfvClient *afvClient() const { return m_voiceClient; }
@@ -237,11 +249,17 @@ namespace BlackCore
//! Client updated from own aicraft data
void updatedFromOwnAircraftCockpit();
**/
Workaround **/
// ------------ local signals -------
private:
//! Init the voice client
void initVoiceClient();
//! Terminate the voice client
void terminateVoiceClient();
//! Enable/disable voice transmission, nornally used with hotkey
//! @{
void setVoiceTransmission(bool enable, BlackMisc::Audio::PTTCOM com);