Code based on Review with RW (userJoinedLeft).

Includes the discussed changes, added the mute methods,
and switchAudioOutput to enable/disable channel1/2
This commit is contained in:
Klaus Basan
2014-01-13 03:19:36 +01:00
parent 71c7318176
commit cedc08eb3d
2 changed files with 137 additions and 57 deletions

View File

@@ -18,12 +18,11 @@ namespace BlackCore
CVoiceVatlib::CVoiceVatlib(QObject *parent) : CVoiceVatlib::CVoiceVatlib(QObject *parent) :
IVoice(parent), IVoice(parent),
m_voice(Cvatlib_Voice_Simple::Create()), m_voice(Cvatlib_Voice_Simple::Create()),
m_aircraftCallsign(), m_voiceRooms(), m_devices(),
m_keyboardPtt(new CKeyboard(nullptr)), m_keyboardPtt(new CKeyboard(nullptr)),
m_pushToTalk(false), m_pushToTalk(false),
m_inputSquelch(-1), m_inputSquelch(-1),
m_micTestResult(Cvatlib_Voice_Simple::agc_Ok), m_micTestResult(Cvatlib_Voice_Simple::agc_Ok),
m_queryUserRoomIndex(-1) m_temporaryUserRoomIndex(CVoiceVatlib::InvalidRoomIndex)
{ {
try try
{ {
@@ -32,7 +31,7 @@ namespace BlackCore
m_voice->GetOutputDevices(onOutputHardwareDeviceReceived, this); m_voice->GetOutputDevices(onOutputHardwareDeviceReceived, this);
// TODO: read audio device settings here and init with the same devices // 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 // If not, settings are there or it is the first run, use the default one
// TODO: KB, setting this kind of default device results in an error // TODO: KB, setting this kind of default device results in an error
// setInputDevice(defaultAudioInputDevice()); // setInputDevice(defaultAudioInputDevice());
// setOutputDevice(defaultAudioOutputDevice()); // setOutputDevice(defaultAudioOutputDevice());
@@ -42,6 +41,8 @@ namespace BlackCore
this->m_voiceRooms.push_back(CVoiceRoom()); // COM1 this->m_voiceRooms.push_back(CVoiceRoom()); // COM1
this->m_voiceRooms.push_back(CVoiceRoom()); // COM2 this->m_voiceRooms.push_back(CVoiceRoom()); // COM2
this->m_outputEnabled.insert(COM1, true);
this->m_outputEnabled.insert(COM2, true);
// do processing // do processing
this->startTimer(100); this->startTimer(100);
@@ -49,7 +50,10 @@ namespace BlackCore
// as last thing enable keyboard handling // as last thing enable keyboard handling
this->m_keyboardPtt.data()->s_voice = this; this->m_keyboardPtt.data()->s_voice = this;
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -106,7 +110,10 @@ namespace BlackCore
qWarning() << "Input device hit a fatal error"; qWarning() << "Input device hit a fatal error";
} }
} }
catch (...) { exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -129,7 +136,10 @@ namespace BlackCore
qWarning() << "Input device hit a fatal error"; qWarning() << "Input device hit a fatal error";
} }
} }
catch (...) { exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -157,15 +167,19 @@ namespace BlackCore
/* /*
* Enable audio * Enable audio
*/ */
void CVoiceVatlib::enableAudio(const ComUnit comUnit) void CVoiceVatlib::switchAudioOutput(const ComUnit comUnit, bool enable)
{ {
Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!"); Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
Q_ASSERT_X(m_voice->IsRoomValid(static_cast<int32_t>(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!"); Q_ASSERT_X(m_voice->IsRoomValid(static_cast<int32_t>(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!");
try try
{ {
m_voice->SetOutoutState(static_cast<int32_t>(comUnit), 0, true); m_voice->SetOutoutState(static_cast<int32_t>(comUnit), 0, enable);
this->m_outputEnabled[comUnit] = enable;
}
catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
} }
/* /*
@@ -179,12 +193,18 @@ namespace BlackCore
{ {
m_voice->BeginFindSquelch(); m_voice->BeginFindSquelch();
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
// Start the timer only if no exception was thrown before // Start the timer only if no exception was thrown before
QTimer::singleShot(5000, this, SLOT(onEndFindSquelch())); QTimer::singleShot(5000, this, SLOT(onEndFindSquelch()));
} }
/*
* Start microphone test
*/
void CVoiceVatlib::runMicTest() void CVoiceVatlib::runMicTest()
{ {
Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!"); Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
@@ -193,23 +213,34 @@ namespace BlackCore
{ {
m_voice->BeginMicTest(); m_voice->BeginMicTest();
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
// Start the timer only if no exception was thrown before // Start the timer only if no exception was thrown before
QTimer::singleShot(5000, this, SLOT(onEndMicTest())); QTimer::singleShot(5000, this, SLOT(onEndMicTest()));
} }
/*
* Input squelch volume
*/
float CVoiceVatlib::inputSquelch() const float CVoiceVatlib::inputSquelch() const
{ {
return m_inputSquelch; return m_inputSquelch;
} }
/*
* Mic test
*/
int32_t CVoiceVatlib::micTestResult() const int32_t CVoiceVatlib::micTestResult() const
{ {
return m_micTestResult; return m_micTestResult;
} }
/*
* Mic test, result as string
*/
QString CVoiceVatlib::micTestResultAsString() const QString CVoiceVatlib::micTestResultAsString() const
{ {
QString result; QString result;
@@ -270,7 +301,10 @@ namespace BlackCore
QString serverSpec = voiceRoom.getVoiceRoomUrl(); QString serverSpec = voiceRoom.getVoiceRoomUrl();
m_voice->JoinRoom(static_cast<int32_t>(comUnit), m_aircraftCallsign.toQString().toLatin1().constData(), serverSpec.toLatin1().constData()); m_voice->JoinRoom(static_cast<int32_t>(comUnit), m_aircraftCallsign.toQString().toLatin1().constData(), serverSpec.toLatin1().constData());
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -290,7 +324,10 @@ namespace BlackCore
vr.setConnected(false); vr.setConnected(false);
this->setVoiceRoomForUnit(comUnit, vr); this->setVoiceRoomForUnit(comUnit, vr);
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -314,7 +351,10 @@ namespace BlackCore
{ {
m_voice->SetRoomVolume(static_cast<int32_t>(comUnit), volumne); m_voice->SetRoomVolume(static_cast<int32_t>(comUnit), volumne);
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -329,7 +369,10 @@ namespace BlackCore
{ {
m_voice->SetMicState(static_cast<int32_t>(comUnit), true); m_voice->SetMicState(static_cast<int32_t>(comUnit), true);
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -343,20 +386,23 @@ namespace BlackCore
{ {
m_voice->SetMicState(static_cast<int32_t>(comUnit), false); m_voice->SetMicState(static_cast<int32_t>(comUnit), false);
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
* Change room status * Change room status
*/ */
void CVoiceVatlib::changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd) void CVoiceVatlib::changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate roomStatus)
{ {
CVoiceRoom vr = this->voiceRoomForUnit(comUnit); CVoiceRoom vr = this->voiceRoomForUnit(comUnit);
switch (upd) switch (roomStatus)
{ {
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinSuccess: case Cvatlib_Voice_Simple::roomStatusUpdate_JoinSuccess:
enableAudio(comUnit); switchAudioOutput(comUnit, this->m_outputEnabled[comUnit]);
vr.setConnected(true); vr.setConnected(true);
this->setVoiceRoomForUnit(comUnit, vr); this->setVoiceRoomForUnit(comUnit, vr);
emit connected(comUnit); emit connected(comUnit);
@@ -408,7 +454,10 @@ namespace BlackCore
this->m_voice->DoProcessing(); this->m_voice->DoProcessing();
this->handlePushToTalk(); this->handlePushToTalk();
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -424,7 +473,10 @@ namespace BlackCore
m_inputSquelch = m_voice->GetInputSquelch(); m_inputSquelch = m_voice->GetInputSquelch();
emit squelchTestFinished(); emit squelchTestFinished();
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
void CVoiceVatlib::onEndMicTest() void CVoiceVatlib::onEndMicTest()
@@ -436,7 +488,10 @@ namespace BlackCore
m_micTestResult = m_voice->EndMicTest(); m_micTestResult = m_voice->EndMicTest();
emit micTestFinished(); emit micTestFinished();
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
}
} }
/* /*
@@ -445,53 +500,49 @@ namespace BlackCore
void CVoiceVatlib::onUserJoinedLeft(const ComUnit comUnit) void CVoiceVatlib::onUserJoinedLeft(const ComUnit comUnit)
{ {
Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!"); Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
Q_ASSERT_X(m_queryUserRoomIndex == -1, "CVoiceClientVatlib::onUserJoinedLeft", "Cannot list users for two rooms in parallel!"); Q_ASSERT_X(m_temporaryUserRoomIndex == CVoiceVatlib::InvalidRoomIndex, "CVoiceClientVatlib::onUserJoinedLeft", "Cannot list users for two rooms in parallel!");
try try
{ {
// Paranoia... // Paranoia...
if (!m_voice->IsRoomConnected(static_cast<int32_t>(comUnit))) if (!m_voice->IsRoomConnected(static_cast<int32_t>(comUnit)))
return; return;
// Store the room index for the slot. // Store the room index for the slot (called in static callback)
m_queryUserRoomIndex = static_cast<int32_t>(comUnit); m_temporaryUserRoomIndex = static_cast<int32_t>(comUnit);
// Callbacks completed when function is called, after the method is done
// m_voiceRoomCallsignsUpdate is filled with the latest callsigns
m_voice->GetRoomUserList(static_cast<int32_t>(comUnit), onRoomUserReceived, this); m_voice->GetRoomUserList(static_cast<int32_t>(comUnit), onRoomUserReceived, this);
m_queryUserRoomIndex = -1; m_temporaryUserRoomIndex = CVoiceVatlib::InvalidRoomIndex; // reset
QSet<QString> temporaryUsers;
// we have all current users in m_voi
foreach(QString callsign, m_voiceRoomCallsigns.value(comUnit)) foreach(QString callsign, m_voiceRoomCallsigns.value(comUnit))
{ {
if (m_voiceRoomCallsignsUpdate.contains(callsign)) if (!m_temporaryVoiceRoomCallsigns.contains(callsign))
{ {
// The user is still there. // He is has left
temporaryUsers.insert(callsign);
}
else
{
// He is has probably left
emit userLeftRoom(callsign); emit userLeftRoom(callsign);
} }
} }
foreach(QString callsign, m_voiceRoomCallsignsUpdate) foreach(QString callsign, m_temporaryVoiceRoomCallsigns)
{ {
if (m_voiceRoomCallsigns.value(comUnit).contains(callsign)) if (!m_voiceRoomCallsigns.value(comUnit).contains(callsign))
{ {
// User was already there before // he joined
temporaryUsers.insert(callsign);
}
else
{
// He joined
temporaryUsers.insert(callsign);
emit userJoinedRoom(callsign); emit userJoinedRoom(callsign);
} }
} }
// Finally we update it with our new list // Finally we update it with our new list
m_voiceRoomCallsignsUpdate.clear(); this->m_voiceRoomCallsigns[comUnit] = this->m_temporaryVoiceRoomCallsigns;
this->m_temporaryVoiceRoomCallsigns.clear();
}
catch (...)
{
this->exceptionDispatcher(Q_FUNC_INFO);
} }
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
} }
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/ /********************************** * * * * * * * * * * * * * * * * * * * ************************************/
@@ -530,7 +581,7 @@ namespace BlackCore
// add user // add user
CVoiceVatlib *voiceClientVatlib = cbvar_cast_voice(cbVar); CVoiceVatlib *voiceClientVatlib = cbvar_cast_voice(cbVar);
ComUnit comUnit = static_cast<ComUnit>(voiceClientVatlib->queryUserRoomIndex()); ComUnit comUnit = static_cast<ComUnit>(voiceClientVatlib->temporaryUserRoomIndex());
// add user // add user
voiceClientVatlib->addUserInRoom(comUnit, callsign); voiceClientVatlib->addUserInRoom(comUnit, callsign);
@@ -577,7 +628,7 @@ namespace BlackCore
*/ */
void CVoiceVatlib::addUserInRoom(const ComUnit /** comUnit **/, const QString &callsign) void CVoiceVatlib::addUserInRoom(const ComUnit /** comUnit **/, const QString &callsign)
{ {
m_voiceRoomCallsignsUpdate.insert(callsign); m_temporaryVoiceRoomCallsigns.insert(callsign);
} }
/* /*

View File

@@ -130,6 +130,23 @@ namespace BlackCore
return this->m_voiceRoomCallsigns[comUnit]; return this->m_voiceRoomCallsigns[comUnit];
} }
/*!
* \brief Switch audio output
* \param comUnit
* \param enable
*/
virtual void switchAudioOutput(const ComUnit comUnit, bool enable);
/*!
* \brief Muted?
*/
virtual bool isMuted() const
{
if (this->m_outputEnabled.isEmpty()) return false;
bool enabled = this->m_outputEnabled[COM1] || this->m_outputEnabled[COM2];
return !enabled;
}
/************************************************ /************************************************
* NON API METHODS: * NON API METHODS:
* The following methods are not part of the * The following methods are not part of the
@@ -137,9 +154,21 @@ namespace BlackCore
* workflow. * workflow.
* *********************************************/ * *********************************************/
int32_t queryUserRoomIndex() const {return m_queryUserRoomIndex;} /*!
* \brief Voice room index
* \return
*/
int32_t temporaryUserRoomIndex() const
{
return m_temporaryUserRoomIndex;
}
void changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd); /*!
* \brief Room status update, used in callback
* \param comUnit
* \param upd
*/
void changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate roomStatus);
signals: signals:
@@ -266,15 +295,15 @@ namespace BlackCore
bool m_pushToTalk; /*!< flag, PTT pressed */ bool m_pushToTalk; /*!< flag, PTT pressed */
float m_inputSquelch; float m_inputSquelch;
Cvatlib_Voice_Simple::agc m_micTestResult; Cvatlib_Voice_Simple::agc m_micTestResult;
QMap < ComUnit, QSet<QString> > m_voiceRoomCallsigns; /*!< voice room callsigns */
QSet<QString> m_temporaryVoiceRoomCallsigns; /*!< temp. storage of voice rooms during update */
QMap<ComUnit, bool> m_outputEnabled; /*!< output enabled, basically a mute flag */
typedef QMap<ComUnit, QSet<QString>> TMapRoomCallsigns; // Need to keep the roomIndex?
TMapRoomCallsigns m_voiceRoomCallsigns;
QSet<QString> m_voiceRoomCallsignsUpdate;
// Need to keep the roomIndex because GetRoomUserList does not specifiy it
// KB: I would remove this approach, it is potentially unsafe // KB: I would remove this approach, it is potentially unsafe
// Maybe just use 2 "wrapper" callbacks, which then set explicitly the voice room (it is only 2 methods) // Maybe just use 2 "wrapper" callbacks, which then set explicitly the voice room (it is only 2 methods)
int32_t m_queryUserRoomIndex; int32_t m_temporaryUserRoomIndex; /*!< temp. storage of voice room, in order to retrieve it in static callback */
const static int32_t InvalidRoomIndex = -1; /*! marks invalid room */
}; };