Added squelch and mic tests

refs #36

refs #81
This commit is contained in:
Roland Winklmeier
2013-11-30 15:48:33 +01:00
committed by Mathew Sutcliffe
parent b511f2ffaa
commit 7292e265fb
3 changed files with 249 additions and 31 deletions

View File

@@ -21,6 +21,9 @@
namespace BlackCore
{
/*!
* Interface to a connection to a ATC voice server for use in flight simulation.
*/
class IVoiceClient : public QObject
{
@@ -54,17 +57,25 @@ namespace BlackCore
virtual bool isConnected(const uint32_t comUnit) = 0;
// The following methods should be called everytime you receive a update signal.
// Reason:
// We cannot say when the device and user lists are completed. Instead information is cached internally
// and signals emitted in case of a change. This way other objects can listen to this signals and call the getter
// again.
// The following method should be called everytime you receive a user update signal
virtual void roomUserList(const uint32_t comUnit) = 0;
virtual const QList<BlackMisc::Voice::CInputAudioDevice> & audioInputDevices(const uint32_t comUnit) const = 0;
virtual const QList<BlackMisc::Voice::COutputAudioDevice> & audioOutputDevices(const uint32_t comUnit) const = 0;
virtual void setInputDevice(const uint32_t comUnit, BlackMisc::Voice::CInputAudioDevice &device) = 0;
virtual void setOutputDevice(const uint32_t comUnit, BlackMisc::Voice::COutputAudioDevice &device) = 0;
// Hardware devices
virtual const QList<BlackMisc::Voice::CInputAudioDevice> & audioInputDevices() const = 0;
virtual const QList<BlackMisc::Voice::COutputAudioDevice> & audioOutputDevices() const = 0;
virtual const BlackMisc::Voice::CInputAudioDevice & defaultAudioInputDevice() const = 0;
virtual const BlackMisc::Voice::COutputAudioDevice & defaultAudioOutputDevice() const = 0;
virtual void setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device) = 0;
virtual void setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device) = 0;
// Mic tests
virtual void runSquelchTest() = 0;
virtual void runMicTest() = 0;
virtual float inputSquelch() const = 0;
virtual const BlackMisc::Voice::CVoiceRoom &voiceRoom (const uint32_t comUnit) = 0;
@@ -86,6 +97,13 @@ namespace BlackCore
void audioStarted(const uint32_t comUnit);
void audioStopped(const uint32_t comUnit);
// Test signals
void squelchTestFinished();
void micTestFinished();
// non protocol related signals
void exception(const QString &message, bool fatal = false); // let remote places know there was an exception
public slots:
};

View File

@@ -6,21 +6,33 @@
#include "voiceclient_vatlib.h"
#include <QDebug>
#include <QTimer>
namespace BlackCore
{
CVoiceClientVatlib::CVoiceClientVatlib(QObject *parent) :
IVoiceClient(parent),
m_voice(Create_Cvatlib_Voice_Simple())
m_voice(Create_Cvatlib_Voice_Simple()),
m_inputSquelch(-1)
{
m_voice->Setup(true, 3290, 2, 1, onRoomStatusUpdate, this);
m_voice->GetInputDevices(onInputHardwareDeviceReceived, this);
m_voice->GetOutputDevices(onOutputHardwareDeviceReceived, this);
try
{
m_voice->Setup(true, 3290, 2, 1, onRoomStatusUpdate, this);
m_voice->GetInputDevices(onInputHardwareDeviceReceived, this);
m_voice->GetOutputDevices(onOutputHardwareDeviceReceived, this);
// TODO: read audio device settings here and init with the same devices
// If not settings are there or it is the first run, use the default one
setInputDevice(defaultAudioInputDevice());
setOutputDevice(defaultAudioOutputDevice());
startTimer(100);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
CVoiceClientVatlib::~CVoiceClientVatlib()
{
}
void CVoiceClientVatlib::setCallsign(const BlackMisc::Aviation::CCallsign &callsign)
@@ -38,54 +50,131 @@ namespace BlackCore
}
void CVoiceClientVatlib::setVolume(const uint32_t comIndex, const uint32_t volumne)
void CVoiceClientVatlib::setVolume(const uint32_t comUnit, const uint32_t volumne)
{
}
void CVoiceClientVatlib::startTransmitting(const uint32_t comIndex)
void CVoiceClientVatlib::startTransmitting(const uint32_t comUnit)
{
}
void CVoiceClientVatlib::stopTransmitting(const uint32_t comIndex)
void CVoiceClientVatlib::stopTransmitting(const uint32_t comUnit)
{
}
bool CVoiceClientVatlib::isReceiving(const uint32_t comIndex)
bool CVoiceClientVatlib::isReceiving(const uint32_t comUnit)
{
}
bool CVoiceClientVatlib::isConnected(const uint32_t comIndex)
bool CVoiceClientVatlib::isConnected(const uint32_t comUnit)
{
}
void CVoiceClientVatlib::roomUserList(const uint32_t comIndex)
void CVoiceClientVatlib::roomUserList(const uint32_t comUnit)
{
}
const QList<BlackMisc::Voice::CInputAudioDevice> &CVoiceClientVatlib::audioInputDevices(const uint32_t comIndex) const
const QList<BlackMisc::Voice::CInputAudioDevice> &CVoiceClientVatlib::audioInputDevices() const
{
return m_inputDevices;
}
const QList<BlackMisc::Voice::COutputAudioDevice> &CVoiceClientVatlib::audioOutputDevices(const uint32_t comIndex) const
const QList<BlackMisc::Voice::COutputAudioDevice> &CVoiceClientVatlib::audioOutputDevices() const
{
return m_outputDevices;
}
void CVoiceClientVatlib::setInputDevice(const uint32_t comUnit, BlackMisc::Voice::CInputAudioDevice &device)
const BlackMisc::Voice::CInputAudioDevice & CVoiceClientVatlib::defaultAudioInputDevice() const
{
foreach(BlackMisc::Voice::CInputAudioDevice inputDevice, m_inputDevices)
{
if(inputDevice.name().contains("[default]", Qt::CaseInsensitive))
return inputDevice;
}
return BlackMisc::Voice::CInputAudioDevice();
}
void CVoiceClientVatlib::setOutputDevice(const uint32_t comUnit, BlackMisc::Voice::COutputAudioDevice &device)
const BlackMisc::Voice::COutputAudioDevice & CVoiceClientVatlib::defaultAudioOutputDevice() const
{
foreach(BlackMisc::Voice::COutputAudioDevice outputDevice, m_outputDevices)
{
if(outputDevice.name().contains("[default]", Qt::CaseInsensitive))
return outputDevice;
}
return BlackMisc::Voice::COutputAudioDevice();
}
void CVoiceClientVatlib::setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device)
{
if (!device.isValid())
return;
try
{
if( !m_voice->SetInputDevice(device.index()))
{
qWarning() << "SetInputDevice() failed";
}
if (!m_voice->IsInputDeviceAlive())
{
qWarning() << "Input device hit a fatal error";
}
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device)
{
if (!device.isValid())
return;
try
{
m_voice->SetOutputDevice(0, device.index());
if (!m_voice->IsOutputDeviceAlive(0))
{
qWarning() << "Input device hit a fatal error";
}
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::runSquelchTest()
{
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->BeginFindSquelch();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
// Start the timer only if no exception was thrown before
QTimer::singleShot(5000, this, SLOT(onEndFindSquelch()));
}
void CVoiceClientVatlib::runMicTest()
{
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->BeginMicTest();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
// Start the timer only if no exception was thrown before
QTimer::singleShot(5000, this, SLOT(onEndMicTest()));
}
float CVoiceClientVatlib::inputSquelch() const
{
return m_inputSquelch;
}
const BlackMisc::Voice::CVoiceRoom &CVoiceClientVatlib::voiceRoom(const uint32_t comUnit)
@@ -93,6 +182,45 @@ namespace BlackCore
}
void CVoiceClientVatlib::timerEvent(QTimerEvent *)
{
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->DoProcessing();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::onEndFindSquelch()
{
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->EndFindSquelch();
//TODO: store captured squelch
m_inputSquelch = m_voice->GetInputSquelch();
qDebug() << m_inputSquelch;
emit squelchTestFinished();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::onEndMicTest()
{
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
Cvatlib_Voice_Simple::agc micTestResult = m_voice->EndMicTest();
qDebug() << micTestResult;
emit micTestFinished();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
/********************************** shimlib callbacks ************************************/
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
@@ -124,4 +252,39 @@ namespace BlackCore
cbvar_cast(cbVar)->m_outputDevices.append(outputDevice);
}
void CVoiceClientVatlib::exceptionDispatcher(const char *caller)
{
QString msg("Caller: ");
msg.append(caller).append(" ").append("Exception: ");
try
{
throw;
}
catch (const NetworkNotConnectedException &e)
{
// this could be caused by a race condition during normal operation, so not an error
msg.append("NetworkNotConnectedException").append(" ").append(e.what());
emit this->exception(msg);
qDebug() << "NetworkNotConnectedException caught in " << caller << "\n" << e.what();
}
catch (const VatlibException &e)
{
msg.append("VatlibException").append(" ").append(e.what());
emit this->exception(msg, true);
qFatal("VatlibException caught in %s\n%s", caller, e.what());
}
catch (const std::exception &e)
{
msg.append("std::exception").append(" ").append(e.what());
emit this->exception(msg, true);
qFatal("std::exception caught in %s\n%s", caller, e.what());
}
catch (...)
{
msg.append("unknown exception");
emit this->exception(msg, true);
qFatal("Unknown exception caught in %s", caller);
}
}
} // namespace BlackCore

View File

@@ -13,7 +13,9 @@
namespace BlackCore
{
/*!
* Vatlib implementation of the IVoiceClient interface.
*/
class CVoiceClientVatlib : public IVoiceClient
{
Q_OBJECT
@@ -32,11 +34,26 @@ namespace BlackCore
virtual bool isConnected(const uint32_t comUnit);
virtual void roomUserList(const uint32_t comUnit);
virtual const QList<BlackMisc::Voice::CInputAudioDevice> &audioInputDevices(const uint32_t comUnit) const ;
virtual const QList<BlackMisc::Voice::COutputAudioDevice> & audioOutputDevices(const uint32_t comUnit) const;
virtual void setInputDevice(const uint32_t comUnit, BlackMisc::Voice::CInputAudioDevice &device);
virtual void setOutputDevice(const uint32_t comUnit, BlackMisc::Voice::COutputAudioDevice &device);
// Hardware devices
// TODO: Vatlib supports multiple output devices. That basically means, you could connect
// to different voice rooms and send their audio to different devices, e.g. ATIS to loudspeakers
// and ATC to headspeakers. Is not important to implement that now, if ever.
virtual const QList<BlackMisc::Voice::CInputAudioDevice> & audioInputDevices() const ;
virtual const QList<BlackMisc::Voice::COutputAudioDevice> & audioOutputDevices() const;
virtual const BlackMisc::Voice::CInputAudioDevice & defaultAudioInputDevice() const;
virtual const BlackMisc::Voice::COutputAudioDevice & defaultAudioOutputDevice() const;
virtual void setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device);
virtual void setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device);
// Mic tests
virtual void runSquelchTest();
virtual void runMicTest();
virtual float inputSquelch() const;
virtual const BlackMisc::Voice::CVoiceRoom &voiceRoom (const uint32_t comUnit);
@@ -44,6 +61,14 @@ namespace BlackCore
public slots:
protected: // QObject overrides
virtual void timerEvent(QTimerEvent *);
private slots:
// slots for Mic tests
void onEndFindSquelch();
void onEndMicTest();
private:
// shimlib callbacks
@@ -52,11 +77,23 @@ namespace BlackCore
static void onInputHardwareDeviceReceived(Cvatlib_Voice_Simple* obj, const char* name, void* cbVar);
static void onOutputHardwareDeviceReceived(Cvatlib_Voice_Simple* obj, const char* name, void* cbVar);
QScopedPointer<Cvatlib_Voice_Simple> m_voice;
void exceptionDispatcher(const char *caller);
struct Cvatlib_Voice_Simple_Deleter
{
static inline void cleanup(Cvatlib_Voice_Simple *pointer)
{
pointer->Destroy();
}
};
QScopedPointer<Cvatlib_Voice_Simple, Cvatlib_Voice_Simple_Deleter> m_voice;
BlackMisc::Aviation::CCallsign m_callsign;
QMap<uint32_t, BlackMisc::Voice::CVoiceRoom> m_voiceRoomMap;
QList<BlackMisc::Voice::CInputAudioDevice> m_inputDevices;
QList<BlackMisc::Voice::COutputAudioDevice> m_outputDevices;
float m_inputSquelch;
};
} // namespace BlackCore