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->guid = devGUID;
device->driver = NULL; 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; device->drvdesc.dnDevNode = wod;
hr = DSOUND_ReopenDevice(device, FALSE);
/* If the driver requests being opened through MMSYSTEM if (FAILED(hr))
* (which is recommended by the DDK), it is supposed to happen
* before the DirectSound interface is opened */
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
{ {
DWORD flags = CALLBACK_FUNCTION; WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
return hr;
/* 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;
}
} }
if (device->driver) { 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 */ /* the driver is now open, so it's now allowed to call GetCaps */
hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps)); hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
if (hr != DS_OK) { if (hr != DS_OK) {

View File

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

View File

@ -68,6 +68,67 @@ static void DSOUND_RecalcPrimary(DirectSoundDevice *device)
device->writelead = (device->pwfx->nSamplesPerSec / 100) * nBlockAlign; 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) static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
{ {
HRESULT err = DS_OK; HRESULT err = DS_OK;
@ -82,17 +143,8 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
if (err != DS_OK) { if (err != DS_OK) {
WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err); WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err);
/* Wine-only: close wine directsound driver, then reopen without WAVE_DIRECTSOUND */ err = DSOUND_ReopenDevice(device, TRUE);
IDsDriver_Close(device->driver); if (FAILED(err))
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)
{ {
WARN("Falling back to waveout failed too! Giving up\n"); WARN("Falling back to waveout failed too! Giving up\n");
return err; return err;
@ -284,9 +336,15 @@ HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
err = IDsDriverBuffer_Stop(device->hwbuf); err = IDsDriverBuffer_Stop(device->hwbuf);
if (err == DSERR_BUFFERLOST) { if (err == DSERR_BUFFERLOST) {
DSOUND_PrimaryClose(device); DSOUND_PrimaryClose(device);
err = DSOUND_PrimaryOpen(device); err = DSOUND_ReopenDevice(device, !device->driver);
if (FAILED(err)) 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) { } else if (err != DS_OK) {
WARN("IDsDriverBuffer_Stop failed\n"); WARN("IDsDriverBuffer_Stop failed\n");
} }