mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-23 07:15:35 +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_outputDevice = m_voice->createOutputDevice();
|
||||
|
||||
m_voice->connectChannelOutputDevice(m_channelCom1.get(), m_outputDevice.get());
|
||||
|
||||
using namespace BlackCore;
|
||||
connect(m_channelCom1.get(), &IVoiceChannel::connectionStatusChanged, this, &Client::connectionStatusChanged);
|
||||
connect(m_channelCom1.get(), &IVoiceChannel::audioStarted, this, &Client::audioStartedStream);
|
||||
@@ -163,15 +165,14 @@ void Client::listCallsignsCmd(QTextStream &args)
|
||||
void Client::enableLoopbackCmd(QTextStream &/*args*/)
|
||||
{
|
||||
std::cout << "Enabling audio loopback." << std::endl;
|
||||
m_voice->enableAudioLoopback(true);
|
||||
m_voice->enableAudioLoopback(m_inputDevice.get(), m_outputDevice.get());
|
||||
printLinePrefix();
|
||||
}
|
||||
|
||||
void Client::disableLoopbackCmd(QTextStream &/*args*/)
|
||||
{
|
||||
std::cout << "Disabling audio loopback." << std::endl;
|
||||
m_voice->enableAudioLoopback(false);
|
||||
printLinePrefix();
|
||||
m_voice->enableAudioLoopback(m_inputDevice.get(), nullptr);
|
||||
printLinePrefix();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace BlackCore
|
||||
|
||||
// 2. Register PTT hotkey function
|
||||
m_inputManager = CInputManager::getInstance();
|
||||
m_handlePtt = m_inputManager->registerHotkeyFunc(CHotkeyFunction::Ptt(), this, &CContextAudio::ps_setVoiceTransmission);
|
||||
|
||||
m_channelCom1 = m_voice->createVoiceChannel();
|
||||
m_channelCom1->setMyAircraftCallsign(getIContextOwnAircraft()->getOwnAircraft().getCallsign());
|
||||
@@ -50,6 +51,9 @@ namespace BlackCore
|
||||
m_voiceInputDevice = m_voice->createInputDevice();
|
||||
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
|
||||
QTimer::singleShot(10 * 1000, this, SLOT(ps_initNotificationSounds()));
|
||||
}
|
||||
@@ -401,7 +405,10 @@ namespace BlackCore
|
||||
{
|
||||
Q_ASSERT(this->m_voice);
|
||||
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)
|
||||
@@ -452,6 +459,13 @@ namespace BlackCore
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -157,6 +157,8 @@ namespace BlackCore
|
||||
//! Init notification sounds
|
||||
void ps_initNotificationSounds();
|
||||
|
||||
void ps_setVoiceTransmission(bool enable);
|
||||
|
||||
private:
|
||||
const int MinUnmuteVolume = 20; //!< minimum volume when unmuted
|
||||
const int VoiceRoomEnabledVolume = 95; //!< voice room volume when enabled
|
||||
|
||||
@@ -47,11 +47,18 @@ namespace BlackCore
|
||||
//! Create output device object
|
||||
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
|
||||
* \param enable (default true)
|
||||
* Connect input device to voice channel to start/stop voice transmission
|
||||
* \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
|
||||
|
||||
@@ -53,6 +53,67 @@ namespace BlackCore
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -50,9 +50,14 @@ namespace BlackCore
|
||||
//! \copydoc IVoice::createOutputDevice()
|
||||
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() override;
|
||||
|
||||
//! \copydoc IVoice::enableAudioLoopback
|
||||
virtual void enableAudioLoopback(bool enable = true) override;
|
||||
//! \copydoc IVoice::connectChannelOutputDevice()
|
||||
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
|
||||
|
||||
@@ -84,8 +89,6 @@ namespace BlackCore
|
||||
|
||||
QScopedPointer<VatAudioService_tag, VatAudioServiceDeleter> m_audioService;
|
||||
QScopedPointer<VatUDPAudioPort_tag, VatUDPAudioPortDeleter> m_udpPort;
|
||||
bool m_isAudioLoopbackEnabled; /*!< A flag whether audio loopback is enabled or not */
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user