diff --git a/src/blackcore/voice_vatlib.cpp b/src/blackcore/voice_vatlib.cpp index ad7ec9b23..f59010d46 100644 --- a/src/blackcore/voice_vatlib.cpp +++ b/src/blackcore/voice_vatlib.cpp @@ -18,12 +18,11 @@ namespace BlackCore CVoiceVatlib::CVoiceVatlib(QObject *parent) : IVoice(parent), m_voice(Cvatlib_Voice_Simple::Create()), - m_aircraftCallsign(), m_voiceRooms(), m_devices(), m_keyboardPtt(new CKeyboard(nullptr)), m_pushToTalk(false), m_inputSquelch(-1), m_micTestResult(Cvatlib_Voice_Simple::agc_Ok), - m_queryUserRoomIndex(-1) + m_temporaryUserRoomIndex(CVoiceVatlib::InvalidRoomIndex) { try { @@ -32,7 +31,7 @@ namespace BlackCore m_voice->GetOutputDevices(onOutputHardwareDeviceReceived, this); // TODO: read audio device settings here and init with the same devices - // If not settings are there or it is the first run, use the default one + // If not, settings are there or it is the first run, use the default one // TODO: KB, setting this kind of default device results in an error // setInputDevice(defaultAudioInputDevice()); // setOutputDevice(defaultAudioOutputDevice()); @@ -42,6 +41,8 @@ namespace BlackCore this->m_voiceRooms.push_back(CVoiceRoom()); // COM1 this->m_voiceRooms.push_back(CVoiceRoom()); // COM2 + this->m_outputEnabled.insert(COM1, true); + this->m_outputEnabled.insert(COM2, true); // do processing this->startTimer(100); @@ -49,7 +50,10 @@ namespace BlackCore // as last thing enable keyboard handling this->m_keyboardPtt.data()->s_voice = this; } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -106,7 +110,10 @@ namespace BlackCore qWarning() << "Input device hit a fatal error"; } } - catch (...) { exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -129,7 +136,10 @@ namespace BlackCore qWarning() << "Input device hit a fatal error"; } } - catch (...) { exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -157,15 +167,19 @@ namespace BlackCore /* * Enable audio */ - void CVoiceVatlib::enableAudio(const ComUnit comUnit) + void CVoiceVatlib::switchAudioOutput(const ComUnit comUnit, bool enable) { Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!"); Q_ASSERT_X(m_voice->IsRoomValid(static_cast(comUnit)), "CVoiceClientVatlib", "Room index out of bounds!"); try { - m_voice->SetOutoutState(static_cast(comUnit), 0, true); + m_voice->SetOutoutState(static_cast(comUnit), 0, enable); + this->m_outputEnabled[comUnit] = enable; + } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } } /* @@ -179,12 +193,18 @@ namespace BlackCore { m_voice->BeginFindSquelch(); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } // Start the timer only if no exception was thrown before QTimer::singleShot(5000, this, SLOT(onEndFindSquelch())); } + /* + * Start microphone test + */ void CVoiceVatlib::runMicTest() { Q_ASSERT_X(m_voice->IsValid() && m_voice->IsSetup(), "CVoiceClientVatlib", "Cvatlib_Voice_Simple invalid or not setup!"); @@ -193,23 +213,34 @@ namespace BlackCore { m_voice->BeginMicTest(); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } // Start the timer only if no exception was thrown before QTimer::singleShot(5000, this, SLOT(onEndMicTest())); } + /* + * Input squelch volume + */ float CVoiceVatlib::inputSquelch() const { return m_inputSquelch; } + /* + * Mic test + */ int32_t CVoiceVatlib::micTestResult() const { return m_micTestResult; } - + /* + * Mic test, result as string + */ QString CVoiceVatlib::micTestResultAsString() const { QString result; @@ -270,7 +301,10 @@ namespace BlackCore QString serverSpec = voiceRoom.getVoiceRoomUrl(); m_voice->JoinRoom(static_cast(comUnit), m_aircraftCallsign.toQString().toLatin1().constData(), serverSpec.toLatin1().constData()); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -290,7 +324,10 @@ namespace BlackCore vr.setConnected(false); this->setVoiceRoomForUnit(comUnit, vr); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -314,7 +351,10 @@ namespace BlackCore { m_voice->SetRoomVolume(static_cast(comUnit), volumne); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -329,7 +369,10 @@ namespace BlackCore { m_voice->SetMicState(static_cast(comUnit), true); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -343,20 +386,23 @@ namespace BlackCore { m_voice->SetMicState(static_cast(comUnit), false); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* * Change room status */ - void CVoiceVatlib::changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd) + void CVoiceVatlib::changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate roomStatus) { CVoiceRoom vr = this->voiceRoomForUnit(comUnit); - switch (upd) + switch (roomStatus) { case Cvatlib_Voice_Simple::roomStatusUpdate_JoinSuccess: - enableAudio(comUnit); + switchAudioOutput(comUnit, this->m_outputEnabled[comUnit]); vr.setConnected(true); this->setVoiceRoomForUnit(comUnit, vr); emit connected(comUnit); @@ -408,7 +454,10 @@ namespace BlackCore this->m_voice->DoProcessing(); this->handlePushToTalk(); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -424,7 +473,10 @@ namespace BlackCore m_inputSquelch = m_voice->GetInputSquelch(); emit squelchTestFinished(); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } void CVoiceVatlib::onEndMicTest() @@ -436,7 +488,10 @@ namespace BlackCore m_micTestResult = m_voice->EndMicTest(); emit micTestFinished(); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); + } } /* @@ -445,53 +500,49 @@ namespace BlackCore void CVoiceVatlib::onUserJoinedLeft(const ComUnit comUnit) { 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!"); + Q_ASSERT_X(m_temporaryUserRoomIndex == CVoiceVatlib::InvalidRoomIndex, "CVoiceClientVatlib::onUserJoinedLeft", "Cannot list users for two rooms in parallel!"); try { // Paranoia... if (!m_voice->IsRoomConnected(static_cast(comUnit))) return; - // Store the room index for the slot. - m_queryUserRoomIndex = static_cast(comUnit); + // Store the room index for the slot (called in static callback) + m_temporaryUserRoomIndex = static_cast(comUnit); + + // Callbacks completed when function is called, after the method is done + // m_voiceRoomCallsignsUpdate is filled with the latest callsigns m_voice->GetRoomUserList(static_cast(comUnit), onRoomUserReceived, this); - m_queryUserRoomIndex = -1; - - QSet temporaryUsers; + m_temporaryUserRoomIndex = CVoiceVatlib::InvalidRoomIndex; // reset + // we have all current users in m_voi foreach(QString callsign, m_voiceRoomCallsigns.value(comUnit)) { - if (m_voiceRoomCallsignsUpdate.contains(callsign)) + if (!m_temporaryVoiceRoomCallsigns.contains(callsign)) { - // The user is still there. - temporaryUsers.insert(callsign); - } - else - { - // He is has probably left + // He is has left emit userLeftRoom(callsign); } } - foreach(QString callsign, m_voiceRoomCallsignsUpdate) + foreach(QString callsign, m_temporaryVoiceRoomCallsigns) { - if (m_voiceRoomCallsigns.value(comUnit).contains(callsign)) + if (!m_voiceRoomCallsigns.value(comUnit).contains(callsign)) { - // User was already there before - temporaryUsers.insert(callsign); - } - else - { - // He joined - temporaryUsers.insert(callsign); + // he joined emit userJoinedRoom(callsign); } } // Finally we update it with our new list - m_voiceRoomCallsignsUpdate.clear(); + this->m_voiceRoomCallsigns[comUnit] = this->m_temporaryVoiceRoomCallsigns; + this->m_temporaryVoiceRoomCallsigns.clear(); + + } + catch (...) + { + this->exceptionDispatcher(Q_FUNC_INFO); } - catch (...) { this->exceptionDispatcher(Q_FUNC_INFO); } } /********************************** * * * * * * * * * * * * * * * * * * * ************************************/ @@ -530,7 +581,7 @@ namespace BlackCore // add user CVoiceVatlib *voiceClientVatlib = cbvar_cast_voice(cbVar); - ComUnit comUnit = static_cast(voiceClientVatlib->queryUserRoomIndex()); + ComUnit comUnit = static_cast(voiceClientVatlib->temporaryUserRoomIndex()); // add user voiceClientVatlib->addUserInRoom(comUnit, callsign); @@ -577,7 +628,7 @@ namespace BlackCore */ void CVoiceVatlib::addUserInRoom(const ComUnit /** comUnit **/, const QString &callsign) { - m_voiceRoomCallsignsUpdate.insert(callsign); + m_temporaryVoiceRoomCallsigns.insert(callsign); } /* diff --git a/src/blackcore/voice_vatlib.h b/src/blackcore/voice_vatlib.h index dc6625f83..d5e99324d 100644 --- a/src/blackcore/voice_vatlib.h +++ b/src/blackcore/voice_vatlib.h @@ -130,6 +130,23 @@ namespace BlackCore return this->m_voiceRoomCallsigns[comUnit]; } + /*! + * \brief Switch audio output + * \param comUnit + * \param enable + */ + virtual void switchAudioOutput(const ComUnit comUnit, bool enable); + + /*! + * \brief Muted? + */ + virtual bool isMuted() const + { + if (this->m_outputEnabled.isEmpty()) return false; + bool enabled = this->m_outputEnabled[COM1] || this->m_outputEnabled[COM2]; + return !enabled; + } + /************************************************ * NON API METHODS: * The following methods are not part of the @@ -137,9 +154,21 @@ namespace BlackCore * workflow. * *********************************************/ - int32_t queryUserRoomIndex() const {return m_queryUserRoomIndex;} + /*! + * \brief Voice room index + * \return + */ + int32_t temporaryUserRoomIndex() const + { + return m_temporaryUserRoomIndex; + } - void changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate upd); + /*! + * \brief Room status update, used in callback + * \param comUnit + * \param upd + */ + void changeRoomStatus(ComUnit comUnit, Cvatlib_Voice_Simple::roomStatusUpdate roomStatus); signals: @@ -266,15 +295,15 @@ namespace BlackCore bool m_pushToTalk; /*!< flag, PTT pressed */ float m_inputSquelch; Cvatlib_Voice_Simple::agc m_micTestResult; + QMap < ComUnit, QSet > m_voiceRoomCallsigns; /*!< voice room callsigns */ + QSet m_temporaryVoiceRoomCallsigns; /*!< temp. storage of voice rooms during update */ + QMap m_outputEnabled; /*!< output enabled, basically a mute flag */ - typedef QMap> TMapRoomCallsigns; - TMapRoomCallsigns m_voiceRoomCallsigns; - QSet m_voiceRoomCallsignsUpdate; - - // Need to keep the roomIndex because GetRoomUserList does not specifiy it + // Need to keep the roomIndex? // KB: I would remove this approach, it is potentially unsafe // Maybe just use 2 "wrapper" callbacks, which then set explicitly the voice room (it is only 2 methods) - int32_t m_queryUserRoomIndex; + int32_t m_temporaryUserRoomIndex; /*!< temp. storage of voice room, in order to retrieve it in static callback */ + const static int32_t InvalidRoomIndex = -1; /*! marks invalid room */ };