mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 11:55:35 +08:00
refs #320 Porting voice channels to new API
This commit is contained in:
@@ -15,8 +15,7 @@ namespace BlackCore
|
||||
// for some reasons (ask RW) these are registered twice
|
||||
qRegisterMetaType<ISimulator::ConnectionStatus>();
|
||||
qRegisterMetaType<ISimulator::ConnectionStatus>("Status");
|
||||
qRegisterMetaType<IVoiceChannel::ConnectionStatus>();
|
||||
qRegisterMetaType<IVoiceChannel::ConnectionStatus>("ConnectionStatus");
|
||||
qRegisterMetaType<BlackCore::IVoiceChannel::ConnectionStatus>();
|
||||
}
|
||||
|
||||
bool isCurrentThreadCreatingThread(QObject *toBeTested)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "context_ownaircraft.h"
|
||||
#include "context_application.h"
|
||||
#include "voice_channel.h"
|
||||
#include "voice_vatlib.h"
|
||||
|
||||
#include "blacksound/soundgenerator.h"
|
||||
#include "blackmisc/notificationsounds.h"
|
||||
@@ -38,14 +39,14 @@ namespace BlackCore
|
||||
|
||||
// 2. Register PTT hotkey function
|
||||
m_inputManager = CInputManager::getInstance();
|
||||
m_handlePtt = m_inputManager->registerHotkeyFunc(CHotkeyFunction::Ptt(), voice, &CVoiceVatlib::handlePushToTalk);
|
||||
|
||||
m_channelCom1 = m_voice->getVoiceChannel(0);
|
||||
m_channelCom1 = m_voice->createVoiceChannel();
|
||||
m_channelCom1->setMyAircraftCallsign(getIContextOwnAircraft()->getOwnAircraft().getCallsign());
|
||||
connect(m_channelCom1.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::ps_com1ConnectionStatusChanged);
|
||||
m_channelCom2 = m_voice->getVoiceChannel(1);
|
||||
connect(m_channelCom1.get(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::ps_com1ConnectionStatusChanged);
|
||||
m_channelCom2 = m_voice->createVoiceChannel();
|
||||
m_channelCom2->setMyAircraftCallsign(getIContextOwnAircraft()->getOwnAircraft().getCallsign());
|
||||
connect(m_channelCom2.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::ps_com2ConnectionStatusChanged);
|
||||
connect(m_channelCom2.get(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::ps_com2ConnectionStatusChanged);
|
||||
|
||||
m_voiceInputDevice = m_voice->createInputDevice();
|
||||
m_voiceOutputDevice = m_voice->createOutputDevice();
|
||||
|
||||
|
||||
@@ -164,12 +164,12 @@ namespace BlackCore
|
||||
//! Connection in transition
|
||||
bool inTransitionState() const;
|
||||
|
||||
std::unique_ptr<CVoiceVatlib> m_voice; //!< underlying voice lib
|
||||
std::unique_ptr<IVoice> m_voice; //!< underlying voice lib
|
||||
|
||||
CInputManager *m_inputManager = nullptr;
|
||||
CInputManager::RegistrationHandle m_handlePtt;
|
||||
QPointer<IVoiceChannel> m_channelCom1;
|
||||
QPointer<IVoiceChannel> m_channelCom2;
|
||||
std::unique_ptr<IVoiceChannel> m_channelCom1;
|
||||
std::unique_ptr<IVoiceChannel> m_channelCom2;
|
||||
std::unique_ptr<IAudioOutputDevice> m_voiceOutputDevice;
|
||||
int m_outDeviceVolume = 100;
|
||||
std::unique_ptr<IAudioInputDevice> m_voiceInputDevice;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#define BLACKCORE_VOICE_H
|
||||
|
||||
#include "audio_device.h"
|
||||
#include "voice_channel.h"
|
||||
|
||||
#include "../blackmisc/avcallsignlist.h"
|
||||
#include "../blackmisc/avselcal.h"
|
||||
#include "../blackmisc/nwuserlist.h"
|
||||
@@ -20,7 +22,6 @@
|
||||
|
||||
namespace BlackCore
|
||||
{
|
||||
class IVoiceChannel;
|
||||
//! Interface to a connection to a ATC voice server for use in flight simulation.
|
||||
class IVoice : public QObject
|
||||
{
|
||||
@@ -37,15 +38,15 @@ namespace BlackCore
|
||||
//! Virtual destructor.
|
||||
virtual ~IVoice() {}
|
||||
|
||||
//! Create voice channel object
|
||||
virtual std::unique_ptr<IVoiceChannel> createVoiceChannel() = 0;
|
||||
|
||||
//! Create input device object
|
||||
virtual std::unique_ptr<IAudioInputDevice> createInputDevice() = 0;
|
||||
|
||||
//! Create output device object
|
||||
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() = 0;
|
||||
|
||||
//! Get voice channel object
|
||||
virtual IVoiceChannel *getVoiceChannel(qint32 channelIndex) const = 0;
|
||||
|
||||
/*!
|
||||
* \brief Enable audio loopback to route recorded voice from microphone to speakers
|
||||
* \param enable (default true)
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#ifndef BLACKCORE_VOICE_CHANNEL_H
|
||||
#define BLACKCORE_VOICE_CHANNEL_H
|
||||
|
||||
#include "voice_vatlib.h"
|
||||
#include "blackmisc/statusmessage.h"
|
||||
#include "blackmisc/voiceroomlist.h"
|
||||
#include "blackmisc/avcallsignlist.h"
|
||||
@@ -40,44 +39,35 @@ namespace BlackCore
|
||||
ConnectingFailed, //!< Failed to connect
|
||||
};
|
||||
|
||||
//! Constructor
|
||||
IVoiceChannel(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
//! Destructor
|
||||
virtual ~IVoiceChannel() {}
|
||||
|
||||
//! Join voice room
|
||||
virtual void joinVoiceRoom(const BlackMisc::Audio::CVoiceRoom &voiceRoom) = 0;
|
||||
|
||||
//! Leave voice room
|
||||
virtual void leaveVoiceRoom() = 0;
|
||||
|
||||
//! Start transmitting
|
||||
virtual void startTransmitting() = 0;
|
||||
|
||||
//! Stop transmitting
|
||||
virtual void stopTransmitting() = 0;
|
||||
|
||||
//! Get voice room callsings
|
||||
virtual BlackMisc::Aviation::CCallsignList getVoiceRoomCallsigns() const = 0;
|
||||
|
||||
//! Switch audio output, enable or disable
|
||||
virtual void switchAudioOutput(bool enable) = 0;
|
||||
|
||||
//! Set own aircraft's callsign
|
||||
virtual void setMyAircraftCallsign(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
//! Get voice room
|
||||
virtual BlackMisc::Audio::CVoiceRoom getVoiceRoom() const = 0;
|
||||
|
||||
//! Get assigned room index
|
||||
virtual qint32 getRoomIndex() const = 0;
|
||||
|
||||
//! Is channel muted?
|
||||
virtual bool isMuted() const = 0;
|
||||
|
||||
//! Set channel volume 0..100
|
||||
virtual void setVolume(quint32 volume) = 0;
|
||||
virtual void setVolume(int volume) = 0;
|
||||
|
||||
//! Get channel volume 0..100
|
||||
virtual quint32 getVolume() const = 0;
|
||||
|
||||
//! Update room status
|
||||
virtual void updateRoomStatus(Cvatlib_Voice_Simple::roomStatusUpdate roomStatus) = 0;
|
||||
virtual int getVolume() const = 0;
|
||||
|
||||
signals:
|
||||
|
||||
@@ -105,12 +95,6 @@ namespace BlackCore
|
||||
|
||||
protected:
|
||||
|
||||
//! Constructor
|
||||
IVoiceChannel(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
//! Destructor
|
||||
virtual ~IVoiceChannel() {}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -22,190 +22,97 @@ namespace BlackCore
|
||||
// Room data hash shared between all CVoiceChannel objects
|
||||
QHash<CVoiceChannelVatlib * const, QSharedPointer<CVoiceChannelVatlibPrivate>> CVoiceChannelVatlibPrivate::m_sharedRoomData;
|
||||
|
||||
// Static list of available rooms
|
||||
QList<qint32> CVoiceChannelVatlibPrivate::m_availableRooms = {0, 1};
|
||||
|
||||
// Constructor
|
||||
// Don't set the QObject parent. It will conflict with @QSharedPointer@ memory management
|
||||
CVoiceChannelVatlibPrivate::CVoiceChannelVatlibPrivate(TVatlibPointer vatlib, CVoiceChannelVatlib *parent)
|
||||
: m_vatlib(vatlib),
|
||||
m_mutexSharedRoomData(QMutex::Recursive),
|
||||
m_mutexCallSign(QMutex::Recursive),
|
||||
m_mutexVoiceRoom(QMutex::Recursive),
|
||||
m_mutexCallsignList(QMutex::Recursive),
|
||||
CVoiceChannelVatlibPrivate::CVoiceChannelVatlibPrivate(VatAudioService audioService, VatUDPAudioPort udpPort, CVoiceChannelVatlib *parent)
|
||||
: m_audioService(audioService),
|
||||
m_udpPort(udpPort),
|
||||
q_ptr(parent)
|
||||
{
|
||||
m_roomIndex.store(InvalidRoomIndex);
|
||||
m_connectionRefCount.store(0);
|
||||
m_outputEnabled.store(true);
|
||||
m_roomStatus.store(IVoiceChannel::Disconnected);
|
||||
Q_ASSERT(m_audioService);
|
||||
Q_ASSERT(m_udpPort);
|
||||
|
||||
connect(this, &CVoiceChannelVatlibPrivate::userJoinedLeft, this, &CVoiceChannelVatlibPrivate::processUserJoinedLeft, Qt::QueuedConnection);
|
||||
m_connectionRefCount = 0;
|
||||
m_roomStatus = IVoiceChannel::Disconnected;
|
||||
|
||||
m_voiceChannels.push_back(parent);
|
||||
|
||||
m_voiceChannel.reset(Vat_CreateVoiceChannel(m_audioService, "", 3782, "", "", m_udpPort));
|
||||
Vat_SetConnectionChangedHandler(m_voiceChannel.data(), onRoomStatusUpdate, this);
|
||||
Vat_SetClientJoinedHandler(m_voiceChannel.data(), processUserJoined, this);
|
||||
Vat_SetClientLeftHandler(m_voiceChannel.data(), processUserLeft, this);
|
||||
Vat_SetVoiceTransmissionChangedHandler(m_voiceChannel.data(), processTransmissionChange, this);
|
||||
}
|
||||
|
||||
CVoiceChannelVatlibPrivate::~CVoiceChannelVatlibPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::changeConnectionStatus(IVoiceChannel::ConnectionStatus newStatus)
|
||||
void CVoiceChannelVatlibPrivate::setRoomOutputVolume(int volume)
|
||||
{
|
||||
Q_Q(CVoiceChannelVatlib);
|
||||
|
||||
m_roomStatus = newStatus;
|
||||
emit q->connectionStatusChanged(m_roomStatus, newStatus);
|
||||
// FIXME
|
||||
Q_UNUSED(volume)
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::switchAudioOutput(bool enable)
|
||||
void CVoiceChannelVatlibPrivate::updateRoomStatus(VatVoiceChannel /* channel */, VatConnectionStatus /** oldVatStatus **/, VatConnectionStatus newVatStatus)
|
||||
{
|
||||
std::lock_guard<TVatlibPointer> locker(m_vatlib);
|
||||
Q_ASSERT_X(m_vatlib->IsValid() && m_vatlib->IsSetup(), "CVoiceChannelVatlibPrivate", "Cvatlib_Voice_Simple invalid or not setup!");
|
||||
Q_ASSERT_X(m_vatlib->IsRoomValid(m_roomIndex), "CVoiceChannelVatlibPrivate", "Room index out of bounds!");
|
||||
|
||||
m_outputEnabled = enable;
|
||||
|
||||
try
|
||||
IVoiceChannel::ConnectionStatus oldStatus = m_roomStatus;
|
||||
switch (newVatStatus)
|
||||
{
|
||||
m_vatlib->SetOutputState(m_roomIndex, 0, enable);
|
||||
}
|
||||
catch (...)
|
||||
case vatStatusConnecting:
|
||||
{
|
||||
exceptionDispatcher(Q_FUNC_INFO);
|
||||
m_roomStatus = IVoiceChannel::Connecting;
|
||||
break;
|
||||
}
|
||||
case vatStatusConnected:
|
||||
{
|
||||
m_voiceRoom.setConnected(true);
|
||||
m_roomStatus = IVoiceChannel::Connected;
|
||||
break;
|
||||
}
|
||||
case vatStatusDisconnecting:
|
||||
{
|
||||
m_roomStatus = IVoiceChannel::Disconnecting;
|
||||
break;
|
||||
}
|
||||
case vatStatusDisconnected:
|
||||
{
|
||||
// Clear all internals
|
||||
m_listCallsigns.clear();
|
||||
m_voiceRoom = {};
|
||||
m_roomStatus = IVoiceChannel::Disconnected;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
emit q_ptr->connectionStatusChanged(oldStatus, m_roomStatus);
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::startTransmitting()
|
||||
void CVoiceChannelVatlibPrivate::userJoinedVoiceRoom(VatVoiceChannel, int /** id **/, const char *name)
|
||||
{
|
||||
std::lock_guard<TVatlibPointer> locker(m_vatlib);
|
||||
Q_ASSERT_X(m_vatlib->IsValid() && m_vatlib->IsSetup(), "CVoiceChannelVatlibPrivate", "Cvatlib_Voice_Simple invalid or not setup!");
|
||||
Q_ASSERT_X(m_vatlib->IsRoomValid(m_roomIndex), "CVoiceChannelVatlibPrivate", "Room index out of bounds!");
|
||||
CCallsign callsign(extractCallsign(name));
|
||||
m_listCallsigns.push_back(callsign);
|
||||
|
||||
if (m_roomStatus != IVoiceChannel::Connected) return;
|
||||
|
||||
try
|
||||
{
|
||||
m_vatlib->SetMicState(m_roomIndex, true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
this->exceptionDispatcher(Q_FUNC_INFO);
|
||||
}
|
||||
for (const auto &e : m_voiceChannels)
|
||||
emit e->userJoinedRoom(callsign);
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::stopTransmitting()
|
||||
void CVoiceChannelVatlibPrivate::userLeftVoiceRoom(VatVoiceChannel, int /** id **/, const char *name)
|
||||
{
|
||||
std::lock_guard<TVatlibPointer> locker(m_vatlib);
|
||||
Q_ASSERT_X(m_vatlib->IsValid() && m_vatlib->IsSetup(), "CVoiceChannelVatlibPrivate", "Cvatlib_Voice_Simple invalid or not setup!");
|
||||
Q_ASSERT_X(m_vatlib->IsRoomValid(m_roomIndex), "CVoiceChannelVatlibPrivate", "Room index out of bounds!");
|
||||
CCallsign callsign(extractCallsign(name));
|
||||
m_listCallsigns.remove(callsign);
|
||||
|
||||
if (m_roomStatus != IVoiceChannel::Connected) return;
|
||||
|
||||
try
|
||||
{
|
||||
m_vatlib->SetMicState(m_roomIndex, false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
this->exceptionDispatcher(Q_FUNC_INFO);
|
||||
}
|
||||
for (const auto &e : m_voiceChannels)
|
||||
emit e->userLeftRoom(callsign);
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::setRoomOutputVolume(const qint32 volume)
|
||||
void CVoiceChannelVatlibPrivate::transmissionChanged(VatVoiceChannel, VatVoiceTransmissionStatus status)
|
||||
{
|
||||
std::lock_guard<TVatlibPointer> locker(m_vatlib);
|
||||
Q_ASSERT_X(m_vatlib->IsValid() && m_vatlib->IsSetup(), "CVoiceChannelVatlibPrivate", "Cvatlib_Voice_Simple invalid or not setup!");
|
||||
Q_ASSERT_X(m_vatlib->IsRoomValid(m_roomIndex), "CVoiceChannelVatlibPrivate", "Room index out of bounds!");
|
||||
|
||||
try
|
||||
{
|
||||
m_vatlib->SetRoomVolume(m_roomIndex, volume);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
this->exceptionDispatcher(Q_FUNC_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
// Forward exception as signal
|
||||
void CVoiceChannelVatlibPrivate::exceptionDispatcher(const char *caller)
|
||||
{
|
||||
Q_Q(CVoiceChannelVatlib);
|
||||
|
||||
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
|
||||
CLogMessage(q).debug() << "NetworkNotConnectedException" << e.what() << "in" << caller;
|
||||
}
|
||||
catch (const VatlibException &e)
|
||||
{
|
||||
CLogMessage(q).error("VatlibException %1 in %2") << e.what() << caller;
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
CLogMessage(q).error("std::exception %1 in %2") << e.what() << caller;
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CLogMessage(q).error("Unknown exception in %1") << caller;
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::processUserJoinedLeft()
|
||||
{
|
||||
Q_Q(CVoiceChannelVatlib);
|
||||
|
||||
try
|
||||
{
|
||||
std::lock_guard<TVatlibPointer> locker(m_vatlib);
|
||||
// Paranoia... clear list completely
|
||||
if (!m_vatlib->IsRoomConnected(m_roomIndex))
|
||||
{
|
||||
QMutexLocker lockCallsignList(&m_mutexCallsignList);
|
||||
m_listCallsigns.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Callbacks already completed when function GetRoomUserList returns,
|
||||
// thereafter m_voiceRoomCallsignsUpdate is filled with the latest callsigns
|
||||
|
||||
m_vatlib->GetRoomUserList(m_roomIndex, updateRoomUsers, this);
|
||||
|
||||
QMutexLocker lockCallsignList(&m_mutexCallsignList);
|
||||
// we have all current users in m_temporaryVoiceRoomCallsigns
|
||||
foreach(CCallsign callsign, m_listCallsigns)
|
||||
{
|
||||
if (!m_temporaryVoiceRoomCallsigns.contains(callsign))
|
||||
{
|
||||
// User has left
|
||||
emit q->userLeftRoom(callsign);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(CCallsign callsign, m_temporaryVoiceRoomCallsigns)
|
||||
{
|
||||
if (!m_listCallsigns.contains(callsign))
|
||||
{
|
||||
// he joined
|
||||
emit q->userJoinedRoom(callsign);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we update it with our new list
|
||||
m_listCallsigns = m_temporaryVoiceRoomCallsigns;
|
||||
m_temporaryVoiceRoomCallsigns.clear();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
this->exceptionDispatcher(Q_FUNC_INFO);
|
||||
}
|
||||
if (status == vatVoiceStarted)
|
||||
emit q_ptr->audioStarted();
|
||||
else
|
||||
emit q_ptr->audioStopped();
|
||||
}
|
||||
|
||||
CVoiceChannelVatlibPrivate *cbvar_cast_voiceChannelPrivate(void *cbvar)
|
||||
@@ -213,39 +120,52 @@ namespace BlackCore
|
||||
return static_cast<CVoiceChannelVatlibPrivate *>(cbvar);
|
||||
}
|
||||
|
||||
/*
|
||||
* Room user received
|
||||
*/
|
||||
void CVoiceChannelVatlibPrivate::updateRoomUsers(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar)
|
||||
CCallsign CVoiceChannelVatlibPrivate::extractCallsign(const QString &name)
|
||||
{
|
||||
Q_UNUSED(obj)
|
||||
CCallsign callsign;
|
||||
if (name.isEmpty()) return callsign;
|
||||
|
||||
// sanity check
|
||||
QString callsign = QString(name);
|
||||
if (callsign.isEmpty()) return;
|
||||
|
||||
// add callsign
|
||||
CVoiceChannelVatlibPrivate *voiceChannelPrivate = cbvar_cast_voiceChannelPrivate(cbVar);
|
||||
|
||||
// add user
|
||||
// callsign might contain: VATSIM id, user name
|
||||
if (callsign.contains(" "))
|
||||
if (name.contains(" "))
|
||||
{
|
||||
QStringList parts = callsign.split(" ");
|
||||
callsign = parts[0];
|
||||
QStringList parts = name.split(" ");
|
||||
callsign = CCallsign(parts[0]);
|
||||
// I throw away VATSIM id here, maybe we could use it
|
||||
}
|
||||
else
|
||||
{
|
||||
callsign = CCallsign(name);
|
||||
}
|
||||
|
||||
voiceChannelPrivate->addTemporaryCallsignForRoom(CCallsign(callsign));
|
||||
return callsign;
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::processUserJoined(VatVoiceChannel channel, int id, const char *name, void *cbVar)
|
||||
{
|
||||
CVoiceChannelVatlibPrivate *voiceChannelPrivate = cbvar_cast_voiceChannelPrivate(cbVar);
|
||||
voiceChannelPrivate->userJoinedVoiceRoom(channel, id, name);
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::processUserLeft(VatVoiceChannel channel, int id, const char *name, void *cbVar)
|
||||
{
|
||||
CVoiceChannelVatlibPrivate *voiceChannelPrivate = cbvar_cast_voiceChannelPrivate(cbVar);
|
||||
voiceChannelPrivate->userLeftVoiceRoom(channel, id, name);
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlibPrivate::processTransmissionChange(VatVoiceChannel channel, VatVoiceTransmissionStatus status, void *cbVar)
|
||||
{
|
||||
CVoiceChannelVatlibPrivate *voiceChannelPrivate = cbvar_cast_voiceChannelPrivate(cbVar);
|
||||
|
||||
voiceChannelPrivate->transmissionChanged(channel, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add temp.callsign for room
|
||||
* Room status update
|
||||
*/
|
||||
void CVoiceChannelVatlibPrivate::addTemporaryCallsignForRoom(const CCallsign &callsign)
|
||||
void CVoiceChannelVatlibPrivate::onRoomStatusUpdate(VatVoiceChannel channel, VatConnectionStatus oldStatus, VatConnectionStatus newStatus, void *cbVar)
|
||||
{
|
||||
if (m_temporaryVoiceRoomCallsigns.contains(callsign)) return;
|
||||
m_temporaryVoiceRoomCallsigns.push_back(callsign);
|
||||
auto obj = cbvar_cast_voiceChannelPrivate(cbVar);
|
||||
obj->updateRoomStatus(channel, oldStatus, newStatus);
|
||||
}
|
||||
|
||||
// Get shared room data
|
||||
@@ -254,23 +174,17 @@ namespace BlackCore
|
||||
return m_sharedRoomData;
|
||||
}
|
||||
|
||||
// Allocate a new room
|
||||
qint32 CVoiceChannelVatlibPrivate::allocateRoom()
|
||||
{
|
||||
Q_ASSERT(!m_availableRooms.isEmpty());
|
||||
return m_availableRooms.takeFirst();
|
||||
}
|
||||
|
||||
// Constructor
|
||||
CVoiceChannelVatlib::CVoiceChannelVatlib(TVatlibPointer vatlib, QObject *parent)
|
||||
CVoiceChannelVatlib::CVoiceChannelVatlib(VatAudioService audioService, VatUDPAudioPort udpPort, QObject *parent)
|
||||
: IVoiceChannel(parent),
|
||||
d_ptr(new CVoiceChannelVatlibPrivate(vatlib, this))
|
||||
d_ptr(new CVoiceChannelVatlibPrivate(audioService, udpPort, this))
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
CVoiceChannelVatlib::~CVoiceChannelVatlib()
|
||||
{
|
||||
d_ptr->m_voiceChannels.removeAll(this);
|
||||
}
|
||||
|
||||
// Join room
|
||||
@@ -283,46 +197,40 @@ namespace BlackCore
|
||||
return roomData->m_voiceRoom.getVoiceRoomUrl() == voiceRoom.getVoiceRoomUrl();
|
||||
});
|
||||
|
||||
try
|
||||
// If we found another channel
|
||||
if (iterator != roomDataList.end())
|
||||
{
|
||||
// If we found an another channel
|
||||
if (iterator != roomDataList.end())
|
||||
{
|
||||
// Increase the connection reference counter
|
||||
(*iterator)->m_connectionRefCount++;
|
||||
// Increase the connection reference counter
|
||||
(*iterator)->m_connectionRefCount++;
|
||||
|
||||
d_ptr = (*iterator);
|
||||
d_ptr = (*iterator);
|
||||
|
||||
// Assign shared room data to this channel index
|
||||
CVoiceChannelVatlibPrivate::getSharedRoomData().insert(this, *iterator);
|
||||
// Assign shared room data to this channel index
|
||||
CVoiceChannelVatlibPrivate::getSharedRoomData().insert(this, *iterator);
|
||||
|
||||
// Since the room is used already, we have to simulate the state changes
|
||||
emit connectionStatusChanged(IVoiceChannel::Disconnected, IVoiceChannel::Connecting);
|
||||
emit connectionStatusChanged(IVoiceChannel::Connecting, IVoiceChannel::Connected);
|
||||
emit d_ptr->userJoinedLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMutexLocker lockVoiceRoom(&d_ptr->m_mutexVoiceRoom);
|
||||
// No one else is using this voice room, so prepare to join
|
||||
d_ptr->m_voiceRoom = voiceRoom;
|
||||
d_ptr->m_roomIndex = d_ptr->allocateRoom();
|
||||
d_ptr->m_roomStatus = IVoiceChannel::Disconnected;
|
||||
// Add ourselfes as listener
|
||||
d_ptr->m_voiceChannels.push_back(this);
|
||||
|
||||
std::lock_guard<TVatlibPointer> locker(d_ptr->m_vatlib);
|
||||
QMutexLocker lockerCallsign(&d_ptr->m_mutexCallSign);
|
||||
bool jr = d_ptr->m_vatlib->JoinRoom(d_ptr->m_roomIndex, d_ptr->m_callsign.toQString().toLatin1().constData(),
|
||||
d_ptr->m_voiceRoom.getVoiceRoomUrl().toLatin1().constData());
|
||||
if (!jr) qWarning() << "Could not join voice room";
|
||||
CVoiceChannelVatlibPrivate::m_sharedRoomData.insert(this, d_ptr);
|
||||
++d_ptr->m_connectionRefCount;
|
||||
}
|
||||
|
||||
// Since the room is used already, we have to simulate the state changes
|
||||
emit connectionStatusChanged(IVoiceChannel::Disconnected, IVoiceChannel::Connecting);
|
||||
emit connectionStatusChanged(IVoiceChannel::Connecting, IVoiceChannel::Connected);
|
||||
}
|
||||
catch (...)
|
||||
else
|
||||
{
|
||||
d_ptr->exceptionDispatcher(Q_FUNC_INFO);
|
||||
// No one else is using this voice room, so prepare to join
|
||||
d_ptr->m_voiceRoom = voiceRoom;
|
||||
Vat_SetRoomInfo(d_ptr->m_voiceChannel.data(), qPrintable(voiceRoom.getHostname()), 3782,
|
||||
qPrintable(voiceRoom.getChannel()),
|
||||
qPrintable(d_ptr->m_callsign.toQString()));
|
||||
|
||||
d_ptr->m_roomStatus = IVoiceChannel::Disconnected;
|
||||
Vat_JoinRoom(d_ptr->m_voiceChannel.data());
|
||||
|
||||
CVoiceChannelVatlibPrivate::m_sharedRoomData.insert(this, d_ptr);
|
||||
++d_ptr->m_connectionRefCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Leave room
|
||||
@@ -337,143 +245,60 @@ namespace BlackCore
|
||||
// If this was the last channel, connected to the room, leave it.
|
||||
if (d_ptr->m_connectionRefCount == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
qDebug() << "Leaving voice room!";
|
||||
if(d_ptr->m_vatlib->IsRoomConnected(d_ptr->m_roomIndex))
|
||||
{
|
||||
std::lock_guard<TVatlibPointer> locker(d_ptr->m_vatlib);
|
||||
d_ptr->m_vatlib->LeaveRoom(d_ptr->m_roomIndex);
|
||||
d_ptr->m_availableRooms.append(d_ptr->m_roomIndex);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
d_ptr->exceptionDispatcher(Q_FUNC_INFO);
|
||||
}
|
||||
qDebug() << "Leaving voice room!";
|
||||
Vat_DisconnectFromRoom(d_ptr->m_voiceChannel.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
d_ptr->m_voiceChannels.removeAll(this);
|
||||
|
||||
// We need to assign a private class
|
||||
// This automatically clears callsign list etc.
|
||||
TVatlibPointer vatlib = d_ptr->m_vatlib;
|
||||
d_ptr.reset(new CVoiceChannelVatlibPrivate(vatlib, this));
|
||||
VatAudioService audioService = d_ptr->m_audioService;
|
||||
VatUDPAudioPort udpPort = d_ptr->m_udpPort;
|
||||
|
||||
d_ptr.reset(new CVoiceChannelVatlibPrivate(audioService, udpPort, this));
|
||||
CVoiceChannelVatlibPrivate::getSharedRoomData().insert(this, d_ptr);
|
||||
|
||||
// Simulate the state change
|
||||
d_ptr->changeConnectionStatus(IVoiceChannel::Disconnecting);
|
||||
d_ptr->changeConnectionStatus(IVoiceChannel::Disconnected);
|
||||
emit connectionStatusChanged(IVoiceChannel::Connected, IVoiceChannel::Disconnecting);
|
||||
emit connectionStatusChanged(IVoiceChannel::Disconnecting, IVoiceChannel::Disconnected);
|
||||
}
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlib::startTransmitting()
|
||||
{
|
||||
d_ptr->startTransmitting();
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlib::stopTransmitting()
|
||||
{
|
||||
d_ptr->stopTransmitting();
|
||||
}
|
||||
|
||||
CCallsignList CVoiceChannelVatlib::getVoiceRoomCallsigns() const
|
||||
{
|
||||
QMutexLocker lockCallsignList(&d_ptr->m_mutexCallsignList);
|
||||
return d_ptr->m_listCallsigns;
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlib::switchAudioOutput(bool enable)
|
||||
{
|
||||
d_ptr->switchAudioOutput(enable);
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlib::setMyAircraftCallsign(const CCallsign &callsign)
|
||||
{
|
||||
QMutexLocker lockerCallsign(&d_ptr->m_mutexCallSign);
|
||||
d_ptr->m_callsign = callsign;
|
||||
}
|
||||
|
||||
BlackMisc::Audio::CVoiceRoom CVoiceChannelVatlib::getVoiceRoom() const
|
||||
{
|
||||
QMutexLocker lockVoiceRoom(&d_ptr->m_mutexVoiceRoom);
|
||||
return d_ptr->m_voiceRoom;
|
||||
}
|
||||
|
||||
qint32 CVoiceChannelVatlib::getRoomIndex() const
|
||||
{
|
||||
return d_ptr->m_roomIndex;
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlib::updateRoomStatus(Cvatlib_Voice_Simple::roomStatusUpdate roomStatus)
|
||||
{
|
||||
switch (roomStatus)
|
||||
{
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinSuccess:
|
||||
{
|
||||
QMutexLocker lockVoiceRoom(&d_ptr->m_mutexVoiceRoom);
|
||||
d_ptr->m_voiceRoom.setConnected(true);
|
||||
d_ptr->changeConnectionStatus(IVoiceChannel::Connected);
|
||||
bool isOutputEnabled = d_ptr->m_outputEnabled;
|
||||
switchAudioOutput(isOutputEnabled);
|
||||
emit d_ptr->userJoinedLeft();
|
||||
break;
|
||||
}
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_JoinFail:
|
||||
{
|
||||
QMutexLocker lockVoiceRoom(&d_ptr->m_mutexVoiceRoom);
|
||||
d_ptr->m_voiceRoom.setConnected(false);
|
||||
d_ptr->changeConnectionStatus(IVoiceChannel::ConnectingFailed);
|
||||
break;
|
||||
}
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_UnexpectedDisconnectOrKicked:
|
||||
d_ptr->m_voiceRoom.setConnected(false);
|
||||
d_ptr->changeConnectionStatus(IVoiceChannel::DisconnectedError);
|
||||
break;
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_LeaveComplete:
|
||||
{
|
||||
// Instead of clearing and resetting all internals, we just assign a new default room data
|
||||
// The former one will be deallocated automatically.
|
||||
TVatlibPointer vatlib = d_ptr->m_vatlib;
|
||||
d_ptr.reset(new CVoiceChannelVatlibPrivate(vatlib, this));
|
||||
CVoiceChannelVatlibPrivate::getSharedRoomData().insert(this, d_ptr);
|
||||
d_ptr->changeConnectionStatus(IVoiceChannel::Disconnected);
|
||||
break;
|
||||
}
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_UserJoinsLeaves:
|
||||
// FIXME: We cannot call GetRoomUserList because vatlib is not reentrent safe.
|
||||
emit d_ptr->userJoinedLeft();
|
||||
break;
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_AudioStarted:
|
||||
break;
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_AudioStopped:
|
||||
break;
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_RoomAudioStarted:
|
||||
emit audioStarted();
|
||||
break;
|
||||
case Cvatlib_Voice_Simple::roomStatusUpdate_RoomAudioStopped:
|
||||
emit audioStopped();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CVoiceChannelVatlib::isMuted() const
|
||||
{
|
||||
return !d_ptr->m_outputEnabled;
|
||||
}
|
||||
|
||||
void CVoiceChannelVatlib::setVolume(quint32 volume)
|
||||
void CVoiceChannelVatlib::setVolume(int volume)
|
||||
{
|
||||
d_ptr->m_volume.store(volume);
|
||||
Q_ASSERT_X(d_ptr->m_vatlib->IsValid() && d_ptr->m_vatlib->IsSetup(), "CVoiceChannelVatlibPrivate", "Cvatlib_Voice_Simple invalid or not setup!");
|
||||
Q_ASSERT_X(d_ptr->m_vatlib->IsRoomValid(d_ptr->m_roomIndex.load()), "CVoiceChannelVatlibPrivate", "Room index out of bounds!");
|
||||
|
||||
d_ptr->m_vatlib->SetOutputVolume(d_ptr->m_roomIndex.load(), volume);
|
||||
d_ptr->setRoomOutputVolume(volume);
|
||||
}
|
||||
|
||||
quint32 CVoiceChannelVatlib::getVolume() const
|
||||
int CVoiceChannelVatlib::getVolume() const
|
||||
{
|
||||
return d_ptr->m_volume.load();
|
||||
// FIXME
|
||||
return 100;
|
||||
}
|
||||
|
||||
VatVoiceChannel CVoiceChannelVatlib::getVoiceChannel() const
|
||||
{
|
||||
return d_ptr->m_voiceChannel.data();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace BlackCore
|
||||
public:
|
||||
|
||||
//! Default constructor
|
||||
CVoiceChannelVatlib(TVatlibPointer vatlib, QObject *parent = nullptr);
|
||||
CVoiceChannelVatlib(VatAudioService audioService, VatUDPAudioPort udpPort, QObject *parent = nullptr);
|
||||
|
||||
//! Destructor
|
||||
virtual ~CVoiceChannelVatlib();
|
||||
@@ -43,38 +43,26 @@ namespace BlackCore
|
||||
//! \copydoc IVoiceChannel::leaveVoiceRoom
|
||||
virtual void leaveVoiceRoom() override;
|
||||
|
||||
//! \copydoc IVoiceChannel::startTransmitting
|
||||
virtual void startTransmitting() override;
|
||||
|
||||
//! \copydoc IVoiceChannel::stopTransmitting
|
||||
virtual void stopTransmitting() override;
|
||||
|
||||
//! \copydoc IVoiceChannel::getVoiceRoomCallsigns
|
||||
virtual BlackMisc::Aviation::CCallsignList getVoiceRoomCallsigns() const override;
|
||||
|
||||
//! \copydoc IVoiceChannel::switchAudioOutput
|
||||
virtual void switchAudioOutput(bool enable) override;
|
||||
|
||||
//! \copydoc IVoiceChannel::setMyAircraftCallsign
|
||||
virtual void setMyAircraftCallsign(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||
|
||||
//! \copydoc IVoiceChannel::getVoiceRoom
|
||||
virtual BlackMisc::Audio::CVoiceRoom getVoiceRoom() const override;
|
||||
|
||||
//! \copydoc IVoiceChannel::getRoomIndex
|
||||
virtual qint32 getRoomIndex() const override;
|
||||
|
||||
//! \copydoc IVoiceChannel::isMuted
|
||||
virtual bool isMuted() const override;
|
||||
|
||||
//! Set channel volume
|
||||
virtual void setVolume(quint32 volume) override;
|
||||
virtual void setVolume(int volume) override;
|
||||
|
||||
//! Get channel volume
|
||||
virtual quint32 getVolume() const override;
|
||||
virtual int getVolume() const override;
|
||||
|
||||
//! \copydoc IVoiceChannel::updateRoomStatus
|
||||
virtual void updateRoomStatus(Cvatlib_Voice_Simple::roomStatusUpdate roomStatus) override;
|
||||
//! Get vatlib channel pointer
|
||||
VatVoiceChannel getVoiceChannel() const;
|
||||
|
||||
private:
|
||||
QSharedPointer<CVoiceChannelVatlibPrivate> d_ptr;
|
||||
|
||||
@@ -31,67 +31,48 @@ namespace BlackCore
|
||||
|
||||
public:
|
||||
|
||||
struct VatVoiceChannelDeleter
|
||||
{
|
||||
static inline void cleanup(VatProducerConsumer_tag *obj)
|
||||
{
|
||||
if (!obj) Vat_DestroyVoiceChannel(obj);
|
||||
}
|
||||
};
|
||||
|
||||
// Default constructor
|
||||
CVoiceChannelVatlibPrivate(TVatlibPointer vatlib, CVoiceChannelVatlib *parent);
|
||||
CVoiceChannelVatlibPrivate(VatAudioService audioService, VatUDPAudioPort udpPort, CVoiceChannelVatlib *parent);
|
||||
|
||||
// Destructor
|
||||
~CVoiceChannelVatlibPrivate();
|
||||
|
||||
// Enable or disable channel audio output
|
||||
void switchAudioOutput(bool enable);
|
||||
|
||||
// Start transmitting
|
||||
void startTransmitting();
|
||||
|
||||
// Stop transmitting
|
||||
void stopTransmitting();
|
||||
|
||||
// Set room output volume
|
||||
void setRoomOutputVolume(const qint32 volume);
|
||||
void setRoomOutputVolume(int volume);
|
||||
|
||||
// FIXME Move into free function
|
||||
void exceptionDispatcher(const char *caller);
|
||||
void updateRoomStatus(VatVoiceChannel channel, VatConnectionStatus /** oldStatus **/, VatConnectionStatus newStatus);
|
||||
|
||||
// Update connected room users
|
||||
static void updateRoomUsers(Cvatlib_Voice_Simple *obj, const char *name, void *cbVar);
|
||||
BlackMisc::Aviation::CCallsign extractCallsign(const QString &name);
|
||||
|
||||
public slots:
|
||||
static void processUserJoined(VatVoiceChannel channel, int id, const char *name, void *cbVar);
|
||||
static void processUserLeft(VatVoiceChannel channel, int id, const char *name, void *cbVar);
|
||||
static void processTransmissionChange(VatVoiceChannel channel, VatVoiceTransmissionStatus status, void *cbVar);
|
||||
|
||||
// Process user joined/left signals
|
||||
void processUserJoinedLeft();
|
||||
|
||||
signals:
|
||||
|
||||
// Signal when user has joined or left
|
||||
void userJoinedLeft();
|
||||
|
||||
public:
|
||||
|
||||
// Add a callsign temporarily. This is used for the getUserList callback
|
||||
void addTemporaryCallsignForRoom(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
static void onRoomStatusUpdate(VatVoiceChannel channel, VatConnectionStatus oldStatus, VatConnectionStatus newStatus, void *cbVar);
|
||||
|
||||
// Get shared room data for this channel
|
||||
static QHash<CVoiceChannelVatlib * const, QSharedPointer<CVoiceChannelVatlibPrivate>> &getSharedRoomData();
|
||||
|
||||
TVatlibPointer m_vatlib; // Shared pointer to vatlib object
|
||||
BlackMisc::Aviation::CCallsign m_callsign; // Own callsign
|
||||
std::atomic<qint32> m_roomIndex; // Room index
|
||||
BlackMisc::Audio::CVoiceRoom m_voiceRoom; // Voice Room
|
||||
std::atomic<qint32> m_volume; // Room volume
|
||||
std::atomic<quint16> m_connectionRefCount; // Connection reference couting
|
||||
std::atomic<bool> m_outputEnabled; // Is room output enabled?
|
||||
BlackMisc::Aviation::CCallsignList m_listCallsigns; // Callsigns connected to room
|
||||
std::atomic<IVoiceChannel::ConnectionStatus> m_roomStatus; // Room connection status
|
||||
QList<CVoiceChannelVatlib *> m_voiceChannels;
|
||||
|
||||
// Mutexes
|
||||
QMutex m_mutexSharedRoomData;
|
||||
QMutex m_mutexCallSign;
|
||||
QMutex m_mutexVoiceRoom;
|
||||
QMutex m_mutexCallsignList;
|
||||
VatAudioService m_audioService;
|
||||
VatUDPAudioPort m_udpPort;
|
||||
QScopedPointer<VatProducerConsumer_tag, VatVoiceChannelDeleter> m_voiceChannel;
|
||||
|
||||
BlackMisc::Aviation::CCallsignList m_temporaryVoiceRoomCallsigns; // temp. storage of voice rooms during update
|
||||
|
||||
static QList<qint32> m_availableRooms; // Static list of not used room indexes
|
||||
static QHash<CVoiceChannelVatlib * const, QSharedPointer<CVoiceChannelVatlibPrivate>> m_sharedRoomData;
|
||||
const static qint32 InvalidRoomIndex = -1; // Invalid room index
|
||||
|
||||
@@ -100,11 +81,9 @@ namespace BlackCore
|
||||
|
||||
private:
|
||||
|
||||
// Change room connection status
|
||||
void changeConnectionStatus(IVoiceChannel::ConnectionStatus newStatus);
|
||||
|
||||
// Allocate a not used room identified by its index
|
||||
qint32 allocateRoom();
|
||||
void userJoinedVoiceRoom(VatVoiceChannel, int id, const char *name);
|
||||
void userLeftVoiceRoom(VatVoiceChannel, int id, const char *name);
|
||||
void transmissionChanged(VatVoiceChannel, VatVoiceTransmissionStatus status);
|
||||
};
|
||||
//! \endcond
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ namespace BlackCore
|
||||
*/
|
||||
CVoiceVatlib::~CVoiceVatlib() {}
|
||||
|
||||
std::unique_ptr<IVoiceChannel> CVoiceVatlib::createVoiceChannel()
|
||||
{
|
||||
return make_unique<CVoiceChannelVatlib>(m_audioService.data(), m_udpPort.data(), this);
|
||||
}
|
||||
|
||||
std::unique_ptr<IAudioInputDevice> CVoiceVatlib::createInputDevice()
|
||||
{
|
||||
return make_unique<CAudioInputDeviceVatlib>(m_audioService.data(), this);
|
||||
@@ -48,38 +53,6 @@ namespace BlackCore
|
||||
return make_unique<CAudioOutputDeviceVatlib>(m_audioService.data(), this);
|
||||
}
|
||||
|
||||
IVoiceChannel *CVoiceVatlib::getVoiceChannel(qint32 channelIndex) const
|
||||
{
|
||||
IVoiceChannel *channel = m_hashChannelIndex.value(channelIndex, nullptr);
|
||||
Q_ASSERT(channel);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle PTT
|
||||
*/
|
||||
void CVoiceVatlib::handlePushToTalk(bool value)
|
||||
{
|
||||
qDebug() << "PTT";
|
||||
if (!this->m_vatlib) return;
|
||||
|
||||
if (value) qDebug() << "Start transmitting...";
|
||||
else qDebug() << "Stop transmitting...";
|
||||
|
||||
// FIXME: Set only once channel to active for transmitting
|
||||
if (value)
|
||||
{
|
||||
getVoiceChannel(0)->startTransmitting();
|
||||
getVoiceChannel(1)->startTransmitting();
|
||||
}
|
||||
else
|
||||
{
|
||||
getVoiceChannel(0)->stopTransmitting();
|
||||
getVoiceChannel(1)->stopTransmitting();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process voice handling
|
||||
*/
|
||||
@@ -89,33 +62,6 @@ namespace BlackCore
|
||||
Vat_ExecuteTasks(m_audioService.data());
|
||||
}
|
||||
|
||||
/*
|
||||
* Room status update
|
||||
*/
|
||||
void CVoiceVatlib::onRoomStatusUpdate(Cvatlib_Voice_Simple *obj, Cvatlib_Voice_Simple::roomStatusUpdate upd, qint32 roomIndex, void *cbVar)
|
||||
{
|
||||
Q_UNUSED(obj)
|
||||
CVoiceVatlib *vatlibRoom = cbvar_cast_voice(cbVar);
|
||||
vatlibRoom->onRoomStatusUpdate(roomIndex, upd);
|
||||
}
|
||||
|
||||
void CVoiceVatlib::onRoomStatusUpdate(qint32 roomIndex, Cvatlib_Voice_Simple::roomStatusUpdate roomStatus)
|
||||
{
|
||||
QList<IVoiceChannel *> voiceChannels = m_hashChannelIndex.values();
|
||||
auto iterator = std::find_if(voiceChannels.begin(), voiceChannels.end(), [&](const IVoiceChannel * voiceChannel)
|
||||
{
|
||||
return voiceChannel->getRoomIndex() == roomIndex;
|
||||
});
|
||||
|
||||
if (iterator == voiceChannels.end())
|
||||
{
|
||||
qWarning() << "Unknown room index";
|
||||
return;
|
||||
}
|
||||
|
||||
(*iterator)->updateRoomStatus(roomStatus);
|
||||
}
|
||||
|
||||
void CVoiceVatlib::voiceErrorHandler(const char *message)
|
||||
{
|
||||
CLogMessage(static_cast<CVoiceVatlib*>(nullptr)).error(message);
|
||||
|
||||
@@ -41,23 +41,18 @@ namespace BlackCore
|
||||
//! \brief Destructor
|
||||
virtual ~CVoiceVatlib();
|
||||
|
||||
//! \copydoc IVoice::createVoiceChannel()
|
||||
virtual std::unique_ptr<IVoiceChannel> createVoiceChannel() override;
|
||||
|
||||
//! \copydoc IVoice::createInputDevice()
|
||||
virtual std::unique_ptr<IAudioInputDevice> createInputDevice() override;
|
||||
|
||||
//! \copydoc IVoice::createOutputDevice()
|
||||
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() override;
|
||||
|
||||
//! \copydoc IVoice::getVoiceChannel
|
||||
virtual IVoiceChannel *getVoiceChannel(qint32 channelIndex) const override;
|
||||
|
||||
//! \copydoc IVoice::enableAudioLoopback
|
||||
virtual void enableAudioLoopback(bool enable = true) override;
|
||||
|
||||
/*!
|
||||
* \brief Starts or stops voice transmission
|
||||
* \param value
|
||||
*/
|
||||
void handlePushToTalk(bool value = false);
|
||||
|
||||
protected: // QObject overrides
|
||||
|
||||
@@ -87,14 +82,8 @@ namespace BlackCore
|
||||
|
||||
static void voiceErrorHandler(const char *message);
|
||||
|
||||
// shimlib callbacks
|
||||
static void onRoomStatusUpdate(Cvatlib_Voice_Simple *obj, Cvatlib_Voice_Simple::roomStatusUpdate upd, qint32 roomIndex, void *cbVar);
|
||||
|
||||
void onRoomStatusUpdate(qint32 roomIndex, Cvatlib_Voice_Simple::roomStatusUpdate roomStatus);
|
||||
|
||||
QScopedPointer<VatAudioService_tag, VatAudioServiceDeleter> m_audioService;
|
||||
QScopedPointer<VatUDPAudioPort_tag, VatUDPAudioPortDeleter> m_udpPort;
|
||||
QHash<qint32, IVoiceChannel *> m_hashChannelIndex;
|
||||
bool m_isAudioLoopbackEnabled; /*!< A flag whether audio loopback is enabled or not */
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user