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 {
205 const AudioOutput::AudioDeviceConfig& ao = *it;
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 {
242 cur_speakers = m_speakerNumberButtonList->GetItemCurrent()->GetData().toInt();
243 }
244 m_maxspeakers = std::max(cur_speakers, m_maxspeakers);
245 if (restore)
246 {
247 cur_speakers = m_maxspeakers;
248 }
249
250 if (cur_speakers > max_speakers)
251 {
252 LOG(VB_AUDIO, LOG_INFO, QString("Reset device %1").arg(out));
253 cur_speakers = max_speakers;
254 }
255
256 // Remove everything and re-add available channels
258 for (int i = 1; i <= max_speakers; i++)
259 {
260 if (settings.IsSupportedChannels(i))
261 {
262 switch (i)
263 {
264 case 2:
265 {
266 auto *stereo =
268 QObject::tr("Stereo"));
269 stereo->SetData(2);
270 break;
271 }
272 case 6:
273 {
274 auto *sixchan =
276 QObject::tr("5.1 Channel Audio"));
277 sixchan->SetData(6);
278 break;
279 }
280 case 8:
281 {
282 auto *eightchan =
284 QObject::tr("7.1 Channel Audio"));
285 eightchan->SetData(8);
286 break;
287 }
288 default:
289 continue;
290 }
291 }
292 }
293 m_speakerNumberButtonList->SetValueByData(QVariant::fromValue(cur_speakers));
294
295 // Return values is used by audio test
296 // where we mainly are interested by the number of channels
297 // if we support AC3 and/or LPCM
298 settings.SetBestSupportedChannels(cur_speakers);
299 settings.setFeature(bAC3, FEATURE_AC3);
300 settings.setFeature(bDTS, FEATURE_DTS);
301 settings.setFeature(bLPCM && realmax_speakers > 2, FEATURE_LPCM);
302
303 return settings;
304}
305
308{
309 bool restore = false;
310 if (item)
311 {
312 restore = item->GetText() != m_lastAudioDevice;
313 m_lastAudioDevice = item->GetText();
314 }
315 return UpdateCapabilities(restore);
316}
317
319{
320 return UpdateCapabilities(false, true);
321}
322
324{
325 if (m_testThread)
326 {
328 }
329
330 save();
331
333 auto *sw = new VideoSetupWizard(mainStack, m_generalScreen,
334 this, "videosetupwizard");
335
336 if (sw->Create())
337 {
338 mainStack->AddScreen(sw);
339 }
340 else
341 {
342 delete sw;
343 }
344}
345
347{
348 // reset advanced audio config to default values
349 gCoreContext->SaveBoolSetting("StereoPCM", false);
350 gCoreContext->SaveBoolSetting("Audio48kOverride", false);
351 gCoreContext->SaveBoolSetting("HBRPassthru", true);
352 gCoreContext->SaveBoolSetting("PassThruDeviceOverride", false);
353 gCoreContext->SaveSetting("PassThruOutputDevice", QString());
354
355 int channels = m_speakerNumberButtonList->GetItemCurrent()->GetData().toInt();
356 gCoreContext->SaveSetting("MaxChannels", channels);
357
358 QString device =
360 gCoreContext->SaveSetting("AudioOutputDevice", device);
361
362 bool ac3State = (m_ac3Check->GetCheckState() == MythUIStateType::Full);
363 gCoreContext->SaveBoolSetting("AC3PassThru", ac3State);
364
365 bool dtsState = (m_dtsCheck->GetCheckState() == MythUIStateType::Full);
366 gCoreContext->SaveBoolSetting("DTSPassThru", dtsState);
367
368 bool eac3State = (m_eac3Check->GetCheckState() == MythUIStateType::Full);
369 gCoreContext->SaveBoolSetting("EAC3PassThru", eac3State);
370
371 bool truehdState = (m_truehdCheck->GetCheckState() == MythUIStateType::Full);
372 gCoreContext->SaveBoolSetting("TrueHDPassThru", truehdState);
373
374 bool dtshdState = (m_dtshdCheck->GetCheckState() == MythUIStateType::Full);
375 gCoreContext->SaveBoolSetting("DTSHDPassThru", dtshdState);
376}
377
379{
380 Close();
381}
382
384{
385 if (GetFocusWidget()->keyPressEvent(event))
386 return true;
387
388 bool handled = false;
389
391 handled = true;
392
393 return handled;
394}
395
397{
398 if (m_testThread)
399 {
402 delete m_testThread;
403 m_testThread = nullptr;
404 m_testSpeakerButton->SetText(tr("Test Speakers"));
405 return;
406 }
407
408 AudioOutputSettings settings = UpdateCapabilities(false);
410 int channels = m_speakerNumberButtonList->GetItemCurrent()->GetData().toInt();
411
413 new AudioTestThread(this, out, out, channels, settings, false);
415 {
416 QString msg = QObject::tr("Audio device is invalid or not useable.");
417 ShowOkPopup(msg);
418 delete m_testThread;
419 m_testThread = nullptr;
420 }
421 else
422 {
424 m_testSpeakerButton->SetText(tr("Stop Speaker Test"));
425 }
426}
427
428#include "moc_setupwizard_audio.cpp"
@ 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