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 <QPointer>
10 #include <QStringLiteral>
11 #include <QToolButton>
12 #include <QtGlobal>
13 
14 #include "ui_audiodevicevolumesetupcomponent.h"
15 
19 #include "gui/guiapplication.h"
20 #include "gui/guiutility.h"
24 #include "misc/sequence.h"
26 
27 using namespace swift::core;
28 using namespace swift::core::afv::audio;
29 using namespace swift::core::afv::clients;
30 using namespace swift::core::context;
31 using namespace swift::misc;
32 using namespace swift::misc::aviation;
33 using namespace swift::misc::audio;
34 using namespace swift::misc::physical_quantities;
35 using namespace swift::misc::simulation;
36 
37 namespace swift::gui::components
38 {
39  CAudioDeviceVolumeSetupComponent::CAudioDeviceVolumeSetupComponent(QWidget *parent)
40  : QFrame(parent), ui(new Ui::CAudioDeviceVolumeSetupComponent)
41  {
42  ui->setupUi(this);
43  connect(ui->hs_VolumeIn, &QSlider::valueChanged, this,
44  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
45  connect(ui->hs_VolumeOut, &QSlider::valueChanged, this,
46  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
47  connect(ui->hs_VolumeOutCom1, &QSlider::valueChanged, this,
48  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
49  connect(ui->hs_VolumeOutCom2, &QSlider::valueChanged, this,
50  &CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged);
51  connect(ui->tb_RefreshInDevice, &QToolButton::released, this,
52  &CAudioDeviceVolumeSetupComponent::onReloadDevices, Qt::QueuedConnection);
53  connect(ui->tb_RefreshOutDevice, &QToolButton::released, this,
54  &CAudioDeviceVolumeSetupComponent::onReloadDevices, Qt::QueuedConnection);
55  connect(ui->tb_ResetInVolume, &QToolButton::released, this, &CAudioDeviceVolumeSetupComponent::onResetVolumeIn,
56  Qt::QueuedConnection);
57  connect(ui->tb_ResetOutVolume, &QToolButton::released, this,
58  &CAudioDeviceVolumeSetupComponent::onResetVolumeOut, Qt::QueuedConnection);
59  connect(ui->tb_ResetOutVolumeCom1, &QToolButton::released, this,
60  &CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom1, Qt::QueuedConnection);
61  connect(ui->tb_ResetOutVolumeCom2, &QToolButton::released, this,
62  &CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom2, Qt::QueuedConnection);
63 
64  connect(ui->cb_1Tx, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
65  Qt::QueuedConnection);
66  connect(ui->cb_2Tx, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
67  Qt::QueuedConnection);
68  connect(ui->cb_1Rec, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
69  Qt::QueuedConnection);
70  connect(ui->cb_2Rec, &QCheckBox::toggled, this, &CAudioDeviceVolumeSetupComponent::onRxTxChanged,
71  Qt::QueuedConnection);
72 
73  ui->hs_VolumeIn->setMaximum(CSettings::InMax);
74  ui->hs_VolumeIn->setMinimum(CSettings::InMin);
75  ui->hs_VolumeOut->setMaximum(CSettings::OutMax);
76  ui->hs_VolumeOut->setMinimum(CSettings::OutMin);
77  ui->hs_VolumeOutCom1->setMaximum(CSettings::OutMax);
78  ui->hs_VolumeOutCom1->setMinimum(CSettings::OutMin);
79  ui->hs_VolumeOutCom2->setMaximum(CSettings::OutMax);
80  ui->hs_VolumeOutCom2->setMinimum(CSettings::OutMin);
81 
82  const CSettings as(m_audioSettings.getThreadLocal());
83  const int i = this->getInValue();
84  const int o = this->getOutValue();
85  const int o1 = this->getOutValueCom1();
86  const int o2 = this->getOutValueCom2();
87  ui->hs_VolumeIn->setValue(i);
88  ui->hs_VolumeOut->setValue(o);
89  ui->hs_VolumeOutCom1->setValue(o1);
90  ui->hs_VolumeOutCom2->setValue(o2);
91  ui->cb_SetupAudioLoopback->setChecked(false);
92  ui->cb_DisableAudioEffects->setChecked(!as.isAudioEffectsEnabled());
93 
94  ui->led_AudioConnected->setToolTips("Voice on and authenticated", "Voice off");
95  ui->led_AudioConnected->setShape(CLedWidget::Rounded);
96  ui->led_Rx1->setToolTips("COM1 receiving", "COM1 idle");
97  ui->led_Rx1->setShape(CLedWidget::Rounded);
98  ui->led_Rx2->setToolTips("COM2 receiving", "COM2 idle");
99  ui->led_Rx2->setShape(CLedWidget::Rounded);
100 
101  // deferred init, because in a distributed swift system
102  // it takes a moment until the settings are sychronized
103  // this is leading to undesired "save settings" messages and played sounds
104  QPointer<CAudioDeviceVolumeSetupComponent> myself(this);
105  QTimer::singleShot(2000, this, [=] {
106  if (!myself || !sGui || sGui->isShuttingDown()) { return; }
107  this->init();
108  });
109 
110  this->setCheckBoxesReadOnly(this->isComIntegrated());
111  this->setVolumeSlidersReadOnly(this->isComIntegrated());
112  }
113 
114  void CAudioDeviceVolumeSetupComponent::init()
115  {
116  if (!sGui || sGui->isShuttingDown() || !sGui->getCContextAudioBase()) { return; }
117 
118  // audio is optional
119  const bool audio = this->hasAudio();
120  this->setEnabled(audio);
121  this->reloadSettings();
122 
123  bool c = connect(ui->cb_SetupAudioLoopback, &QCheckBox::toggled, this,
124  &CAudioDeviceVolumeSetupComponent::onLoopbackToggled);
125  Q_ASSERT(c);
126  c = connect(ui->cb_DisableAudioEffects, &QCheckBox::toggled, this,
127  &CAudioDeviceVolumeSetupComponent::onDisableAudioEffectsToggled);
128  Q_ASSERT(c);
129 
130  if (hasSimulator())
131  {
132  c = connect(sGui->getIContextSimulator(), &IContextSimulator::simulatorSettingsChanged, this,
133  &CAudioDeviceVolumeSetupComponent::simulatorSettingsChanged);
134  Q_ASSERT(c);
135  }
136 
137  if (audio)
138  {
139  this->setAudioRunsWhere();
140  this->initAudioDeviceLists();
141 
142  // default
143  ui->cb_SetupAudioLoopback->setChecked(sGui->getCContextAudioBase()->isAudioLoopbackEnabled());
144 
145  // the connects depend on initAudioDeviceLists
146  c = connect(ui->cb_SetupAudioInputDevice, qOverload<int>(&QComboBox::currentIndexChanged), this,
147  &CAudioDeviceVolumeSetupComponent::onAudioDeviceSelected, Qt::QueuedConnection);
148  Q_ASSERT(c);
149  c = connect(ui->cb_SetupAudioOutputDevice, qOverload<int>(&QComboBox::currentIndexChanged), this,
150  &CAudioDeviceVolumeSetupComponent::onAudioDeviceSelected, Qt::QueuedConnection);
151  Q_ASSERT(c);
152 
153  // context
154  c = connect(sGui->getCContextAudioBase(), &CContextAudioBase::changedLocalAudioDevices, this,
155  &CAudioDeviceVolumeSetupComponent::onAudioDevicesChanged, Qt::QueuedConnection);
156  Q_ASSERT(c);
157  c = connect(sGui->getCContextAudioBase(), &CContextAudioBase::startedAudio, this,
158  &CAudioDeviceVolumeSetupComponent::onAudioStarted, Qt::QueuedConnection);
159  Q_ASSERT(c);
160  c = connect(sGui->getCContextAudioBase(), &CContextAudioBase::stoppedAudio, this,
161  &CAudioDeviceVolumeSetupComponent::onAudioStopped, Qt::QueuedConnection);
162  Q_ASSERT(c);
163 
164  this->initWithAfvClient();
165  m_init = true;
166  }
167  Q_UNUSED(c)
168  }
169 
170  void CAudioDeviceVolumeSetupComponent::initWithAfvClient()
171  {
172  if (!afvClient()) { return; }
173  m_afvConnections.disconnectAll();
174 
176  CAfvClient *afv = afvClient();
177  const Qt::ConnectionType ct = Qt::QueuedConnection;
178  QMetaObject::Connection c;
179  c = connect(afv, &CAfvClient::outputVolumePeakVU, this, &CAudioDeviceVolumeSetupComponent::onOutputVU, ct);
180  Q_ASSERT(c);
181  m_afvConnections.append(c);
182  c = connect(afv, &CAfvClient::inputVolumePeakVU, this, &CAudioDeviceVolumeSetupComponent::onInputVU, ct);
183  Q_ASSERT(c);
184  m_afvConnections.append(c);
185  c = connect(afv, &CAfvClient::receivedCallsignsChanged, this,
186  &CAudioDeviceVolumeSetupComponent::onReceivingCallsignsChanged, ct);
187  Q_ASSERT(c);
188  m_afvConnections.append(c);
189  c = connect(afv, &CAfvClient::updatedFromOwnAircraftCockpit, this,
190  &CAudioDeviceVolumeSetupComponent::onUpdatedClientWithCockpitData, ct);
191  Q_ASSERT(c);
192  m_afvConnections.append(c);
193 
194  // default values for RX/TX
195  afv->setRxTx(true, true, true, false);
196 
197  QPointer<CAudioDeviceVolumeSetupComponent> myself(this);
198  c = connect(
199  afv, &CAfvClient::connectionStatusChanged, this,
200  [=](CAfvClient::ConnectionStatus status) {
201  if (!myself || !sGui || sGui->isShuttingDown()) { return; }
202  myself->setTransmitReceiveInUiFromVoiceClient();
203  Q_UNUSED(status)
204  },
205  ct);
206  Q_ASSERT(c);
207  m_afvConnections.append(c);
208 
209  this->setTransmitReceiveInUiFromVoiceClient();
210  }
211 
213 
215  {
216  const double r = ui->hs_VolumeIn->maximum() - ui->hs_VolumeIn->minimum();
217  const double tr = to - from;
218  return qRound(ui->hs_VolumeIn->value() / r * tr);
219  }
220 
222  {
223  const double r = ui->hs_VolumeOut->maximum() - ui->hs_VolumeOut->minimum();
224  const double tr = to - from;
225  return qRound(ui->hs_VolumeOut->value() / r * tr);
226  }
227 
229  {
230  const double r = ui->hs_VolumeOutCom1->maximum() - ui->hs_VolumeOutCom1->minimum();
231  const double tr = to - from;
232  return qRound(ui->hs_VolumeOutCom1->value() / r * tr);
233  }
234 
236  {
237  const double r = ui->hs_VolumeOutCom2->maximum() - ui->hs_VolumeOutCom2->minimum();
238  const double tr = to - from;
239  return qRound(ui->hs_VolumeOutCom2->value() / r * tr);
240  }
241 
242  void CAudioDeviceVolumeSetupComponent::setInValue(int value, int from, int to)
243  {
244  if (value > to) { value = to; }
245  else if (value < from) { value = from; }
246  const double r = ui->hs_VolumeIn->maximum() - ui->hs_VolumeIn->minimum();
247  const double tr = to - from;
248  ui->hs_VolumeIn->setValue(qRound(value / tr * r));
249  }
250 
251  void CAudioDeviceVolumeSetupComponent::setOutValue(int value, int from, int to)
252  {
253  if (value > to) { value = to; }
254  else if (value < from) { value = from; }
255  const double r = ui->hs_VolumeOut->maximum() - ui->hs_VolumeOut->minimum();
256  const double tr = to - from;
257  ui->hs_VolumeOut->setValue(qRound(value / tr * r));
258  }
259 
260  void CAudioDeviceVolumeSetupComponent::setOutValueCom1(int value, int from, int to)
261  {
262  if (value > to) { value = to; }
263  else if (value < from) { value = from; }
264  const double r = ui->hs_VolumeOutCom1->maximum() - ui->hs_VolumeOutCom1->minimum();
265  const double tr = to - from;
266  ui->hs_VolumeOutCom1->setValue(qRound(value / tr * r));
267  }
268 
269  void CAudioDeviceVolumeSetupComponent::setOutValueCom2(int value, int from, int to)
270  {
271  if (value > to) { value = to; }
272  else if (value < from) { value = from; }
273  const double r = ui->hs_VolumeOutCom2->maximum() - ui->hs_VolumeOutCom2->minimum();
274  const double tr = to - from;
275  ui->hs_VolumeOutCom2->setValue(qRound(value / tr * r));
276  }
277 
279  {
280  if (value > 1.0) { value = 1.0; }
281  else if (value < 0.0) { value = 0.0; }
282  ui->wip_InLevelMeter->levelChanged(value);
283  }
284 
286  {
287  if (value > 1.0) { value = 1.0; }
288  else if (value < 0.0) { value = 0.0; }
289  ui->wip_OutLevelMeter->levelChanged(value);
290  }
291 
293  {
294  ui->le_Info->setText(info);
295  ui->le_Info->setToolTip(info);
296  }
297 
298  void CAudioDeviceVolumeSetupComponent::setTransmitReceiveInUi(bool tx1, bool rec1, bool tx2, bool rec2,
299  bool integrated)
300  {
301  this->setRxTxCheckboxes(rec1, tx1, rec2, tx2);
302  this->setCheckBoxesReadOnly(integrated);
303  this->setVolumeSlidersReadOnly(integrated);
304  }
305 
306  void CAudioDeviceVolumeSetupComponent::setTransmitReceiveInUiFromVoiceClient()
307  {
308  if (!this->hasAudio())
309  {
310  ui->led_AudioConnected->setOn(false);
311  return;
312  }
313 
314  const bool on = sGui->getCContextAudioBase()->isAudioConnected();
315  ui->led_AudioConnected->setOn(on);
316 
317  const bool com1Enabled = sGui->getCContextAudioBase()->isEnabledComUnit(CComSystem::Com1);
318  const bool com2Enabled = sGui->getCContextAudioBase()->isEnabledComUnit(CComSystem::Com2);
319 
320  const bool com1Tx = com1Enabled && sGui->getCContextAudioBase()->isTransmittingComUnit(CComSystem::Com1);
321  const bool com2Tx = com2Enabled && sGui->getCContextAudioBase()->isTransmittingComUnit(CComSystem::Com2);
322 
323  // we do not have receiving, so we use enable
324  const bool com1Rx = com1Enabled;
325  const bool com2Rx = com2Enabled;
326 
327  const bool integrated = this->isComIntegrated();
328  this->setTransmitReceiveInUi(com1Tx, com1Rx, com2Tx, com2Rx, integrated);
329 
330  // Set transmit volume in GUI
331  if (integrated)
332  {
333  const int vol1 = sGui->getCContextAudioBase()->getComOutputVolume(CComSystem::Com1);
334  const int vol2 = sGui->getCContextAudioBase()->getComOutputVolume(CComSystem::Com2);
335  ui->hs_VolumeOutCom1->setValue(vol1);
336  ui->hs_VolumeOutCom2->setValue(vol2);
337  }
338  }
339 
340  void CAudioDeviceVolumeSetupComponent::setCheckBoxesReadOnly(bool readonly)
341  {
342  // all tx/rec checkboxes
343  CGuiUtility::checkBoxReadOnly(ui->cb_1Tx, readonly);
344  CGuiUtility::checkBoxReadOnly(ui->cb_2Tx, readonly);
345  CGuiUtility::checkBoxReadOnly(ui->cb_1Rec, readonly);
346  CGuiUtility::checkBoxReadOnly(ui->cb_2Rec, readonly);
347  }
348 
349  void CAudioDeviceVolumeSetupComponent::setVolumeSlidersReadOnly(bool readonly)
350  {
351  ui->hs_VolumeOutCom1->setDisabled(readonly);
352  ui->hs_VolumeOutCom2->setDisabled(readonly);
353  if (readonly)
354  {
355  // \fixme hardcoded stylesheet setting, should come from stylesheet")
356  ui->hs_VolumeOutCom1->setStyleSheet("background: rgb(40,40,40)");
357  ui->hs_VolumeOutCom2->setStyleSheet("background: rgb(40,40,40)");
358  }
359  else
360  {
361  ui->hs_VolumeOutCom1->setStyleSheet("");
362  ui->hs_VolumeOutCom2->setStyleSheet("");
363  }
364  }
365 
366  CAfvClient *CAudioDeviceVolumeSetupComponent::afvClient()
367  {
368  if (!sGui || sGui->isShuttingDown() || !sGui->getCContextAudioBase()) { return nullptr; }
369  return sGui->getCContextAudioBase()->afvClient();
370  }
371 
372  void CAudioDeviceVolumeSetupComponent::reloadSettings()
373  {
374  const CSettings as(m_audioSettings.getThreadLocal());
375  ui->cb_DisableAudioEffects->setChecked(!as.isAudioEffectsEnabled());
376  this->setInValue(as.getInVolume());
377  this->setOutValue(as.getOutVolume());
378  this->setOutValueCom1(as.getOutVolumeCom1());
379  this->setOutValueCom2(as.getOutVolumeCom2());
380  }
381 
382  void CAudioDeviceVolumeSetupComponent::initAudioDeviceLists()
383  {
384  if (!this->hasAudio()) { return; }
385  const bool changed = this->onAudioDevicesChanged(sGui->getCContextAudioBase()->getAudioDevices());
386  if (!changed) { return; }
388  this->onAudioStarted(currentDevices.getInputDevices().frontOrDefault(),
389  currentDevices.getOutputDevices().frontOrDefault());
390  }
391 
392  bool CAudioDeviceVolumeSetupComponent::hasAudio() const { return sGui && sGui->getCContextAudioBase(); }
393 
394  bool CAudioDeviceVolumeSetupComponent::hasSimulator() const { return sGui && sGui->getIContextSimulator(); }
395 
396  void CAudioDeviceVolumeSetupComponent::onVolumeSliderChanged(int v)
397  {
398  Q_UNUSED(v)
399  m_volumeSliderChanged.inputSignal();
400  }
401 
402  void CAudioDeviceVolumeSetupComponent::saveVolumes()
403  {
404  CSettings as(m_audioSettings.getThreadLocal());
405  const int i = this->getInValue();
406  const int o = this->getOutValue();
407  const int o1 = this->getOutValueCom1();
408  const int o2 = this->getOutValueCom2();
409  if (as.getInVolume() == i && o == as.getOutVolume() && as.getOutVolumeCom1() == o1 &&
410  as.getOutVolumeCom2() == o2)
411  {
412  return;
413  }
414  as.setInVolume(i);
415  as.setOutVolume(o);
416  as.setOutVolumeCom1(o1);
417  as.setOutVolumeCom2(o2);
418  m_audioSettings.setAndSave(as);
419  }
420 
421  void CAudioDeviceVolumeSetupComponent::onOutputVU(double vu) { this->setOutLevel(vu); }
422 
423  void CAudioDeviceVolumeSetupComponent::onInputVU(double vu) { this->setInLevel(vu); }
424 
425  void CAudioDeviceVolumeSetupComponent::onReloadDevices()
426  {
427  if (!hasAudio()) { return; }
428  this->initAudioDeviceLists();
429  const CAudioDeviceInfo i = this->getSelectedInputDevice();
430  const CAudioDeviceInfo o = this->getSelectedOutputDevice();
432  }
433 
434  void CAudioDeviceVolumeSetupComponent::onResetVolumeIn()
435  {
436  ui->hs_VolumeIn->setValue((ui->hs_VolumeIn->maximum() - ui->hs_VolumeIn->minimum()) / 2);
437  }
438 
439  void CAudioDeviceVolumeSetupComponent::onResetVolumeOut()
440  {
441  ui->hs_VolumeOut->setValue((ui->hs_VolumeOut->maximum() - ui->hs_VolumeOut->minimum()) / 2);
442  }
443 
444  void CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom1()
445  {
446  ui->hs_VolumeOutCom1->setValue(ui->hs_VolumeOutCom1->maximum());
447  }
448 
449  void CAudioDeviceVolumeSetupComponent::onResetVolumeOutCom2()
450  {
451  ui->hs_VolumeOutCom2->setValue(ui->hs_VolumeOutCom2->maximum());
452  }
453 
454  void CAudioDeviceVolumeSetupComponent::setAudioRunsWhere()
455  {
456  if (!this->hasAudio()) { return; }
457  const QString ai = sGui->getCContextAudioBase()->audioRunsWhereInfo();
458  ui->le_Info->setPlaceholderText(ai);
459  }
460 
461  void CAudioDeviceVolumeSetupComponent::simulatorSettingsChanged()
462  {
463  const bool integrated = this->isComIntegrated();
464  setCheckBoxesReadOnly(integrated);
465  setVolumeSlidersReadOnly(integrated);
466  }
467 
468  bool CAudioDeviceVolumeSetupComponent::isComIntegrated() const
469  {
470  if (!this->hasSimulator()) { return false; }
472  const bool integrate = settings.isComIntegrated();
473  return integrate;
474  }
475 
476  void CAudioDeviceVolumeSetupComponent::onRxTxChanged(bool checked)
477  {
478  if (!this->hasAudio()) { return; }
479  if (this->isComIntegrated()) { return; }
480 
481  Q_UNUSED(checked)
482  const bool rx1 = ui->cb_1Rec->isChecked();
483  const bool rx2 = ui->cb_2Rec->isChecked();
484 
485  // no transmit without receiving
486  const bool tx1 = rx1 && ui->cb_1Tx->isChecked();
487  const bool tx2 = rx2 && ui->cb_2Tx->isChecked();
488 
489  sGui->getCContextAudioBase()->setRxTx(rx1, tx1, rx2, tx2);
490 
491  QPointer<CAudioDeviceVolumeSetupComponent> myself(this);
492  QTimer::singleShot(25, this, [=] {
493  // in case UI values are not correct
494  if (!myself) { return; }
495  this->setRxTxCheckboxes(rx1, tx1, rx2, tx2);
496  });
497  }
498 
499  void CAudioDeviceVolumeSetupComponent::setRxTxCheckboxes(bool rx1, bool tx1, bool rx2, bool tx2)
500  {
501  if (ui->cb_1Tx->isChecked() != tx1) { ui->cb_1Tx->setChecked(tx1); }
502  if (ui->cb_2Tx->isChecked() != tx2) { ui->cb_2Tx->setChecked(tx2); }
503  if (ui->cb_1Rec->isChecked() != rx1) { ui->cb_1Rec->setChecked(rx1); }
504  if (ui->cb_2Rec->isChecked() != rx2) { ui->cb_2Rec->setChecked(rx2); }
505  }
506 
507  void CAudioDeviceVolumeSetupComponent::onReceivingCallsignsChanged(const CCallsignSet &com1Callsigns,
508  const CCallsignSet &com2Callsigns)
509  {
510  const QString info =
511  (com1Callsigns.isEmpty() ? QString() : QStringLiteral("COM1: ") % com1Callsigns.getCallsignsAsString()) %
512  (!com1Callsigns.isEmpty() && !com2Callsigns.isEmpty() ? QStringLiteral(" | ") : QString()) %
513  (com2Callsigns.isEmpty() ? QString() : QStringLiteral("COM2: ") % com2Callsigns.getCallsignsAsString());
514 
515  ui->led_Rx1->setOn(!com1Callsigns.isEmpty());
516  ui->led_Rx2->setOn(!com2Callsigns.isEmpty());
517  this->setInfo(info);
518  }
519 
520  void CAudioDeviceVolumeSetupComponent::onUpdatedClientWithCockpitData()
521  {
522  this->setTransmitReceiveInUiFromVoiceClient();
523  }
524 
525  CAudioDeviceInfo CAudioDeviceVolumeSetupComponent::getSelectedInputDevice() const
526  {
527  if (!hasAudio()) { return CAudioDeviceInfo(); }
529  return devices.findByName(ui->cb_SetupAudioInputDevice->currentText());
530  }
531 
532  CAudioDeviceInfo CAudioDeviceVolumeSetupComponent::getSelectedOutputDevice() const
533  {
534  if (!hasAudio()) { return CAudioDeviceInfo(); }
536  return devices.findByName(ui->cb_SetupAudioOutputDevice->currentText());
537  }
538 
539  void CAudioDeviceVolumeSetupComponent::onAudioDeviceSelected(int index)
540  {
541  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextAudio()) { return; }
542  if (index < 0) { return; }
543 
544  const CAudioDeviceInfo in = this->getSelectedInputDevice();
545  const CAudioDeviceInfo out = this->getSelectedOutputDevice();
547  }
548 
549  void CAudioDeviceVolumeSetupComponent::onAudioStarted(const CAudioDeviceInfo &input, const CAudioDeviceInfo &output)
550  {
551  if (!afvClient()) { return; }
552  if (m_afvConnections.isEmpty() && m_init) { this->initWithAfvClient(); }
553 
554  ui->cb_SetupAudioInputDevice->setCurrentText(input.toQString(true));
555  ui->cb_SetupAudioOutputDevice->setCurrentText(output.toQString(true));
556  this->setAudioRunsWhere();
557  }
558 
559  void CAudioDeviceVolumeSetupComponent::onAudioStopped()
560  {
561  this->setAudioRunsWhere();
562  if (!afvClient()) { m_afvConnections.disconnectAll(); }
563  }
564 
565  bool CAudioDeviceVolumeSetupComponent::onAudioDevicesChanged(const CAudioDeviceInfoList &devices)
566  {
567  if (m_cbDevices.hasSameDevices(devices)) { return false; } // avoid numerous follow up actions
568  m_cbDevices = devices;
569 
570  this->setAudioRunsWhere();
571  ui->cb_SetupAudioOutputDevice->clear();
572  ui->cb_SetupAudioInputDevice->clear();
573 
574  const QString i = ui->cb_SetupAudioInputDevice->currentText();
575  const QString o = ui->cb_SetupAudioOutputDevice->currentText();
576 
577  for (const CAudioDeviceInfo &device : devices)
578  {
579  if (device.getType() == CAudioDeviceInfo::InputDevice)
580  {
581  ui->cb_SetupAudioInputDevice->addItem(device.toQString(true));
582  }
583  else if (device.getType() == CAudioDeviceInfo::OutputDevice)
584  {
585  ui->cb_SetupAudioOutputDevice->addItem(device.toQString(true));
586  }
587  }
588 
589  if (!i.isEmpty()) { ui->cb_SetupAudioInputDevice->setCurrentText(i); }
590  if (!o.isEmpty()) { ui->cb_SetupAudioOutputDevice->setCurrentText(o); }
591 
592  return true;
593  }
594 
595  void CAudioDeviceVolumeSetupComponent::onLoopbackToggled(bool loopback)
596  {
597  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextAudio()) { return; }
598  if (sGui->getCContextAudioBase()->isAudioLoopbackEnabled() == loopback) { return; }
600  }
601 
602  void CAudioDeviceVolumeSetupComponent::onDisableAudioEffectsToggled(bool disabled)
603  {
604  if (!sGui || sGui->isShuttingDown() || !sGui->getIContextAudio()) { return; }
605  CSettings as(m_audioSettings.getThreadLocal());
606  const bool enabled = !disabled;
607  if (as.isAudioEffectsEnabled() == enabled) { return; }
608  as.setAudioEffectsEnabled(enabled);
609  m_audioSettings.setAndSave(as);
610  }
611 } // 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:601
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 isEmpty() const
Synonym for empty.
Definition: collection.h:191
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 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:13
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30