Finalized voice vatlib implementation.

refs #36
- Implemented the rest of the methods
- Added more commands to the voice sample, to login to voice server
- Login successfull. However, no voice yet.

refs #81
This commit is contained in:
Roland Winklmeier
2013-12-01 01:53:26 +01:00
committed by Mathew Sutcliffe
parent f91525b65b
commit 45b9f60444
5 changed files with 304 additions and 61 deletions

View File

@@ -12,6 +12,8 @@ Client::Client(QObject *parent) :
using namespace BlackCore;
connect(m_voiceClient, &IVoiceClient::squelchTestFinished, this, &Client::onSquelchTestFinished);
connect(m_voiceClient, &IVoiceClient::micTestFinished, this, &Client::onMicTestFinished);
connect(m_voiceClient, &IVoiceClient::connected, this, &Client::connectionStatusConnected);
@@ -19,8 +21,11 @@ Client::Client(QObject *parent) :
m_commands["help"] = std::bind(&Client::help, this, _1);
m_commands["echo"] = std::bind(&Client::echo, this, _1);
m_commands["exit"] = std::bind(&Client::exit, this, _1);
m_commands["runsquelchtest"] = std::bind(&Client::runSquelchTest, this, _1);
m_commands["runmictest"] = std::bind(&Client::runMicTest, this, _1);
m_commands["squelchtest"] = std::bind(&Client::runSquelchTest, this, _1);
m_commands["mictest"] = std::bind(&Client::runMicTest, this, _1);
m_commands["setcallsign"] = std::bind(&Client::setCallsignCmd, this, _1);
m_commands["initconnect"] = std::bind(&Client::initiateConnectionCmd, this, _1);
m_commands["termconnect"] = std::bind(&Client::terminateConnectionCmd, this, _1);
}
@@ -89,6 +94,30 @@ void Client::runMicTest(QTextStream &args)
m_voiceClient->runMicTest();
}
void Client::setCallsignCmd(QTextStream &args)
{
QString callsign;
args >> callsign;
m_voiceClient->setCallsign(BlackMisc::Aviation::CCallsign(callsign));
}
void Client::initiateConnectionCmd(QTextStream &args)
{
QString hostname;
QString channel;
args >> hostname >> channel;
std::cout << "Joining voice room: " << hostname.toStdString() << "/" << channel.toStdString() << std::endl;
m_voiceClient->joinVoiceRoom(0, BlackMisc::Voice::CVoiceRoom(hostname, channel));
printLinePrefix();
}
void Client::terminateConnectionCmd(QTextStream &args)
{
std::cout << "Leaving room." << std::endl;
m_voiceClient->leaveVoiceRoom(0);
printLinePrefix();
}
void Client::onSquelchTestFinished()
{
std::cout << "Input squelch: " << m_voiceClient->inputSquelch() << std::endl;
@@ -100,3 +129,16 @@ void Client::onMicTestFinished()
std::cout << "Mic test result: " << (int)m_voiceClient->micTestResult() << std::endl;
printLinePrefix();
}
void Client::connectionStatusConnected()
{
std::cout << "CONN_STATUS_CONNECTED" << std::endl;
printLinePrefix();
}
void Client::connectionStatusDisconnected()
{
std::cout << "CONN_STATUS_DISCONNECTED" << std::endl;
printLinePrefix();
}

View File

@@ -29,12 +29,19 @@ private: //commands
void exit(QTextStream &args);
void runSquelchTest(QTextStream &args);
void runMicTest(QTextStream &args);
void setCallsignCmd(QTextStream &args);
void initiateConnectionCmd(QTextStream &args);
void terminateConnectionCmd(QTextStream &args);
void printLinePrefix();
public slots:
void onSquelchTestFinished();
void onMicTestFinished();
private slots:
void connectionStatusConnected();
void connectionStatusDisconnected();
private:
QMap<QString, std::function<void(QTextStream &)>> m_commands;

View File

@@ -18,11 +18,17 @@
#include <vatlib/vatlib.h>
#include <QObject>
#include <QStringList>
namespace BlackCore
{
/*!
* Interface to a connection to a ATC voice server for use in flight simulation.
*
* \warning If an INetwork signal is connected to a slot, and that slot emits a signal
* which is connected to an INetwork slot, then at least one of those connections
* must be a Qt::QueuedConnection.
* Reason: IVoiceClient implementations are not re-entrant.
*/
class IVoiceClient : public QObject
{
@@ -47,18 +53,8 @@ namespace BlackCore
virtual ~IVoiceClient() {}
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign) = 0;
virtual void joinVoiceRoom(const uint32_t comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom) = 0;
virtual void leaveVoiceRoom(const uint32_t comUnit) = 0;
virtual void setVolume(const uint32_t comUnit, const uint32_t volumne) = 0;
virtual void startTransmitting(const uint32_t comUnit) = 0;
virtual void stopTransmitting(const uint32_t comUnit) = 0;
virtual bool isReceiving(const uint32_t comUnit) = 0;
virtual bool isConnected(const uint32_t comUnit) = 0;
// The following method should be called everytime you receive a user update signal
virtual void roomUserList(const uint32_t comUnit) = 0;
virtual const QStringList roomUserList(const int32_t comUnit) = 0;
// Hardware devices
virtual const QList<BlackMisc::Voice::CInputAudioDevice> & audioInputDevices() const = 0;
@@ -70,6 +66,8 @@ namespace BlackCore
virtual void setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device) = 0;
virtual void setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device) = 0;
virtual void enableAudio(const int32_t comUnit) = 0;
// Mic tests
virtual void runSquelchTest() = 0;
@@ -80,23 +78,36 @@ namespace BlackCore
virtual const BlackMisc::Voice::CVoiceRoom &voiceRoom (const uint32_t comUnit) = 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;
signals:
// Signals regarding the voice server connection
void notConnected(const uint32_t comUnit);
void connecting(const uint32_t comUnit);
void connected(const uint32_t comUnit);
void connectionFailed(const uint32_t comUnit);
void kicked(const uint32_t comUnit);
void disconnecting(const uint32_t comUnit);
void disconnected(const uint32_t comUnit);
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);
// Signals about users joining and leaving
void userJoined(const uint32_t comUnit, const BlackMisc::Aviation::CCallsign &callsign);
void userLeft(const uint32_t comUnit, const BlackMisc::Aviation::CCallsign &callsign);
void userJoinedRoom(const QString &callsign);
void userLeftRoom(const QString &callsign);
// Audio signals
void audioStarted(const uint32_t comUnit);
void audioStopped(const uint32_t comUnit);
void audioStarted(const int32_t comUnit);
void audioStopped(const int32_t comUnit);
void audioStarted();
void audioStopped();
// Test signals
void squelchTestFinished();

View File

@@ -13,7 +13,8 @@ namespace BlackCore
CVoiceClientVatlib::CVoiceClientVatlib(QObject *parent) :
IVoiceClient(parent),
m_voice(Create_Cvatlib_Voice_Simple()),
m_inputSquelch(-1)
m_inputSquelch(-1),
m_queryUserRoomIndex(-1)
{
try
{
@@ -26,6 +27,9 @@ namespace BlackCore
setInputDevice(defaultAudioInputDevice());
setOutputDevice(defaultAudioOutputDevice());
connect(this, &CVoiceClientVatlib::userJoinedLeft, this, &CVoiceClientVatlib::onUserJoinedLeft, Qt::QueuedConnection);
connect(this, &CVoiceClientVatlib::connected, this, &CVoiceClientVatlib::onUserJoinedLeft, Qt::QueuedConnection);
startTimer(100);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
@@ -40,44 +44,110 @@ namespace BlackCore
m_callsign = callsign;
}
void CVoiceClientVatlib::joinVoiceRoom(const uint32_t comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom)
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::leaveVoiceRoom(const uint32_t comUnit)
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); }
}
void CVoiceClientVatlib::setVolume(const uint32_t comUnit, const uint32_t volumne)
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!");
m_voice->IsRoomConnected(comUnit);
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::startTransmitting(const uint32_t comUnit)
const QStringList CVoiceClientVatlib::roomUserList(const int32_t comUnit)
{
}
void CVoiceClientVatlib::stopTransmitting(const uint32_t comUnit)
{
}
bool CVoiceClientVatlib::isReceiving(const uint32_t comUnit)
{
}
bool CVoiceClientVatlib::isConnected(const uint32_t comUnit)
{
}
void CVoiceClientVatlib::roomUserList(const uint32_t comUnit)
{
/**/
return m_voiceRoomsUsers.value(comUnit);
}
const QList<BlackMisc::Voice::CInputAudioDevice> &CVoiceClientVatlib::audioInputDevices() const
@@ -129,6 +199,11 @@ 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)
{
if (!device.isValid())
@@ -224,6 +299,29 @@ namespace BlackCore
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
void CVoiceClientVatlib::onUserJoinedLeft(const int32_t roomIndex)
{
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))
return;
// Store the room index for the slot.
m_queryUserRoomIndex = roomIndex;
m_voice->GetRoomUserList(roomIndex, onRoomUserReceived, this);
m_queryUserRoomIndex = -1;
}
catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); }
}
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
/********************************** shimlib callbacks ************************************/
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
@@ -235,12 +333,62 @@ 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;
}
}
void CVoiceClientVatlib::onRoomUserReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar)
{
CVoiceClientVatlib *voiceClientVatlib = cbvar_cast(cbVar);
// This method retrieves first of all a list of the known users
QStringList users = voiceClientVatlib->roomUserList(voiceClientVatlib->queryUserRoomIndex());
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);
}
}
void CVoiceClientVatlib::onInputHardwareDeviceReceived(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar)
@@ -255,6 +403,19 @@ namespace BlackCore
cbvar_cast(cbVar)->m_outputDevices.append(outputDevice);
}
void CVoiceClientVatlib::addUserInRoom(const int32_t roomIndex, 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);
}
void CVoiceClientVatlib::exceptionDispatcher(const char *caller)
{
QString msg("Caller: ");

View File

@@ -25,15 +25,15 @@ namespace BlackCore
virtual ~CVoiceClientVatlib();
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign);
virtual void joinVoiceRoom(const uint32_t comUnit, const BlackMisc::Voice::CVoiceRoom &voiceRoom);
virtual void leaveVoiceRoom(const uint32_t comUnit);
virtual void setVolume(const uint32_t comUnit, const uint32_t volumne);
virtual void startTransmitting(const uint32_t comUnit);
virtual void stopTransmitting(const uint32_t comUnit);
virtual bool isReceiving(const uint32_t comUnit);
virtual bool isConnected(const uint32_t comUnit);
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 void roomUserList(const uint32_t comUnit);
virtual const QStringList roomUserList(const int32_t comUnit);
// Hardware devices
// TODO: Vatlib supports multiple output devices. That basically means, you could connect
@@ -48,6 +48,8 @@ namespace BlackCore
virtual void setInputDevice(const BlackMisc::Voice::CInputAudioDevice &device);
virtual void setOutputDevice(const BlackMisc::Voice::COutputAudioDevice &device);
virtual void enableAudio(const int32_t comUnit);
// Mic tests
virtual void runSquelchTest();
virtual void runMicTest();
@@ -58,6 +60,8 @@ namespace BlackCore
virtual const BlackMisc::Voice::CVoiceRoom &voiceRoom (const uint32_t comUnit);
int32_t queryUserRoomIndex() const {return m_queryUserRoomIndex;}
signals:
public slots:
@@ -70,6 +74,12 @@ namespace BlackCore
void onEndFindSquelch();
void onEndMicTest();
// slot to handle users
void onUserJoinedLeft(const int32_t roomIndex);
signals:
void userJoinedLeft(const int32_t roomIndex);
private:
// shimlib callbacks
@@ -78,6 +88,9 @@ 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);
void addUserInRoom(const int32_t roomIndex, const QString &callsign);
void removeUserFromRoom(const int32_t roomIndex, const QString &callsign);
void exceptionDispatcher(const char *caller);
struct Cvatlib_Voice_Simple_Deleter
@@ -90,12 +103,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_voiceRoomMap;
QMap<uint32_t, 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;
TMapRoomsStatus m_voiceRoomsStatus;
typedef QMap<int32_t, QStringList> TMapRoomsUsers;
TMapRoomsUsers m_voiceRoomsUsers;
// Need to keep the roomIndex because GetRoomUserList does not specifiy it
int32_t m_queryUserRoomIndex;
};
} // namespace BlackCore