Ticket #7757: 7757-directx_devices.2.patch
File 7757-directx_devices.2.patch, 9.5 KB (added by , 14 years ago) |
---|
-
libs/libmyth/audiooutputdx.cpp
57 57 dsbuffer(NULL), 58 58 playStarted(false), 59 59 writeCursor(0), 60 lastValidTime(0) 60 lastValidTime(0), 61 chosenGUID(NULL), 62 device_count(0), 63 device_num(0) 61 64 { 62 InitDirectSound();63 65 } 64 66 65 67 ~AudioOutputDXPrivate() … … 74 76 } 75 77 76 78 int InitDirectSound(void); 79 void ResetDirectSound(void); 77 80 void DestroyDSBuffer(void); 78 81 void FillBuffer(unsigned char *buffer, int size); 79 82 bool StartPlayback(void); 80 83 void StopPlayback(bool reset); 84 static int CALLBACK DSEnumCallback(LPGUID lpGuid, 85 LPCSTR lpcstrDesc, LPCSTR lpcstrModule, LPVOID lpContext); 81 86 82 87 public: 83 88 AudioOutputDX *parent; … … 87 92 bool playStarted; 88 93 DWORD writeCursor; 89 94 DWORD lastValidTime; 95 GUID deviceGUID, *chosenGUID; 96 int device_count, device_num; 97 QString device_name; 90 98 }; 91 99 92 100 … … 112 120 } 113 121 114 122 typedef HRESULT (WINAPI *LPFNDSC) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN); 123 typedef HRESULT (WINAPI *LPFNDSE) (LPDSENUMCALLBACK, LPVOID); 115 124 125 int CALLBACK AudioOutputDXPrivate::DSEnumCallback(LPGUID lpGuid, 126 LPCSTR lpcstrDesc, LPCSTR lpcstrModule, LPVOID lpContext) 127 { 128 const QString enum_desc = lpcstrDesc, 129 cfg_desc = ((AudioOutputDXPrivate*)lpContext)->device_name; 130 const int device_num = ((AudioOutputDXPrivate*)lpContext)->device_num, 131 device_count = ((AudioOutputDXPrivate*)lpContext)->device_count; 132 133 VERBOSE(VB_AUDIO, QString(LOC + "Device %1:" + enum_desc) 134 .arg(device_count)); 135 136 if ( (device_num == device_count) 137 || (device_num == 0 && !cfg_desc.isEmpty() 138 && enum_desc.startsWith(cfg_desc, Qt::CaseInsensitive)) ) 139 { 140 if (lpGuid) 141 { 142 ((AudioOutputDXPrivate*)lpContext)->deviceGUID = *lpGuid; 143 ((AudioOutputDXPrivate*)lpContext)->chosenGUID = 144 &(((AudioOutputDXPrivate*)lpContext)->deviceGUID); 145 ((AudioOutputDXPrivate*)lpContext)->device_name = enum_desc; 146 ((AudioOutputDXPrivate*)lpContext)->device_num = device_count; 147 } 148 } 149 150 ((AudioOutputDXPrivate*)lpContext)->device_count++; 151 return 1; 152 } 153 154 void AudioOutputDXPrivate::ResetDirectSound(void) 155 { 156 DestroyDSBuffer(); 157 158 if (dsobject) 159 { 160 IDirectSound_Release(dsobject); 161 dsobject = NULL; 162 } 163 164 if (dsound_dll) 165 { 166 FreeLibrary(dsound_dll); 167 dsound_dll = NULL; 168 } 169 170 chosenGUID=NULL; 171 device_count=0; 172 device_num=0; 173 } 174 116 175 int AudioOutputDXPrivate::InitDirectSound(void) 117 176 { 118 177 LPFNDSC OurDirectSoundCreate; 119 178 LPFNDSE OurDirectSoundEnumerate; 179 bool ok; 180 181 ResetDirectSound(); 182 120 183 dsound_dll = LoadLibrary("DSOUND.DLL"); 121 184 if (dsound_dll == NULL ) 122 185 { … … 124 187 goto error; 125 188 } 126 189 190 device_name = (parent->m_UseSPDIF) ? 191 parent->audio_passthru_device : parent->audio_main_device; 192 device_name = device_name.section(':', 1); 193 device_num = device_name.toInt(&ok, 10); 194 VERBOSE(VB_AUDIO, LOC + QString("Looking for device num:%1 or name:%2") 195 .arg(device_num).arg(device_name)); 196 197 OurDirectSoundEnumerate = 198 (LPFNDSE)GetProcAddress(dsound_dll, "DirectSoundEnumerateA" ); 199 if(OurDirectSoundEnumerate) 200 { 201 if(FAILED(OurDirectSoundEnumerate(DSEnumCallback, this))) 202 { 203 VERBOSE(VB_IMPORTANT, LOC_ERR + "DirectSoundEnumerate FAILED" ); 204 } 205 } 206 207 if (!chosenGUID) 208 { 209 device_num = 0; 210 device_name = "Primary Sound Driver"; 211 } 212 VERBOSE(VB_AUDIO, LOC + QString("Using device %1:%2") 213 .arg(device_num).arg(device_name)); 214 127 215 OurDirectSoundCreate = 128 216 (LPFNDSC)GetProcAddress(dsound_dll, "DirectSoundCreate"); 129 217 if (OurDirectSoundCreate == NULL) … … 132 220 goto error; 133 221 } 134 222 135 if (FAILED(OurDirectSoundCreate( NULL, &dsobject, NULL)))223 if (FAILED(OurDirectSoundCreate(chosenGUID, &dsobject, NULL))) 136 224 { 137 225 VERBOSE(VB_IMPORTANT, LOC_ERR + "cannot create a direct sound device" ); 138 226 goto error; … … 174 262 if (dsbuffer) 175 263 { 176 264 VERBOSE(VB_AUDIO, LOC + "Destroying DirectSound buffer"); 177 IDirectSoundBuffer_Stop(dsbuffer);265 StopPlayback(true); 178 266 IDirectSoundBuffer_Release(dsbuffer); 179 267 dsbuffer = NULL; 180 268 } 181 writeCursor = 0;182 playStarted = false;183 269 } 184 270 185 271 void AudioOutputDXPrivate::FillBuffer(unsigned char *buffer, int size) … … 284 370 { 285 371 const int srates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000 }; 286 372 vector<int> rates(srates, srates + sizeof(srates) / sizeof(int) ); 373 m_UseSPDIF = audio_passthru || audio_enc; 374 if (m_UseSPDIF) 375 { 376 rates.clear(); 377 rates.push_back(48000); 378 } 379 287 380 DSCAPS devcaps; 288 381 devcaps.dwSize = sizeof(DSCAPS); 289 382 383 m_priv->InitDirectSound(); 290 384 if ((!m_priv->dsobject || !m_priv->dsound_dll) || 291 385 FAILED(IDirectSound_GetCaps(m_priv->dsobject, &devcaps)) ) 292 386 { … … 316 410 WAVEFORMATEXTENSIBLE wf; 317 411 DSBUFFERDESC dsbdesc; 318 412 413 CloseDevice(); 414 415 m_UseSPDIF = audio_passthru || audio_enc; 416 m_priv->InitDirectSound(); 319 417 if (!m_priv->dsobject || !m_priv->dsound_dll) 320 418 { 321 419 Error("DirectSound initialization failed"); 322 420 return false; 323 421 } 324 422 325 CloseDevice();326 327 423 SetBlocking(true); 328 424 fragment_size = (source == AUDIOOUTPUT_TELEPHONY) ? 320 : 6144; 329 425 if (audio_channels > 2) 330 426 fragment_size *= 2; 331 427 soundcard_buffer_size = kFramesNum * fragment_size; 332 428 audio_bytes_per_sample = audio_bits / 8 * audio_channels; 333 m_UseSPDIF = audio_passthru || audio_enc;334 429 if (m_UseSPDIF && (audio_channels != 2)) 335 430 { 336 431 Error("SPDIF passthru requires 2 channel data"); … … 349 444 wf.SubFormat = (m_UseSPDIF) ? _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF 350 445 : _KSDATAFORMAT_SUBTYPE_PCM; 351 446 352 VERBOSE(VB_AUDIO, LOC + QString("New format: %1bits %2ch %3Hz") 353 .arg(audio_bits).arg(audio_channels).arg(audio_samplerate)); 447 VERBOSE(VB_AUDIO, LOC + QString("New format: %1bits %2ch %3Hz %4") 448 .arg(audio_bits).arg(audio_channels).arg(audio_samplerate) 449 .arg((m_UseSPDIF) ? "data" : "PCM")); 354 450 355 451 if (audio_channels <= 2) 356 452 { … … 384 480 m_priv->dsobject, &dsbdesc, &m_priv->dsbuffer, NULL); 385 481 if FAILED(dsresult) 386 482 { 387 Error(QString("Failed to create DS buffer %1").arg((DWORD)dsresult)); 388 return false; 483 if (dsresult == DSERR_UNSUPPORTED) 484 Error(QString("Unsupported format for device %1:%2") 485 .arg(m_priv->device_num).arg(m_priv->device_name)); 486 else 487 Error(QString("Failed to create DS buffer 0x%1") 488 .arg((DWORD)dsresult, 0, 16)); 489 return false; 389 490 } 390 491 VERBOSE(VB_AUDIO, LOC + "Using software mixer" ); 391 492 } … … 428 529 } 429 530 430 531 m_priv->FillBuffer(buffer, size); 431 m_priv->StartPlayback(); 532 if (!pauseaudio) 533 m_priv->StartPlayback(); 534 else 535 m_priv->playStarted = true; 432 536 } 433 537 434 538 void AudioOutputDX::Pause(bool pause) … … 482 586 .arg(play_pos).arg(write_pos).arg(m_priv->writeCursor)); 483 587 // WriteCursor is in unsafe zone - stop playback for now 484 588 // Next call to WriteAudio will restart the buffer 485 m_priv->StopPlayback(false); 589 m_priv->StopPlayback(true); 590 buffer_free = soundcard_buffer_size; 486 591 } 487 592 else if (m_priv->lastValidTime && (currentTime > m_priv->lastValidTime)) 488 593 { … … 490 595 .arg(play_pos).arg(write_pos).arg(m_priv->writeCursor) 491 596 .arg(currentTime - m_priv->lastValidTime)); 492 597 m_priv->StopPlayback(true); 598 buffer_free = soundcard_buffer_size; 493 599 } 494 600 495 601 return buffer_free; -
programs/mythfrontend/globalsettings.cpp
80 80 #endif 81 81 #ifdef USING_MINGW 82 82 gc->addSelection("Windows:"); 83 gc->addSelection("DirectX: ");83 gc->addSelection("DirectX:Primary Sound Driver"); 84 84 #endif 85 85 86 86 gc->addSelection("NULL", "NULL"); … … 164 164 165 165 gc->setLabel(QObject::tr("Digital output device")); 166 166 gc->addSelection(QObject::tr("Default"), "Default"); 167 #ifndef USING_MINGW 167 #ifdef USING_MINGW 168 gc->addSelection("DirectX:Primary Sound Driver"); 169 #else 168 170 gc->addSelection("ALSA:iec958:{ AES0 0x02 }", "ALSA:iec958:{ AES0 0x02 }"); 169 171 gc->addSelection("ALSA:hdmi", "ALSA:hdmi"); 170 172 gc->addSelection("ALSA:plughw:0,3", "ALSA:plughw:0,3"); … … 175 177 176 178 gc->setHelpText(QObject::tr("Audio output device to use for digital audio. Default is the same as Audio output " 177 179 "device. This value is currently only used with ALSA " 178 " sound output."));180 "and DirectX sound output.")); 179 181 return gc; 180 182 } 181 183