swift
Loading...
Searching...
No Matches
contextaudio.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
10#include "core/context/contextnetwork.h" // for user login
11#include "core/context/contextownaircraft.h" // for COM integration
12#include "core/context/contextsimulator.h" // for COM intergration
13#include "misc/dbusserver.h"
14#include "misc/icons.h"
16#include "misc/stringutils.h"
17#include "misc/verify.h"
18
19#ifdef Q_OS_WIN
20# include "comdef.h"
21#endif
22
23using namespace swift::misc;
24using namespace swift::misc::aviation;
25using namespace swift::misc::audio;
26using namespace swift::misc::network;
27using namespace swift::misc::physical_quantities;
28using namespace swift::misc::simulation;
29using namespace swift::sound;
30using namespace swift::core::afv::clients;
31
33
34namespace swift::core::context
35{
36 IContextAudio::IContextAudio(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime) : IContext(mode, runtime)
37 {
38 // void
39 }
40
41 void IContextAudio::onChangedLocalDevices(const CAudioDeviceInfoList &devices) { this->registerDevices(devices); }
42
43 const QString &IContextAudio::InterfaceName()
44 {
46 return s;
47 }
48
49 const QString &IContextAudio::ObjectPath()
50 {
52 return s;
53 }
54
55 IContextAudio *IContextAudio::create(CCoreFacade *runtime, CCoreFacadeConfig::ContextMode mode, CDBusServer *server,
56 QDBusConnection &connection)
57 {
58 // for audio no empty context is available
59 // since CContextAudioBaseImpl provides audio on either side (core/GUI) we do not use ContextAudioEmpty
60 // ContextAudioEmpty would cause issue, as it is initializing "common parts" during shutdown
61 switch (mode)
62 {
63 case CCoreFacadeConfig::Local: return new CContextAudio(mode, runtime);
65 {
66 auto *context = new CContextAudio(mode, runtime);
67 context->registerWithDBus(ObjectPath(), server);
68 return context;
69 }
71 return new CContextAudioProxy(CDBusServer::coreServiceName(connection), connection, mode, runtime);
73 SWIFT_VERIFY_X(false, Q_FUNC_INFO, "Empty context not supported for audio (since AFV)");
74 return nullptr;
75 default: SWIFT_VERIFY_X(false, Q_FUNC_INFO, "Unknown context mode"); return nullptr;
76 }
77 }
78
79 bool CContextAudioBase::parseCommandLine(const QString &commandLine, const CIdentifier &originator)
80 {
81 Q_UNUSED(originator)
82 if (commandLine.isEmpty())
83 {
84 return false;
85 }
87 ".vol",
88 ".volume", // output volume
89 ".mute", // mute
90 ".unmute", // unmute
91 });
92 parser.parse(commandLine);
93 if (!parser.isKnownCommand())
94 {
95 return false;
96 }
97
98 if (parser.matchesCommand(".mute"))
99 {
100 this->setOutputMute(true);
101 return true;
102 }
103 else if (parser.matchesCommand(".unmute"))
104 {
105 this->setOutputMute(false);
106 return true;
107 }
108 else if (parser.commandStartsWith("vol") && parser.countParts() > 1)
109 {
110 const int v = parser.toInt(1);
111 this->setMasterOutputVolume(v);
112 return true;
113 }
114 return false;
115 }
116
117 CContextAudioBase::CContextAudioBase(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime)
118 : IContextAudio(mode, runtime), CIdentifiable(this)
119 {
120 CContextAudioBase::registerHelp();
121
122 if (CContextAudioBase::isNoAudioSet())
123 {
124 CLogMessage(this).info(u"Voice client disabled");
125 }
126 else
127 {
128 this->initVoiceClient();
129 }
130
131 // here we are in a base class of one context
132 // the whole context/facade system is not initialized when this code here is executed
133
134 QPointer<CContextAudioBase> myself(this);
135 QTimer::singleShot(5000, this, [=, this] {
136 if (!myself || !sApp || sApp->isShuttingDown())
137 {
138 return;
139 }
140
141 const CSettings as = m_audioSettings.getThreadLocal();
142 this->setMasterOutputVolume(as.getOutVolume());
143 this->setComOutputVolume(CComSystem::Com1, as.getOutVolumeCom1());
144 this->setComOutputVolume(CComSystem::Com2, as.getOutVolumeCom2());
145 m_selcalPlayer = new CSelcalPlayer(CAudioDeviceInfo::getDefaultOutputDevice(), this);
146
147 myself->changeDeviceSettings();
148 myself->onChangedAudioSettings();
149 myself->onChangedLocalDevices(m_activeLocalDevices);
150 });
151 }
152
153 CContextAudioBase::~CContextAudioBase() { this->gracefulShutdown(); }
154
155 void CContextAudioBase::initVoiceClient()
156 {
157 if (m_voiceClient || !sApp)
158 {
159 return;
160 }
161
163 if (devices != m_activeLocalDevices)
164 {
165 m_activeLocalDevices = devices;
166 emit this->changedLocalAudioDevices(devices);
167 }
168
169#ifdef Q_OS_WIN
170 if (!m_winCoInitialized)
171 {
172 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
173
174 // RPC_E_CHANGED_MODE: CoInitializeEx was already called by someone else in this thread with a different
175 // mode.
176 if (hr == RPC_E_CHANGED_MODE)
177 {
178 CLogMessage(this).debug(u"CoInitializeEx was already called with a different mode. Trying again.");
179 hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
180 }
181
182 // S_OK: The COM library was initialized successfully on this thread.
183 // S_FALSE: The COM library is already initialized on this thread. Reference count was incremented. This is
184 // not an error.
185 if (hr == S_OK || hr == S_FALSE)
186 {
187 m_winCoInitialized = true;
188 }
189 }
190#endif
191
192 m_voiceClient = new CAfvClient(sApp->getGlobalSetup().getAfvApiServerUrl().toQString(), this);
193
194 Q_ASSERT_X(m_voiceClient->thread() == qApp->thread(), Q_FUNC_INFO, "Should be in main thread");
195 m_voiceClient->start(); // thread
196 Q_ASSERT_X(m_voiceClient->owner() == this, Q_FUNC_INFO, "Wrong owner");
197 Q_ASSERT_X(m_voiceClient->thread() != qApp->thread(), Q_FUNC_INFO, "Must NOT be in main thread");
198
199 // connect(m_voiceClient, &CAfvClient::outputVolumePeakVU, this,
200 // &CContextAudioBase::outputVolumePeakVU, Qt::QueuedConnection); connect(m_voiceClient,
201 // &CAfvClient::inputVolumePeakVU, this, &CContextAudioBase::inputVolumePeakVU,
202 // Qt::QueuedConnection); connect(m_voiceClient, &CAfvClient::receivingCallsignsChanged, this,
203 // &CContextAudioBase::receivingCallsignsChanged, Qt::QueuedConnection); connect(m_voiceClient,
204 // &CAfvClient::updatedFromOwnAircraftCockpit, this, &CContextAudioBase::updatedFromOwnAircraftCockpit,
205 // Qt::QueuedConnection);
206 connect(m_voiceClient, &CAfvClient::startedAudio, this, &CContextAudioBase::startedAudio, Qt::QueuedConnection);
207 connect(m_voiceClient, &CAfvClient::stoppedAudio, this, &CContextAudioBase::stoppedAudio, Qt::QueuedConnection);
208 connect(m_voiceClient, &CAfvClient::ptt, this, &CContextAudioBase::ptt, Qt::QueuedConnection);
209 connect(m_voiceClient, &CAfvClient::changedOutputMute, this, &CContextAudioBase::changedOutputMute,
211 connect(m_voiceClient, &CAfvClient::connectionStatusChanged, this,
212 &CContextAudioBase::onAfvConnectionStatusChanged, Qt::QueuedConnection);
213 connect(m_voiceClient, &CAfvClient::afvConnectionFailure, this, &CContextAudioBase::onAfvConnectionFailure,
215 }
216
217 void CContextAudioBase::terminateVoiceClient()
218 {
219 if (m_voiceClient)
220 {
221 m_voiceClient->gracefulShutdown();
222 Q_ASSERT_X(CThreadUtils::isInThisThread(m_voiceClient), Q_FUNC_INFO, "Needs to be back in current thread");
223 m_voiceClient->deleteLater();
224 m_voiceClient = nullptr;
225#ifdef Q_OS_WIN
226 if (m_winCoInitialized)
227 {
228 CoUninitialize();
229 m_winCoInitialized = false;
230 }
231#endif
232 }
233 }
234
235 void CContextAudioBase::gracefulShutdown()
236 {
237 this->terminateVoiceClient();
238 if (m_selcalPlayer)
239 {
240 m_selcalPlayer->gracefulShutdown();
241 m_selcalPlayer = nullptr;
242 }
244 }
245
246 void CContextAudioBase::setRxTx(bool rx1, bool tx1, bool rx2, bool tx2)
247 {
248 if (m_voiceClient)
249 {
250 m_voiceClient->setRxTx(rx1, tx1, rx2, tx2);
251 }
252 }
253
254 void CContextAudioBase::getRxTx(bool &rx1, bool &tx1, bool &rx2, bool &tx2) const
255 {
256 if (m_voiceClient)
257 {
258 m_voiceClient->setRxTx(rx1, tx1, rx2, tx2);
259 }
260 }
261
262 const CIdentifier &CContextAudioBase::audioRunsWhere() const
263 {
264 static const CIdentifier i("CContextAudioBaseImpl");
265 return i;
266 }
267
268 bool CContextAudioBase::isEnabledComUnit(CComSystem::ComUnit comUnit) const
269 {
270 if (!m_voiceClient)
271 {
272 return false;
273 }
274 return m_voiceClient->isEnabledComUnit(comUnit);
275 }
276
277 bool CContextAudioBase::isTransmittingComUnit(CComSystem::ComUnit comUnit) const
278 {
279 if (!m_voiceClient)
280 {
281 return false;
282 }
283 return m_voiceClient->isTransmittingComUnit(comUnit);
284 }
285
286 bool CContextAudioBase::connectAudioWithNetworkCredentials()
287 {
288 if (!m_voiceClient)
289 {
290 return false;
291 }
292 if (!sApp || sApp->isShuttingDown() || !sApp->getIContextNetwork())
293 {
294 return false;
295 }
296
297 const CEcosystem ecoSystem = this->getIContextNetwork()->getConnectedServer().getEcosystem();
298 if (ecoSystem != CEcosystem::vatsim())
299 {
300 CLogMessage(this).info(u"Will not use AFV as ecosystem is '%1'") << ecoSystem.toQString(true);
301 return false;
302 }
303
304 const CUser connectedUser = this->getIContextNetwork()->getConnectedServer().getUser();
306 CCallsign cs = connectedUser.getCallsign();
307 this->unRegisterAudioCallsign(cs, this->identifier()); // un-register "myself"
308 if (this->hasRegisteredAudioCallsign(cs)) // anybody else using that callsign
309 {
311 cs = CCallsign(cs.asString() + "2");
312 }
313 CLogMessage(this).info(u"About to connect to voice as '%1' '%2'") << connectedUser.getId() << cs;
314 m_voiceClient->connectTo(connectedUser.getId(), connectedUser.getPassword(), cs.asString(), client);
315 this->registerAudioCallsign(cs, this->identifier()); // login can still fail, but we "block" this callsign
316 return true;
317 }
318
319 bool CContextAudioBase::isAudioConnected() const { return m_voiceClient && m_voiceClient->isConnected(); }
320
321 bool CContextAudioBase::isAudioStarted() const { return m_voiceClient && m_voiceClient->isStarted(); }
322
323 bool CContextAudioBase::isComUnitIntegrated() const
324 {
325 return m_voiceClient && m_voiceClient->isComUnitIntegrated();
326 }
327
328 const QList<QCommandLineOption> &CContextAudioBase::getCmdLineOptions()
329 {
331 { { "n", "noaudio" },
332 QCoreApplication::translate("CContextAudioBase", "No audio for GUI or core.", "noaudio") }) };
333 return opts;
334 }
335
336 bool CContextAudioBase::isNoAudioSet()
337 {
338 if (!sApp)
339 {
340 return false;
341 }
342 return sApp->isParserOptionSet("noaudio");
343 }
344
345 QString CContextAudioBase::audioRunsWhereInfo() const
346 {
347 const QString s = QStringLiteral("[%1] Audio on '%2', '%3'.")
348 .arg(boolToEnabledDisabled(this->isAudioStarted()), audioRunsWhere().getMachineName(),
349 audioRunsWhere().getProcessName());
350 return s;
351 }
352
353 CAudioDeviceInfoList CContextAudioBase::getAudioDevices() const { return CAudioDeviceInfoList::allDevices(); }
354
355 CAudioDeviceInfoList CContextAudioBase::getAudioInputDevices() const
356 {
357 return this->getAudioDevices().getInputDevices();
358 }
359
360 CAudioDeviceInfoList CContextAudioBase::getAudioOutputDevices() const
361 {
362 return this->getAudioDevices().getOutputDevices();
363 }
364
365 CAudioDeviceInfoList CContextAudioBase::getCurrentAudioDevices() const
366 {
367 const QString inputDeviceName = m_inputDeviceSetting.get();
368 const CAudioDeviceInfo inputDevice = this->getAudioInputDevices().findByNameOrDefault(
369 inputDeviceName, CAudioDeviceInfo::getDefaultInputDevice());
370
371 const QString outputDeviceName = m_outputDeviceSetting.get();
372 const CAudioDeviceInfo outputDevice = this->getAudioOutputDevices().findByNameOrDefault(
373 outputDeviceName, CAudioDeviceInfo::getDefaultOutputDevice());
374
375 CAudioDeviceInfoList devices;
376 devices.push_back(inputDevice);
377 devices.push_back(outputDevice);
378 return devices;
379 }
380
381 void CContextAudioBase::setCurrentAudioDevices(const CAudioDeviceInfo &inputDevice,
382 const CAudioDeviceInfo &outputDevice)
383 {
384 if (!m_voiceClient)
385 {
386 return;
387 }
388 if (!sApp)
389 {
390 return;
391 }
392
393 if (!inputDevice.getName().isEmpty() && inputDevice.getName() != m_inputDeviceSetting.get())
394 {
395 Q_ASSERT_X(inputDevice.isInputDevice(), Q_FUNC_INFO, "Need input device");
396 const CStatusMessage m = m_inputDeviceSetting.setAndSave(inputDevice.getName());
398 }
399 if (!outputDevice.getName().isEmpty() && outputDevice.getName() != m_outputDeviceSetting.get())
400 {
401 Q_ASSERT_X(outputDevice.isOutputDevice(), Q_FUNC_INFO, "Need output device");
402 const CStatusMessage m = m_outputDeviceSetting.setAndSave(outputDevice.getName());
404 }
405
406 m_voiceClient->startAudio(inputDevice, outputDevice);
407 }
408
409 void CContextAudioBase::setMasterOutputVolume(int volume)
410 {
411 if (!m_voiceClient)
412 {
413 return;
414 }
415
416 const bool wasMuted = this->isOutputMuted();
417 volume = CSettings::fixOutVolume(volume);
418
419 const int currentVolume = m_voiceClient->getNormalizedMasterOutputVolume();
420 const bool changedVoiceOutput = (currentVolume != volume);
421 if (changedVoiceOutput)
422 {
423 // TODO: KB 2020-05 the mute handling should entirely go to AFV client!
424 m_voiceClient->setNormalizedMasterOutputVolume(volume);
425 m_outMasterVolumeBeforeMute = volume;
426
427 emit this->changedAudioVolume(volume);
428 if ((volume > 0 && wasMuted) || (volume < 1 && !wasMuted))
429 {
430 // inform about muted
431 emit this->changedOutputMute(volume < 1);
432 }
433 }
434
435 CSettings as(m_audioSettings.getThreadLocal());
436 if (as.getOutVolume() != volume)
437 {
438 as.setOutVolume(volume);
439 m_audioSettings.set(as);
440 }
441 }
442
443 void CContextAudioBase::setComOutputVolume(CComSystem::ComUnit comUnit, int volume)
444 {
445 if (comUnit != CComSystem::Com1 && comUnit != CComSystem::Com2)
446 {
447 return;
448 }
449 if (!m_voiceClient)
450 {
451 return;
452 }
453
454 volume = CSettings::fixOutVolume(volume);
455
456 const int currentVolume = m_voiceClient->getNormalizedComOutputVolume(comUnit);
457 const bool changedVoiceOutput = (currentVolume != volume);
458 if (changedVoiceOutput)
459 {
460 m_voiceClient->setNormalizedComOutputVolume(comUnit, volume);
461 emit this->changedAudioVolume(volume);
462 }
463
464 CSettings as(m_audioSettings.getThreadLocal());
465 if (comUnit == CComSystem::Com1 && as.getOutVolumeCom1() != volume)
466 {
467 as.setOutVolumeCom1(volume);
468 m_audioSettings.set(as);
469 }
470 else if (comUnit == CComSystem::Com2 && as.getOutVolumeCom2() != volume)
471 {
472 as.setOutVolumeCom2(volume);
473 m_audioSettings.set(as);
474 }
475 }
476
477 int CContextAudioBase::getMasterOutputVolume() const
478 {
479 if (!m_voiceClient)
480 {
481 return 0;
482 }
483 return m_voiceClient->getNormalizedMasterOutputVolume();
484 }
485
486 int CContextAudioBase::getComOutputVolume(CComSystem::ComUnit comUnit) const
487 {
488 if (!m_voiceClient)
489 {
490 return 0;
491 }
492 return m_voiceClient->getNormalizedComOutputVolume(comUnit);
493 }
494
495 void CContextAudioBase::setOutputMute(bool muted)
496 {
497 if (!m_voiceClient)
498 {
499 return;
500 }
501 if (this->isOutputMuted() == muted)
502 {
503 return;
504 } // avoid roundtrips / unnecessary signals
505
506 if (muted)
507 {
508 m_outMasterVolumeBeforeMute = m_voiceClient->getNormalizedMasterOutputVolume();
509 }
510
511 m_voiceClient->setOutputMuted(muted);
512 if (!muted)
513 {
514 m_voiceClient->setNormalizedMasterOutputVolume(m_outMasterVolumeBeforeMute);
515 }
516 }
517
518 bool CContextAudioBase::isOutputMuted() const
519 {
520 if (!m_voiceClient)
521 {
522 return false;
523 }
524 return m_voiceClient->isOutputMuted();
525 }
526
527 void CContextAudioBase::playSelcalTone(const CSelcal &selcal)
528 {
529 using namespace std::chrono_literals;
530 const std::chrono::milliseconds ms = m_selcalPlayer->play(90, selcal);
531 if (ms > 10ms)
532 {
533 // Play additional notification
534 const QPointer<const CContextAudioBase> myself(this);
535 QTimer::singleShot(ms, this, [=, this] {
536 if (!sApp || sApp->isShuttingDown() || !myself)
537 {
538 return;
539 }
540 this->playNotification(CNotificationSounds::NotificationTextMessageSupervisor, true);
541 });
542 }
543 }
544
545 void CContextAudioBase::playNotification(CNotificationSounds::NotificationFlag notification, bool considerSettings,
546 int volume)
547 {
548 if (isDebugEnabled())
549 {
550 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << notification;
551 }
552
553 const CSettings settings = m_audioSettings.getThreadLocal();
554 const bool play = !considerSettings || settings.isNotificationFlagSet(notification);
555 if (!play)
556 {
557 return;
558 }
559
560 if (volume < 0 || volume > 100)
561 {
562 volume = 90;
563 if (considerSettings)
564 {
565 volume = qMax(25, settings.getNotificationVolume());
566 }
567 }
568 m_notificationPlayer.play(notification, volume);
569 }
570
571 void CContextAudioBase::enableAudioLoopback(bool enable)
572 {
573 if (!m_voiceClient)
574 {
575 return;
576 }
577 m_voiceClient->setLoopBack(enable);
578 }
579
580 bool CContextAudioBase::isAudioLoopbackEnabled() const
581 {
582 if (!m_voiceClient)
583 {
584 return false;
585 }
586 return m_voiceClient->isLoopback();
587 }
588
589 void CContextAudioBase::setVoiceTransmission(bool enable)
590 {
591 if (!m_voiceClient)
592 {
593 return;
594 }
595 m_voiceClient->setPtt(enable);
596 }
597
598 void CContextAudioBase::changeDeviceSettings()
599 {
600 const CAudioDeviceInfoList devices = this->getCurrentAudioDevices();
601 Q_ASSERT_X(devices.size() == 2, Q_FUNC_INFO, "Expect INPUT and OUTPUT device");
602
603 const CAudioDeviceInfo input = devices.front();
604 const CAudioDeviceInfo output = devices.back();
605 this->setCurrentAudioDevices(input, output);
606 }
607
608 void CContextAudioBase::onChangedAudioSettings()
609 {
610 const CSettings s = m_audioSettings.get();
612 m_notificationPlayer.updateDirectory(dir);
613 this->setMasterOutputVolume(s.getOutVolume());
614 this->setComOutputVolume(CComSystem::Com1, s.getOutVolumeCom1());
615 this->setComOutputVolume(CComSystem::Com2, s.getOutVolumeCom2());
616 }
617
618 void CContextAudioBase::audioIncreaseVolume(bool enabled)
619 {
620 if (!enabled)
621 {
622 return;
623 }
624 const int v = qRound(this->getMasterOutputVolume() * 1.05);
625 this->setMasterOutputVolume(v);
626 }
627
628 void CContextAudioBase::audioDecreaseVolume(bool enabled)
629 {
630 if (!enabled)
631 {
632 return;
633 }
634 const int v = qRound(this->getMasterOutputVolume() / 1.05);
635 this->setMasterOutputVolume(v);
636 }
637
638 void CContextAudioBase::audioIncreaseVolumeCom1(bool enabled)
639 {
640 if (!enabled)
641 {
642 return;
643 }
644 if (isComUnitIntegrated())
645 {
646 return;
647 }
648 const int v = qRound(this->getComOutputVolume(CComSystem::Com1) * 1.05);
649 this->setComOutputVolume(CComSystem::Com1, v);
650 }
651
652 void CContextAudioBase::audioDecreaseVolumeCom1(bool enabled)
653 {
654 if (!enabled)
655 {
656 return;
657 }
658 if (isComUnitIntegrated())
659 {
660 return;
661 }
662 const int v = qRound(this->getComOutputVolume(CComSystem::Com1) / 1.05);
663 this->setComOutputVolume(CComSystem::Com1, v);
664 }
665
666 void CContextAudioBase::audioIncreaseVolumeCom2(bool enabled)
667 {
668 if (!enabled)
669 {
670 return;
671 }
672 if (isComUnitIntegrated())
673 {
674 return;
675 }
676 const int v = qRound(this->getComOutputVolume(CComSystem::Com2) * 1.05);
677 this->setComOutputVolume(CComSystem::Com2, v);
678 }
679
680 void CContextAudioBase::audioDecreaseVolumeCom2(bool enabled)
681 {
682 if (!enabled)
683 {
684 return;
685 }
686 if (isComUnitIntegrated())
687 {
688 return;
689 }
690 const int v = qRound(this->getComOutputVolume(CComSystem::Com2) / 1.05);
691 this->setComOutputVolume(CComSystem::Com2, v);
692 }
693
694 void CContextAudioBase::xCtxNetworkConnectionStatusChanged(const CConnectionStatus &from,
695 const CConnectionStatus &to)
696 {
697 if (!m_voiceClient)
698 {
699 return;
700 }
701
702 Q_UNUSED(from)
703 SWIFT_VERIFY_X(this->getIContextNetwork(), Q_FUNC_INFO, "Missing network context");
704
705 // we only change network connection of AFV client here
706 if (to.isConnected() && this->getIContextNetwork())
707 {
708 const bool connected = this->connectAudioWithNetworkCredentials();
709 Q_UNUSED(connected)
710
711 // one reason for not connecting is NOT using the VATSIM ecosystem
712 }
713 else if (to.isDisconnected())
714 {
715 m_voiceClient->disconnectFrom();
716 }
717 }
718
719 void CContextAudioBase::onAfvConnectionStatusChanged(int status)
720 {
721 if (!m_voiceClient)
722 {
723 return;
724 }
725
726 const CCallsign cs = m_voiceClient->getCallsign();
727 const auto s = static_cast<CAfvClient::ConnectionStatus>(status);
728
729 switch (s)
730 {
731 case CAfvClient::Connected: this->registerAudioCallsign(cs, this->identifier()); break;
732 case CAfvClient::Disconnected: this->unRegisterAudioCallsign(cs, this->identifier()); break;
733 }
734 }
735
736 void CContextAudioBase::onAfvConnectionFailure(const CStatusMessage &msg)
737 {
738 if (!m_voiceClient)
739 {
740 return;
741 }
742 emit this->voiceClientFailure(msg);
743 }
744
745 bool CContextAudioBase::isRunningWithLocalCore() { return sApp && sApp->isLocalContext(); }
746
747} // namespace swift::core::context
748
static const QString & getShortVersionString()
Version as QVersionNumber.
ContextMode
How to handle a given context.
@ NotUsed
during shutdown or not used at all
@ Local
context runs in same process
@ Remote
context runs in a different process.
@ LocalInDBusServer
context runs in same process.
The class providing facades (the contexts) for all DBus relevant operations.
Definition corefacade.h:57
void ptt(bool active, const swift::misc::CIdentifier &identifier)
PTT status in this particular AFV client.
void changedOutputMute(bool muted)
Output mute changed.
void afvConnectionFailure(const swift::misc::CStatusMessage &msg)
Authentication has failed with AFV server.
void stoppedAudio()
Audio has been stopped.
void startedAudio(const swift::misc::audio::CAudioDeviceInfo &inputDevice, const swift::misc::audio::CAudioDeviceInfo &outputDevice)
Started audio with devices.
void connectionStatusChanged(ConnectionStatus status)
Connection status has been changed.
IContextAudio(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime)
Constructor.
Base for all context classes.
Definition context.h:34
Custom DBusServer.
Definition dbusserver.h:34
static const QString & coreServiceName()
Default service name.
Base class with a member CIdentifier to be inherited by a class which has an identity in the environm...
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition identifier.h:29
static const QString & contextSlot()
Context slots.
Class for emitting a log message.
Definition logmessage.h:27
static void preformatted(const CStatusMessage &statusMessage)
Sends a verbatim, preformatted message to the log.
Derived & debug()
Set the severity to debug.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
size_type size() const
Returns number of elements in the sequence.
Definition sequence.h:273
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition sequence.h:308
reference front()
Access the first element.
Definition sequence.h:225
reference back()
Access the last element.
Definition sequence.h:249
Utility methods for simple line parsing used with the command line.
void parse(const QString &commandLine)
Parse.
Streamable status message, e.g.
static bool isInThisThread(const QObject *toBeTested)
Is the current thread the object's thread?
Value object encapsulating information of a audio device.
static CAudioDeviceInfo getDefaultInputDevice()
Default input device.
bool isInputDevice() const
Input device.
const QString & getName() const
Get the device name.
bool isOutputDevice() const
Output device.
static CAudioDeviceInfo getDefaultOutputDevice()
Default output device.
Value object encapsulating a list of audio devices.
CAudioDeviceInfoList getOutputDevices() const
Get output devices in that list.
static CAudioDeviceInfoList allDevices()
Lists of all available devices.
CAudioDeviceInfoList getInputDevices() const
Get output devices in that list.
Value object encapsulating information of audio related settings.
int getOutVolumeCom2() const
Get volume for com2 (audio) 0..100.
const QString & getNotificationSoundDirectory() const
Notification directory.
void setOutVolume(int volume)
Set volume (audio) 0..100.
int getOutVolume() const
Get volume (audio) 0..100.
void setOutVolumeCom2(int volume)
Set volume for com2 (audio) 0..100.
int getOutVolumeCom1() const
Get volume for com1 (audio) 0..100.
void setOutVolumeCom1(int volume)
Set volume for com1 (audio) 0..100.
static int fixOutVolume(int v)
Make sure the volume is within the range.
Value object encapsulating information of a callsign.
Definition callsign.h:30
const QString & asString() const
Get callsign (normalized).
Definition callsign.h:96
Value object for SELCAL.
Definition selcal.h:31
QString toQString(bool i18n=false) const
Cast as QString.
Definition mixinstring.h:74
Value object encapsulating information about a connection status.
bool isDisconnected() const
Query status.
Ecosystem of server belonging together.
Definition ecosystem.h:21
static const CEcosystem & vatsim()
VATSIM eco system.
Definition ecosystem.cpp:26
Value object encapsulating information of a user.
Definition user.h:28
const QString & getId() const
Get id.
Definition user.h:119
const QString & getPassword() const
Get password.
Definition user.h:65
const aviation::CCallsign & getCallsign() const
Get associated callsign.
Definition user.h:140
#define SWIFT_CORE_CONTEXTAUDIO_INTERFACENAME
DBus interface for context.
#define SWIFT_CORE_CONTEXTAUDIO_OBJECTPATH
DBus object path for context.
Classes related to configuration settings.
Free functions in swift::misc.
SWIFT_MISC_EXPORT const QString & boolToEnabledDisabled(bool v)
Bool to enabled/disabled.
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
bool disconnect(const QMetaObject::Connection &connection)
QString arg(Args &&... args) const const
bool isEmpty() const const
QueuedConnection
QFuture< QtFuture::ArgsType< Signal > > connect(Sender *sender, Signal signal)
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition verify.h:26