Support DirectSound 8 interfaces. Split interface implementations into

separate files. Split primary buffer and secondary buffer interfaces
into separate implementations. Made the primary buffer state part of
the dsound object, so primary buffer objects can be created and
refcounted independently. Made the interfaces follow COM aggregation
rules more closely. Converted the dsound critical section to a R/W
lock to improve potential remixing concurrency. Fixed various bugs and
refcounting issues.
This commit is contained in:
Ove Kaaven 2002-06-13 19:15:06 +00:00 committed by Alexandre Julliard
parent 8e4eb3ab5f
commit 935e3df35c
11 changed files with 4719 additions and 3608 deletions

View file

@ -10,7 +10,13 @@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
dsound_main.c
buffer.c \
capture.c \
dsound_main.c \
mixer.c \
primary.c \
propset.c \
sound3d.c
@MAKE_DLL_RULES@

986
dlls/dsound/buffer.c Normal file
View file

@ -0,0 +1,986 @@
/* 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 <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> /* Insomnia - pow() function */
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "ntddk.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
) {
ICOM_THIS(IDirectSoundNotifyImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundBuffer8_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
}
static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) {
ICOM_THIS(IDirectSoundNotifyImpl,iface);
DWORD ref;
TRACE("(%p) ref was %ld\n", This, This->ref);
ref = InterlockedIncrement(&(This->ref));
return ref;
}
static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
ICOM_THIS(IDirectSoundNotifyImpl,iface);
DWORD ref;
TRACE("(%p) ref was %ld\n", This, This->ref);
ref = InterlockedDecrement(&(This->ref));
if (!ref) {
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return ref;
}
static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
) {
ICOM_THIS(IDirectSoundNotifyImpl,iface);
int i;
if (TRACE_ON(dsound)) {
TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
for (i=0;i<howmuch;i++)
TRACE("notify at %ld to 0x%08lx\n",
notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
}
This->dsb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->dsb->notifies,(This->dsb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY));
memcpy( This->dsb->notifies+This->dsb->nrofnotifies,
notify,
howmuch*sizeof(DSBPOSITIONNOTIFY)
);
This->dsb->nrofnotifies+=howmuch;
return S_OK;
}
static ICOM_VTABLE(IDirectSoundNotify) dsnvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IDirectSoundNotifyImpl_QueryInterface,
IDirectSoundNotifyImpl_AddRef,
IDirectSoundNotifyImpl_Release,
IDirectSoundNotifyImpl_SetNotificationPositions,
};
/*******************************************************************************
* IDirectSoundBuffer
*/
static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(
LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX wfex
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p)\n",This,wfex);
/* This method is not available on secondary buffers */
return DSERR_INVALIDCALL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(
LPDIRECTSOUNDBUFFER8 iface,LONG vol
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
LONG oldVol;
TRACE("(%p,%ld)\n",This,vol);
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME))
return DSERR_CONTROLUNAVAIL;
if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN))
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) {
IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
}
else DSOUND_ForceRemix(This);
}
LeaveCriticalSection(&(This->lock));
/* **** */
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(
LPDIRECTSOUNDBUFFER8 iface,LPLONG vol
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p)\n",This,vol);
if (vol == NULL)
return DSERR_INVALIDPARAM;
if (This->dsbd.dwFlags & DSBCAPS_CTRL3D)
*vol = This->ds3db->lVolume;
else
*vol = This->volpan.lVolume;
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(
LPDIRECTSOUNDBUFFER8 iface,DWORD freq
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
DWORD oldFreq;
TRACE("(%p,%ld)\n",This,freq);
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY))
return DSERR_CONTROLUNAVAIL;
if (freq == DSBFREQUENCY_ORIGINAL)
freq = This->wfx.nSamplesPerSec;
if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX))
return DSERR_INVALIDPARAM;
/* **** */
EnterCriticalSection(&(This->lock));
oldFreq = This->freq;
This->freq = freq;
if (freq != oldFreq) {
This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->wfx.nSamplesPerSec;
This->nAvgBytesPerSec = freq * This->wfx.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
) {
ICOM_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) {
IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags);
This->state = STATE_PLAYING;
}
LeaveCriticalSection(&(This->lock));
/* **** */
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
{
ICOM_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) {
IDsDriverBuffer_Stop(This->hwbuf);
This->state = STATE_STOPPED;
}
DSOUND_CheckEvent(This, 0);
LeaveCriticalSection(&(This->lock));
/* **** */
return DS_OK;
}
static DWORD WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
DWORD ref;
TRACE("(%p) ref was %ld, thread is %lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedIncrement(&(This->ref));
if (!ref) {
FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
}
return ref;
}
static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
int i;
DWORD ref;
TRACE("(%p) ref was %ld, thread is %lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedDecrement(&(This->ref));
if (ref) return ref;
RtlAcquireResourceExclusive(&(This->dsound->lock), TRUE);
for (i=0;i<This->dsound->nrofbuffers;i++)
if (This->dsound->buffers[i] == This)
break;
if (i < This->dsound->nrofbuffers) {
/* Put the last buffer of the list in the (now empty) position */
This->dsound->buffers[i] = This->dsound->buffers[This->dsound->nrofbuffers - 1];
This->dsound->nrofbuffers--;
This->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,This->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*This->dsound->nrofbuffers);
TRACE("buffer count is now %d\n", This->dsound->nrofbuffers);
IDirectSound_Release((LPDIRECTSOUND)This->dsound);
}
RtlReleaseResource(&(This->dsound->lock));
DeleteCriticalSection(&(This->lock));
if (This->hwbuf) {
IDsDriverBuffer_Release(This->hwbuf);
if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
HeapFree(GetProcessHeap(),0,This->buffer);
}
else if (!This->parent)
HeapFree(GetProcessHeap(),0,This->buffer);
if (This->ds3db) {
DeleteCriticalSection(&This->ds3db->lock);
HeapFree(GetProcessHeap(), 0, This->ds3db);
}
if (This->iks) {
HeapFree(GetProcessHeap(), 0, This->iks);
}
if (This->parent)
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->parent);
HeapFree(GetProcessHeap(),0,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->wfx.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->wfx.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;
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p,%p)\n",This,playpos,writepos);
if (This->hwbuf) {
hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
if (hres)
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));
DSOUND_PrimaryGetPosition(This->dsound, &pplay, &pwrite);
/* 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;
while (wp >= This->dsound->buflen)
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;
while (*writepos >= This->buflen) *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
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p), thread is %lx\n",This,status,GetCurrentThreadId());
if (status == NULL)
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
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
if (wfsize>sizeof(This->wfx))
wfsize = sizeof(This->wfx);
if (lpwf) { /* NULL is valid */
memcpy(lpwf,&(This->wfx),wfsize);
if (wfwritten)
*wfwritten = wfsize;
} else
if (wfwritten)
*wfwritten = sizeof(This->wfx);
else
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
) {
ICOM_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 */
IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writepos);
writecursor += writepos;
}
while (writecursor >= This->buflen)
writecursor -= This->buflen;
if (flags & DSBLOCK_ENTIREBUFFER)
writebytes = This->buflen;
if (writebytes > This->buflen)
writebytes = This->buflen;
assert(audiobytes1!=audiobytes2);
assert(lplpaudioptr1!=lplpaudioptr2);
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) {
IDsDriverBuffer_Lock(This->hwbuf,
lplpaudioptr1, audiobytes1,
lplpaudioptr2, audiobytes2,
writecursor, writebytes,
0);
}
else {
BOOL remix = FALSE;
if (writecursor+writebytes <= This->buflen) {
*(LPBYTE*)lplpaudioptr1 = This->buffer+writecursor;
*audiobytes1 = writebytes;
if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = NULL;
if (audiobytes2)
*audiobytes2 = 0;
TRACE("->%ld.0\n",writebytes);
} else {
*(LPBYTE*)lplpaudioptr1 = This->buffer+writecursor;
*audiobytes1 = This->buflen-writecursor;
if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = This->buffer;
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);
}
}
}
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(
LPDIRECTSOUNDBUFFER8 iface,DWORD newpos
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%ld)\n",This,newpos);
/* **** */
EnterCriticalSection(&(This->lock));
while (newpos >= This->buflen)
newpos -= This->buflen;
This->buf_mixpos = newpos;
if (This->hwbuf)
IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos);
LeaveCriticalSection(&(This->lock));
/* **** */
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(
LPDIRECTSOUNDBUFFER8 iface,LONG pan
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
LONG oldPan;
TRACE("(%p,%ld)\n",This,pan);
if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT))
return DSERR_INVALIDPARAM;
/* You cannot use both pan and 3D controls */
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
(This->dsbd.dwFlags & DSBCAPS_CTRL3D))
return DSERR_CONTROLUNAVAIL;
/* **** */
EnterCriticalSection(&(This->lock));
oldPan = This->volpan.lPan;
This->volpan.lPan = pan;
if (pan != oldPan) {
DSOUND_RecalcVolPan(&(This->volpan));
if (This->hwbuf) {
IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
}
else DSOUND_ForceRemix(This);
}
LeaveCriticalSection(&(This->lock));
/* **** */
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(
LPDIRECTSOUNDBUFFER8 iface,LPLONG pan
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p)\n",This,pan);
if (pan == NULL)
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
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
DWORD probably_valid_to;
TRACE("(%p,%p,%ld,%p,%ld):stub\n", This,p1,x1,p2,x2);
#if 0
/* Preprocess 3D buffers... */
/* This is highly experimental and liable to break things */
if (This->dsbd.dwFlags & DSBCAPS_CTRL3D)
DSOUND_Create3DBuffer(This);
#endif
if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
}
if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer) + x2;
else probably_valid_to = (((LPBYTE)p1)-This->buffer) + x1;
while (probably_valid_to >= This->buflen)
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;
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_Restore(
LPDIRECTSOUNDBUFFER8 iface
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
FIXME("(%p):stub\n",This);
return DS_OK;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%p)\n",This,freq);
if (freq == NULL)
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
) {
ICOM_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;
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(
LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes
) {
ICOM_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;
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(
LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(
LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND8 dsound,LPDSBUFFERDESC dbsd
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd);
DPRINTF("Re-Init!!!\n");
return DSERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(
LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p)->(%p)\n",This,caps);
if (caps == NULL)
return DSERR_INVALIDPARAM;
/* I think we should check this value, not set it. See */
/* Inside DirectX, p215. That should apply here, too. */
caps->dwSize = sizeof(*caps);
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
) {
ICOM_THIS(IDirectSoundBufferImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
IDirectSoundNotifyImpl *dsn;
dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn));
dsn->ref = 1;
dsn->dsb = This;
IDirectSoundBuffer8_AddRef(iface);
ICOM_VTBL(dsn) = &dsnvt;
*ppobj = (LPVOID)dsn;
return S_OK;
}
if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
if (!This->ds3db)
IDirectSound3DBufferImpl_Create(This, &This->ds3db);
*ppobj = This->ds3db;
if (*ppobj) {
IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)*ppobj);
return S_OK;
}
return E_FAIL;
}
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
ERR("app requested IDirectSound3DListener on secondary buffer\n");
*ppobj = NULL;
return E_FAIL;
}
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
if (!This->iks)
IKsPropertySetImpl_Create(This, &This->iks);
*ppobj = This->iks;
if (*ppobj) {
IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj);
return S_OK;
}
return E_FAIL;
}
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
*ppobj = NULL;
return E_NOINTERFACE;
}
static ICOM_VTABLE(IDirectSoundBuffer8) dsbvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IDirectSoundBufferImpl_QueryInterface,
IDirectSoundBufferImpl_AddRef,
IDirectSoundBufferImpl_Release,
IDirectSoundBufferImpl_GetCaps,
IDirectSoundBufferImpl_GetCurrentPosition,
IDirectSoundBufferImpl_GetFormat,
IDirectSoundBufferImpl_GetVolume,
IDirectSoundBufferImpl_GetPan,
IDirectSoundBufferImpl_GetFrequency,
IDirectSoundBufferImpl_GetStatus,
IDirectSoundBufferImpl_Initialize,
IDirectSoundBufferImpl_Lock,
IDirectSoundBufferImpl_Play,
IDirectSoundBufferImpl_SetCurrentPosition,
IDirectSoundBufferImpl_SetFormat,
IDirectSoundBufferImpl_SetVolume,
IDirectSoundBufferImpl_SetPan,
IDirectSoundBufferImpl_SetFrequency,
IDirectSoundBufferImpl_Stop,
IDirectSoundBufferImpl_Unlock,
IDirectSoundBufferImpl_Restore,
IDirectSoundBufferImpl_SetFX,
IDirectSoundBufferImpl_AcquireResources,
IDirectSoundBufferImpl_GetObjectInPath
};
HRESULT WINAPI SecondaryBuffer_Create(
IDirectSoundImpl *This,
IDirectSoundBufferImpl **pdsb,
LPDSBUFFERDESC dsbd)
{
IDirectSoundBufferImpl *dsb;
LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
HRESULT err = DS_OK;
DWORD capf = 0;
int use_hw;
if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
ERR("invalid sound buffer size %ld\n", dsbd->dwBufferBytes);
return DSERR_INVALIDPARAM; /* FIXME: which error? */
}
dsb = (IDirectSoundBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
dsb->ref = 1;
dsb->dsound = This;
dsb->parent = NULL;
ICOM_VTBL(dsb) = &dsbvt;
memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd));
if (wfex)
memcpy(&dsb->wfx, wfex, sizeof(dsb->wfx));
TRACE("Created buffer at %p\n", dsb);
dsb->buflen = dsbd->dwBufferBytes;
dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
/* Check necessary hardware mixing capabilities */
if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
else capf |= DSCAPS_SECONDARYMONO;
if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
else capf |= DSCAPS_SECONDARY8BIT;
use_hw = (This->drvcaps.dwFlags & capf) == capf;
/* FIXME: check hardware sample rate mixing capabilities */
/* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
/* FIXME: check whether any hardware buffers are left */
/* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */
/* Allocate system memory if applicable */
if ((This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
dsb->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer == NULL)
err = DSERR_OUTOFMEMORY;
}
/* Allocate the hardware buffer */
if (use_hw && (err == DS_OK)) {
err = IDsDriver_CreateSoundBuffer(This->driver,wfex,dsbd->dwFlags,0,
&(dsb->buflen),&(dsb->buffer),
(LPVOID*)&(dsb->hwbuf));
}
if (err != DS_OK) {
if (dsb->buffer)
HeapFree(GetProcessHeap(),0,dsb->buffer);
HeapFree(GetProcessHeap(),0,dsb);
dsb = NULL;
return err;
}
/* calculate fragment size and write lead */
DSOUND_RecalcFormat(dsb);
/* It's not necessary to initialize values to zero since */
/* we allocated this structure with HEAP_ZERO_MEMORY... */
dsb->playpos = 0;
dsb->buf_mixpos = 0;
dsb->state = STATE_STOPPED;
dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) /
This->wfx.nSamplesPerSec;
dsb->nAvgBytesPerSec = dsb->freq *
dsbd->lpwfxFormat->nBlockAlign;
if (dsbd->dwFlags & DSBCAPS_CTRL3D) {
IDirectSound3DBufferImpl_Create(dsb, &dsb->ds3db);
}
else
DSOUND_RecalcVolPan(&(dsb->volpan));
InitializeCriticalSection(&(dsb->lock));
/* register buffer */
RtlAcquireResourceExclusive(&(This->lock), TRUE);
if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
IDirectSoundBufferImpl **newbuffers = (IDirectSoundBufferImpl**)HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl*)*(This->nrofbuffers+1));
if (newbuffers) {
This->buffers = newbuffers;
This->buffers[This->nrofbuffers] = dsb;
This->nrofbuffers++;
TRACE("buffer count is now %d\n", This->nrofbuffers);
} else {
ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
err = DSERR_OUTOFMEMORY;
}
}
RtlReleaseResource(&(This->lock));
IDirectSound8_AddRef((LPDIRECTSOUND8)This);
if (err != DS_OK) {
/* oops... */
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)dsb);
*pdsb = NULL;
return err;
}
*pdsb = dsb;
return S_OK;
}

537
dlls/dsound/capture.c Normal file
View file

@ -0,0 +1,537 @@
/* DirectSoundCapture
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Rob Riggs
* Copyright 2000-2001 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
*/
/*
* TODO:
* Implement DirectSoundCapture API
*/
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "wine/debug.h"
#include "dsound.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
/*****************************************************************************
* Predeclare the interface implementation structures
*/
typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
/*****************************************************************************
* IDirectSoundCapture implementation structure
*/
struct IDirectSoundCaptureImpl
{
/* IUnknown fields */
ICOM_VFIELD(IDirectSoundCapture);
DWORD ref;
/* IDirectSoundCaptureImpl fields */
CRITICAL_SECTION lock;
};
/*****************************************************************************
* IDirectSoundCapture implementation structure
*/
struct IDirectSoundCaptureBufferImpl
{
/* IUnknown fields */
ICOM_VFIELD(IDirectSoundCaptureBuffer8);
DWORD ref;
/* IDirectSoundCaptureBufferImpl fields */
CRITICAL_SECTION lock;
};
static HRESULT DSOUND_CreateDirectSoundCapture( LPVOID* ppobj );
static HRESULT DSOUND_CreateDirectSoundCaptureBuffer( LPCDSCBUFFERDESC lpcDSCBufferDesc, LPVOID* ppobj );
static ICOM_VTABLE(IDirectSoundCapture) dscvt;
static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt;
/***************************************************************************
* DirectSoundCaptureCreate [DSOUND.6]
*
* Create and initialize a DirectSoundCapture interface
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
* DSERR_OUTOFMEMORY
*/
HRESULT WINAPI DirectSoundCaptureCreate8(
LPCGUID lpcGUID,
LPDIRECTSOUNDCAPTURE* lplpDSC,
LPUNKNOWN pUnkOuter )
{
TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
if( pUnkOuter ) {
return DSERR_NOAGGREGATION;
}
/* Default device? */
if ( !lpcGUID ||
IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) ||
IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture) ) {
return DSOUND_CreateDirectSoundCapture( (LPVOID*)lplpDSC );
}
FIXME( "Unknown GUID %s\n", debugstr_guid(lpcGUID) );
*lplpDSC = NULL;
return DSERR_OUTOFMEMORY;
}
/***************************************************************************
* DirectSoundCaptureEnumerateA [DSOUND.7]
*
* Enumerate all DirectSound drivers installed in the system
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_INVALIDPARAM
*/
HRESULT WINAPI DirectSoundCaptureEnumerateA(
LPDSENUMCALLBACKA lpDSEnumCallback,
LPVOID lpContext)
{
TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
if ( lpDSEnumCallback )
lpDSEnumCallback(NULL,"WINE Primary Sound Capture Driver",
"SoundCap",lpContext);
return DS_OK;
}
/***************************************************************************
* DirectSoundCaptureEnumerateW [DSOUND.8]
*
* Enumerate all DirectSound drivers installed in the system
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_INVALIDPARAM
*/
HRESULT WINAPI DirectSoundCaptureEnumerateW(
LPDSENUMCALLBACKW lpDSEnumCallback,
LPVOID lpContext)
{
FIXME("(%p,%p):stub\n", lpDSEnumCallback, lpContext );
return DS_OK;
}
static HRESULT
DSOUND_CreateDirectSoundCapture( LPVOID* ppobj )
{
*ppobj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( IDirectSoundCaptureImpl ) );
if ( *ppobj == NULL ) {
return DSERR_OUTOFMEMORY;
}
{
ICOM_THIS(IDirectSoundCaptureImpl,*ppobj);
This->ref = 1;
ICOM_VTBL(This) = &dscvt;
InitializeCriticalSection( &This->lock );
}
return S_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureImpl_QueryInterface(
LPDIRECTSOUNDCAPTURE iface,
REFIID riid,
LPVOID* ppobj )
{
ICOM_THIS(IDirectSoundCaptureImpl,iface);
FIXME( "(%p)->(%s,%p): stub\n", This, debugstr_guid(riid), ppobj );
return E_FAIL;
}
static ULONG WINAPI
IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
{
ULONG uRef;
ICOM_THIS(IDirectSoundCaptureImpl,iface);
EnterCriticalSection( &This->lock );
TRACE( "(%p) was 0x%08lx\n", This, This->ref );
uRef = ++(This->ref);
LeaveCriticalSection( &This->lock );
return uRef;
}
static ULONG WINAPI
IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
{
ULONG uRef;
ICOM_THIS(IDirectSoundCaptureImpl,iface);
EnterCriticalSection( &This->lock );
TRACE( "(%p) was 0x%08lx\n", This, This->ref );
uRef = --(This->ref);
LeaveCriticalSection( &This->lock );
if ( uRef == 0 ) {
DeleteCriticalSection( &This->lock );
HeapFree( GetProcessHeap(), 0, This );
}
return uRef;
}
static HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(
LPDIRECTSOUNDCAPTURE iface,
LPCDSCBUFFERDESC lpcDSCBufferDesc,
LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
LPUNKNOWN pUnk )
{
HRESULT hr;
ICOM_THIS(IDirectSoundCaptureImpl,iface);
TRACE( "(%p)->(%p,%p,%p)\n", This, lpcDSCBufferDesc, lplpDSCaptureBuffer, pUnk );
if ( pUnk ) {
return DSERR_INVALIDPARAM;
}
hr = DSOUND_CreateDirectSoundCaptureBuffer( lpcDSCBufferDesc, (LPVOID*)lplpDSCaptureBuffer );
return hr;
}
static HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(
LPDIRECTSOUNDCAPTURE iface,
LPDSCCAPS lpDSCCaps )
{
ICOM_THIS(IDirectSoundCaptureImpl,iface);
FIXME( "(%p)->(%p): stub\n", This, lpDSCCaps );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
LPDIRECTSOUNDCAPTURE iface,
LPCGUID lpcGUID )
{
ICOM_THIS(IDirectSoundCaptureImpl,iface);
FIXME( "(%p)->(%p): stub\n", This, lpcGUID );
return DS_OK;
}
static ICOM_VTABLE(IDirectSoundCapture) dscvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown methods */
IDirectSoundCaptureImpl_QueryInterface,
IDirectSoundCaptureImpl_AddRef,
IDirectSoundCaptureImpl_Release,
/* IDirectSoundCapture methods */
IDirectSoundCaptureImpl_CreateCaptureBuffer,
IDirectSoundCaptureImpl_GetCaps,
IDirectSoundCaptureImpl_Initialize
};
static HRESULT
DSOUND_CreateDirectSoundCaptureBuffer( LPCDSCBUFFERDESC lpcDSCBufferDesc, LPVOID* ppobj )
{
FIXME( "(%p,%p): ignoring lpcDSCBufferDesc\n", lpcDSCBufferDesc, ppobj );
*ppobj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( IDirectSoundCaptureBufferImpl ) );
if ( *ppobj == NULL ) {
return DSERR_OUTOFMEMORY;
}
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj);
This->ref = 1;
ICOM_VTBL(This) = &dscbvt;
InitializeCriticalSection( &This->lock );
}
return S_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_QueryInterface(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
REFIID riid,
LPVOID* ppobj )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%s,%p): stub\n", This, debugstr_guid(riid), ppobj );
return E_FAIL;
}
static ULONG WINAPI
IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
{
ULONG uRef;
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
EnterCriticalSection( &This->lock );
TRACE( "(%p) was 0x%08lx\n", This, This->ref );
uRef = ++(This->ref);
LeaveCriticalSection( &This->lock );
return uRef;
}
static ULONG WINAPI
IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
{
ULONG uRef;
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
EnterCriticalSection( &This->lock );
TRACE( "(%p) was 0x%08lx\n", This, This->ref );
uRef = --(This->ref);
LeaveCriticalSection( &This->lock );
if ( uRef == 0 ) {
DeleteCriticalSection( &This->lock );
HeapFree( GetProcessHeap(), 0, This );
}
return uRef;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetCaps(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
LPDSCBCAPS lpDSCBCaps )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%p): stub\n", This, lpDSCBCaps );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetCurrentPosition(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
LPDWORD lpdwCapturePosition,
LPDWORD lpdwReadPosition )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%p,%p): stub\n", This, lpdwCapturePosition, lpdwReadPosition );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetFormat(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
LPWAVEFORMATEX lpwfxFormat,
DWORD dwSizeAllocated,
LPDWORD lpdwSizeWritten )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%p,0x%08lx,%p): stub\n", This, lpwfxFormat, dwSizeAllocated, lpdwSizeWritten );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetStatus(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
LPDWORD lpdwStatus )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%p): stub\n", This, lpdwStatus );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Initialize(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
LPDIRECTSOUNDCAPTURE lpDSC,
LPCDSCBUFFERDESC lpcDSCBDesc )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Lock(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
DWORD dwReadCusor,
DWORD dwReadBytes,
LPVOID* lplpvAudioPtr1,
LPDWORD lpdwAudioBytes1,
LPVOID* lplpvAudioPtr2,
LPDWORD lpdwAudioBytes2,
DWORD dwFlags )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%08lu,%08lu,%p,%p,%p,%p,0x%08lx): stub\n", This, dwReadCusor, dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2, dwFlags );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Start(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
DWORD dwFlags )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(0x%08lx): stub\n", This, dwFlags );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p): stub\n", This );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Unlock(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
LPVOID lpvAudioPtr1,
DWORD dwAudioBytes1,
LPVOID lpvAudioPtr2,
DWORD dwAudioBytes2 )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%p,%08lu,%p,%08lu): stub\n", This, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2 );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetObjectInPath(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
REFGUID rguidObject,
DWORD dwIndex,
REFGUID rguidInterface,
LPVOID* ppObject )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject), dwIndex, debugstr_guid(rguidInterface), ppObject );
return DS_OK;
}
static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetFXStatus(
LPDIRECTSOUNDCAPTUREBUFFER8 iface,
DWORD dwFXCount,
LPDWORD pdwFXStatus )
{
ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
FIXME( "(%p)->(%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
return DS_OK;
}
static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown methods */
IDirectSoundCaptureBufferImpl_QueryInterface,
IDirectSoundCaptureBufferImpl_AddRef,
IDirectSoundCaptureBufferImpl_Release,
/* IDirectSoundCaptureBuffer methods */
IDirectSoundCaptureBufferImpl_GetCaps,
IDirectSoundCaptureBufferImpl_GetCurrentPosition,
IDirectSoundCaptureBufferImpl_GetFormat,
IDirectSoundCaptureBufferImpl_GetStatus,
IDirectSoundCaptureBufferImpl_Initialize,
IDirectSoundCaptureBufferImpl_Lock,
IDirectSoundCaptureBufferImpl_Start,
IDirectSoundCaptureBufferImpl_Stop,
IDirectSoundCaptureBufferImpl_Unlock,
/* IDirectSoundCaptureBuffer methods */
IDirectSoundCaptureBufferImpl_GetObjectInPath,
IDirectSoundCaptureBufferImpl_GetFXStatus
};

View file

@ -1,11 +1,15 @@
name dsound
0 stub DirectSoundUnknown
1 stdcall DirectSoundCreate(ptr ptr ptr) DirectSoundCreate
1 stdcall DirectSoundCreate(ptr ptr ptr) DirectSoundCreate8
2 stdcall DirectSoundEnumerateA(ptr ptr) DirectSoundEnumerateA
3 stdcall DirectSoundEnumerateW(ptr ptr) DirectSoundEnumerateW
4 stdcall DllCanUnloadNow() DSOUND_DllCanUnloadNow
5 stdcall DllGetClassObject(ptr ptr ptr) DSOUND_DllGetClassObject
6 stdcall DirectSoundCaptureCreate(ptr ptr ptr) DirectSoundCaptureCreate
6 stdcall DirectSoundCaptureCreate(ptr ptr ptr) DirectSoundCaptureCreate8
7 stdcall DirectSoundCaptureEnumerateA(ptr ptr) DirectSoundCaptureEnumerateA
8 stdcall DirectSoundCaptureEnumerateW(ptr ptr) DirectSoundCaptureEnumerateW
9 stub GetDeviceID
10 stub DirectSoundFullDuplexCreate
11 stdcall DirectSoundCreate8(ptr ptr ptr) DirectSoundCreate8
12 stdcall DirectSoundCaptureCreate8(ptr ptr ptr) DirectSoundCaptureCreate8

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,234 @@
/* DirectSound
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Rob Riggs
* Copyright 2000-2001 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
*/
/* Linux does not support better timing than 10ms */
#define DS_TIME_RES 10 /* Resolution of multimedia timer */
#define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
#define DS_HEL_FRAGS 48 /* HEL only: number of waveOut fragments in primary buffer
* (changing this won't help you) */
extern int ds_emuldriver;
extern int ds_hel_margin;
extern int ds_hel_queue;
extern int ds_snd_queue_max;
extern int ds_snd_queue_min;
/*****************************************************************************
* Predeclare the interface implementation structures
*/
typedef struct IDirectSoundImpl IDirectSoundImpl;
typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl;
typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl;
typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl;
typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl;
typedef struct IKsPropertySetImpl IKsPropertySetImpl;
typedef struct PrimaryBufferImpl PrimaryBufferImpl;
/*****************************************************************************
* IDirectSound implementation structure
*/
struct IDirectSoundImpl
{
/* IUnknown fields */
ICOM_VFIELD(IDirectSound8);
DWORD ref;
/* IDirectSoundImpl fields */
PIDSDRIVER driver;
DSDRIVERDESC drvdesc;
DSDRIVERCAPS drvcaps;
DWORD priolevel;
WAVEFORMATEX wfx; /* current main waveformat */
HWAVEOUT hwo;
LPWAVEHDR pwave[DS_HEL_FRAGS];
UINT timerID, pwplay, pwwrite, pwqueue, prebuf, precount;
DWORD fraglen;
PIDSDRIVERBUFFER hwbuf;
LPBYTE buffer;
DWORD writelead, buflen, state, playpos, mixpos;
BOOL need_remix;
int nrofbuffers;
IDirectSoundBufferImpl** buffers;
IDirectSound3DListenerImpl* listener;
RTL_RWLOCK lock;
CRITICAL_SECTION mixlock;
DSVOLUMEPAN volpan;
};
/*****************************************************************************
* IDirectSoundBuffer implementation structure
*/
struct IDirectSoundBufferImpl
{
/* FIXME: document */
/* IUnknown fields */
ICOM_VFIELD(IDirectSoundBuffer8);
DWORD ref;
/* IDirectSoundBufferImpl fields */
IDirectSoundImpl* dsound;
IDirectSoundBufferImpl* parent; /* for duplicates */
IDirectSound3DBufferImpl* ds3db;
IKsPropertySetImpl* iks;
CRITICAL_SECTION lock;
PIDSDRIVERBUFFER hwbuf;
WAVEFORMATEX wfx;
LPBYTE buffer;
DWORD playflags,state,leadin;
DWORD playpos,startpos,writelead,buflen;
DWORD nAvgBytesPerSec;
DWORD freq;
DSVOLUMEPAN volpan, cvolpan;
DSBUFFERDESC dsbd;
/* used for frequency conversion (PerfectPitch) */
ULONG freqAdjust, freqAcc;
/* used for intelligent (well, sort of) prebuffering */
DWORD probably_valid_to, last_playpos;
DWORD primary_mixpos, buf_mixpos;
BOOL need_remix;
/* IDirectSoundNotifyImpl fields */
LPDSBPOSITIONNOTIFY notifies;
int nrofnotifies;
};
HRESULT WINAPI SecondaryBuffer_Create(
IDirectSoundImpl *This,
IDirectSoundBufferImpl **pdsb,
LPDSBUFFERDESC dsbd);
struct PrimaryBufferImpl {
ICOM_VFIELD(IDirectSoundBuffer8);
DWORD ref;
IDirectSoundImpl* dsound;
DSBUFFERDESC dsbd;
};
HRESULT WINAPI PrimaryBuffer_Create(
IDirectSoundImpl *This,
PrimaryBufferImpl **pdsb,
LPDSBUFFERDESC dsbd);
/*****************************************************************************
* IDirectSoundNotify implementation structure
*/
struct IDirectSoundNotifyImpl
{
/* IUnknown fields */
ICOM_VFIELD(IDirectSoundNotify);
DWORD ref;
/* IDirectSoundNotifyImpl fields */
IDirectSoundBufferImpl* dsb;
};
/*****************************************************************************
* IDirectSound3DListener implementation structure
*/
struct IDirectSound3DListenerImpl
{
/* IUnknown fields */
ICOM_VFIELD(IDirectSound3DListener);
DWORD ref;
/* IDirectSound3DListenerImpl fields */
PrimaryBufferImpl* dsb;
DS3DLISTENER ds3dl;
CRITICAL_SECTION lock;
BOOL need_recalc;
};
HRESULT WINAPI IDirectSound3DListenerImpl_Create(
PrimaryBufferImpl *This,
IDirectSound3DListenerImpl **pdsl);
/*****************************************************************************
* IKsPropertySet implementation structure
*/
struct IKsPropertySetImpl
{
/* IUnknown fields */
ICOM_VFIELD(IKsPropertySet);
DWORD ref;
/* IKsPropertySetImpl fields */
IDirectSoundBufferImpl* dsb;
};
HRESULT WINAPI IKsPropertySetImpl_Create(
IDirectSoundBufferImpl *This,
IKsPropertySetImpl **piks);
/*****************************************************************************
* IDirectSound3DBuffer implementation structure
*/
struct IDirectSound3DBufferImpl
{
/* IUnknown fields */
ICOM_VFIELD(IDirectSound3DBuffer);
DWORD ref;
/* IDirectSound3DBufferImpl fields */
IDirectSoundBufferImpl* dsb;
DS3DBUFFER ds3db;
LONG lVolume;
CRITICAL_SECTION lock;
BOOL need_recalc;
};
HRESULT WINAPI IDirectSound3DBufferImpl_Create(
IDirectSoundBufferImpl *This,
IDirectSound3DBufferImpl **pds3db);
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan);
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb);
/* 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);
/* buffer.c */
DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix);
/* mixer.c */
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(void);
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);
#define STATE_STOPPED 0
#define STATE_STARTING 1
#define STATE_PLAYING 2
#define STATE_STOPPING 3
#define DSOUND_FREQSHIFT (14)
extern IDirectSoundImpl* dsound;
struct PrimaryBuffer {
DWORD ref;
PIDSDRIVERBUFFER hwbuf;
DWORD state;
};

1035
dlls/dsound/mixer.c Normal file

File diff suppressed because it is too large Load diff

889
dlls/dsound/primary.c Normal file
View file

@ -0,0 +1,889 @@
/* 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 <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> /* Insomnia - pow() function */
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "ntddk.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);
static HRESULT mmErr(UINT err)
{
switch(err) {
case MMSYSERR_NOERROR:
return DS_OK;
case MMSYSERR_ALLOCATED:
return DSERR_ALLOCATED;
case MMSYSERR_INVALHANDLE:
return DSERR_GENERIC; /* FIXME */
case MMSYSERR_NODRIVER:
return DSERR_NODRIVER;
case MMSYSERR_NOMEM:
return DSERR_OUTOFMEMORY;
case MMSYSERR_INVALPARAM:
return DSERR_INVALIDPARAM;
default:
FIXME("Unknown MMSYS error %d\n",err);
return DSERR_GENERIC;
}
}
void DSOUND_RecalcPrimary(IDirectSoundImpl *This)
{
DWORD sw;
sw = This->wfx.nChannels * (This->wfx.wBitsPerSample / 8);
if (This->hwbuf) {
DWORD fraglen;
/* let fragment size approximate the timer delay */
fraglen = (This->wfx.nSamplesPerSec * DS_TIME_DEL / 1000) * sw;
/* reduce fragment size until an integer number of them fits in the buffer */
/* (FIXME: this may or may not be a good idea) */
while (This->buflen % fraglen) fraglen -= sw;
This->fraglen = fraglen;
TRACE("fraglen=%ld\n", This->fraglen);
}
/* calculate the 10ms write lead */
This->writelead = (This->wfx.nSamplesPerSec / 100) * sw;
}
static HRESULT DSOUND_PrimaryOpen(IDirectSoundImpl *This)
{
HRESULT err = DS_OK;
/* are we using waveOut stuff? */
if (!This->hwbuf) {
LPBYTE newbuf;
DWORD buflen;
HRESULT merr = DS_OK;
/* Start in pause mode, to allow buffers to get filled */
waveOutPause(This->hwo);
if (This->state == STATE_PLAYING) This->state = STATE_STARTING;
else if (This->state == STATE_STOPPING) This->state = STATE_STOPPED;
/* use fragments of 10ms (1/100s) each (which should get us within
* the documented write cursor lead of 10-15ms) */
buflen = ((This->wfx.nAvgBytesPerSec / 100) & ~3) * DS_HEL_FRAGS;
TRACE("desired buflen=%ld, old buffer=%p\n", buflen, This->buffer);
/* reallocate emulated primary buffer */
newbuf = (LPBYTE)HeapReAlloc(GetProcessHeap(),0,This->buffer,buflen);
if (newbuf == NULL) {
ERR("failed to allocate primary buffer\n");
merr = DSERR_OUTOFMEMORY;
/* but the old buffer might still exists and must be re-prepared */
} else {
This->buffer = newbuf;
This->buflen = buflen;
}
if (This->buffer) {
unsigned c;
This->fraglen = This->buflen / DS_HEL_FRAGS;
/* prepare fragment headers */
for (c=0; c<DS_HEL_FRAGS; c++) {
This->pwave[c]->lpData = This->buffer + c*This->fraglen;
This->pwave[c]->dwBufferLength = This->fraglen;
This->pwave[c]->dwUser = (DWORD)This;
This->pwave[c]->dwFlags = 0;
This->pwave[c]->dwLoops = 0;
err = mmErr(waveOutPrepareHeader(This->hwo,This->pwave[c],sizeof(WAVEHDR)));
if (err != DS_OK) {
while (c--)
waveOutUnprepareHeader(This->hwo,This->pwave[c],sizeof(WAVEHDR));
break;
}
}
This->pwplay = 0;
This->pwwrite = 0;
This->pwqueue = 0;
memset(This->buffer, (This->wfx.wBitsPerSample == 16) ? 0 : 128, This->buflen);
TRACE("fraglen=%ld\n", This->fraglen);
DSOUND_WaveQueue(This, (DWORD)-1);
}
if ((err == DS_OK) && (merr != DS_OK))
err = merr;
}
return err;
}
static void DSOUND_PrimaryClose(IDirectSoundImpl *This)
{
/* are we using waveOut stuff? */
if (!This->hwbuf) {
unsigned c;
This->pwqueue = (DWORD)-1; /* resetting queues */
waveOutReset(This->hwo);
for (c=0; c<DS_HEL_FRAGS; c++)
waveOutUnprepareHeader(This->hwo, This->pwave[c], sizeof(WAVEHDR));
This->pwqueue = 0;
}
}
HRESULT DSOUND_PrimaryCreate(IDirectSoundImpl *This)
{
HRESULT err = DS_OK;
This->buflen = This->wfx.nAvgBytesPerSec;
/* FIXME: verify that hardware capabilities (DSCAPS_PRIMARY flags) match */
if (This->driver) {
err = IDsDriver_CreateSoundBuffer(This->driver,&(This->wfx),
DSBCAPS_PRIMARYBUFFER,0,
&(This->buflen),&(This->buffer),
(LPVOID*)&(This->hwbuf));
}
if (err == DS_OK)
err = DSOUND_PrimaryOpen(This);
if (err != DS_OK)
return err;
/* calculate fragment size and write lead */
DSOUND_RecalcPrimary(This);
This->state = STATE_STOPPED;
return DS_OK;
}
HRESULT DSOUND_PrimaryDestroy(IDirectSoundImpl *This)
{
DSOUND_PrimaryClose(This);
if (This->hwbuf) {
IDsDriverBuffer_Release(This->hwbuf);
}
return DS_OK;
}
HRESULT DSOUND_PrimaryPlay(IDirectSoundImpl *This)
{
HRESULT err = DS_OK;
if (This->hwbuf)
err = IDsDriverBuffer_Play(This->hwbuf, 0, 0, DSBPLAY_LOOPING);
else
err = mmErr(waveOutRestart(This->hwo));
return err;
}
HRESULT DSOUND_PrimaryStop(IDirectSoundImpl *This)
{
HRESULT err = DS_OK;
TRACE("\n");
if (This->hwbuf) {
err = IDsDriverBuffer_Stop(This->hwbuf);
if (err == DSERR_BUFFERLOST) {
/* Wine-only: the driver wants us to reopen the device */
/* FIXME: check for errors */
IDsDriverBuffer_Release(This->hwbuf);
waveOutClose(This->hwo);
This->hwo = 0;
err = mmErr(waveOutOpen(&(This->hwo), This->drvdesc.dnDevNode,
&(This->wfx), (DWORD)DSOUND_callback, (DWORD)This,
CALLBACK_FUNCTION | WAVE_DIRECTSOUND));
if (err == DS_OK)
err = IDsDriver_CreateSoundBuffer(This->driver,&(This->wfx),
DSBCAPS_PRIMARYBUFFER,0,
&(This->buflen),&(This->buffer),
(LPVOID)&(This->hwbuf));
}
}
else
err = mmErr(waveOutPause(This->hwo));
return err;
}
HRESULT DSOUND_PrimaryGetPosition(IDirectSoundImpl *This, LPDWORD playpos, LPDWORD writepos)
{
if (This->hwbuf) {
HRESULT err=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
if (err) return err;
}
else {
if (playpos) {
MMTIME mtime;
mtime.wType = TIME_BYTES;
waveOutGetPosition(This->hwo, &mtime, sizeof(mtime));
mtime.u.cb = mtime.u.cb % This->buflen;
*playpos = mtime.u.cb;
}
if (writepos) {
/* the writepos should only be used by apps with WRITEPRIMARY priority,
* in which case our software mixer is disabled anyway */
*writepos = (This->pwplay + ds_hel_margin) * This->fraglen;
while (*writepos >= This->buflen)
*writepos -= This->buflen;
}
}
TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount());
return DS_OK;
}
/*******************************************************************************
* IDirectSoundBuffer
*/
/* This sets this format for the <em>Primary Buffer Only</em> */
/* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */
static HRESULT WINAPI PrimaryBufferImpl_SetFormat(
LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX wfex
) {
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
IDirectSoundBufferImpl** dsb;
HRESULT err = DS_OK;
int i;
if (This->dsound->priolevel == DSSCL_NORMAL) {
TRACE("failed priority check!\n");
return DSERR_PRIOLEVELNEEDED;
}
/* Let's be pedantic! */
if ((wfex == NULL) ||
(wfex->wFormatTag != WAVE_FORMAT_PCM) ||
(wfex->nChannels < 1) || (wfex->nChannels > 2) ||
(wfex->nSamplesPerSec < 1) ||
(wfex->nBlockAlign < 1) || (wfex->nChannels > 4) ||
((wfex->wBitsPerSample != 8) && (wfex->wBitsPerSample != 16))) {
TRACE("failed pedantic check!\n");
return DSERR_INVALIDPARAM;
}
/* **** */
RtlAcquireResourceExclusive(&(dsound->lock), TRUE);
if (dsound->wfx.nSamplesPerSec != wfex->nSamplesPerSec) {
dsb = dsound->buffers;
for (i = 0; i < dsound->nrofbuffers; i++, dsb++) {
/* **** */
EnterCriticalSection(&((*dsb)->lock));
(*dsb)->freqAdjust = ((*dsb)->freq << DSOUND_FREQSHIFT) /
wfex->nSamplesPerSec;
LeaveCriticalSection(&((*dsb)->lock));
/* **** */
}
}
memcpy(&(dsound->wfx), wfex, sizeof(dsound->wfx));
TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
"bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
wfex->nAvgBytesPerSec, wfex->nBlockAlign,
wfex->wBitsPerSample, wfex->cbSize);
dsound->wfx.nAvgBytesPerSec =
dsound->wfx.nSamplesPerSec * dsound->wfx.nBlockAlign;
if (dsound->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) {
/* FIXME: check for errors */
DSOUND_PrimaryClose(dsound);
waveOutClose(dsound->hwo);
dsound->hwo = 0;
err = mmErr(waveOutOpen(&(dsound->hwo), dsound->drvdesc.dnDevNode,
&(dsound->wfx), (DWORD)DSOUND_callback, (DWORD)dsound,
CALLBACK_FUNCTION | WAVE_DIRECTSOUND));
if (err == DS_OK)
DSOUND_PrimaryOpen(dsound);
}
if (dsound->hwbuf) {
err = IDsDriverBuffer_SetFormat(dsound->hwbuf, &(dsound->wfx));
if (err == DSERR_BUFFERLOST) {
/* Wine-only: the driver wants us to recreate the HW buffer */
IDsDriverBuffer_Release(dsound->hwbuf);
err = IDsDriver_CreateSoundBuffer(dsound->driver,&(dsound->wfx),
DSBCAPS_PRIMARYBUFFER,0,
&(dsound->buflen),&(dsound->buffer),
(LPVOID)&(dsound->hwbuf));
if (dsound->state == STATE_PLAYING) dsound->state = STATE_STARTING;
else if (dsound->state == STATE_STOPPING) dsound->state = STATE_STOPPED;
}
/* FIXME: should we set err back to DS_OK in all cases ? */
}
DSOUND_RecalcPrimary(dsound);
RtlReleaseResource(&(dsound->lock));
/* **** */
return err;
}
static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
LPDIRECTSOUNDBUFFER8 iface,LONG vol
) {
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
LONG oldVol;
TRACE("(%p,%ld)\n",This,vol);
/* I'm not sure if we need this for primary buffer */
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME))
return DSERR_CONTROLUNAVAIL;
if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN))
return DSERR_INVALIDPARAM;
/* **** */
EnterCriticalSection(&(dsound->mixlock));
oldVol = dsound->volpan.lVolume;
dsound->volpan.lVolume = vol;
DSOUND_RecalcVolPan(&dsound->volpan);
if (vol != oldVol) {
if (dsound->hwbuf) {
IDsDriverBuffer_SetVolumePan(dsound->hwbuf, &(dsound->volpan));
}
else {
#if 0 /* should we really do this? */
/* the DS volume ranges from 0 (max, 0dB attenuation) to -10000 (min, 100dB attenuation) */
/* the MM volume ranges from 0 to 0xffff in an unspecified logarithmic scale */
WORD cvol = 0xffff + vol*6 + vol/2;
DWORD vol = cvol | ((DWORD)cvol << 16)
waveOutSetVolume(dsound->hwo, vol);
#endif
}
}
LeaveCriticalSection(&(dsound->mixlock));
/* **** */
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
LPDIRECTSOUNDBUFFER8 iface,LPLONG vol
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p)\n",This,vol);
if (vol == NULL)
return DSERR_INVALIDPARAM;
*vol = This->dsound->volpan.lVolume;
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_SetFrequency(
LPDIRECTSOUNDBUFFER8 iface,DWORD freq
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%ld)\n",This,freq);
/* You cannot set the frequency of the primary buffer */
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI PrimaryBufferImpl_Play(
LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags
) {
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p,%08lx,%08lx,%08lx)\n",
This,reserved1,reserved2,flags
);
if (!(flags & DSBPLAY_LOOPING))
return DSERR_INVALIDPARAM;
/* **** */
EnterCriticalSection(&(dsound->mixlock));
if (dsound->state == STATE_STOPPED)
dsound->state = STATE_STARTING;
else if (dsound->state == STATE_STOPPING)
dsound->state = STATE_PLAYING;
LeaveCriticalSection(&(dsound->mixlock));
/* **** */
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
{
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p)\n",This);
/* **** */
EnterCriticalSection(&(dsound->mixlock));
if (dsound->state == STATE_PLAYING)
dsound->state = STATE_STOPPING;
else if (dsound->state == STATE_STARTING)
dsound->state = STATE_STOPPED;
LeaveCriticalSection(&(dsound->mixlock));
/* **** */
return DS_OK;
}
static DWORD WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(PrimaryBufferImpl,iface);
DWORD ref;
TRACE("(%p) ref was %ld, thread is %lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedIncrement(&(This->ref));
if (!ref) {
FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
}
return ref;
}
static DWORD WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(PrimaryBufferImpl,iface);
DWORD ref;
TRACE("(%p) ref was %ld, thread is %lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedDecrement(&(This->ref));
if (ref) return ref;
IDirectSound_Release((LPDIRECTSOUND)This->dsound);
#if 0
if (This->iks) {
HeapFree(GetProcessHeap(), 0, This->iks);
}
#endif
HeapFree(GetProcessHeap(),0,This);
return 0;
}
static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos
) {
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p,%p,%p)\n",This,playpos,writepos);
DSOUND_PrimaryGetPosition(dsound, playpos, writepos);
if (writepos) {
if (dsound->state != STATE_STOPPED)
/* apply the documented 10ms lead to writepos */
*writepos += dsound->writelead;
while (*writepos >= dsound->buflen) *writepos -= dsound->buflen;
}
TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount());
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD status
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p), thread is %lx\n",This,status,GetCurrentThreadId());
if (status == NULL)
return DSERR_INVALIDPARAM;
*status = 0;
if ((This->dsound->state == STATE_STARTING) ||
(This->dsound->state == STATE_PLAYING))
*status |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
TRACE("status=%lx\n", *status);
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_GetFormat(
LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
if (wfsize>sizeof(This->dsound->wfx))
wfsize = sizeof(This->dsound->wfx);
if (lpwf) { /* NULL is valid */
memcpy(lpwf,&(This->dsound->wfx),wfsize);
if (wfwritten)
*wfwritten = wfsize;
} else
if (wfwritten)
*wfwritten = sizeof(This->dsound->wfx);
else
return DSERR_INVALIDPARAM;
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_Lock(
LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
) {
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n",
This,
writecursor,
writebytes,
lplpaudioptr1,
audiobytes1,
lplpaudioptr2,
audiobytes2,
flags,
GetTickCount()
);
if (dsound->priolevel != DSSCL_WRITEPRIMARY)
return DSERR_PRIOLEVELNEEDED;
if (flags & DSBLOCK_FROMWRITECURSOR) {
DWORD writepos;
/* GetCurrentPosition does too much magic to duplicate here */
IDirectSoundBuffer_GetCurrentPosition(iface, NULL, &writepos);
writecursor += writepos;
}
while (writecursor >= dsound->buflen)
writecursor -= dsound->buflen;
if (flags & DSBLOCK_ENTIREBUFFER)
writebytes = dsound->buflen;
if (writebytes > dsound->buflen)
writebytes = dsound->buflen;
assert(audiobytes1!=audiobytes2);
assert(lplpaudioptr1!=lplpaudioptr2);
if (!(dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && dsound->hwbuf) {
IDsDriverBuffer_Lock(dsound->hwbuf,
lplpaudioptr1, audiobytes1,
lplpaudioptr2, audiobytes2,
writecursor, writebytes,
0);
}
else {
if (writecursor+writebytes <= dsound->buflen) {
*(LPBYTE*)lplpaudioptr1 = dsound->buffer+writecursor;
*audiobytes1 = writebytes;
if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = NULL;
if (audiobytes2)
*audiobytes2 = 0;
TRACE("->%ld.0\n",writebytes);
} else {
*(LPBYTE*)lplpaudioptr1 = dsound->buffer+writecursor;
*audiobytes1 = dsound->buflen-writecursor;
if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = dsound->buffer;
if (audiobytes2)
*audiobytes2 = writebytes-(dsound->buflen-writecursor);
TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
}
}
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition(
LPDIRECTSOUNDBUFFER8 iface,DWORD newpos
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%ld)\n",This,newpos);
/* You cannot set the position of the primary buffer */
return DSERR_INVALIDCALL;
}
static HRESULT WINAPI PrimaryBufferImpl_SetPan(
LPDIRECTSOUNDBUFFER8 iface,LONG pan
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%ld)\n",This,pan);
/* You cannot set the pan of the primary buffer */
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI PrimaryBufferImpl_GetPan(
LPDIRECTSOUNDBUFFER8 iface,LPLONG pan
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p)\n",This,pan);
if (pan == NULL)
return DSERR_INVALIDPARAM;
*pan = This->dsound->volpan.lPan;
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_Unlock(
LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
) {
ICOM_THIS(PrimaryBufferImpl,iface);
IDirectSoundImpl* dsound = This->dsound;
TRACE("(%p,%p,%ld,%p,%ld):stub\n", This,p1,x1,p2,x2);
if (dsound->priolevel != DSSCL_WRITEPRIMARY)
return DSERR_PRIOLEVELNEEDED;
if (!(dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && dsound->hwbuf) {
IDsDriverBuffer_Unlock(dsound->hwbuf, p1, x1, p2, x2);
}
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_Restore(
LPDIRECTSOUNDBUFFER8 iface
) {
ICOM_THIS(PrimaryBufferImpl,iface);
FIXME("(%p):stub\n",This);
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p)\n",This,freq);
if (freq == NULL)
return DSERR_INVALIDPARAM;
*freq = This->dsound->wfx.nSamplesPerSec;
TRACE("-> %ld\n", *freq);
return DS_OK;
}
static HRESULT WINAPI PrimaryBufferImpl_SetFX(
LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes
) {
ICOM_THIS(PrimaryBufferImpl,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;
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI PrimaryBufferImpl_AcquireResources(
LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes
) {
ICOM_THIS(PrimaryBufferImpl,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;
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI PrimaryBufferImpl_GetObjectInPath(
LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
) {
ICOM_THIS(PrimaryBufferImpl,iface);
FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
return DSERR_CONTROLUNAVAIL;
}
static HRESULT WINAPI PrimaryBufferImpl_Initialize(
LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND8 dsound,LPDSBUFFERDESC dbsd
) {
ICOM_THIS(PrimaryBufferImpl,iface);
FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd);
DPRINTF("Re-Init!!!\n");
return DSERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p)->(%p)\n",This,caps);
if (caps == NULL)
return DSERR_INVALIDPARAM;
/* I think we should check this value, not set it. See */
/* Inside DirectX, p215. That should apply here, too. */
caps->dwSize = sizeof(*caps);
caps->dwFlags = This->dsbd.dwFlags;
if (This->dsound->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
caps->dwBufferBytes = This->dsound->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 PrimaryBufferImpl_QueryInterface(
LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
) {
ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
ERR("app requested IDirectSoundNotify on primary buffer\n");
/* should we support this? */
*ppobj = NULL;
return E_FAIL;
}
if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
ERR("app requested IDirectSound3DBuffer on primary buffer\n");
*ppobj = NULL;
return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
if (!This->dsound->listener)
IDirectSound3DListenerImpl_Create(This, &This->dsound->listener);
*ppobj = This->dsound->listener;
if (This->dsound->listener) {
IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
return DS_OK;
}
return E_FAIL;
}
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
#if 0
if (!This->iks)
IKsPropertySetImpl_Create(This, &This->iks);
*ppobj = This->iks;
if (*ppobj) {
IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj);
return S_OK;
}
return E_FAIL;
#else
FIXME("app requested IKsPropertySet on primary buffer\n");
*ppobj = NULL;
return E_FAIL;
#endif
}
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
*ppobj = NULL;
return E_NOINTERFACE;
}
static ICOM_VTABLE(IDirectSoundBuffer8) dspbvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
PrimaryBufferImpl_QueryInterface,
PrimaryBufferImpl_AddRef,
PrimaryBufferImpl_Release,
PrimaryBufferImpl_GetCaps,
PrimaryBufferImpl_GetCurrentPosition,
PrimaryBufferImpl_GetFormat,
PrimaryBufferImpl_GetVolume,
PrimaryBufferImpl_GetPan,
PrimaryBufferImpl_GetFrequency,
PrimaryBufferImpl_GetStatus,
PrimaryBufferImpl_Initialize,
PrimaryBufferImpl_Lock,
PrimaryBufferImpl_Play,
PrimaryBufferImpl_SetCurrentPosition,
PrimaryBufferImpl_SetFormat,
PrimaryBufferImpl_SetVolume,
PrimaryBufferImpl_SetPan,
PrimaryBufferImpl_SetFrequency,
PrimaryBufferImpl_Stop,
PrimaryBufferImpl_Unlock,
PrimaryBufferImpl_Restore,
PrimaryBufferImpl_SetFX,
PrimaryBufferImpl_AcquireResources,
PrimaryBufferImpl_GetObjectInPath
};
HRESULT WINAPI PrimaryBuffer_Create(
IDirectSoundImpl *This,
PrimaryBufferImpl **pdsb,
LPDSBUFFERDESC dsbd)
{
PrimaryBufferImpl *dsb;
if (dsbd->lpwfxFormat)
return DSERR_INVALIDPARAM;
dsb = (PrimaryBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
dsb->ref = 1;
dsb->dsound = This;
ICOM_VTBL(dsb) = &dspbvt;
memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd));
TRACE("Created primary buffer at %p\n", dsb);
if (dsbd->dwFlags & DSBCAPS_CTRL3D) {
/* FIXME: IDirectSound3DListener */
}
IDirectSound8_AddRef((LPDIRECTSOUND8)This);
*pdsb = dsb;
return S_OK;
}

139
dlls/dsound/propset.c Normal file
View file

@ -0,0 +1,139 @@
/* 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 <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> /* Insomnia - pow() function */
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "ntddk.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);
/*******************************************************************************
* IKsPropertySet
*/
/* IUnknown methods */
static HRESULT WINAPI IKsPropertySetImpl_QueryInterface(
LPKSPROPERTYSET iface, REFIID riid, LPVOID *ppobj
) {
ICOM_THIS(IKsPropertySetImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
}
static ULONG WINAPI IKsPropertySetImpl_AddRef(LPKSPROPERTYSET iface) {
ICOM_THIS(IKsPropertySetImpl,iface);
ULONG ulReturn;
ulReturn = InterlockedIncrement(&This->ref);
if (ulReturn == 1)
IDirectSoundBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->dsb);
return ulReturn;
}
static ULONG WINAPI IKsPropertySetImpl_Release(LPKSPROPERTYSET iface) {
ICOM_THIS(IKsPropertySetImpl,iface);
ULONG ulReturn;
ulReturn = InterlockedDecrement(&This->ref);
if (ulReturn)
return ulReturn;
IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
return 0;
}
static HRESULT WINAPI IKsPropertySetImpl_Get(LPKSPROPERTYSET iface,
REFGUID guidPropSet, ULONG dwPropID,
LPVOID pInstanceData, ULONG cbInstanceData,
LPVOID pPropData, ULONG cbPropData,
PULONG pcbReturned
) {
ICOM_THIS(IKsPropertySetImpl,iface);
FIXME("(%p,%s,%ld,%p,%ld,%p,%ld,%p), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
return E_PROP_ID_UNSUPPORTED;
}
static HRESULT WINAPI IKsPropertySetImpl_Set(LPKSPROPERTYSET iface,
REFGUID guidPropSet, ULONG dwPropID,
LPVOID pInstanceData, ULONG cbInstanceData,
LPVOID pPropData, ULONG cbPropData
) {
ICOM_THIS(IKsPropertySetImpl,iface);
FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
return E_PROP_ID_UNSUPPORTED;
}
static HRESULT WINAPI IKsPropertySetImpl_QuerySupport(LPKSPROPERTYSET iface,
REFGUID guidPropSet, ULONG dwPropID, PULONG pTypeSupport
) {
ICOM_THIS(IKsPropertySetImpl,iface);
FIXME("(%p,%s,%ld,%p), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
return E_PROP_ID_UNSUPPORTED;
}
static ICOM_VTABLE(IKsPropertySet) iksvt = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IKsPropertySetImpl_QueryInterface,
IKsPropertySetImpl_AddRef,
IKsPropertySetImpl_Release,
IKsPropertySetImpl_Get,
IKsPropertySetImpl_Set,
IKsPropertySetImpl_QuerySupport
};
HRESULT WINAPI IKsPropertySetImpl_Create(
IDirectSoundBufferImpl *This,
IKsPropertySetImpl **piks)
{
IKsPropertySetImpl *iks;
iks = (IKsPropertySetImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*iks));
iks->ref = 0;
iks->dsb = This;
ICOM_VTBL(iks) = &iksvt;
*piks = iks;
return S_OK;
}

568
dlls/dsound/sound3d.c Normal file
View file

@ -0,0 +1,568 @@
/* DirectSound
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Rob Riggs
* Copyright 2000-2001 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
*/
/*
* Most thread locking is complete. There may be a few race
* conditions still lurking.
*
* Tested with a Soundblaster clone, a Gravis UltraSound Classic,
* and a Turtle Beach Tropez+.
*
* TODO:
* Implement SetCooperativeLevel properly (need to address focus issues)
* Implement DirectSound3DBuffers (stubs in place)
* Use hardware 3D support if available
* Add critical section locking inside Release and AddRef methods
* Handle static buffers - put those in hardware, non-static not in hardware
* Hardware DuplicateSoundBuffer
* Proper volume calculation, and setting volume in HEL primary buffer
* Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
*/
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> /* Insomnia - pow() function */
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "ntddk.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);
/*******************************************************************************
* IDirectSound3DBuffer
*/
/* IUnknown methods */
static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
{
ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
}
static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
{
ICOM_THIS(IDirectSound3DBufferImpl,iface);
ULONG ulReturn;
TRACE("(%p) ref was %ld\n", This, This->ref);
ulReturn = InterlockedIncrement(&This->ref);
if (ulReturn == 1)
IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
return ulReturn;
}
static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
{
ICOM_THIS(IDirectSound3DBufferImpl,iface);
ULONG ulReturn;
TRACE("(%p) ref was %ld\n", This, This->ref);
ulReturn = InterlockedDecrement(&This->ref);
if(ulReturn)
return ulReturn;
if (This->dsb) {
BOOL std = (This->dsb->dsbd.dwFlags & DSBCAPS_CTRL3D);
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
if (std)
return 0; /* leave it to IDirectSoundBufferImpl_Release */
}
if (This->dsb->ds3db == This) This->dsb->ds3db = NULL;
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(),0,This);
return 0;
}
/* IDirectSound3DBuffer methods */
static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
LPDIRECTSOUND3DBUFFER iface,
LPDS3DBUFFER lpDs3dBuffer)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
LPDIRECTSOUND3DBUFFER iface,
LPDWORD lpdwInsideConeAngle,
LPDWORD lpdwOutsideConeAngle)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
LPDIRECTSOUND3DBUFFER iface,
LPD3DVECTOR lpvConeOrientation)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
LPDIRECTSOUND3DBUFFER iface,
LPLONG lplConeOutsideVolume)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
LPDIRECTSOUND3DBUFFER iface,
LPD3DVALUE lpfMaxDistance)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
LPDIRECTSOUND3DBUFFER iface,
LPD3DVALUE lpfMinDistance)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
LPDIRECTSOUND3DBUFFER iface,
LPDWORD lpdwMode)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
LPDIRECTSOUND3DBUFFER iface,
LPD3DVECTOR lpvPosition)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
LPDIRECTSOUND3DBUFFER iface,
LPD3DVECTOR lpvVelocity)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
LPDIRECTSOUND3DBUFFER iface,
LPCDS3DBUFFER lpcDs3dBuffer,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
LPDIRECTSOUND3DBUFFER iface,
DWORD dwInsideConeAngle,
DWORD dwOutsideConeAngle,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
LPDIRECTSOUND3DBUFFER iface,
D3DVALUE x, D3DVALUE y, D3DVALUE z,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
LPDIRECTSOUND3DBUFFER iface,
LONG lConeOutsideVolume,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
LPDIRECTSOUND3DBUFFER iface,
D3DVALUE fMaxDistance,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
LPDIRECTSOUND3DBUFFER iface,
D3DVALUE fMinDistance,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
LPDIRECTSOUND3DBUFFER iface,
DWORD dwMode,
DWORD dwApply)
{
ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("mode = %lx\n", dwMode);
This->ds3db.dwMode = dwMode;
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
LPDIRECTSOUND3DBUFFER iface,
D3DVALUE x, D3DVALUE y, D3DVALUE z,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
LPDIRECTSOUND3DBUFFER iface,
D3DVALUE x, D3DVALUE y, D3DVALUE z,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown methods */
IDirectSound3DBufferImpl_QueryInterface,
IDirectSound3DBufferImpl_AddRef,
IDirectSound3DBufferImpl_Release,
/* IDirectSound3DBuffer methods */
IDirectSound3DBufferImpl_GetAllParameters,
IDirectSound3DBufferImpl_GetConeAngles,
IDirectSound3DBufferImpl_GetConeOrientation,
IDirectSound3DBufferImpl_GetConeOutsideVolume,
IDirectSound3DBufferImpl_GetMaxDistance,
IDirectSound3DBufferImpl_GetMinDistance,
IDirectSound3DBufferImpl_GetMode,
IDirectSound3DBufferImpl_GetPosition,
IDirectSound3DBufferImpl_GetVelocity,
IDirectSound3DBufferImpl_SetAllParameters,
IDirectSound3DBufferImpl_SetConeAngles,
IDirectSound3DBufferImpl_SetConeOrientation,
IDirectSound3DBufferImpl_SetConeOutsideVolume,
IDirectSound3DBufferImpl_SetMaxDistance,
IDirectSound3DBufferImpl_SetMinDistance,
IDirectSound3DBufferImpl_SetMode,
IDirectSound3DBufferImpl_SetPosition,
IDirectSound3DBufferImpl_SetVelocity,
};
HRESULT WINAPI IDirectSound3DBufferImpl_Create(
IDirectSoundBufferImpl *This,
IDirectSound3DBufferImpl **pds3db)
{
IDirectSound3DBufferImpl *ds3db;
ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*ds3db));
ds3db->ref = 0;
ds3db->dsb = This;
ICOM_VTBL(ds3db) = &ds3dbvt;
InitializeCriticalSection(&ds3db->lock);
ds3db->ds3db.dwSize = sizeof(DS3DBUFFER);
ds3db->ds3db.vPosition.u1.x = 0.0;
ds3db->ds3db.vPosition.u2.y = 0.0;
ds3db->ds3db.vPosition.u3.z = 0.0;
ds3db->ds3db.vVelocity.u1.x = 0.0;
ds3db->ds3db.vVelocity.u2.y = 0.0;
ds3db->ds3db.vVelocity.u3.z = 0.0;
ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
ds3db->ds3db.vConeOrientation.u1.x = 0.0;
ds3db->ds3db.vConeOrientation.u2.y = 0.0;
ds3db->ds3db.vConeOrientation.u3.z = 0.0;
ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
ds3db->ds3db.dwMode = DS3DMODE_NORMAL;
*pds3db = ds3db;
return S_OK;
}
/*******************************************************************************
* IDirectSound3DListener
*/
/* IUnknown methods */
static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
{
ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
}
static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
{
ICOM_THIS(IDirectSound3DListenerImpl,iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
{
ICOM_THIS(IDirectSound3DListenerImpl,iface);
ULONG ulReturn;
TRACE("(%p) ref was %ld\n", This, This->ref);
ulReturn = InterlockedDecrement(&This->ref);
/* Free all resources */
if( ulReturn == 0 ) {
if(This->dsb)
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(),0,This);
}
return ulReturn;
}
/* IDirectSound3DListener methods */
static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
LPDIRECTSOUND3DLISTENER iface,
LPDS3DLISTENER lpDS3DL)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
LPDIRECTSOUND3DLISTENER iface,
LPD3DVALUE lpfDistanceFactor)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
LPDIRECTSOUND3DLISTENER iface,
LPD3DVALUE lpfDopplerFactor)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
LPDIRECTSOUND3DLISTENER iface,
LPD3DVECTOR lpvOrientFront,
LPD3DVECTOR lpvOrientTop)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
LPDIRECTSOUND3DLISTENER iface,
LPD3DVECTOR lpvPosition)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
LPDIRECTSOUND3DLISTENER iface,
LPD3DVALUE lpfRolloffFactor)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
LPDIRECTSOUND3DLISTENER iface,
LPD3DVECTOR lpvVelocity)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
LPDIRECTSOUND3DLISTENER iface,
LPCDS3DLISTENER lpcDS3DL,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
LPDIRECTSOUND3DLISTENER iface,
D3DVALUE fDistanceFactor,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
LPDIRECTSOUND3DLISTENER iface,
D3DVALUE fDopplerFactor,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
LPDIRECTSOUND3DLISTENER iface,
D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
LPDIRECTSOUND3DLISTENER iface,
D3DVALUE x, D3DVALUE y, D3DVALUE z,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
LPDIRECTSOUND3DLISTENER iface,
D3DVALUE fRolloffFactor,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
LPDIRECTSOUND3DLISTENER iface,
D3DVALUE x, D3DVALUE y, D3DVALUE z,
DWORD dwApply)
{
FIXME("stub\n");
return DS_OK;
}
static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
LPDIRECTSOUND3DLISTENER iface)
{
FIXME("stub\n");
return DS_OK;
}
static ICOM_VTABLE(IDirectSound3DListener) ds3dlvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
/* IUnknown methods */
IDirectSound3DListenerImpl_QueryInterface,
IDirectSound3DListenerImpl_AddRef,
IDirectSound3DListenerImpl_Release,
/* IDirectSound3DListener methods */
IDirectSound3DListenerImpl_GetAllParameter,
IDirectSound3DListenerImpl_GetDistanceFactor,
IDirectSound3DListenerImpl_GetDopplerFactor,
IDirectSound3DListenerImpl_GetOrientation,
IDirectSound3DListenerImpl_GetPosition,
IDirectSound3DListenerImpl_GetRolloffFactor,
IDirectSound3DListenerImpl_GetVelocity,
IDirectSound3DListenerImpl_SetAllParameters,
IDirectSound3DListenerImpl_SetDistanceFactor,
IDirectSound3DListenerImpl_SetDopplerFactor,
IDirectSound3DListenerImpl_SetOrientation,
IDirectSound3DListenerImpl_SetPosition,
IDirectSound3DListenerImpl_SetRolloffFactor,
IDirectSound3DListenerImpl_SetVelocity,
IDirectSound3DListenerImpl_CommitDeferredSettings,
};
HRESULT WINAPI IDirectSound3DListenerImpl_Create(
PrimaryBufferImpl *This,
IDirectSound3DListenerImpl **pdsl)
{
IDirectSound3DListenerImpl *dsl;
dsl = (IDirectSound3DListenerImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsl));
dsl->ref = 1;
ICOM_VTBL(dsl) = &ds3dlvt;
dsl->ds3dl.dwSize = sizeof(DS3DLISTENER);
dsl->ds3dl.vPosition.u1.x = 0.0;
dsl->ds3dl.vPosition.u2.y = 0.0;
dsl->ds3dl.vPosition.u3.z = 0.0;
dsl->ds3dl.vVelocity.u1.x = 0.0;
dsl->ds3dl.vVelocity.u2.y = 0.0;
dsl->ds3dl.vVelocity.u3.z = 0.0;
dsl->ds3dl.vOrientFront.u1.x = 0.0;
dsl->ds3dl.vOrientFront.u2.y = 0.0;
dsl->ds3dl.vOrientFront.u3.z = 1.0;
dsl->ds3dl.vOrientTop.u1.x = 0.0;
dsl->ds3dl.vOrientTop.u2.y = 1.0;
dsl->ds3dl.vOrientTop.u3.z = 0.0;
dsl->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
dsl->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
InitializeCriticalSection(&dsl->lock);
dsl->dsb = This;
IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This);
*pdsl = dsl;
return S_OK;
}

View file

@ -19,7 +19,10 @@
#ifndef __WINE_DSOUND_H
#define __WINE_DSOUND_H
#include "winbase.h" /* for CRITICAL_SECTION */
#ifndef DIRECTSOUND_VERSION
#define DIRECTSOUND_VERSION 0x0800
#endif
#include "mmsystem.h"
#include "d3dtypes.h"
@ -30,14 +33,24 @@ extern "C" {
/*****************************************************************************
* Predeclare the interfaces
*/
DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b);
DEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x08, 0x00, 0xa0, 0xc9, 0x25, 0xcd, 0x16);
DEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1);
DEFINE_GUID(CLSID_DirectSoundFullDuplex,0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d);
DEFINE_GUID(IID_IDirectSound, 0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
typedef struct IDirectSound IDirectSound,*LPDIRECTSOUND;
DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93,0xF395,0x4834,0x9E,0xF6,0x7F,0xA9,0x9D,0xE5,0x09,0x66);
typedef struct IDirectSound8 IDirectSound8,*LPDIRECTSOUND8;
DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60);
typedef struct IDirectSoundBuffer IDirectSoundBuffer,*LPDIRECTSOUNDBUFFER,**LPLPDIRECTSOUNDBUFFER;
DEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825A449,0x7524,0x4D82,0x92,0x0F,0x50,0xE3,0x6A,0xB3,0xAB,0x1E);
typedef struct IDirectSoundBuffer8 IDirectSoundBuffer8,*LPDIRECTSOUNDBUFFER8,**LPLPDIRECTSOUNDBUFFER8;
DEFINE_GUID(IID_IDirectSoundNotify, 0xB0210783,0x89cd,0x11d0,0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16);
typedef struct IDirectSoundNotify IDirectSoundNotify,*LPDIRECTSOUNDNOTIFY;
@ -58,6 +71,14 @@ DEFINE_GUID(DSDEVID_WinePlayback, 0x40316A1D,0x605B,0xD611,0x87,0xC6,0x00,0x80,0
DEFINE_GUID(IID_IKsPropertySet, 0x31EFAC30,0x515C,0x11D0,0xA9,0xAA,0x00,0xAA,0x00,0x61,0xBE,0x93);
typedef struct IKsPropertySet IKsPropertySet,*LPKSPROPERTYSET;
DEFINE_GUID(IID_IDirectSoundCaptureBuffer8,0x00990DF4,0x0DBB,0x4872,0x83,0x3E,0x6D,0x30,0x3E,0x80,0xAE,0xB6);
typedef struct IDirectSoundCaptureBuffer8 IDirectSoundCaptureBuffer8,*LPDIRECTSOUNDCAPTUREBUFFER8;
DEFINE_GUID(DSDEVID_DefaultPlayback, 0xDEF00000,0x9C6D,0x47Ed,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03);
DEFINE_GUID(DSDEVID_DefaultCapture, 0xDEF00001,0x9C6D,0x47Ed,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03);
DEFINE_GUID(DSDEVID_DefaultVoicePlayback,0xDEF00002,0x9C6D,0x47Ed,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03);
DEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xDEF00003,0x9C6D,0x47ED,0xAA,0xF1,0x4D,0xDA,0x8F,0x2B,0x5C,0x03);
#define _FACDS 0x878
#define MAKE_DSHRESULT(code) MAKE_HRESULT(1,_FACDS,code)
@ -174,6 +195,30 @@ typedef struct _DSBCAPS
#define DSSCL_EXCLUSIVE 3
#define DSSCL_WRITEPRIMARY 4
typedef struct _DSEFFECTDESC
{
DWORD dwSize;
DWORD dwFlags;
GUID guidDSFXClass;
DWORD_PTR dwReserved1;
DWORD_PTR dwReserved2;
} DSEFFECTDESC,*LPDSEFFECTDESC;
typedef const DSEFFECTDESC *LPCDSEFFECTDESC;
#define DSFX_LOCHARDWARE 0x00000001
#define DSFX_LOCSOFTWARE 0x00000002
enum
{
DSFXR_PRESENT,
DSFXR_LOCHARDWARE,
DSFXR_LOCSOFTWARE,
DSFXR_UNALLOCATED,
DSFXR_FAILED,
DSFXR_UNKNOWN,
DSFXR_SENDLOOP
};
typedef struct _DSBUFFERDESC
{
DWORD dwSize;
@ -181,14 +226,17 @@ typedef struct _DSBUFFERDESC
DWORD dwBufferBytes;
DWORD dwReserved;
LPWAVEFORMATEX lpwfxFormat;
#if DIRECTSOUND_VERSION >= 0x0700
GUID guid3DAlgorithm;
#endif
} DSBUFFERDESC,*LPDSBUFFERDESC;
typedef const DSBUFFERDESC *LPCDSBUFFERDESC;
typedef struct _DSBPOSITIONNOTIFY
{
DWORD dwOffset;
HANDLE hEventNotify;
DWORD dwOffset;
HANDLE hEventNotify;
} DSBPOSITIONNOTIFY,*LPDSBPOSITIONNOTIFY;
typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY;
#define DSSPEAKER_HEADPHONE 1
@ -202,6 +250,9 @@ typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY;
#define DSSPEAKER_GEOMETRY_WIDE 0x00000014 /* 20 degrees */
#define DSSPEAKER_GEOMETRY_MAX 0x000000B4 /* 180 degrees */
#define DS_CERTIFIED 0x00000000
#define DS_UNCERTIFIED 0x00000001
typedef struct _DSCBUFFERDESC
{
DWORD dwSize;
@ -237,17 +288,22 @@ typedef const GUID *LPCGUID;
typedef LPVOID* LPLPVOID;
typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID,LPWSTR,LPWSTR,LPVOID);
typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID,LPSTR,LPSTR,LPVOID);
typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID,LPCWSTR,LPCWSTR,LPVOID);
typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID,LPCSTR,LPCSTR,LPVOID);
extern HRESULT WINAPI DirectSoundCreate(LPCGUID lpGUID,LPDIRECTSOUND * ppDS,IUnknown *pUnkOuter );
extern HRESULT WINAPI DirectSoundCreate(LPCGUID lpGUID,LPDIRECTSOUND *ppDS,LPUNKNOWN pUnkOuter);
extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA, LPVOID);
extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW, LPVOID);
extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN);
extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpGUID, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter);
extern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA, LPVOID);
extern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW, LPVOID);
extern HRESULT WINAPI DirectSoundCreate8(LPCGUID lpGUID,LPDIRECTSOUND8 *ppDS8,LPUNKNOWN pUnkOuter);
extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpGUID, LPDIRECTSOUNDCAPTURE *ppDSC8, LPUNKNOWN pUnkOuter);
/* FIXME: DirectSoundFullDuplexCreate */
extern HRESULT WINAPI GetDeviceID(LPCGUID lpGuidSrc, LPGUID lpGuidDest);
/*****************************************************************************
* IDirectSound interface
@ -283,6 +339,43 @@ ICOM_DEFINE(IDirectSound,IUnknown)
#define IDirectSound_Initialize(p,a) ICOM_CALL1(Initialize,p,a)
/*****************************************************************************
* IDirectSound8 interface
*/
#define ICOM_INTERFACE IDirectSound8
#define IDirectSound8_METHODS \
ICOM_METHOD3(HRESULT,CreateSoundBuffer, LPDSBUFFERDESC,lpcDSBufferDesc, LPLPDIRECTSOUNDBUFFER8,lplpDirectSoundBuffer, IUnknown*,pUnkOuter) \
ICOM_METHOD1(HRESULT,GetCaps, LPDSCAPS,lpDSCaps) \
ICOM_METHOD2(HRESULT,DuplicateSoundBuffer, LPDIRECTSOUNDBUFFER8,lpDsbOriginal, LPLPDIRECTSOUNDBUFFER8,lplpDsbDuplicate) \
ICOM_METHOD2(HRESULT,SetCooperativeLevel, HWND,hwnd, DWORD,dwLevel) \
ICOM_METHOD (HRESULT,Compact) \
ICOM_METHOD1(HRESULT,GetSpeakerConfig, LPDWORD,lpdwSpeakerConfig) \
ICOM_METHOD1(HRESULT,SetSpeakerConfig, DWORD,dwSpeakerConfig) \
ICOM_METHOD1(HRESULT,Initialize, LPCGUID,lpcGuid) \
ICOM_METHOD1(HRESULT,VerifyCertification, LPDWORD,pdwCertified)
#define IDirectSound8_IMETHODS \
IUnknown_IMETHODS \
IDirectSound8_METHODS
ICOM_DEFINE(IDirectSound8,IUnknown)
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IDirectSound8_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IDirectSound8_AddRef(p) ICOM_CALL (AddRef,p)
#define IDirectSound8_Release(p) ICOM_CALL (Release,p)
/*** IDirectSound methods ***/
#define IDirectSound8_CreateSoundBuffer(p,a,b,c) ICOM_CALL3(CreateSoundBuffer,p,a,b,c)
#define IDirectSound8_GetCaps(p,a) ICOM_CALL1(GetCaps,p,a)
#define IDirectSound8_DuplicateSoundBuffer(p,a,b) ICOM_CALL2(DuplicateSoundBuffer,p,a,b)
#define IDirectSound8_SetCooperativeLevel(p,a,b) ICOM_CALL2(SetCooperativeLevel,p,a,b)
#define IDirectSound8_Compact(p) ICOM_CALL (Compact,p)
#define IDirectSound8_GetSpeakerConfig(p,a) ICOM_CALL1(GetSpeakerConfig,p,a)
#define IDirectSound8_SetSpeakerConfig(p,a) ICOM_CALL1(SetSpeakerConfig,p,a)
#define IDirectSound8_Initialize(p,a) ICOM_CALL1(Initialize,p,a)
/*** IDirectSound8 methods ***/
#define IDirectSound8_VerifyCertification(p,a) ICOM_CALL1(VerifyCertification,p,a)
/*****************************************************************************
* IDirectSoundBuffer interface
*/
@ -337,6 +430,67 @@ ICOM_DEFINE(IDirectSoundBuffer,IUnknown)
#define IDirectSoundBuffer_Restore(p) ICOM_CALL (Restore,p)
/*****************************************************************************
* IDirectSoundBuffer8 interface
*/
#define ICOM_INTERFACE IDirectSoundBuffer8
#define IDirectSoundBuffer8_METHODS \
ICOM_METHOD1(HRESULT,GetCaps, LPDSBCAPS,lpDSBufferCaps) \
ICOM_METHOD2(HRESULT,GetCurrentPosition, LPDWORD,lpdwCurrentPlayCursor, LPDWORD,lpdwCurrentWriteCursor) \
ICOM_METHOD3(HRESULT,GetFormat, LPWAVEFORMATEX,lpwfxFormat, DWORD,dwSizeAllocated, LPDWORD,lpdwSizeWritten) \
ICOM_METHOD1(HRESULT,GetVolume, LPLONG,lplVolume) \
ICOM_METHOD1(HRESULT,GetPan, LPLONG,lplpan) \
ICOM_METHOD1(HRESULT,GetFrequency, LPDWORD,lpdwFrequency) \
ICOM_METHOD1(HRESULT,GetStatus, LPDWORD,lpdwStatus) \
ICOM_METHOD2(HRESULT,Initialize, LPDIRECTSOUND8,lpDirectSound, LPDSBUFFERDESC,lpcDSBufferDesc) \
ICOM_METHOD7(HRESULT,Lock, DWORD,dwWriteCursor, DWORD,dwWriteBytes, LPVOID,lplpvAudioPtr1, LPDWORD,lpdwAudioBytes1, LPVOID,lplpvAudioPtr2, LPDWORD,lpdwAudioBytes2, DWORD,dwFlags) \
ICOM_METHOD3(HRESULT,Play, DWORD,dwReserved1, DWORD,dwReserved2, DWORD,dwFlags) \
ICOM_METHOD1(HRESULT,SetCurrentPosition, DWORD,dwNewPosition) \
ICOM_METHOD1(HRESULT,SetFormat, LPWAVEFORMATEX,lpcfxFormat) \
ICOM_METHOD1(HRESULT,SetVolume, LONG,lVolume) \
ICOM_METHOD1(HRESULT,SetPan, LONG,lPan) \
ICOM_METHOD1(HRESULT,SetFrequency, DWORD,dwFrequency) \
ICOM_METHOD (HRESULT,Stop) \
ICOM_METHOD4(HRESULT,Unlock, LPVOID,lpvAudioPtr1, DWORD,dwAudioBytes1, LPVOID,lpvAudioPtr2, DWORD,dwAudioPtr2) \
ICOM_METHOD (HRESULT,Restore) \
ICOM_METHOD3(HRESULT,SetFX, DWORD,dwEffectsCount, LPDSEFFECTDESC,pDSFXDesc, LPDWORD,pdwResultCodes) \
ICOM_METHOD3(HRESULT,AcquireResources, DWORD,dwFlags, DWORD,dwEffectsCount, LPDWORD,pdwResultCodes) \
ICOM_METHOD4(HRESULT,GetObjectInPath, REFGUID,rguidObject, DWORD,dwIndex, REFGUID,rguidInterface, LPVOID*,ppObject)
#define IDirectSoundBuffer8_IMETHODS \
IUnknown_IMETHODS \
IDirectSoundBuffer8_METHODS
ICOM_DEFINE(IDirectSoundBuffer8,IUnknown)
#undef ICOM_INTERFACE
/*** IUnknown methods ***/
#define IDirectSoundBuffer8_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IDirectSoundBuffer8_AddRef(p) ICOM_CALL (AddRef,p)
#define IDirectSoundBuffer8_Release(p) ICOM_CALL (Release,p)
/*** IDirectSoundBuffer methods ***/
#define IDirectSoundBuffer8_GetCaps(p,a) ICOM_CALL1(GetCaps,p,a)
#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b) ICOM_CALL2(GetCurrentPosition,p,a,b)
#define IDirectSoundBuffer8_GetFormat(p,a,b,c) ICOM_CALL3(GetFormat,p,a,b,c)
#define IDirectSoundBuffer8_GetVolume(p,a) ICOM_CALL1(GetVolume,p,a)
#define IDirectSoundBuffer8_GetPan(p,a) ICOM_CALL1(GetPan,p,a)
#define IDirectSoundBuffer8_GetFrequency(p,a) ICOM_CALL1(GetFrequency,p,a)
#define IDirectSoundBuffer8_GetStatus(p,a) ICOM_CALL1(GetStatus,p,a)
#define IDirectSoundBuffer8_Initialize(p,a,b) ICOM_CALL2(Initialize,p,a,b)
#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g) ICOM_CALL7(Lock,p,a,b,c,d,e,f,g)
#define IDirectSoundBuffer8_Play(p,a,b,c) ICOM_CALL3(Play,p,a,b,c)
#define IDirectSoundBuffer8_SetCurrentPosition(p,a) ICOM_CALL1(SetCurrentPosition,p,a)
#define IDirectSoundBuffer8_SetFormat(p,a) ICOM_CALL1(SetFormat,p,a)
#define IDirectSoundBuffer8_SetVolume(p,a) ICOM_CALL1(SetVolume,p,a)
#define IDirectSoundBuffer8_SetPan(p,a) ICOM_CALL1(SetPan,p,a)
#define IDirectSoundBuffer8_SetFrequency(p,a) ICOM_CALL1(SetFrequency,p,a)
#define IDirectSoundBuffer8_Stop(p) ICOM_CALL (Stop,p)
#define IDirectSoundBuffer8_Unlock(p,a,b,c,d) ICOM_CALL4(Unlock,p,a,b,c,d)
#define IDirectSoundBuffer8_Restore(p) ICOM_CALL (Restore,p)
/*** IDirectSoundBuffer8 methods ***/
#define IDirectSoundBuffer8_SetFX(p,a,b,c) ICOM_CALL3(SetFX,p,a,b,c)
#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) ICOM_CALL3(AcquireResources,p,a,b,c)
#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c) ICOM_CALL3(GetObjectInPath,p,a,b,c)
/*****************************************************************************
* IDirectSoundCapture interface
*/
@ -392,6 +546,34 @@ ICOM_DEFINE(IDirectSoundCaptureBuffer,IUnknown)
#define IDirectSoundCaptureBuffer_Stop(p) ICOM_CALL (Stop,p)
#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) ICOM_CALL4(Unlock,p,a,b,c,d)
/*****************************************************************************
* IDirectSoundCaptureBuffer8 interface
*/
#define ICOM_INTERFACE IDirectSoundCaptureBuffer8
#define IDirectSoundCaptureBuffer8_METHODS \
ICOM_METHOD4(HRESULT,GetObjectInPath, REFGUID,rguidObject, DWORD,dwIndex, REFGUID,rguidInterface, LPVOID*,ppObject) \
ICOM_METHOD2(HRESULT,GetFXStatus, DWORD,dwFXCount, LPDWORD,pdwFXStatus)
#define IDirectSoundCaptureBuffer8_IMETHODS \
IDirectSoundCaptureBuffer_IMETHODS \
IDirectSoundCaptureBuffer8_METHODS
ICOM_DEFINE(IDirectSoundCaptureBuffer8,IDirectSoundCaptureBuffer)
#undef ICOM_INTERFACE
#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
#define IDirectSoundCaptureBuffer8_AddRef(p) ICOM_CALL (AddRef,p)
#define IDirectSoundCaptureBuffer8_Release(p) ICOM_CALL (Release,p)
#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b) ICOM_CALL2(GetCurrentPosition,p,a,b)
#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c) ICOM_CALL3(GetFormat,p,a,b,c)
#define IDirectSoundCaptureBuffer8_GetStatus(p,a) ICOM_CALL1(GetStatus,p,a)
#define IDirectSoundCaptureBuffer8_Initialize(p,a,b) ICOM_CALL2(Initialize,p,a,b)
#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g) ICOM_CALL7(Lock,p,a,b,c,d,e,f,g)
#define IDirectSoundCaptureBuffer8_Start(p,a) ICOM_CALL1(Start,p,a)
#define IDirectSoundCaptureBuffer8_Stop(p) ICOM_CALL (Stop,p)
#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d) ICOM_CALL4(Unlock,p,a,b,c,d)
#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) ICOM_CALL4(GetObjectInPath,p,a,b,c,d)
#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) ICOM_CALL2(GetFXStatus,p,a,b)
/*****************************************************************************
* IDirectSoundNotify interface
*/