Commit a2f1fd3a authored by Robert Reif's avatar Robert Reif Committed by Alexandre Julliard

Add multiple DIRECTSOUND object support (multiple sound cards can play

at the same time). Fix CoCreateInstance when no sound card is present. Fix create bug found by Mike Hearn.
parent bdfcb09c
......@@ -276,7 +276,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(
oldFreq = This->freq;
This->freq = freq;
if (freq != oldFreq) {
This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->pwfx->nSamplesPerSec;
This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->device->pwfx->nSamplesPerSec;
This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
DSOUND_RecalcFormat(This);
if (!This->hwbuf)
......@@ -370,7 +370,7 @@ static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
if (This->hwbuf) {
IDsDriverBuffer_Release(This->hwbuf);
if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
if (This->dsound->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
This->buffer->ref--;
if (This->buffer->ref==0) {
HeapFree(GetProcessHeap(),0,This->buffer->memory);
......@@ -403,17 +403,17 @@ DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, DWORD pplay, DWORD p
/* the actual primary play position (pplay) is always behind last mixed (pmix),
* unless the computer is too slow or something */
/* we need to know how far away we are from there */
if (pmix < pplay) pmix += This->dsound->buflen; /* wraparound */
if (pmix < pplay) pmix += This->dsound->device->buflen; /* wraparound */
pmix -= pplay;
/* detect buffer underrun */
if (pwrite < pplay) pwrite += This->dsound->buflen; /* wraparound */
if (pwrite < pplay) pwrite += This->dsound->device->buflen; /* wraparound */
pwrite -= pplay;
if (pmix > (ds_snd_queue_max * This->dsound->fraglen + pwrite + This->dsound->writelead)) {
if (pmix > (ds_snd_queue_max * This->dsound->device->fraglen + pwrite + This->dsound->device->writelead)) {
WARN("detected an underrun: primary queue was %ld\n",pmix);
pmix = 0;
}
/* divide the offset by its sample size */
pmix /= This->dsound->pwfx->nBlockAlign;
pmix /= This->dsound->device->pwfx->nBlockAlign;
TRACE("primary back-samples=%ld\n",pmix);
/* adjust for our frequency */
pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT;
......@@ -451,13 +451,13 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
} else if (playpos) {
DWORD pplay, pwrite;
/* let's get this exact; first, recursively call GetPosition on the primary */
EnterCriticalSection(&(This->dsound->mixlock));
if (DSOUND_PrimaryGetPosition(This->dsound, &pplay, &pwrite) != DS_OK)
EnterCriticalSection(&(This->dsound->device->mixlock));
if (DSOUND_PrimaryGetPosition(This->dsound->device, &pplay, &pwrite) != DS_OK)
WARN("DSOUND_PrimaryGetPosition failed\n");
/* detect HEL mode underrun */
if (!(This->dsound->hwbuf || This->dsound->pwqueue))
if (!(This->dsound->device->hwbuf || This->dsound->device->pwqueue))
TRACE("detected an underrun\n");
if ((This->dsbd.dwFlags & DSBCAPS_GETCURRENTPOSITION2) || This->dsound->hwbuf) {
if ((This->dsbd.dwFlags & DSBCAPS_GETCURRENTPOSITION2) || This->dsound->device->hwbuf) {
/* calculate play position using this */
*playpos = DSOUND_CalcPlayPosition(This, pplay, pwrite);
} else {
......@@ -467,11 +467,11 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
* behind write cursor, hmm... */
/* let's just do what might work for Half-Life */
DWORD wp;
wp = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
wp %= This->dsound->buflen;
wp = (This->dsound->device->pwplay + ds_hel_margin) * This->dsound->device->fraglen;
wp %= This->dsound->device->buflen;
*playpos = DSOUND_CalcPlayPosition(This, wp, pwrite);
}
LeaveCriticalSection(&(This->dsound->mixlock));
LeaveCriticalSection(&(This->dsound->device->mixlock));
}
if (writepos)
*writepos = This->buf_mixpos;
......@@ -594,7 +594,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
else
This->probably_valid_to = writecursor;
if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
if (!(This->dsound->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
hres = IDsDriverBuffer_Lock(This->hwbuf,
lplpaudioptr1, audiobytes1,
lplpaudioptr2, audiobytes2,
......@@ -747,7 +747,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
/* **** */
EnterCriticalSection(&(This->lock));
if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
if (!(This->dsound->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
if (hres != DS_OK)
WARN("IDsDriverBuffer_Unlock failed\n");
......@@ -1055,8 +1055,8 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
else capf |= DSCAPS_SECONDARY8BIT;
use_hw = (ds->drvcaps.dwFlags & capf) == capf;
TRACE("use_hw = 0x%08x, capf = 0x%08lx, ds->drvcaps.dwFlags = 0x%08lx\n", use_hw, capf, ds->drvcaps.dwFlags);
use_hw = (ds->device->drvcaps.dwFlags & capf) == capf;
TRACE("use_hw = 0x%08x, capf = 0x%08lx, ds->drvcaps.dwFlags = 0x%08lx\n", use_hw, capf, ds->device->drvcaps.dwFlags);
/* FIXME: check hardware sample rate mixing capabilities */
/* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
......@@ -1074,7 +1074,7 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
}
/* Allocate system memory for buffer if applicable */
if ((ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
if ((ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) {
WARN("out of memory\n");
......@@ -1090,14 +1090,14 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
/* Allocate the hardware buffer */
if (use_hw) {
err = IDsDriver_CreateSoundBuffer(ds->driver,wfex,dsbd->dwFlags,0,
err = IDsDriver_CreateSoundBuffer(ds->device->driver,wfex,dsbd->dwFlags,0,
&(dsb->buflen),&(dsb->buffer->memory),
(LPVOID*)&(dsb->hwbuf));
/* fall back to software buffer on failure */
if (err != DS_OK) {
TRACE("IDsDriver_CreateSoundBuffer failed, falling back to software buffer\n");
use_hw = 0;
if (ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
if (ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) {
WARN("out of memory\n");
......@@ -1124,7 +1124,7 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
dsb->state = STATE_STOPPED;
dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) /
ds->pwfx->nSamplesPerSec;
ds->device->pwfx->nSamplesPerSec;
dsb->nAvgBytesPerSec = dsb->freq *
dsbd->lpwfxFormat->nBlockAlign;
......
......@@ -44,6 +44,9 @@ static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice);
static ULONG DirectSoundDevice_Release(DirectSoundDevice * device);
static const char * dumpCooperativeLevel(DWORD level)
{
static char unknown[32];
......@@ -243,52 +246,10 @@ static ULONG WINAPI IDirectSoundImpl_Release(
TRACE("(%p) ref was %ld\n", This, ref + 1);
if (!ref) {
HRESULT hres;
INT i;
timeKillEvent(This->timerID);
timeEndPeriod(DS_TIME_RES);
/* wait for timer to expire */
Sleep(DS_TIME_RES+1);
/* The sleep above should have allowed the timer process to expire
* but try to grab the lock just in case. Can't hold lock because
* IDirectSoundBufferImpl_Destroy also grabs the lock */
RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
RtlReleaseResource(&(This->buffer_list_lock));
/* It is allowed to release this object even when buffers are playing */
if (This->buffers) {
WARN("%d secondary buffers not released\n", This->nrofbuffers);
for( i=0;i<This->nrofbuffers;i++)
IDirectSoundBufferImpl_Destroy(This->buffers[i]);
}
if (This->primary) {
WARN("primary buffer not released\n");
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
}
if (This->device)
DirectSoundDevice_Release(This->device);
hres = DSOUND_PrimaryDestroy(This);
if (hres != DS_OK)
WARN("DSOUND_PrimaryDestroy failed\n");
if (This->driver)
IDsDriver_Close(This->driver);
if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
waveOutClose(This->hwo);
if (This->driver)
IDsDriver_Release(This->driver);
HeapFree(GetProcessHeap(),0,This->tmp_buffer);
HeapFree(GetProcessHeap(),0,This->buffer);
RtlDeleteResource(&This->buffer_list_lock);
This->mixlock.DebugInfo->Spare[1] = 0;
DeleteCriticalSection(&This->mixlock);
HeapFree(GetProcessHeap(),0,This);
DSOUND_renderer = NULL;
TRACE("(%p) released\n", This);
}
return ref;
......@@ -322,7 +283,7 @@ static HRESULT WINAPI DSOUND_CreateSoundBuffer(
return DSERR_INVALIDPARAM;
}
if (This->initialized == FALSE) {
if (This->device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
......@@ -359,16 +320,16 @@ static HRESULT WINAPI DSOUND_CreateSoundBuffer(
return DSERR_INVALIDPARAM;
}
if (This->primary) {
if (This->device->primary) {
WARN("Primary Buffer already created\n");
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
*ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
*ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
} else {
This->dsbd = *dsbd;
hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
if (This->primary) {
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
*ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
This->device->dsbd = *dsbd;
hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd));
if (This->device->primary) {
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
*ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
} else
WARN("PrimaryBufferImpl_Create failed\n");
}
......@@ -414,6 +375,7 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(
LPDSCAPS lpDSCaps)
{
IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
DirectSoundDevice *device;
TRACE("(%p,%p)\n",This,lpDSCaps);
if (This == NULL) {
......@@ -421,7 +383,9 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(
return DSERR_INVALIDPARAM;
}
if (This->initialized == FALSE) {
device = This->device;
if (device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
......@@ -438,30 +402,30 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(
return DSERR_INVALIDPARAM;
}
lpDSCaps->dwFlags = This->drvcaps.dwFlags;
lpDSCaps->dwFlags = device->drvcaps.dwFlags;
if (TRACE_ON(dsound)) {
TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
_dump_DSCAPS(lpDSCaps->dwFlags);
DPRINTF(")\n");
}
lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
/* driver doesn't have these */
lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
......@@ -488,7 +452,7 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
return DSERR_INVALIDPARAM;
}
if (This->initialized == FALSE) {
if (This->device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
......@@ -525,12 +489,12 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
if (pdsb->hwbuf) {
TRACE("duplicating hardware buffer\n");
hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
hres = IDsDriver_DuplicateSoundBuffer(This->device->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
if (hres != DS_OK) {
TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
dsb->hwbuf = NULL;
/* allocate buffer */
if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
if (dsb->buffer == NULL) {
WARN("out of memory\n");
......@@ -617,7 +581,7 @@ static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
WARN("level=%s not fully supported\n",
level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
}
This->priolevel = level;
This->device->priolevel = level;
return DS_OK;
}
......@@ -627,12 +591,12 @@ static HRESULT WINAPI IDirectSoundImpl_Compact(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p)\n",This);
if (This->initialized == FALSE) {
if (This->device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
if (This->priolevel != DSSCL_PRIORITY) {
if (This->device->priolevel != DSSCL_PRIORITY) {
WARN("incorrect priority level\n");
return DSERR_PRIOLEVELNEEDED;
}
......@@ -647,7 +611,7 @@ static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
if (This->initialized == FALSE) {
if (This->device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
......@@ -658,7 +622,7 @@ static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
}
WARN("not fully functional\n");
*lpdwSpeakerConfig = This->speaker_config;
*lpdwSpeakerConfig = This->device->speaker_config;
return DS_OK;
}
......@@ -669,33 +633,108 @@ static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p,0x%08lx)\n",This,config);
if (This->initialized == FALSE) {
if (This->device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
This->speaker_config = config;
This->device->speaker_config = config;
WARN("not fully functional\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSoundImpl_Initialize(
LPDIRECTSOUND8 iface,
LPCGUID lpcGuid)
LPCGUID lpcGUID)
{
IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
DirectSoundDevice *device = This->device;
HRESULT hr = DS_OK;
TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
unsigned wod, wodn;
BOOLEAN found = FALSE;
GUID devGUID;
TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID));
if (This->initialized == TRUE) {
if (device != NULL) {
WARN("already initialized\n");
return DSERR_ALREADYINITIALIZED;
}
/* Default device? */
if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
lpcGUID = &DSDEVID_DefaultPlayback;
if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
WARN("invalid parameter: lpcGUID\n");
return DSERR_INVALIDPARAM;
}
/* Enumerate WINMM audio devices and find the one we want */
wodn = waveOutGetNumDevs();
if (!wodn) {
WARN("no driver\n");
return DSERR_NODRIVER;
}
for (wod=0; wod<wodn; wod++) {
if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
found = TRUE;
break;
}
}
if (found == FALSE) {
WARN("No device found matching given ID!\n");
return DSERR_NODRIVER;
}
if (DSOUND_renderer[wod]) {
if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
device = DSOUND_renderer[wod];
device->ref++;
This->device = device;
return DS_OK;
} else {
ERR("device GUID doesn't match\n");
hr = DSERR_GENERIC;
return hr;
}
} else {
hr = DirectSoundDevice_Create(&(device));
if (hr != DS_OK) {
WARN("DirectSoundDevice_Create failed\n");
return hr;
}
}
This->device = device;
device->guid = devGUID;
/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&device->driver, 0);
/* Disable the direct sound driver to force emulation if requested. */
if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
device->driver = NULL;
/* 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 (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
{
DWORD flags = CALLBACK_FUNCTION;
......@@ -703,9 +742,9 @@ static HRESULT WINAPI IDirectSoundImpl_Initialize(
if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
flags |= WAVE_DIRECTSOUND;
hr = mmErr(waveOutOpen(&(This->hwo),
This->drvdesc.dnDevNode, This->pwfx,
(DWORD)DSOUND_callback, (DWORD)This,
hr = mmErr(waveOutOpen(&(device->hwo),
device->drvdesc.dnDevNode, device->pwfx,
(DWORD)DSOUND_callback, (DWORD)device,
flags));
if (hr != DS_OK) {
WARN("waveOutOpen failed\n");
......@@ -713,73 +752,72 @@ static HRESULT WINAPI IDirectSoundImpl_Initialize(
}
}
if (This->driver) {
hr = IDsDriver_Open(This->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 */
hr = IDsDriver_GetCaps(This->driver,&(This->drvcaps));
hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
if (hr != DS_OK) {
WARN("IDsDriver_GetCaps failed\n");
return hr;
}
} else {
WAVEOUTCAPSA woc;
hr = mmErr(waveOutGetDevCapsA(This->drvdesc.dnDevNode, &woc, sizeof(woc)));
hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
if (hr != DS_OK) {
WARN("waveOutGetDevCaps failed\n");
return hr;
}
ZeroMemory(&This->drvcaps, sizeof(This->drvcaps));
ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
(woc.dwFormats & WAVE_FORMAT_2M08) ||
(woc.dwFormats & WAVE_FORMAT_4M08) ||
(woc.dwFormats & WAVE_FORMAT_48M08) ||
(woc.dwFormats & WAVE_FORMAT_96M08)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
}
if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
(woc.dwFormats & WAVE_FORMAT_2M16) ||
(woc.dwFormats & WAVE_FORMAT_4M16) ||
(woc.dwFormats & WAVE_FORMAT_48M16) ||
(woc.dwFormats & WAVE_FORMAT_96M16)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
}
if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
(woc.dwFormats & WAVE_FORMAT_2S08) ||
(woc.dwFormats & WAVE_FORMAT_4S08) ||
(woc.dwFormats & WAVE_FORMAT_48S08) ||
(woc.dwFormats & WAVE_FORMAT_96S08)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
}
if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
(woc.dwFormats & WAVE_FORMAT_2S16) ||
(woc.dwFormats & WAVE_FORMAT_4S16) ||
(woc.dwFormats & WAVE_FORMAT_48S16) ||
(woc.dwFormats & WAVE_FORMAT_96S16)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
}
if (ds_emuldriver)
This->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
This->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
This->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
This->drvcaps.dwPrimaryBuffers = 1;
device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
device->drvcaps.dwPrimaryBuffers = 1;
}
hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)This);
hr = DSOUND_PrimaryCreate(device);
if (hr == DS_OK) {
This->initialized = TRUE;
DSOUND_renderer = (IDirectSoundImpl*)This;
DSOUND_renderer[device->drvdesc.dnDevNode] = device;
timeBeginPeriod(DS_TIME_RES);
DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
(DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
(DWORD)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
} else {
WARN("DSOUND_PrimaryCreate failed\n");
}
......@@ -794,12 +832,12 @@ static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p, %p)\n",This,pdwCertified);
if (This->initialized == FALSE) {
if (This->device == NULL) {
WARN("not initialized\n");
return DSERR_UNINITIALIZED;
}
if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
*pdwCertified = DS_CERTIFIED;
else
*pdwCertified = DS_UNCERTIFIED;
......@@ -822,142 +860,166 @@ static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
IDirectSoundImpl_VerifyCertification
};
HRESULT WINAPI IDirectSoundImpl_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND8 * ppDS)
static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
{
HRESULT err;
PIDSDRIVER drv = NULL;
IDirectSoundImpl* pDS;
unsigned wod, wodn;
BOOLEAN found = FALSE;
TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
DirectSoundDevice * device;
TRACE("(%p)\n", ppDevice);
/* Enumerate WINMM audio devices and find the one we want */
wodn = waveOutGetNumDevs();
if (!wodn) {
WARN("no driver\n");
*ppDS = NULL;
return DSERR_NODRIVER;
/* Allocate memory */
device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
if (device == NULL) {
WARN("out of memory\n");
return DSERR_OUTOFMEMORY;
}
TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
device->ref = 1;
device->driver = NULL;
device->priolevel = DSSCL_NORMAL;
device->fraglen = 0;
device->hwbuf = NULL;
device->buffer = NULL;
device->buflen = 0;
device->writelead = 0;
device->state = STATE_STOPPED;
device->nrofbuffers = 0;
device->buffers = NULL;
device->primary = NULL;
device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
device->tmp_buffer = NULL;
device->tmp_buffer_len = 0;
for (wod=0; wod<wodn; wod++) {
if (IsEqualGUID( lpcGUID, &DSOUND_renderer_guids[wod])) {
found = TRUE;
break;
}
}
/* 3D listener initial parameters */
device->listener = NULL;
device->ds3dl.dwSize = sizeof(DS3DLISTENER);
device->ds3dl.vPosition.x = 0.0;
device->ds3dl.vPosition.y = 0.0;
device->ds3dl.vPosition.z = 0.0;
device->ds3dl.vVelocity.x = 0.0;
device->ds3dl.vVelocity.y = 0.0;
device->ds3dl.vVelocity.z = 0.0;
device->ds3dl.vOrientFront.x = 0.0;
device->ds3dl.vOrientFront.y = 0.0;
device->ds3dl.vOrientFront.z = 1.0;
device->ds3dl.vOrientTop.x = 0.0;
device->ds3dl.vOrientTop.y = 1.0;
device->ds3dl.vOrientTop.z = 0.0;
device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
device->prebuf = ds_snd_queue_max;
device->guid = GUID_NULL;
if (found == FALSE) {
WARN("No device found matching given ID!\n");
*ppDS = NULL;
return DSERR_NODRIVER;
/* Set default wave format (may need it for waveOutOpen) */
device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
if (device->pwfx == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,device);
return DSERR_OUTOFMEMORY;
}
/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
/* We rely on the sound driver to return the actual sound format of
* the device if it does not support 22050x8x2 and is given the
* WAVE_DIRECTSOUND flag.
*/
device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
device->pwfx->nSamplesPerSec = 22050;
device->pwfx->wBitsPerSample = 8;
device->pwfx->nChannels = 2;
device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
device->pwfx->cbSize = 0;
/* Disable the direct sound driver to force emulation if requested. */
if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
drv = NULL;
InitializeCriticalSection(&(device->mixlock));
device->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
/* Allocate memory */
pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
if (pDS == NULL) {
WARN("out of memory\n");
*ppDS = NULL;
return DSERR_OUTOFMEMORY;
}
RtlInitializeResource(&(device->buffer_list_lock));
pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
pDS->ref = 0;
*ppDevice = device;
pDS->driver = drv;
pDS->priolevel = DSSCL_NORMAL;
pDS->fraglen = 0;
pDS->hwbuf = NULL;
pDS->buffer = NULL;
pDS->buflen = 0;
pDS->writelead = 0;
pDS->state = STATE_STOPPED;
pDS->nrofbuffers = 0;
pDS->buffers = NULL;
pDS->primary = NULL;
pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
pDS->initialized = FALSE;
pDS->tmp_buffer = NULL;
pDS->tmp_buffer_len = 0;
return DS_OK;
}
/* 3D listener initial parameters */
pDS->listener = NULL;
pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
pDS->ds3dl.vPosition.x = 0.0;
pDS->ds3dl.vPosition.y = 0.0;
pDS->ds3dl.vPosition.z = 0.0;
pDS->ds3dl.vVelocity.x = 0.0;
pDS->ds3dl.vVelocity.y = 0.0;
pDS->ds3dl.vVelocity.z = 0.0;
pDS->ds3dl.vOrientFront.x = 0.0;
pDS->ds3dl.vOrientFront.y = 0.0;
pDS->ds3dl.vOrientFront.z = 1.0;
pDS->ds3dl.vOrientTop.x = 0.0;
pDS->ds3dl.vOrientTop.y = 1.0;
pDS->ds3dl.vOrientTop.z = 0.0;
pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
pDS->prebuf = ds_snd_queue_max;
pDS->guid = *lpcGUID;
static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
{
int i;
HRESULT hr;
TRACE("(%p) ref was %lu\n", device, device->ref);
/* Get driver description */
if (drv) {
err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
if (err != DS_OK) {
WARN("IDsDriver_GetDriverDesc failed\n");
HeapFree(GetProcessHeap(),0,pDS);
*ppDS = NULL;
return err;
device->ref--;
if (device->ref == 0) {
timeKillEvent(device->timerID);
timeEndPeriod(DS_TIME_RES);
/* wait for timer to expire */
Sleep(DS_TIME_RES+1);
/* The sleep above should have allowed the timer process to expire
* but try to grab the lock just in case. Can't hold lock because
* IDirectSoundBufferImpl_Destroy also grabs the lock */
RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
RtlReleaseResource(&(device->buffer_list_lock));
/* It is allowed to release this object even when buffers are playing */
if (device->buffers) {
WARN("%d secondary buffers not released\n", device->nrofbuffers);
for( i=0;i<device->nrofbuffers;i++)
IDirectSoundBufferImpl_Destroy(device->buffers[i]);
}
} else {
/* if no DirectSound interface available, use WINMM API instead */
pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
if (device->primary) {
WARN("primary buffer not released\n");
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
}
pDS->drvdesc.dnDevNode = wod;
hr = DSOUND_PrimaryDestroy(device);
if (hr != DS_OK)
WARN("DSOUND_PrimaryDestroy failed\n");
/* Set default wave format (may need it for waveOutOpen) */
pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
if (pDS->pwfx == NULL) {
if (device->driver)
IDsDriver_Close(device->driver);
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
waveOutClose(device->hwo);
if (device->driver)
IDsDriver_Release(device->driver);
DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
HeapFree(GetProcessHeap(),0,device->tmp_buffer);
HeapFree(GetProcessHeap(),0,device->buffer);
RtlDeleteResource(&device->buffer_list_lock);
device->mixlock.DebugInfo->Spare[1] = 0;
DeleteCriticalSection(&device->mixlock);
HeapFree(GetProcessHeap(),0,device);
TRACE("(%p) released\n", device);
}
return device->ref;
}
HRESULT WINAPI IDirectSoundImpl_Create(
LPDIRECTSOUND8 * ppDS)
{
IDirectSoundImpl* pDS;
TRACE("(%p)\n",ppDS);
/* Allocate memory */
pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
if (pDS == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,pDS);
*ppDS = NULL;
return DSERR_OUTOFMEMORY;
}
/* We rely on the sound driver to return the actual sound format of
* the device if it does not support 22050x8x2 and is given the
* WAVE_DIRECTSOUND flag.
*/
pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
pDS->pwfx->nSamplesPerSec = 22050;
pDS->pwfx->wBitsPerSample = 8;
pDS->pwfx->nChannels = 2;
pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
pDS->pwfx->cbSize = 0;
InitializeCriticalSection(&(pDS->mixlock));
pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
RtlInitializeResource(&(pDS->buffer_list_lock));
pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
pDS->ref = 0;
pDS->device = NULL;
*ppDS = (LPDIRECTSOUND8)pDS;
return DS_OK;
}
/*******************************************************************************
* IDirectSound_IUnknown
*/
......@@ -1608,43 +1670,17 @@ HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
}
HRESULT WINAPI DSOUND_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND *ppDS,
IUnknown *pUnkOuter)
{
LPDIRECTSOUND8 pDS;
HRESULT hr;
GUID devGuid;
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
TRACE("(%p,%p)\n",ppDS,pUnkOuter);
/* Get dsound configuration */
setup_dsound_options();
/* Default device? */
if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
lpcGUID = &DSDEVID_DefaultPlayback;
if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
WARN("invalid parameter: lpcGUID\n");
*ppDS = NULL;
return DSERR_INVALIDPARAM;
}
if (DSOUND_renderer) {
if (IsEqualGUID(&devGuid, &DSOUND_renderer->guid)) {
hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)DSOUND_renderer, ppDS);
if (*ppDS)
IDirectSound_IDirectSound_AddRef(*ppDS);
else
WARN("IDirectSound_IDirectSound_Create failed\n");
} else {
ERR("different dsound already opened (only support one sound card at a time now)\n");
*ppDS = NULL;
hr = DSERR_ALLOCATED;
}
} else {
LPDIRECTSOUND8 pDS;
hr = IDirectSoundImpl_Create(&devGuid, &pDS);
hr = IDirectSoundImpl_Create(&pDS);
if (hr == DS_OK) {
hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
if (*ppDS)
......@@ -1653,8 +1689,9 @@ HRESULT WINAPI DSOUND_Create(
WARN("IDirectSound_IDirectSound_Create failed\n");
IDirectSound8_Release(pDS);
}
} else
} else {
WARN("IDirectSoundImpl_Create failed\n");
*ppDS = 0;
}
return hr;
......@@ -1696,14 +1733,15 @@ HRESULT WINAPI DirectSoundCreate(
return DSERR_INVALIDPARAM;
}
hr = DSOUND_Create(lpcGUID, &pDS, pUnkOuter);
hr = DSOUND_Create(&pDS, pUnkOuter);
if (hr == DS_OK) {
IDirectSound_IDirectSound * pp = (IDirectSound_IDirectSound *)pDS;
IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds);
if (!(p->initialized)) {
hr = IDirectSound_Initialize(pDS, lpcGUID);
if (hr != DS_OK)
if (hr != DS_OK) {
if (hr != DSERR_ALREADYINITIALIZED) {
IDirectSound_Release(pDS);
pDS = 0;
} else
hr = DS_OK;
}
}
......@@ -1713,43 +1751,17 @@ HRESULT WINAPI DirectSoundCreate(
}
HRESULT WINAPI DSOUND_Create8(
LPCGUID lpcGUID,
LPDIRECTSOUND8 *ppDS,
IUnknown *pUnkOuter)
{
LPDIRECTSOUND8 pDS;
HRESULT hr;
GUID devGuid;
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
TRACE("(%p,%p)\n",ppDS,pUnkOuter);
/* Get dsound configuration */
setup_dsound_options();
/* Default device? */
if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
lpcGUID = &DSDEVID_DefaultPlayback;
if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
WARN("invalid parameter: lpcGUID\n");
*ppDS = NULL;
return DSERR_INVALIDPARAM;
}
if (DSOUND_renderer) {
if (IsEqualGUID(&devGuid, &DSOUND_renderer->guid)) {
hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)DSOUND_renderer, ppDS);
if (*ppDS)
IDirectSound8_IDirectSound8_AddRef(*ppDS);
else
WARN("IDirectSound8_IDirectSound8_Create failed\n");
} else {
ERR("different dsound already opened (only support one sound card at a time now)\n");
*ppDS = NULL;
hr = DSERR_ALLOCATED;
}
} else {
LPDIRECTSOUND8 pDS;
hr = IDirectSoundImpl_Create(&devGuid, &pDS);
hr = IDirectSoundImpl_Create(&pDS);
if (hr == DS_OK) {
hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
if (*ppDS)
......@@ -1758,8 +1770,9 @@ HRESULT WINAPI DSOUND_Create8(
WARN("IDirectSound8_IDirectSound8_Create failed\n");
IDirectSound8_Release(pDS);
}
} else
} else {
WARN("IDirectSoundImpl_Create failed\n");
*ppDS = 0;
}
return hr;
......@@ -1801,14 +1814,15 @@ HRESULT WINAPI DirectSoundCreate8(
return DSERR_INVALIDPARAM;
}
hr = DSOUND_Create8(lpcGUID, &pDS, pUnkOuter);
hr = DSOUND_Create8(&pDS, pUnkOuter);
if (hr == DS_OK) {
IDirectSound8_IDirectSound8 * pp = (IDirectSound8_IDirectSound8 *)pDS;
IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds);
if (!(p->initialized)) {
hr = IDirectSound8_Initialize(pDS, lpcGUID);
if (hr != DS_OK)
if (hr != DS_OK) {
if (hr != DSERR_ALREADYINITIALIZED) {
IDirectSound8_Release(pDS);
pDS = 0;
} else
hr = DS_OK;
}
}
......@@ -1830,24 +1844,24 @@ HRESULT DSOUND_AddBuffer(
TRACE("(%p, %p)\n", pDS, pDSB);
RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
if (pDS->buffers)
newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
if (pDS->device->buffers)
newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
else
newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
if (newbuffers) {
pDS->buffers = newbuffers;
pDS->buffers[pDS->nrofbuffers] = pDSB;
pDS->nrofbuffers++;
TRACE("buffer count is now %d\n", pDS->nrofbuffers);
pDS->device->buffers = newbuffers;
pDS->device->buffers[pDS->device->nrofbuffers] = pDSB;
pDS->device->nrofbuffers++;
TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
} else {
ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->device->nrofbuffers);
hr = DSERR_OUTOFMEMORY;
}
RtlReleaseResource(&(pDS->buffer_list_lock));
RtlReleaseResource(&(pDS->device->buffer_list_lock));
return hr;
}
......@@ -1865,26 +1879,26 @@ HRESULT DSOUND_RemoveBuffer(
TRACE("(%p, %p)\n", pDS, pDSB);
RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
for (i = 0; i < pDS->nrofbuffers; i++)
if (pDS->buffers[i] == pDSB)
for (i = 0; i < pDS->device->nrofbuffers; i++)
if (pDS->device->buffers[i] == pDSB)
break;
if (i < pDS->nrofbuffers) {
if (i < pDS->device->nrofbuffers) {
/* Put the last buffer of the list in the (now empty) position */
pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
pDS->nrofbuffers--;
pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
TRACE("buffer count is now %d\n", pDS->nrofbuffers);
pDS->device->buffers[i] = pDS->device->buffers[pDS->device->nrofbuffers - 1];
pDS->device->nrofbuffers--;
pDS->device->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->device->nrofbuffers);
TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
}
if (pDS->nrofbuffers == 0) {
HeapFree(GetProcessHeap(),0,pDS->buffers);
pDS->buffers = NULL;
if (pDS->device->nrofbuffers == 0) {
HeapFree(GetProcessHeap(),0,pDS->device->buffers);
pDS->device->buffers = NULL;
}
RtlReleaseResource(&(pDS->buffer_list_lock));
RtlReleaseResource(&(pDS->device->buffer_list_lock));
return hr;
}
......@@ -68,7 +68,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound);
#define DS_SND_QUEUE_MAX 28 /* max number of fragments to prebuffer */
#define DS_SND_QUEUE_MIN 12 /* min number of fragments to prebuffer */
IDirectSoundImpl* DSOUND_renderer = NULL;
DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
......@@ -460,10 +460,10 @@ static HRESULT WINAPI DSCF_CreateInstance(
*ppobj = NULL;
if ( IsEqualIID( &IID_IDirectSound, riid ) )
return DSOUND_Create(0,(LPDIRECTSOUND*)ppobj,pOuter);
return DSOUND_Create((LPDIRECTSOUND*)ppobj,pOuter);
if ( IsEqualIID( &IID_IDirectSound8, riid ) )
return DSOUND_Create8(0,(LPDIRECTSOUND8*)ppobj,pOuter);
return DSOUND_Create8((LPDIRECTSOUND8*)ppobj,pOuter);
WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
return E_NOINTERFACE;
......@@ -664,6 +664,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_ATTACH:
TRACE("DLL_PROCESS_ATTACH\n");
for (i = 0; i < MAXWAVEDRIVERS; i++) {
DSOUND_renderer[i] = NULL;
INIT_GUID(DSOUND_renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
INIT_GUID(DSOUND_capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
}
......
......@@ -63,6 +63,7 @@ typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl;
typedef struct PrimaryBufferImpl PrimaryBufferImpl;
typedef struct SecondaryBufferImpl SecondaryBufferImpl;
typedef struct IClassFactoryImpl IClassFactoryImpl;
typedef struct DirectSoundDevice DirectSoundDevice;
/*****************************************************************************
* IDirectSound implementation structure
......@@ -72,7 +73,17 @@ struct IDirectSoundImpl
/* IUnknown fields */
IDirectSound8Vtbl *lpVtbl;
DWORD ref;
/* IDirectSoundImpl fields */
DirectSoundDevice *device;
LPUNKNOWN pUnknown;
LPDIRECTSOUND pDS;
LPDIRECTSOUND8 pDS8;
};
struct DirectSoundDevice
{
DWORD ref;
GUID guid;
PIDSDRIVER driver;
DSDRIVERDESC drvdesc;
......@@ -94,7 +105,6 @@ struct IDirectSoundImpl
PrimaryBufferImpl* primary;
DSBUFFERDESC dsbd;
DWORD speaker_config;
BOOL initialized;
LPBYTE tmp_buffer;
DWORD tmp_buffer_len;
......@@ -102,10 +112,6 @@ struct IDirectSoundImpl
IDirectSound3DListenerImpl* listener;
DS3DLISTENER ds3dl;
BOOL ds3dl_need_recalc;
LPUNKNOWN pUnknown;
LPDIRECTSOUND pDS;
LPDIRECTSOUND8 pDS8;
};
/* reference counted buffer memory for duplicated buffer memory */
......@@ -116,16 +122,13 @@ typedef struct BufferMemory
} BufferMemory;
HRESULT WINAPI IDirectSoundImpl_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND8 * ppds);
HRESULT WINAPI DSOUND_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND *ppDS,
IUnknown *pUnkOuter);
HRESULT WINAPI DSOUND_Create8(
LPCGUID lpcGUID,
LPDIRECTSOUND8 *ppDS,
IUnknown *pUnkOuter);
......@@ -461,11 +464,11 @@ HRESULT DSOUND_RemoveBuffer(IDirectSoundImpl * pDS, IDirectSoundBufferImpl * pDS
/* primary.c */
HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This);
HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos);
HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos);
/* buffer.c */
......@@ -476,8 +479,8 @@ DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, DWORD pplay, DWORD p
void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len);
void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb);
void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos);
void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq);
void DSOUND_PerformMix(IDirectSoundImpl *dsound);
void DSOUND_WaveQueue(DirectSoundDevice *device, DWORD mixq);
void DSOUND_PerformMix(DirectSoundDevice *device);
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
......@@ -493,7 +496,7 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
#define DSOUND_FREQSHIFT (14)
extern IDirectSoundImpl* DSOUND_renderer;
extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
......
......@@ -164,11 +164,12 @@ static inline BYTE cvtS16toU8(INT16 s)
static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE *obuf )
{
DirectSoundDevice * device = dsb->dsound->device;
INT fl,fr;
if (dsb->pwfx->wBitsPerSample == 8) {
if (dsb->dsound->pwfx->wBitsPerSample == 8 &&
dsb->dsound->pwfx->nChannels == dsb->pwfx->nChannels) {
if (device->pwfx->wBitsPerSample == 8 &&
device->pwfx->nChannels == dsb->pwfx->nChannels) {
/* avoid needless 8->16->8 conversion */
*obuf=*ibuf;
if (dsb->pwfx->nChannels==2)
......@@ -182,25 +183,25 @@ static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE
fr = (dsb->pwfx->nChannels==2 ? *(((INT16 *)ibuf) + 1) : fl);
}
if (dsb->dsound->pwfx->nChannels == 2) {
if (dsb->dsound->pwfx->wBitsPerSample == 8) {
if (device->pwfx->nChannels == 2) {
if (device->pwfx->wBitsPerSample == 8) {
*obuf = cvtS16toU8(fl);
*(obuf + 1) = cvtS16toU8(fr);
return;
}
if (dsb->dsound->pwfx->wBitsPerSample == 16) {
if (device->pwfx->wBitsPerSample == 16) {
*((INT16 *)obuf) = fl;
*(((INT16 *)obuf) + 1) = fr;
return;
}
}
if (dsb->dsound->pwfx->nChannels == 1) {
if (device->pwfx->nChannels == 1) {
fl = (fl + fr) >> 1;
if (dsb->dsound->pwfx->wBitsPerSample == 8) {
if (device->pwfx->wBitsPerSample == 8) {
*obuf = cvtS16toU8(fl);
return;
}
if (dsb->dsound->pwfx->wBitsPerSample == 16) {
if (device->pwfx->wBitsPerSample == 16) {
*((INT16 *)obuf) = fl;
return;
}
......@@ -213,16 +214,16 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
INT i, size, ipos, ilen;
BYTE *ibp, *obp;
INT iAdvance = dsb->pwfx->nBlockAlign;
INT oAdvance = dsb->dsound->pwfx->nBlockAlign;
INT oAdvance = dsb->dsound->device->pwfx->nBlockAlign;
ibp = dsb->buffer->memory + dsb->buf_mixpos;
obp = buf;
TRACE("(%p, %p, %p), buf_mixpos=%ld\n", dsb, ibp, obp, dsb->buf_mixpos);
/* Check for the best case */
if ((dsb->freq == dsb->dsound->pwfx->nSamplesPerSec) &&
(dsb->pwfx->wBitsPerSample == dsb->dsound->pwfx->wBitsPerSample) &&
(dsb->pwfx->nChannels == dsb->dsound->pwfx->nChannels)) {
if ((dsb->freq == dsb->dsound->device->pwfx->nSamplesPerSec) &&
(dsb->pwfx->wBitsPerSample == dsb->dsound->device->pwfx->wBitsPerSample) &&
(dsb->pwfx->nChannels == dsb->dsound->device->pwfx->nChannels)) {
INT bytesleft = dsb->buflen - dsb->buf_mixpos;
TRACE("(%p) Best case\n", dsb);
if (len <= bytesleft )
......@@ -235,9 +236,9 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
}
/* Check for same sample rate */
if (dsb->freq == dsb->dsound->pwfx->nSamplesPerSec) {
if (dsb->freq == dsb->dsound->device->pwfx->nSamplesPerSec) {
TRACE("(%p) Same sample rate %ld = primary %ld\n", dsb,
dsb->freq, dsb->dsound->pwfx->nSamplesPerSec);
dsb->freq, dsb->dsound->device->pwfx->nSamplesPerSec);
ilen = 0;
for (i = 0; i < len; i += oAdvance) {
cp_fields(dsb, ibp, obp );
......@@ -259,7 +260,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
* TransGaming Technologies Inc. */
/* FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n",
dsb, dsb->freq, dsb->dsound->pwfx->nSamplesPerSec); */
dsb, dsb->freq, dsb->dsound->device->pwfx->nSamplesPerSec); */
size = len / oAdvance;
ilen = 0;
......@@ -297,11 +298,11 @@ static void DSOUND_MixerVol(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
/* with a mono primary buffer, it could sound very weird using */
/* this method. Oh well, tough patooties. */
switch (dsb->dsound->pwfx->wBitsPerSample) {
switch (dsb->dsound->device->pwfx->wBitsPerSample) {
case 8:
/* 8-bit WAV is unsigned, but we need to operate */
/* on signed data for this to work properly */
switch (dsb->dsound->pwfx->nChannels) {
switch (dsb->dsound->device->pwfx->nChannels) {
case 1:
for (i = 0; i < len; i++) {
INT val = *bpc - 128;
......@@ -322,13 +323,13 @@ static void DSOUND_MixerVol(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
}
break;
default:
FIXME("doesn't support %d channels\n", dsb->dsound->pwfx->nChannels);
FIXME("doesn't support %d channels\n", dsb->dsound->device->pwfx->nChannels);
break;
}
break;
case 16:
/* 16-bit WAV is signed -- much better */
switch (dsb->dsound->pwfx->nChannels) {
switch (dsb->dsound->device->pwfx->nChannels) {
case 1:
for (i = 0; i < len; i += 2) {
*bps = (*bps * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16;
......@@ -344,30 +345,30 @@ static void DSOUND_MixerVol(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
}
break;
default:
FIXME("doesn't support %d channels\n", dsb->dsound->pwfx->nChannels);
FIXME("doesn't support %d channels\n", dsb->dsound->device->pwfx->nChannels);
break;
}
break;
default:
FIXME("doesn't support %d bit samples\n", dsb->dsound->pwfx->wBitsPerSample);
FIXME("doesn't support %d bit samples\n", dsb->dsound->device->pwfx->wBitsPerSample);
break;
}
}
static LPBYTE DSOUND_tmpbuffer(IDirectSoundImpl *dsound, DWORD len)
static LPBYTE DSOUND_tmpbuffer(DirectSoundDevice *device, DWORD len)
{
TRACE("(%p,%ld)\n",dsound,len);
TRACE("(%p,%ld)\n", device, len);
if (len > dsound->tmp_buffer_len) {
if (dsound->tmp_buffer)
dsound->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsound->tmp_buffer, len);
if (len > device->tmp_buffer_len) {
if (device->tmp_buffer)
device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, device->tmp_buffer, len);
else
dsound->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, len);
device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, len);
dsound->tmp_buffer_len = len;
device->tmp_buffer_len = len;
}
return dsound->tmp_buffer;
return device->tmp_buffer;
}
static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
......@@ -379,15 +380,15 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
len = fraglen;
if (!(dsb->playflags & DSBPLAY_LOOPING)) {
INT temp = MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buflen,
INT temp = MulDiv(dsb->dsound->device->pwfx->nAvgBytesPerSec, dsb->buflen,
dsb->nAvgBytesPerSec) -
MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buf_mixpos,
MulDiv(dsb->dsound->device->pwfx->nAvgBytesPerSec, dsb->buf_mixpos,
dsb->nAvgBytesPerSec);
len = min(len, temp);
}
if (len % dsb->dsound->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->dsound->pwfx->nBlockAlign;
if (len % dsb->dsound->device->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->dsound->device->pwfx->nBlockAlign;
ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign);
len = (len / nBlockAlign) * nBlockAlign; /* data alignment */
}
......@@ -397,7 +398,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
return 0;
}
if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound, len)) == NULL)
if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound->device, len)) == NULL)
return 0;
TRACE("MixInBuffer (%p) len = %d, dest = %ld\n", dsb, len, writepos);
......@@ -408,13 +409,13 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
DSOUND_MixerVol(dsb, ibuf, len);
if (dsb->dsound->pwfx->wBitsPerSample == 8) {
BYTE *obuf = dsb->dsound->buffer + writepos;
if (dsb->dsound->device->pwfx->wBitsPerSample == 8) {
BYTE *obuf = dsb->dsound->device->buffer + writepos;
if ((writepos + len) <= dsb->dsound->buflen)
if ((writepos + len) <= dsb->dsound->device->buflen)
todo = len;
else
todo = dsb->dsound->buflen - writepos;
todo = dsb->dsound->device->buflen - writepos;
for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */
......@@ -427,7 +428,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
if (todo < len) {
todo = len - todo;
obuf = dsb->dsound->buffer;
obuf = dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */
......@@ -442,12 +443,12 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
INT16 *ibufs, *obufs;
ibufs = (INT16 *) ibuf;
obufs = (INT16 *)(dsb->dsound->buffer + writepos);
obufs = (INT16 *)(dsb->dsound->device->buffer + writepos);
if ((writepos + len) <= dsb->dsound->buflen)
if ((writepos + len) <= dsb->dsound->device->buflen)
todo = len / 2;
else
todo = (dsb->dsound->buflen - writepos) / 2;
todo = (dsb->dsound->device->buflen - writepos) / 2;
for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */
......@@ -460,7 +461,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
if (todo < (len / 2)) {
todo = (len / 2) - todo;
obufs = (INT16 *)dsb->dsound->buffer;
obufs = (INT16 *)dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */
......@@ -503,13 +504,13 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
TRACE("(%p,%ld,%ld)\n",dsb,writepos,len);
if (len % dsb->dsound->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->dsound->pwfx->nBlockAlign;
if (len % dsb->dsound->device->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->dsound->device->pwfx->nBlockAlign;
ERR("length not a multiple of block size, len = %ld, block size = %d\n", len, nBlockAlign);
len = (len / nBlockAlign) * nBlockAlign; /* data alignment */
}
if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound, len)) == NULL)
if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound->device, len)) == NULL)
return;
TRACE("PhaseCancel (%p) len = %ld, dest = %ld\n", dsb, len, writepos);
......@@ -521,13 +522,13 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
DSOUND_MixerVol(dsb, ibuf, len);
/* subtract instead of add, to phase out premixed data */
if (dsb->dsound->pwfx->wBitsPerSample == 8) {
BYTE *obuf = dsb->dsound->buffer + writepos;
if (dsb->dsound->device->pwfx->wBitsPerSample == 8) {
BYTE *obuf = dsb->dsound->device->buffer + writepos;
if ((writepos + len) <= dsb->dsound->buflen)
if ((writepos + len) <= dsb->dsound->device->buflen)
todo = len;
else
todo = dsb->dsound->buflen - writepos;
todo = dsb->dsound->device->buflen - writepos;
for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */
......@@ -540,7 +541,7 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
if (todo < len) {
todo = len - todo;
obuf = dsb->dsound->buffer;
obuf = dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */
......@@ -555,12 +556,12 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
INT16 *ibufs, *obufs;
ibufs = (INT16 *) ibuf;
obufs = (INT16 *)(dsb->dsound->buffer + writepos);
obufs = (INT16 *)(dsb->dsound->device->buffer + writepos);
if ((writepos + len) <= dsb->dsound->buflen)
if ((writepos + len) <= dsb->dsound->device->buflen)
todo = len / 2;
else
todo = (dsb->dsound->buflen - writepos) / 2;
todo = (dsb->dsound->device->buflen - writepos) / 2;
for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */
......@@ -573,7 +574,7 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
if (todo < (len / 2)) {
todo = (len / 2) - todo;
obufs = (INT16 *)dsb->dsound->buffer;
obufs = (INT16 *)dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */
......@@ -591,10 +592,10 @@ static void DSOUND_MixCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, BOOL c
{
DWORD size, flen, len, npos, nlen;
INT iAdvance = dsb->pwfx->nBlockAlign;
INT oAdvance = dsb->dsound->pwfx->nBlockAlign;
INT oAdvance = dsb->dsound->device->pwfx->nBlockAlign;
/* determine amount of premixed data to cancel */
DWORD primary_done =
((dsb->primary_mixpos < writepos) ? dsb->dsound->buflen : 0) +
((dsb->primary_mixpos < writepos) ? dsb->dsound->device->buflen : 0) +
dsb->primary_mixpos - writepos;
TRACE("(%p, %ld), buf_mixpos=%ld\n", dsb, writepos, dsb->buf_mixpos);
......@@ -619,9 +620,9 @@ static void DSOUND_MixCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, BOOL c
flen = dsb->freqAcc;
nlen = len / dsb->pwfx->nBlockAlign;
nlen = ((nlen << DSOUND_FREQSHIFT) + flen) / dsb->freqAdjust;
nlen *= dsb->dsound->pwfx->nBlockAlign;
nlen *= dsb->dsound->device->pwfx->nBlockAlign;
writepos =
((dsb->primary_mixpos < nlen) ? dsb->dsound->buflen : 0) +
((dsb->primary_mixpos < nlen) ? dsb->dsound->device->buflen : 0) +
dsb->primary_mixpos - nlen;
}
......@@ -640,7 +641,7 @@ void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos)
#if 0
DWORD i, size, flen, len, npos, nlen;
INT iAdvance = dsb->pwfx->nBlockAlign;
INT oAdvance = dsb->dsound->pwfx->nBlockAlign;
INT oAdvance = dsb->dsound->device->pwfx->nBlockAlign;
/* determine amount of premixed data to cancel */
DWORD buf_done =
((dsb->buf_mixpos < buf_writepos) ? dsb->buflen : 0) +
......@@ -650,7 +651,7 @@ void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos)
WARN("(%p, %ld), buf_mixpos=%ld\n", dsb, buf_writepos, dsb->buf_mixpos);
/* since this is not implemented yet, just cancel *ALL* prebuffering for now
* (which is faster anyway when there's only a single secondary buffer) */
dsb->dsound->need_remix = TRUE;
dsb->dsound->device->need_remix = TRUE;
}
void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb)
......@@ -658,7 +659,7 @@ void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb)
TRACE("(%p)\n",dsb);
EnterCriticalSection(&dsb->lock);
if (dsb->state == STATE_PLAYING)
dsb->dsound->need_remix = TRUE;
dsb->dsound->device->need_remix = TRUE;
LeaveCriticalSection(&dsb->lock);
}
......@@ -672,11 +673,11 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri
((dsb->buf_mixpos < buf_writepos) ? dsb->buflen : 0) +
dsb->buf_mixpos - buf_writepos;
DWORD primary_done =
((dsb->primary_mixpos < writepos) ? dsb->dsound->buflen : 0) +
((dsb->primary_mixpos < writepos) ? dsb->dsound->device->buflen : 0) +
dsb->primary_mixpos - writepos;
DWORD adv_done =
((dsb->dsound->mixpos < writepos) ? dsb->dsound->buflen : 0) +
dsb->dsound->mixpos - writepos;
((dsb->dsound->device->mixpos < writepos) ? dsb->dsound->device->buflen : 0) +
dsb->dsound->device->mixpos - writepos;
DWORD played =
((buf_writepos < dsb->playpos) ? dsb->buflen : 0) +
buf_writepos - dsb->playpos;
......@@ -745,7 +746,7 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri
probably_valid_left = MulDiv(probably_valid_left,
1 << DSOUND_FREQSHIFT,
dsb->pwfx->nBlockAlign * dsb->freqAdjust) *
dsb->dsound->pwfx->nBlockAlign;
dsb->dsound->device->pwfx->nBlockAlign;
/* check whether to clip mix_len */
if (probably_valid_left < mixlen) {
TRACE("clipping to probably_valid_left=%ld\n", probably_valid_left);
......@@ -763,7 +764,7 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri
len = mixlen - primary_done;
TRACE("remaining mixlen=%ld\n", len);
if (len < dsb->dsound->fraglen) {
if (len < dsb->dsound->device->fraglen) {
/* smaller than a fragment, wait until it gets larger
* before we take the mixing overhead */
TRACE("mixlen not worth it, deferring mixing\n");
......@@ -774,20 +775,20 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri
/* ok, we know how much to mix, let's go */
still_behind = (adv_done > primary_done);
while (len) {
slen = dsb->dsound->buflen - dsb->primary_mixpos;
slen = dsb->dsound->device->buflen - dsb->primary_mixpos;
if (slen > len) slen = len;
slen = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, slen);
if ((dsb->primary_mixpos < dsb->dsound->mixpos) &&
(dsb->primary_mixpos + slen >= dsb->dsound->mixpos))
if ((dsb->primary_mixpos < dsb->dsound->device->mixpos) &&
(dsb->primary_mixpos + slen >= dsb->dsound->device->mixpos))
still_behind = FALSE;
dsb->primary_mixpos += slen; len -= slen;
dsb->primary_mixpos %= dsb->dsound->buflen;
dsb->primary_mixpos %= dsb->dsound->device->buflen;
if ((dsb->state == STATE_STOPPED) || !slen) break;
}
TRACE("new primary_mixpos=%ld, primary_advbase=%ld\n", dsb->primary_mixpos, dsb->dsound->mixpos);
TRACE("new primary_mixpos=%ld, primary_advbase=%ld\n", dsb->primary_mixpos, dsb->dsound->device->mixpos);
TRACE("mixed data len=%ld, still_behind=%d\n", mixlen-len, still_behind);
post_mix:
......@@ -807,9 +808,9 @@ post_mix:
* advance its underrun detector...*/
if (still_behind) return 0;
if ((mixlen - len) < primary_done) return 0;
slen = ((dsb->primary_mixpos < dsb->dsound->mixpos) ?
dsb->dsound->buflen : 0) + dsb->primary_mixpos -
dsb->dsound->mixpos;
slen = ((dsb->primary_mixpos < dsb->dsound->device->mixpos) ?
dsb->dsound->device->buflen : 0) + dsb->primary_mixpos -
dsb->dsound->device->mixpos;
if (slen > mixlen) {
/* the primary_done and still_behind checks above should have worked */
FIXME("problem with advancement calculation (advlen=%ld > mixlen=%ld)\n", slen, mixlen);
......@@ -818,14 +819,14 @@ post_mix:
return slen;
}
static DWORD DSOUND_MixToPrimary(IDirectSoundImpl *dsound, DWORD playpos, DWORD writepos, DWORD mixlen, BOOL recover)
static DWORD DSOUND_MixToPrimary(DirectSoundDevice *device, DWORD playpos, DWORD writepos, DWORD mixlen, BOOL recover)
{
INT i, len, maxlen = 0;
IDirectSoundBufferImpl *dsb;
TRACE("(%ld,%ld,%ld,%d)\n", playpos, writepos, mixlen, recover);
for (i = 0; i < dsound->nrofbuffers; i++) {
dsb = dsound->buffers[i];
for (i = 0; i < device->nrofbuffers; i++) {
dsb = device->buffers[i];
if (dsb->buflen && dsb->state && !dsb->hwbuf) {
TRACE("Checking %p, mixlen=%ld\n", dsb, mixlen);
......@@ -857,20 +858,20 @@ static DWORD DSOUND_MixToPrimary(IDirectSoundImpl *dsound, DWORD playpos, DWORD
return maxlen;
}
static void DSOUND_MixReset(IDirectSoundImpl *dsound, DWORD writepos)
static void DSOUND_MixReset(DirectSoundDevice *device, DWORD writepos)
{
INT i;
IDirectSoundBufferImpl *dsb;
int nfiller;
TRACE("(%ld)\n", writepos);
TRACE("(%p,%ld)\n", device, writepos);
/* the sound of silence */
nfiller = dsound->pwfx->wBitsPerSample == 8 ? 128 : 0;
nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0;
/* reset all buffer mix positions */
for (i = 0; i < dsound->nrofbuffers; i++) {
dsb = dsound->buffers[i];
for (i = 0; i < device->nrofbuffers; i++) {
dsb = device->buffers[i];
if (dsb->buflen && dsb->state && !dsb->hwbuf) {
TRACE("Resetting %p\n", dsb);
......@@ -890,72 +891,72 @@ static void DSOUND_MixReset(IDirectSoundImpl *dsound, DWORD writepos)
}
/* wipe out premixed data */
if (dsound->mixpos < writepos) {
FillMemory(dsound->buffer + writepos, dsound->buflen - writepos, nfiller);
FillMemory(dsound->buffer, dsound->mixpos, nfiller);
if (device->mixpos < writepos) {
FillMemory(device->buffer + writepos, device->buflen - writepos, nfiller);
FillMemory(device->buffer, device->mixpos, nfiller);
} else {
FillMemory(dsound->buffer + writepos, dsound->mixpos - writepos, nfiller);
FillMemory(device->buffer + writepos, device->mixpos - writepos, nfiller);
}
/* reset primary mix position */
dsound->mixpos = writepos;
device->mixpos = writepos;
}
static void DSOUND_CheckReset(IDirectSoundImpl *dsound, DWORD writepos)
static void DSOUND_CheckReset(DirectSoundDevice *device, DWORD writepos)
{
TRACE("(%p,%ld)\n",dsound,writepos);
if (dsound->need_remix) {
DSOUND_MixReset(dsound, writepos);
dsound->need_remix = FALSE;
TRACE("(%p,%ld)\n",device,writepos);
if (device->need_remix) {
DSOUND_MixReset(device, writepos);
device->need_remix = FALSE;
/* maximize Half-Life performance */
dsound->prebuf = ds_snd_queue_min;
dsound->precount = 0;
device->prebuf = ds_snd_queue_min;
device->precount = 0;
} else {
dsound->precount++;
if (dsound->precount >= 4) {
if (dsound->prebuf < ds_snd_queue_max)
dsound->prebuf++;
dsound->precount = 0;
device->precount++;
if (device->precount >= 4) {
if (device->prebuf < ds_snd_queue_max)
device->prebuf++;
device->precount = 0;
}
}
TRACE("premix adjust: %d\n", dsound->prebuf);
TRACE("premix adjust: %d\n", device->prebuf);
}
void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq)
void DSOUND_WaveQueue(DirectSoundDevice *device, DWORD mixq)
{
TRACE("(%p,%ld)\n",dsound,mixq);
if (mixq + dsound->pwqueue > ds_hel_queue) mixq = ds_hel_queue - dsound->pwqueue;
TRACE("queueing %ld buffers, starting at %d\n", mixq, dsound->pwwrite);
TRACE("(%p,%ld)\n", device, mixq);
if (mixq + device->pwqueue > ds_hel_queue) mixq = ds_hel_queue - device->pwqueue;
TRACE("queueing %ld buffers, starting at %d\n", mixq, device->pwwrite);
for (; mixq; mixq--) {
waveOutWrite(dsound->hwo, dsound->pwave[dsound->pwwrite], sizeof(WAVEHDR));
dsound->pwwrite++;
if (dsound->pwwrite >= DS_HEL_FRAGS) dsound->pwwrite = 0;
dsound->pwqueue++;
waveOutWrite(device->hwo, device->pwave[device->pwwrite], sizeof(WAVEHDR));
device->pwwrite++;
if (device->pwwrite >= DS_HEL_FRAGS) device->pwwrite = 0;
device->pwqueue++;
}
}
/* #define SYNC_CALLBACK */
void DSOUND_PerformMix(IDirectSoundImpl *dsound)
void DSOUND_PerformMix(DirectSoundDevice *device)
{
int nfiller;
BOOL forced;
HRESULT hres;
TRACE("(%p)\n", dsound);
TRACE("(%p)\n", device);
/* the sound of silence */
nfiller = dsound->pwfx->wBitsPerSample == 8 ? 128 : 0;
nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0;
/* whether the primary is forced to play even without secondary buffers */
forced = ((dsound->state == STATE_PLAYING) || (dsound->state == STATE_STARTING));
forced = ((device->state == STATE_PLAYING) || (device->state == STATE_STARTING));
if (dsound->priolevel != DSSCL_WRITEPRIMARY) {
BOOL paused = ((dsound->state == STATE_STOPPED) || (dsound->state == STATE_STARTING));
if (device->priolevel != DSSCL_WRITEPRIMARY) {
BOOL paused = ((device->state == STATE_STOPPED) || (device->state == STATE_STARTING));
/* FIXME: document variables */
DWORD playpos, writepos, inq, maxq, frag;
if (dsound->hwbuf) {
hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, &writepos);
if (device->hwbuf) {
hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, &writepos);
if (hres) {
WARN("IDsDriverBuffer_GetPosition failed\n");
return;
......@@ -964,50 +965,50 @@ void DSOUND_PerformMix(IDirectSoundImpl *dsound)
* but that's a little bit ambitious and unnecessary... */
/* rather add our safety margin to the writepos, if we're playing */
if (!paused) {
writepos += dsound->writelead;
writepos %= dsound->buflen;
writepos += device->writelead;
writepos %= device->buflen;
} else writepos = playpos;
} else {
playpos = dsound->pwplay * dsound->fraglen;
playpos = device->pwplay * device->fraglen;
writepos = playpos;
if (!paused) {
writepos += ds_hel_margin * dsound->fraglen;
writepos %= dsound->buflen;
writepos += ds_hel_margin * device->fraglen;
writepos %= device->buflen;
}
}
TRACE("primary playpos=%ld, writepos=%ld, clrpos=%ld, mixpos=%ld, buflen=%ld\n",
playpos,writepos,dsound->playpos,dsound->mixpos,dsound->buflen);
assert(dsound->playpos < dsound->buflen);
playpos,writepos,device->playpos,device->mixpos,device->buflen);
assert(device->playpos < device->buflen);
/* wipe out just-played sound data */
if (playpos < dsound->playpos) {
FillMemory(dsound->buffer + dsound->playpos, dsound->buflen - dsound->playpos, nfiller);
FillMemory(dsound->buffer, playpos, nfiller);
if (playpos < device->playpos) {
FillMemory(device->buffer + device->playpos, device->buflen - device->playpos, nfiller);
FillMemory(device->buffer, playpos, nfiller);
} else {
FillMemory(dsound->buffer + dsound->playpos, playpos - dsound->playpos, nfiller);
FillMemory(device->buffer + device->playpos, playpos - device->playpos, nfiller);
}
dsound->playpos = playpos;
device->playpos = playpos;
EnterCriticalSection(&(dsound->mixlock));
EnterCriticalSection(&(device->mixlock));
/* reset mixing if necessary */
DSOUND_CheckReset(dsound, writepos);
DSOUND_CheckReset(device, writepos);
/* check how much prebuffering is left */
inq = dsound->mixpos;
inq = device->mixpos;
if (inq < writepos)
inq += dsound->buflen;
inq += device->buflen;
inq -= writepos;
/* find the maximum we can prebuffer */
if (!paused) {
maxq = playpos;
if (maxq < writepos)
maxq += dsound->buflen;
maxq += device->buflen;
maxq -= writepos;
} else maxq = dsound->buflen;
} else maxq = device->buflen;
/* clip maxq to dsound->prebuf */
frag = dsound->prebuf * dsound->fraglen;
/* clip maxq to device->prebuf */
frag = device->prebuf * device->fraglen;
if (maxq > frag) maxq = frag;
/* check for consistency */
......@@ -1018,111 +1019,111 @@ void DSOUND_PerformMix(IDirectSoundImpl *dsound)
TRACE("reached end of mixed data (inq=%ld, maxq=%ld)\n", inq, maxq);
inq = 0;
/* stop the playback now, to allow buffers to refill */
if (dsound->state == STATE_PLAYING) {
dsound->state = STATE_STARTING;
if (device->state == STATE_PLAYING) {
device->state = STATE_STARTING;
}
else if (dsound->state == STATE_STOPPING) {
dsound->state = STATE_STOPPED;
else if (device->state == STATE_STOPPING) {
device->state = STATE_STOPPED;
}
else {
/* how can we have an underrun if we aren't playing? */
WARN("unexpected primary state (%ld)\n", dsound->state);
WARN("unexpected primary state (%ld)\n", device->state);
}
#ifdef SYNC_CALLBACK
/* DSOUND_callback may need this lock */
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
#endif
if (DSOUND_PrimaryStop(dsound) != DS_OK)
if (DSOUND_PrimaryStop(device) != DS_OK)
WARN("DSOUND_PrimaryStop failed\n");
#ifdef SYNC_CALLBACK
EnterCriticalSection(&(dsound->mixlock));
EnterCriticalSection(&(device->mixlock));
#endif
if (dsound->hwbuf) {
if (device->hwbuf) {
/* the Stop is supposed to reset play position to beginning of buffer */
/* unfortunately, OSS is not able to do so, so get current pointer */
hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, NULL);
hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, NULL);
if (hres) {
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
WARN("IDsDriverBuffer_GetPosition failed\n");
return;
}
} else {
playpos = dsound->pwplay * dsound->fraglen;
playpos = device->pwplay * device->fraglen;
}
writepos = playpos;
dsound->playpos = playpos;
dsound->mixpos = writepos;
device->playpos = playpos;
device->mixpos = writepos;
inq = 0;
maxq = dsound->buflen;
maxq = device->buflen;
if (maxq > frag) maxq = frag;
FillMemory(dsound->buffer, dsound->buflen, nfiller);
FillMemory(device->buffer, device->buflen, nfiller);
paused = TRUE;
}
/* do the mixing */
frag = DSOUND_MixToPrimary(dsound, playpos, writepos, maxq, paused);
frag = DSOUND_MixToPrimary(device, playpos, writepos, maxq, paused);
if (forced) frag = maxq - inq;
dsound->mixpos += frag;
dsound->mixpos %= dsound->buflen;
device->mixpos += frag;
device->mixpos %= device->buflen;
if (frag) {
/* buffers have been filled, restart playback */
if (dsound->state == STATE_STARTING) {
dsound->state = STATE_PLAYING;
if (device->state == STATE_STARTING) {
device->state = STATE_PLAYING;
}
else if (dsound->state == STATE_STOPPED) {
else if (device->state == STATE_STOPPED) {
/* the dsound is supposed to play if there's something to play
* even if it is reported as stopped, so don't let this confuse you */
dsound->state = STATE_STOPPING;
device->state = STATE_STOPPING;
}
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
if (paused) {
if (DSOUND_PrimaryPlay(dsound) != DS_OK)
if (DSOUND_PrimaryPlay(device) != DS_OK)
WARN("DSOUND_PrimaryPlay failed\n");
else
TRACE("starting playback\n");
}
}
else
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
} else {
/* in the DSSCL_WRITEPRIMARY mode, the app is totally in charge... */
if (dsound->state == STATE_STARTING) {
if (DSOUND_PrimaryPlay(dsound) != DS_OK)
if (device->state == STATE_STARTING) {
if (DSOUND_PrimaryPlay(device) != DS_OK)
WARN("DSOUND_PrimaryPlay failed\n");
else
dsound->state = STATE_PLAYING;
device->state = STATE_PLAYING;
}
else if (dsound->state == STATE_STOPPING) {
if (DSOUND_PrimaryStop(dsound) != DS_OK)
else if (device->state == STATE_STOPPING) {
if (DSOUND_PrimaryStop(device) != DS_OK)
WARN("DSOUND_PrimaryStop failed\n");
else
dsound->state = STATE_STOPPED;
device->state = STATE_STOPPED;
}
}
}
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
IDirectSoundImpl* This = (IDirectSoundImpl*)dwUser;
DirectSoundDevice * device = (DirectSoundDevice*)dwUser;
DWORD start_time = GetTickCount();
DWORD end_time;
TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2);
TRACE("entering at %ld\n", start_time);
if (DSOUND_renderer != This) {
if (DSOUND_renderer[device->drvdesc.dnDevNode] != device) {
ERR("dsound died without killing us?\n");
timeKillEvent(timerID);
timeEndPeriod(DS_TIME_RES);
return;
}
RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
if (This->ref)
DSOUND_PerformMix(This);
if (device->ref)
DSOUND_PerformMix(device);
RtlReleaseResource(&(This->buffer_list_lock));
RtlReleaseResource(&(device->buffer_list_lock));
end_time = GetTickCount();
TRACE("completed processing at %ld, duration = %ld\n", end_time, end_time - start_time);
......@@ -1130,28 +1131,28 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
IDirectSoundImpl* This = (IDirectSoundImpl*)dwUser;
DirectSoundDevice * device = (DirectSoundDevice*)dwUser;
TRACE("(%p,%x,%lx,%lx,%lx)\n",hwo,msg,dwUser,dw1,dw2);
TRACE("entering at %ld, msg=%08x(%s)\n", GetTickCount(), msg,
msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" :
msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN");
if (msg == MM_WOM_DONE) {
DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos;
if (This->pwqueue == (DWORD)-1) {
if (device->pwqueue == (DWORD)-1) {
TRACE("completed due to reset\n");
return;
}
/* it could be a bad idea to enter critical section here... if there's lock contention,
* the resulting scheduling delays might obstruct the winmm player thread */
#ifdef SYNC_CALLBACK
EnterCriticalSection(&(This->mixlock));
EnterCriticalSection(&(device->mixlock));
#endif
/* retrieve current values */
fraglen = This->fraglen;
buflen = This->buflen;
pwplay = This->pwplay;
fraglen = device->fraglen;
buflen = device->buflen;
pwplay = device->pwplay;
playpos = pwplay * fraglen;
mixpos = This->mixpos;
mixpos = device->mixpos;
/* check remaining mixed data */
inq = ((mixpos < playpos) ? buflen : 0) + mixpos - playpos;
mixq = inq / fraglen;
......@@ -1161,12 +1162,12 @@ void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, D
pwplay++;
if (pwplay >= DS_HEL_FRAGS) pwplay = 0;
/* write new values */
This->pwplay = pwplay;
This->pwqueue--;
device->pwplay = pwplay;
device->pwqueue--;
/* queue new buffer if we have data for it */
if (inq>1) DSOUND_WaveQueue(This, inq-1);
if (inq>1) DSOUND_WaveQueue(device, inq-1);
#ifdef SYNC_CALLBACK
LeaveCriticalSection(&(This->mixlock));
LeaveCriticalSection(&(device->mixlock));
#endif
}
TRACE("completed\n");
......
......@@ -36,48 +36,48 @@
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
void DSOUND_RecalcPrimary(IDirectSoundImpl *This)
void DSOUND_RecalcPrimary(DirectSoundDevice *device)
{
DWORD nBlockAlign;
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
nBlockAlign = This->pwfx->nBlockAlign;
if (This->hwbuf) {
nBlockAlign = device->pwfx->nBlockAlign;
if (device->hwbuf) {
DWORD fraglen;
/* let fragment size approximate the timer delay */
fraglen = (This->pwfx->nSamplesPerSec * DS_TIME_DEL / 1000) * nBlockAlign;
fraglen = (device->pwfx->nSamplesPerSec * DS_TIME_DEL / 1000) * nBlockAlign;
/* reduce fragment size until an integer number of them fits in the buffer */
/* (FIXME: this may or may not be a good idea) */
while (This->buflen % fraglen) fraglen -= nBlockAlign;
This->fraglen = fraglen;
TRACE("fraglen=%ld\n", This->fraglen);
while (device->buflen % fraglen) fraglen -= nBlockAlign;
device->fraglen = fraglen;
TRACE("fraglen=%ld\n", device->fraglen);
}
/* calculate the 10ms write lead */
This->writelead = (This->pwfx->nSamplesPerSec / 100) * nBlockAlign;
device->writelead = (device->pwfx->nSamplesPerSec / 100) * nBlockAlign;
}
static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This)
static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
{
HRESULT err = DS_OK;
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
/* are we using waveOut stuff? */
if (!This->driver) {
if (!device->driver) {
LPBYTE newbuf;
DWORD buflen;
HRESULT merr = DS_OK;
/* Start in pause mode, to allow buffers to get filled */
waveOutPause(This->hwo);
if (This->state == STATE_PLAYING) This->state = STATE_STARTING;
else if (This->state == STATE_STOPPING) This->state = STATE_STOPPED;
waveOutPause(device->hwo);
if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
/* use fragments of 10ms (1/100s) each (which should get us within
* the documented write cursor lead of 10-15ms) */
buflen = ((This->pwfx->nSamplesPerSec / 100) * This->pwfx->nBlockAlign) * DS_HEL_FRAGS;
TRACE("desired buflen=%ld, old buffer=%p\n", buflen, This->buffer);
buflen = ((device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign) * DS_HEL_FRAGS;
TRACE("desired buflen=%ld, old buffer=%p\n", buflen, device->buffer);
/* reallocate emulated primary buffer */
if (This->buffer)
newbuf = HeapReAlloc(GetProcessHeap(),0,This->buffer,buflen);
if (device->buffer)
newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
else
newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
......@@ -86,108 +86,108 @@ static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This)
merr = DSERR_OUTOFMEMORY;
/* but the old buffer might still exist and must be re-prepared */
} else {
This->buffer = newbuf;
This->buflen = buflen;
device->buffer = newbuf;
device->buflen = buflen;
}
if (This->buffer) {
if (device->buffer) {
unsigned c;
This->fraglen = This->buflen / DS_HEL_FRAGS;
device->fraglen = device->buflen / DS_HEL_FRAGS;
/* prepare fragment headers */
for (c=0; c<DS_HEL_FRAGS; c++) {
This->pwave[c]->lpData = This->buffer + c*This->fraglen;
This->pwave[c]->dwBufferLength = This->fraglen;
This->pwave[c]->dwUser = (DWORD)This;
This->pwave[c]->dwFlags = 0;
This->pwave[c]->dwLoops = 0;
err = mmErr(waveOutPrepareHeader(This->hwo,This->pwave[c],sizeof(WAVEHDR)));
device->pwave[c]->lpData = device->buffer + c*device->fraglen;
device->pwave[c]->dwBufferLength = device->fraglen;
device->pwave[c]->dwUser = (DWORD)device;
device->pwave[c]->dwFlags = 0;
device->pwave[c]->dwLoops = 0;
err = mmErr(waveOutPrepareHeader(device->hwo,device->pwave[c],sizeof(WAVEHDR)));
if (err != DS_OK) {
while (c--)
waveOutUnprepareHeader(This->hwo,This->pwave[c],sizeof(WAVEHDR));
waveOutUnprepareHeader(device->hwo,device->pwave[c],sizeof(WAVEHDR));
break;
}
}
This->pwplay = 0;
This->pwwrite = 0;
This->pwqueue = 0;
This->playpos = 0;
This->mixpos = 0;
FillMemory(This->buffer, This->buflen, (This->pwfx->wBitsPerSample == 8) ? 128 : 0);
TRACE("fraglen=%ld\n", This->fraglen);
DSOUND_WaveQueue(This, (DWORD)-1);
device->pwplay = 0;
device->pwwrite = 0;
device->pwqueue = 0;
device->playpos = 0;
device->mixpos = 0;
FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
TRACE("fraglen=%ld\n", device->fraglen);
DSOUND_WaveQueue(device, (DWORD)-1);
}
if ((err == DS_OK) && (merr != DS_OK))
err = merr;
} else if (!This->hwbuf) {
err = IDsDriver_CreateSoundBuffer(This->driver,This->pwfx,
} else if (!device->hwbuf) {
err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
DSBCAPS_PRIMARYBUFFER,0,
&(This->buflen),&(This->buffer),
(LPVOID*)&(This->hwbuf));
&(device->buflen),&(device->buffer),
(LPVOID*)&(device->hwbuf));
if (err != DS_OK) {
WARN("IDsDriver_CreateSoundBuffer failed\n");
return err;
}
if (This->state == STATE_PLAYING) This->state = STATE_STARTING;
else if (This->state == STATE_STOPPING) This->state = STATE_STOPPED;
This->playpos = 0;
This->mixpos = 0;
FillMemory(This->buffer, This->buflen, (This->pwfx->wBitsPerSample == 8) ? 128 : 0);
if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
device->playpos = 0;
device->mixpos = 0;
FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
}
return err;
}
static void DSOUND_PrimaryClose(IDirectSoundImpl *This)
static void DSOUND_PrimaryClose(DirectSoundDevice *device)
{
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
/* are we using waveOut stuff? */
if (!This->hwbuf) {
if (!device->hwbuf) {
unsigned c;
This->pwqueue = (DWORD)-1; /* resetting queues */
waveOutReset(This->hwo);
device->pwqueue = (DWORD)-1; /* resetting queues */
waveOutReset(device->hwo);
for (c=0; c<DS_HEL_FRAGS; c++)
waveOutUnprepareHeader(This->hwo, This->pwave[c], sizeof(WAVEHDR));
This->pwqueue = 0;
waveOutUnprepareHeader(device->hwo, device->pwave[c], sizeof(WAVEHDR));
device->pwqueue = 0;
} else {
if (IDsDriverBuffer_Release(This->hwbuf) == 0)
This->hwbuf = 0;
if (IDsDriverBuffer_Release(device->hwbuf) == 0)
device->hwbuf = 0;
}
}
HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This)
HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device)
{
HRESULT err = DS_OK;
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
This->buflen = This->pwfx->nAvgBytesPerSec;
device->buflen = device->pwfx->nAvgBytesPerSec;
/* FIXME: verify that hardware capabilities (DSCAPS_PRIMARY flags) match */
if (This->driver) {
err = IDsDriver_CreateSoundBuffer(This->driver,This->pwfx,
if (device->driver) {
err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
DSBCAPS_PRIMARYBUFFER,0,
&(This->buflen),&(This->buffer),
(LPVOID*)&(This->hwbuf));
&(device->buflen),&(device->buffer),
(LPVOID*)&(device->hwbuf));
if (err != DS_OK) {
WARN("IDsDriver_CreateSoundBuffer failed\n");
return err;
}
}
if (!This->hwbuf) {
if (!device->hwbuf) {
/* Allocate memory for HEL buffer headers */
unsigned c;
for (c=0; c<DS_HEL_FRAGS; c++) {
This->pwave[c] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEHDR));
if (!This->pwave[c]) {
device->pwave[c] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEHDR));
if (!device->pwave[c]) {
/* Argh, out of memory */
while (c--) {
HeapFree(GetProcessHeap(),0,This->pwave[c]);
HeapFree(GetProcessHeap(),0,device->pwave[c]);
}
WARN("out of memory\n");
return DSERR_OUTOFMEMORY;
......@@ -195,7 +195,7 @@ HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This)
}
}
err = DSOUND_PrimaryOpen(This);
err = DSOUND_PrimaryOpen(device);
if (err != DS_OK) {
WARN("DSOUND_PrimaryOpen failed\n");
......@@ -203,43 +203,43 @@ HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This)
}
/* calculate fragment size and write lead */
DSOUND_RecalcPrimary(This);
This->state = STATE_STOPPED;
DSOUND_RecalcPrimary(device);
device->state = STATE_STOPPED;
return DS_OK;
}
HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This)
HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
{
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
DSOUND_PrimaryClose(This);
if (This->driver) {
if (This->hwbuf) {
if (IDsDriverBuffer_Release(This->hwbuf) == 0)
This->hwbuf = 0;
DSOUND_PrimaryClose(device);
if (device->driver) {
if (device->hwbuf) {
if (IDsDriverBuffer_Release(device->hwbuf) == 0)
device->hwbuf = 0;
}
} else {
unsigned c;
for (c=0; c<DS_HEL_FRAGS; c++) {
HeapFree(GetProcessHeap(),0,This->pwave[c]);
HeapFree(GetProcessHeap(),0,device->pwave[c]);
}
}
HeapFree(GetProcessHeap(),0,This->pwfx);
This->pwfx=NULL;
HeapFree(GetProcessHeap(),0,device->pwfx);
device->pwfx=NULL;
return DS_OK;
}
HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This)
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device)
{
HRESULT err = DS_OK;
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
if (This->hwbuf) {
err = IDsDriverBuffer_Play(This->hwbuf, 0, 0, DSBPLAY_LOOPING);
if (device->hwbuf) {
err = IDsDriverBuffer_Play(device->hwbuf, 0, 0, DSBPLAY_LOOPING);
if (err != DS_OK)
WARN("IDsDriverBuffer_Play failed\n");
} else {
err = mmErr(waveOutRestart(This->hwo));
err = mmErr(waveOutRestart(device->hwo));
if (err != DS_OK)
WARN("waveOutRestart failed\n");
}
......@@ -247,30 +247,30 @@ HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This)
return err;
}
HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This)
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
{
HRESULT err = DS_OK;
TRACE("(%p)\n",This);
TRACE("(%p)\n", device);
if (This->hwbuf) {
err = IDsDriverBuffer_Stop(This->hwbuf);
if (device->hwbuf) {
err = IDsDriverBuffer_Stop(device->hwbuf);
if (err == DSERR_BUFFERLOST) {
DWORD flags = CALLBACK_FUNCTION;
if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
flags |= WAVE_DIRECTSOUND;
/* Wine-only: the driver wants us to reopen the device */
/* FIXME: check for errors */
IDsDriverBuffer_Release(This->hwbuf);
waveOutClose(This->hwo);
This->hwo = 0;
err = mmErr(waveOutOpen(&(This->hwo), This->drvdesc.dnDevNode,
This->pwfx, (DWORD)DSOUND_callback, (DWORD)This,
IDsDriverBuffer_Release(device->hwbuf);
waveOutClose(device->hwo);
device->hwo = 0;
err = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode,
device->pwfx, (DWORD)DSOUND_callback, (DWORD)device,
flags));
if (err == DS_OK) {
err = IDsDriver_CreateSoundBuffer(This->driver,This->pwfx,
err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
DSBCAPS_PRIMARYBUFFER,0,
&(This->buflen),&(This->buffer),
(LPVOID)&(This->hwbuf));
&(device->buflen),&(device->buffer),
(LPVOID)&(device->hwbuf));
if (err != DS_OK)
WARN("IDsDriver_CreateSoundBuffer failed\n");
} else {
......@@ -280,19 +280,19 @@ HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This)
WARN("IDsDriverBuffer_Stop failed\n");
}
} else {
err = mmErr(waveOutPause(This->hwo));
err = mmErr(waveOutPause(device->hwo));
if (err != DS_OK)
WARN("waveOutPause failed\n");
}
return err;
}
HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos)
HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos)
{
TRACE("(%p,%p,%p)\n",This,playpos,writepos);
TRACE("(%p,%p,%p)\n", device, playpos, writepos);
if (This->hwbuf) {
HRESULT err=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
if (device->hwbuf) {
HRESULT err=IDsDriverBuffer_GetPosition(device->hwbuf,playpos,writepos);
if (err) {
WARN("IDsDriverBuffer_GetPosition failed\n");
return err;
......@@ -301,19 +301,19 @@ HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWO
if (playpos) {
MMTIME mtime;
mtime.wType = TIME_BYTES;
waveOutGetPosition(This->hwo, &mtime, sizeof(mtime));
mtime.u.cb = mtime.u.cb % This->buflen;
waveOutGetPosition(device->hwo, &mtime, sizeof(mtime));
mtime.u.cb = mtime.u.cb % device->buflen;
*playpos = mtime.u.cb;
}
if (writepos) {
/* the writepos should only be used by apps with WRITEPRIMARY priority,
* in which case our software mixer is disabled anyway */
*writepos = (This->pwplay + ds_hel_margin) * This->fraglen;
while (*writepos >= This->buflen)
*writepos -= This->buflen;
*writepos = (device->pwplay + ds_hel_margin) * device->fraglen;
while (*writepos >= device->buflen)
*writepos -= device->buflen;
}
}
TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount());
TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount());
return DS_OK;
}
......@@ -325,14 +325,13 @@ HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWO
static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX wfex
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
HRESULT err = DS_OK;
int i, alloc_size, cp_size;
DWORD nSamplesPerSec;
TRACE("(%p,%p)\n",This,wfex);
TRACE("(%p,%p)\n", iface, wfex);
if (This->dsound->priolevel == DSSCL_NORMAL) {
if (device->priolevel == DSSCL_NORMAL) {
WARN("failed priority check!\n");
return DSERR_PRIOLEVELNEEDED;
}
......@@ -349,8 +348,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
wfex->wBitsPerSample, wfex->cbSize);
/* **** */
RtlAcquireResourceExclusive(&(dsound->buffer_list_lock), TRUE);
EnterCriticalSection(&(dsound->mixlock));
RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
EnterCriticalSection(&(device->mixlock));
if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
alloc_size = sizeof(WAVEFORMATEX);
......@@ -358,25 +357,25 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
} else
alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize;
dsound->pwfx = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dsound->pwfx,alloc_size);
device->pwfx = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,device->pwfx,alloc_size);
nSamplesPerSec = dsound->pwfx->nSamplesPerSec;
nSamplesPerSec = device->pwfx->nSamplesPerSec;
CopyMemory(dsound->pwfx, wfex, cp_size);
CopyMemory(device->pwfx, wfex, cp_size);
if (dsound->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) {
if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) {
DWORD flags = CALLBACK_FUNCTION;
if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
flags |= WAVE_DIRECTSOUND;
/* FIXME: check for errors */
DSOUND_PrimaryClose(dsound);
waveOutClose(dsound->hwo);
dsound->hwo = 0;
err = mmErr(waveOutOpen(&(dsound->hwo), dsound->drvdesc.dnDevNode,
dsound->pwfx, (DWORD)DSOUND_callback, (DWORD)dsound,
DSOUND_PrimaryClose(device);
waveOutClose(device->hwo);
device->hwo = 0;
err = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode,
device->pwfx, (DWORD)DSOUND_callback, (DWORD)device,
flags));
if (err == DS_OK) {
err = DSOUND_PrimaryOpen(dsound);
err = DSOUND_PrimaryOpen(device);
if (err != DS_OK) {
WARN("DSOUND_PrimaryOpen failed\n");
goto done;
......@@ -385,32 +384,32 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
WARN("waveOutOpen failed\n");
goto done;
}
} else if (dsound->hwbuf) {
err = IDsDriverBuffer_SetFormat(dsound->hwbuf, dsound->pwfx);
} else if (device->hwbuf) {
err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx);
if (err == DSERR_BUFFERLOST) {
/* Wine-only: the driver wants us to recreate the HW buffer */
IDsDriverBuffer_Release(dsound->hwbuf);
err = IDsDriver_CreateSoundBuffer(dsound->driver,dsound->pwfx,
IDsDriverBuffer_Release(device->hwbuf);
err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
DSBCAPS_PRIMARYBUFFER,0,
&(dsound->buflen),&(dsound->buffer),
(LPVOID)&(dsound->hwbuf));
&(device->buflen),&(device->buffer),
(LPVOID)&(device->hwbuf));
if (err != DS_OK) {
WARN("IDsDriver_CreateSoundBuffer failed\n");
goto done;
}
if (dsound->state == STATE_PLAYING) dsound->state = STATE_STARTING;
else if (dsound->state == STATE_STOPPING) dsound->state = STATE_STOPPED;
if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;
} else {
WARN("IDsDriverBuffer_SetFormat failed\n");
goto done;
}
/* FIXME: should we set err back to DS_OK in all cases ? */
}
DSOUND_RecalcPrimary(dsound);
DSOUND_RecalcPrimary(device);
if (nSamplesPerSec != dsound->pwfx->nSamplesPerSec) {
IDirectSoundBufferImpl** dsb = dsound->buffers;
for (i = 0; i < dsound->nrofbuffers; i++, dsb++) {
if (nSamplesPerSec != device->pwfx->nSamplesPerSec) {
IDirectSoundBufferImpl** dsb = device->buffers;
for (i = 0; i < device->nrofbuffers; i++, dsb++) {
/* **** */
EnterCriticalSection(&((*dsb)->lock));
......@@ -423,8 +422,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
}
done:
LeaveCriticalSection(&(dsound->mixlock));
RtlReleaseResource(&(dsound->buffer_list_lock));
LeaveCriticalSection(&(device->mixlock));
RtlReleaseResource(&(device->buffer_list_lock));
/* **** */
return err;
......@@ -433,15 +432,13 @@ done:
static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
LPDIRECTSOUNDBUFFER8 iface,LONG vol
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
DWORD ampfactors;
DSVOLUMEPAN volpan;
HRESULT hres = DS_OK;
TRACE("(%p,%ld)\n", iface, vol);
TRACE("(%p,%ld)\n",This,vol);
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
......@@ -452,26 +449,26 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
}
/* **** */
EnterCriticalSection(&(dsound->mixlock));
EnterCriticalSection(&(device->mixlock));
waveOutGetVolume(dsound->hwo, &ampfactors);
waveOutGetVolume(device->hwo, &ampfactors);
volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
volpan.dwTotalRightAmpFactor=ampfactors >> 16;
DSOUND_AmpFactorToVolPan(&volpan);
if (vol != volpan.lVolume) {
volpan.lVolume=vol;
DSOUND_RecalcVolPan(&volpan);
if (dsound->hwbuf) {
hres = IDsDriverBuffer_SetVolumePan(dsound->hwbuf, &volpan);
if (device->hwbuf) {
hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &volpan);
if (hres != DS_OK)
WARN("IDsDriverBuffer_SetVolumePan failed\n");
} else {
ampfactors = (volpan.dwTotalLeftAmpFactor & 0xffff) | (volpan.dwTotalRightAmpFactor << 16);
waveOutSetVolume(dsound->hwo, ampfactors);
waveOutSetVolume(device->hwo, ampfactors);
}
}
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
/* **** */
return hres;
......@@ -480,12 +477,12 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
LPDIRECTSOUNDBUFFER8 iface,LPLONG vol
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
DWORD ampfactors;
DSVOLUMEPAN volpan;
TRACE("(%p,%p)\n",This,vol);
TRACE("(%p,%p)\n", iface, vol);
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
......@@ -495,7 +492,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
return DSERR_INVALIDPARAM;
}
waveOutGetVolume(This->dsound->hwo, &ampfactors);
waveOutGetVolume(device->hwo, &ampfactors);
volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
volpan.dwTotalRightAmpFactor=ampfactors >> 16;
DSOUND_AmpFactorToVolPan(&volpan);
......@@ -507,7 +504,6 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(
LPDIRECTSOUNDBUFFER8 iface,DWORD freq
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
TRACE("(%p,%ld)\n",This,freq);
/* You cannot set the frequency of the primary buffer */
......@@ -518,12 +514,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(
static HRESULT WINAPI PrimaryBufferImpl_Play(
LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p,%08lx,%08lx,%08lx)\n",
This,reserved1,reserved2,flags
);
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%08lx,%08lx,%08lx)\n", iface, reserved1, reserved2, flags);
if (!(flags & DSBPLAY_LOOPING)) {
WARN("invalid parameter: flags = %08lx\n", flags);
......@@ -531,14 +523,14 @@ static HRESULT WINAPI PrimaryBufferImpl_Play(
}
/* **** */
EnterCriticalSection(&(dsound->mixlock));
EnterCriticalSection(&(device->mixlock));
if (dsound->state == STATE_STOPPED)
dsound->state = STATE_STARTING;
else if (dsound->state == STATE_STOPPING)
dsound->state = STATE_PLAYING;
if (device->state == STATE_STOPPED)
device->state = STATE_STARTING;
else if (device->state == STATE_STOPPING)
device->state = STATE_PLAYING;
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
/* **** */
return DS_OK;
......@@ -546,20 +538,18 @@ static HRESULT WINAPI PrimaryBufferImpl_Play(
static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
{
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p)\n",This);
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p)\n", iface);
/* **** */
EnterCriticalSection(&(dsound->mixlock));
EnterCriticalSection(&(device->mixlock));
if (dsound->state == STATE_PLAYING)
dsound->state = STATE_STOPPING;
else if (dsound->state == STATE_STARTING)
dsound->state = STATE_STOPPED;
if (device->state == STATE_PLAYING)
device->state = STATE_STOPPING;
else if (device->state == STATE_STARTING)
device->state = STATE_STOPPED;
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
/* **** */
return DS_OK;
......@@ -580,7 +570,7 @@ static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
TRACE("(%p) ref was %ld\n", This, ref + 1);
if (!ref) {
This->dsound->primary = NULL;
This->dsound->device->primary = NULL;
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
}
......@@ -591,30 +581,29 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos
) {
HRESULT hres;
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%p,%p)\n", iface, playpos, writepos);
TRACE("(%p,%p,%p)\n",This,playpos,writepos);
hres = DSOUND_PrimaryGetPosition(dsound, playpos, writepos);
hres = DSOUND_PrimaryGetPosition(device, playpos, writepos);
if (hres != DS_OK) {
WARN("DSOUND_PrimaryGetPosition failed\n");
return hres;
}
if (writepos) {
if (dsound->state != STATE_STOPPED)
if (device->state != STATE_STOPPED)
/* apply the documented 10ms lead to writepos */
*writepos += dsound->writelead;
while (*writepos >= dsound->buflen) *writepos -= dsound->buflen;
*writepos += device->writelead;
while (*writepos >= device->buflen) *writepos -= device->buflen;
}
TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount());
TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount());
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD status
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
TRACE("(%p,%p), thread is %04lx\n",This,status,GetCurrentThreadId());
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%p)\n", iface, status);
if (status == NULL) {
WARN("invalid parameter: status == NULL\n");
......@@ -622,8 +611,8 @@ static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
}
*status = 0;
if ((This->dsound->state == STATE_STARTING) ||
(This->dsound->state == STATE_PLAYING))
if ((device->state == STATE_STARTING) ||
(device->state == STATE_PLAYING))
*status |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
TRACE("status=%lx\n", *status);
......@@ -638,14 +627,14 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
LPDWORD wfwritten)
{
DWORD size;
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%p,%ld,%p)\n", iface, lpwf, wfsize, wfwritten);
size = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
if (lpwf) { /* NULL is valid */
if (wfsize >= size) {
CopyMemory(lpwf,This->dsound->pwfx,size);
CopyMemory(lpwf,device->pwfx,size);
if (wfwritten)
*wfwritten = size;
} else {
......@@ -656,7 +645,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
}
} else {
if (wfwritten)
*wfwritten = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
*wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
else {
WARN("invalid parameter: wfwritten == NULL\n");
return DSERR_INVALIDPARAM;
......@@ -669,11 +658,9 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
static HRESULT WINAPI PrimaryBufferImpl_Lock(
LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n",
This,
iface,
writecursor,
writebytes,
lplpaudioptr1,
......@@ -684,7 +671,7 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock(
GetTickCount()
);
if (dsound->priolevel != DSSCL_WRITEPRIMARY) {
if (device->priolevel != DSSCL_WRITEPRIMARY) {
WARN("failed priority check!\n");
return DSERR_PRIOLEVELNEEDED;
}
......@@ -700,16 +687,16 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock(
}
writecursor += writepos;
}
while (writecursor >= dsound->buflen)
writecursor -= dsound->buflen;
while (writecursor >= device->buflen)
writecursor -= device->buflen;
if (flags & DSBLOCK_ENTIREBUFFER)
writebytes = dsound->buflen;
if (writebytes > dsound->buflen)
writebytes = dsound->buflen;
writebytes = device->buflen;
if (writebytes > device->buflen)
writebytes = device->buflen;
if (!(dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && dsound->hwbuf) {
if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
HRESULT hres;
hres = IDsDriverBuffer_Lock(dsound->hwbuf,
hres = IDsDriverBuffer_Lock(device->hwbuf,
lplpaudioptr1, audiobytes1,
lplpaudioptr2, audiobytes2,
writecursor, writebytes,
......@@ -719,8 +706,8 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock(
return hres;
}
} else {
if (writecursor+writebytes <= dsound->buflen) {
*(LPBYTE*)lplpaudioptr1 = dsound->buffer+writecursor;
if (writecursor+writebytes <= device->buflen) {
*(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
*audiobytes1 = writebytes;
if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = NULL;
......@@ -728,12 +715,12 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock(
*audiobytes2 = 0;
TRACE("->%ld.0\n",writebytes);
} else {
*(LPBYTE*)lplpaudioptr1 = dsound->buffer+writecursor;
*audiobytes1 = dsound->buflen-writecursor;
*(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor;
*audiobytes1 = device->buflen-writecursor;
if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = dsound->buffer;
*(LPBYTE*)lplpaudioptr2 = device->buffer;
if (audiobytes2)
*audiobytes2 = writebytes-(dsound->buflen-writecursor);
*audiobytes2 = writebytes-(device->buflen-writecursor);
TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
}
}
......@@ -754,15 +741,13 @@ static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(
static HRESULT WINAPI PrimaryBufferImpl_SetPan(
LPDIRECTSOUNDBUFFER8 iface,LONG pan
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
DWORD ampfactors;
DSVOLUMEPAN volpan;
HRESULT hres = DS_OK;
TRACE("(%p,%ld)\n", iface, pan);
TRACE("(%p,%ld)\n",This,pan);
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
if (!(device->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
......@@ -773,26 +758,26 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
}
/* **** */
EnterCriticalSection(&(dsound->mixlock));
EnterCriticalSection(&(device->mixlock));
waveOutGetVolume(dsound->hwo, &ampfactors);
waveOutGetVolume(device->hwo, &ampfactors);
volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
volpan.dwTotalRightAmpFactor=ampfactors >> 16;
DSOUND_AmpFactorToVolPan(&volpan);
if (pan != volpan.lPan) {
volpan.lPan=pan;
DSOUND_RecalcVolPan(&volpan);
if (dsound->hwbuf) {
hres = IDsDriverBuffer_SetVolumePan(dsound->hwbuf, &volpan);
if (device->hwbuf) {
hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &volpan);
if (hres != DS_OK)
WARN("IDsDriverBuffer_SetVolumePan failed\n");
} else {
ampfactors = (volpan.dwTotalLeftAmpFactor & 0xffff) | (volpan.dwTotalRightAmpFactor << 16);
waveOutSetVolume(dsound->hwo, ampfactors);
waveOutSetVolume(device->hwo, ampfactors);
}
}
LeaveCriticalSection(&(dsound->mixlock));
LeaveCriticalSection(&(device->mixlock));
/* **** */
return hres;
......@@ -801,12 +786,12 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan(
static HRESULT WINAPI PrimaryBufferImpl_GetPan(
LPDIRECTSOUNDBUFFER8 iface,LPLONG pan
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
DWORD ampfactors;
DSVOLUMEPAN volpan;
TRACE("(%p,%p)\n",This,pan);
TRACE("(%p,%p)\n", iface, pan);
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
if (!(device->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
......@@ -816,7 +801,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(
return DSERR_INVALIDPARAM;
}
waveOutGetVolume(This->dsound->hwo, &ampfactors);
waveOutGetVolume(device->hwo, &ampfactors);
volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff;
volpan.dwTotalRightAmpFactor=ampfactors >> 16;
DSOUND_AmpFactorToVolPan(&volpan);
......@@ -827,20 +812,18 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan(
static HRESULT WINAPI PrimaryBufferImpl_Unlock(
LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2);
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%p,%ld,%p,%ld)\n", iface, p1, x1, p2, x2);
if (dsound->priolevel != DSSCL_WRITEPRIMARY) {
if (device->priolevel != DSSCL_WRITEPRIMARY) {
WARN("failed priority check!\n");
return DSERR_PRIOLEVELNEEDED;
}
if (!(dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && dsound->hwbuf) {
if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) {
HRESULT hres;
hres = IDsDriverBuffer_Unlock(dsound->hwbuf, p1, x1, p2, x2);
hres = IDsDriverBuffer_Unlock(device->hwbuf, p1, x1, p2, x2);
if (hres != DS_OK) {
WARN("IDsDriverBuffer_Unlock failed\n");
return hres;
......@@ -861,20 +844,20 @@ static HRESULT WINAPI PrimaryBufferImpl_Restore(
static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
TRACE("(%p,%p)\n",This,freq);
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%p)\n", iface, freq);
if (freq == NULL) {
WARN("invalid parameter: freq == NULL\n");
return DSERR_INVALIDPARAM;
}
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
if (!(device->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
*freq = This->dsound->pwfx->nSamplesPerSec;
*freq = device->pwfx->nSamplesPerSec;
TRACE("-> %ld\n", *freq);
return DS_OK;
......@@ -885,7 +868,6 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFX(
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
DWORD u;
FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
if (pdwResultCodes)
......@@ -900,7 +882,6 @@ static HRESULT WINAPI PrimaryBufferImpl_AcquireResources(
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
DWORD u;
FIXME("(%p,%08lu,%lu,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
if (pdwResultCodes)
......@@ -914,7 +895,6 @@ static HRESULT WINAPI PrimaryBufferImpl_GetObjectInPath(
LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
WARN("control unavailable\n");
......@@ -934,8 +914,8 @@ static HRESULT WINAPI PrimaryBufferImpl_Initialize(
static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
TRACE("(%p)->(%p)\n",This,caps);
DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device;
TRACE("(%p,%p)\n", iface, caps);
if (caps == NULL) {
WARN("invalid parameter: caps == NULL\n");
......@@ -947,11 +927,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
return DSERR_INVALIDPARAM;
}
caps->dwFlags = This->dsound->dsbd.dwFlags;
if (This->dsound->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
caps->dwFlags = device->dsbd.dwFlags;
if (device->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
caps->dwBufferBytes = This->dsound->buflen;
caps->dwBufferBytes = device->buflen;
/* This value represents the speed of the "unlock" command.
As unlock is quite fast (it does not do anything), I put
......@@ -967,7 +947,8 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
) {
PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
DirectSoundDevice *device = This->dsound->device;
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj);
if (ppobj == NULL) {
WARN("invalid parameter\n");
......@@ -1002,10 +983,10 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
}
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
if (!This->dsound->listener)
IDirectSound3DListenerImpl_Create(This, &This->dsound->listener);
if (This->dsound->listener) {
*ppobj = This->dsound->listener;
if (!device->listener)
IDirectSound3DListenerImpl_Create(This, &device->listener);
if (device->listener) {
*ppobj = device->listener;
IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
return S_OK;
}
......@@ -1057,7 +1038,6 @@ HRESULT WINAPI PrimaryBufferImpl_Create(
LPCDSBUFFERDESC dsbd)
{
PrimaryBufferImpl *dsb;
TRACE("%p,%p,%p)\n",ds,pdsb,dsbd);
if (dsbd->lpwfxFormat) {
......@@ -1078,14 +1058,14 @@ HRESULT WINAPI PrimaryBufferImpl_Create(
dsb->dsound = ds;
dsb->lpVtbl = &dspbvt;
CopyMemory(&ds->dsbd, dsbd, sizeof(*dsbd));
CopyMemory(&ds->device->dsbd, dsbd, sizeof(*dsbd));
TRACE("Created primary buffer at %p\n", dsb);
TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
"bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
ds->pwfx->wFormatTag, ds->pwfx->nChannels, ds->pwfx->nSamplesPerSec,
ds->pwfx->nAvgBytesPerSec, ds->pwfx->nBlockAlign,
ds->pwfx->wBitsPerSample, ds->pwfx->cbSize);
ds->device->pwfx->wFormatTag, ds->device->pwfx->nChannels, ds->device->pwfx->nSamplesPerSec,
ds->device->pwfx->nAvgBytesPerSec, ds->device->pwfx->nBlockAlign,
ds->device->pwfx->wBitsPerSample, ds->device->pwfx->cbSize);
*pdsb = dsb;
return S_OK;
......
......@@ -206,7 +206,7 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
case DS3DMODE_NORMAL:
TRACE("Normal 3D processing mode\n");
/* we need to calculate distance between buffer and listener*/
vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->dsound->ds3dl.vPosition);
vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->dsound->device->ds3dl.vPosition);
flDistance = VectorMagnitude (&vDistance);
break;
case DS3DMODE_HEADRELATIVE:
......@@ -276,16 +276,16 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
dsb->volpan.lVolume = lVolume;
/* panning */
if (dsb->dsound->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x &&
dsb->dsound->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y &&
dsb->dsound->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) {
if (dsb->dsound->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x &&
dsb->dsound->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y &&
dsb->dsound->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) {
dsb->volpan.lPan = 0;
flAngle = 0.0;
}
else
{
vDistance = VectorBetweenTwoPoints(&dsb->dsound->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
vLeft = VectorProduct(&dsb->dsound->ds3dl.vOrientFront, &dsb->dsound->ds3dl.vOrientTop);
vDistance = VectorBetweenTwoPoints(&dsb->dsound->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
vLeft = VectorProduct(&dsb->dsound->device->ds3dl.vOrientFront, &dsb->dsound->device->ds3dl.vOrientTop);
flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance);
/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */
dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000;
......@@ -295,7 +295,7 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
/* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */
#if 0
/* doppler shift*/
if ((VectorMagnitude(&ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->dsound->ds3dl.vVelocity) == 0))
if ((VectorMagnitude(&ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->dsound->device->ds3dl.vVelocity) == 0))
{
TRACE("doppler: Buffer and Listener don't have velocities\n");
}
......@@ -308,7 +308,7 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
/* calculate length of ds3dl.vVelocity component which causes Doppler Effect
NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE
if listener moves AWAY from buffer, it's velocity component is NEGATIVE */
flListenerVel = ProjectVector(&dsb->dsound->ds3dl.vVelocity, &vDistance);
flListenerVel = ProjectVector(&dsb->dsound->device->ds3dl.vVelocity, &vDistance);
/* formula taken from Gianicoli D.: Physics, 4th edition: */
/* FIXME: replace dsb->freq with appropriate frequency ! */
flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel));
......@@ -335,15 +335,15 @@ static void WINAPI DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl)
{
int i;
TRACE("(%p)\n",ds3dl);
for (i = 0; i < ds3dl->dsound->nrofbuffers; i++)
for (i = 0; i < ds3dl->dsound->device->nrofbuffers; i++)
{
/* some buffers don't have 3d buffer (Ultima IX seems to
crash without the following line) */
if (ds3dl->dsound->buffers[i]->ds3db == NULL)
if (ds3dl->dsound->device->buffers[i]->ds3db == NULL)
continue;
if (ds3dl->dsound->buffers[i]->ds3db_need_recalc)
if (ds3dl->dsound->device->buffers[i]->ds3db_need_recalc)
{
DSOUND_Mix3DBuffer(ds3dl->dsound->buffers[i]);
DSOUND_Mix3DBuffer(ds3dl->dsound->device->buffers[i]);
}
}
}
......@@ -785,10 +785,10 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
}
if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
if (!This->dsound->primary)
PrimaryBufferImpl_Create(This->dsound, &(This->dsound->primary), &(This->dsound->dsbd));
if (This->dsound->primary) {
*ppobj = This->dsound->primary;
if (!This->dsound->device->primary)
PrimaryBufferImpl_Create(This->dsound, &(This->dsound->device->primary), &(This->dsound->device->dsbd));
if (This->dsound->device->primary) {
*ppobj = This->dsound->device->primary;
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj);
return S_OK;
}
......@@ -813,7 +813,7 @@ static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER i
TRACE("(%p) ref was %ld\n", This, ref + 1);
if (!ref) {
This->dsound->listener = 0;
This->dsound->device->listener = 0;
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
}
......@@ -839,7 +839,7 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
}
TRACE("returning: all parameters\n");
*lpDS3DL = This->dsound->ds3dl;
*lpDS3DL = This->dsound->device->ds3dl;
return DS_OK;
}
......@@ -848,8 +848,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
LPD3DVALUE lpfDistanceFactor)
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Distance Factor = %f\n", This->dsound->ds3dl.flDistanceFactor);
*lpfDistanceFactor = This->dsound->ds3dl.flDistanceFactor;
TRACE("returning: Distance Factor = %f\n", This->dsound->device->ds3dl.flDistanceFactor);
*lpfDistanceFactor = This->dsound->device->ds3dl.flDistanceFactor;
return DS_OK;
}
......@@ -858,8 +858,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
LPD3DVALUE lpfDopplerFactor)
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Doppler Factor = %f\n", This->dsound->ds3dl.flDopplerFactor);
*lpfDopplerFactor = This->dsound->ds3dl.flDopplerFactor;
TRACE("returning: Doppler Factor = %f\n", This->dsound->device->ds3dl.flDopplerFactor);
*lpfDopplerFactor = This->dsound->device->ds3dl.flDopplerFactor;
return DS_OK;
}
......@@ -869,11 +869,11 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
LPD3DVECTOR lpvOrientTop)
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->ds3dl.vOrientFront.x, \
This->dsound->ds3dl.vOrientFront.y, This->dsound->ds3dl.vOrientFront.z, This->dsound->ds3dl.vOrientTop.x, This->dsound->ds3dl.vOrientTop.y, \
This->dsound->ds3dl.vOrientTop.z);
*lpvOrientFront = This->dsound->ds3dl.vOrientFront;
*lpvOrientTop = This->dsound->ds3dl.vOrientTop;
TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->device->ds3dl.vOrientFront.x, \
This->dsound->device->ds3dl.vOrientFront.y, This->dsound->device->ds3dl.vOrientFront.z, This->dsound->device->ds3dl.vOrientTop.x, This->dsound->device->ds3dl.vOrientTop.y, \
This->dsound->device->ds3dl.vOrientTop.z);
*lpvOrientFront = This->dsound->device->ds3dl.vOrientFront;
*lpvOrientTop = This->dsound->device->ds3dl.vOrientTop;
return DS_OK;
}
......@@ -882,8 +882,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
LPD3DVECTOR lpvPosition)
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Position vector = (%f,%f,%f)\n", This->dsound->ds3dl.vPosition.x, This->dsound->ds3dl.vPosition.y, This->dsound->ds3dl.vPosition.z);
*lpvPosition = This->dsound->ds3dl.vPosition;
TRACE("returning: Position vector = (%f,%f,%f)\n", This->dsound->device->ds3dl.vPosition.x, This->dsound->device->ds3dl.vPosition.y, This->dsound->device->ds3dl.vPosition.z);
*lpvPosition = This->dsound->device->ds3dl.vPosition;
return DS_OK;
}
......@@ -892,8 +892,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
LPD3DVALUE lpfRolloffFactor)
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: RolloffFactor = %f\n", This->dsound->ds3dl.flRolloffFactor);
*lpfRolloffFactor = This->dsound->ds3dl.flRolloffFactor;
TRACE("returning: RolloffFactor = %f\n", This->dsound->device->ds3dl.flRolloffFactor);
*lpfRolloffFactor = This->dsound->device->ds3dl.flRolloffFactor;
return DS_OK;
}
......@@ -902,8 +902,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
LPD3DVECTOR lpvVelocity)
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->dsound->ds3dl.vVelocity.x, This->dsound->ds3dl.vVelocity.y, This->dsound->ds3dl.vVelocity.z);
*lpvVelocity = This->dsound->ds3dl.vVelocity;
TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->dsound->device->ds3dl.vVelocity.x, This->dsound->device->ds3dl.vVelocity.y, This->dsound->device->ds3dl.vVelocity.z);
*lpvVelocity = This->dsound->device->ds3dl.vVelocity;
return DS_OK;
}
......@@ -914,13 +914,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: all parameters; dwApply = %ld\n", dwApply);
This->dsound->ds3dl = *lpcDS3DL;
This->dsound->device->ds3dl = *lpcDS3DL;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -931,13 +931,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Distance Factor = %f; dwApply = %ld\n", fDistanceFactor, dwApply);
This->dsound->ds3dl.flDistanceFactor = fDistanceFactor;
This->dsound->device->ds3dl.flDistanceFactor = fDistanceFactor;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -948,13 +948,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Doppler Factor = %f; dwApply = %ld\n", fDopplerFactor, dwApply);
This->dsound->ds3dl.flDopplerFactor = fDopplerFactor;
This->dsound->device->ds3dl.flDopplerFactor = fDopplerFactor;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -967,18 +967,18 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %ld\n", \
xFront, yFront, zFront, xTop, yTop, zTop, dwApply);
This->dsound->ds3dl.vOrientFront.x = xFront;
This->dsound->ds3dl.vOrientFront.y = yFront;
This->dsound->ds3dl.vOrientFront.z = zFront;
This->dsound->ds3dl.vOrientTop.x = xTop;
This->dsound->ds3dl.vOrientTop.y = yTop;
This->dsound->ds3dl.vOrientTop.z = zTop;
This->dsound->device->ds3dl.vOrientFront.x = xFront;
This->dsound->device->ds3dl.vOrientFront.y = yFront;
This->dsound->device->ds3dl.vOrientFront.z = zFront;
This->dsound->device->ds3dl.vOrientTop.x = xTop;
This->dsound->device->ds3dl.vOrientTop.y = yTop;
This->dsound->device->ds3dl.vOrientTop.z = zTop;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -989,15 +989,15 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->dsound->ds3dl.vPosition.x = x;
This->dsound->ds3dl.vPosition.y = y;
This->dsound->ds3dl.vPosition.z = z;
This->dsound->device->ds3dl.vPosition.x = x;
This->dsound->device->ds3dl.vPosition.y = y;
This->dsound->device->ds3dl.vPosition.z = z;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -1008,13 +1008,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Rolloff Factor = %f; dwApply = %ld\n", fRolloffFactor, dwApply);
This->dsound->ds3dl.flRolloffFactor = fRolloffFactor;
This->dsound->device->ds3dl.flRolloffFactor = fRolloffFactor;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -1025,15 +1025,15 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
{
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->dsound->ds3dl.vVelocity.x = x;
This->dsound->ds3dl.vVelocity.y = y;
This->dsound->ds3dl.vVelocity.z = z;
This->dsound->device->ds3dl.vVelocity.x = x;
This->dsound->device->ds3dl.vVelocity.y = y;
This->dsound->device->ds3dl.vVelocity.z = z;
if (dwApply == DS3D_IMMEDIATE)
{
This->dsound->ds3dl_need_recalc = FALSE;
This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This);
}
This->dsound->ds3dl_need_recalc = TRUE;
This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK;
}
......@@ -1090,24 +1090,24 @@ HRESULT WINAPI IDirectSound3DListenerImpl_Create(
dsl->dsound = This->dsound;
dsl->dsound->ds3dl.dwSize = sizeof(DS3DLISTENER);
dsl->dsound->ds3dl.vPosition.x = 0.0;
dsl->dsound->ds3dl.vPosition.y = 0.0;
dsl->dsound->ds3dl.vPosition.z = 0.0;
dsl->dsound->ds3dl.vVelocity.x = 0.0;
dsl->dsound->ds3dl.vVelocity.y = 0.0;
dsl->dsound->ds3dl.vVelocity.z = 0.0;
dsl->dsound->ds3dl.vOrientFront.x = 0.0;
dsl->dsound->ds3dl.vOrientFront.y = 0.0;
dsl->dsound->ds3dl.vOrientFront.z = 1.0;
dsl->dsound->ds3dl.vOrientTop.x = 0.0;
dsl->dsound->ds3dl.vOrientTop.y = 1.0;
dsl->dsound->ds3dl.vOrientTop.z = 0.0;
dsl->dsound->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
dsl->dsound->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
dsl->dsound->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
dsl->dsound->ds3dl_need_recalc = TRUE;
dsl->dsound->device->ds3dl.dwSize = sizeof(DS3DLISTENER);
dsl->dsound->device->ds3dl.vPosition.x = 0.0;
dsl->dsound->device->ds3dl.vPosition.y = 0.0;
dsl->dsound->device->ds3dl.vPosition.z = 0.0;
dsl->dsound->device->ds3dl.vVelocity.x = 0.0;
dsl->dsound->device->ds3dl.vVelocity.y = 0.0;
dsl->dsound->device->ds3dl.vVelocity.z = 0.0;
dsl->dsound->device->ds3dl.vOrientFront.x = 0.0;
dsl->dsound->device->ds3dl.vOrientFront.y = 0.0;
dsl->dsound->device->ds3dl.vOrientFront.z = 1.0;
dsl->dsound->device->ds3dl.vOrientTop.x = 0.0;
dsl->dsound->device->ds3dl.vOrientTop.y = 1.0;
dsl->dsound->device->ds3dl.vOrientTop.z = 0.0;
dsl->dsound->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
dsl->dsound->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
dsl->dsound->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
dsl->dsound->device->ds3dl_need_recalc = TRUE;
*pdsl = dsl;
return S_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment