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

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

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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