mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-24 09:54:16 +08:00
refs #320 Voicechannel and audio device connections
- Methods to connect voice channel and audio devices - Methods to connect audio devices with each other (loopback)
This commit is contained in:
@@ -23,6 +23,8 @@ Client::Client(QObject *parent) :
|
|||||||
m_inputDevice = m_voice->createInputDevice();
|
m_inputDevice = m_voice->createInputDevice();
|
||||||
m_outputDevice = m_voice->createOutputDevice();
|
m_outputDevice = m_voice->createOutputDevice();
|
||||||
|
|
||||||
|
m_voice->connectChannelOutputDevice(m_channelCom1.get(), m_outputDevice.get());
|
||||||
|
|
||||||
using namespace BlackCore;
|
using namespace BlackCore;
|
||||||
connect(m_channelCom1.get(), &IVoiceChannel::connectionStatusChanged, this, &Client::connectionStatusChanged);
|
connect(m_channelCom1.get(), &IVoiceChannel::connectionStatusChanged, this, &Client::connectionStatusChanged);
|
||||||
connect(m_channelCom1.get(), &IVoiceChannel::audioStarted, this, &Client::audioStartedStream);
|
connect(m_channelCom1.get(), &IVoiceChannel::audioStarted, this, &Client::audioStartedStream);
|
||||||
@@ -163,15 +165,14 @@ void Client::listCallsignsCmd(QTextStream &args)
|
|||||||
void Client::enableLoopbackCmd(QTextStream &/*args*/)
|
void Client::enableLoopbackCmd(QTextStream &/*args*/)
|
||||||
{
|
{
|
||||||
std::cout << "Enabling audio loopback." << std::endl;
|
std::cout << "Enabling audio loopback." << std::endl;
|
||||||
m_voice->enableAudioLoopback(true);
|
m_voice->enableAudioLoopback(m_inputDevice.get(), m_outputDevice.get());
|
||||||
printLinePrefix();
|
printLinePrefix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::disableLoopbackCmd(QTextStream &/*args*/)
|
void Client::disableLoopbackCmd(QTextStream &/*args*/)
|
||||||
{
|
{
|
||||||
std::cout << "Disabling audio loopback." << std::endl;
|
std::cout << "Disabling audio loopback." << std::endl;
|
||||||
m_voice->enableAudioLoopback(false);
|
m_voice->enableAudioLoopback(m_inputDevice.get(), nullptr);
|
||||||
printLinePrefix();
|
|
||||||
printLinePrefix();
|
printLinePrefix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace BlackCore
|
|||||||
|
|
||||||
// 2. Register PTT hotkey function
|
// 2. Register PTT hotkey function
|
||||||
m_inputManager = CInputManager::getInstance();
|
m_inputManager = CInputManager::getInstance();
|
||||||
|
m_handlePtt = m_inputManager->registerHotkeyFunc(CHotkeyFunction::Ptt(), this, &CContextAudio::ps_setVoiceTransmission);
|
||||||
|
|
||||||
m_channelCom1 = m_voice->createVoiceChannel();
|
m_channelCom1 = m_voice->createVoiceChannel();
|
||||||
m_channelCom1->setMyAircraftCallsign(getIContextOwnAircraft()->getOwnAircraft().getCallsign());
|
m_channelCom1->setMyAircraftCallsign(getIContextOwnAircraft()->getOwnAircraft().getCallsign());
|
||||||
@@ -50,6 +51,9 @@ namespace BlackCore
|
|||||||
m_voiceInputDevice = m_voice->createInputDevice();
|
m_voiceInputDevice = m_voice->createInputDevice();
|
||||||
m_voiceOutputDevice = m_voice->createOutputDevice();
|
m_voiceOutputDevice = m_voice->createOutputDevice();
|
||||||
|
|
||||||
|
m_voice->connectChannelOutputDevice(m_channelCom1.get(), m_voiceOutputDevice.get());
|
||||||
|
m_voice->connectChannelOutputDevice(m_channelCom2.get(), m_voiceOutputDevice.get());
|
||||||
|
|
||||||
// 4. load sounds (init), not possible in own thread
|
// 4. load sounds (init), not possible in own thread
|
||||||
QTimer::singleShot(10 * 1000, this, SLOT(ps_initNotificationSounds()));
|
QTimer::singleShot(10 * 1000, this, SLOT(ps_initNotificationSounds()));
|
||||||
}
|
}
|
||||||
@@ -401,7 +405,10 @@ namespace BlackCore
|
|||||||
{
|
{
|
||||||
Q_ASSERT(this->m_voice);
|
Q_ASSERT(this->m_voice);
|
||||||
CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
|
CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
|
||||||
m_voice->enableAudioLoopback(enable);
|
if (enable)
|
||||||
|
m_voice->enableAudioLoopback(m_voiceInputDevice.get(), m_voiceOutputDevice.get());
|
||||||
|
else
|
||||||
|
m_voice->enableAudioLoopback(m_voiceInputDevice.get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CContextAudio::parseCommandLine(const QString &commandLine)
|
bool CContextAudio::parseCommandLine(const QString &commandLine)
|
||||||
@@ -452,6 +459,13 @@ namespace BlackCore
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CContextAudio::ps_setVoiceTransmission(bool enable)
|
||||||
|
{
|
||||||
|
// FIXME: Use the 'active' channel instead of hardcoded COM1
|
||||||
|
if (enable) m_voice->connectChannelInputDevice(m_voiceInputDevice.get(), m_channelCom1.get());
|
||||||
|
else m_voice->connectChannelInputDevice(nullptr, m_channelCom1.get());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connection status changed
|
* Connection status changed
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ namespace BlackCore
|
|||||||
//! Init notification sounds
|
//! Init notification sounds
|
||||||
void ps_initNotificationSounds();
|
void ps_initNotificationSounds();
|
||||||
|
|
||||||
|
void ps_setVoiceTransmission(bool enable);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int MinUnmuteVolume = 20; //!< minimum volume when unmuted
|
const int MinUnmuteVolume = 20; //!< minimum volume when unmuted
|
||||||
const int VoiceRoomEnabledVolume = 95; //!< voice room volume when enabled
|
const int VoiceRoomEnabledVolume = 95; //!< voice room volume when enabled
|
||||||
|
|||||||
@@ -47,11 +47,18 @@ namespace BlackCore
|
|||||||
//! Create output device object
|
//! Create output device object
|
||||||
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() = 0;
|
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() = 0;
|
||||||
|
|
||||||
|
//! Connect voice channel to an audio output device
|
||||||
|
virtual void connectChannelOutputDevice(IVoiceChannel *channel, IAudioOutputDevice *device) = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Enable audio loopback to route recorded voice from microphone to speakers
|
* Connect input device to voice channel to start/stop voice transmission
|
||||||
* \param enable (default true)
|
* \param device Audio input device, e.g. a microphone. Pass nullptr to stop transmission
|
||||||
|
* \param channel Voice channel audio should be transmitted to
|
||||||
*/
|
*/
|
||||||
virtual void enableAudioLoopback(bool enable = true) = 0;
|
virtual void connectChannelInputDevice(IAudioInputDevice *device, IVoiceChannel *channel) = 0;
|
||||||
|
|
||||||
|
//! Connect audio input to an audio output to hear your own voice
|
||||||
|
virtual void enableAudioLoopback(IAudioInputDevice *input, IAudioOutputDevice *output) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BlackCore
|
} // namespace BlackCore
|
||||||
|
|||||||
@@ -53,6 +53,67 @@ namespace BlackCore
|
|||||||
return make_unique<CAudioOutputDeviceVatlib>(m_audioService.data(), this);
|
return make_unique<CAudioOutputDeviceVatlib>(m_audioService.data(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME:
|
||||||
|
Can the following methods be more general somehow?
|
||||||
|
E.g.:
|
||||||
|
template <typename Input, typename Output>
|
||||||
|
connectVoice(Input input, Output output)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void CVoiceVatlib::connectChannelOutputDevice(IVoiceChannel *channel, IAudioOutputDevice *device)
|
||||||
|
{
|
||||||
|
auto voiceChannelVatlib = qobject_cast<CVoiceChannelVatlib*>(channel);
|
||||||
|
Q_ASSERT_X(voiceChannelVatlib, "CVoiceVatlib::connectChannelOutputDevice", "No valid CVoiceChannelVatlib pointer.");
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
Vat_VoiceConnect(voiceChannelVatlib->getVoiceChannel(), 0, nullptr, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto audioDeviceVatlib = qobject_cast<CAudioOutputDeviceVatlib*>(device);
|
||||||
|
Q_ASSERT_X(audioDeviceVatlib, "CVoiceVatlib::connectOutputDevice", "No valid CAudioOutputDeviceVatlib pointer.");
|
||||||
|
|
||||||
|
Vat_VoiceConnect(voiceChannelVatlib->getVoiceChannel(), 0, audioDeviceVatlib->getVatLocalOutputCodec(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVoiceVatlib::connectChannelInputDevice(IAudioInputDevice *device, IVoiceChannel *channel)
|
||||||
|
{
|
||||||
|
auto voiceChannelVatlib = qobject_cast<CVoiceChannelVatlib*>(channel);
|
||||||
|
Q_ASSERT_X(voiceChannelVatlib, "CVoiceVatlib::connectChannelInputDevice", "No valid CVoiceChannelVatlib pointer.");
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
Vat_VoiceConnect(voiceChannelVatlib->getVoiceChannel(), 0, nullptr, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto audioDeviceVatlib = qobject_cast<CAudioInputDeviceVatlib*>(device);
|
||||||
|
Q_ASSERT_X(audioDeviceVatlib, "CVoiceVatlib::connectChannelInputDevice", "No valid CAudioInputDeviceVatlib pointer.");
|
||||||
|
|
||||||
|
Vat_VoiceConnect(audioDeviceVatlib->getVatLocalInputCodec(), 0, voiceChannelVatlib->getVoiceChannel(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVoiceVatlib::enableAudioLoopback(IAudioInputDevice *input, IAudioOutputDevice *output)
|
||||||
|
{
|
||||||
|
auto vatlibInput = qobject_cast<CAudioInputDeviceVatlib*>(input);
|
||||||
|
Q_ASSERT_X(vatlibInput, "CVoiceVatlib::enableAudioLoopback", "No valid CAudioInputDeviceVatlib pointer.");
|
||||||
|
|
||||||
|
if (!output)
|
||||||
|
{
|
||||||
|
Vat_VoiceConnect(vatlibInput->getVatLocalInputCodec(), 0, nullptr, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto vatlibOutput = qobject_cast<CAudioOutputDeviceVatlib*>(output);
|
||||||
|
Q_ASSERT_X(vatlibOutput, "CVoiceVatlib::enableAudioLoopback", "No valid CAudioOutputDeviceVatlib pointer.");
|
||||||
|
|
||||||
|
Vat_VoiceConnect(vatlibInput->getVatLocalInputCodec(), 0, vatlibOutput->getVatLocalOutputCodec(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process voice handling
|
* Process voice handling
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -50,9 +50,14 @@ namespace BlackCore
|
|||||||
//! \copydoc IVoice::createOutputDevice()
|
//! \copydoc IVoice::createOutputDevice()
|
||||||
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() override;
|
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() override;
|
||||||
|
|
||||||
//! \copydoc IVoice::enableAudioLoopback
|
//! \copydoc IVoice::connectChannelOutputDevice()
|
||||||
virtual void enableAudioLoopback(bool enable = true) override;
|
virtual void connectChannelOutputDevice(IVoiceChannel *channel, IAudioOutputDevice *device) override;
|
||||||
|
|
||||||
|
//! \copydoc IVoice::connectChannelInputDevice()
|
||||||
|
virtual void connectChannelInputDevice(IAudioInputDevice *device, IVoiceChannel *channel) override;
|
||||||
|
|
||||||
|
//! \copydoc IVoice::enableAudioLoopback()
|
||||||
|
virtual void enableAudioLoopback(IAudioInputDevice *input, IAudioOutputDevice *output) override;
|
||||||
|
|
||||||
protected: // QObject overrides
|
protected: // QObject overrides
|
||||||
|
|
||||||
@@ -84,8 +89,6 @@ namespace BlackCore
|
|||||||
|
|
||||||
QScopedPointer<VatAudioService_tag, VatAudioServiceDeleter> m_audioService;
|
QScopedPointer<VatAudioService_tag, VatAudioServiceDeleter> m_audioService;
|
||||||
QScopedPointer<VatUDPAudioPort_tag, VatUDPAudioPortDeleter> m_udpPort;
|
QScopedPointer<VatUDPAudioPort_tag, VatUDPAudioPortDeleter> m_udpPort;
|
||||||
bool m_isAudioLoopbackEnabled; /*!< A flag whether audio loopback is enabled or not */
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user