Wine-20041201 vendor drop Added: vendor/wine/dlls/dsound/ Added: vendor/wine/dlls/dsound/current/ Added: vendor/wine/dlls/dsound/current/Makefile.in Added: vendor/wine/dlls/dsound/current/buffer.c Added: vendor/wine/dlls/dsound/current/capture.c Added: vendor/wine/dlls/dsound/current/dsound.c Added: vendor/wine/dlls/dsound/current/dsound.spec Added: vendor/wine/dlls/dsound/current/dsound_main.c Added: vendor/wine/dlls/dsound/current/dsound_private.h Added: vendor/wine/dlls/dsound/current/mixer.c Added: vendor/wine/dlls/dsound/current/primary.c Added: vendor/wine/dlls/dsound/current/propset.c Added: vendor/wine/dlls/dsound/current/regsvr.c Added: vendor/wine/dlls/dsound/current/sound3d.c Added: vendor/wine/dlls/dsound/current/version.rc _____
Added: vendor/wine/dlls/dsound/current/Makefile.in --- vendor/wine/dlls/dsound/current/Makefile.in 2004-12-31 14:53:28 UTC (rev 12510) +++ vendor/wine/dlls/dsound/current/Makefile.in 2004-12-31 14:53:50 UTC (rev 12511) @@ -0,0 +1,26 @@
+TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = dsound.dll +IMPORTS = winmm ole32 user32 advapi32 kernel32 ntdll +EXTRALIBS = -ldxguid -luuid + +C_SRCS = \ + buffer.c \ + capture.c \ + dsound.c \ + dsound_main.c \ + mixer.c \ + primary.c \ + propset.c \ + regsvr.c \ + sound3d.c + +RC_SRCS = version.rc + +SUBDIRS = tests + +@MAKE_DLL_RULES@ + +### Dependencies: _____
Added: vendor/wine/dlls/dsound/current/buffer.c --- vendor/wine/dlls/dsound/current/buffer.c 2004-12-31 14:53:28 UTC (rev 12510) +++ vendor/wine/dlls/dsound/current/buffer.c 2004-12-31 14:53:50 UTC (rev 12511) @@ -0,0 +1,1567 @@
+/* DirectSound + * + * Copyright 1998 Marcus Meissner + * Copyright 1998 Rob Riggs + * Copyright 2000-2002 TransGaming Technologies, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/fcntl.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#define NONAMELESSSTRUCT +#define NONAMELESSUNION +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winerror.h" +#include "mmsystem.h" +#include "winreg.h" +#include "winternl.h" +#include "mmddk.h" +#include "wine/windef16.h" +#include "wine/debug.h" +#include "dsound.h" +#include "dsdriver.h" +#include "dsound_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dsound); + +/********************************************************************** ********* + * IDirectSoundNotify + */ +static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface( + LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj +) { + IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + + if (This->dsb == NULL) { + WARN("invalid parameter\n"); + return E_INVALIDARG; + } + + return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj); +} + +static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) +{ + IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; + TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + return InterlockedIncrement(&(This->ref)); +} + +static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { + IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; + ULONG ref; + + TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + + ref = InterlockedDecrement(&(This->ref)); + if (ref == 0) { + IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb); + This->dsb->notify = NULL; + HeapFree(GetProcessHeap(),0,This); + TRACE("(%p) released\n",This); + } + return ref; +} + +static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions( + LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify +) { + IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; + TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify); + + if (howmuch > 0 && notify == NULL) { + WARN("invalid parameter: notify == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (TRACE_ON(dsound)) { + unsigned int i; + for (i=0;i<howmuch;i++) + TRACE("notify at %ld to 0x%08lx\n", + notify[i].dwOffset,(DWORD)notify[i].hEventNotify); + } + + if (This->dsb->hwnotify) { + HRESULT hres; + hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify); + if (hres != DS_OK) + WARN("IDsDriverNotify_SetNotificationPositions failed\n"); + return hres; + } else if (howmuch > 0) { + /* Make an internal copy of the caller-supplied array. + * Replace the existing copy if one is already present. */ + if (This->dsb->notifies) + This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + This->dsb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY)); + else + This->dsb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + howmuch * sizeof(DSBPOSITIONNOTIFY)); + + if (This->dsb->notifies == NULL) { + WARN("out of memory\n"); + return DSERR_OUTOFMEMORY; + } + memcpy(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY)); + This->dsb->nrofnotifies = howmuch; + } else { + if (This->dsb->notifies) { + HeapFree(GetProcessHeap(), 0, This->dsb->notifies); + This->dsb->notifies = NULL; + } + This->dsb->nrofnotifies = 0; + } + + return S_OK; +} + +IDirectSoundNotifyVtbl dsnvt = +{ + IDirectSoundNotifyImpl_QueryInterface, + IDirectSoundNotifyImpl_AddRef, + IDirectSoundNotifyImpl_Release, + IDirectSoundNotifyImpl_SetNotificationPositions, +}; + +HRESULT WINAPI IDirectSoundNotifyImpl_Create( + IDirectSoundBufferImpl * dsb, + IDirectSoundNotifyImpl **pdsn) +{ + IDirectSoundNotifyImpl * dsn; + TRACE("(%p,%p)\n",dsb,pdsn); + + dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dsn)); + + if (dsn == NULL) { + WARN("out of memory\n"); + return DSERR_OUTOFMEMORY; + } + + dsn->ref = 0; + dsn->lpVtbl = &dsnvt; + dsn->dsb = dsb; + dsb->notify = dsn; + IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb); + + *pdsn = dsn; + return DS_OK; +} + +HRESULT WINAPI IDirectSoundNotifyImpl_Destroy( + IDirectSoundNotifyImpl *pdsn) +{ + TRACE("(%p)\n",pdsn); + + while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0); + + return DS_OK; +} + +/********************************************************************** ********* + * IDirectSoundBuffer + */ + +static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat( + LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX wfex +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + + TRACE("(%p,%p)\n",This,wfex); + /* This method is not available on secondary buffers */ + WARN("invalid call\n"); + return DSERR_INVALIDCALL; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume( + LPDIRECTSOUNDBUFFER8 iface,LONG vol +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + LONG oldVol; + HRESULT hres = DS_OK; + + TRACE("(%p,%ld)\n",This,vol); + + if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { + WARN("control unavailable: This->dsbd.dwFlags = 0x%08lx\n", This->dsbd.dwFlags); + return DSERR_CONTROLUNAVAIL; + } + + if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) { + WARN("invalid parameter: vol = %ld\n", vol); + return DSERR_INVALIDPARAM; + } + + /* **** */ + EnterCriticalSection(&(This->lock)); + + if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) { + oldVol = This->ds3db_lVolume; + This->ds3db_lVolume = vol; + } else { + oldVol = This->volpan.lVolume; + This->volpan.lVolume = vol; + if (vol != oldVol) + DSOUND_RecalcVolPan(&(This->volpan)); + } + + if (vol != oldVol) { + if (This->hwbuf) { + hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan)); + if (hres != DS_OK) + WARN("IDsDriverBuffer_SetVolumePan failed\n"); + } else + DSOUND_ForceRemix(This); + } + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + return hres; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume( + LPDIRECTSOUNDBUFFER8 iface,LPLONG vol +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%p)\n",This,vol); + + if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; + } + + if (vol == NULL) { + WARN("invalid parameter: vol == NULL\n"); + return DSERR_INVALIDPARAM; + } + + *vol = This->volpan.lVolume; + + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency( + LPDIRECTSOUNDBUFFER8 iface,DWORD freq +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + DWORD oldFreq; + + TRACE("(%p,%ld)\n",This,freq); + + if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) { + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; + } + + if (freq == DSBFREQUENCY_ORIGINAL) + freq = This->pwfx->nSamplesPerSec; + + if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) { + WARN("invalid parameter: freq = %ld\n", freq); + return DSERR_INVALIDPARAM; + } + + /* **** */ + EnterCriticalSection(&(This->lock)); + + oldFreq = This->freq; + This->freq = freq; + if (freq != oldFreq) { + This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->pwfx->nSamplesPerSec; + This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign; + DSOUND_RecalcFormat(This); + if (!This->hwbuf) + DSOUND_ForceRemix(This); + } + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_Play( + LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags +) { + HRESULT hres = DS_OK; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags); + + /* **** */ + EnterCriticalSection(&(This->lock)); + + This->playflags = flags; + if (This->state == STATE_STOPPED) { + This->leadin = TRUE; + This->startpos = This->buf_mixpos; + This->state = STATE_STARTING; + } else if (This->state == STATE_STOPPING) + This->state = STATE_PLAYING; + if (This->hwbuf) { + hres = IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags); + if (hres != DS_OK) + WARN("IDsDriverBuffer_Play failed\n"); + else + This->state = STATE_PLAYING; + } + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + return hres; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface) +{ + HRESULT hres = DS_OK; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p)\n",This); + + /* **** */ + EnterCriticalSection(&(This->lock)); + + if (This->state == STATE_PLAYING) + This->state = STATE_STOPPING; + else if (This->state == STATE_STARTING) + This->state = STATE_STOPPED; + if (This->hwbuf) { + hres = IDsDriverBuffer_Stop(This->hwbuf); + if (hres != DS_OK) + WARN("IDsDriverBuffer_Stop failed\n"); + else + This->state = STATE_STOPPED; + } + DSOUND_CheckEvent(This, 0); + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + return hres; +} + +static ULONG WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) +{ + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + return InterlockedIncrement(&(This->ref)); +} + +static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) +{ + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + ULONG ref; + + TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId()); + + ref = InterlockedDecrement(&(This->ref)); + if (ref) + return ref; + + DSOUND_RemoveBuffer(This->dsound, This); + + This->lock.DebugInfo->Spare[1] = 0; + DeleteCriticalSection(&(This->lock)); + + if (This->hwbuf) { + IDsDriverBuffer_Release(This->hwbuf); + if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { + This->buffer->ref--; + if (This->buffer->ref==0) { + HeapFree(GetProcessHeap(),0,This->buffer->memory); + HeapFree(GetProcessHeap(),0,This->buffer); + } + } + } else { + This->buffer->ref--; + if (This->buffer->ref==0) { + HeapFree(GetProcessHeap(),0,This->buffer->memory); + HeapFree(GetProcessHeap(),0,This->buffer); + } + } + + if (This->notifies != NULL) + HeapFree(GetProcessHeap(), 0, This->notifies); + + if (This->pwfx) + HeapFree(GetProcessHeap(), 0, This->pwfx); + + HeapFree(GetProcessHeap(),0,This); + + TRACE("(%p) released\n",This); + return 0; +} + +DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, + DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix) +{ + DWORD bplay; + + TRACE("primary playpos=%ld, mixpos=%ld\n", pplay, pmix); + TRACE("this mixpos=%ld, time=%ld\n", bmix, GetTickCount()); + + /* 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 0 /* we'll never fill the primary entirely */ + if (pmix == pplay) { + if ((state == STATE_PLAYING) || (state == STATE_STOPPING)) { + /* wow, the software mixer is really doing well, + * seems the entire primary buffer is filled! */ + pmix += This->dsound->buflen; + } + /* else: the primary buffer is not playing, so probably empty */ + } +#endif + if (pmix < pplay) pmix += This->dsound->buflen; /* wraparound */ + pmix -= pplay; + /* detect buffer underrun */ + if (pwrite < pplay) pwrite += This->dsound->buflen; /* wraparound */ + pwrite -= pplay; + if (pmix > (ds_snd_queue_max * This->dsound->fraglen + pwrite + This->dsound->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; + TRACE("primary back-samples=%ld\n",pmix); + /* adjust for our frequency */ + pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT; + /* multiply by our own sample size */ + pmix *= This->pwfx->nBlockAlign; + TRACE("this back-offset=%ld\n", pmix); + /* subtract from our last mixed position */ + bplay = bmix; + while (bplay < pmix) bplay += This->buflen; /* wraparound */ + bplay -= pmix; + if (This->leadin && ((bplay < This->startpos) || (bplay > bmix))) { + /* seems we haven't started playing yet */ + TRACE("this still in lead-in phase\n"); + bplay = This->startpos; + } + /* return the result */ + return bplay; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition( + LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos +) { + HRESULT hres; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%p,%p)\n",This,playpos,writepos); + if (This->hwbuf) { + hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos); + if (hres != DS_OK) { + WARN("IDsDriverBuffer_GetPosition failed\n"); + return hres; + } + } else { + if (playpos && (This->state != STATE_PLAYING)) { + /* we haven't been merged into the primary buffer (yet) */ + *playpos = This->buf_mixpos; + } else if (playpos) { + DWORD pplay, pwrite, lplay, splay, pstate; + /* 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) + WARN("DSOUND_PrimaryGetPosition failed\n"); + /* detect HEL mode underrun */ + pstate = This->dsound->state; + if (!(This->dsound->hwbuf || This->dsound->pwqueue)) { + TRACE("detected an underrun\n"); + /* pplay = ? */ + if (pstate == STATE_PLAYING) + pstate = STATE_STARTING; + else if (pstate == STATE_STOPPING) + pstate = STATE_STOPPED; + } + /* get data for ourselves while we still have the lock */ + pstate &= This->state; + lplay = This->primary_mixpos; + splay = This->buf_mixpos; + if ((This->dsbd.dwFlags & DSBCAPS_GETCURRENTPOSITION2) || This->dsound->hwbuf) { + /* calculate play position using this */ + *playpos = DSOUND_CalcPlayPosition(This, pstate, pplay, pwrite, lplay, splay); + } else { + /* (unless the app isn't using GETCURRENTPOSITION2) */ + /* don't know exactly how this should be handled... + * the docs says that play cursor is reported as directly + * 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; + *playpos = DSOUND_CalcPlayPosition(This, pstate, wp, pwrite, lplay, splay); + } + LeaveCriticalSection(&(This->dsound->mixlock)); + } + if (writepos) + *writepos = This->buf_mixpos; + } + if (writepos) { + if (This->state != STATE_STOPPED) { + /* apply the documented 10ms lead to writepos */ + *writepos += This->writelead; + } + *writepos %= This->buflen; + } + if (playpos) + This->last_playpos = *playpos; + TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount()); + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus( + LPDIRECTSOUNDBUFFER8 iface,LPDWORD status +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%p), thread is %04lx\n",This,status,GetCurrentThreadId()); + + if (status == NULL) { + WARN("invalid parameter: status = NULL\n"); + return DSERR_INVALIDPARAM; + } + + *status = 0; + if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) { + *status |= DSBSTATUS_PLAYING; + if (This->playflags & DSBPLAY_LOOPING) + *status |= DSBSTATUS_LOOPING; + } + + TRACE("status=%lx\n", *status); + return DS_OK; +} + + +static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat( + LPDIRECTSOUNDBUFFER8 iface, + LPWAVEFORMATEX lpwf, + DWORD wfsize, + LPDWORD wfwritten) +{ + DWORD size; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten); + + size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize; + + if (lpwf) { /* NULL is valid */ + if (wfsize >= size) { + memcpy(lpwf,This->pwfx,size); + if (wfwritten) + *wfwritten = size; + } else { + WARN("invalid parameter: wfsize to small\n"); + if (wfwritten) + *wfwritten = 0; + return DSERR_INVALIDPARAM; + } + } else { + if (wfwritten) + *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize; + else { + WARN("invalid parameter: wfwritten == NULL\n"); + return DSERR_INVALIDPARAM; + } + } + + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_Lock( + LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags +) { + HRESULT hres = DS_OK; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + + TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n", + This, + writecursor, + writebytes, + lplpaudioptr1, + audiobytes1, + lplpaudioptr2, + audiobytes2, + flags, + GetTickCount() + ); + + if (flags & DSBLOCK_FROMWRITECURSOR) { + DWORD writepos; + /* GetCurrentPosition does too much magic to duplicate here */ + hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writepos); + if (hres != DS_OK) { + WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n"); + return hres; + } + writecursor += writepos; + } + writecursor %= This->buflen; + if (flags & DSBLOCK_ENTIREBUFFER) + writebytes = This->buflen; + if (writebytes > This->buflen) + writebytes = This->buflen; + + EnterCriticalSection(&(This->lock)); + + if ((writebytes == This->buflen) && + ((This->state == STATE_STARTING) || + (This->state == STATE_PLAYING))) + /* some games, like Half-Life, try to be clever (not) and + * keep one secondary buffer, and mix sounds into it itself, + * locking the entire buffer every time... so we can just forget + * about tracking the last-written-to-position... */ + This->probably_valid_to = (DWORD)-1; + else + This->probably_valid_to = writecursor; + + if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { + hres = IDsDriverBuffer_Lock(This->hwbuf, + lplpaudioptr1, audiobytes1, + lplpaudioptr2, audiobytes2, + writecursor, writebytes, + 0); + if (hres != DS_OK) { + WARN("IDsDriverBuffer_Lock failed\n"); + LeaveCriticalSection(&(This->lock)); + return hres; + } + } else { + BOOL remix = FALSE; + if (writecursor+writebytes <= This->buflen) { + *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor; + *audiobytes1 = writebytes; + if (lplpaudioptr2) + *(LPBYTE*)lplpaudioptr2 = NULL; + if (audiobytes2) + *audiobytes2 = 0; + TRACE("->%ld.0\n",writebytes); + } else { + *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor; + *audiobytes1 = This->buflen-writecursor; + if (lplpaudioptr2) + *(LPBYTE*)lplpaudioptr2 = This->buffer->memory; + if (audiobytes2) + *audiobytes2 = writebytes-(This->buflen-writecursor); + TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0); + } + if (This->state == STATE_PLAYING) { + /* if the segment between playpos and buf_mixpos is touched, + * we need to cancel some mixing */ + /* we'll assume that the app always calls GetCurrentPosition before + * locking a playing buffer, so that last_playpos is up-to-date */ + if (This->buf_mixpos >= This->last_playpos) { + if (This->buf_mixpos > writecursor && + This->last_playpos < writecursor+writebytes) + remix = TRUE; + } else { + if (This->buf_mixpos > writecursor || + This->last_playpos < writecursor+writebytes) + remix = TRUE; + } + if (remix) { + TRACE("locking prebuffered region, ouch\n"); + DSOUND_MixCancelAt(This, writecursor); + } + } + } + + LeaveCriticalSection(&(This->lock)); + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition( + LPDIRECTSOUNDBUFFER8 iface,DWORD newpos +) { + HRESULT hres = DS_OK; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%ld)\n",This,newpos); + + /* **** */ + EnterCriticalSection(&(This->lock)); + + newpos %= This->buflen; + This->buf_mixpos = newpos; + if (This->hwbuf) { + hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos); + if (hres != DS_OK) + WARN("IDsDriverBuffer_SetPosition failed\n"); + } + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + return hres; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_SetPan( + LPDIRECTSOUNDBUFFER8 iface,LONG pan +) { + HRESULT hres = DS_OK; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + + TRACE("(%p,%ld)\n",This,pan); + + if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) { + WARN("invalid parameter: pan = %ld\n", pan); + return DSERR_INVALIDPARAM; + } + + /* You cannot use both pan and 3D controls */ + if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) || + (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) { + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; + } + + /* **** */ + EnterCriticalSection(&(This->lock)); + + if (This->volpan.lPan != pan) { + This->volpan.lPan = pan; + DSOUND_RecalcVolPan(&(This->volpan)); + + if (This->hwbuf) { + hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan)); + if (hres != DS_OK) + WARN("IDsDriverBuffer_SetVolumePan failed\n"); + } else + DSOUND_ForceRemix(This); + } + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + return hres; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetPan( + LPDIRECTSOUNDBUFFER8 iface,LPLONG pan +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%p)\n",This,pan); + + if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) { + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; + } + + if (pan == NULL) { + WARN("invalid parameter: pan = NULL\n"); + return DSERR_INVALIDPARAM; + } + + *pan = This->volpan.lPan; + + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( + LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2 +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + DWORD probably_valid_to; + HRESULT hres = DS_OK; + + TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2); + + /* **** */ + EnterCriticalSection(&(This->lock)); + + if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { + hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2); + if (hres != DS_OK) + WARN("IDsDriverBuffer_Unlock failed\n"); + } + + if (hres == DS_OK) { + if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2; + else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1; + probably_valid_to %= This->buflen; + if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) && + ((This->state == STATE_STARTING) || + (This->state == STATE_PLAYING))) + /* see IDirectSoundBufferImpl_Lock */ + probably_valid_to = (DWORD)-1; + This->probably_valid_to = probably_valid_to; + } + + LeaveCriticalSection(&(This->lock)); + /* **** */ + + TRACE("probably_valid_to=%ld\n", This->probably_valid_to); + return hres; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_Restore( + LPDIRECTSOUNDBUFFER8 iface +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + FIXME("(%p):stub\n",This); + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency( + LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p,%p)\n",This,freq); + + if (freq == NULL) { + WARN("invalid parameter: freq = NULL\n"); + return DSERR_INVALIDPARAM; + } + + *freq = This->freq; + TRACE("-> %ld\n", *freq); + + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_SetFX( + LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + DWORD u; + + FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); + + if (pdwResultCodes) + for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN; + + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources( + LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + DWORD u; + + FIXME("(%p,%08lu,%lu,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes); + + if (pdwResultCodes) + for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN; + + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath( + LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + + FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInter face),ppObject); + + WARN("control unavailable\n"); + return DSERR_CONTROLUNAVAIL; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_Initialize( + LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND dsound,LPCDSBUFFERDESC dbsd +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd); + DPRINTF("Re-Init!!!\n"); + WARN("already initialized\n"); + return DSERR_ALREADYINITIALIZED; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps( + LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + TRACE("(%p)->(%p)\n",This,caps); + + if (caps == NULL) { + WARN("invalid parameter: caps == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (caps->dwSize < sizeof(*caps)) { + WARN("invalid parameter: caps->dwSize = %ld < %d\n",caps->dwSize, sizeof(*caps)); + return DSERR_INVALIDPARAM; + } + + caps->dwFlags = This->dsbd.dwFlags; + if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE; + else caps->dwFlags |= DSBCAPS_LOCSOFTWARE; + + caps->dwBufferBytes = This->buflen; + + /* This value represents the speed of the "unlock" command. + As unlock is quite fast (it does not do anything), I put + 4096 ko/s = 4 Mo / s */ + /* FIXME: hwbuf speed */ + caps->dwUnlockTransferRate = 4096; + caps->dwPlayCpuOverhead = 0; + + return DS_OK; +} + +static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( + LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj +) { + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + + if (ppobj == NULL) { + WARN("invalid parameter\n"); + return E_INVALIDARG; + } + + *ppobj = NULL; /* assume failure */ + + if ( IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDirectSoundBuffer) || + IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) { + if (!This->dsb) + SecondaryBufferImpl_Create(This, &(This->dsb)); + if (This->dsb) { + IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb); + *ppobj = This->dsb; + return S_OK; + } + WARN("IID_IDirectSoundBuffer\n"); + return E_NOINTERFACE; + } + + if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) { + if (!This->notify) + IDirectSoundNotifyImpl_Create(This, &(This->notify)); + if (This->notify) { + IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify); + *ppobj = This->notify; [truncated at 1000 lines; 10802 more skipped]