swift
audiodevicevolumesetupcomponent.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2019 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #include <QCheckBox>
7 #include <QComboBox>
8 #include <QFileDialog>
9 #include <QMessageBox>
10 #include <QPointer>
11 #include <QStringLiteral>
12 #include <QToolButton>
13 #include <QtGlobal>
14 
15 #include "ui_audiodevicevolumesetupcomponent.h"
16 
20 #include "gui/guiapplication.h"
21 #include "gui/guiutility.h"
25 #include "misc/sequence.h"
27 
28 using namespace swift::core;
29 using namespace swift::core::afv::audio;
30 using namespace swift::core::afv::clients;
31 using namespace swift::core::context;
32 using namespace swift::misc;
33 using namespace swift::misc::aviation;
34 using namespace swift::misc::audio;
35 using namespace swift::misc::physical_quantities;
36 using namespace swift::misc::simulation;
37 
38 namespace swift::gui::components
39 {
40  CAudioDeviceVolumeSetupComponent::CAudioDeviceVolumeSetupComponent(QWidget *parent)
41  : QFrame(parent), ui(new Ui::CAudioDeviceVolumeSetupComponent)
42  {
43  ui->setupUi(this);
44  connect(ui->hs_VolumeIn, &QSlider::valueChanged, this,
45  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
46  connect(ui->hs_VolumeOut, &QSlider::valueChanged, this,
47  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
48  connect(ui->hs_VolumeOutCom1, &QSlider::valueChanged, this,
49  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
50  connect(ui->hs_VolumeOutCom2, &QSlider::valueChanged, this,
51  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
52  connect(ui->tb_RefreshInDevice, &QToolButton::released, this,
53  &CAudioDeviceVolumeSetupComponent::onReloadDevices, Qt::QueuedConnection);
54  connect(ui->tb_RefreshOutDevice, &QToolButton::released, this,
55  &CAudioDeviceVolumeSetupComponent::onReloadDevices, Qt::QueuedConnection);
56  connect(ui->tb_ResetInVolume, &QToolButton::released, this, &CAudioDeviceVolumeSetupComponent::onResetVolumeIn,
58  connect(ui->tb_ResetOutVolume, &QToolButton::released, this,
59  &CAudioDeviceVolumeSetupComponent::onResetVolumeOut, Qt::QueuedConnection);
60  connect(ui->tb_ResetOutVolumeCom1, &QToolButton::released, this,
61  &CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom1, Qt::QueuedConnection);
62  connect(ui->tb_ResetOutVolumeCom2, &QToolButton::released, this,
63  &CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom2, Qt::QueuedConnection);
64 
65  connect(ui->cb_1Tx, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
67  connect(ui->cb_2Tx, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
69  connect(ui->cb_1Rec, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
71  connect(ui->cb_2Rec, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
73 
74  connect(ui->tb_Info, &QToolButton::released, this, &CAudioDeviceVolumeSetupComponent::showAudioRunsWhereDialog);
75 
76  ui->hs_VolumeIn->setMaximum(CSettings::InMax);
77  ui->hs_VolumeIn->setMinimum(CSettings::InMin);
78  ui->hs_VolumeOut->setMaximum(CSettings::OutMax);
79  ui->hs_VolumeOut->setMinimum(CSettings::OutMin);
80  ui->hs_VolumeOutCom1->setMaximum(CSettings::OutMax);
81  ui->hs_VolumeOutCom1->setMinimum(CSettings::OutMin);
82  ui->hs_VolumeOutCom2->setMaximum(CSettings::OutMax);
83  ui->hs_VolumeOutCom2->setMinimum(CSettings::OutMin);
84 
85  const CSettings as(m_audioSettings.getThreadLocal());
86  const int i = this->getInValue();
87  const int o = this->getOutValue();
88  const int o1 = this->getOutValueCom1();
89  const int o2 = this->getOutValueCom2();
90  ui->hs_VolumeIn->setValue(i);
91  ui->hs_VolumeOut->setValue(o);
92  ui->hs_VolumeOutCom1->setValue(o1);
93  ui->hs_VolumeOutCom2->setValue(o2);
94  ui->cb_SetupAudioLoopback->setChecked(false);
95  ui->cb_DisableAudioEffects->setChecked(!as.isAudioEffectsEnabled());
96 
97  ui->led_AudioConnected->setToolTips("Voice on and authenticated", "Voice off");
98  ui->led_AudioConnected->setShape(CLedWidget::Rounded);
99  ui->led_Rx1->setToolTips("COM1 receiving", "COM1 idle");
100  ui->led_Rx1->setShape(CLedWidget::Rounded);
101  ui->led_Rx2->setToolTips("COM2 receiving", "COM2 idle");
102  ui->led_Rx2->setShape(CLedWidget::Rounded);
103 
104  // deferred init, because in a distributed swift system
105  // it takes a moment until the settings are sychronized
106  // this is leading to undesired "save settings" messages and played sounds
108  QTimer::singleShot(2000, this, [=, this] {
109  if (!myself || !sGui || sGui->isShuttingDown()) { return; }
110  this->init();
111  });
112 
113  this->setCheckBoxesReadOnly(this->isComIntegrated());
114  this->setVolumeSlidersReadOnly(this->isComIntegrated());
115  }
116 
117  void CAudioDeviceVolumeSetupComponent::init()
118  {
119  if (!sGui || sGui->isShuttingDown() || !sGui->getCContextAudioBase()) { return; }
120 
121  // audio is optional
122  const bool audio = this->hasAudio();
123  this->setEnabled(audio);
124  this->reloadSettings();
125 
126  bool c = connect(ui->cb_SetupAudioLoopback, &QCheckBox::toggled, this,
127  &CAudioDeviceVolumeSetupComponent::onLoopbackToggled);
128  Q_ASSERT(c);
129  c = connect(ui->cb_DisableAudioEffects, &QCheckBox::toggled, this,
130  &CAudioDeviceVolumeSetupComponent::onDisableAudioEffectsToggled);
131  Q_ASSERT(c);
132 
133  if (hasSimulator())
134  {
135  c = connect(sGui->getIContextSimulator(), &IContextSimulator::simulatorSettingsChanged, this,
136  &CAudioDeviceVolumeSetupComponent::simulatorSettingsChanged);
137  Q_ASSERT(c);
138  }
139 
140  if (audio)
141  {
142  this->initAudioDeviceLists();
143 
144  // default
145  ui->cb_SetupAudioLoopback->setChecked(sGui->getCContextAudioBase()->isAudioLoopbackEnabled());
146 
147  // the connects depend on initAudioDeviceLists
148  c = connect(ui->cb_SetupAudioInputDevice, qOverload<int>(&QComboBox::currentIndexChanged), this,
149  &CAudioDeviceVolumeSetupComponent::onAudioDeviceSelected, Qt::QueuedConnection);
150  Q_ASSERT(c);
151  c = connect(ui->cb_SetupAudioOutputDevice, qOverload<int>(&QComboBox::currentIndexChanged), this,
152  &CAudioDeviceVolumeSetupComponent::onAudioDeviceSelected, Qt::QueuedConnection);
153  Q_ASSERT(c);
154 
155  // context
156  c = connect(sGui->getCContextAudioBase(), &CContextAudioBase::changedLocalAudioDevices, this,
157  &CAudioDeviceVolumeSetupComponent::onAudioDevicesChanged, Qt::QueuedConnection);
158  Q_ASSERT(c);
159  c = connect(sGui->getCContextAudioBase(), &CContextAudioBase::startedAudio, this,
160  &CAudioDeviceVolumeSetupComponent::onAudioStarted, Qt::QueuedConnection);
161  Q_ASSERT(c);
162  c = connect(sGui->getCContextAudioBase(), &CContextAudioBase::stoppedAudio, this,
163  &CAudioDeviceVolumeSetupComponent::onAudioStopped, Qt::QueuedConnection);
164  Q_ASSERT(c);
165 
166  this->initWithAfvClient();
167  m_init = true;
168  }
169  Q_UNUSED(c)
170  }
171 
172  void CAudioDeviceVolumeSetupComponent::initWithAfvClient()
173  {
174  if (!afvClient()) { return; }
175  m_afvConnections.disconnectAll();
176 
178  CAfvClient *afv = afvClient();
181  c = connect(afv, &CAfvClient::outputVolumePeakVU, this, &CAudioDeviceVolumeSetupComponent::onOutputVU, ct);
182  Q_ASSERT(c);
183  m_afvConnections.append(c);
184  c = connect(afv, &CAfvClient::inputVolumePeakVU, this, &CAudioDeviceVolumeSetupComponent::onInputVU, ct);
185  Q_ASSERT(c);
186  m_afvConnections.append(c);
187  c = connect(afv, &CAfvClient::receivedCallsignsChanged, this,
188  &CAudioDeviceVolumeSetupComponent::onReceivingCallsignsChanged, ct);
189  Q_ASSERT(c);
190  m_afvConnections.append(c);
191  c = connect(afv, &CAfvClient::updatedFromOwnAircraftCockpit, this,
192  &CAudioDeviceVolumeSetupComponent::onUpdatedClientWithCockpitData, ct);
193  Q_ASSERT(c);
194  m_afvConnections.append(c);
195 
196  // default values for RX/TX
197  afv->setRxTx(true, true, true, false);
198 
200  c = connect(
201  afv, &CAfvClient::connectionStatusChanged, this,
202  [=](CAfvClient::ConnectionStatus status) {
203  if (!myself || !sGui || sGui->isShuttingDown()) { return; }
204  myself->setTransmitReceiveInUiFromVoiceClient();
205  Q_UNUSED(status)
206  },
207  ct);
208  Q_ASSERT(c);
209  m_afvConnections.append(c);
210 
211  this->setTransmitReceiveInUiFromVoiceClient();
212  }
213 
215 
217  {
218  const double r = ui->hs_VolumeIn->maximum() - ui->hs_VolumeIn->minimum();
219  const double tr = to - from;
220  return qRound(ui->hs_VolumeIn->value() / r * tr);
221  }
222 
224  {
225  const double r = ui->hs_VolumeOut->maximum() - ui->hs_VolumeOut->minimum();
226  const double tr = to - from;
227  return qRound(ui->hs_VolumeOut->value() / r * tr);
228  }
229 
231  {
232  const double r = ui->hs_VolumeOutCom1->maximum() - ui->hs_VolumeOutCom1->minimum();
233  const double tr = to - from;
234  return qRound(ui->hs_VolumeOutCom1->value() / r * tr);
235  }
236 
238  {
239  const double r = ui->hs_VolumeOutCom2->maximum() - ui->hs_VolumeOutCom2->minimum();
240  const double tr = to - from;
241  return qRound(ui->hs_VolumeOutCom2->value() / r * tr);
242  }
243 
244  void CAudioDeviceVolumeSetupComponent::setInValue(int value, int from, int to)
245  {
246  if (value > to) { value = to; }
247  else if (value < from) { value = from; }
248  const double r = ui->hs_VolumeIn->maximum() - ui->hs_VolumeIn->minimum();
249  const double tr = to - from;
250  ui->hs_VolumeIn->setValue(qRound(value / tr * r));
251  }
252 
253  void CAudioDeviceVolumeSetupComponent::setOutValue(int value, int from, int to)
254  {
255  if (value > to) { value = to; }
256  else if (value < from) { value = from; }
257  const double r = ui->hs_VolumeOut->maximum() - ui->hs_VolumeOut->minimum();
258  const double tr = to - from;
259  ui->hs_VolumeOut->setValue(qRound(value / tr * r));
260  }
261 
262  void CAudioDeviceVolumeSetupComponent::setOutValueCom1(int value, int from, int to)
263  {
264  if (value > to) { value = to; }
265  else if (value < from) { value = from; }
266  const double r = ui->hs_VolumeOutCom1->maximum() - ui->hs_VolumeOutCom1->minimum();
267  const double tr = to - from;
268  ui->hs_VolumeOutCom1->setValue(qRound(value / tr * r));
269  }
270 
271  void CAudioDeviceVolumeSetupComponent::setOutValueCom2(int value, int from, int to)
272  {
273  if (value > to) { value = to; }
274  else if (value < from) { value = from; }
275  const double r = ui->hs_VolumeOutCom2->maximum() - ui->hs_VolumeOutCom2->minimum();
276  const double tr = to - from;
277  ui->hs_VolumeOutCom2->setValue(qRound(value / tr * r));
278  }
279 
281  {
282  if (value > 1.0) { value = 1.0; }
283  else if (value < 0.0) { value = 0.0; }
284  ui->wip_InLevelMeter->levelChanged(value);
285  }
286 
288  {
289  if (value > 1.0) { value = 1.0; }
290  else if (value < 0.0) { value = 0.0; }
291  ui->wip_OutLevelMeter->levelChanged(value);
292  }
293 
294  void CAudioDeviceVolumeSetupComponent::setTransmitReceiveInUi(bool tx1, bool rec1, bool tx2, bool rec2,
295  bool integrated)
296  {
297  this->setRxTxCheckboxes(rec1, tx1, rec2, tx2);
298  this->setCheckBoxesReadOnly(integrated);
299  this->setVolumeSlidersReadOnly(integrated);
300  }
301 
302  void CAudioDeviceVolumeSetupComponent::setTransmitReceiveInUiFromVoiceClient()
303  {
304  if (!this->hasAudio())
305  {
306  ui->led_AudioConnected->setOn(false);
307  return;
308  }
309 
310  const bool on = sGui->getCContextAudioBase()->isAudioConnected();
311  ui->led_AudioConnected->setOn(on);
312 
313  const bool com1Enabled = sGui->getCContextAudioBase()->isEnabledComUnit(CComSystem::Com1);
314  const bool com2Enabled = sGui->getCContextAudioBase()->isEnabledComUnit(CComSystem::Com2);
315 
316  const bool com1Tx = com1Enabled && sGui->getCContextAudioBase()->isTransmittingComUnit(CComSystem::Com1);
317  const bool com2Tx = com2Enabled && sGui->getCContextAudioBase()->isTransmittingComUnit(CComSystem::Com2);
318 
319  // we do not have receiving, so we use enable
320  const bool com1Rx = com1Enabled;
321  const bool com2Rx = com2Enabled;
322 
323  const bool integrated = this->isComIntegrated();
324  this->setTransmitReceiveInUi(com1Tx, com1Rx, com2Tx, com2Rx, integrated);
325 
326  // Set transmit volume in GUI
327  if (integrated)
328  {
329  const int vol1 = sGui->getCContextAudioBase()->getComOutputVolume(CComSystem::Com1);
330  const int vol2 = sGui->getCContextAudioBase()->getComOutputVolume(CComSystem::Com2);
331  ui->hs_VolumeOutCom1->setValue(vol1);
332  ui->hs_VolumeOutCom2->setValue(vol2);
333  }
334  }
335 
336  void CAudioDeviceVolumeSetupComponent::setCheckBoxesReadOnly(bool readonly)
337  {
338  // all tx/rec checkboxes
339  CGuiUtility::checkBoxReadOnly(ui->cb_1Tx, readonly);
340  CGuiUtility::checkBoxReadOnly(ui->cb_2Tx, readonly);
341  CGuiUtility::checkBoxReadOnly(ui->cb_1Rec, readonly);
342  CGuiUtility::checkBoxReadOnly(ui->cb_2Rec, readonly);
343  }
344 
345  void CAudioDeviceVolumeSetupComponent::setVolumeSlidersReadOnly(bool readonly)
346  {
347  ui->hs_VolumeOutCom1->setDisabled(readonly);
348  ui->hs_VolumeOutCom2->setDisabled(readonly);
349  if (readonly)
350  {
351  // \fixme hardcoded stylesheet setting, should come from stylesheet")
352  ui->hs_VolumeOutCom1->setStyleSheet("background: rgb(40,40,40)");
353  ui->hs_VolumeOutCom2->setStyleSheet("background: rgb(40,40,40)");
354  }
355  else
356  {
357  ui->hs_VolumeOutCom1->setStyleSheet("");
358  ui->hs_VolumeOutCom2->setStyleSheet("");
359  }
360  }
361 
362  CAfvClient *CAudioDeviceVolumeSetupComponent::afvClient()
363  {
364  if (!sGui || sGui->isShuttingDown() || !sGui->getCContextAudioBase()) { return nullptr; }
365  return sGui->getCContextAudioBase()->afvClient();
366  }
367 
368  void CAudioDeviceVolumeSetupComponent::reloadSettings()
369  {
370  const CSettings as(m_audioSettings.getThreadLocal());
371  ui->cb_DisableAudioEffects->setChecked(!as.isAudioEffectsEnabled());
372  this->setInValue(as.getInVolume());
373  this->setOutValue(as.getOutVolume());
374  this->setOutValueCom1(as.getOutVolumeCom1());
375  this->setOutValueCom2(as.getOutVolumeCom2());
376  }
377 
378  void CAudioDeviceVolumeSetupComponent::initAudioDeviceLists()
379  {
380  if (!this->hasAudio()) { return; }
381  const bool changed = this->onAudioDevicesChanged(sGui->getCContextAudioBase()->getAudioDevices());
382  if (!changed) { return; }
384  this->onAudioStarted(currentDevices.getInputDevices().frontOrDefault(),
385  currentDevices.getOutputDevices().frontOrDefault());
386  }
387 
388  bool CAudioDeviceVolumeSetupComponent::hasAudio() const { return sGui && sGui->getCContextAudioBase(); }
389 
390  bool CAudioDeviceVolumeSetupComponent::hasSimulator() const { return sGui && sGui->getIContextSimulator(); }
391 
392  void CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged(int v)
393  {
394  Q_UNUSED(v)
395  m_volumeSliderChanged.inputSignal();
396  }
397 
398  void CAudioDeviceVolumeSetupComponent::saveVolumes()
399  {
400  CSettings as(m_audioSettings.getThreadLocal());
401  const int i = this->getInValue();
402  const int o = this->getOutValue();
403  const int o1 = this->getOutValueCom1();
404  const int o2 = this->getOutValueCom2();
405  if (as.getInVolume() == i && o == as.getOutVolume() && as.getOutVolumeCom1() == o1 &&
406  as.getOutVolumeCom2() == o2)
407  {
408  return;
409  }
410  as.setInVolume(i);
411  as.setOutVolume(o);
412  as.setOutVolumeCom1(o1);
413  as.setOutVolumeCom2(o2);
414  m_audioSettings.setAndSave(as);
415  }
416 
417  void CAudioDeviceVolumeSetupComponent::onOutputVU(double vu) { this->setOutLevel(vu); }
418 
419  void CAudioDeviceVolumeSetupComponent::onInputVU(double vu) { this->setInLevel(vu); }
420 
421  void CAudioDeviceVolumeSetupComponent::onReloadDevices()
422  {
423  if (!hasAudio()) { return; }
424  this->initAudioDeviceLists();
425  const CAudioDeviceInfo i = this->getSelectedInputDevice();
426  const CAudioDeviceInfo o = this->getSelectedOutputDevice();
428  }
429 
430  void CAudioDeviceVolumeSetupComponent::onResetVolumeIn()
431  {
432  ui->hs_VolumeIn->setValue((ui->hs_VolumeIn->maximum() - ui->hs_VolumeIn->minimum()) / 2);
433  }
434 
435  void CAudioDeviceVolumeSetupComponent::onResetVolumeOut()
436  {
437  ui->hs_VolumeOut->setValue((ui->hs_VolumeOut->maximum() - ui->hs_VolumeOut->minimum()) / 2);
438  }
439 
440  void CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom1()
441  {
442  ui->hs_VolumeOutCom1->setValue(ui->hs_VolumeOutCom1->maximum());
443  }
444 
445  void CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom2()
446  {
447  ui->hs_VolumeOutCom2->setValue(ui->hs_VolumeOutCom2->maximum());
448  }
449 
450  void CAudioDeviceVolumeSetupComponent::showAudioRunsWhereDialog()
451  {
452  if (!this->hasAudio()) { return; }
454  QMessageBox::information(this, "Audio information", ai);
455  }
456 
457  void CAudioDeviceVolumeSetupComponent::simulatorSettingsChanged()
458  {
459  const bool integrated = this->isComIntegrated();
460  setCheckBoxesReadOnly(integrated);
461  setVolumeSlidersReadOnly(integrated);
462  }
463 
464  bool CAudioDeviceVolumeSetupComponent::isComIntegrated() const
465  {
466  if (!this->hasSimulator()) { return false; }
468  const bool integrate = settings.isComIntegrated();
469  return integrate;
470  }
471 
472  void CAudioDeviceVolumeSetupComponent::onRxTxChanged(bool checked)
473  {
474  if (!this->hasAudio()) { return; }
475  if (this->isComIntegrated()) { return; }
476 
477  Q_UNUSED(checked)
478  const bool rx1 = ui->cb_1Rec->isChecked();
479  const bool rx2 = ui->cb_2Rec->isChecked();
480 
481  // no transmit without receiving
482  const bool tx1 = rx1 && ui->cb_1Tx->isChecked();
483  const bool tx2 = rx2 && ui->cb_2Tx->isChecked();
484 
485  sGui->getCContextAudioBase()->setRxTx(rx1, tx1, rx2, tx2);
486 
488  QTimer::singleShot(25, this, [=, this] {
489  // in case UI values are not correct
490  if (!myself) { return; }
491  this->setRxTxCheckboxes(rx1, tx1, rx2, tx2);
492  });
493  }
494 
495  void CAudioDeviceVolumeSetupComponent::setRxTxCheckboxes(bool rx1, bool tx1, bool rx2, bool tx2)
496  {
497  if (ui->cb_1Tx->isChecked() != tx1) { ui->cb_1Tx->setChecked(tx1); }
498  if (ui->cb_2Tx->isChecked() != tx2) { ui->cb_2Tx->setChecked(tx2); }
499  if (ui->cb_1Rec->isChecked() != rx1) { ui->cb_1Rec->setChecked(rx1); }
500  if (ui->cb_2Rec->isChecked() != rx2) { ui->cb_2Rec->setChecked(rx2); }
501  }
502 
503  void CAudioDeviceVolumeSetupComponent::onReceivingCallsignsChanged(const CCallsignSet &com1Callsigns,
504  const CCallsignSet &com2Callsigns)
505  {
506  if (!com1Callsigns.empty())
507  {
508  ui->le_Com1->setText(QStringLiteral("COM1: ") % com1Callsigns.getCallsignsAsString());
509  }
510  else
511  {
512  if (!ui->le_Com1->text().isEmpty())
513  {
514  ui->le_Com1->setPlaceholderText(ui->le_Com1->text());
515  ui->le_Com1->clear();
516  }
517  }
518 
519  if (!com2Callsigns.empty())
520  {
521  ui->le_Com2->setText(QStringLiteral("COM2: ") % com2Callsigns.getCallsignsAsString());
522  }
523  else
524  {
525  if (!ui->le_Com2->text().isEmpty())
526  {
527  ui->le_Com2->setPlaceholderText(ui->le_Com2->text());
528  ui->le_Com2->clear();
529  }
530  }
531  }
532 
533  void CAudioDeviceVolumeSetupComponent::onUpdatedClientWithCockpitData()
534  {
535  this->setTransmitReceiveInUiFromVoiceClient();
536  }
537 
538  CAudioDeviceInfo CAudioDeviceVolumeSetupComponent::getSelectedInputDevice() const
539  {
540  if (!hasAudio()) { return {}; }
542  return devices.findByName(ui->cb_SetupAudioInputDevice->currentText());
543  }
544 
545  CAudioDeviceInfo CAudioDeviceVolumeSetupComponent::getSelectedOutputDevice() const
546  {
547  if (!hasAudio()) { return {}; }
549  return devices.findByName(ui->cb_SetupAudioOutputDevice->currentText());
550  }
551 
552  void CAudioDeviceVolumeSetupComponent::onAudioDeviceSelected(int index)
553  {
554  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextAudio()) { return; }
555  if (index < 0) { return; }
556 
557  const CAudioDeviceInfo in = this->getSelectedInputDevice();
558  const CAudioDeviceInfo out = this->getSelectedOutputDevice();
560  }
561 
562  void CAudioDeviceVolumeSetupComponent::onAudioStarted(const CAudioDeviceInfo &input, const CAudioDeviceInfo &output)
563  {
564  if (!afvClient()) { return; }
565  if (m_afvConnections.isEmpty() && m_init) { this->initWithAfvClient(); }
566 
567  ui->cb_SetupAudioInputDevice->setCurrentText(input.toQString(true));
568  ui->cb_SetupAudioOutputDevice->setCurrentText(output.toQString(true));
569  }
570 
571  void CAudioDeviceVolumeSetupComponent::onAudioStopped()
572  {
573  if (!afvClient()) { m_afvConnections.disconnectAll(); }
574  }
575 
576  bool CAudioDeviceVolumeSetupComponent::onAudioDevicesChanged(const CAudioDeviceInfoList &devices)
577  {
578  if (m_cbDevices.hasSameDevices(devices)) { return false; } // avoid numerous follow up actions
579  m_cbDevices = devices;
580 
581  ui->cb_SetupAudioOutputDevice->clear();
582  ui->cb_SetupAudioInputDevice->clear();
583 
584  const QString i = ui->cb_SetupAudioInputDevice->currentText();
585  const QString o = ui->cb_SetupAudioOutputDevice->currentText();
586 
587  for (const CAudioDeviceInfo &device : devices)
588  {
589  if (device.getType() == CAudioDeviceInfo::InputDevice)
590  {
591  ui->cb_SetupAudioInputDevice->addItem(device.toQString(true));
592  }
593  else if (device.getType() == CAudioDeviceInfo::OutputDevice)
594  {
595  ui->cb_SetupAudioOutputDevice->addItem(device.toQString(true));
596  }
597  }
598 
599  if (!i.isEmpty()) { ui->cb_SetupAudioInputDevice->setCurrentText(i); }
600  if (!o.isEmpty()) { ui->cb_SetupAudioOutputDevice->setCurrentText(o); }
601 
602  return true;
603  }
604 
605  void CAudioDeviceVolumeSetupComponent::onLoopbackToggled(bool loopback)
606  {
607  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextAudio()) { return; }
608  if (sGui->getCContextAudioBase()->isAudioLoopbackEnabled() == loopback) { return; }
610  }
611 
612  void CAudioDeviceVolumeSetupComponent::onDisableAudioEffectsToggled(bool disabled)
613  {
614  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextAudio()) { return; }
615  CSettings as(m_audioSettings.getThreadLocal());
616  const bool enabled = !disabled;
617  if (as.isAudioEffectsEnabled() == enabled) { return; }
618  as.setAudioEffectsEnabled(enabled);
619  m_audioSettings.setAndSave(as);
620  }
621 } // namespace swift::gui::components
const context::IContextAudio * getIContextAudio() const
Direct access to contexts if a CCoreFacade has been initialized.
bool isShuttingDown() const
Is application shutting down?
const context::IContextSimulator * getIContextSimulator() const
Direct access to contexts if a CCoreFacade has been initialized.
const context::CContextAudioBase * getCContextAudioBase() const
Direct access to contexts if a CCoreFacade has been initialized.
ConnectionStatus
Connection status.
Definition: afvclient.h:53
void setRxTx(bool rx1, bool tx1, bool rx2, bool tx2)
Simplified enable/disable.
Definition: afvclient.cpp:612
bool isAudioLoopbackEnabled() const
Loopback.
bool isAudioConnected() const
Is audio connected?
void enableAudioLoopback(bool enable=true)
Loopback.
swift::misc::audio::CAudioDeviceInfoList getAudioOutputDevices() const
Audio devices.
bool isTransmittingComUnit(swift::misc::aviation::CComSystem::ComUnit comUnit) const
Is COM unit transmitting?
swift::misc::audio::CAudioDeviceInfoList getAudioDevices() const
Audio devices.
void setCurrentAudioDevices(const swift::misc::audio::CAudioDeviceInfo &inputDevice, const swift::misc::audio::CAudioDeviceInfo &outputDevice)
Set current audio devices.
QString audioRunsWhereInfo() const
Info string about audio.
swift::misc::audio::CAudioDeviceInfoList getCurrentAudioDevices() const
Get current audio device.
int getComOutputVolume(swift::misc::aviation::CComSystem::ComUnit comUnit) const
Volume.
bool isEnabledComUnit(swift::misc::aviation::CComSystem::ComUnit comUnit) const
Is COM unit enabled?
void setRxTx(bool rx1, bool tx1, bool rx2, bool tx2)
Receive/transmit.
afv::clients::CAfvClient * afvClient() const
Definition: contextaudio.h:229
swift::misc::audio::CAudioDeviceInfoList getAudioInputDevices() const
Audio devices.
virtual swift::misc::simulation::settings::CSimulatorSettings getSimulatorSettings() const =0
Get the current simulator settings.
static void checkBoxReadOnly(QCheckBox *checkBox, bool readOnly)
Pseudo readonly state for checkbox.
Definition: guiutility.cpp:450
void setOutValueCom1(int value, int from=swift::misc::audio::CSettings::OutMin, int to=swift::misc::audio::CSettings::OutMax)
Set input and output volume values.
int getInValue(int from=swift::misc::audio::CSettings::InMin, int to=swift::misc::audio::CSettings::InMax) const
Get input and output volume values.
int getOutValueCom2(int from=swift::misc::audio::CSettings::OutMin, int to=swift::misc::audio::CSettings::OutMax) const
Get input and output volume values.
int getOutValue(int from=swift::misc::audio::CSettings::OutMin, int to=swift::misc::audio::CSettings::OutMax) const
Get input and output volume values.
int getOutValueCom1(int from=swift::misc::audio::CSettings::OutMin, int to=swift::misc::audio::CSettings::OutMax) const
Get input and output volume values.
void setOutValueCom2(int value, int from=swift::misc::audio::CSettings::OutMin, int to=swift::misc::audio::CSettings::OutMax)
Set input and output volume values.
void setInValue(int value, int from=swift::misc::audio::CSettings::InMin, int to=swift::misc::audio::CSettings::InMax)
Set input and output volume values.
void setInLevel(double value)
Set input and output level values 0..1.
void setOutLevel(double value)
Set input and output level values 0..1.
void setOutValue(int value, int from=swift::misc::audio::CSettings::InMin, int to=swift::misc::audio::CSettings::InMax)
Set input and output volume values.
CStatusMessage setAndSave(const T &value, qint64 timestamp=0)
Write and save in the same step. Must be called from the thread in which the owner lives.
Definition: valuecache.h:417
const T & getThreadLocal() const
Read the current value.
Definition: valuecache.h:400
bool empty() const
Returns true if the collection is empty.
Definition: collection.h:188
bool append(const QMetaObject::Connection &connection)
Add connection.
int disconnectAll()
Disconnect all.
void inputSignal()
Received input signal, or manually trigger.
const_reference frontOrDefault() const
Access the first element, or a default-initialized value if the sequence is empty.
Definition: sequence.h:239
Value object encapsulating information of a audio device.
Value object encapsulating a list of audio devices.
CAudioDeviceInfoList getOutputDevices() const
Get output devices in that list.
CAudioDeviceInfoList getInputDevices() const
Get output devices in that list.
bool hasSameDevices(const CAudioDeviceInfoList &compareDevices) const
Has same devices.
CAudioDeviceInfo findByName(const QString &name, bool strict=false) const
Find by name.
Value object encapsulating information of audio related settings.
Definition: audiosettings.h:25
bool isAudioEffectsEnabled() const
Audio effects enabled?
Value object for a set of callsigns.
Definition: callsignset.h:26
QString getCallsignsAsString(bool sorted=false, const QString &separator=", ") const
Callsigns as string.
Definition: callsignset.cpp:43
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:74
Settings for simulator Driver independent parts (such as directories), also used in model loaders.
SWIFT_GUI_EXPORT swift::gui::CGuiApplication * sGui
Single instance of GUI application object.
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
High level reusable GUI components.
Definition: aboutdialog.cpp:14
Free functions in swift::misc.
void toggled(bool checked)
void valueChanged(int value)
void currentIndexChanged(int index)
QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
QueuedConnection
void setEnabled(bool)