diff --git a/src/blackcore/context_audio.h b/src/blackcore/context_audio.h index febb8cfde..55c73e266 100644 --- a/src/blackcore/context_audio.h +++ b/src/blackcore/context_audio.h @@ -83,11 +83,17 @@ namespace BlackCore // KB: Is see some potential changes here, which we should do when we have the new 2.0 vatlib // 1. volume integrated in voice room? // 2. Value object for volumes CVolume / CVolumeList? - void changedAudioVolumes(QList volumes); + void changedAudioVolumes(qint32 com1Volume, qint32 com2Volume); //! Mute changed void changedMute(bool muted); + //! Changed audio devices (e.g. device enabled/disable) + void changedAudioDevices(const BlackMisc::Audio::CAudioDeviceList &devices); + + //! Changed slection of audio devices + void changedSelectedAudioDevices(const BlackMisc::Audio::CAudioDeviceList &devices); + public slots: //! Get voice rooms for COM1, COM2: virtual BlackMisc::Audio::CVoiceRoomList getComVoiceRoomsWithAudioStatus() const = 0; @@ -182,6 +188,9 @@ namespace BlackCore //! Enable audio loopback virtual void enableAudioLoopback(bool enable = true) = 0; + + //! Command line was entered + virtual bool parseCommandLine(const QString &commandLine) = 0; }; } diff --git a/src/blackcore/context_audio_impl.cpp b/src/blackcore/context_audio_impl.cpp index b99f6e1f9..50e3a1d92 100644 --- a/src/blackcore/context_audio_impl.cpp +++ b/src/blackcore/context_audio_impl.cpp @@ -14,6 +14,7 @@ #include "blackmisc/voiceroomlist.h" #include "blackmisc/hotkeyfunction.h" #include "blackmisc/logmessage.h" +#include "blackmisc/simplecommandparser.h" #include @@ -154,13 +155,27 @@ namespace BlackCore Q_ASSERT(this->m_voice); Q_ASSERT(audioDevice.getType() != CAudioDevice::Unknown); CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << audioDevice; + bool changed = false; if (audioDevice.getType() == CAudioDevice::InputDevice) { - this->m_voice->setInputDevice(audioDevice); + if (this->m_voice->getCurrentInputDevice() != audioDevice) + { + this->m_voice->setInputDevice(audioDevice); + changed = true; + } } else { - this->m_voice->setOutputDevice(audioDevice); + if (this->m_voice->getCurrentOutputDevice() != audioDevice) + { + this->m_voice->setOutputDevice(audioDevice); + changed = true; + } + } + + if (changed) + { + emit changedSelectedAudioDevices(this->getCurrentAudioDevices()); } } @@ -176,28 +191,45 @@ namespace BlackCore qint32 vol1 = com1.getVolumeOutput(); qint32 vol2 = com2.getVolumeOutput(); this->setVolumes(vol1, vol2); - - // enable / disable in the same step - m_channelCom1->switchAudioOutput(com1.isEnabled()); - m_channelCom2->switchAudioOutput(com2.isEnabled()); } void CContextAudio::setVolumes(qint32 com1Volume, qint32 com2Volume) { if (m_channelCom1->getVolume() == com1Volume && m_channelCom2->getVolume() == com2Volume) { return; } - m_channelCom1->setRoomOutputVolume(com1Volume); - m_channelCom2->setRoomOutputVolume(com2Volume); - m_channelCom1->switchAudioOutput(com1Volume < 1); - m_channelCom2->switchAudioOutput(com2Volume < 1); - emit changedAudioVolumes(QList({com1Volume, com2Volume})); + bool enable1 = com1Volume > 0; + bool enable2 = com2Volume > 0; + bool muted = !enable1 && !enable2; + + //! \todo m_channelCom1->setVolume here crashed, also what is correct setRoomOutputVolume or setVolume + m_channelCom1->setVolume(com1Volume); + m_channelCom2->setVolume(com2Volume); + this->setMute(muted); + + emit changedAudioVolumes(com1Volume, com2Volume); } void CContextAudio::setMute(bool muted) { if (this->isMuted() == muted) { return; } // avoid roundtrips / unnecessary signals + m_channelCom1->switchAudioOutput(!muted); m_channelCom2->switchAudioOutput(!muted); + m_channelCom1->setRoomOutputVolume(muted ? 0 : VoiceRoomEnabledVolume); + m_channelCom2->setRoomOutputVolume(muted ? 0 : VoiceRoomEnabledVolume); + + // adjust volume when unmuted + if (!muted) + { + bool adjusted = false; + qint32 v1 = this->m_channelCom1->getVolume(); + qint32 v2 = this->m_channelCom2->getVolume(); + if (this->m_channelCom1->getVolume() < MinUnmuteVolume) { v1 = MinUnmuteVolume; adjusted = true; } + if (this->m_channelCom2->getVolume() < MinUnmuteVolume) { v2 = MinUnmuteVolume; adjusted = true; } + if (adjusted) { this->setVolumes(v1, v2); } + } + + // signal emit changedMute(muted); } @@ -385,6 +417,54 @@ namespace BlackCore m_voice->enableAudioLoopback(enable); } + bool CContextAudio::parseCommandLine(const QString &commandLine) + { + static CSimpleCommandParser parser( + { + ".vol", ".volume", // all volumes + ".vol1", ".volume1", // COM1 volume + ".vol2", ".volume2", // COM2 volume + ".mute", // mute + ".unmute" // unmute + }); + if (commandLine.isEmpty()) return false; + parser.parse(commandLine); + if (!parser.isKnownCommand()) return false; + + if (parser.matchesCommand(".mute")) + { + this->setMute(true); + return true; + } + else if (parser.matchesCommand(".unmute")) + { + this->setMute(false); + return true; + } + else if (parser.commandStartsWith("vol") && parser.countParts() > 1) + { + qint32 v = parser.toInt(1); + if (v >= 0 && v <= 100) + { + qint32 v1 = this->m_channelCom1->getVolume(); + qint32 v2 = this->m_channelCom2->getVolume(); + if (parser.commandEndsWith("1")) + { + this->setVolumes(v, v2); + } + else if (parser.commandEndsWith("2")) + { + this->setVolumes(v1, v); + } + else + { + this->setVolumes(v, v); + } + } + } + return false; + } + /* * Connection status changed */ diff --git a/src/blackcore/context_audio_impl.h b/src/blackcore/context_audio_impl.h index 7da7a1787..be68c976e 100644 --- a/src/blackcore/context_audio_impl.h +++ b/src/blackcore/context_audio_impl.h @@ -118,6 +118,19 @@ namespace BlackCore //! \copydoc IContextAudio::enableAudioLoopback() virtual void enableAudioLoopback(bool enable = true) override; + //! \addtogroup commandline + //! @{ + //!
+        //! .mute                          mute             CContextAudio
+        //! .unmute                        unmute           CContextAudio
+        //! .vol .volume   volume 0..100   set volume       CContextAudio
+        //! .vol1 .volume1 volume 0..100   set volume COM1  CContextAudio
+        //! .vol2 .volume2 volume 0..100   set volume COM2  CContextAudio
+        //! 
+ //! @} + //! \copydoc IContextAudio::parseCommandLine + virtual bool parseCommandLine(const QString &commandLine) override; + protected: //! Constructor CContextAudio(CRuntimeConfig::ContextMode mode, CRuntime *runtime); @@ -144,6 +157,9 @@ namespace BlackCore void ps_initNotificationSounds(); private: + const qint32 MinUnmuteVolume = 20; //!< minimum volume when unmuted + const qint32 VoiceRoomEnabledVolume = 95; //!< voice room volume when enabled + //! Connection in transition bool inTransitionState() const; @@ -156,6 +172,6 @@ namespace BlackCore QPointer m_channelCom1; QPointer m_channelCom2; }; -} +} // namespace #endif // guard diff --git a/src/blackcore/context_audio_proxy.cpp b/src/blackcore/context_audio_proxy.cpp index d707b20eb..e2e838ca0 100644 --- a/src/blackcore/context_audio_proxy.cpp +++ b/src/blackcore/context_audio_proxy.cpp @@ -39,7 +39,13 @@ namespace BlackCore "changedVoiceRooms", this, SIGNAL(changedVoiceRooms(BlackMisc::Audio::CVoiceRoomList, bool))); Q_ASSERT(s); s = connection.connect(serviceName, IContextAudio::ObjectPath(), IContextAudio::InterfaceName(), - "changedAudioVolumes", this, SIGNAL(changedAudioVolumes(QList))); + "changedAudioVolumes", this, SIGNAL(changedAudioVolumes(qint32, qint32))); + Q_ASSERT(s); + s = connection.connect(serviceName, IContextAudio::ObjectPath(), IContextAudio::InterfaceName(), + "changedAudioDevices", this, SIGNAL(changedAudioDevices(BlackMisc::Audio::CAudioDeviceList))); + Q_ASSERT(s); + s = connection.connect(serviceName, IContextAudio::ObjectPath(), IContextAudio::InterfaceName(), + "changedSelectedAudioDevices", this, SIGNAL(changedSelectedAudioDevices(BlackMisc::Audio::CAudioDeviceList))); Q_ASSERT(s); s = connection.connect(serviceName, IContextAudio::ObjectPath(), IContextAudio::InterfaceName(), "changedMute", this, SIGNAL(changedMute(bool))); @@ -239,4 +245,12 @@ namespace BlackCore return this->m_dBusInterface->callDBus(QLatin1Literal("enableAudioLoopback"), enable); } + /* + * Parse command line + */ + bool CContextAudioProxy::parseCommandLine(const QString &commandLine) + { + return this->m_dBusInterface->callDBusRet(QLatin1Literal("parseCommandLine"), commandLine); + } + } // namespace diff --git a/src/blackcore/context_audio_proxy.h b/src/blackcore/context_audio_proxy.h index 6c7ce5abd..c66a9fb22 100644 --- a/src/blackcore/context_audio_proxy.h +++ b/src/blackcore/context_audio_proxy.h @@ -122,6 +122,10 @@ namespace BlackCore //! \copydoc IContextAudio::enableAudioLoopback() virtual void enableAudioLoopback(bool enable = true) override; + + //! \copydoc IContextOwnAircraft::parseCommandLine + virtual bool parseCommandLine(const QString &commandLine) override; + }; } diff --git a/src/blackgui/components/audiosetupcomponent.cpp b/src/blackgui/components/audiosetupcomponent.cpp index 46d9b26d6..73248b3a1 100644 --- a/src/blackgui/components/audiosetupcomponent.cpp +++ b/src/blackgui/components/audiosetupcomponent.cpp @@ -50,18 +50,23 @@ namespace BlackGui // based on audio context Q_ASSERT(this->getIContextAudio()); - bool connected = false; if (this->getIContextAudio()) { this->initAudioDeviceLists(); - connected = this->connect(this->getIContextAudio(), &IContextAudio::audioTestCompleted, this, &CAudioSetupComponent::ps_audioTestUpdate); - Q_ASSERT(connected); - connected = this->connect(this->ui->cb_SetupAudioInputDevice, SIGNAL(currentIndexChanged(int)), this, SLOT(ps_audioDeviceSelected(int))); + + // the connects depend on initAudioDeviceLists + bool connected = this->connect(this->ui->cb_SetupAudioInputDevice, SIGNAL(currentIndexChanged(int)), this, SLOT(ps_audioDeviceSelected(int))); Q_ASSERT(connected); connected = this->connect(this->ui->cb_SetupAudioOutputDevice, SIGNAL(currentIndexChanged(int)), this, SLOT(ps_audioDeviceSelected(int))); Q_ASSERT(connected); + this->connect(this->ui->pb_SetupAudioMicrophoneTest, &QPushButton::clicked, this, &CAudioSetupComponent::ps_startAudioTest); this->connect(this->ui->pb_SetupAudioSquelchTest, &QPushButton::clicked, this, &CAudioSetupComponent::ps_startAudioTest); + + // context + this->connect(this->getIContextAudio(), &IContextAudio::audioTestCompleted, this, &CAudioSetupComponent::ps_audioTestUpdate); + this->connect(this->getIContextAudio(), &IContextAudio::changedAudioDevices, this, &CAudioSetupComponent::ps_onAudioDevicesChanged); + this->connect(this->getIContextAudio(), &IContextAudio::changedSelectedAudioDevices, this, &CAudioSetupComponent::ps_onCurrentAudioDevicesChanged); } this->reloadSettings(); } @@ -92,33 +97,9 @@ namespace BlackGui */ void CAudioSetupComponent::initAudioDeviceLists() { - if (!this->getIContextAudio()) return; - this->ui->cb_SetupAudioOutputDevice->clear(); - this->ui->cb_SetupAudioInputDevice->clear(); - - foreach(CAudioDevice device, this->getIContextAudio()->getAudioDevices()) - { - if (device.getType() == CAudioDevice::InputDevice) - { - this->ui->cb_SetupAudioInputDevice->addItem(device.toQString(true)); - } - else if (device.getType() == CAudioDevice::OutputDevice) - { - this->ui->cb_SetupAudioOutputDevice->addItem(device.toQString(true)); - } - } - - foreach(CAudioDevice device, this->getIContextAudio()->getCurrentAudioDevices()) - { - if (device.getType() == CAudioDevice::InputDevice) - { - this->ui->cb_SetupAudioInputDevice->setCurrentText(device.toQString(true)); - } - else if (device.getType() == CAudioDevice::OutputDevice) - { - this->ui->cb_SetupAudioOutputDevice->setCurrentText(device.toQString(true)); - } - } + if (!this->getIContextAudio()) { return; } + this->ps_onAudioDevicesChanged(this->getIContextAudio()->getAudioDevices()); + this->ps_onCurrentAudioDevicesChanged(this->getIContextAudio()->getCurrentAudioDevices()); } /* @@ -236,6 +217,38 @@ namespace BlackGui } } + void CAudioSetupComponent::ps_onCurrentAudioDevicesChanged(const BlackMisc::Audio::CAudioDeviceList &devices) + { + foreach(CAudioDevice device, devices) + { + if (device.getType() == CAudioDevice::InputDevice) + { + this->ui->cb_SetupAudioInputDevice->setCurrentText(device.toQString(true)); + } + else if (device.getType() == CAudioDevice::OutputDevice) + { + this->ui->cb_SetupAudioOutputDevice->setCurrentText(device.toQString(true)); + } + } + } + + void CAudioSetupComponent::ps_onAudioDevicesChanged(const BlackMisc::Audio::CAudioDeviceList &devices) + { + this->ui->cb_SetupAudioOutputDevice->clear(); + this->ui->cb_SetupAudioInputDevice->clear(); + + foreach(CAudioDevice device, devices) + { + if (device.getType() == CAudioDevice::InputDevice) + { + this->ui->cb_SetupAudioInputDevice->addItem(device.toQString(true)); + } + else if (device.getType() == CAudioDevice::OutputDevice) + { + this->ui->cb_SetupAudioOutputDevice->addItem(device.toQString(true)); + } + } + } + } // namespace } // namespace - diff --git a/src/blackgui/components/audiosetupcomponent.h b/src/blackgui/components/audiosetupcomponent.h index 6d49ed1b8..894913b1e 100644 --- a/src/blackgui/components/audiosetupcomponent.h +++ b/src/blackgui/components/audiosetupcomponent.h @@ -65,6 +65,12 @@ namespace BlackGui */ void ps_audioDeviceSelected(int index); + //! Current audio devices changed + void ps_onCurrentAudioDevicesChanged(const Audio::CAudioDeviceList &devices); + + //! Audio devices changed + void ps_onAudioDevicesChanged(const Audio::CAudioDeviceList &devices); + private: //! Audio test modes enum AudioTest diff --git a/src/blackgui/components/audiovolumecomponent.cpp b/src/blackgui/components/audiovolumecomponent.cpp index 5cece150c..b1a428aef 100644 --- a/src/blackgui/components/audiovolumecomponent.cpp +++ b/src/blackgui/components/audiovolumecomponent.cpp @@ -23,8 +23,16 @@ namespace BlackGui ui(new Ui::CAudioVolumeComponent) { ui->setupUi(this); - bool c = connect(this->ui->pb_ShowWinMixer, &QPushButton::pressed, this, &CAudioVolumeComponent::ps_onWindowsMixer); + bool c = connect(this->ui->pb_ShowWinMixer, &QPushButton::pressed, this, &CAudioVolumeComponent::ps_onWindowsMixerRequested); Q_ASSERT(c); + + c = connect(this->ui->hs_VolumeCom1, &QSlider::sliderReleased, this, &CAudioVolumeComponent::ps_changeVolume); + Q_ASSERT(c); + + c = connect(this->ui->hs_VolumeCom2, &QSlider::sliderReleased, this, &CAudioVolumeComponent::ps_changeVolume); + Q_ASSERT(c); + + Q_UNUSED(c); } CAudioVolumeComponent::~CAudioVolumeComponent() @@ -32,8 +40,13 @@ namespace BlackGui void CAudioVolumeComponent::runtimeHasBeenSet() { + // from audio context bool c = connect(this->getIContextAudio(), &IContextAudio::changedMute, this, &CAudioVolumeComponent::ps_onMuteChanged); Q_ASSERT(c); + connect(this->getIContextAudio(), &IContextAudio::changedAudioVolumes, this, &CAudioVolumeComponent::ps_onVolumesChanged); + Q_ASSERT(c); + + // to audio audio context c = connect(this->ui->pb_Mute, &QPushButton::toggled, this->getIContextAudio(), &IContextAudio::setMute); Q_ASSERT(c); } @@ -44,15 +57,24 @@ namespace BlackGui this->ui->pb_Mute->setChecked(muted); } - void CAudioVolumeComponent::ps_onVolumeChanged(QList volumes) + void CAudioVolumeComponent::ps_onVolumesChanged(qint32 com1Volume, qint32 com2Volume) { - Q_ASSERT(volumes.length() == 2); - if (volumes.length() != 2) return; - this->ui->hs_VolumeCom1->setValue(volumes.at(0)); - this->ui->hs_VolumeCom2->setValue(volumes.at(1)); + this->ui->hs_VolumeCom1->setValue(com1Volume); + this->ui->hs_VolumeCom2->setValue(com2Volume); + this->ui->hs_VolumeCom1->setToolTip(QString::number(com1Volume)); + this->ui->hs_VolumeCom2->setToolTip(QString::number(com2Volume)); } - void CAudioVolumeComponent::ps_onWindowsMixer() + void CAudioVolumeComponent::ps_changeVolume() + { + qint32 v1 = this->ui->hs_VolumeCom1->value(); + qint32 v2 = this->ui->hs_VolumeCom2->value(); + this->ui->hs_VolumeCom1->setToolTip(QString::number(v1)); + this->ui->hs_VolumeCom2->setToolTip(QString::number(v2)); + this->getIContextAudio()->setVolumes(v1, v2); + } + + void CAudioVolumeComponent::ps_onWindowsMixerRequested() { BlackMisc::Audio::startWindowsMixer(); } diff --git a/src/blackgui/components/audiovolumecomponent.h b/src/blackgui/components/audiovolumecomponent.h index 7e64e7fe6..c2337d5e8 100644 --- a/src/blackgui/components/audiovolumecomponent.h +++ b/src/blackgui/components/audiovolumecomponent.h @@ -44,11 +44,14 @@ namespace BlackGui //! Mute toggle void ps_onMuteChanged(bool muted); - //! Volumes changed - void ps_onVolumeChanged(QList volumes); + //! Volumes changed (elsewhere) + void ps_onVolumesChanged(qint32 com1Volume, qint32 com2Volume); + + //! Change values because of volume GUI controls + void ps_changeVolume(); //! Requested windows mixer - void ps_onWindowsMixer(); + void ps_onWindowsMixerRequested(); private: QScopedPointer ui; diff --git a/src/blackgui/components/infobarstatuscomponent.cpp b/src/blackgui/components/infobarstatuscomponent.cpp index ac6c21357..dcbe24f70 100644 --- a/src/blackgui/components/infobarstatuscomponent.cpp +++ b/src/blackgui/components/infobarstatuscomponent.cpp @@ -170,13 +170,9 @@ namespace BlackGui } } - void CInfoBarStatusComponent::ps_onVolumesChanged(QList volumes) + void CInfoBarStatusComponent::ps_onVolumesChanged(qint32 com1Volume, qint32 com2Volume) { - Q_ASSERT(volumes.count() == 2); - if (volumes.count() != 2) { return; } - qint32 v1 = volumes.at(0); - qint32 v2 = volumes.at(1); - bool pseudoMute = (v1 < 1 && v2 < 1); + bool pseudoMute = (com1Volume < 1 && com2Volume < 1); this->ps_onMuteChanged(pseudoMute); } @@ -184,5 +180,5 @@ namespace BlackGui { this->ui->led_Audio->setOn(!muted); } - } -} + } // namespace +} // namespace diff --git a/src/blackgui/components/infobarstatuscomponent.h b/src/blackgui/components/infobarstatuscomponent.h index f814a9747..01ee91cde 100644 --- a/src/blackgui/components/infobarstatuscomponent.h +++ b/src/blackgui/components/infobarstatuscomponent.h @@ -63,7 +63,7 @@ namespace BlackGui void ps_customAudioContextMenuRequested(const QPoint &position); //! Volumes changed 0..100 - void ps_onVolumesChanged(QList volumes); + void ps_onVolumesChanged(qint32 com1Volume, qint32 com2Volume); //! Mute changed void ps_onMuteChanged(bool muted);