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