MythTV master
setupwizard_audio.cpp
Go to the documentation of this file.
1// C++
2#include <algorithm>
3
4// Qt
5#include <QString>
6#include <QVariant>
7
8// MythTV
16
17// MythFrontend
19#include "setupwizard_audio.h"
20#include "setupwizard_general.h"
21#include "setupwizard_video.h"
22
24{
25 // Load the theme for this screen
26 bool foundtheme = LoadWindowFromXML("config-ui.xml", "audiowizard", this);
27 if (!foundtheme)
28 return false;
29
31 dynamic_cast<MythUIButtonList *> (GetChild("audiodevices"));
33 dynamic_cast<MythUIButtonList *> (GetChild("speakers"));
34
35 m_dtsCheck = dynamic_cast<MythUICheckBox *> (GetChild("dtscheck"));
36 m_ac3Check = dynamic_cast<MythUICheckBox *> (GetChild("ac3check"));
37 m_eac3Check = dynamic_cast<MythUICheckBox *> (GetChild("eac3check"));
38 m_truehdCheck = dynamic_cast<MythUICheckBox *> (GetChild("truehdcheck"));
39 m_dtshdCheck = dynamic_cast<MythUICheckBox *> (GetChild("dtshdcheck"));
40
42 dynamic_cast<MythUIButton *> (GetChild("testspeakers"));
43
44 m_nextButton = dynamic_cast<MythUIButton *> (GetChild("next"));
45 m_prevButton = dynamic_cast<MythUIButton *> (GetChild("previous"));
46
50 {
51 LOG(VB_GENERAL, LOG_ERR, "Theme is missing critical theme elements.");
52 return false;
53 }
54
55 // Pre-set the widgets to their database values
56 // Buttonlists are set in load()
57
58 int dtsSetting = gCoreContext->GetNumSetting("DTSPassThru", 0);
59 if (dtsSetting == 1)
61
62 int ac3Setting = gCoreContext->GetNumSetting("AC3PassThru", 0);
63 if (ac3Setting == 1)
65
66 int eac3Setting = gCoreContext->GetNumSetting("EAC3PassThru", 0);
67 if (eac3Setting == 1)
69
70 int truehdSetting = gCoreContext->GetNumSetting("TrueHDPassThru", 0);
71 if (truehdSetting == 1)
73
74 int dtshdSetting = gCoreContext->GetNumSetting("DTSHDPassThru", 0);
75 if (dtshdSetting == 1)
77
78 // Help Text
79
80 // Buttonlists
81 m_audioDeviceButtonList->SetHelpText( tr("Select from one of the "
82 "audio devices detected on your system. When "
83 "satisfied, you can test audio before moving "
84 "on. If you fail to configure audio, video "
85 "playback may fail as well.") );
86 m_speakerNumberButtonList->SetHelpText( tr("Select the number of speakers you "
87 "have.") );
88
89 // Checkboxes
90 m_dtsCheck->SetHelpText( tr("Select this checkbox if your receiver "
91 "is capable of playing DTS.") );
92 m_ac3Check->SetHelpText( tr("Select this checkbox if your receiver "
93 "is capable of playing AC-3 (Dolby Digital).") );
94 m_eac3Check->SetHelpText( tr("Select this checkbox if your receiver "
95 "is capable of playing E-AC-3 (Dolby Digital Plus).") );
96 m_truehdCheck->SetHelpText( tr("Select this checkbox if your receiver "
97 "is capable of playing TrueHD.") );
98 m_dtshdCheck->SetHelpText( tr("Select this checkbox if your receiver "
99 "is capable of playing DTS-HD.") );
100
101 // Buttons
102 m_testSpeakerButton->SetHelpText( tr("Test your audio settings by playing "
103 "noise through each speaker.") );
104 m_nextButton->SetHelpText( tr("Save these changes and move on to the next "
105 "configuration step.") );
106 m_prevButton->SetHelpText( tr("Return to the previous configuration step.") );
107
108 // I hate to SetText but it's the only way to make it reliably bi-modal
109 m_testSpeakerButton->SetText(tr("Test Speakers"));
110
114
115 QString message = tr("Discovering audio devices...");
116 LoadInBackground(message);
117
119
120 return true;
121}
122
124{
125 if (m_testThread)
126 {
129 delete m_testThread;
130 }
131 delete m_outputlist;
132}
133
135{
137}
138
140{
141 QString current = gCoreContext->GetSetting(QString("AudioOutputDevice"));
142 bool found = false;
143
144 if (!current.isEmpty())
145 {
146 auto samename = [current](const auto & ao){ return ao.m_name == current; };
147 found = std::any_of(m_outputlist->cbegin(), m_outputlist->cend(), samename);
148 if (!found)
149 {
152 if (adc->m_settings.IsInvalid())
153 {
154 LOG(VB_GENERAL, LOG_ERR, QString("Audio device %1 isn't usable")
155 .arg(current));
156 }
157 else
158 {
159 // only insert the device if it is valid
160 m_outputlist->insert(0, *adc);
161 }
162 delete adc;
163 }
164 }
165 for (const auto & ao : std::as_const(*m_outputlist))
166 {
167 QString name = ao.m_name;
169 output->SetData(name);
170 }
171 if (found)
172 {
173 m_audioDeviceButtonList->SetValueByData(QVariant::fromValue(current));
174 }
175
176 m_maxspeakers = gCoreContext->GetNumSetting("MaxChannels", 2);
178
179 // Update list for default audio device
181
185 this, qOverload<MythUIButtonListItem*>(&AudioSetupWizard::UpdateCapabilities));
186}
187
189{
191 int max_speakers = 8;
192 int realmax_speakers = 8;
193
194 AudioOutputSettings settings;
195
196 auto samename = [out](const auto & ao){ return ao.m_name == out; };
197 // NOLINTNEXTLINE(readability-qualified-auto) // qt6
198 const auto ao = std::find_if(m_outputlist->cbegin(), m_outputlist->cend(), samename);
199 if (ao != m_outputlist->cend())
200 settings = ao->m_settings;
201
202 realmax_speakers = max_speakers = settings.BestSupportedChannels();
203
204 bool bAC3 = settings.canFeature(FEATURE_AC3);
205 bool bDTS = settings.canFeature(FEATURE_DTS);
206 bool bLPCM = settings.canFeature(FEATURE_LPCM);
207 bool bEAC3 = settings.canFeature(FEATURE_EAC3);
208 bool bTRUEHD = settings.canFeature(FEATURE_TRUEHD);
209 bool bDTSHD = settings.canFeature(FEATURE_DTSHD);
210
211 bAC3 ? m_ac3Check->Show() : m_ac3Check->Hide();
212 bDTS ? m_dtsCheck->Show() : m_dtsCheck->Hide();
213 bEAC3 ? m_eac3Check->Show() : m_eac3Check->Hide();
214 bTRUEHD ? m_truehdCheck->Show() : m_truehdCheck->Hide();
215 bDTSHD ? m_dtshdCheck->Show() : m_dtshdCheck->Hide();
216
219
220 if (max_speakers > 2 && !bLPCM)
221 max_speakers = 2;
222 if (max_speakers == 2 && bAC3)
223 {
224 max_speakers = 6;
225 if (AC3)
226 {
227 restore = true;
228 }
229 }
230
231 int cur_speakers = m_maxspeakers;
232
234 {
236 .value<int>();
237 }
238 m_maxspeakers = std::max(cur_speakers, m_maxspeakers);
239 if (restore)
240 {
241 cur_speakers = m_maxspeakers;
242 }
243
244 if (cur_speakers > max_speakers)
245 {
246 LOG(VB_AUDIO, LOG_INFO, QString("Reset device %1").arg(out));
247 cur_speakers = max_speakers;
248 }
249
250 // Remove everything and re-add available channels
252 for (int i = 1; i <= max_speakers; i++)
253 {
254 if (settings.IsSupportedChannels(i))
255 {
256 switch (i)
257 {
258 case 2:
259 {
260 auto *stereo =
262 QObject::tr("Stereo"));
263 stereo->SetData(2);
264 break;
265 }
266 case 6:
267 {
268 auto *sixchan =
270 QObject::tr("5.1 Channel Audio"));
271 sixchan->SetData(6);
272 break;
273 }
274 case 8:
275 {
276 auto *eightchan =
278 QObject::tr("7.1 Channel Audio"));
279 eightchan->SetData(8);
280 break;
281 }
282 default:
283 continue;
284 }
285 }
286 }
287 m_speakerNumberButtonList->SetValueByData(QVariant::fromValue(cur_speakers));
288
289 // Return values is used by audio test
290 // where we mainly are interested by the number of channels
291 // if we support AC3 and/or LPCM
292 settings.SetBestSupportedChannels(cur_speakers);
293 settings.setFeature(bAC3, FEATURE_AC3);
294 settings.setFeature(bDTS, FEATURE_DTS);
295 settings.setFeature(bLPCM && realmax_speakers > 2, FEATURE_LPCM);
296
297 return settings;
298}
299
302{
303 bool restore = false;
304 if (item)
305 {
306 restore = item->GetText() != m_lastAudioDevice;
307 m_lastAudioDevice = item->GetText();
308 }
309 return UpdateCapabilities(restore);
310}
311
313{
314 return UpdateCapabilities(false, true);
315}
316
318{
319 if (m_testThread)
320 {
322 }
323
324 save();
325
327 auto *sw = new VideoSetupWizard(mainStack, m_generalScreen,
328 this, "videosetupwizard");
329
330 if (sw->Create())
331 {
332 mainStack->AddScreen(sw);
333 }
334 else
335 {
336 delete sw;
337 }
338}
339
341{
342 // reset advanced audio config to default values
343 gCoreContext->SaveBoolSetting("StereoPCM", false);
344 gCoreContext->SaveBoolSetting("Audio48kOverride", false);
345 gCoreContext->SaveBoolSetting("HBRPassthru", true);
346 gCoreContext->SaveBoolSetting("PassThruDeviceOverride", false);
347 gCoreContext->SaveSetting("PassThruOutputDevice", QString());
348
350 .value<int>();
351 gCoreContext->SaveSetting("MaxChannels", channels);
352
353 QString device =
355 gCoreContext->SaveSetting("AudioOutputDevice", device);
356
357 bool ac3State = (m_ac3Check->GetCheckState() == MythUIStateType::Full);
358 gCoreContext->SaveBoolSetting("AC3PassThru", ac3State);
359
360 bool dtsState = (m_dtsCheck->GetCheckState() == MythUIStateType::Full);
361 gCoreContext->SaveBoolSetting("DTSPassThru", dtsState);
362
363 bool eac3State = (m_eac3Check->GetCheckState() == MythUIStateType::Full);
364 gCoreContext->SaveBoolSetting("EAC3PassThru", eac3State);
365
366 bool truehdState = (m_truehdCheck->GetCheckState() == MythUIStateType::Full);
367 gCoreContext->SaveBoolSetting("TrueHDPassThru", truehdState);
368
369 bool dtshdState = (m_dtshdCheck->GetCheckState() == MythUIStateType::Full);
370 gCoreContext->SaveBoolSetting("DTSHDPassThru", dtshdState);
371}
372
374{
375 Close();
376}
377
379{
380 if (GetFocusWidget()->keyPressEvent(event))
381 return true;
382
383 bool handled = false;
384
386 handled = true;
387
388 return handled;
389}
390
392{
393 if (m_testThread)
394 {
397 delete m_testThread;
398 m_testThread = nullptr;
399 m_testSpeakerButton->SetText(tr("Test Speakers"));
400 return;
401 }
402
403 AudioOutputSettings settings = UpdateCapabilities(false);
406 .value<int> ();
407
409 new AudioTestThread(this, out, out, channels, settings, false);
411 {
412 QString msg = QObject::tr("Audio device is invalid or not useable.");
413 ShowOkPopup(msg);
414 delete m_testThread;
415 m_testThread = nullptr;
416 }
417 else
418 {
420 m_testSpeakerButton->SetText(tr("Stop Speaker Test"));
421 }
422}
@ FEATURE_DTS
@ FEATURE_AC3
@ FEATURE_DTSHD
@ FEATURE_EAC3
@ FEATURE_LPCM
@ FEATURE_TRUEHD
bool IsSupportedChannels(int channels)
bool canFeature(DigitalFeature arg) const
return DigitalFeature mask.
void SetBestSupportedChannels(int channels)
Force set the greatest number of channels supported by the audio device.
void setFeature(DigitalFeature arg)
set the provided digital feature possible values are:
bool IsInvalid() const
return true if class instance is marked invalid.
AudioOutputSettings m_settings
Definition: audiooutput.h:40
static ADCVect * GetOutputList(void)
static AudioDeviceConfig * GetAudioDeviceConfig(QString &name, const QString &desc, bool willsuspendpa=false)
AudioTestThread * m_testThread
AudioOutputSettings UpdateCapabilitiesAC3(void)
AudioOutputSettings UpdateCapabilities(bool restore=true, bool AC3=false)
MythUICheckBox * m_dtsCheck
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool Create(void) override
MythUIButton * m_testSpeakerButton
MythUICheckBox * m_eac3Check
MythUICheckBox * m_ac3Check
MythUIButtonList * m_speakerNumberButtonList
MythUICheckBox * m_dtshdCheck
~AudioSetupWizard() override
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
MythUIButtonList * m_audioDeviceButtonList
MythUICheckBox * m_truehdCheck
MythUIButton * m_nextButton
QVector< AudioOutput::AudioDeviceConfig > * m_outputlist
MythScreenType * m_generalScreen
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
MythUIButton * m_prevButton
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
void SaveBoolSetting(const QString &key, bool newValue)
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
int GetNumSetting(const QString &key, int defaultval=0)
MythScreenStack * GetMainStack()
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
void LoadInBackground(const QString &message="")
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
virtual void Close()
QString GetText(const QString &name="") const
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
MythUIButtonListItem * GetItemCurrent() const
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
void SetValueByData(const QVariant &data)
void itemSelected(MythUIButtonListItem *item)
A single button widget.
Definition: mythuibutton.h:22
void SetText(const QString &msg)
void Clicked()
A checkbox widget supporting three check states - on,off,half and two conditions - selected and unsel...
void SetCheckState(MythUIStateType::StateType state)
MythUIStateType::StateType GetCheckState() const
void valueChanged()
void SetHelpText(const QString &text)
Definition: mythuitype.h:177
void Hide(void)
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:138
void Show(void)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
@ AC3
Definition: element.h:84
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
#define output