dsound: Add a function to (re)open sound device to avoid code duplication.

This commit is contained in:
Maarten Lankhorst 2007-08-27 17:07:14 +02:00 committed by Alexandre Julliard
parent 3bf6315af2
commit 7519326d03
3 changed files with 76 additions and 54 deletions

View file

@ -1413,52 +1413,15 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG
device->guid = devGUID;
device->driver = NULL;
/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
/* Get driver description */
if (device->driver) {
hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
if (hr != DS_OK) {
WARN("IDsDriver_GetDriverDesc failed\n");
return hr;
}
} else {
/* if no DirectSound interface available, use WINMM API instead */
device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
}
device->drvdesc.dnDevNode = wod;
/* If the driver requests being opened through MMSYSTEM
* (which is recommended by the DDK), it is supposed to happen
* before the DirectSound interface is opened */
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
hr = DSOUND_ReopenDevice(device, FALSE);
if (FAILED(hr))
{
DWORD flags = CALLBACK_FUNCTION;
/* disable direct sound if requested */
if (device->driver)
flags |= WAVE_DIRECTSOUND;
hr = mmErr(waveOutOpen(&(device->hwo),
device->drvdesc.dnDevNode, device->pwfx,
(DWORD_PTR)DSOUND_callback, (DWORD)device,
flags));
if (hr != DS_OK) {
WARN("waveOutOpen failed\n");
return hr;
}
WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
return hr;
}
if (device->driver) {
hr = IDsDriver_Open(device->driver);
if (hr != DS_OK) {
WARN("IDsDriver_Open failed\n");
return hr;
}
/* the driver is now open, so it's now allowed to call GetCaps */
hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
if (hr != DS_OK) {

View file

@ -426,6 +426,7 @@ HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos);
HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex);
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave);
/* duplex.c */

View file

@ -68,6 +68,67 @@ static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
device->writelead = (device->pwfx->nSamplesPerSec / 100) * nBlockAlign;
}
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
{
HRESULT hres = DS_OK;
if (device->driver)
{
IDsDriver_Close(device->driver);
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
waveOutClose(device->hwo);
IDsDriver_Release(device->driver);
device->driver = NULL;
device->buffer = NULL;
device->hwo = 0;
}
else if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
waveOutClose(device->hwo);
/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
if (ds_hw_accel != DS_HW_ACCEL_EMULATION && !forcewave)
waveOutMessage((HWAVEOUT)device->drvdesc.dnDevNode, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
/* Get driver description */
if (device->driver) {
DWORD wod = device->drvdesc.dnDevNode;
hres = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
device->drvdesc.dnDevNode = wod;
if (FAILED(hres)) {
WARN("IDsDriver_GetDriverDesc failed: %08x\n", hres);
IDsDriver_Release(device->driver);
device->driver = NULL;
}
}
/* if no DirectSound interface available, use WINMM API instead */
if (!device->driver)
device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
{
DWORD flags = CALLBACK_FUNCTION;
if (device->driver)
flags |= WAVE_DIRECTSOUND;
hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD)device, flags));
if (FAILED(hres)) {
WARN("waveOutOpen failed\n");
if (device->driver)
{
IDsDriver_Release(device->driver);
device->driver = NULL;
}
return hres;
}
}
if (device->driver)
hres = IDsDriver_Open(device->driver);
return hres;
}
static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
{
HRESULT err = DS_OK;
@ -82,17 +143,8 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
if (err != DS_OK) {
WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err);
/* Wine-only: close wine directsound driver, then reopen without WAVE_DIRECTSOUND */
IDsDriver_Close(device->driver);
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
waveOutClose(device->hwo);
IDsDriver_Release(device->driver);
device->driver = NULL;
device->buffer = NULL;
device->hwo = 0;
device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
err = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD)device, CALLBACK_FUNCTION));
if (err != DS_OK)
err = DSOUND_ReopenDevice(device, TRUE);
if (FAILED(err))
{
WARN("Falling back to waveout failed too! Giving up\n");
return err;
@ -284,9 +336,15 @@ HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
err = IDsDriverBuffer_Stop(device->hwbuf);
if (err == DSERR_BUFFERLOST) {
DSOUND_PrimaryClose(device);
err = DSOUND_PrimaryOpen(device);
err = DSOUND_ReopenDevice(device, !device->driver);
if (FAILED(err))
WARN("DSOUND_PrimaryOpen failed\n");
ERR("DSOUND_ReopenDevice failed\n");
else
{
err = DSOUND_PrimaryOpen(device);
if (FAILED(err))
WARN("DSOUND_PrimaryOpen failed\n");
}
} else if (err != DS_OK) {
WARN("IDsDriverBuffer_Stop failed\n");
}