Dsound from win 2004 month 12 or month 11. It is working in windows 2000
in software emulation mode. Tested with quake2 and some other apps. Not
tested in ReactOS
Added: trunk/reactos/lib/dsound/buffer.c
Added: trunk/reactos/lib/dsound/capture.c
Modified: trunk/reactos/lib/dsound/dsound.c
Deleted: trunk/reactos/lib/dsound/dsound.def
Added: trunk/reactos/lib/dsound/dsound.spec
Modified: trunk/reactos/lib/dsound/dsound.xml
Added: trunk/reactos/lib/dsound/dsound_main.c
Added: trunk/reactos/lib/dsound/dsound_private.h
Added: trunk/reactos/lib/dsound/dxroslayer/
Added: trunk/reactos/lib/dsound/dxroslayer/dxros_layer.h
Added: trunk/reactos/lib/dsound/dxroslayer/dxrosdrv_querydsounddesc.c
Added: trunk/reactos/lib/dsound/dxroslayer/dxrosdrv_querydsoundiface.c
Added: trunk/reactos/lib/dsound/dxroslayer/dxroslayer.c
Added: trunk/reactos/lib/dsound/dxroslayer/getguidfromstring.c
Added: trunk/reactos/lib/dsound/mixer.c
Added: trunk/reactos/lib/dsound/primary.c
Added: trunk/reactos/lib/dsound/propset.c
Added: trunk/reactos/lib/dsound/regsvr.c
Added: trunk/reactos/lib/dsound/sound3d.c
Added: trunk/reactos/lib/dsound/tests/
Added: trunk/reactos/lib/dsound/tests/.cvsignore
Added: trunk/reactos/lib/dsound/tests/Makefile.in
Added: trunk/reactos/lib/dsound/tests/capture.c
Added: trunk/reactos/lib/dsound/tests/ds3d.c
Added: trunk/reactos/lib/dsound/tests/ds3d8.c
Added: trunk/reactos/lib/dsound/tests/dsound.c
Added: trunk/reactos/lib/dsound/tests/dsound8.c
Added: trunk/reactos/lib/dsound/tests/dsound_test.h
Added: trunk/reactos/lib/dsound/tests/propset.c
Added: trunk/reactos/lib/dsound/version.rc
_____
Added: trunk/reactos/lib/dsound/buffer.c
--- trunk/reactos/lib/dsound/buffer.c 2005-10-08 16:26:04 UTC (rev
18338)
+++ trunk/reactos/lib/dsound/buffer.c 2005-10-08 16:38:07 UTC (rev
18339)
@@ -0,0 +1,1562 @@
+/* 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;
+ return S_OK;
+ }
+ WARN("IID_IDirectSoundNotify\n");
+ return E_NOINTERFACE;
+ }
+
+ if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
+ if (!This->ds3db)
+ IDirectSound3DBufferImpl_Create(This,
&(This->ds3db));
+ if (This->ds3db) {
+
IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
+ *ppobj = This->ds3db;
+ return S_OK;
+ }
+ WARN("IID_IDirectSound3DBuffer\n");
+ return E_NOINTERFACE;
+ }
+
+ if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
+ ERR("app requested IDirectSound3DListener on secondary
buffer\n");
+ return E_NOINTERFACE;
+ }
+
+ if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
+ if (!This->iks)
+ IKsBufferPropertySetImpl_Create(This,
&(This->iks));
+ if (This->iks) {
+
IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks);
+ *ppobj = This->iks;
+ return S_OK;
+ }
[truncated at 1000 lines; 16475 more skipped]