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:
Roland Winklmeier
2014-12-25 18:30:13 +01:00
parent 3126067d31
commit b6869affd5
6 changed files with 99 additions and 11 deletions

View File

@@ -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();
} }

View File

@@ -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
*/ */

View File

@@ -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

View File

@@ -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

View File

@@ -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
*/ */

View File

@@ -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