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