Refactoring and clean up of voice implementation

refs #36
- Cleanup of library and sample code
- Completed now all signals in voice sample
- Fixed minor bugs with the user list
- TODO: Remove the VATSIM id from the user string

refs #81
This commit is contained in:
Roland Winklmeier
2013-12-06 21:26:08 +01:00
committed by Mathew Sutcliffe
parent 0bae898db8
commit db4a3c5de4
7 changed files with 534 additions and 275 deletions

View File

@@ -0,0 +1,15 @@
/* Copyright (C) 2013 VATSIM Community / authors
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "voiceclient.h"
namespace BlackCore
{
IVoiceClient::IVoiceClient(QObject *parent)
: QObject(parent)
{
qRegisterMetaType<IVoiceClient::ComUnit>("IVoiceClient::ComUnit");
}
}

View File

@@ -3,10 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*!
\file
*/
#ifndef BLACKCORE_VOICE_H
#define BLACKCORE_VOICE_H
@@ -19,6 +15,7 @@
#include <QObject>
#include <QStringList>
#include <QMetaType>
namespace BlackCore
{
@@ -46,68 +43,184 @@ namespace BlackCore
* \brief Default constructor with parent
* \param parent
*/
IVoiceClient(QObject *parent = 0) : QObject(parent) {}
IVoiceClient(QObject *parent = 0);
public:
BLACK_INTERFACE(BlackCore::IVoice)
//! ComUnit
/*! IVoiceClient currently supports two different com units */
enum ComUnit {
COM1 = 0, /*!< ComUnit 1 */
COM2 /*!< ComUnit 2 */
};
//! Virtual destructor.
virtual ~IVoiceClient() {}
// The following method should be called everytime you receive a user update signal
virtual const QStringList roomUserList(const int32_t comUnit) = 0;
//! roomUserList
/*!
\return A list of users currently connected to the voice room
*/
virtual const QSet<QString> roomUserList(const ComUnit comUnit) = 0;
// Hardware devices
//! audioInputDevices
/*!
\return A list of available input devices
*/
virtual const QList<BlackMisc::Voice::CInputAudioDevice> & audioInputDevices() const = 0;
//! audioOutputDevices
/*!
\return A list of available output devices
*/
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;
//! defaultAudioInputDevice
/*!
\return Default input device
*/
virtual const BlackMisc::Voice::CInputAudioDevice defaultAudioInputDevice() const = 0;
//! defaultAudioOutputDevice
/*!
\return Default output device
*/
virtual const BlackMisc::Voice::COutputAudioDevice defaultAudioOutputDevice() const = 0;
//! setInputDevice
/*!
\param input device
*/
virtual void setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device) = 0;
//! setOutputDevice
/*!
\param output device
*/
virtual void setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device) = 0;
virtual void enableAudio(const int32_t comUnit) = 0;
//! enableAudio
/*!
\brief After you have joined a voice room, you must enable audio output.
\param comUnit
*/
virtual void enableAudio(const ComUnit comUnit) = 0;
// Mic tests
//! voiceRoom
/*!
\brief After you have joined a voice room, you must enable audio output.
\param comUnit
\return voiceRoom
*/
virtual const BlackMisc::Voice::CVoiceRoom voiceRoom (const ComUnit comUnit) = 0;
//! isConnected
/*!
\param comUnit
\return if connected
*/
virtual bool isConnected(const ComUnit comUnit) = 0;
//! isReceiving
/*!
\param comUnit
*/
virtual bool isReceiving(const ComUnit comUnit) = 0;
/************************************************
* SETUP TESTS
* *********************************************/
//! runSquelchTest
/*!
\brief Runs a 5 seconds test, measuring your background noise.
*/
virtual void runSquelchTest() = 0;
//! runMicTest
/*!
\brief Runs a 5 seconds test, measuring the qualitiy of your mic input
*/
virtual void runMicTest() = 0;
//! inputSquelch
/*!
\return Value of the measured squelch
*/
virtual float inputSquelch() const = 0;
virtual Cvatlib_Voice_Simple::agc micTestResult() const = 0;
virtual const BlackMisc::Voice::CVoiceRoom &voiceRoom (const uint32_t comUnit) = 0;
//! micTestResult
/*!
\return Result of the mic test.
*/
virtual int32_t micTestResult() const = 0;
//! micTestResult
/*!
\return Result of the mic test as human readable string
*/
virtual QString micTestResultAsString() const = 0;
public slots:
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign) = 0;
virtual void joinVoiceRoom(const int32_t comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom) = 0;
virtual void leaveVoiceRoom(const int32_t comUnit) = 0;
virtual void setVolume(const int32_t comUnit, const uint32_t volumne) = 0;
virtual void startTransmitting(const int32_t comUnit) = 0;
virtual void stopTransmitting(const int32_t comUnit) = 0;
virtual bool isReceiving(const int32_t comUnit) = 0;
virtual bool isConnected(const int32_t comUnit) = 0;
//! setCallsign
/*!
\param callsign
*/
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign) = 0;
//! joinVoiceRoom
/*!
\param comUnit
\param voiceRoom
*/
virtual void joinVoiceRoom(const ComUnit comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom) = 0;
//! leaveVoiceRoom
/*!
\param comUnit
*/
virtual void leaveVoiceRoom(const ComUnit comUnit) = 0;
//! setVolume
/*!
\param comUnit
\param volumne
*/
virtual void setVolume(const ComUnit comUnit, const int32_t volumne) = 0;
//! startTransmitting
/*!
\param comUnit
*/
virtual void startTransmitting(const ComUnit comUnit) = 0;
//! stopTransmitting
/*!
\param comUnit
*/
virtual void stopTransmitting(const ComUnit comUnit) = 0;
signals:
// Signals regarding the voice server connection
void notConnected(const int32_t comUnit);
void connecting(const int32_t comUnit);
void connected(const int32_t comUnit);
void connectionFailed(const int32_t comUnit);
void kicked(const int32_t comUnit);
void disconnecting(const int32_t comUnit);
void disconnected(const int32_t comUnit);
void notConnected(const ComUnit comUnit);
void connecting(const ComUnit comUnit);
void connected(const ComUnit comUnit);
void connectionFailed(const ComUnit comUnit);
void kicked(const ComUnit comUnit);
void disconnecting(const ComUnit comUnit);
void disconnected(const ComUnit comUnit);
// Signals about users joining and leaving
void userJoinedRoom(const QString &callsign);
void userLeftRoom(const QString &callsign);
// Audio signals
void audioStarted(const int32_t comUnit);
void audioStopped(const int32_t comUnit);
void audioStarted();
void audioStopped();
void audioStarted(const ComUnit comUnit);
void audioStopped(const ComUnit comUnit);
void globalAudioStarted();
void globalAudioStopped();
// Test signals
void squelchTestFinished();
@@ -116,10 +229,13 @@ namespace BlackCore
// non protocol related signals
void exception(const QString &message, bool fatal = false); // let remote places know there was an exception
public slots:
protected:
};
} // namespace BlackCore
Q_DECLARE_METATYPE(BlackCore::IVoiceClient::ComUnit)
#endif // BLACKCORE_VOICE_H

View File

@@ -14,6 +14,7 @@ namespace BlackCore
IVoiceClient(parent),
m_voice(Cvatlib_Voice_Simple::Create()),
m_inputSquelch(-1),
m_micTestResult(Cvatlib_Voice_Simple::agc_Ok),
m_queryUserRoomIndex(-1)
{
try
@@ -39,112 +40,7 @@ namespace BlackCore
{
}
void CVoiceClientVatlib::setCallsign(const BlackMisc::Aviation::CCallsign &callsign)
{
m_callsign = callsign;
}
void CVoiceClientVatlib::joinVoiceRoom(const int32_t comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom)
{
if (!voiceRoom.isValid())
{
qDebug() << "Error: voiceRoom is invalid.";
}
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
try
{
if (!m_voice->IsRoomValid(comUnit))
{
qDebug() << "Error: room index out of bounds";
return;
}
QString serverSpec = voiceRoom.hostName() + "/" + voiceRoom.channel();
m_voice->JoinRoom(comUnit, m_callsign.toQString().toLatin1().constData(), serverSpec.toLatin1().constData());
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::leaveVoiceRoom(const int32_t comUnit)
{
try
{
if (!m_voice->IsRoomValid(comUnit))
{
qDebug() << "Error: room index out of bounds";
return;
}
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->LeaveRoom(comUnit);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::setVolume(const int32_t comUnit, const uint32_t volumne)
{
}
void CVoiceClientVatlib::startTransmitting(const int32_t comUnit)
{
try
{
if (!m_voice->IsRoomValid(comUnit))
{
qDebug() << "Error: room index out of bounds";
return;
}
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->SetMicState(comUnit, true);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::stopTransmitting(const int32_t comUnit)
{
try
{
if (!m_voice->IsRoomValid(comUnit))
{
qDebug() << "Error: room index out of bounds";
return;
}
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->SetMicState(comUnit, false);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
bool CVoiceClientVatlib::isReceiving(const int32_t comUnit)
{
try
{
if (!m_voice->IsRoomValid(comUnit))
{
qDebug() << "Error: room index out of bounds";
return false;
}
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_voice->IsAudioPlaying(comUnit);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
bool CVoiceClientVatlib::isConnected(const int32_t comUnit)
{
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
return m_voice->IsRoomConnected(comUnit);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
const QStringList CVoiceClientVatlib::roomUserList(const int32_t comUnit)
const QSet<QString> CVoiceClientVatlib::roomUserList(const ComUnit comUnit)
{
/**/
return m_voiceRoomsUsers.value(comUnit);
@@ -160,30 +56,26 @@ namespace BlackCore
return m_outputDevices;
}
const BlackMisc::Voice::CInputAudioDevice & CVoiceClientVatlib::defaultAudioInputDevice() const
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();
// Constructor creates already a default device
return BlackMisc::Voice::CInputAudioDevice(BlackMisc::Voice::CInputAudioDevice::defaultDevice(), "default");
}
const BlackMisc::Voice::COutputAudioDevice & CVoiceClientVatlib::defaultAudioOutputDevice() const
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();
// Constructor creates already a default device
return BlackMisc::Voice::COutputAudioDevice(BlackMisc::Voice::COutputAudioDevice::defaultDevice(), "default");
}
void CVoiceClientVatlib::setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device)
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
if (!device.isValid())
{
qWarning() << "Cannot set invalid input device!";
return;
}
try
{
@@ -199,15 +91,14 @@ namespace BlackCore
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::enableAudio(const int32_t comUnit)
{
m_voice->SetOutoutState(comUnit, 0, true);
}
void CVoiceClientVatlib::setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device)
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
if (!device.isValid())
{
qWarning() << "Cannot set invalid output device!";
return;
}
try
{
@@ -221,11 +112,56 @@ namespace BlackCore
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::runSquelchTest()
void CVoiceClientVatlib::enableAudio(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->IsRoomValid(static_cast<int32_t>(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!");
try
{
m_voice->SetOutoutState(static_cast<int32_t>(comUnit), 0, true);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
const BlackMisc::Voice::CVoiceRoom CVoiceClientVatlib::voiceRoom(const ComUnit comUnit)
{
return m_voiceRooms.value(comUnit);
}
bool CVoiceClientVatlib::isConnected(const ComUnit comUnit)
{
bool result;
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!");
try
{
result = m_voice->IsRoomConnected(static_cast<int32_t>(comUnit));
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
return result;
}
bool CVoiceClientVatlib::isReceiving(const ComUnit comUnit)
{
bool receiving;
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!");
try
{
receiving = m_voice->IsAudioPlaying(static_cast<int32_t>(comUnit));
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
return receiving;
}
void CVoiceClientVatlib::runSquelchTest()
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
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); }
@@ -236,9 +172,10 @@ namespace BlackCore
void CVoiceClientVatlib::runMicTest()
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
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); }
@@ -252,21 +189,159 @@ namespace BlackCore
return m_inputSquelch;
}
Cvatlib_Voice_Simple::agc CVoiceClientVatlib::micTestResult() const
int32_t CVoiceClientVatlib::micTestResult() const
{
return m_micTestResult;
}
const BlackMisc::Voice::CVoiceRoom &CVoiceClientVatlib::voiceRoom(const uint32_t comUnit)
QString CVoiceClientVatlib::micTestResultAsString() const
{
return BlackMisc::Voice::CVoiceRoom();
QString result;
switch (m_micTestResult)
{
case Cvatlib_Voice_Simple::agc_Ok:
result = "The test went ok";
break;
case Cvatlib_Voice_Simple::agc_BkgndNoiseLoud:
result = "The overall background noise is very loud and may be a nuisance to others";
break;
case Cvatlib_Voice_Simple::agc_TalkDrownedOut:
result = "The overall background noise is loud enough that others probably wont be able to distinguish speech from it";
break;
case Cvatlib_Voice_Simple::agc_TalkMicHot:
result = "The overall mic volume is too hot, you should lower the volume in the windows volume control panel";
break;
case Cvatlib_Voice_Simple::agc_TalkMicCold:
result = "The overall mic volume is too cold, you should raise the volume in the windows control panel and enable mic boost if needed";
break;
default:
result = "Unknown result.";
break;
}
return result;
}
void CVoiceClientVatlib::setCallsign(const BlackMisc::Aviation::CCallsign &callsign)
{
m_callsign = callsign;
}
void CVoiceClientVatlib::joinVoiceRoom(const ComUnit comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom)
{
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!");
if (!voiceRoom.isValid())
{
qDebug() << "Error: Cannot join invalid voice room.";
return;
}
try
{
QString serverSpec = voiceRoom.hostName() + "/" + voiceRoom.channel();
m_voice->JoinRoom(static_cast<int32_t>(comUnit), m_callsign.toQString().toLatin1().constData(), serverSpec.toLatin1().constData());
m_voiceRooms[comUnit] = voiceRoom;
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::leaveVoiceRoom(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->IsRoomValid(static_cast<int32_t>(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!");
try
{
m_voice->LeaveRoom(static_cast<int32_t>(comUnit));
m_voiceRooms.remove(comUnit);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::setVolume(const ComUnit comUnit, const int32_t volumne)
{
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!");
try
{
m_voice->SetRoomVolume(static_cast<int32_t>(comUnit), volumne);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::startTransmitting(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->IsRoomValid(static_cast<int32_t>(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!");
try
{
m_voice->SetMicState(static_cast<int32_t>(comUnit), true);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::stopTransmitting(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->IsRoomValid(static_cast<int32_t>(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!");
try
{
m_voice->SetMicState(static_cast<int32_t>(comUnit), false);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd)
{
m_voiceRoomsStatus[comUnit] = upd;
switch (upd)
{
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinSuccess:
enableAudio(comUnit);
emit connected(comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinFail:
emit connectionFailed(comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_UnexpectedDisconnectOrKicked:
emit kicked(comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_LeaveComplete:
m_voiceRoomsUsers.clear();
emit disconnected(comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_UserJoinsLeaves:
// FIXME: We cannot call GetRoomUserList because vatlib is reentrent safe.
emit userJoinedLeft (comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_RoomAudioStarted:
emit audioStarted (comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_RoomAudioStopped:
emit audioStopped (comUnit);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_AudioStarted:
emit globalAudioStarted();
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_AudioStopped:
emit globalAudioStopped();
break;
default:
break;
}
}
void CVoiceClientVatlib::timerEvent(QTimerEvent *)
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
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); }
@@ -274,13 +349,11 @@ namespace BlackCore
void CVoiceClientVatlib::onEndFindSquelch()
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
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();
emit squelchTestFinished();
}
@@ -289,35 +362,65 @@ namespace BlackCore
void CVoiceClientVatlib::onEndMicTest()
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
try
{
Q_ASSERT_X (m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!");
m_micTestResult = m_voice->EndMicTest();
emit micTestFinished();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::onUserJoinedLeft(const int32_t roomIndex)
void CVoiceClientVatlib::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_queryUserRoomIndex == -1, "CVoiceClientVatlib::onUserJoinedLeft", "Cannot list users for two rooms in parallel!");
try
{
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!");
if (!m_voice->IsRoomValid(roomIndex))
{
qDebug() << "Error: room index out of bounds";
return;
}
if (!m_voice->IsRoomConnected(roomIndex))
// Paranoia...
if (!m_voice->IsRoomConnected(static_cast<int32_t>(comUnit)))
return;
// Store the room index for the slot.
m_queryUserRoomIndex = roomIndex;
m_voice->GetRoomUserList(roomIndex, onRoomUserReceived, this);
m_queryUserRoomIndex = static_cast<int32_t>(comUnit);
m_voice->GetRoomUserList(static_cast<int32_t>(comUnit), onRoomUserReceived, this);
m_queryUserRoomIndex = -1;
QSet<QString> temporaryUsers;
foreach (QString callsign, m_voiceRoomsUsers.value(comUnit))
{
if (m_voiceRoomUsersUpdate.contains(callsign))
{
// The user is still there.
temporaryUsers.insert(callsign);
}
else
{
// He is has probably left
emit userLeftRoom(callsign);
}
}
foreach (QString callsign, m_voiceRoomUsersUpdate)
{
if (m_voiceRoomsUsers.value(comUnit).contains(callsign))
{
// User was already there before
temporaryUsers.insert(callsign);
}
else
{
// He joined
temporaryUsers.insert(callsign);
emit userJoinedRoom(callsign);
}
}
// Finally we update it with our new list
m_voiceRoomsUsers[comUnit] = temporaryUsers;
m_voiceRoomUsersUpdate.clear();
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
@@ -333,87 +436,43 @@ namespace BlackCore
void CVoiceClientVatlib::onRoomStatusUpdate(Cvatlib_Voice_Simple *obj, Cvatlib_Voice_Simple::roomStatusUpdate upd, int32_t roomIndex, void *cbVar)
{
cbvar_cast(cbVar)->m_voiceRoomsStatus[roomIndex] = upd;
switch (upd)
{
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinSuccess:
cbvar_cast(cbVar)->enableAudio(roomIndex);
emit cbvar_cast(cbVar)->connected(roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinFail:
emit cbvar_cast(cbVar)->connectionFailed(roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_UnexpectedDisconnectOrKicked:
emit cbvar_cast(cbVar)->kicked(roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_LeaveComplete:
emit cbvar_cast(cbVar)->disconnected(roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_UserJoinsLeaves:
// FIXME: We cannot call GetRoomUserList because vatlib is reentrent safe.
emit cbvar_cast(cbVar)->userJoinedLeft (roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_RoomAudioStarted:
emit cbvar_cast(cbVar)->audioStarted (roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_RoomAudioStopped:
emit cbvar_cast(cbVar)->audioStopped (roomIndex);
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_AudioStarted:
emit cbvar_cast(cbVar)->audioStarted();
break;
case Cvatlib_Voice_Simple::roomStatusUpdate_AudioStopped:
emit cbvar_cast(cbVar)->audioStopped();
break;
default:
break;
}
Q_UNUSED(obj)
ComUnit comUnit = static_cast<ComUnit>(roomIndex);
CVoiceClientVatlib *voiceClientVatlib = cbvar_cast(cbVar);
voiceClientVatlib->changeRoomStatus(comUnit, upd);
}
void CVoiceClientVatlib::onRoomUserReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar)
{
Q_UNUSED(obj)
CVoiceClientVatlib *voiceClientVatlib = cbvar_cast(cbVar);
ComUnit comUnit = static_cast<ComUnit>(voiceClientVatlib->queryUserRoomIndex());
// This method retrieves first of all a list of the known users
QStringList users = voiceClientVatlib->roomUserList(voiceClientVatlib->queryUserRoomIndex());
QSet<QString> users = voiceClientVatlib->roomUserList(comUnit);
QString callsign = QString(name);
if (callsign.isEmpty())
return;
// if the user is already known, the user had left
// else, the user joined.
if (users.contains(callsign))
{
voiceClientVatlib->removeUserFromRoom(voiceClientVatlib->queryUserRoomIndex(), callsign);
}
else
{
voiceClientVatlib->addUserInRoom(voiceClientVatlib->queryUserRoomIndex(), callsign);
}
voiceClientVatlib->addUserInRoom(comUnit, callsign);
}
void CVoiceClientVatlib::onInputHardwareDeviceReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar)
{
Q_UNUSED(obj)
BlackMisc::Voice::CInputAudioDevice inputDevice(cbvar_cast(cbVar)->m_inputDevices.size(), QString(name));
cbvar_cast(cbVar)->m_inputDevices.append(inputDevice);
}
void CVoiceClientVatlib::onOutputHardwareDeviceReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar)
{
Q_UNUSED(obj)
BlackMisc::Voice::COutputAudioDevice outputDevice(cbvar_cast(cbVar)->m_outputDevices.size(), QString(name));
cbvar_cast(cbVar)->m_outputDevices.append(outputDevice);
}
void CVoiceClientVatlib::addUserInRoom(const int32_t roomIndex, const QString &callsign)
void CVoiceClientVatlib::addUserInRoom(const ComUnit comUnit, const QString &callsign)
{
m_voiceRoomsUsers[roomIndex].append(callsign);
bool test = m_voice->IsAudioPlaying(roomIndex);
emit userJoinedRoom(callsign);
}
void CVoiceClientVatlib::removeUserFromRoom(const int32_t roomIndex, const QString &callsign)
{
m_voiceRoomsUsers[roomIndex].removeAll(callsign);
emit userLeftRoom(callsign);
m_voiceRoomUsersUpdate.insert(callsign);
}
void CVoiceClientVatlib::exceptionDispatcher(const char *caller)

View File

@@ -10,6 +10,8 @@
#include <QScopedPointer>
#include <QMap>
#include <QSet>
#include <QString>
namespace BlackCore
{
@@ -24,16 +26,7 @@ namespace BlackCore
CVoiceClientVatlib(QObject *parent = 0);
virtual ~CVoiceClientVatlib();
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign);
virtual void joinVoiceRoom(const int32_t comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom);
virtual void leaveVoiceRoom(const int32_t comUnit);
virtual void setVolume(const int32_t comUnit, const uint32_t volumne);
virtual void startTransmitting(const int32_t comUnit);
virtual void stopTransmitting(const int32_t comUnit);
virtual bool isReceiving(const int32_t comUnit);
virtual bool isConnected(const int32_t comUnit);
virtual const QStringList roomUserList(const int32_t comUnit);
virtual const QSet<QString> roomUserList(const ComUnit comUnit);
// Hardware devices
// TODO: Vatlib supports multiple output devices. That basically means, you could connect
@@ -42,29 +35,54 @@ namespace BlackCore
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 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);
virtual void enableAudio(const int32_t comUnit);
virtual void enableAudio(const ComUnit comUnit);
virtual const BlackMisc::Voice::CVoiceRoom voiceRoom (const ComUnit comUnit);
virtual bool isConnected(const ComUnit comUnit);
virtual bool isReceiving(const ComUnit comUnit);
/************************************************
* SETUP TESTS
* *********************************************/
// Mic tests
virtual void runSquelchTest();
virtual void runMicTest();
virtual float inputSquelch() const;
virtual Cvatlib_Voice_Simple::agc micTestResult() const;
virtual int32_t micTestResult() const;
virtual QString micTestResultAsString() const;
virtual const BlackMisc::Voice::CVoiceRoom &voiceRoom (const uint32_t comUnit);
public slots:
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign);
virtual void joinVoiceRoom(const ComUnit comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom);
virtual void leaveVoiceRoom(const ComUnit comUnit);
virtual void setVolume(const ComUnit comUnit, const int32_t volumne);
virtual void startTransmitting(const ComUnit comUnit);
virtual void stopTransmitting(const ComUnit comUnit);
/************************************************
* NON API METHODS:
* The following methods are not part of the
* public API. They are needed for internal
* workflow.
* *********************************************/
int32_t queryUserRoomIndex() const {return m_queryUserRoomIndex;}
signals:
void changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd);
public slots:
signals:
void userJoinedLeft(const ComUnit comUnit);
protected: // QObject overrides
virtual void timerEvent(QTimerEvent *);
@@ -75,21 +93,18 @@ namespace BlackCore
void onEndMicTest();
// slot to handle users
void onUserJoinedLeft(const int32_t roomIndex);
signals:
void userJoinedLeft(const int32_t roomIndex);
void onUserJoinedLeft(const ComUnit comUnit);
private:
// shimlib callbacks
static void onRoomStatusUpdate(Cvatlib_Voice_Simple* obj, Cvatlib_Voice_Simple::roomStatusUpdate upd, INT roomIndex, void* cbVar);
static void onRoomStatusUpdate(Cvatlib_Voice_Simple* obj, Cvatlib_Voice_Simple::roomStatusUpdate upd, int32_t roomIndex, void* cbVar);
static void onRoomUserReceived(Cvatlib_Voice_Simple* obj, const char* name, void* cbVar);
static void onInputHardwareDeviceReceived(Cvatlib_Voice_Simple* obj, const char* name, void* cbVar);
static void onOutputHardwareDeviceReceived(Cvatlib_Voice_Simple* obj, const char* name, void* cbVar);
void addUserInRoom(const int32_t roomIndex, const QString &callsign);
void removeUserFromRoom(const int32_t roomIndex, const QString &callsign);
void addUserInRoom(const ComUnit comUnit, const QString &callsign);
void removeUserFromRoom(const ComUnit comUnit, const QString &callsign);
void exceptionDispatcher(const char *caller);
@@ -103,19 +118,21 @@ namespace BlackCore
QScopedPointer<Cvatlib_Voice_Simple, Cvatlib_Voice_Simple_Deleter> m_voice;
BlackMisc::Aviation::CCallsign m_callsign;
QMap<uint32_t, BlackMisc::Voice::CVoiceRoom> m_voiceRooms;
QMap<ComUnit, BlackMisc::Voice::CVoiceRoom> m_voiceRooms;
QList<BlackMisc::Voice::CInputAudioDevice> m_inputDevices;
QList<BlackMisc::Voice::COutputAudioDevice> m_outputDevices;
float m_inputSquelch;
Cvatlib_Voice_Simple::agc m_micTestResult;
typedef QMap<int32_t, Cvatlib_Voice_Simple::roomStatusUpdate> TMapRoomsStatus;
typedef QMap<ComUnit, Cvatlib_Voice_Simple::roomStatusUpdate> TMapRoomsStatus;
TMapRoomsStatus m_voiceRoomsStatus;
typedef QMap<int32_t, QStringList> TMapRoomsUsers;
typedef QMap<ComUnit, QSet<QString>> TMapRoomsUsers;
TMapRoomsUsers m_voiceRoomsUsers;
QSet<QString> m_voiceRoomUsersUpdate;
// Need to keep the roomIndex because GetRoomUserList does not specifiy it
int32_t m_queryUserRoomIndex;
};