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::ranges::any_of(std::as_const(*m_outputlist), 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#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
197 const auto* it = std::ranges::find(std::as_const(*m_outputlist), out,
199#else
200 const auto it = std::ranges::find(std::as_const(*m_outputlist), out,
202#endif
203 if (it != m_outputlist->cend())
204 {
206 settings = ao.m_settings;
207 }
208
209 realmax_speakers = max_speakers = settings.BestSupportedChannels();
210
211 bool bAC3 = settings.canFeature(FEATURE_AC3);
212 bool bDTS = settings.canFeature(FEATURE_DTS);
213 bool bLPCM = settings.canFeature(FEATURE_LPCM);
214 bool bEAC3 = settings.canFeature(FEATURE_EAC3);
215 bool bTRUEHD = settings.canFeature(FEATURE_TRUEHD);
216 bool bDTSHD = settings.canFeature(FEATURE_DTSHD);
217
218 bAC3 ? m_ac3Check->Show() : m_ac3Check->Hide();
219 bDTS ? m_dtsCheck->Show() : m_dtsCheck->Hide();
220 bEAC3 ? m_eac3Check->Show() : m_eac3Check->Hide();
221 bTRUEHD ? m_truehdCheck->Show() : m_truehdCheck->Hide();
222 bDTSHD ? m_dtshdCheck->Show() : m_dtshdCheck->Hide();
223
226
227 if (max_speakers > 2 && !bLPCM)
228 max_speakers = 2;
229 if (max_speakers == 2 && bAC3)
230 {
231 max_speakers = 6;
232 if (AC3)
233 {
234 restore = true;
235 }
236 }
237
238 int cur_speakers = m_maxspeakers;
239
241 {
243 .value<int>();
244 }
245 m_maxspeakers = std::max(cur_speakers, m_maxspeakers);
246 if (restore)
247 {
248 cur_speakers = m_maxspeakers;
249 }
250
251 if (cur_speakers > max_speakers)
252 {
253 LOG(VB_AUDIO, LOG_INFO, QString("Reset device %1").arg(out));
254 cur_speakers = max_speakers;
255 }
256
257 // Remove everything and re-add available channels
259 for (int i = 1; i <= max_speakers; i++)
260 {
261 if (settings.IsSupportedChannels(i))
262 {
263 switch (i)
264 {
265 case 2:
266 {
267 auto *stereo =
269 QObject::tr("Stereo"));
270 stereo->SetData(2);
271 break;
272 }
273 case 6:
274 {
275 auto *sixchan =
277 QObject::tr("5.1 Channel Audio"));
278 sixchan->SetData(6);
279 break;
280 }
281 case 8:
282 {
283 auto *eightchan =
285 QObject::tr("7.1 Channel Audio"));
286 eightchan->SetData(8);
287 break;
288 }
289 default:
290 continue;
291 }
292 }
293 }
294 m_speakerNumberButtonList->SetValueByData(QVariant::fromValue(cur_speakers));
295
296 // Return values is used by audio test
297 // where we mainly are interested by the number of channels
298 // if we support AC3 and/or LPCM
299 settings.SetBestSupportedChannels(cur_speakers);
300 settings.setFeature(bAC3, FEATURE_AC3);
301 settings.setFeature(bDTS, FEATURE_DTS);
302 settings.setFeature(bLPCM && realmax_speakers > 2, FEATURE_LPCM);
303
304 return settings;
305}
306
309{
310 bool restore = false;
311 if (item)
312 {
313 restore = item->GetText() != m_lastAudioDevice;
314 m_lastAudioDevice = item->GetText();
315 }
316 return UpdateCapabilities(restore);
317}
318
320{
321 return UpdateCapabilities(false, true);
322}
323
325{
326 if (m_testThread)
327 {
329 }
330
331 save();
332
334 auto *sw = new VideoSetupWizard(mainStack, m_generalScreen,
335 this, "videosetupwizard");
336
337 if (sw->Create())
338 {
339 mainStack->AddScreen(sw);
340 }
341 else
342 {
343 delete sw;
344 }
345}
346
348{
349 // reset advanced audio config to default values
350 gCoreContext->SaveBoolSetting("StereoPCM", false);
351 gCoreContext->SaveBoolSetting("Audio48kOverride", false);
352 gCoreContext->SaveBoolSetting("HBRPassthru", true);
353 gCoreContext->SaveBoolSetting("PassThruDeviceOverride", false);
354 gCoreContext->SaveSetting("PassThruOutputDevice", QString());
355
357 .value<int>();
358 gCoreContext->SaveSetting("MaxChannels", channels);
359
360 QString device =
362 gCoreContext->SaveSetting("AudioOutputDevice", device);
363
364 bool ac3State = (m_ac3Check->GetCheckState() == MythUIStateType::Full);
365 gCoreContext->SaveBoolSetting("AC3PassThru", ac3State);
366
367 bool dtsState = (m_dtsCheck->GetCheckState() == MythUIStateType::Full);
368 gCoreContext->SaveBoolSetting("DTSPassThru", dtsState);
369
370 bool eac3State = (m_eac3Check->GetCheckState() == MythUIStateType::Full);
371 gCoreContext->SaveBoolSetting("EAC3PassThru", eac3State);
372
373 bool truehdState = (m_truehdCheck->GetCheckState() == MythUIStateType::Full);
374 gCoreContext->SaveBoolSetting("TrueHDPassThru", truehdState);
375
376 bool dtshdState = (m_dtshdCheck->GetCheckState() == MythUIStateType::Full);
377 gCoreContext->SaveBoolSetting("DTSHDPassThru", dtshdState);
378}
379
381{
382 Close();
383}
384
386{
387 if (GetFocusWidget()->keyPressEvent(event))
388 return true;
389
390 bool handled = false;
391
393 handled = true;
394
395 return handled;
396}
397
399{
400 if (m_testThread)
401 {
404 delete m_testThread;
405 m_testThread = nullptr;
406 m_testSpeakerButton->SetText(tr("Test Speakers"));
407 return;
408 }
409
410 AudioOutputSettings settings = UpdateCapabilities(false);
413 .value<int> ();
414
416 new AudioTestThread(this, out, out, channels, settings, false);
418 {
419 QString msg = QObject::tr("Audio device is invalid or not useable.");
420 ShowOkPopup(msg);
421 delete m_testThread;
422 m_testThread = nullptr;
423 }
424 else
425 {
427 m_testSpeakerButton->SetText(tr("Stop Speaker Test"));
428 }
429}
@ 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:267
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:284
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:188
void Hide(void)
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
Definition: mythuitype.cpp:130
void Show(void)
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
@ 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