MythTV  master
audiooutputdx.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <cmath>
3 
4 using namespace std;
5 
6 #include "mythlogging.h"
7 #include "audiooutputdx.h"
8 
9 #include <windows.h>
10 #include <mmsystem.h>
11 #include <dsound.h>
12 #include <unistd.h>
13 
14 #define LOC QString("AODX: ")
15 
16 #include <initguid.h>
17 DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0,
18  0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
19 
20 #ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
21 #define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
22 #endif
23 
24 #ifndef WAVE_FORMAT_IEEE_FLOAT
25 #define WAVE_FORMAT_IEEE_FLOAT 0x0003
26 #endif
27 
28 #ifndef WAVE_FORMAT_EXTENSIBLE
29 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
30 #endif
31 
32 #ifndef _WAVEFORMATEXTENSIBLE_
34  WAVEFORMATEX Format;
35  union {
36  WORD wValidBitsPerSample; // bits of precision
37  WORD wSamplesPerBlock; // valid if wBitsPerSample==0
38  WORD wReserved; // If neither applies, set to zero
39  } Samples;
40  DWORD dwChannelMask; // which channels are present in stream
41  GUID SubFormat;
42 };
44 #endif
45 
46 DEFINE_GUID(_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT,
47  0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
48 DEFINE_GUID(_KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM,
49  0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
50 DEFINE_GUID(_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF,
51  0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
52 
54 {
55  public:
56  explicit AudioOutputDXPrivate(AudioOutputDX *in_parent) :
57  m_parent(in_parent) {}
58 
60  {
61  DestroyDSBuffer();
62 
63  if (m_dsobject)
64  IDirectSound_Release(m_dsobject);
65 
66  if (m_dsound_dll)
67  FreeLibrary(m_dsound_dll);
68  }
69 
70  int InitDirectSound(bool passthrough = false);
71  void ResetDirectSound(void);
72  void DestroyDSBuffer(void);
73  void FillBuffer(unsigned char *buffer, int size);
74  bool StartPlayback(void);
75 #ifdef UNICODE
76  static int CALLBACK DSEnumCallback(LPGUID lpGuid,
77  LPCWSTR lpcstrDesc,
78  LPCWSTR lpcstrModule,
79  LPVOID lpContext);
80 #else
81  static int CALLBACK DSEnumCallback(LPGUID lpGuid,
82  LPCSTR lpcstrDesc,
83  LPCSTR lpcstrModule,
84  LPVOID lpContext);
85 #endif
86  public:
87  AudioOutputDX *m_parent {nullptr};
88  HINSTANCE m_dsound_dll {nullptr};
89  LPDIRECTSOUND m_dsobject {nullptr};
90  LPDIRECTSOUNDBUFFER m_dsbuffer {nullptr};
91  bool m_playStarted {false};
92  DWORD m_writeCursor {0};
94  GUID *m_chosenGUID {nullptr};
95  int m_device_count {0};
96  int m_device_num {0};
97  QString m_device_name;
98  QMap<int, QString> m_device_list;
99 };
100 
101 
103  AudioOutputBase(settings),
104  m_priv(new AudioOutputDXPrivate(this)),
105  m_UseSPDIF(settings.use_passthru)
106 {
107  timeBeginPeriod(1);
108  InitSettings(settings);
109  if (passthru_device == "auto" || passthru_device.toLower() == "default")
110  passthru_device = main_device;
111  else
112  m_discretedigital = true;
113  if (settings.init)
114  Reconfigure(settings);
115 }
116 
118 {
119  KillAudio();
120  if (m_priv)
121  {
122  delete m_priv;
123  m_priv = nullptr;
124  }
125  timeEndPeriod(1);
126 }
127 
128 using LPFNDSC = HRESULT (WINAPI *) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
129 using LPFNDSE = HRESULT (WINAPI *) (LPDSENUMCALLBACK, LPVOID);
130 
131 #ifdef UNICODE
132 int CALLBACK AudioOutputDXPrivate::DSEnumCallback(LPGUID lpGuid,
133  LPCWSTR lpcstrDesc,
134  LPCWSTR lpcstrModule,
135  LPVOID lpContext)
136 {
137  QString enum_desc = QString::fromWCharArray( lpcstrDesc );
138 #else
139 int CALLBACK AudioOutputDXPrivate::DSEnumCallback(LPGUID lpGuid,
140  LPCSTR lpcstrDesc,
141  LPCSTR lpcstrModule,
142  LPVOID lpContext)
143 {
144  QString enum_desc = QString::fromLocal8Bit( lpcstrDesc );
145 
146 #endif
147  AudioOutputDXPrivate *context = static_cast<AudioOutputDXPrivate*>(lpContext);
148  const QString cfg_desc = context->m_device_name;
149  const int device_num = context->m_device_num;
150  const int device_count = context->m_device_count;
151 
152  VBAUDIO(QString("Device %1:" + enum_desc).arg(device_count));
153 
154  if ((device_num == device_count ||
155  (device_num == 0 && !cfg_desc.isEmpty() &&
156  enum_desc.startsWith(cfg_desc, Qt::CaseInsensitive))) && lpGuid)
157  {
158  context->m_deviceGUID = *lpGuid;
159  context->m_chosenGUID =
160  &(context->m_deviceGUID);
161  context->m_device_name = enum_desc;
162  context->m_device_num = device_count;
163  }
164 
165  context->m_device_list.insert(device_count, enum_desc);
166  context->m_device_count++;
167  return 1;
168 }
169 
171 {
172  DestroyDSBuffer();
173 
174  if (m_dsobject)
175  {
176  IDirectSound_Release(m_dsobject);
177  m_dsobject = nullptr;
178  }
179 
180  if (m_dsound_dll)
181  {
182  FreeLibrary(m_dsound_dll);
183  m_dsound_dll = nullptr;
184  }
185 
186  m_chosenGUID = nullptr;
187  m_device_count = 0;
188  m_device_num = 0;
189  m_device_list.clear();
190 }
191 
193 {
194  LPFNDSC OurDirectSoundCreate;
195  LPFNDSE OurDirectSoundEnumerate;
196  bool ok;
197 
199 
200  m_dsound_dll = LoadLibrary(TEXT("DSOUND.DLL"));
201  if (m_dsound_dll == nullptr)
202  {
203  VBERROR("Cannot open DSOUND.DLL");
204  goto error;
205  }
206 
207  if (m_parent) // parent can be nullptr only when called from GetDXDevices()
208  m_device_name = passthrough ?
209  m_parent->passthru_device : m_parent->main_device;
210  m_device_name = m_device_name.section(':', 1);
211  m_device_num = m_device_name.toInt(&ok, 10);
212 
213  VBAUDIO(QString("Looking for device num:%1 or name:%2")
215 
216  OurDirectSoundEnumerate =
217  (LPFNDSE)GetProcAddress(m_dsound_dll, "DirectSoundEnumerateA");
218 
219  if(OurDirectSoundEnumerate)
220  if(FAILED(OurDirectSoundEnumerate(DSEnumCallback, this) != DS_OK))
221  VBERROR("DirectSoundEnumerate FAILED");
222 
223  if (!m_chosenGUID)
224  {
225  m_device_num = 0;
226  m_device_name = "Primary Sound Driver";
227  }
228 
229  VBAUDIO(QString("Using device %1:%2").arg(m_device_num).arg(m_device_name));
230 
231  OurDirectSoundCreate =
232  (LPFNDSC)GetProcAddress(m_dsound_dll, "DirectSoundCreate");
233 
234  if (OurDirectSoundCreate == nullptr)
235  {
236  VBERROR("GetProcAddress FAILED");
237  goto error;
238  }
239 
240  if (FAILED(OurDirectSoundCreate(m_chosenGUID, &m_dsobject, nullptr)))
241  {
242  VBERROR("Cannot create a direct sound device");
243  goto error;
244  }
245 
246  /* Set DirectSound Cooperative level, ie what control we want over Windows
247  * sound device. In our case, DSSCL_EXCLUSIVE means that we can modify the
248  * settings of the primary buffer, but also that only the sound of our
249  * application will be hearable when it will have the focus.
250  * !!! (this is not really working as intended yet because to set the
251  * cooperative level you need the window handle of your application, and
252  * I don't know of any easy way to get it. Especially since we might play
253  * sound without any video, and so what window handle should we use ???
254  * The hack for now is to use the Desktop window handle - it seems to be
255  * working */
256  if (FAILED(IDirectSound_SetCooperativeLevel(m_dsobject, GetDesktopWindow(),
257  DSSCL_EXCLUSIVE)))
258  VBERROR("Cannot set DS cooperative level");
259 
260  VBAUDIO("Initialised DirectSound");
261 
262  return 0;
263 
264  error:
265  m_dsobject = nullptr;
266  if (m_dsound_dll)
267  {
268  FreeLibrary(m_dsound_dll);
269  m_dsound_dll = nullptr;
270  }
271  return -1;
272 }
273 
275 {
276  if (!m_dsbuffer)
277  return;
278 
279  VBAUDIO("Destroying DirectSound buffer");
280  IDirectSoundBuffer_Stop(m_dsbuffer);
281  m_writeCursor = 0;
282  IDirectSoundBuffer_SetCurrentPosition(m_dsbuffer, m_writeCursor);
283  m_playStarted = false;
284  IDirectSoundBuffer_Release(m_dsbuffer);
285  m_dsbuffer = nullptr;
286 }
287 
288 void AudioOutputDXPrivate::FillBuffer(unsigned char *buffer, int size)
289 {
290  void *p_write_position, *p_wrap_around;
291  DWORD l_bytes1, l_bytes2, play_pos, write_pos;
292  HRESULT dsresult;
293 
294  if (!m_dsbuffer)
295  return;
296 
297  while (true)
298  {
299 
300  dsresult = IDirectSoundBuffer_GetCurrentPosition(m_dsbuffer,
301  &play_pos, &write_pos);
302  if (dsresult != DS_OK)
303  {
304  VBERROR("Cannot get current buffer position");
305  return;
306  }
307 
308  VBAUDIOTS(QString("play: %1 write: %2 wcursor: %3")
309  .arg(play_pos).arg(write_pos).arg(m_writeCursor));
310 
311  while ((m_writeCursor < write_pos &&
312  ((m_writeCursor >= play_pos && write_pos >= play_pos) ||
313  (m_writeCursor < play_pos && write_pos < play_pos))) ||
314  (m_writeCursor >= play_pos && write_pos < play_pos))
315  {
316  VBERROR("buffer underrun");
317  m_writeCursor += size;
318  while (m_writeCursor >= (DWORD)m_parent->soundcard_buffer_size)
319  m_writeCursor -= m_parent->soundcard_buffer_size;
320  }
321 
322  if ((m_writeCursor < play_pos && m_writeCursor + size >= play_pos) ||
323  (m_writeCursor >= play_pos &&
324  m_writeCursor + size >= play_pos + m_parent->soundcard_buffer_size))
325  {
326  usleep(50000);
327  continue;
328  }
329 
330  break;
331  }
332 
333  dsresult = IDirectSoundBuffer_Lock(
334  m_dsbuffer, /* DS buffer */
335  m_writeCursor, /* Start offset */
336  size, /* Number of bytes */
337  &p_write_position, /* Address of lock start */
338  &l_bytes1, /* Bytes locked before wrap */
339  &p_wrap_around, /* Buffer address (if wrap around) */
340  &l_bytes2, /* Count of bytes after wrap around */
341  0); /* Flags */
342 
343  if (dsresult == DSERR_BUFFERLOST)
344  {
345  IDirectSoundBuffer_Restore(m_dsbuffer);
346  dsresult = IDirectSoundBuffer_Lock(m_dsbuffer, m_writeCursor, size,
347  &p_write_position, &l_bytes1,
348  &p_wrap_around, &l_bytes2, 0);
349  }
350 
351  if (dsresult != DS_OK)
352  {
353  VBERROR("Cannot lock buffer, audio dropped");
354  return;
355  }
356 
357  memcpy(p_write_position, buffer, l_bytes1);
358  if (p_wrap_around)
359  memcpy(p_wrap_around, buffer + l_bytes1, l_bytes2);
360 
361  m_writeCursor += l_bytes1 + l_bytes2;
362 
363  while (m_writeCursor >= (DWORD)m_parent->soundcard_buffer_size)
364  m_writeCursor -= m_parent->soundcard_buffer_size;
365 
366  IDirectSoundBuffer_Unlock(m_dsbuffer, p_write_position, l_bytes1,
367  p_wrap_around, l_bytes2);
368 }
369 
371 {
372  HRESULT dsresult;
373 
374  dsresult = IDirectSoundBuffer_Play(m_dsbuffer, 0, 0, DSBPLAY_LOOPING);
375  if (dsresult == DSERR_BUFFERLOST)
376  {
377  IDirectSoundBuffer_Restore(m_dsbuffer);
378  dsresult = IDirectSoundBuffer_Play(m_dsbuffer, 0, 0, DSBPLAY_LOOPING);
379  }
380  if (dsresult != DS_OK)
381  {
382  VBERROR("Cannot start playing buffer");
383  m_playStarted = false;
384  return false;
385  }
386 
387  m_playStarted=true;
388  return true;
389 }
390 
392 {
393  AudioOutputSettings *settings = new AudioOutputSettings();
394  DSCAPS devcaps;
395  devcaps.dwSize = sizeof(DSCAPS);
396 
397  m_priv->InitDirectSound(passthrough);
398  if ((!m_priv->m_dsobject || !m_priv->m_dsound_dll) ||
399  FAILED(IDirectSound_GetCaps(m_priv->m_dsobject, &devcaps)) )
400  {
401  delete settings;
402  return nullptr;
403  }
404 
405  VBAUDIO(QString("GetCaps sample rate min: %1 max: %2")
406  .arg(devcaps.dwMinSecondarySampleRate)
407  .arg(devcaps.dwMaxSecondarySampleRate));
408 
409  /* We shouldn't assume we can do everything between min and max but
410  there's no way to test individual rates, so we'll have to */
411  while (DWORD rate = (DWORD)settings->GetNextRate())
412  if((rate >= devcaps.dwMinSecondarySampleRate) ||
413  (rate <= devcaps.dwMaxSecondarySampleRate))
414  settings->AddSupportedRate(rate);
415 
416  /* We can only test for 8 and 16 bit support, DS uses float internally */
417  if (devcaps.dwFlags & DSCAPS_PRIMARY8BIT)
418  settings->AddSupportedFormat(FORMAT_U8);
419  if (devcaps.dwFlags & DSCAPS_PRIMARY16BIT)
420  settings->AddSupportedFormat(FORMAT_S16);
421 #if 0 // 24-bit integer is not supported
422  settings->AddSupportedFormat(FORMAT_S24);
423 #endif
424 #if 0 // 32-bit integer (OGG) is not supported on all platforms.
425  settings->AddSupportedFormat(FORMAT_S32);
426 #endif
427 #if 0 // 32-bit floating point (AC3) is not supported on all platforms.
428  settings->AddSupportedFormat(FORMAT_FLT);
429 #endif
430 
431  /* No way to test anything other than mono or stereo, guess that we can do
432  up to 5.1 */
433  for (uint i = 2; i < 7; i++)
434  settings->AddSupportedChannels(i);
435 
436  settings->setPassthrough(0); // Maybe passthrough
437 
438  return settings;
439 }
440 
442 {
444  DSBUFFERDESC dsbdesc;
445 
446  CloseDevice();
447 
448  m_UseSPDIF = passthru || enc;
449  m_priv->InitDirectSound(m_UseSPDIF);
450  if (!m_priv->m_dsobject || !m_priv->m_dsound_dll)
451  {
452  Error(QObject::tr("DirectSound initialization failed"));
453  return false;
454  }
455 
456  // fragments are 50ms worth of samples
457  fragment_size = 50 * output_bytes_per_frame * samplerate / 1000;
458  // DirectSound buffer holds 4 fragments = 200ms worth of samples
459  soundcard_buffer_size = fragment_size << 2;
460 
461  VBAUDIO(QString("DirectSound buffer size: %1").arg(soundcard_buffer_size));
462 
463  wf.Format.nChannels = channels;
464  wf.Format.nSamplesPerSec = samplerate;
465  wf.Format.nBlockAlign = output_bytes_per_frame;
466  wf.Format.nAvgBytesPerSec = samplerate * output_bytes_per_frame;
467  wf.Format.wBitsPerSample = (output_bytes_per_frame << 3) / channels;
469  AudioOutputSettings::FormatToBits(output_format);
470 
471  if (m_UseSPDIF)
472  {
473  wf.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
474  wf.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
475  }
476  else if (output_format == FORMAT_FLT)
477  {
478  wf.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
479  wf.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
480  }
481  else
482  {
483  wf.Format.wFormatTag = WAVE_FORMAT_PCM;
484  wf.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM;
485  }
486 
487  VBAUDIO(QString("New format: %1bits %2ch %3Hz %4")
488  .arg(wf.Samples.wValidBitsPerSample).arg(channels)
489  .arg(samplerate).arg(m_UseSPDIF ? "data" : "PCM"));
490 
491  if (channels <= 2)
492  wf.Format.cbSize = 0;
493  else
494  {
495  wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
496  wf.dwChannelMask = 0x003F; // 0x003F = 5.1 channels
497  wf.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
498  }
499 
500  memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
501  dsbdesc.dwSize = sizeof(DSBUFFERDESC);
502  dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 // Better position accuracy
503  | DSBCAPS_GLOBALFOCUS // Allows background playing
504  | DSBCAPS_LOCHARDWARE; // Needed for 5.1 on emu101k
505 
506  if (!m_UseSPDIF)
507  dsbdesc.dwFlags |= DSBCAPS_CTRLVOLUME; // Allow volume control
508 
509  dsbdesc.dwBufferBytes = soundcard_buffer_size; // buffer size
510  dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wf;
511 
512  if (FAILED(IDirectSound_CreateSoundBuffer(m_priv->m_dsobject, &dsbdesc,
513  &m_priv->m_dsbuffer, nullptr)))
514  {
515  /* Vista does not support hardware mixing
516  try without DSBCAPS_LOCHARDWARE */
517  dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE;
518  HRESULT dsresult =
519  IDirectSound_CreateSoundBuffer(m_priv->m_dsobject, &dsbdesc,
520  &m_priv->m_dsbuffer, nullptr);
521  if (FAILED(dsresult))
522  {
523  if (dsresult == DSERR_UNSUPPORTED)
524  Error(QObject::tr("Unsupported format for device %1:%2")
525  .arg(m_priv->m_device_num).arg(m_priv->m_device_name));
526  else
527  Error(QObject::tr("Failed to create DS buffer 0x%1")
528  .arg((DWORD)dsresult, 0, 16));
529  return false;
530  }
531  VBAUDIO("Using software mixer");
532  }
533  VBAUDIO("Created DirectSound buffer");
534 
535  return true;
536 }
537 
539 {
540  if (m_priv->m_dsbuffer)
541  m_priv->DestroyDSBuffer();
542 }
543 
544 void AudioOutputDX::WriteAudio(unsigned char * buffer, int size)
545 {
546  if (size == 0)
547  return;
548 
549  m_priv->FillBuffer(buffer, size);
550  if (!m_priv->m_playStarted)
551  m_priv->StartPlayback();
552 }
553 
555 {
556  if (!m_priv->m_playStarted)
557  return 0;
558 
559  HRESULT dsresult;
560  DWORD play_pos, write_pos;
561  int buffered;
562 
563  dsresult = IDirectSoundBuffer_GetCurrentPosition(m_priv->m_dsbuffer,
564  &play_pos, &write_pos);
565  if (dsresult != DS_OK)
566  {
567  VBERROR("Cannot get current buffer position");
568  return 0;
569  }
570 
571  buffered = (int)m_priv->m_writeCursor - (int)play_pos;
572 
573  if (buffered <= 0)
574  buffered += soundcard_buffer_size;
575 
576  return buffered;
577 }
578 
580 {
581  HRESULT dsresult;
582  long dxVolume = 0;
583  int volume;
584 
585  if (m_UseSPDIF)
586  return 100;
587 
588  dsresult = IDirectSoundBuffer_GetVolume(m_priv->m_dsbuffer, &dxVolume);
589  volume = (int)(pow(10,(float)dxVolume/20)*100);
590 
591  if (dsresult != DS_OK)
592  {
593  VBERROR(QString("Failed to get volume %1").arg(dxVolume));
594  return volume;
595  }
596 
597  VBAUDIO(QString("Got volume %1").arg(volume));
598  return volume;
599 }
600 
602 {
603  HRESULT dsresult;
604  float dbAtten = 20 * log10((float)volume/100);
605  long dxVolume = (volume == 0) ? DSBVOLUME_MIN : (long)(100.0F * dbAtten);
606 
607  if (m_UseSPDIF)
608  return;
609 
610  // dxVolume is attenuation in 100ths of a decibel
611  dsresult = IDirectSoundBuffer_SetVolume(m_priv->m_dsbuffer, dxVolume);
612 
613  if (dsresult != DS_OK)
614  {
615  VBERROR(QString("Failed to set volume %1").arg(dxVolume));
616  return;
617  }
618 
619  VBAUDIO(QString("Set volume %1").arg(dxVolume));
620 }
621 
622 QMap<int, QString> *AudioOutputDX::GetDXDevices(void)
623 {
624  AudioOutputDXPrivate *tmp_priv = new AudioOutputDXPrivate(nullptr);
625  tmp_priv->InitDirectSound(false);
626  QMap<int, QString> *dxdevs = new QMap<int, QString>(tmp_priv->m_device_list);
627  delete tmp_priv;
628  return dxdevs;
629 }
630 
631 /* vim: set expandtab tabstop=4 shiftwidth=4: */
AudioOutputDXPrivate::AudioOutputDXPrivate
AudioOutputDXPrivate(AudioOutputDX *in_parent)
Definition: audiooutputdx.cpp:56
AudioOutputDXPrivate::m_dsbuffer
LPDIRECTSOUNDBUFFER m_dsbuffer
Definition: audiooutputdx.cpp:90
FORMAT_U8
@ FORMAT_U8
Definition: audiooutputsettings.h:27
LPFNDSC
HRESULT(WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN) LPFNDSC
Definition: audiooutputdx.cpp:128
WAVEFORMATEXTENSIBLE::SubFormat
GUID SubFormat
Definition: audiooutputdx.cpp:41
AudioOutputSettings::GetNextRate
int GetNextRate()
Definition: audiooutputsettings.cpp:68
channel
QDomElement channel
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:504
AudioOutputDXPrivate::m_device_name
QString m_device_name
Definition: audiooutputdx.cpp:97
AudioOutputDX
Definition: audiooutputdx.h:13
AudioOutputSettings::setPassthrough
void setPassthrough(int val)
Definition: audiooutputsettings.h:77
VBAUDIO
#define VBAUDIO(str)
Definition: audiooutputbase.h:19
error
static void error(const char *str,...)
Definition: vbi.cpp:42
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:28
AudioOutputDXPrivate::DestroyDSBuffer
void DestroyDSBuffer(void)
Definition: audiooutputdx.cpp:274
AudioOutputSettings::AddSupportedFormat
void AddSupportedFormat(AudioFormat format)
Definition: audiooutputsettings.cpp:129
AudioOutputDX::~AudioOutputDX
virtual ~AudioOutputDX()
Definition: audiooutputdx.cpp:117
AudioOutputDXPrivate::DSEnumCallback
static int CALLBACK DSEnumCallback(LPGUID lpGuid, LPCSTR lpcstrDesc, LPCSTR lpcstrModule, LPVOID lpContext)
Definition: audiooutputdx.cpp:139
AudioOutputDX::AudioOutputDX
AudioOutputDX(const AudioSettings &settings)
Definition: audiooutputdx.cpp:102
WAVEFORMATEXTENSIBLE::Samples
union WAVEFORMATEXTENSIBLE::@0 Samples
AudioOutputDX::OpenDevice
bool OpenDevice(void) override
Definition: audiooutputdx.cpp:441
AudioOutputBase::KillAudio
void KillAudio(void)
Kill the output thread and cleanup.
Definition: audiooutputbase.cpp:859
AudioOutputDX::GetVolumeChannel
int GetVolumeChannel(int channel) const override
Definition: audiooutputdx.cpp:579
AudioOutputSettings::FormatToBits
static int FormatToBits(AudioFormat format)
Definition: audiooutputsettings.cpp:152
AudioOutputDXPrivate::m_deviceGUID
GUID m_deviceGUID
Definition: audiooutputdx.cpp:93
arg
arg(title).arg(filename).arg(doDelete))
WAVE_FORMAT_DOLBY_AC3_SPDIF
#define WAVE_FORMAT_DOLBY_AC3_SPDIF
Definition: audiooutputdx.cpp:21
VBERROR
#define VBERROR(str)
Definition: audiooutputbase.h:22
x0
static int x0
Definition: mythsocket.cpp:59
AudioOutputDXPrivate
Definition: audiooutputdx.cpp:54
AudioOutputDXPrivate::ResetDirectSound
void ResetDirectSound(void)
Definition: audiooutputdx.cpp:170
AudioOutputDX::m_priv
AudioOutputDXPrivate * m_priv
Definition: audiooutputdx.h:31
DEFINE_GUID
DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16)
WAVE_FORMAT_EXTENSIBLE
#define WAVE_FORMAT_EXTENSIBLE
Definition: audiooutputdx.cpp:29
AudioOutputSettings::AddSupportedChannels
void AddSupportedChannels(int channels)
Definition: audiooutputsettings.cpp:239
AudioOutputDX::GetDXDevices
static QMap< int, QString > * GetDXDevices(void)
Definition: audiooutputdx.cpp:622
AudioSettings
Definition: audiosettings.h:29
AudioOutputBase
Definition: audiooutputbase.h:50
AudioOutputDXPrivate::m_parent
AudioOutputDX * m_parent
Definition: audiooutputdx.cpp:87
mythlogging.h
AudioOutputDXPrivate::FillBuffer
void FillBuffer(unsigned char *buffer, int size)
Definition: audiooutputdx.cpp:288
AudioOutputDXPrivate::InitDirectSound
int InitDirectSound(bool passthrough=false)
Definition: audiooutputdx.cpp:192
FORMAT_S24
@ FORMAT_S24
Definition: audiooutputsettings.h:30
FORMAT_FLT
@ FORMAT_FLT
Definition: audiooutputsettings.h:32
AudioOutputBase::Reconfigure
void Reconfigure(const AudioSettings &settings) override
(Re)Configure AudioOutputBase
Definition: audiooutputbase.cpp:467
AudioOutputDXPrivate::m_dsound_dll
HINSTANCE m_dsound_dll
Definition: audiooutputdx.cpp:88
AudioOutputSettings::AddSupportedRate
void AddSupportedRate(int rate)
Definition: audiooutputsettings.cpp:79
FORMAT_S32
@ FORMAT_S32
Definition: audiooutputsettings.h:31
AudioOutputDXPrivate::m_playStarted
bool m_playStarted
Definition: audiooutputdx.cpp:91
AudioOutputDXPrivate::m_device_list
QMap< int, QString > m_device_list
Definition: audiooutputdx.cpp:98
AudioOutputDXPrivate::m_chosenGUID
GUID * m_chosenGUID
Definition: audiooutputdx.cpp:94
uint
unsigned int uint
Definition: compat.h:140
WAVEFORMATEXTENSIBLE::dwChannelMask
DWORD dwChannelMask
Definition: audiooutputdx.cpp:40
WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT
Definition: audiooutputdx.cpp:25
AudioOutputDXPrivate::m_device_num
int m_device_num
Definition: audiooutputdx.cpp:96
AudioOutputSettings
Definition: audiooutputsettings.h:50
AudioOutputDX::GetOutputSettings
AudioOutputSettings * GetOutputSettings(bool passthrough) override
Definition: audiooutputdx.cpp:391
WAVEFORMATEXTENSIBLE::wValidBitsPerSample
WORD wValidBitsPerSample
Definition: audiooutputdx.cpp:36
AudioOutputBase::InitSettings
void InitSettings(const AudioSettings &settings)
Definition: audiooutputbase.cpp:119
audiooutputdx.h
AudioOutputDX::GetBufferedOnSoundcard
int GetBufferedOnSoundcard(void) const override
Return the size in bytes of frames currently in the audio buffer adjusted with the audio playback lat...
Definition: audiooutputdx.cpp:554
AudioOutputDXPrivate::m_dsobject
LPDIRECTSOUND m_dsobject
Definition: audiooutputdx.cpp:89
LPFNDSE
HRESULT(WINAPI *)(LPDSENUMCALLBACK, LPVOID) LPFNDSE
Definition: audiooutputdx.cpp:129
AudioOutputDX::CloseDevice
void CloseDevice(void) override
Definition: audiooutputdx.cpp:538
AudioOutputDXPrivate::m_device_count
int m_device_count
Definition: audiooutputdx.cpp:95
AudioOutputDX::SetVolumeChannel
void SetVolumeChannel(int channel, int volume) override
Definition: audiooutputdx.cpp:601
AudioOutputDX::WriteAudio
void WriteAudio(unsigned char *buffer, int size) override
Definition: audiooutputdx.cpp:544
AudioOutputDXPrivate::m_writeCursor
DWORD m_writeCursor
Definition: audiooutputdx.cpp:92
AudioOutputDXPrivate::StartPlayback
bool StartPlayback(void)
Definition: audiooutputdx.cpp:370
WAVEFORMATEXTENSIBLE::wSamplesPerBlock
WORD wSamplesPerBlock
Definition: audiooutputdx.cpp:37
WAVEFORMATEXTENSIBLE
Definition: audiooutputdx.cpp:33
WAVEFORMATEXTENSIBLE::wReserved
WORD wReserved
Definition: audiooutputdx.cpp:38
VBAUDIOTS
#define VBAUDIOTS(str)
Definition: audiooutputbase.h:20
WAVEFORMATEXTENSIBLE::Format
WAVEFORMATEX Format
Definition: audiooutputdx.cpp:34
AudioOutputDXPrivate::~AudioOutputDXPrivate
~AudioOutputDXPrivate()
Definition: audiooutputdx.cpp:59