mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-21 04:45:31 +08:00
Ref T730, AFV client
* restart function * bogus mute function (needs implementation) * float -> double * log categories * settings
This commit is contained in:
committed by
Mat Sutcliffe
parent
835fdc478a
commit
661a6576c5
@@ -10,6 +10,7 @@
|
|||||||
#include "blackcore/context/contextownaircraft.h"
|
#include "blackcore/context/contextownaircraft.h"
|
||||||
#include "blackcore/application.h"
|
#include "blackcore/application.h"
|
||||||
#include "blacksound/audioutilities.h"
|
#include "blacksound/audioutilities.h"
|
||||||
|
#include "blackmisc/audio/audiodeviceinfolist.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
using namespace BlackCore::Context;
|
using namespace BlackCore::Context;
|
||||||
@@ -28,8 +29,14 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
namespace Clients
|
namespace Clients
|
||||||
{
|
{
|
||||||
|
const CLogCategoryList &CAfvClient::getLogCategories()
|
||||||
|
{
|
||||||
|
static const CLogCategoryList cats { CLogCategory::audio(), CLogCategory::vatsimSpecific() };
|
||||||
|
return cats;
|
||||||
|
}
|
||||||
|
|
||||||
CAfvClient::CAfvClient(const QString &apiServer, QObject *parent) :
|
CAfvClient::CAfvClient(const QString &apiServer, QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent), CIdentifiable(this)
|
||||||
{
|
{
|
||||||
m_connection = new CClientConnection(apiServer, this);
|
m_connection = new CClientConnection(apiServer, this);
|
||||||
m_connection->setReceiveAudio(false);
|
m_connection->setReceiveAudio(false);
|
||||||
@@ -40,9 +47,7 @@ namespace BlackCore
|
|||||||
|
|
||||||
m_output = new Output(this);
|
m_output = new Output(this);
|
||||||
connect(m_output, &Output::outputVolumeStream, this, &CAfvClient::outputVolumeStream);
|
connect(m_output, &Output::outputVolumeStream, this, &CAfvClient::outputVolumeStream);
|
||||||
|
|
||||||
connect(m_connection, &CClientConnection::audioReceived, this, &CAfvClient::audioOutDataAvailable);
|
connect(m_connection, &CClientConnection::audioReceived, this, &CAfvClient::audioOutDataAvailable);
|
||||||
|
|
||||||
connect(&m_voiceServerPositionTimer, &QTimer::timeout, this, qOverload<>(&CAfvClient::updateTransceivers));
|
connect(&m_voiceServerPositionTimer, &QTimer::timeout, this, qOverload<>(&CAfvClient::updateTransceivers));
|
||||||
|
|
||||||
m_transceivers =
|
m_transceivers =
|
||||||
@@ -54,7 +59,10 @@ namespace BlackCore
|
|||||||
m_enabledTransceivers = { 0, 1 };
|
m_enabledTransceivers = { 0, 1 };
|
||||||
m_transmittingTransceivers = { { 0 } }; // TxTransceiverDto
|
m_transmittingTransceivers = { { 0 } }; // TxTransceiverDto
|
||||||
|
|
||||||
qDebug() << "UserClient instantiated";
|
// init by settings
|
||||||
|
this->onSettingsChanged();
|
||||||
|
|
||||||
|
CLogMessage(this).info(u"UserClient instantiated");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::initWithContext()
|
void CAfvClient::initWithContext()
|
||||||
@@ -72,8 +80,8 @@ namespace BlackCore
|
|||||||
m_connection->connectTo(cid, password, callsign);
|
m_connection->connectTo(cid, password, callsign);
|
||||||
this->updateTransceivers();
|
this->updateTransceivers();
|
||||||
|
|
||||||
if (m_connection->isConnected()) { emit connectionStatusChanged(Connected); }
|
if (m_connection->isConnected()) { emit this->connectionStatusChanged(Connected); }
|
||||||
else { emit connectionStatusChanged(Disconnected); }
|
else { emit this->connectionStatusChanged(Disconnected); }
|
||||||
|
|
||||||
m_connection->getAllAliasedStations();
|
m_connection->getAllAliasedStations();
|
||||||
}
|
}
|
||||||
@@ -86,26 +94,12 @@ namespace BlackCore
|
|||||||
|
|
||||||
QStringList CAfvClient::availableInputDevices() const
|
QStringList CAfvClient::availableInputDevices() const
|
||||||
{
|
{
|
||||||
const QList<QAudioDeviceInfo> inputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
|
return CAudioDeviceInfoList::allQtInputDevices().getDeviceNames();
|
||||||
|
|
||||||
QStringList deviceNames;
|
|
||||||
for (const QAudioDeviceInfo &inputDevice : inputDevices)
|
|
||||||
{
|
|
||||||
deviceNames << inputDevice.deviceName();
|
|
||||||
}
|
|
||||||
return deviceNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CAfvClient::availableOutputDevices() const
|
QStringList CAfvClient::availableOutputDevices() const
|
||||||
{
|
{
|
||||||
const QList<QAudioDeviceInfo> outputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
|
return CAudioDeviceInfoList::allQtOutputDevices().getDeviceNames();
|
||||||
|
|
||||||
QStringList deviceNames;
|
|
||||||
for (const QAudioDeviceInfo &outputDevice : outputDevices)
|
|
||||||
{
|
|
||||||
deviceNames << outputDevice.deviceName();
|
|
||||||
}
|
|
||||||
return deviceNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::setBypassEffects(bool value)
|
void CAfvClient::setBypassEffects(bool value)
|
||||||
@@ -116,11 +110,28 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CAfvClient::isMuted() const
|
||||||
|
{
|
||||||
|
return !this->isStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAfvClient::setMuted(bool mute)
|
||||||
|
{
|
||||||
|
Q_UNUSED(mute)
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAfvClient::restartWithNewDevices(const QAudioDeviceInfo &inputDevice, const QAudioDeviceInfo &outputDevice)
|
||||||
|
{
|
||||||
|
this->stop();
|
||||||
|
this->start(inputDevice, outputDevice, allTransceiverIds());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CAfvClient::start(const QAudioDeviceInfo &inputDevice, const QAudioDeviceInfo &outputDevice, const QVector<quint16> &transceiverIDs)
|
void CAfvClient::start(const QAudioDeviceInfo &inputDevice, const QAudioDeviceInfo &outputDevice, const QVector<quint16> &transceiverIDs)
|
||||||
{
|
{
|
||||||
if (m_isStarted)
|
if (m_isStarted)
|
||||||
{
|
{
|
||||||
qDebug() << "Client already started";
|
CLogMessage(this).info(u"Client already started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,59 +140,28 @@ namespace BlackCore
|
|||||||
outputSampleProvider = new CVolumeSampleProvider(soundcardSampleProvider, this);
|
outputSampleProvider = new CVolumeSampleProvider(soundcardSampleProvider, this);
|
||||||
outputSampleProvider->setVolume(m_outputVolume);
|
outputSampleProvider->setVolume(m_outputVolume);
|
||||||
|
|
||||||
m_output->start(outputDevice, outputSampleProvider);
|
m_output->start(outputDevice.isNull() ? QAudioDeviceInfo::defaultOutputDevice() : outputDevice, outputSampleProvider);
|
||||||
m_input->start(inputDevice);
|
m_input->start(inputDevice.isNull() ? QAudioDeviceInfo::defaultInputDevice() : inputDevice);
|
||||||
|
|
||||||
m_startDateTimeUtc = QDateTime::currentDateTimeUtc();
|
m_startDateTimeUtc = QDateTime::currentDateTimeUtc();
|
||||||
m_connection->setReceiveAudio(true);
|
m_connection->setReceiveAudio(true);
|
||||||
m_voiceServerPositionTimer.start(5000);
|
m_voiceServerPositionTimer.start(5000);
|
||||||
m_isStarted = true;
|
m_isStarted = true;
|
||||||
qDebug() << ("Started [Input: " + inputDevice.deviceName() + "] [Output: " + outputDevice.deviceName() + "]");
|
CLogMessage(this).info(u"Started [Input: %1] [Output: %2]") << inputDevice.deviceName() << outputDevice.deviceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::start(const QString &inputDeviceName, const QString &outputDeviceName)
|
void CAfvClient::start(const QString &inputDeviceName, const QString &outputDeviceName)
|
||||||
{
|
{
|
||||||
if (m_isStarted) { return; }
|
const QAudioDeviceInfo i = CAudioDeviceInfoList::allQtInputDevices().findByName(inputDeviceName).toAudioDeviceInfo();
|
||||||
|
const QAudioDeviceInfo o = CAudioDeviceInfoList::allQtOutputDevices().findByName(outputDeviceName).toAudioDeviceInfo();
|
||||||
soundcardSampleProvider = new CSoundcardSampleProvider(SampleRate, { 0, 1 }, this);
|
this->start(i, o, allTransceiverIds());
|
||||||
connect(soundcardSampleProvider, &CSoundcardSampleProvider::receivingCallsignsChanged, this, &CAfvClient::receivingCallsignsChanged);
|
|
||||||
outputSampleProvider = new CVolumeSampleProvider(soundcardSampleProvider, this);
|
|
||||||
outputSampleProvider->setVolume(m_outputVolume);
|
|
||||||
|
|
||||||
QAudioDeviceInfo inputDevice = QAudioDeviceInfo::defaultInputDevice();
|
|
||||||
for (const auto &device : QAudioDeviceInfo::availableDevices(QAudio::AudioInput))
|
|
||||||
{
|
|
||||||
if (device.deviceName().startsWith(inputDeviceName))
|
|
||||||
{
|
|
||||||
inputDevice = device;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QAudioDeviceInfo outputDevice = QAudioDeviceInfo::defaultOutputDevice();
|
|
||||||
for (const auto &device : QAudioDeviceInfo::availableDevices(QAudio::AudioOutput))
|
|
||||||
{
|
|
||||||
if (device.deviceName().startsWith(outputDeviceName))
|
|
||||||
{
|
|
||||||
outputDevice = device;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_output->start(outputDevice, outputSampleProvider);
|
|
||||||
m_input->start(inputDevice);
|
|
||||||
|
|
||||||
m_startDateTimeUtc = QDateTime::currentDateTimeUtc();
|
|
||||||
m_connection->setReceiveAudio(true);
|
|
||||||
m_voiceServerPositionTimer.start(5000);
|
|
||||||
m_isStarted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::stop()
|
void CAfvClient::stop()
|
||||||
{
|
{
|
||||||
if (! m_isStarted)
|
if (!m_isStarted)
|
||||||
{
|
{
|
||||||
qDebug() << "Client not started";
|
CLogMessage(this).info(u"Client NOT started");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +173,7 @@ namespace BlackCore
|
|||||||
|
|
||||||
m_input->stop();
|
m_input->stop();
|
||||||
m_output->stop();
|
m_output->stop();
|
||||||
|
CLogMessage(this).info(u"Client NOT stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::enableTransceiver(quint16 id, bool enable)
|
void CAfvClient::enableTransceiver(quint16 id, bool enable)
|
||||||
@@ -212,9 +193,9 @@ namespace BlackCore
|
|||||||
|
|
||||||
if (m_transceivers.size() >= id + 1)
|
if (m_transceivers.size() >= id + 1)
|
||||||
{
|
{
|
||||||
if (m_transceivers[id].frequency != roundedFrequencyHz)
|
if (m_transceivers[id].frequencyHz != roundedFrequencyHz)
|
||||||
{
|
{
|
||||||
m_transceivers[id].frequency = roundedFrequencyHz;
|
m_transceivers[id].frequencyHz = roundedFrequencyHz;
|
||||||
updateTransceivers();
|
updateTransceivers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,7 +257,14 @@ namespace BlackCore
|
|||||||
|
|
||||||
void CAfvClient::setPtt(bool active)
|
void CAfvClient::setPtt(bool active)
|
||||||
{
|
{
|
||||||
if (! m_isStarted)
|
this->setPttForCom(active, COMUnspecified);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAfvClient::setPttForCom(bool active, PTTCOM com)
|
||||||
|
{
|
||||||
|
Q_UNUSED(com)
|
||||||
|
|
||||||
|
if (!m_isStarted)
|
||||||
{
|
{
|
||||||
qDebug() << "Client not started";
|
qDebug() << "Client not started";
|
||||||
return;
|
return;
|
||||||
@@ -301,20 +289,50 @@ namespace BlackCore
|
|||||||
m_maxDbReadingInPTTInterval = -100;
|
m_maxDbReadingInPTTInterval = -100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit this->ptt(active, com, this->identifier());
|
||||||
qDebug() << "PTT:" << active;
|
qDebug() << "PTT:" << active;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::setPttForCom(bool active, PTTCOM com)
|
|
||||||
{
|
|
||||||
this->setPtt(active);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAfvClient::setInputVolumeDb(double value)
|
void CAfvClient::setInputVolumeDb(double value)
|
||||||
{
|
{
|
||||||
if (value > 18) { value = 18; }
|
if (value > MaxDb) { value = MaxDb; }
|
||||||
if (value < -18) { value = -18; }
|
if (value < MinDb) { value = MinDb; }
|
||||||
m_inputVolumeDb = value;
|
m_inputVolumeDb = value;
|
||||||
m_input->setVolume(qPow(10, value / 20));
|
m_input->setVolume(qPow(10, value / 20.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
int CAfvClient::getNormalizedInputVolume() const
|
||||||
|
{
|
||||||
|
const double db = this->getInputVolumeDb();
|
||||||
|
const double range = MaxDb - MinDb;
|
||||||
|
const int i = qRound((db - MinDb) / range * 100);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CAfvClient::getNormalizedOutputVolume() const
|
||||||
|
{
|
||||||
|
const double db = this->getOutputVolumeDb();
|
||||||
|
const double range = MaxDb - MinDb;
|
||||||
|
const int i = qRound((db - MinDb) / range * 100);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAfvClient::setNormalizedInputVolume(int volume)
|
||||||
|
{
|
||||||
|
if (volume < 0) { volume = 0; }
|
||||||
|
else if (volume > 100) { volume = 100; }
|
||||||
|
const double range = MaxDb - MinDb;
|
||||||
|
const double dB = MinDb + (volume * range / 100.0);
|
||||||
|
this->setInputVolumeDb(dB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAfvClient::setNormalizedOutputVolume(int volume)
|
||||||
|
{
|
||||||
|
if (volume < 0) { volume = 0; }
|
||||||
|
else if (volume > 100) { volume = 100; }
|
||||||
|
const double range = MaxDb - MinDb;
|
||||||
|
const double dB = MinDb + (volume * range / 100.0);
|
||||||
|
this->setOutputVolumeDb(dB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::opusDataAvailable(const OpusDataAvailableArgs &args)
|
void CAfvClient::opusDataAvailable(const OpusDataAvailableArgs &args)
|
||||||
@@ -326,8 +344,9 @@ namespace BlackCore
|
|||||||
audioData.callsign = "loopback";
|
audioData.callsign = "loopback";
|
||||||
audioData.lastPacket = false;
|
audioData.lastPacket = false;
|
||||||
audioData.sequenceCounter = 0;
|
audioData.sequenceCounter = 0;
|
||||||
RxTransceiverDto com1 = { 0, m_transceivers[0].frequency, 0.0 };
|
|
||||||
RxTransceiverDto com2 = { 1, m_transceivers[1].frequency, 0.0 };
|
RxTransceiverDto com1 = { 0, m_transceivers.size() > 0 ? m_transceivers[0].frequencyHz : UniCom, 0.0 };
|
||||||
|
RxTransceiverDto com2 = { 1, m_transceivers.size() > 1 ? m_transceivers[1].frequencyHz : UniCom, 0.0 };
|
||||||
|
|
||||||
soundcardSampleProvider->addOpusSamples(audioData, { com1, com2 });
|
soundcardSampleProvider->addOpusSamples(audioData, { com1, com2 });
|
||||||
return;
|
return;
|
||||||
@@ -408,8 +427,10 @@ namespace BlackCore
|
|||||||
|
|
||||||
void CAfvClient::onSettingsChanged()
|
void CAfvClient::onSettingsChanged()
|
||||||
{
|
{
|
||||||
CSettings audioSettings = m_audioSettings.get();
|
const CSettings audioSettings = m_audioSettings.get();
|
||||||
|
this->setNormalizedInputVolume(audioSettings.getInVolume());
|
||||||
|
this->setNormalizedOutputVolume(audioSettings.getOutVolume());
|
||||||
|
this->setBypassEffects(!audioSettings.isAudioEffectsEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAfvClient::updateTransceiversFromContext(const CSimulatedAircraft &aircraft, const CIdentifier &originator)
|
void CAfvClient::updateTransceiversFromContext(const CSimulatedAircraft &aircraft, const CIdentifier &originator)
|
||||||
@@ -448,6 +469,20 @@ namespace BlackCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QAudioDeviceInfo &CAfvClient::getInputDevice() const
|
||||||
|
{
|
||||||
|
if (m_input) { return m_input->device(); }
|
||||||
|
static const QAudioDeviceInfo null = QAudioDeviceInfo();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QAudioDeviceInfo &CAfvClient::getOutputDevice() const
|
||||||
|
{
|
||||||
|
if (m_output) { return m_output->device(); }
|
||||||
|
static const QAudioDeviceInfo null = QAudioDeviceInfo();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
CAfvClient::ConnectionStatus CAfvClient::getConnectionStatus() const
|
CAfvClient::ConnectionStatus CAfvClient::getConnectionStatus() const
|
||||||
{
|
{
|
||||||
return m_connection->isConnected() ? Connected : Disconnected;
|
return m_connection->isConnected() ? Connected : Disconnected;
|
||||||
|
|||||||
@@ -20,10 +20,11 @@
|
|||||||
#include "blackcore/blackcoreexport.h"
|
#include "blackcore/blackcoreexport.h"
|
||||||
|
|
||||||
#include "blacksound/sampleprovider/volumesampleprovider.h"
|
#include "blacksound/sampleprovider/volumesampleprovider.h"
|
||||||
|
|
||||||
#include "blackmisc/settingscache.h"
|
|
||||||
#include "blackmisc/audio/audiosettings.h"
|
#include "blackmisc/audio/audiosettings.h"
|
||||||
#include "blackmisc/audio/ptt.h"
|
#include "blackmisc/audio/ptt.h"
|
||||||
|
#include "blackmisc/logcategorylist.h"
|
||||||
|
#include "blackmisc/identifiable.h"
|
||||||
|
#include "blackmisc/settingscache.h"
|
||||||
|
|
||||||
#include <QAudioDeviceInfo>
|
#include <QAudioDeviceInfo>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -40,16 +41,20 @@ namespace BlackCore
|
|||||||
namespace Clients
|
namespace Clients
|
||||||
{
|
{
|
||||||
//! AFV client
|
//! AFV client
|
||||||
class BLACKCORE_EXPORT CAfvClient final : public QObject
|
class BLACKCORE_EXPORT CAfvClient final : public QObject, public BlackMisc::CIdentifiable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(double inputVolumePeakVU READ getInputVolumePeakVU NOTIFY inputVolumePeakVU)
|
Q_PROPERTY(double inputVolumePeakVU READ getInputVolumePeakVU NOTIFY inputVolumePeakVU)
|
||||||
Q_PROPERTY(double outputVolumePeakVU READ getOutputVolumePeakVU NOTIFY outputVolumePeakVU)
|
Q_PROPERTY(double outputVolumePeakVU READ getOutputVolumePeakVU NOTIFY outputVolumePeakVU)
|
||||||
Q_PROPERTY(ConnectionStatus connectionStatus READ getConnectionStatus NOTIFY connectionStatusChanged)
|
Q_PROPERTY(ConnectionStatus connectionStatus READ getConnectionStatus NOTIFY connectionStatusChanged)
|
||||||
Q_PROPERTY(QString receivingCallsignsCom1 READ getReceivingCallsignsCom1 NOTIFY receivingCallsignsChanged)
|
Q_PROPERTY(QString receivingCallsignsCom1 READ getReceivingCallsignsCom1 NOTIFY receivingCallsignsChanged)
|
||||||
Q_PROPERTY(QString receivingCallsignsCom2 READ getReceivingCallsignsCom2 NOTIFY receivingCallsignsChanged)
|
Q_PROPERTY(QString receivingCallsignsCom2 READ getReceivingCallsignsCom2 NOTIFY receivingCallsignsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
//! Categories
|
||||||
|
static const BlackMisc::CLogCategoryList &getLogCategories();
|
||||||
|
|
||||||
|
//! Connection status
|
||||||
enum ConnectionStatus { Disconnected, Connected };
|
enum ConnectionStatus { Disconnected, Connected };
|
||||||
Q_ENUM(ConnectionStatus)
|
Q_ENUM(ConnectionStatus)
|
||||||
|
|
||||||
@@ -57,13 +62,9 @@ namespace BlackCore
|
|||||||
CAfvClient(const QString &apiServer, QObject *parent = nullptr);
|
CAfvClient(const QString &apiServer, QObject *parent = nullptr);
|
||||||
|
|
||||||
//! Dtor
|
//! Dtor
|
||||||
virtual ~CAfvClient() override
|
virtual ~CAfvClient() override { this->stop(); }
|
||||||
{
|
|
||||||
this->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// void setContextOwnAircraft(const BlackCore::Context::IContextOwnAircraft *contextOwnAircraft);
|
|
||||||
|
|
||||||
|
//! Corresponding callsign
|
||||||
QString callsign() const { return m_callsign; }
|
QString callsign() const { return m_callsign; }
|
||||||
|
|
||||||
bool isConnected() const { return m_connection->isConnected(); }
|
bool isConnected() const { return m_connection->isConnected(); }
|
||||||
@@ -72,14 +73,23 @@ namespace BlackCore
|
|||||||
Q_INVOKABLE void connectTo(const QString &cid, const QString &password, const QString &callsign);
|
Q_INVOKABLE void connectTo(const QString &cid, const QString &password, const QString &callsign);
|
||||||
Q_INVOKABLE void disconnectFrom();
|
Q_INVOKABLE void disconnectFrom();
|
||||||
|
|
||||||
|
//! Audio devices @{
|
||||||
Q_INVOKABLE QStringList availableInputDevices() const;
|
Q_INVOKABLE QStringList availableInputDevices() const;
|
||||||
Q_INVOKABLE QStringList availableOutputDevices() const;
|
Q_INVOKABLE QStringList availableOutputDevices() const;
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
//! Enable/disable VHF simulation, true means effects are NOT used
|
||||||
Q_INVOKABLE void setBypassEffects(bool value);
|
Q_INVOKABLE void setBypassEffects(bool value);
|
||||||
|
|
||||||
bool isStarted() const { return m_isStarted; }
|
bool isStarted() const { return m_isStarted; }
|
||||||
QDateTime getStartDateTimeUt() const { return m_startDateTimeUtc; }
|
QDateTime getStartDateTimeUt() const { return m_startDateTimeUtc; }
|
||||||
|
|
||||||
|
//! Muted @{
|
||||||
|
bool isMuted() const;
|
||||||
|
void setMuted(bool mute);
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
bool restartWithNewDevices(const QAudioDeviceInfo &inputDevice, const QAudioDeviceInfo &outputDevice);
|
||||||
void start(const QAudioDeviceInfo &inputDevice, const QAudioDeviceInfo &outputDevice, const QVector<quint16> &transceiverIDs);
|
void start(const QAudioDeviceInfo &inputDevice, const QAudioDeviceInfo &outputDevice, const QVector<quint16> &transceiverIDs);
|
||||||
Q_INVOKABLE void start(const QString &inputDeviceName, const QString &outputDeviceName);
|
Q_INVOKABLE void start(const QString &inputDeviceName, const QString &outputDeviceName);
|
||||||
void stop();
|
void stop();
|
||||||
@@ -96,29 +106,52 @@ namespace BlackCore
|
|||||||
void setPttForCom(bool active, BlackMisc::Audio::PTTCOM com);
|
void setPttForCom(bool active, BlackMisc::Audio::PTTCOM com);
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
|
//! Loopback @{
|
||||||
Q_INVOKABLE void setLoopBack(bool on) { m_loopbackOn = on; }
|
Q_INVOKABLE void setLoopBack(bool on) { m_loopbackOn = on; }
|
||||||
|
Q_INVOKABLE bool isLoopback() const { return m_loopbackOn; }
|
||||||
|
//! @}
|
||||||
|
|
||||||
//! Input volume in DB, +-18DB @{
|
//! Input volume in dB, +-18dB @{
|
||||||
double getInputVolumeDb() const { return m_inputVolumeDb; }
|
double getInputVolumeDb() const { return m_inputVolumeDb; }
|
||||||
Q_INVOKABLE void setInputVolumeDb(double value);
|
Q_INVOKABLE void setInputVolumeDb(double value);
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
//! Output volume in DB, +-18DB @{
|
//! Output volume in dB, +-18dB @{
|
||||||
double getOutputVolumeDb() const;
|
double getOutputVolumeDb() const;
|
||||||
Q_INVOKABLE void setOutputVolumeDb(double outputVolume);
|
Q_INVOKABLE void setOutputVolumeDb(double outputVolume);
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
|
//! Normalized volumes 0..100 @{
|
||||||
|
int getNormalizedInputVolume() const;
|
||||||
|
int getNormalizedOutputVolume() const;
|
||||||
|
void setNormalizedInputVolume(int volume);
|
||||||
|
void setNormalizedOutputVolume(int volume);
|
||||||
|
//! @}
|
||||||
|
|
||||||
//! VU values, 0..1 @{
|
//! VU values, 0..1 @{
|
||||||
double getInputVolumePeakVU() const { return m_inputVolumeStream.PeakVU; }
|
double getInputVolumePeakVU() const { return m_inputVolumeStream.PeakVU; }
|
||||||
double getOutputVolumePeakVU() const { return m_outputVolumeStream.PeakVU; }
|
double getOutputVolumePeakVU() const { return m_outputVolumeStream.PeakVU; }
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
|
//! Recently used device @{
|
||||||
|
const QAudioDeviceInfo &getInputDevice() const;
|
||||||
|
const QAudioDeviceInfo &getOutputDevice() const;
|
||||||
|
//! @}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
//! Callsigns have been changed
|
||||||
void receivingCallsignsChanged(const Audio::TransceiverReceivingCallsignsChangedArgs &args);
|
void receivingCallsignsChanged(const Audio::TransceiverReceivingCallsignsChangedArgs &args);
|
||||||
|
|
||||||
|
//! Connection status has been changed
|
||||||
|
void connectionStatusChanged(ConnectionStatus status);
|
||||||
|
|
||||||
|
//! PTT status in this particular AFV client
|
||||||
|
void ptt(bool active, BlackMisc::Audio::PTTCOM pttcom, const BlackMisc::CIdentifier &identifier);
|
||||||
|
|
||||||
|
//! VU levels @{
|
||||||
void inputVolumePeakVU(double value);
|
void inputVolumePeakVU(double value);
|
||||||
void outputVolumePeakVU(double value);
|
void outputVolumePeakVU(double value);
|
||||||
void connectionStatusChanged(ConnectionStatus status);
|
//! @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void opusDataAvailable(const Audio::OpusDataAvailableArgs &args);
|
void opusDataAvailable(const Audio::OpusDataAvailableArgs &args);
|
||||||
@@ -135,12 +168,13 @@ namespace BlackCore
|
|||||||
void updateTransceiversFromContext(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, const BlackMisc::CIdentifier &originator);
|
void updateTransceiversFromContext(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, const BlackMisc::CIdentifier &originator);
|
||||||
|
|
||||||
static constexpr int SampleRate = 48000;
|
static constexpr int SampleRate = 48000;
|
||||||
static constexpr int FrameSize = 960; // 20ms
|
static constexpr int FrameSize = 960; // 20ms
|
||||||
|
static constexpr double MinDb = -18.0;
|
||||||
|
static constexpr double MaxDb = 18.0;
|
||||||
|
static constexpr quint32 UniCom = 122800000;
|
||||||
|
|
||||||
// Connection
|
|
||||||
Connection::CClientConnection *m_connection = nullptr;
|
Connection::CClientConnection *m_connection = nullptr;
|
||||||
|
BlackMisc::CSetting<BlackMisc::Audio::TSettings> m_audioSettings { this, &CAfvClient::onSettingsChanged };
|
||||||
// Properties
|
|
||||||
QString m_callsign;
|
QString m_callsign;
|
||||||
|
|
||||||
Audio::CInput *m_input = nullptr;
|
Audio::CInput *m_input = nullptr;
|
||||||
@@ -152,17 +186,16 @@ namespace BlackCore
|
|||||||
bool m_transmit = false;
|
bool m_transmit = false;
|
||||||
bool m_transmitHistory = false;
|
bool m_transmitHistory = false;
|
||||||
QVector<TxTransceiverDto> m_transmittingTransceivers;
|
QVector<TxTransceiverDto> m_transmittingTransceivers;
|
||||||
|
static const QVector<quint16> &allTransceiverIds() { static const QVector<quint16> transceiverIds{0, 1}; return transceiverIds; }
|
||||||
|
|
||||||
bool m_isStarted = false;
|
bool m_isStarted = false;
|
||||||
|
bool m_loopbackOn = false;
|
||||||
QDateTime m_startDateTimeUtc;
|
QDateTime m_startDateTimeUtc;
|
||||||
|
|
||||||
double m_inputVolumeDb;
|
double m_inputVolumeDb;
|
||||||
double m_outputVolume = 1.0;
|
double m_outputVolume = 1.0;
|
||||||
|
|
||||||
double m_maxDbReadingInPTTInterval = -100;
|
double m_maxDbReadingInPTTInterval = -100;
|
||||||
|
|
||||||
bool m_loopbackOn = false;
|
|
||||||
|
|
||||||
QTimer m_voiceServerPositionTimer;
|
QTimer m_voiceServerPositionTimer;
|
||||||
QVector<TransceiverDto> m_transceivers;
|
QVector<TransceiverDto> m_transceivers;
|
||||||
QSet<quint16> m_enabledTransceivers;
|
QSet<quint16> m_enabledTransceivers;
|
||||||
@@ -170,11 +203,8 @@ namespace BlackCore
|
|||||||
Audio::InputVolumeStreamArgs m_inputVolumeStream;
|
Audio::InputVolumeStreamArgs m_inputVolumeStream;
|
||||||
Audio::OutputVolumeStreamArgs m_outputVolumeStream;
|
Audio::OutputVolumeStreamArgs m_outputVolumeStream;
|
||||||
|
|
||||||
BlackMisc::CSetting<BlackMisc::Audio::TSettings> m_audioSettings { this, &CAfvClient::onSettingsChanged };
|
|
||||||
|
|
||||||
void initWithContext();
|
void initWithContext();
|
||||||
static bool hasContext();
|
static bool hasContext();
|
||||||
|
|
||||||
};
|
};
|
||||||
} // ns
|
} // ns
|
||||||
} // ns
|
} // ns
|
||||||
|
|||||||
Reference in New Issue
Block a user