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.
oldstable
Robert Reif 2005-05-31 09:31:37 +00:00 committed by Alexandre Julliard
parent bdfcb09c57
commit a2f1fd3aca
7 changed files with 903 additions and 904 deletions

View File

@ -276,7 +276,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(
oldFreq = This->freq; oldFreq = This->freq;
This->freq = freq; This->freq = freq;
if (freq != oldFreq) { 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; This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
DSOUND_RecalcFormat(This); DSOUND_RecalcFormat(This);
if (!This->hwbuf) if (!This->hwbuf)
@ -370,7 +370,7 @@ static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
if (This->hwbuf) { if (This->hwbuf) {
IDsDriverBuffer_Release(This->hwbuf); IDsDriverBuffer_Release(This->hwbuf);
if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { if (This->dsound->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
This->buffer->ref--; This->buffer->ref--;
if (This->buffer->ref==0) { if (This->buffer->ref==0) {
HeapFree(GetProcessHeap(),0,This->buffer->memory); 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), /* the actual primary play position (pplay) is always behind last mixed (pmix),
* unless the computer is too slow or something */ * unless the computer is too slow or something */
/* we need to know how far away we are from there */ /* 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; pmix -= pplay;
/* detect buffer underrun */ /* detect buffer underrun */
if (pwrite < pplay) pwrite += This->dsound->buflen; /* wraparound */ if (pwrite < pplay) pwrite += This->dsound->device->buflen; /* wraparound */
pwrite -= pplay; 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); WARN("detected an underrun: primary queue was %ld\n",pmix);
pmix = 0; pmix = 0;
} }
/* divide the offset by its sample size */ /* 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); TRACE("primary back-samples=%ld\n",pmix);
/* adjust for our frequency */ /* adjust for our frequency */
pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT; pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT;
@ -451,13 +451,13 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
} else if (playpos) { } else if (playpos) {
DWORD pplay, pwrite; DWORD pplay, pwrite;
/* let's get this exact; first, recursively call GetPosition on the primary */ /* let's get this exact; first, recursively call GetPosition on the primary */
EnterCriticalSection(&(This->dsound->mixlock)); EnterCriticalSection(&(This->dsound->device->mixlock));
if (DSOUND_PrimaryGetPosition(This->dsound, &pplay, &pwrite) != DS_OK) if (DSOUND_PrimaryGetPosition(This->dsound->device, &pplay, &pwrite) != DS_OK)
WARN("DSOUND_PrimaryGetPosition failed\n"); WARN("DSOUND_PrimaryGetPosition failed\n");
/* detect HEL mode underrun */ /* 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"); 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 */ /* calculate play position using this */
*playpos = DSOUND_CalcPlayPosition(This, pplay, pwrite); *playpos = DSOUND_CalcPlayPosition(This, pplay, pwrite);
} else { } else {
@ -467,11 +467,11 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
* behind write cursor, hmm... */ * behind write cursor, hmm... */
/* let's just do what might work for Half-Life */ /* let's just do what might work for Half-Life */
DWORD wp; DWORD wp;
wp = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen; wp = (This->dsound->device->pwplay + ds_hel_margin) * This->dsound->device->fraglen;
wp %= This->dsound->buflen; wp %= This->dsound->device->buflen;
*playpos = DSOUND_CalcPlayPosition(This, wp, pwrite); *playpos = DSOUND_CalcPlayPosition(This, wp, pwrite);
} }
LeaveCriticalSection(&(This->dsound->mixlock)); LeaveCriticalSection(&(This->dsound->device->mixlock));
} }
if (writepos) if (writepos)
*writepos = This->buf_mixpos; *writepos = This->buf_mixpos;
@ -594,7 +594,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
else else
This->probably_valid_to = writecursor; 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, hres = IDsDriverBuffer_Lock(This->hwbuf,
lplpaudioptr1, audiobytes1, lplpaudioptr1, audiobytes1,
lplpaudioptr2, audiobytes2, lplpaudioptr2, audiobytes2,
@ -747,7 +747,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
/* **** */ /* **** */
EnterCriticalSection(&(This->lock)); 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); hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
if (hres != DS_OK) if (hres != DS_OK)
WARN("IDsDriverBuffer_Unlock failed\n"); WARN("IDsDriverBuffer_Unlock failed\n");
@ -1055,8 +1055,8 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT; if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
else capf |= DSCAPS_SECONDARY8BIT; else capf |= DSCAPS_SECONDARY8BIT;
use_hw = (ds->drvcaps.dwFlags & capf) == capf; 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->drvcaps.dwFlags); 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 hardware sample rate mixing capabilities */
/* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */ /* 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 */ /* 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); dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) { if (dsb->buffer->memory == NULL) {
WARN("out of memory\n"); WARN("out of memory\n");
@ -1090,14 +1090,14 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
/* Allocate the hardware buffer */ /* Allocate the hardware buffer */
if (use_hw) { 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), &(dsb->buflen),&(dsb->buffer->memory),
(LPVOID*)&(dsb->hwbuf)); (LPVOID*)&(dsb->hwbuf));
/* fall back to software buffer on failure */ /* fall back to software buffer on failure */
if (err != DS_OK) { if (err != DS_OK) {
TRACE("IDsDriver_CreateSoundBuffer failed, falling back to software buffer\n"); TRACE("IDsDriver_CreateSoundBuffer failed, falling back to software buffer\n");
use_hw = 0; use_hw = 0;
if (ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { if (ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen); dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) { if (dsb->buffer->memory == NULL) {
WARN("out of memory\n"); WARN("out of memory\n");
@ -1124,7 +1124,7 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create(
dsb->state = STATE_STOPPED; dsb->state = STATE_STOPPED;
dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) / dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) /
ds->pwfx->nSamplesPerSec; ds->device->pwfx->nSamplesPerSec;
dsb->nAvgBytesPerSec = dsb->freq * dsb->nAvgBytesPerSec = dsb->freq *
dsbd->lpwfxFormat->nBlockAlign; dsbd->lpwfxFormat->nBlockAlign;

View File

@ -44,6 +44,9 @@ static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface); static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 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 const char * dumpCooperativeLevel(DWORD level)
{ {
static char unknown[32]; static char unknown[32];
@ -243,52 +246,10 @@ static ULONG WINAPI IDirectSoundImpl_Release(
TRACE("(%p) ref was %ld\n", This, ref + 1); TRACE("(%p) ref was %ld\n", This, ref + 1);
if (!ref) { if (!ref) {
HRESULT hres; if (This->device)
INT i; DirectSoundDevice_Release(This->device);
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);
}
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); HeapFree(GetProcessHeap(),0,This);
DSOUND_renderer = NULL;
TRACE("(%p) released\n", This); TRACE("(%p) released\n", This);
} }
return ref; return ref;
@ -322,7 +283,7 @@ static HRESULT WINAPI DSOUND_CreateSoundBuffer(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
if (This->initialized == FALSE) { if (This->device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
@ -359,16 +320,16 @@ static HRESULT WINAPI DSOUND_CreateSoundBuffer(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
if (This->primary) { if (This->device->primary) {
WARN("Primary Buffer already created\n"); WARN("Primary Buffer already created\n");
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary)); IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
*ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary); *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
} else { } else {
This->dsbd = *dsbd; This->device->dsbd = *dsbd;
hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd)); hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd));
if (This->primary) { if (This->device->primary) {
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary)); IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
*ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary); *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
} else } else
WARN("PrimaryBufferImpl_Create failed\n"); WARN("PrimaryBufferImpl_Create failed\n");
} }
@ -414,6 +375,7 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(
LPDSCAPS lpDSCaps) LPDSCAPS lpDSCaps)
{ {
IDirectSoundImpl *This = (IDirectSoundImpl *)iface; IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
DirectSoundDevice *device;
TRACE("(%p,%p)\n",This,lpDSCaps); TRACE("(%p,%p)\n",This,lpDSCaps);
if (This == NULL) { if (This == NULL) {
@ -421,7 +383,9 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
if (This->initialized == FALSE) { device = This->device;
if (device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
@ -438,30 +402,30 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
lpDSCaps->dwFlags = This->drvcaps.dwFlags; lpDSCaps->dwFlags = device->drvcaps.dwFlags;
if (TRACE_ON(dsound)) { if (TRACE_ON(dsound)) {
TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags); TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
_dump_DSCAPS(lpDSCaps->dwFlags); _dump_DSCAPS(lpDSCaps->dwFlags);
DPRINTF(")\n"); DPRINTF(")\n");
} }
lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate; lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate; lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers; lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers; lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers; lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers; lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers; lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers; lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers; lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers; lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers; lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers; lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers; lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers; lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers; lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes; lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes; lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes; lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
/* driver doesn't have these */ /* driver doesn't have these */
lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */ lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
@ -488,7 +452,7 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
if (This->initialized == FALSE) { if (This->device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
@ -525,12 +489,12 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
if (pdsb->hwbuf) { if (pdsb->hwbuf) {
TRACE("duplicating hardware buffer\n"); 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) { if (hres != DS_OK) {
TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n"); TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
dsb->hwbuf = NULL; dsb->hwbuf = NULL;
/* allocate buffer */ /* allocate buffer */
if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer))); dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
if (dsb->buffer == NULL) { if (dsb->buffer == NULL) {
WARN("out of memory\n"); WARN("out of memory\n");
@ -617,7 +581,7 @@ static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
WARN("level=%s not fully supported\n", WARN("level=%s not fully supported\n",
level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
} }
This->priolevel = level; This->device->priolevel = level;
return DS_OK; return DS_OK;
} }
@ -627,12 +591,12 @@ static HRESULT WINAPI IDirectSoundImpl_Compact(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface; IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p)\n",This); TRACE("(%p)\n",This);
if (This->initialized == FALSE) { if (This->device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
if (This->priolevel != DSSCL_PRIORITY) { if (This->device->priolevel != DSSCL_PRIORITY) {
WARN("incorrect priority level\n"); WARN("incorrect priority level\n");
return DSERR_PRIOLEVELNEEDED; return DSERR_PRIOLEVELNEEDED;
} }
@ -647,7 +611,7 @@ static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface; IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p, %p)\n",This,lpdwSpeakerConfig); TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
if (This->initialized == FALSE) { if (This->device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
@ -658,7 +622,7 @@ static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
} }
WARN("not fully functional\n"); WARN("not fully functional\n");
*lpdwSpeakerConfig = This->speaker_config; *lpdwSpeakerConfig = This->device->speaker_config;
return DS_OK; return DS_OK;
} }
@ -669,33 +633,108 @@ static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface; IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p,0x%08lx)\n",This,config); TRACE("(%p,0x%08lx)\n",This,config);
if (This->initialized == FALSE) { if (This->device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
This->speaker_config = config; This->device->speaker_config = config;
WARN("not fully functional\n"); WARN("not fully functional\n");
return DS_OK; return DS_OK;
} }
static HRESULT WINAPI IDirectSoundImpl_Initialize( static HRESULT WINAPI IDirectSoundImpl_Initialize(
LPDIRECTSOUND8 iface, LPDIRECTSOUND8 iface,
LPCGUID lpcGuid) LPCGUID lpcGUID)
{ {
IDirectSoundImpl *This = (IDirectSoundImpl *)iface; IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
DirectSoundDevice *device = This->device;
HRESULT hr = DS_OK; 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"); WARN("already initialized\n");
return DSERR_ALREADYINITIALIZED; 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 /* If the driver requests being opened through MMSYSTEM
* (which is recommended by the DDK), it is supposed to happen * (which is recommended by the DDK), it is supposed to happen
* before the DirectSound interface is opened */ * before the DirectSound interface is opened */
if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
{ {
DWORD flags = CALLBACK_FUNCTION; DWORD flags = CALLBACK_FUNCTION;
@ -703,9 +742,9 @@ static HRESULT WINAPI IDirectSoundImpl_Initialize(
if (ds_hw_accel != DS_HW_ACCEL_EMULATION) if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
flags |= WAVE_DIRECTSOUND; flags |= WAVE_DIRECTSOUND;
hr = mmErr(waveOutOpen(&(This->hwo), hr = mmErr(waveOutOpen(&(device->hwo),
This->drvdesc.dnDevNode, This->pwfx, device->drvdesc.dnDevNode, device->pwfx,
(DWORD)DSOUND_callback, (DWORD)This, (DWORD)DSOUND_callback, (DWORD)device,
flags)); flags));
if (hr != DS_OK) { if (hr != DS_OK) {
WARN("waveOutOpen failed\n"); WARN("waveOutOpen failed\n");
@ -713,73 +752,72 @@ static HRESULT WINAPI IDirectSoundImpl_Initialize(
} }
} }
if (This->driver) { if (device->driver) {
hr = IDsDriver_Open(This->driver); hr = IDsDriver_Open(device->driver);
if (hr != DS_OK) { if (hr != DS_OK) {
WARN("IDsDriver_Open failed\n"); WARN("IDsDriver_Open failed\n");
return hr; return hr;
} }
/* the driver is now open, so it's now allowed to call GetCaps */ /* the driver is now open, so it's now allowed to call GetCaps */
hr = IDsDriver_GetCaps(This->driver,&(This->drvcaps)); hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
if (hr != DS_OK) { if (hr != DS_OK) {
WARN("IDsDriver_GetCaps failed\n"); WARN("IDsDriver_GetCaps failed\n");
return hr; return hr;
} }
} else { } else {
WAVEOUTCAPSA woc; WAVEOUTCAPSA woc;
hr = mmErr(waveOutGetDevCapsA(This->drvdesc.dnDevNode, &woc, sizeof(woc))); hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
if (hr != DS_OK) { if (hr != DS_OK) {
WARN("waveOutGetDevCaps failed\n"); WARN("waveOutGetDevCaps failed\n");
return hr; return hr;
} }
ZeroMemory(&This->drvcaps, sizeof(This->drvcaps)); ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
if ((woc.dwFormats & WAVE_FORMAT_1M08) || if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
(woc.dwFormats & WAVE_FORMAT_2M08) || (woc.dwFormats & WAVE_FORMAT_2M08) ||
(woc.dwFormats & WAVE_FORMAT_4M08) || (woc.dwFormats & WAVE_FORMAT_4M08) ||
(woc.dwFormats & WAVE_FORMAT_48M08) || (woc.dwFormats & WAVE_FORMAT_48M08) ||
(woc.dwFormats & WAVE_FORMAT_96M08)) { (woc.dwFormats & WAVE_FORMAT_96M08)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
} }
if ((woc.dwFormats & WAVE_FORMAT_1M16) || if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
(woc.dwFormats & WAVE_FORMAT_2M16) || (woc.dwFormats & WAVE_FORMAT_2M16) ||
(woc.dwFormats & WAVE_FORMAT_4M16) || (woc.dwFormats & WAVE_FORMAT_4M16) ||
(woc.dwFormats & WAVE_FORMAT_48M16) || (woc.dwFormats & WAVE_FORMAT_48M16) ||
(woc.dwFormats & WAVE_FORMAT_96M16)) { (woc.dwFormats & WAVE_FORMAT_96M16)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
} }
if ((woc.dwFormats & WAVE_FORMAT_1S08) || if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
(woc.dwFormats & WAVE_FORMAT_2S08) || (woc.dwFormats & WAVE_FORMAT_2S08) ||
(woc.dwFormats & WAVE_FORMAT_4S08) || (woc.dwFormats & WAVE_FORMAT_4S08) ||
(woc.dwFormats & WAVE_FORMAT_48S08) || (woc.dwFormats & WAVE_FORMAT_48S08) ||
(woc.dwFormats & WAVE_FORMAT_96S08)) { (woc.dwFormats & WAVE_FORMAT_96S08)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
} }
if ((woc.dwFormats & WAVE_FORMAT_1S16) || if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
(woc.dwFormats & WAVE_FORMAT_2S16) || (woc.dwFormats & WAVE_FORMAT_2S16) ||
(woc.dwFormats & WAVE_FORMAT_4S16) || (woc.dwFormats & WAVE_FORMAT_4S16) ||
(woc.dwFormats & WAVE_FORMAT_48S16) || (woc.dwFormats & WAVE_FORMAT_48S16) ||
(woc.dwFormats & WAVE_FORMAT_96S16)) { (woc.dwFormats & WAVE_FORMAT_96S16)) {
This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
} }
if (ds_emuldriver) if (ds_emuldriver)
This->drvcaps.dwFlags |= DSCAPS_EMULDRIVER; device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
This->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
This->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
This->drvcaps.dwPrimaryBuffers = 1; device->drvcaps.dwPrimaryBuffers = 1;
} }
hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)This); hr = DSOUND_PrimaryCreate(device);
if (hr == DS_OK) { if (hr == DS_OK) {
This->initialized = TRUE; DSOUND_renderer[device->drvdesc.dnDevNode] = device;
DSOUND_renderer = (IDirectSoundImpl*)This;
timeBeginPeriod(DS_TIME_RES); timeBeginPeriod(DS_TIME_RES);
DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer, DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
(DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); (DWORD)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
} else { } else {
WARN("DSOUND_PrimaryCreate failed\n"); WARN("DSOUND_PrimaryCreate failed\n");
} }
@ -794,12 +832,12 @@ static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
IDirectSoundImpl *This = (IDirectSoundImpl *)iface; IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
TRACE("(%p, %p)\n",This,pdwCertified); TRACE("(%p, %p)\n",This,pdwCertified);
if (This->initialized == FALSE) { if (This->device == NULL) {
WARN("not initialized\n"); WARN("not initialized\n");
return DSERR_UNINITIALIZED; return DSERR_UNINITIALIZED;
} }
if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED) if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
*pdwCertified = DS_CERTIFIED; *pdwCertified = DS_CERTIFIED;
else else
*pdwCertified = DS_UNCERTIFIED; *pdwCertified = DS_UNCERTIFIED;
@ -822,46 +860,148 @@ static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
IDirectSoundImpl_VerifyCertification IDirectSoundImpl_VerifyCertification
}; };
static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
{
DirectSoundDevice * device;
TRACE("(%p)\n", ppDevice);
/* Allocate memory */
device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
if (device == NULL) {
WARN("out of memory\n");
return DSERR_OUTOFMEMORY;
}
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;
/* 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;
/* 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;
}
/* 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;
InitializeCriticalSection(&(device->mixlock));
device->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
RtlInitializeResource(&(device->buffer_list_lock));
*ppDevice = device;
return DS_OK;
}
static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
{
int i;
HRESULT hr;
TRACE("(%p) ref was %lu\n", device, device->ref);
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]);
}
if (device->primary) {
WARN("primary buffer not released\n");
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
}
hr = DSOUND_PrimaryDestroy(device);
if (hr != DS_OK)
WARN("DSOUND_PrimaryDestroy failed\n");
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( HRESULT WINAPI IDirectSoundImpl_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND8 * ppDS) LPDIRECTSOUND8 * ppDS)
{ {
HRESULT err;
PIDSDRIVER drv = NULL;
IDirectSoundImpl* pDS; IDirectSoundImpl* pDS;
unsigned wod, wodn; TRACE("(%p)\n",ppDS);
BOOLEAN found = FALSE;
TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
/* Enumerate WINMM audio devices and find the one we want */
wodn = waveOutGetNumDevs();
if (!wodn) {
WARN("no driver\n");
*ppDS = NULL;
return DSERR_NODRIVER;
}
TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
for (wod=0; wod<wodn; wod++) {
if (IsEqualGUID( lpcGUID, &DSOUND_renderer_guids[wod])) {
found = TRUE;
break;
}
}
if (found == FALSE) {
WARN("No device found matching given ID!\n");
*ppDS = NULL;
return DSERR_NODRIVER;
}
/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
/* Disable the direct sound driver to force emulation if requested. */
if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
drv = NULL;
/* Allocate memory */ /* Allocate memory */
pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl)); pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
@ -871,93 +1011,15 @@ HRESULT WINAPI IDirectSoundImpl_Create(
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
pDS->lpVtbl = &IDirectSoundImpl_Vtbl; pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
pDS->ref = 0; pDS->ref = 0;
pDS->device = NULL;
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;
/* 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;
/* 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;
}
} else {
/* if no DirectSound interface available, use WINMM API instead */
pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
}
pDS->drvdesc.dnDevNode = wod;
/* Set default wave format (may need it for waveOutOpen) */
pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
if (pDS->pwfx == 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));
*ppDS = (LPDIRECTSOUND8)pDS; *ppDS = (LPDIRECTSOUND8)pDS;
return DS_OK; return DS_OK;
} }
/******************************************************************************* /*******************************************************************************
* IDirectSound_IUnknown * IDirectSound_IUnknown
*/ */
@ -1608,53 +1670,28 @@ HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
} }
HRESULT WINAPI DSOUND_Create( HRESULT WINAPI DSOUND_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND *ppDS, LPDIRECTSOUND *ppDS,
IUnknown *pUnkOuter) IUnknown *pUnkOuter)
{ {
LPDIRECTSOUND8 pDS;
HRESULT hr; HRESULT hr;
GUID devGuid; TRACE("(%p,%p)\n",ppDS,pUnkOuter);
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
/* Get dsound configuration */ /* Get dsound configuration */
setup_dsound_options(); setup_dsound_options();
/* Default device? */ hr = IDirectSoundImpl_Create(&pDS);
if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL)) if (hr == DS_OK) {
lpcGUID = &DSDEVID_DefaultPlayback; hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
if (*ppDS)
if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) { IDirectSound_IDirectSound_AddRef(*ppDS);
WARN("invalid parameter: lpcGUID\n"); else {
*ppDS = NULL; WARN("IDirectSound_IDirectSound_Create failed\n");
return DSERR_INVALIDPARAM; IDirectSound8_Release(pDS);
}
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 { } else {
LPDIRECTSOUND8 pDS; WARN("IDirectSoundImpl_Create failed\n");
hr = IDirectSoundImpl_Create(&devGuid, &pDS); *ppDS = 0;
if (hr == DS_OK) {
hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
if (*ppDS)
IDirectSound_IDirectSound_AddRef(*ppDS);
else {
WARN("IDirectSound_IDirectSound_Create failed\n");
IDirectSound8_Release(pDS);
}
} else
WARN("IDirectSoundImpl_Create failed\n");
} }
return hr; return hr;
@ -1696,14 +1733,15 @@ HRESULT WINAPI DirectSoundCreate(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
hr = DSOUND_Create(lpcGUID, &pDS, pUnkOuter); hr = DSOUND_Create(&pDS, pUnkOuter);
if (hr == DS_OK) { if (hr == DS_OK) {
IDirectSound_IDirectSound * pp = (IDirectSound_IDirectSound *)pDS; hr = IDirectSound_Initialize(pDS, lpcGUID);
IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds); if (hr != DS_OK) {
if (!(p->initialized)) { if (hr != DSERR_ALREADYINITIALIZED) {
hr = IDirectSound_Initialize(pDS, lpcGUID);
if (hr != DS_OK)
IDirectSound_Release(pDS); IDirectSound_Release(pDS);
pDS = 0;
} else
hr = DS_OK;
} }
} }
@ -1713,53 +1751,28 @@ HRESULT WINAPI DirectSoundCreate(
} }
HRESULT WINAPI DSOUND_Create8( HRESULT WINAPI DSOUND_Create8(
LPCGUID lpcGUID,
LPDIRECTSOUND8 *ppDS, LPDIRECTSOUND8 *ppDS,
IUnknown *pUnkOuter) IUnknown *pUnkOuter)
{ {
LPDIRECTSOUND8 pDS;
HRESULT hr; HRESULT hr;
GUID devGuid; TRACE("(%p,%p)\n",ppDS,pUnkOuter);
TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
/* Get dsound configuration */ /* Get dsound configuration */
setup_dsound_options(); setup_dsound_options();
/* Default device? */ hr = IDirectSoundImpl_Create(&pDS);
if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL)) if (hr == DS_OK) {
lpcGUID = &DSDEVID_DefaultPlayback; hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
if (*ppDS)
if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) { IDirectSound8_IDirectSound8_AddRef(*ppDS);
WARN("invalid parameter: lpcGUID\n"); else {
*ppDS = NULL; WARN("IDirectSound8_IDirectSound8_Create failed\n");
return DSERR_INVALIDPARAM; IDirectSound8_Release(pDS);
}
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 { } else {
LPDIRECTSOUND8 pDS; WARN("IDirectSoundImpl_Create failed\n");
hr = IDirectSoundImpl_Create(&devGuid, &pDS); *ppDS = 0;
if (hr == DS_OK) {
hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
if (*ppDS)
IDirectSound8_IDirectSound8_AddRef(*ppDS);
else {
WARN("IDirectSound8_IDirectSound8_Create failed\n");
IDirectSound8_Release(pDS);
}
} else
WARN("IDirectSoundImpl_Create failed\n");
} }
return hr; return hr;
@ -1801,14 +1814,15 @@ HRESULT WINAPI DirectSoundCreate8(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
hr = DSOUND_Create8(lpcGUID, &pDS, pUnkOuter); hr = DSOUND_Create8(&pDS, pUnkOuter);
if (hr == DS_OK) { if (hr == DS_OK) {
IDirectSound8_IDirectSound8 * pp = (IDirectSound8_IDirectSound8 *)pDS; hr = IDirectSound8_Initialize(pDS, lpcGUID);
IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds); if (hr != DS_OK) {
if (!(p->initialized)) { if (hr != DSERR_ALREADYINITIALIZED) {
hr = IDirectSound8_Initialize(pDS, lpcGUID);
if (hr != DS_OK)
IDirectSound8_Release(pDS); IDirectSound8_Release(pDS);
pDS = 0;
} else
hr = DS_OK;
} }
} }
@ -1830,24 +1844,24 @@ HRESULT DSOUND_AddBuffer(
TRACE("(%p, %p)\n", pDS, pDSB); TRACE("(%p, %p)\n", pDS, pDSB);
RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE); RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
if (pDS->buffers) if (pDS->device->buffers)
newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1)); newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
else else
newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1)); newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
if (newbuffers) { if (newbuffers) {
pDS->buffers = newbuffers; pDS->device->buffers = newbuffers;
pDS->buffers[pDS->nrofbuffers] = pDSB; pDS->device->buffers[pDS->device->nrofbuffers] = pDSB;
pDS->nrofbuffers++; pDS->device->nrofbuffers++;
TRACE("buffer count is now %d\n", pDS->nrofbuffers); TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
} else { } 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; hr = DSERR_OUTOFMEMORY;
} }
RtlReleaseResource(&(pDS->buffer_list_lock)); RtlReleaseResource(&(pDS->device->buffer_list_lock));
return hr; return hr;
} }
@ -1865,26 +1879,26 @@ HRESULT DSOUND_RemoveBuffer(
TRACE("(%p, %p)\n", pDS, pDSB); 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++) for (i = 0; i < pDS->device->nrofbuffers; i++)
if (pDS->buffers[i] == pDSB) if (pDS->device->buffers[i] == pDSB)
break; break;
if (i < pDS->nrofbuffers) { if (i < pDS->device->nrofbuffers) {
/* Put the last buffer of the list in the (now empty) position */ /* Put the last buffer of the list in the (now empty) position */
pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1]; pDS->device->buffers[i] = pDS->device->buffers[pDS->device->nrofbuffers - 1];
pDS->nrofbuffers--; pDS->device->nrofbuffers--;
pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers); pDS->device->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->device->nrofbuffers);
TRACE("buffer count is now %d\n", pDS->nrofbuffers); TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
} }
if (pDS->nrofbuffers == 0) { if (pDS->device->nrofbuffers == 0) {
HeapFree(GetProcessHeap(),0,pDS->buffers); HeapFree(GetProcessHeap(),0,pDS->device->buffers);
pDS->buffers = NULL; pDS->device->buffers = NULL;
} }
RtlReleaseResource(&(pDS->buffer_list_lock)); RtlReleaseResource(&(pDS->device->buffer_list_lock));
return hr; return hr;
} }

View File

@ -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_MAX 28 /* max number of fragments to prebuffer */
#define DS_SND_QUEUE_MIN 12 /* min 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_renderer_guids[MAXWAVEDRIVERS];
GUID DSOUND_capture_guids[MAXWAVEDRIVERS]; GUID DSOUND_capture_guids[MAXWAVEDRIVERS];
@ -460,10 +460,10 @@ static HRESULT WINAPI DSCF_CreateInstance(
*ppobj = NULL; *ppobj = NULL;
if ( IsEqualIID( &IID_IDirectSound, riid ) ) if ( IsEqualIID( &IID_IDirectSound, riid ) )
return DSOUND_Create(0,(LPDIRECTSOUND*)ppobj,pOuter); return DSOUND_Create((LPDIRECTSOUND*)ppobj,pOuter);
if ( IsEqualIID( &IID_IDirectSound8, riid ) ) 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); WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
return E_NOINTERFACE; return E_NOINTERFACE;
@ -664,6 +664,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
TRACE("DLL_PROCESS_ATTACH\n"); TRACE("DLL_PROCESS_ATTACH\n");
for (i = 0; i < MAXWAVEDRIVERS; i++) { 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_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); INIT_GUID(DSOUND_capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i);
} }

View File

@ -63,6 +63,7 @@ typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl;
typedef struct PrimaryBufferImpl PrimaryBufferImpl; typedef struct PrimaryBufferImpl PrimaryBufferImpl;
typedef struct SecondaryBufferImpl SecondaryBufferImpl; typedef struct SecondaryBufferImpl SecondaryBufferImpl;
typedef struct IClassFactoryImpl IClassFactoryImpl; typedef struct IClassFactoryImpl IClassFactoryImpl;
typedef struct DirectSoundDevice DirectSoundDevice;
/***************************************************************************** /*****************************************************************************
* IDirectSound implementation structure * IDirectSound implementation structure
@ -72,7 +73,17 @@ struct IDirectSoundImpl
/* IUnknown fields */ /* IUnknown fields */
IDirectSound8Vtbl *lpVtbl; IDirectSound8Vtbl *lpVtbl;
DWORD ref; DWORD ref;
/* IDirectSoundImpl fields */
DirectSoundDevice *device;
LPUNKNOWN pUnknown;
LPDIRECTSOUND pDS;
LPDIRECTSOUND8 pDS8;
};
struct DirectSoundDevice
{
DWORD ref;
GUID guid; GUID guid;
PIDSDRIVER driver; PIDSDRIVER driver;
DSDRIVERDESC drvdesc; DSDRIVERDESC drvdesc;
@ -94,7 +105,6 @@ struct IDirectSoundImpl
PrimaryBufferImpl* primary; PrimaryBufferImpl* primary;
DSBUFFERDESC dsbd; DSBUFFERDESC dsbd;
DWORD speaker_config; DWORD speaker_config;
BOOL initialized;
LPBYTE tmp_buffer; LPBYTE tmp_buffer;
DWORD tmp_buffer_len; DWORD tmp_buffer_len;
@ -102,10 +112,6 @@ struct IDirectSoundImpl
IDirectSound3DListenerImpl* listener; IDirectSound3DListenerImpl* listener;
DS3DLISTENER ds3dl; DS3DLISTENER ds3dl;
BOOL ds3dl_need_recalc; BOOL ds3dl_need_recalc;
LPUNKNOWN pUnknown;
LPDIRECTSOUND pDS;
LPDIRECTSOUND8 pDS8;
}; };
/* reference counted buffer memory for duplicated buffer memory */ /* reference counted buffer memory for duplicated buffer memory */
@ -116,16 +122,13 @@ typedef struct BufferMemory
} BufferMemory; } BufferMemory;
HRESULT WINAPI IDirectSoundImpl_Create( HRESULT WINAPI IDirectSoundImpl_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND8 * ppds); LPDIRECTSOUND8 * ppds);
HRESULT WINAPI DSOUND_Create( HRESULT WINAPI DSOUND_Create(
LPCGUID lpcGUID,
LPDIRECTSOUND *ppDS, LPDIRECTSOUND *ppDS,
IUnknown *pUnkOuter); IUnknown *pUnkOuter);
HRESULT WINAPI DSOUND_Create8( HRESULT WINAPI DSOUND_Create8(
LPCGUID lpcGUID,
LPDIRECTSOUND8 *ppDS, LPDIRECTSOUND8 *ppDS,
IUnknown *pUnkOuter); IUnknown *pUnkOuter);
@ -461,11 +464,11 @@ HRESULT DSOUND_RemoveBuffer(IDirectSoundImpl * pDS, IDirectSoundBufferImpl * pDS
/* primary.c */ /* primary.c */
HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This); HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This); HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This); HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This); HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device);
HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos); HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos);
/* buffer.c */ /* buffer.c */
@ -476,8 +479,8 @@ DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, DWORD pplay, DWORD p
void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len); void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len);
void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb); void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb);
void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos); void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos);
void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq); void DSOUND_WaveQueue(DirectSoundDevice *device, DWORD mixq);
void DSOUND_PerformMix(IDirectSoundImpl *dsound); void DSOUND_PerformMix(DirectSoundDevice *device);
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2); 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); 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) #define DSOUND_FREQSHIFT (14)
extern IDirectSoundImpl* DSOUND_renderer; extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS]; extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS]; extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS];

View File

@ -164,11 +164,12 @@ static inline BYTE cvtS16toU8(INT16 s)
static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE *obuf ) static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE *obuf )
{ {
DirectSoundDevice * device = dsb->dsound->device;
INT fl,fr; INT fl,fr;
if (dsb->pwfx->wBitsPerSample == 8) { if (dsb->pwfx->wBitsPerSample == 8) {
if (dsb->dsound->pwfx->wBitsPerSample == 8 && if (device->pwfx->wBitsPerSample == 8 &&
dsb->dsound->pwfx->nChannels == dsb->pwfx->nChannels) { device->pwfx->nChannels == dsb->pwfx->nChannels) {
/* avoid needless 8->16->8 conversion */ /* avoid needless 8->16->8 conversion */
*obuf=*ibuf; *obuf=*ibuf;
if (dsb->pwfx->nChannels==2) 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); fr = (dsb->pwfx->nChannels==2 ? *(((INT16 *)ibuf) + 1) : fl);
} }
if (dsb->dsound->pwfx->nChannels == 2) { if (device->pwfx->nChannels == 2) {
if (dsb->dsound->pwfx->wBitsPerSample == 8) { if (device->pwfx->wBitsPerSample == 8) {
*obuf = cvtS16toU8(fl); *obuf = cvtS16toU8(fl);
*(obuf + 1) = cvtS16toU8(fr); *(obuf + 1) = cvtS16toU8(fr);
return; return;
} }
if (dsb->dsound->pwfx->wBitsPerSample == 16) { if (device->pwfx->wBitsPerSample == 16) {
*((INT16 *)obuf) = fl; *((INT16 *)obuf) = fl;
*(((INT16 *)obuf) + 1) = fr; *(((INT16 *)obuf) + 1) = fr;
return; return;
} }
} }
if (dsb->dsound->pwfx->nChannels == 1) { if (device->pwfx->nChannels == 1) {
fl = (fl + fr) >> 1; fl = (fl + fr) >> 1;
if (dsb->dsound->pwfx->wBitsPerSample == 8) { if (device->pwfx->wBitsPerSample == 8) {
*obuf = cvtS16toU8(fl); *obuf = cvtS16toU8(fl);
return; return;
} }
if (dsb->dsound->pwfx->wBitsPerSample == 16) { if (device->pwfx->wBitsPerSample == 16) {
*((INT16 *)obuf) = fl; *((INT16 *)obuf) = fl;
return; return;
} }
@ -213,16 +214,16 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
INT i, size, ipos, ilen; INT i, size, ipos, ilen;
BYTE *ibp, *obp; BYTE *ibp, *obp;
INT iAdvance = dsb->pwfx->nBlockAlign; 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; ibp = dsb->buffer->memory + dsb->buf_mixpos;
obp = buf; obp = buf;
TRACE("(%p, %p, %p), buf_mixpos=%ld\n", dsb, ibp, obp, dsb->buf_mixpos); TRACE("(%p, %p, %p), buf_mixpos=%ld\n", dsb, ibp, obp, dsb->buf_mixpos);
/* Check for the best case */ /* Check for the best case */
if ((dsb->freq == dsb->dsound->pwfx->nSamplesPerSec) && if ((dsb->freq == dsb->dsound->device->pwfx->nSamplesPerSec) &&
(dsb->pwfx->wBitsPerSample == dsb->dsound->pwfx->wBitsPerSample) && (dsb->pwfx->wBitsPerSample == dsb->dsound->device->pwfx->wBitsPerSample) &&
(dsb->pwfx->nChannels == dsb->dsound->pwfx->nChannels)) { (dsb->pwfx->nChannels == dsb->dsound->device->pwfx->nChannels)) {
INT bytesleft = dsb->buflen - dsb->buf_mixpos; INT bytesleft = dsb->buflen - dsb->buf_mixpos;
TRACE("(%p) Best case\n", dsb); TRACE("(%p) Best case\n", dsb);
if (len <= bytesleft ) if (len <= bytesleft )
@ -235,9 +236,9 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
} }
/* Check for same sample rate */ /* 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, 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; ilen = 0;
for (i = 0; i < len; i += oAdvance) { for (i = 0; i < len; i += oAdvance) {
cp_fields(dsb, ibp, obp ); cp_fields(dsb, ibp, obp );
@ -259,7 +260,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
* TransGaming Technologies Inc. */ * TransGaming Technologies Inc. */
/* FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n", /* 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; size = len / oAdvance;
ilen = 0; 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 */ /* with a mono primary buffer, it could sound very weird using */
/* this method. Oh well, tough patooties. */ /* this method. Oh well, tough patooties. */
switch (dsb->dsound->pwfx->wBitsPerSample) { switch (dsb->dsound->device->pwfx->wBitsPerSample) {
case 8: case 8:
/* 8-bit WAV is unsigned, but we need to operate */ /* 8-bit WAV is unsigned, but we need to operate */
/* on signed data for this to work properly */ /* on signed data for this to work properly */
switch (dsb->dsound->pwfx->nChannels) { switch (dsb->dsound->device->pwfx->nChannels) {
case 1: case 1:
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
INT val = *bpc - 128; INT val = *bpc - 128;
@ -322,13 +323,13 @@ static void DSOUND_MixerVol(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
} }
break; break;
default: 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;
} }
break; break;
case 16: case 16:
/* 16-bit WAV is signed -- much better */ /* 16-bit WAV is signed -- much better */
switch (dsb->dsound->pwfx->nChannels) { switch (dsb->dsound->device->pwfx->nChannels) {
case 1: case 1:
for (i = 0; i < len; i += 2) { for (i = 0; i < len; i += 2) {
*bps = (*bps * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16; *bps = (*bps * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16;
@ -344,30 +345,30 @@ static void DSOUND_MixerVol(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
} }
break; break;
default: 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;
} }
break; break;
default: 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; 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 (len > device->tmp_buffer_len) {
if (dsound->tmp_buffer) if (device->tmp_buffer)
dsound->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsound->tmp_buffer, len); device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, device->tmp_buffer, len);
else 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) 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; len = fraglen;
if (!(dsb->playflags & DSBPLAY_LOOPING)) { 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) - dsb->nAvgBytesPerSec) -
MulDiv(dsb->dsound->pwfx->nAvgBytesPerSec, dsb->buf_mixpos, MulDiv(dsb->dsound->device->pwfx->nAvgBytesPerSec, dsb->buf_mixpos,
dsb->nAvgBytesPerSec); dsb->nAvgBytesPerSec);
len = min(len, temp); len = min(len, temp);
} }
if (len % dsb->dsound->pwfx->nBlockAlign) { if (len % dsb->dsound->device->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->dsound->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); ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign);
len = (len / nBlockAlign) * nBlockAlign; /* data alignment */ len = (len / nBlockAlign) * nBlockAlign; /* data alignment */
} }
@ -397,7 +398,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
return 0; return 0;
} }
if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound, len)) == NULL) if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound->device, len)) == NULL)
return 0; return 0;
TRACE("MixInBuffer (%p) len = %d, dest = %ld\n", dsb, len, writepos); 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)) (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
DSOUND_MixerVol(dsb, ibuf, len); DSOUND_MixerVol(dsb, ibuf, len);
if (dsb->dsound->pwfx->wBitsPerSample == 8) { if (dsb->dsound->device->pwfx->wBitsPerSample == 8) {
BYTE *obuf = dsb->dsound->buffer + writepos; BYTE *obuf = dsb->dsound->device->buffer + writepos;
if ((writepos + len) <= dsb->dsound->buflen) if ((writepos + len) <= dsb->dsound->device->buflen)
todo = len; todo = len;
else else
todo = dsb->dsound->buflen - writepos; todo = dsb->dsound->device->buflen - writepos;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */ /* 8-bit WAV is unsigned */
@ -427,7 +428,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
if (todo < len) { if (todo < len) {
todo = len - todo; todo = len - todo;
obuf = dsb->dsound->buffer; obuf = dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */ /* 8-bit WAV is unsigned */
@ -442,12 +443,12 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
INT16 *ibufs, *obufs; INT16 *ibufs, *obufs;
ibufs = (INT16 *) ibuf; 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; todo = len / 2;
else else
todo = (dsb->dsound->buflen - writepos) / 2; todo = (dsb->dsound->device->buflen - writepos) / 2;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */ /* 16-bit WAV is signed */
@ -460,7 +461,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
if (todo < (len / 2)) { if (todo < (len / 2)) {
todo = (len / 2) - todo; todo = (len / 2) - todo;
obufs = (INT16 *)dsb->dsound->buffer; obufs = (INT16 *)dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */ /* 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); TRACE("(%p,%ld,%ld)\n",dsb,writepos,len);
if (len % dsb->dsound->pwfx->nBlockAlign) { if (len % dsb->dsound->device->pwfx->nBlockAlign) {
INT nBlockAlign = dsb->dsound->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); ERR("length not a multiple of block size, len = %ld, block size = %d\n", len, nBlockAlign);
len = (len / nBlockAlign) * nBlockAlign; /* data alignment */ 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; return;
TRACE("PhaseCancel (%p) len = %ld, dest = %ld\n", dsb, len, writepos); 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); DSOUND_MixerVol(dsb, ibuf, len);
/* subtract instead of add, to phase out premixed data */ /* subtract instead of add, to phase out premixed data */
if (dsb->dsound->pwfx->wBitsPerSample == 8) { if (dsb->dsound->device->pwfx->wBitsPerSample == 8) {
BYTE *obuf = dsb->dsound->buffer + writepos; BYTE *obuf = dsb->dsound->device->buffer + writepos;
if ((writepos + len) <= dsb->dsound->buflen) if ((writepos + len) <= dsb->dsound->device->buflen)
todo = len; todo = len;
else else
todo = dsb->dsound->buflen - writepos; todo = dsb->dsound->device->buflen - writepos;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */ /* 8-bit WAV is unsigned */
@ -540,7 +541,7 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
if (todo < len) { if (todo < len) {
todo = len - todo; todo = len - todo;
obuf = dsb->dsound->buffer; obuf = dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 8-bit WAV is unsigned */ /* 8-bit WAV is unsigned */
@ -555,12 +556,12 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
INT16 *ibufs, *obufs; INT16 *ibufs, *obufs;
ibufs = (INT16 *) ibuf; 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; todo = len / 2;
else else
todo = (dsb->dsound->buflen - writepos) / 2; todo = (dsb->dsound->device->buflen - writepos) / 2;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */ /* 16-bit WAV is signed */
@ -573,7 +574,7 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
if (todo < (len / 2)) { if (todo < (len / 2)) {
todo = (len / 2) - todo; todo = (len / 2) - todo;
obufs = (INT16 *)dsb->dsound->buffer; obufs = (INT16 *)dsb->dsound->device->buffer;
for (i = 0; i < todo; i++) { for (i = 0; i < todo; i++) {
/* 16-bit WAV is signed */ /* 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; DWORD size, flen, len, npos, nlen;
INT iAdvance = dsb->pwfx->nBlockAlign; 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 */ /* determine amount of premixed data to cancel */
DWORD primary_done = DWORD primary_done =
((dsb->primary_mixpos < writepos) ? dsb->dsound->buflen : 0) + ((dsb->primary_mixpos < writepos) ? dsb->dsound->device->buflen : 0) +
dsb->primary_mixpos - writepos; dsb->primary_mixpos - writepos;
TRACE("(%p, %ld), buf_mixpos=%ld\n", dsb, writepos, dsb->buf_mixpos); 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; flen = dsb->freqAcc;
nlen = len / dsb->pwfx->nBlockAlign; nlen = len / dsb->pwfx->nBlockAlign;
nlen = ((nlen << DSOUND_FREQSHIFT) + flen) / dsb->freqAdjust; nlen = ((nlen << DSOUND_FREQSHIFT) + flen) / dsb->freqAdjust;
nlen *= dsb->dsound->pwfx->nBlockAlign; nlen *= dsb->dsound->device->pwfx->nBlockAlign;
writepos = writepos =
((dsb->primary_mixpos < nlen) ? dsb->dsound->buflen : 0) + ((dsb->primary_mixpos < nlen) ? dsb->dsound->device->buflen : 0) +
dsb->primary_mixpos - nlen; dsb->primary_mixpos - nlen;
} }
@ -640,7 +641,7 @@ void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos)
#if 0 #if 0
DWORD i, size, flen, len, npos, nlen; DWORD i, size, flen, len, npos, nlen;
INT iAdvance = dsb->pwfx->nBlockAlign; 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 */ /* determine amount of premixed data to cancel */
DWORD buf_done = DWORD buf_done =
((dsb->buf_mixpos < buf_writepos) ? dsb->buflen : 0) + ((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); 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 /* since this is not implemented yet, just cancel *ALL* prebuffering for now
* (which is faster anyway when there's only a single secondary buffer) */ * (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) void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb)
@ -658,7 +659,7 @@ void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb)
TRACE("(%p)\n",dsb); TRACE("(%p)\n",dsb);
EnterCriticalSection(&dsb->lock); EnterCriticalSection(&dsb->lock);
if (dsb->state == STATE_PLAYING) if (dsb->state == STATE_PLAYING)
dsb->dsound->need_remix = TRUE; dsb->dsound->device->need_remix = TRUE;
LeaveCriticalSection(&dsb->lock); 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) ? dsb->buflen : 0) +
dsb->buf_mixpos - buf_writepos; dsb->buf_mixpos - buf_writepos;
DWORD primary_done = DWORD primary_done =
((dsb->primary_mixpos < writepos) ? dsb->dsound->buflen : 0) + ((dsb->primary_mixpos < writepos) ? dsb->dsound->device->buflen : 0) +
dsb->primary_mixpos - writepos; dsb->primary_mixpos - writepos;
DWORD adv_done = DWORD adv_done =
((dsb->dsound->mixpos < writepos) ? dsb->dsound->buflen : 0) + ((dsb->dsound->device->mixpos < writepos) ? dsb->dsound->device->buflen : 0) +
dsb->dsound->mixpos - writepos; dsb->dsound->device->mixpos - writepos;
DWORD played = DWORD played =
((buf_writepos < dsb->playpos) ? dsb->buflen : 0) + ((buf_writepos < dsb->playpos) ? dsb->buflen : 0) +
buf_writepos - dsb->playpos; 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, probably_valid_left = MulDiv(probably_valid_left,
1 << DSOUND_FREQSHIFT, 1 << DSOUND_FREQSHIFT,
dsb->pwfx->nBlockAlign * dsb->freqAdjust) * dsb->pwfx->nBlockAlign * dsb->freqAdjust) *
dsb->dsound->pwfx->nBlockAlign; dsb->dsound->device->pwfx->nBlockAlign;
/* check whether to clip mix_len */ /* check whether to clip mix_len */
if (probably_valid_left < mixlen) { if (probably_valid_left < mixlen) {
TRACE("clipping to probably_valid_left=%ld\n", probably_valid_left); 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; len = mixlen - primary_done;
TRACE("remaining mixlen=%ld\n", len); 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 /* smaller than a fragment, wait until it gets larger
* before we take the mixing overhead */ * before we take the mixing overhead */
TRACE("mixlen not worth it, deferring mixing\n"); 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 */ /* ok, we know how much to mix, let's go */
still_behind = (adv_done > primary_done); still_behind = (adv_done > primary_done);
while (len) { while (len) {
slen = dsb->dsound->buflen - dsb->primary_mixpos; slen = dsb->dsound->device->buflen - dsb->primary_mixpos;
if (slen > len) slen = len; if (slen > len) slen = len;
slen = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, slen); slen = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, slen);
if ((dsb->primary_mixpos < dsb->dsound->mixpos) && if ((dsb->primary_mixpos < dsb->dsound->device->mixpos) &&
(dsb->primary_mixpos + slen >= dsb->dsound->mixpos)) (dsb->primary_mixpos + slen >= dsb->dsound->device->mixpos))
still_behind = FALSE; still_behind = FALSE;
dsb->primary_mixpos += slen; len -= slen; 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; 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); TRACE("mixed data len=%ld, still_behind=%d\n", mixlen-len, still_behind);
post_mix: post_mix:
@ -807,9 +808,9 @@ post_mix:
* advance its underrun detector...*/ * advance its underrun detector...*/
if (still_behind) return 0; if (still_behind) return 0;
if ((mixlen - len) < primary_done) return 0; if ((mixlen - len) < primary_done) return 0;
slen = ((dsb->primary_mixpos < dsb->dsound->mixpos) ? slen = ((dsb->primary_mixpos < dsb->dsound->device->mixpos) ?
dsb->dsound->buflen : 0) + dsb->primary_mixpos - dsb->dsound->device->buflen : 0) + dsb->primary_mixpos -
dsb->dsound->mixpos; dsb->dsound->device->mixpos;
if (slen > mixlen) { if (slen > mixlen) {
/* the primary_done and still_behind checks above should have worked */ /* the primary_done and still_behind checks above should have worked */
FIXME("problem with advancement calculation (advlen=%ld > mixlen=%ld)\n", slen, mixlen); FIXME("problem with advancement calculation (advlen=%ld > mixlen=%ld)\n", slen, mixlen);
@ -818,14 +819,14 @@ post_mix:
return slen; 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; INT i, len, maxlen = 0;
IDirectSoundBufferImpl *dsb; IDirectSoundBufferImpl *dsb;
TRACE("(%ld,%ld,%ld,%d)\n", playpos, writepos, mixlen, recover); TRACE("(%ld,%ld,%ld,%d)\n", playpos, writepos, mixlen, recover);
for (i = 0; i < dsound->nrofbuffers; i++) { for (i = 0; i < device->nrofbuffers; i++) {
dsb = dsound->buffers[i]; dsb = device->buffers[i];
if (dsb->buflen && dsb->state && !dsb->hwbuf) { if (dsb->buflen && dsb->state && !dsb->hwbuf) {
TRACE("Checking %p, mixlen=%ld\n", dsb, mixlen); TRACE("Checking %p, mixlen=%ld\n", dsb, mixlen);
@ -857,20 +858,20 @@ static DWORD DSOUND_MixToPrimary(IDirectSoundImpl *dsound, DWORD playpos, DWORD
return maxlen; return maxlen;
} }
static void DSOUND_MixReset(IDirectSoundImpl *dsound, DWORD writepos) static void DSOUND_MixReset(DirectSoundDevice *device, DWORD writepos)
{ {
INT i; INT i;
IDirectSoundBufferImpl *dsb; IDirectSoundBufferImpl *dsb;
int nfiller; int nfiller;
TRACE("(%ld)\n", writepos); TRACE("(%p,%ld)\n", device, writepos);
/* the sound of silence */ /* the sound of silence */
nfiller = dsound->pwfx->wBitsPerSample == 8 ? 128 : 0; nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0;
/* reset all buffer mix positions */ /* reset all buffer mix positions */
for (i = 0; i < dsound->nrofbuffers; i++) { for (i = 0; i < device->nrofbuffers; i++) {
dsb = dsound->buffers[i]; dsb = device->buffers[i];
if (dsb->buflen && dsb->state && !dsb->hwbuf) { if (dsb->buflen && dsb->state && !dsb->hwbuf) {
TRACE("Resetting %p\n", dsb); TRACE("Resetting %p\n", dsb);
@ -890,72 +891,72 @@ static void DSOUND_MixReset(IDirectSoundImpl *dsound, DWORD writepos)
} }
/* wipe out premixed data */ /* wipe out premixed data */
if (dsound->mixpos < writepos) { if (device->mixpos < writepos) {
FillMemory(dsound->buffer + writepos, dsound->buflen - writepos, nfiller); FillMemory(device->buffer + writepos, device->buflen - writepos, nfiller);
FillMemory(dsound->buffer, dsound->mixpos, nfiller); FillMemory(device->buffer, device->mixpos, nfiller);
} else { } else {
FillMemory(dsound->buffer + writepos, dsound->mixpos - writepos, nfiller); FillMemory(device->buffer + writepos, device->mixpos - writepos, nfiller);
} }
/* reset primary mix position */ /* 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); TRACE("(%p,%ld)\n",device,writepos);
if (dsound->need_remix) { if (device->need_remix) {
DSOUND_MixReset(dsound, writepos); DSOUND_MixReset(device, writepos);
dsound->need_remix = FALSE; device->need_remix = FALSE;
/* maximize Half-Life performance */ /* maximize Half-Life performance */
dsound->prebuf = ds_snd_queue_min; device->prebuf = ds_snd_queue_min;
dsound->precount = 0; device->precount = 0;
} else { } else {
dsound->precount++; device->precount++;
if (dsound->precount >= 4) { if (device->precount >= 4) {
if (dsound->prebuf < ds_snd_queue_max) if (device->prebuf < ds_snd_queue_max)
dsound->prebuf++; device->prebuf++;
dsound->precount = 0; 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); TRACE("(%p,%ld)\n", device, mixq);
if (mixq + dsound->pwqueue > ds_hel_queue) mixq = ds_hel_queue - dsound->pwqueue; if (mixq + device->pwqueue > ds_hel_queue) mixq = ds_hel_queue - device->pwqueue;
TRACE("queueing %ld buffers, starting at %d\n", mixq, dsound->pwwrite); TRACE("queueing %ld buffers, starting at %d\n", mixq, device->pwwrite);
for (; mixq; mixq--) { for (; mixq; mixq--) {
waveOutWrite(dsound->hwo, dsound->pwave[dsound->pwwrite], sizeof(WAVEHDR)); waveOutWrite(device->hwo, device->pwave[device->pwwrite], sizeof(WAVEHDR));
dsound->pwwrite++; device->pwwrite++;
if (dsound->pwwrite >= DS_HEL_FRAGS) dsound->pwwrite = 0; if (device->pwwrite >= DS_HEL_FRAGS) device->pwwrite = 0;
dsound->pwqueue++; device->pwqueue++;
} }
} }
/* #define SYNC_CALLBACK */ /* #define SYNC_CALLBACK */
void DSOUND_PerformMix(IDirectSoundImpl *dsound) void DSOUND_PerformMix(DirectSoundDevice *device)
{ {
int nfiller; int nfiller;
BOOL forced; BOOL forced;
HRESULT hres; HRESULT hres;
TRACE("(%p)\n", dsound); TRACE("(%p)\n", device);
/* the sound of silence */ /* 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 */ /* 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) { if (device->priolevel != DSSCL_WRITEPRIMARY) {
BOOL paused = ((dsound->state == STATE_STOPPED) || (dsound->state == STATE_STARTING)); BOOL paused = ((device->state == STATE_STOPPED) || (device->state == STATE_STARTING));
/* FIXME: document variables */ /* FIXME: document variables */
DWORD playpos, writepos, inq, maxq, frag; DWORD playpos, writepos, inq, maxq, frag;
if (dsound->hwbuf) { if (device->hwbuf) {
hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, &writepos); hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, &writepos);
if (hres) { if (hres) {
WARN("IDsDriverBuffer_GetPosition failed\n"); WARN("IDsDriverBuffer_GetPosition failed\n");
return; return;
@ -964,50 +965,50 @@ void DSOUND_PerformMix(IDirectSoundImpl *dsound)
* but that's a little bit ambitious and unnecessary... */ * but that's a little bit ambitious and unnecessary... */
/* rather add our safety margin to the writepos, if we're playing */ /* rather add our safety margin to the writepos, if we're playing */
if (!paused) { if (!paused) {
writepos += dsound->writelead; writepos += device->writelead;
writepos %= dsound->buflen; writepos %= device->buflen;
} else writepos = playpos; } else writepos = playpos;
} else { } else {
playpos = dsound->pwplay * dsound->fraglen; playpos = device->pwplay * device->fraglen;
writepos = playpos; writepos = playpos;
if (!paused) { if (!paused) {
writepos += ds_hel_margin * dsound->fraglen; writepos += ds_hel_margin * device->fraglen;
writepos %= dsound->buflen; writepos %= device->buflen;
} }
} }
TRACE("primary playpos=%ld, writepos=%ld, clrpos=%ld, mixpos=%ld, buflen=%ld\n", TRACE("primary playpos=%ld, writepos=%ld, clrpos=%ld, mixpos=%ld, buflen=%ld\n",
playpos,writepos,dsound->playpos,dsound->mixpos,dsound->buflen); playpos,writepos,device->playpos,device->mixpos,device->buflen);
assert(dsound->playpos < dsound->buflen); assert(device->playpos < device->buflen);
/* wipe out just-played sound data */ /* wipe out just-played sound data */
if (playpos < dsound->playpos) { if (playpos < device->playpos) {
FillMemory(dsound->buffer + dsound->playpos, dsound->buflen - dsound->playpos, nfiller); FillMemory(device->buffer + device->playpos, device->buflen - device->playpos, nfiller);
FillMemory(dsound->buffer, playpos, nfiller); FillMemory(device->buffer, playpos, nfiller);
} else { } 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 */ /* reset mixing if necessary */
DSOUND_CheckReset(dsound, writepos); DSOUND_CheckReset(device, writepos);
/* check how much prebuffering is left */ /* check how much prebuffering is left */
inq = dsound->mixpos; inq = device->mixpos;
if (inq < writepos) if (inq < writepos)
inq += dsound->buflen; inq += device->buflen;
inq -= writepos; inq -= writepos;
/* find the maximum we can prebuffer */ /* find the maximum we can prebuffer */
if (!paused) { if (!paused) {
maxq = playpos; maxq = playpos;
if (maxq < writepos) if (maxq < writepos)
maxq += dsound->buflen; maxq += device->buflen;
maxq -= writepos; maxq -= writepos;
} else maxq = dsound->buflen; } else maxq = device->buflen;
/* clip maxq to dsound->prebuf */ /* clip maxq to device->prebuf */
frag = dsound->prebuf * dsound->fraglen; frag = device->prebuf * device->fraglen;
if (maxq > frag) maxq = frag; if (maxq > frag) maxq = frag;
/* check for consistency */ /* 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); TRACE("reached end of mixed data (inq=%ld, maxq=%ld)\n", inq, maxq);
inq = 0; inq = 0;
/* stop the playback now, to allow buffers to refill */ /* stop the playback now, to allow buffers to refill */
if (dsound->state == STATE_PLAYING) { if (device->state == STATE_PLAYING) {
dsound->state = STATE_STARTING; device->state = STATE_STARTING;
} }
else if (dsound->state == STATE_STOPPING) { else if (device->state == STATE_STOPPING) {
dsound->state = STATE_STOPPED; device->state = STATE_STOPPED;
} }
else { else {
/* how can we have an underrun if we aren't playing? */ /* 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 #ifdef SYNC_CALLBACK
/* DSOUND_callback may need this lock */ /* DSOUND_callback may need this lock */
LeaveCriticalSection(&(dsound->mixlock)); LeaveCriticalSection(&(device->mixlock));
#endif #endif
if (DSOUND_PrimaryStop(dsound) != DS_OK) if (DSOUND_PrimaryStop(device) != DS_OK)
WARN("DSOUND_PrimaryStop failed\n"); WARN("DSOUND_PrimaryStop failed\n");
#ifdef SYNC_CALLBACK #ifdef SYNC_CALLBACK
EnterCriticalSection(&(dsound->mixlock)); EnterCriticalSection(&(device->mixlock));
#endif #endif
if (dsound->hwbuf) { if (device->hwbuf) {
/* the Stop is supposed to reset play position to beginning of buffer */ /* the Stop is supposed to reset play position to beginning of buffer */
/* unfortunately, OSS is not able to do so, so get current pointer */ /* 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) { if (hres) {
LeaveCriticalSection(&(dsound->mixlock)); LeaveCriticalSection(&(device->mixlock));
WARN("IDsDriverBuffer_GetPosition failed\n"); WARN("IDsDriverBuffer_GetPosition failed\n");
return; return;
} }
} else { } else {
playpos = dsound->pwplay * dsound->fraglen; playpos = device->pwplay * device->fraglen;
} }
writepos = playpos; writepos = playpos;
dsound->playpos = playpos; device->playpos = playpos;
dsound->mixpos = writepos; device->mixpos = writepos;
inq = 0; inq = 0;
maxq = dsound->buflen; maxq = device->buflen;
if (maxq > frag) maxq = frag; if (maxq > frag) maxq = frag;
FillMemory(dsound->buffer, dsound->buflen, nfiller); FillMemory(device->buffer, device->buflen, nfiller);
paused = TRUE; paused = TRUE;
} }
/* do the mixing */ /* do the mixing */
frag = DSOUND_MixToPrimary(dsound, playpos, writepos, maxq, paused); frag = DSOUND_MixToPrimary(device, playpos, writepos, maxq, paused);
if (forced) frag = maxq - inq; if (forced) frag = maxq - inq;
dsound->mixpos += frag; device->mixpos += frag;
dsound->mixpos %= dsound->buflen; device->mixpos %= device->buflen;
if (frag) { if (frag) {
/* buffers have been filled, restart playback */ /* buffers have been filled, restart playback */
if (dsound->state == STATE_STARTING) { if (device->state == STATE_STARTING) {
dsound->state = STATE_PLAYING; 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 /* 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 */ * 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 (paused) {
if (DSOUND_PrimaryPlay(dsound) != DS_OK) if (DSOUND_PrimaryPlay(device) != DS_OK)
WARN("DSOUND_PrimaryPlay failed\n"); WARN("DSOUND_PrimaryPlay failed\n");
else else
TRACE("starting playback\n"); TRACE("starting playback\n");
} }
} }
else else
LeaveCriticalSection(&(dsound->mixlock)); LeaveCriticalSection(&(device->mixlock));
} else { } else {
/* in the DSSCL_WRITEPRIMARY mode, the app is totally in charge... */ /* in the DSSCL_WRITEPRIMARY mode, the app is totally in charge... */
if (dsound->state == STATE_STARTING) { if (device->state == STATE_STARTING) {
if (DSOUND_PrimaryPlay(dsound) != DS_OK) if (DSOUND_PrimaryPlay(device) != DS_OK)
WARN("DSOUND_PrimaryPlay failed\n"); WARN("DSOUND_PrimaryPlay failed\n");
else else
dsound->state = STATE_PLAYING; device->state = STATE_PLAYING;
} }
else if (dsound->state == STATE_STOPPING) { else if (device->state == STATE_STOPPING) {
if (DSOUND_PrimaryStop(dsound) != DS_OK) if (DSOUND_PrimaryStop(device) != DS_OK)
WARN("DSOUND_PrimaryStop failed\n"); WARN("DSOUND_PrimaryStop failed\n");
else else
dsound->state = STATE_STOPPED; device->state = STATE_STOPPED;
} }
} }
} }
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) 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 start_time = GetTickCount();
DWORD end_time; DWORD end_time;
TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2); TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2);
TRACE("entering at %ld\n", start_time); 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"); ERR("dsound died without killing us?\n");
timeKillEvent(timerID); timeKillEvent(timerID);
timeEndPeriod(DS_TIME_RES); timeEndPeriod(DS_TIME_RES);
return; return;
} }
RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE); RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
if (This->ref) if (device->ref)
DSOUND_PerformMix(This); DSOUND_PerformMix(device);
RtlReleaseResource(&(This->buffer_list_lock)); RtlReleaseResource(&(device->buffer_list_lock));
end_time = GetTickCount(); end_time = GetTickCount();
TRACE("completed processing at %ld, duration = %ld\n", end_time, end_time - start_time); 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) 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("(%p,%x,%lx,%lx,%lx)\n",hwo,msg,dwUser,dw1,dw2);
TRACE("entering at %ld, msg=%08x(%s)\n", GetTickCount(), msg, 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_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" :
msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN"); msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN");
if (msg == MM_WOM_DONE) { if (msg == MM_WOM_DONE) {
DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos; DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos;
if (This->pwqueue == (DWORD)-1) { if (device->pwqueue == (DWORD)-1) {
TRACE("completed due to reset\n"); TRACE("completed due to reset\n");
return; return;
} }
/* it could be a bad idea to enter critical section here... if there's lock contention, /* 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 */ * the resulting scheduling delays might obstruct the winmm player thread */
#ifdef SYNC_CALLBACK #ifdef SYNC_CALLBACK
EnterCriticalSection(&(This->mixlock)); EnterCriticalSection(&(device->mixlock));
#endif #endif
/* retrieve current values */ /* retrieve current values */
fraglen = This->fraglen; fraglen = device->fraglen;
buflen = This->buflen; buflen = device->buflen;
pwplay = This->pwplay; pwplay = device->pwplay;
playpos = pwplay * fraglen; playpos = pwplay * fraglen;
mixpos = This->mixpos; mixpos = device->mixpos;
/* check remaining mixed data */ /* check remaining mixed data */
inq = ((mixpos < playpos) ? buflen : 0) + mixpos - playpos; inq = ((mixpos < playpos) ? buflen : 0) + mixpos - playpos;
mixq = inq / fraglen; mixq = inq / fraglen;
@ -1161,12 +1162,12 @@ void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, D
pwplay++; pwplay++;
if (pwplay >= DS_HEL_FRAGS) pwplay = 0; if (pwplay >= DS_HEL_FRAGS) pwplay = 0;
/* write new values */ /* write new values */
This->pwplay = pwplay; device->pwplay = pwplay;
This->pwqueue--; device->pwqueue--;
/* queue new buffer if we have data for it */ /* 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 #ifdef SYNC_CALLBACK
LeaveCriticalSection(&(This->mixlock)); LeaveCriticalSection(&(device->mixlock));
#endif #endif
} }
TRACE("completed\n"); TRACE("completed\n");

File diff suppressed because it is too large Load Diff

View File

@ -206,7 +206,7 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
case DS3DMODE_NORMAL: case DS3DMODE_NORMAL:
TRACE("Normal 3D processing mode\n"); TRACE("Normal 3D processing mode\n");
/* we need to calculate distance between buffer and listener*/ /* 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); flDistance = VectorMagnitude (&vDistance);
break; break;
case DS3DMODE_HEADRELATIVE: case DS3DMODE_HEADRELATIVE:
@ -276,16 +276,16 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
dsb->volpan.lVolume = lVolume; dsb->volpan.lVolume = lVolume;
/* panning */ /* panning */
if (dsb->dsound->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x && if (dsb->dsound->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x &&
dsb->dsound->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y && dsb->dsound->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y &&
dsb->dsound->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) { dsb->dsound->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) {
dsb->volpan.lPan = 0; dsb->volpan.lPan = 0;
flAngle = 0.0; flAngle = 0.0;
} }
else else
{ {
vDistance = VectorBetweenTwoPoints(&dsb->dsound->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition); vDistance = VectorBetweenTwoPoints(&dsb->dsound->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
vLeft = VectorProduct(&dsb->dsound->ds3dl.vOrientFront, &dsb->dsound->ds3dl.vOrientTop); vLeft = VectorProduct(&dsb->dsound->device->ds3dl.vOrientFront, &dsb->dsound->device->ds3dl.vOrientTop);
flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance); flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance);
/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */ /* 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; 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 */ /* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */
#if 0 #if 0
/* doppler shift*/ /* 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"); 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 /* calculate length of ds3dl.vVelocity component which causes Doppler Effect
NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE 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 */ 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: */ /* formula taken from Gianicoli D.: Physics, 4th edition: */
/* FIXME: replace dsb->freq with appropriate frequency ! */ /* FIXME: replace dsb->freq with appropriate frequency ! */
flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel)); flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel));
@ -335,15 +335,15 @@ static void WINAPI DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl)
{ {
int i; int i;
TRACE("(%p)\n",ds3dl); 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 /* some buffers don't have 3d buffer (Ultima IX seems to
crash without the following line) */ crash without the following line) */
if (ds3dl->dsound->buffers[i]->ds3db == NULL) if (ds3dl->dsound->device->buffers[i]->ds3db == NULL)
continue; 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 ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
if (!This->dsound->primary) if (!This->dsound->device->primary)
PrimaryBufferImpl_Create(This->dsound, &(This->dsound->primary), &(This->dsound->dsbd)); PrimaryBufferImpl_Create(This->dsound, &(This->dsound->device->primary), &(This->dsound->device->dsbd));
if (This->dsound->primary) { if (This->dsound->device->primary) {
*ppobj = This->dsound->primary; *ppobj = This->dsound->device->primary;
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj); IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj);
return S_OK; return S_OK;
} }
@ -813,7 +813,7 @@ static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER i
TRACE("(%p) ref was %ld\n", This, ref + 1); TRACE("(%p) ref was %ld\n", This, ref + 1);
if (!ref) { if (!ref) {
This->dsound->listener = 0; This->dsound->device->listener = 0;
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This); TRACE("(%p) released\n", This);
} }
@ -839,7 +839,7 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
} }
TRACE("returning: all parameters\n"); TRACE("returning: all parameters\n");
*lpDS3DL = This->dsound->ds3dl; *lpDS3DL = This->dsound->device->ds3dl;
return DS_OK; return DS_OK;
} }
@ -848,8 +848,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
LPD3DVALUE lpfDistanceFactor) LPD3DVALUE lpfDistanceFactor)
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Distance Factor = %f\n", This->dsound->ds3dl.flDistanceFactor); TRACE("returning: Distance Factor = %f\n", This->dsound->device->ds3dl.flDistanceFactor);
*lpfDistanceFactor = This->dsound->ds3dl.flDistanceFactor; *lpfDistanceFactor = This->dsound->device->ds3dl.flDistanceFactor;
return DS_OK; return DS_OK;
} }
@ -858,8 +858,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
LPD3DVALUE lpfDopplerFactor) LPD3DVALUE lpfDopplerFactor)
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: Doppler Factor = %f\n", This->dsound->ds3dl.flDopplerFactor); TRACE("returning: Doppler Factor = %f\n", This->dsound->device->ds3dl.flDopplerFactor);
*lpfDopplerFactor = This->dsound->ds3dl.flDopplerFactor; *lpfDopplerFactor = This->dsound->device->ds3dl.flDopplerFactor;
return DS_OK; return DS_OK;
} }
@ -869,11 +869,11 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
LPD3DVECTOR lpvOrientTop) LPD3DVECTOR lpvOrientTop)
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->ds3dl.vOrientFront.x, \ TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->device->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->device->ds3dl.vOrientFront.y, This->dsound->device->ds3dl.vOrientFront.z, This->dsound->device->ds3dl.vOrientTop.x, This->dsound->device->ds3dl.vOrientTop.y, \
This->dsound->ds3dl.vOrientTop.z); This->dsound->device->ds3dl.vOrientTop.z);
*lpvOrientFront = This->dsound->ds3dl.vOrientFront; *lpvOrientFront = This->dsound->device->ds3dl.vOrientFront;
*lpvOrientTop = This->dsound->ds3dl.vOrientTop; *lpvOrientTop = This->dsound->device->ds3dl.vOrientTop;
return DS_OK; return DS_OK;
} }
@ -882,8 +882,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
LPD3DVECTOR lpvPosition) LPD3DVECTOR lpvPosition)
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; 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); 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->ds3dl.vPosition; *lpvPosition = This->dsound->device->ds3dl.vPosition;
return DS_OK; return DS_OK;
} }
@ -892,8 +892,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
LPD3DVALUE lpfRolloffFactor) LPD3DVALUE lpfRolloffFactor)
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("returning: RolloffFactor = %f\n", This->dsound->ds3dl.flRolloffFactor); TRACE("returning: RolloffFactor = %f\n", This->dsound->device->ds3dl.flRolloffFactor);
*lpfRolloffFactor = This->dsound->ds3dl.flRolloffFactor; *lpfRolloffFactor = This->dsound->device->ds3dl.flRolloffFactor;
return DS_OK; return DS_OK;
} }
@ -902,8 +902,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
LPD3DVECTOR lpvVelocity) LPD3DVECTOR lpvVelocity)
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; 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); 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->ds3dl.vVelocity; *lpvVelocity = This->dsound->device->ds3dl.vVelocity;
return DS_OK; return DS_OK;
} }
@ -914,13 +914,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: all parameters; dwApply = %ld\n", dwApply); TRACE("setting: all parameters; dwApply = %ld\n", dwApply);
This->dsound->ds3dl = *lpcDS3DL; This->dsound->device->ds3dl = *lpcDS3DL;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -931,13 +931,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Distance Factor = %f; dwApply = %ld\n", fDistanceFactor, dwApply); 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) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -948,13 +948,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Doppler Factor = %f; dwApply = %ld\n", fDopplerFactor, dwApply); 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) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -967,18 +967,18 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %ld\n", \ TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %ld\n", \
xFront, yFront, zFront, xTop, yTop, zTop, dwApply); xFront, yFront, zFront, xTop, yTop, zTop, dwApply);
This->dsound->ds3dl.vOrientFront.x = xFront; This->dsound->device->ds3dl.vOrientFront.x = xFront;
This->dsound->ds3dl.vOrientFront.y = yFront; This->dsound->device->ds3dl.vOrientFront.y = yFront;
This->dsound->ds3dl.vOrientFront.z = zFront; This->dsound->device->ds3dl.vOrientFront.z = zFront;
This->dsound->ds3dl.vOrientTop.x = xTop; This->dsound->device->ds3dl.vOrientTop.x = xTop;
This->dsound->ds3dl.vOrientTop.y = yTop; This->dsound->device->ds3dl.vOrientTop.y = yTop;
This->dsound->ds3dl.vOrientTop.z = zTop; This->dsound->device->ds3dl.vOrientTop.z = zTop;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -989,15 +989,15 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->dsound->ds3dl.vPosition.x = x; This->dsound->device->ds3dl.vPosition.x = x;
This->dsound->ds3dl.vPosition.y = y; This->dsound->device->ds3dl.vPosition.y = y;
This->dsound->ds3dl.vPosition.z = z; This->dsound->device->ds3dl.vPosition.z = z;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -1008,13 +1008,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Rolloff Factor = %f; dwApply = %ld\n", fRolloffFactor, dwApply); 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) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -1025,15 +1025,15 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
{ {
IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->dsound->ds3dl.vVelocity.x = x; This->dsound->device->ds3dl.vVelocity.x = x;
This->dsound->ds3dl.vVelocity.y = y; This->dsound->device->ds3dl.vVelocity.y = y;
This->dsound->ds3dl.vVelocity.z = z; This->dsound->device->ds3dl.vVelocity.z = z;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->dsound->ds3dl_need_recalc = FALSE; This->dsound->device->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->dsound->ds3dl_need_recalc = TRUE; This->dsound->device->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
@ -1090,24 +1090,24 @@ HRESULT WINAPI IDirectSound3DListenerImpl_Create(
dsl->dsound = This->dsound; dsl->dsound = This->dsound;
dsl->dsound->ds3dl.dwSize = sizeof(DS3DLISTENER); dsl->dsound->device->ds3dl.dwSize = sizeof(DS3DLISTENER);
dsl->dsound->ds3dl.vPosition.x = 0.0; dsl->dsound->device->ds3dl.vPosition.x = 0.0;
dsl->dsound->ds3dl.vPosition.y = 0.0; dsl->dsound->device->ds3dl.vPosition.y = 0.0;
dsl->dsound->ds3dl.vPosition.z = 0.0; dsl->dsound->device->ds3dl.vPosition.z = 0.0;
dsl->dsound->ds3dl.vVelocity.x = 0.0; dsl->dsound->device->ds3dl.vVelocity.x = 0.0;
dsl->dsound->ds3dl.vVelocity.y = 0.0; dsl->dsound->device->ds3dl.vVelocity.y = 0.0;
dsl->dsound->ds3dl.vVelocity.z = 0.0; dsl->dsound->device->ds3dl.vVelocity.z = 0.0;
dsl->dsound->ds3dl.vOrientFront.x = 0.0; dsl->dsound->device->ds3dl.vOrientFront.x = 0.0;
dsl->dsound->ds3dl.vOrientFront.y = 0.0; dsl->dsound->device->ds3dl.vOrientFront.y = 0.0;
dsl->dsound->ds3dl.vOrientFront.z = 1.0; dsl->dsound->device->ds3dl.vOrientFront.z = 1.0;
dsl->dsound->ds3dl.vOrientTop.x = 0.0; dsl->dsound->device->ds3dl.vOrientTop.x = 0.0;
dsl->dsound->ds3dl.vOrientTop.y = 1.0; dsl->dsound->device->ds3dl.vOrientTop.y = 1.0;
dsl->dsound->ds3dl.vOrientTop.z = 0.0; dsl->dsound->device->ds3dl.vOrientTop.z = 0.0;
dsl->dsound->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; dsl->dsound->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
dsl->dsound->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; dsl->dsound->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
dsl->dsound->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; dsl->dsound->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
dsl->dsound->ds3dl_need_recalc = TRUE; dsl->dsound->device->ds3dl_need_recalc = TRUE;
*pdsl = dsl; *pdsl = dsl;
return S_OK; return S_OK;