3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 * Copyright 2004 Robert Reif
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
28 #include <sys/types.h>
29 #include <sys/fcntl.h>
36 #define NONAMELESSSTRUCT
37 #define NONAMELESSUNION
48 #include "wine/windef16.h"
49 #include "wine/winbase16.h"
50 #include "wine/debug.h"
53 #include "dsound_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
58 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
59 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
60 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
61 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
62 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
64 static const char * dumpCooperativeLevel(DWORD level
)
66 static char unknown
[32];
67 #define LE(x) case x: return #x
72 LE(DSSCL_WRITEPRIMARY
);
75 sprintf(unknown
, "Unknown(%08lx)", level
);
79 static void _dump_DSCAPS(DWORD xmask
) {
84 #define FE(x) { x, #x },
85 FE(DSCAPS_PRIMARYMONO
)
86 FE(DSCAPS_PRIMARYSTEREO
)
87 FE(DSCAPS_PRIMARY8BIT
)
88 FE(DSCAPS_PRIMARY16BIT
)
89 FE(DSCAPS_CONTINUOUSRATE
)
92 FE(DSCAPS_SECONDARYMONO
)
93 FE(DSCAPS_SECONDARYSTEREO
)
94 FE(DSCAPS_SECONDARY8BIT
)
95 FE(DSCAPS_SECONDARY16BIT
)
100 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
101 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
102 DPRINTF("%s ",flags
[i
].name
);
105 static void _dump_DSBCAPS(DWORD xmask
) {
110 #define FE(x) { x, #x },
111 FE(DSBCAPS_PRIMARYBUFFER
)
113 FE(DSBCAPS_LOCHARDWARE
)
114 FE(DSBCAPS_LOCSOFTWARE
)
116 FE(DSBCAPS_CTRLFREQUENCY
)
118 FE(DSBCAPS_CTRLVOLUME
)
119 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
120 FE(DSBCAPS_STICKYFOCUS
)
121 FE(DSBCAPS_GLOBALFOCUS
)
122 FE(DSBCAPS_GETCURRENTPOSITION2
)
123 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
128 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
129 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
130 DPRINTF("%s ",flags
[i
].name
);
133 /*******************************************************************************
134 * IDirectSoundImpl_DirectSound
136 static HRESULT WINAPI
IDirectSoundImpl_QueryInterface(
137 LPDIRECTSOUND8 iface
,
141 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppobj
);
142 FIXME("shouldn't be called directly\n");
143 return E_NOINTERFACE
;
146 static HRESULT WINAPI
DSOUND_QueryInterface(
147 LPDIRECTSOUND8 iface
,
151 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
152 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
155 WARN("invalid parameter\n");
159 if (IsEqualIID(riid
, &IID_IUnknown
)) {
160 if (!This
->pUnknown
) {
161 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
162 if (!This
->pUnknown
) {
163 WARN("IDirectSound_IUnknown_Create() failed\n");
165 return E_NOINTERFACE
;
168 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
169 *ppobj
= This
->pUnknown
;
171 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
173 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
175 WARN("IDirectSound_IDirectSound_Create() failed\n");
177 return E_NOINTERFACE
;
180 IDirectSound_IDirectSound_AddRef(This
->pDS
);
186 WARN("Unknown IID %s\n",debugstr_guid(riid
));
187 return E_NOINTERFACE
;
190 static HRESULT WINAPI
DSOUND_QueryInterface8(
191 LPDIRECTSOUND8 iface
,
195 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
196 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
199 WARN("invalid parameter\n");
203 if (IsEqualIID(riid
, &IID_IUnknown
)) {
204 if (!This
->pUnknown
) {
205 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
206 if (!This
->pUnknown
) {
207 WARN("IDirectSound8_IUnknown_Create() failed\n");
209 return E_NOINTERFACE
;
212 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
213 *ppobj
= This
->pUnknown
;
215 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
217 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
219 WARN("IDirectSound8_IDirectSound_Create() failed\n");
221 return E_NOINTERFACE
;
224 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
227 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
229 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
231 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
233 return E_NOINTERFACE
;
236 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
242 WARN("Unknown IID %s\n",debugstr_guid(riid
));
243 return E_NOINTERFACE
;
246 static ULONG WINAPI
IDirectSoundImpl_AddRef(
247 LPDIRECTSOUND8 iface
)
249 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
250 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
252 return InterlockedIncrement(&This
->ref
);
255 static ULONG WINAPI
IDirectSoundImpl_Release(
256 LPDIRECTSOUND8 iface
)
258 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
260 TRACE("(%p) ref was %ld, thread is %04lx\n",
261 This
, This
->ref
, GetCurrentThreadId());
263 ref
= InterlockedDecrement(&This
->ref
);
268 timeKillEvent(This
->timerID
);
269 timeEndPeriod(DS_TIME_RES
);
270 /* wait for timer to expire */
271 Sleep(DS_TIME_RES
+1);
273 /* The sleep above should have allowed the timer process to expire
274 * but try to grab the lock just in case. Can't hold lock because
275 * IDirectSoundBufferImpl_Destroy also grabs the lock */
276 RtlAcquireResourceShared(&(This
->buffer_list_lock
), TRUE
);
277 RtlReleaseResource(&(This
->buffer_list_lock
));
279 /* It is allowed to release this object even when buffers are playing */
281 WARN("%d secondary buffers not released\n", This
->nrofbuffers
);
282 for( i
=0;i
<This
->nrofbuffers
;i
++)
283 IDirectSoundBufferImpl_Destroy(This
->buffers
[i
]);
287 WARN("primary buffer not released\n");
288 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)This
->primary
);
291 hres
= DSOUND_PrimaryDestroy(This
);
293 WARN("DSOUND_PrimaryDestroy failed\n");
296 IDsDriver_Close(This
->driver
);
298 if (This
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
299 waveOutClose(This
->hwo
);
302 IDsDriver_Release(This
->driver
);
304 RtlDeleteResource(&This
->buffer_list_lock
);
305 This
->mixlock
.DebugInfo
->Spare
[1] = 0;
306 DeleteCriticalSection(&This
->mixlock
);
307 HeapFree(GetProcessHeap(),0,This
);
309 TRACE("(%p) released\n",This
);
315 static HRESULT WINAPI
IDirectSoundImpl_CreateSoundBuffer(
316 LPDIRECTSOUND8 iface
,
317 LPCDSBUFFERDESC dsbd
,
318 LPLPDIRECTSOUNDBUFFER ppdsb
,
321 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
322 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
323 FIXME("shouldn't be called directly\n");
324 return DSERR_GENERIC
;
327 static HRESULT WINAPI
DSOUND_CreateSoundBuffer(
328 LPDIRECTSOUND8 iface
,
329 LPCDSBUFFERDESC dsbd
,
330 LPLPDIRECTSOUNDBUFFER ppdsb
,
334 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
335 HRESULT hres
= DS_OK
;
336 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
339 WARN("invalid parameter: This == NULL\n");
340 return DSERR_INVALIDPARAM
;
343 if (This
->initialized
== FALSE
) {
344 WARN("not initialized\n");
345 return DSERR_UNINITIALIZED
;
349 WARN("invalid parameter: dsbd == NULL\n");
350 return DSERR_INVALIDPARAM
;
353 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
354 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
355 WARN("invalid parameter: dsbd\n");
356 return DSERR_INVALIDPARAM
;
360 WARN("invalid parameter: ppdsb == NULL\n");
361 return DSERR_INVALIDPARAM
;
364 if (TRACE_ON(dsound
)) {
365 TRACE("(structsize=%ld)\n",dsbd
->dwSize
);
366 TRACE("(flags=0x%08lx:\n",dsbd
->dwFlags
);
367 _dump_DSBCAPS(dsbd
->dwFlags
);
369 TRACE("(bufferbytes=%ld)\n",dsbd
->dwBufferBytes
);
370 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
373 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
374 if (dsbd
->lpwfxFormat
!= NULL
) {
375 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
377 return DSERR_INVALIDPARAM
;
381 WARN("Primary Buffer already created\n");
382 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->primary
));
383 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->primary
);
386 hres
= PrimaryBufferImpl_Create(This
, (PrimaryBufferImpl
**)&(This
->primary
), &(This
->dsbd
));
388 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->primary
));
389 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->primary
);
391 WARN("PrimaryBufferImpl_Create failed\n");
394 IDirectSoundBufferImpl
* dsb
;
396 if (dsbd
->lpwfxFormat
== NULL
) {
397 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
398 "secondary buffer\n");
399 return DSERR_INVALIDPARAM
;
402 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
403 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
404 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
405 dsbd
->lpwfxFormat
->nSamplesPerSec
,
406 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
407 dsbd
->lpwfxFormat
->nBlockAlign
,
408 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
410 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
411 WARN("invalid parameter: 3D buffer format must be mono\n");
412 return DSERR_INVALIDPARAM
;
415 hres
= IDirectSoundBufferImpl_Create(This
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
417 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
419 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
420 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
422 WARN("SecondaryBufferImpl_Create failed\n");
424 WARN("IDirectSoundBufferImpl_Create failed\n");
430 static HRESULT WINAPI
IDirectSoundImpl_GetCaps(
431 LPDIRECTSOUND8 iface
,
434 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
435 TRACE("(%p,%p)\n",This
,lpDSCaps
);
438 WARN("invalid parameter: This == NULL\n");
439 return DSERR_INVALIDPARAM
;
442 if (This
->initialized
== FALSE
) {
443 WARN("not initialized\n");
444 return DSERR_UNINITIALIZED
;
447 if (lpDSCaps
== NULL
) {
448 WARN("invalid parameter: lpDSCaps = NULL\n");
449 return DSERR_INVALIDPARAM
;
452 /* check if there is enough room */
453 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
454 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
455 lpDSCaps
->dwSize
, sizeof(*lpDSCaps
));
456 return DSERR_INVALIDPARAM
;
459 lpDSCaps
->dwFlags
= This
->drvcaps
.dwFlags
;
460 if (TRACE_ON(dsound
)) {
461 TRACE("(flags=0x%08lx:\n",lpDSCaps
->dwFlags
);
462 _dump_DSCAPS(lpDSCaps
->dwFlags
);
465 lpDSCaps
->dwMinSecondarySampleRate
= This
->drvcaps
.dwMinSecondarySampleRate
;
466 lpDSCaps
->dwMaxSecondarySampleRate
= This
->drvcaps
.dwMaxSecondarySampleRate
;
467 lpDSCaps
->dwPrimaryBuffers
= This
->drvcaps
.dwPrimaryBuffers
;
468 lpDSCaps
->dwMaxHwMixingAllBuffers
= This
->drvcaps
.dwMaxHwMixingAllBuffers
;
469 lpDSCaps
->dwMaxHwMixingStaticBuffers
= This
->drvcaps
.dwMaxHwMixingStaticBuffers
;
470 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= This
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
471 lpDSCaps
->dwFreeHwMixingAllBuffers
= This
->drvcaps
.dwFreeHwMixingAllBuffers
;
472 lpDSCaps
->dwFreeHwMixingStaticBuffers
= This
->drvcaps
.dwFreeHwMixingStaticBuffers
;
473 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= This
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
474 lpDSCaps
->dwMaxHw3DAllBuffers
= This
->drvcaps
.dwMaxHw3DAllBuffers
;
475 lpDSCaps
->dwMaxHw3DStaticBuffers
= This
->drvcaps
.dwMaxHw3DStaticBuffers
;
476 lpDSCaps
->dwMaxHw3DStreamingBuffers
= This
->drvcaps
.dwMaxHw3DStreamingBuffers
;
477 lpDSCaps
->dwFreeHw3DAllBuffers
= This
->drvcaps
.dwFreeHw3DAllBuffers
;
478 lpDSCaps
->dwFreeHw3DStaticBuffers
= This
->drvcaps
.dwFreeHw3DStaticBuffers
;
479 lpDSCaps
->dwFreeHw3DStreamingBuffers
= This
->drvcaps
.dwFreeHw3DStreamingBuffers
;
480 lpDSCaps
->dwTotalHwMemBytes
= This
->drvcaps
.dwTotalHwMemBytes
;
481 lpDSCaps
->dwFreeHwMemBytes
= This
->drvcaps
.dwFreeHwMemBytes
;
482 lpDSCaps
->dwMaxContigFreeHwMemBytes
= This
->drvcaps
.dwMaxContigFreeHwMemBytes
;
484 /* driver doesn't have these */
485 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
486 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
491 static HRESULT WINAPI
IDirectSoundImpl_DuplicateSoundBuffer(
492 LPDIRECTSOUND8 iface
,
493 LPDIRECTSOUNDBUFFER psb
,
494 LPLPDIRECTSOUNDBUFFER ppdsb
)
496 IDirectSoundBufferImpl
* pdsb
;
497 IDirectSoundBufferImpl
* dsb
;
498 HRESULT hres
= DS_OK
;
500 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
502 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
505 WARN("invalid parameter: This == NULL\n");
506 return DSERR_INVALIDPARAM
;
509 if (This
->initialized
== FALSE
) {
510 WARN("not initialized\n");
511 return DSERR_UNINITIALIZED
;
515 WARN("invalid parameter: psb == NULL\n");
516 return DSERR_INVALIDPARAM
;
520 WARN("invalid parameter: ppdsb == NULL\n");
521 return DSERR_INVALIDPARAM
;
524 /* FIXME: hack to make sure we have a secondary buffer */
525 if ((DWORD
)((SecondaryBufferImpl
*)psb
)->dsb
== (DWORD
)This
) {
526 WARN("trying to duplicate primary buffer\n");
528 return DSERR_INVALIDCALL
;
531 pdsb
= ((SecondaryBufferImpl
*)psb
)->dsb
;
533 dsb
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(*dsb
));
536 WARN("out of memory\n");
538 return DSERR_OUTOFMEMORY
;
541 memcpy(dsb
, pdsb
, sizeof(IDirectSoundBufferImpl
));
544 TRACE("duplicating hardware buffer\n");
546 hres
= IDsDriver_DuplicateSoundBuffer(This
->driver
, pdsb
->hwbuf
, (LPVOID
*)&dsb
->hwbuf
);
548 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
550 /* allocate buffer */
551 if (This
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
552 dsb
->buffer
= HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb
->buffer
)));
553 if (dsb
->buffer
== NULL
) {
554 WARN("out of memory\n");
555 HeapFree(GetProcessHeap(),0,dsb
);
557 return DSERR_OUTOFMEMORY
;
560 dsb
->buffer
->memory
= HeapAlloc(GetProcessHeap(),0,dsb
->buflen
);
561 if (dsb
->buffer
->memory
== NULL
) {
562 WARN("out of memory\n");
563 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
564 HeapFree(GetProcessHeap(),0,dsb
);
566 return DSERR_OUTOFMEMORY
;
568 dsb
->buffer
->ref
= 1;
570 /* FIXME: copy buffer ? */
579 dsb
->state
= STATE_STOPPED
;
584 dsb
->iks
= NULL
; /* FIXME? */
587 /* variable sized struct so calculate size based on format */
588 size
= sizeof(WAVEFORMATEX
) + pdsb
->pwfx
->cbSize
;
590 dsb
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
591 if (dsb
->pwfx
== NULL
) {
592 WARN("out of memory\n");
593 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
594 HeapFree(GetProcessHeap(),0,dsb
);
596 return DSERR_OUTOFMEMORY
;
599 memcpy(dsb
->pwfx
, pdsb
->pwfx
, size
);
601 InitializeCriticalSection(&(dsb
->lock
));
602 dsb
->lock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUNDBUFFER_lock";
604 /* register buffer */
605 hres
= DSOUND_AddBuffer(This
, dsb
);
607 IDirectSoundBuffer8_Release(psb
);
608 dsb
->lock
.DebugInfo
->Spare
[1] = 0;
609 DeleteCriticalSection(&(dsb
->lock
));
610 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
611 HeapFree(GetProcessHeap(),0,dsb
->pwfx
);
612 HeapFree(GetProcessHeap(),0,dsb
);
615 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
617 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
618 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
620 WARN("SecondaryBufferImpl_Create failed\n");
626 static HRESULT WINAPI
IDirectSoundImpl_SetCooperativeLevel(
627 LPDIRECTSOUND8 iface
,
631 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
632 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
634 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
635 FIXME("level=%s not fully supported\n",
636 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
638 This
->priolevel
= level
;
642 static HRESULT WINAPI
IDirectSoundImpl_Compact(
643 LPDIRECTSOUND8 iface
)
645 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
646 TRACE("(%p)\n",This
);
648 if (This
->initialized
== FALSE
) {
649 WARN("not initialized\n");
650 return DSERR_UNINITIALIZED
;
653 if (This
->priolevel
!= DSSCL_PRIORITY
) {
654 WARN("incorrect priority level\n");
655 return DSERR_PRIOLEVELNEEDED
;
661 static HRESULT WINAPI
IDirectSoundImpl_GetSpeakerConfig(
662 LPDIRECTSOUND8 iface
,
663 LPDWORD lpdwSpeakerConfig
)
665 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
666 TRACE("(%p, %p)\n",This
,lpdwSpeakerConfig
);
668 if (This
->initialized
== FALSE
) {
669 WARN("not initialized\n");
670 return DSERR_UNINITIALIZED
;
673 if (lpdwSpeakerConfig
== NULL
) {
674 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
675 return DSERR_INVALIDPARAM
;
678 WARN("not fully functional\n");
679 *lpdwSpeakerConfig
= This
->speaker_config
;
683 static HRESULT WINAPI
IDirectSoundImpl_SetSpeakerConfig(
684 LPDIRECTSOUND8 iface
,
687 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
688 TRACE("(%p,0x%08lx)\n",This
,config
);
690 if (This
->initialized
== FALSE
) {
691 WARN("not initialized\n");
692 return DSERR_UNINITIALIZED
;
695 This
->speaker_config
= config
;
696 WARN("not fully functional\n");
700 static HRESULT WINAPI
IDirectSoundImpl_Initialize(
701 LPDIRECTSOUND8 iface
,
704 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
705 TRACE("(%p,%s)\n",This
,debugstr_guid(lpcGuid
));
707 This
->initialized
= TRUE
;
712 static HRESULT WINAPI
IDirectSoundImpl_VerifyCertification(
713 LPDIRECTSOUND8 iface
,
714 LPDWORD pdwCertified
)
716 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
717 TRACE("(%p, %p)\n",This
,pdwCertified
);
719 if (This
->initialized
== FALSE
) {
720 WARN("not initialized\n");
721 return DSERR_UNINITIALIZED
;
724 if (This
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
725 *pdwCertified
= DS_CERTIFIED
;
727 *pdwCertified
= DS_UNCERTIFIED
;
731 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl
=
733 IDirectSoundImpl_QueryInterface
,
734 IDirectSoundImpl_AddRef
,
735 IDirectSoundImpl_Release
,
736 IDirectSoundImpl_CreateSoundBuffer
,
737 IDirectSoundImpl_GetCaps
,
738 IDirectSoundImpl_DuplicateSoundBuffer
,
739 IDirectSoundImpl_SetCooperativeLevel
,
740 IDirectSoundImpl_Compact
,
741 IDirectSoundImpl_GetSpeakerConfig
,
742 IDirectSoundImpl_SetSpeakerConfig
,
743 IDirectSoundImpl_Initialize
,
744 IDirectSoundImpl_VerifyCertification
747 HRESULT WINAPI
IDirectSoundImpl_Create(
749 LPDIRECTSOUND8
* ppDS
)
752 PIDSDRIVER drv
= NULL
;
753 IDirectSoundImpl
* pDS
;
755 BOOLEAN found
= FALSE
;
756 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID
),ppDS
);
758 /* Enumerate WINMM audio devices and find the one we want */
759 wodn
= waveOutGetNumDevs();
763 return DSERR_NODRIVER
;
766 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID
));
768 for (wod
=0; wod
<wodn
; wod
++) {
769 if (IsEqualGUID( lpcGUID
, &renderer_guids
[wod
])) {
775 if (found
== FALSE
) {
776 WARN("No device found matching given ID!\n");
778 return DSERR_NODRIVER
;
781 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
782 waveOutMessage((HWAVEOUT
)wod
, DRV_QUERYDSOUNDIFACE
, (DWORD
)&drv
, 0);
784 /* Disable the direct sound driver to force emulation if requested. */
785 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
788 /* Allocate memory */
789 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
791 WARN("out of memory\n");
793 return DSERR_OUTOFMEMORY
;
796 pDS
->lpVtbl
= &IDirectSoundImpl_Vtbl
;
800 pDS
->priolevel
= DSSCL_NORMAL
;
806 pDS
->state
= STATE_STOPPED
;
807 pDS
->nrofbuffers
= 0;
810 pDS
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
811 pDS
->initialized
= FALSE
;
813 /* 3D listener initial parameters */
814 pDS
->listener
= NULL
;
815 pDS
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
816 pDS
->ds3dl
.vPosition
.x
= 0.0;
817 pDS
->ds3dl
.vPosition
.y
= 0.0;
818 pDS
->ds3dl
.vPosition
.z
= 0.0;
819 pDS
->ds3dl
.vVelocity
.x
= 0.0;
820 pDS
->ds3dl
.vVelocity
.y
= 0.0;
821 pDS
->ds3dl
.vVelocity
.z
= 0.0;
822 pDS
->ds3dl
.vOrientFront
.x
= 0.0;
823 pDS
->ds3dl
.vOrientFront
.y
= 0.0;
824 pDS
->ds3dl
.vOrientFront
.z
= 1.0;
825 pDS
->ds3dl
.vOrientTop
.x
= 0.0;
826 pDS
->ds3dl
.vOrientTop
.y
= 1.0;
827 pDS
->ds3dl
.vOrientTop
.z
= 0.0;
828 pDS
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
829 pDS
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
830 pDS
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
832 pDS
->prebuf
= ds_snd_queue_max
;
833 pDS
->guid
= *lpcGUID
;
835 /* Get driver description */
837 err
= IDsDriver_GetDriverDesc(drv
,&(pDS
->drvdesc
));
839 WARN("IDsDriver_GetDriverDesc failed\n");
840 HeapFree(GetProcessHeap(),0,pDS
);
845 /* if no DirectSound interface available, use WINMM API instead */
846 pDS
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
| DSDDESC_DOMMSYSTEMSETFORMAT
;
849 pDS
->drvdesc
.dnDevNode
= wod
;
851 /* Set default wave format (may need it for waveOutOpen) */
852 pDS
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
853 if (pDS
->pwfx
== NULL
) {
854 WARN("out of memory\n");
855 HeapFree(GetProcessHeap(),0,pDS
);
857 return DSERR_OUTOFMEMORY
;
860 pDS
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
861 /* We rely on the sound driver to return the actual sound format of
862 * the device if it does not support 22050x8x2 and is given the
863 * WAVE_DIRECTSOUND flag.
865 pDS
->pwfx
->nSamplesPerSec
= 22050;
866 pDS
->pwfx
->wBitsPerSample
= 8;
867 pDS
->pwfx
->nChannels
= 2;
868 pDS
->pwfx
->nBlockAlign
= pDS
->pwfx
->wBitsPerSample
* pDS
->pwfx
->nChannels
/ 8;
869 pDS
->pwfx
->nAvgBytesPerSec
= pDS
->pwfx
->nSamplesPerSec
* pDS
->pwfx
->nBlockAlign
;
870 pDS
->pwfx
->cbSize
= 0;
872 /* If the driver requests being opened through MMSYSTEM
873 * (which is recommended by the DDK), it is supposed to happen
874 * before the DirectSound interface is opened */
875 if (pDS
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
877 DWORD flags
= CALLBACK_FUNCTION
;
879 /* disable direct sound if requested */
880 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
881 flags
|= WAVE_DIRECTSOUND
;
883 err
= mmErr(waveOutOpen(&(pDS
->hwo
),
884 pDS
->drvdesc
.dnDevNode
, pDS
->pwfx
,
885 (DWORD
)DSOUND_callback
, (DWORD
)pDS
,
888 WARN("waveOutOpen failed\n");
889 HeapFree(GetProcessHeap(),0,pDS
);
896 err
= IDsDriver_Open(drv
);
898 WARN("IDsDriver_Open failed\n");
899 HeapFree(GetProcessHeap(),0,pDS
);
904 /* the driver is now open, so it's now allowed to call GetCaps */
905 err
= IDsDriver_GetCaps(drv
,&(pDS
->drvcaps
));
907 WARN("IDsDriver_GetCaps failed\n");
908 HeapFree(GetProcessHeap(),0,pDS
);
914 err
= mmErr(waveOutGetDevCapsA(pDS
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
916 WARN("waveOutGetDevCaps failed\n");
917 HeapFree(GetProcessHeap(),0,pDS
);
921 ZeroMemory(&pDS
->drvcaps
, sizeof(pDS
->drvcaps
));
922 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
923 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
924 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
925 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
926 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
927 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
928 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
930 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
931 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
932 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
933 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
934 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
935 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
936 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
938 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
939 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
940 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
941 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
942 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
943 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
944 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
946 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
947 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
948 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
949 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
950 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
951 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
952 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
955 pDS
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
956 pDS
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
957 pDS
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
958 pDS
->drvcaps
.dwPrimaryBuffers
= 1;
961 InitializeCriticalSection(&(pDS
->mixlock
));
962 pDS
->mixlock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUND_mixlock";
964 RtlInitializeResource(&(pDS
->buffer_list_lock
));
966 *ppDS
= (LPDIRECTSOUND8
)pDS
;
970 /*******************************************************************************
971 * IDirectSound_IUnknown
973 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
978 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
979 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
980 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
983 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
986 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
987 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
988 return InterlockedIncrement(&This
->ref
);
991 static ULONG WINAPI
IDirectSound_IUnknown_Release(
994 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
996 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
997 ulReturn
= InterlockedDecrement(&This
->ref
);
999 IDirectSoundImpl_Release(This
->pds
);
1000 HeapFree(GetProcessHeap(),0,This
);
1001 TRACE("(%p) released\n",This
);
1006 static IUnknownVtbl DirectSound_Unknown_Vtbl
=
1008 IDirectSound_IUnknown_QueryInterface
,
1009 IDirectSound_IUnknown_AddRef
,
1010 IDirectSound_IUnknown_Release
1013 HRESULT WINAPI
IDirectSound_IUnknown_Create(
1017 IDirectSound_IUnknown
* pdsunk
;
1018 TRACE("(%p,%p)\n",pds
,ppunk
);
1020 if (ppunk
== NULL
) {
1021 ERR("invalid parameter: ppunk == NULL\n");
1022 return DSERR_INVALIDPARAM
;
1026 ERR("invalid parameter: pds == NULL\n");
1028 return DSERR_INVALIDPARAM
;
1031 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1032 if (pdsunk
== NULL
) {
1033 WARN("out of memory\n");
1035 return DSERR_OUTOFMEMORY
;
1038 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
1042 IDirectSoundImpl_AddRef(pds
);
1043 *ppunk
= (LPUNKNOWN
)pdsunk
;
1048 /*******************************************************************************
1049 * IDirectSound_IDirectSound
1051 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
1052 LPDIRECTSOUND iface
,
1056 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1057 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1058 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
1061 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
1062 LPDIRECTSOUND iface
)
1064 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1065 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1066 return InterlockedIncrement(&This
->ref
);
1069 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
1070 LPDIRECTSOUND iface
)
1072 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1074 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1075 ulReturn
= InterlockedDecrement(&This
->ref
);
1076 if (ulReturn
== 0) {
1077 IDirectSoundImpl_Release(This
->pds
);
1078 HeapFree(GetProcessHeap(),0,This
);
1079 TRACE("(%p) released\n",This
);
1084 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
1085 LPDIRECTSOUND iface
,
1086 LPCDSBUFFERDESC dsbd
,
1087 LPLPDIRECTSOUNDBUFFER ppdsb
,
1090 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1091 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1092 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,FALSE
);
1095 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
1096 LPDIRECTSOUND iface
,
1099 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1100 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1101 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1104 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
1105 LPDIRECTSOUND iface
,
1106 LPDIRECTSOUNDBUFFER psb
,
1107 LPLPDIRECTSOUNDBUFFER ppdsb
)
1109 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1110 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1111 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1114 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
1115 LPDIRECTSOUND iface
,
1119 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1120 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1121 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1124 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
1125 LPDIRECTSOUND iface
)
1127 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1128 TRACE("(%p)\n", This
);
1129 return IDirectSoundImpl_Compact(This
->pds
);
1132 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
1133 LPDIRECTSOUND iface
,
1134 LPDWORD lpdwSpeakerConfig
)
1136 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1137 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1138 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1141 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
1142 LPDIRECTSOUND iface
,
1145 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1146 TRACE("(%p,0x%08lx)\n",This
,config
);
1147 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1150 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
1151 LPDIRECTSOUND iface
,
1154 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1155 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1156 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1159 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
1161 IDirectSound_IDirectSound_QueryInterface
,
1162 IDirectSound_IDirectSound_AddRef
,
1163 IDirectSound_IDirectSound_Release
,
1164 IDirectSound_IDirectSound_CreateSoundBuffer
,
1165 IDirectSound_IDirectSound_GetCaps
,
1166 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
1167 IDirectSound_IDirectSound_SetCooperativeLevel
,
1168 IDirectSound_IDirectSound_Compact
,
1169 IDirectSound_IDirectSound_GetSpeakerConfig
,
1170 IDirectSound_IDirectSound_SetSpeakerConfig
,
1171 IDirectSound_IDirectSound_Initialize
1174 HRESULT WINAPI
IDirectSound_IDirectSound_Create(
1176 LPDIRECTSOUND
* ppds
)
1178 IDirectSound_IDirectSound
* pdsds
;
1179 TRACE("(%p,%p)\n",pds
,ppds
);
1182 ERR("invalid parameter: ppds == NULL\n");
1183 return DSERR_INVALIDPARAM
;
1187 ERR("invalid parameter: pds == NULL\n");
1189 return DSERR_INVALIDPARAM
;
1192 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1193 if (pdsds
== NULL
) {
1194 WARN("out of memory\n");
1196 return DSERR_OUTOFMEMORY
;
1199 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
1203 IDirectSoundImpl_AddRef(pds
);
1204 *ppds
= (LPDIRECTSOUND
)pdsds
;
1209 /*******************************************************************************
1210 * IDirectSound8_IUnknown
1212 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
1217 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1218 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1219 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1222 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
1225 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1226 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1227 return InterlockedIncrement(&This
->ref
);
1230 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
1233 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1235 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1236 ulReturn
= InterlockedDecrement(&This
->ref
);
1237 if (ulReturn
== 0) {
1238 IDirectSoundImpl_Release(This
->pds
);
1239 HeapFree(GetProcessHeap(),0,This
);
1240 TRACE("(%p) released\n",This
);
1245 static IUnknownVtbl DirectSound8_Unknown_Vtbl
=
1247 IDirectSound8_IUnknown_QueryInterface
,
1248 IDirectSound8_IUnknown_AddRef
,
1249 IDirectSound8_IUnknown_Release
1252 HRESULT WINAPI
IDirectSound8_IUnknown_Create(
1256 IDirectSound8_IUnknown
* pdsunk
;
1257 TRACE("(%p,%p)\n",pds
,ppunk
);
1259 if (ppunk
== NULL
) {
1260 ERR("invalid parameter: ppunk == NULL\n");
1261 return DSERR_INVALIDPARAM
;
1265 ERR("invalid parameter: pds == NULL\n");
1267 return DSERR_INVALIDPARAM
;
1270 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1271 if (pdsunk
== NULL
) {
1272 WARN("out of memory\n");
1274 return DSERR_OUTOFMEMORY
;
1277 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
1281 IDirectSoundImpl_AddRef(pds
);
1282 *ppunk
= (LPUNKNOWN
)pdsunk
;
1287 /*******************************************************************************
1288 * IDirectSound8_IDirectSound
1290 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
1291 LPDIRECTSOUND iface
,
1295 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1296 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1297 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1300 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
1301 LPDIRECTSOUND iface
)
1303 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1304 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1305 return InterlockedIncrement(&This
->ref
);
1308 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
1309 LPDIRECTSOUND iface
)
1311 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1313 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1314 ulReturn
= InterlockedDecrement(&This
->ref
);
1315 if (ulReturn
== 0) {
1316 IDirectSoundImpl_Release(This
->pds
);
1317 HeapFree(GetProcessHeap(),0,This
);
1318 TRACE("(%p) released\n",This
);
1323 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
1324 LPDIRECTSOUND iface
,
1325 LPCDSBUFFERDESC dsbd
,
1326 LPLPDIRECTSOUNDBUFFER ppdsb
,
1329 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1330 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1331 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,TRUE
);
1334 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
1335 LPDIRECTSOUND iface
,
1338 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1339 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1340 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1343 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1344 LPDIRECTSOUND iface
,
1345 LPDIRECTSOUNDBUFFER psb
,
1346 LPLPDIRECTSOUNDBUFFER ppdsb
)
1348 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1349 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1350 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1353 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
1354 LPDIRECTSOUND iface
,
1358 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1359 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1360 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1363 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
1364 LPDIRECTSOUND iface
)
1366 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1367 TRACE("(%p)\n", This
);
1368 return IDirectSoundImpl_Compact(This
->pds
);
1371 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
1372 LPDIRECTSOUND iface
,
1373 LPDWORD lpdwSpeakerConfig
)
1375 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1376 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1377 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1380 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
1381 LPDIRECTSOUND iface
,
1384 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1385 TRACE("(%p,0x%08lx)\n",This
,config
);
1386 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1389 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
1390 LPDIRECTSOUND iface
,
1393 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1394 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1395 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1398 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
1400 IDirectSound8_IDirectSound_QueryInterface
,
1401 IDirectSound8_IDirectSound_AddRef
,
1402 IDirectSound8_IDirectSound_Release
,
1403 IDirectSound8_IDirectSound_CreateSoundBuffer
,
1404 IDirectSound8_IDirectSound_GetCaps
,
1405 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
1406 IDirectSound8_IDirectSound_SetCooperativeLevel
,
1407 IDirectSound8_IDirectSound_Compact
,
1408 IDirectSound8_IDirectSound_GetSpeakerConfig
,
1409 IDirectSound8_IDirectSound_SetSpeakerConfig
,
1410 IDirectSound8_IDirectSound_Initialize
1413 HRESULT WINAPI
IDirectSound8_IDirectSound_Create(
1415 LPDIRECTSOUND
* ppds
)
1417 IDirectSound8_IDirectSound
* pdsds
;
1418 TRACE("(%p,%p)\n",pds
,ppds
);
1421 ERR("invalid parameter: ppds == NULL\n");
1422 return DSERR_INVALIDPARAM
;
1426 ERR("invalid parameter: pds == NULL\n");
1428 return DSERR_INVALIDPARAM
;
1431 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1432 if (pdsds
== NULL
) {
1433 WARN("out of memory\n");
1435 return DSERR_OUTOFMEMORY
;
1438 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
1442 IDirectSoundImpl_AddRef(pds
);
1443 *ppds
= (LPDIRECTSOUND
)pdsds
;
1448 /*******************************************************************************
1449 * IDirectSound8_IDirectSound8
1451 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
1452 LPDIRECTSOUND8 iface
,
1456 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1457 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1458 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1461 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
1462 LPDIRECTSOUND8 iface
)
1464 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1465 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1466 return InterlockedIncrement(&This
->ref
);
1469 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
1470 LPDIRECTSOUND8 iface
)
1472 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1474 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1475 ulReturn
= InterlockedDecrement(&This
->ref
);
1476 if (ulReturn
== 0) {
1477 IDirectSoundImpl_Release(This
->pds
);
1478 HeapFree(GetProcessHeap(),0,This
);
1479 TRACE("(%p) released\n",This
);
1484 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
1485 LPDIRECTSOUND8 iface
,
1486 LPCDSBUFFERDESC dsbd
,
1487 LPLPDIRECTSOUNDBUFFER ppdsb
,
1490 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1491 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1492 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,TRUE
);
1495 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
1496 LPDIRECTSOUND8 iface
,
1499 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1500 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1501 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1504 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1505 LPDIRECTSOUND8 iface
,
1506 LPDIRECTSOUNDBUFFER psb
,
1507 LPLPDIRECTSOUNDBUFFER ppdsb
)
1509 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1510 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1511 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1514 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
1515 LPDIRECTSOUND8 iface
,
1519 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1520 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1521 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1524 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
1525 LPDIRECTSOUND8 iface
)
1527 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1528 TRACE("(%p)\n", This
);
1529 return IDirectSoundImpl_Compact(This
->pds
);
1532 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
1533 LPDIRECTSOUND8 iface
,
1534 LPDWORD lpdwSpeakerConfig
)
1536 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1537 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1538 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1541 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
1542 LPDIRECTSOUND8 iface
,
1545 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1546 TRACE("(%p,0x%08lx)\n",This
,config
);
1547 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1550 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
1551 LPDIRECTSOUND8 iface
,
1554 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1555 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1556 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1559 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
1560 LPDIRECTSOUND8 iface
,
1561 LPDWORD pdwCertified
)
1563 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1564 TRACE("(%p, %p)\n", This
, pdwCertified
);
1565 return IDirectSoundImpl_VerifyCertification(This
->pds
,pdwCertified
);
1568 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
1570 IDirectSound8_IDirectSound8_QueryInterface
,
1571 IDirectSound8_IDirectSound8_AddRef
,
1572 IDirectSound8_IDirectSound8_Release
,
1573 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
1574 IDirectSound8_IDirectSound8_GetCaps
,
1575 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
1576 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
1577 IDirectSound8_IDirectSound8_Compact
,
1578 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
1579 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
1580 IDirectSound8_IDirectSound8_Initialize
,
1581 IDirectSound8_IDirectSound8_VerifyCertification
1584 HRESULT WINAPI
IDirectSound8_IDirectSound8_Create(
1586 LPDIRECTSOUND8
* ppds
)
1588 IDirectSound8_IDirectSound8
* pdsds
;
1589 TRACE("(%p,%p)\n",pds
,ppds
);
1592 ERR("invalid parameter: ppds == NULL\n");
1593 return DSERR_INVALIDPARAM
;
1597 ERR("invalid parameter: pds == NULL\n");
1599 return DSERR_INVALIDPARAM
;
1602 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1603 if (pdsds
== NULL
) {
1604 WARN("out of memory\n");
1606 return DSERR_OUTOFMEMORY
;
1609 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
1613 IDirectSoundImpl_AddRef(pds
);
1614 *ppds
= (LPDIRECTSOUND8
)pdsds
;
1619 HRESULT WINAPI
DSOUND_Create(
1621 LPDIRECTSOUND
*ppDS
,
1622 IUnknown
*pUnkOuter
)
1627 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1629 if (pUnkOuter
!= NULL
) {
1630 WARN("invalid parameter: pUnkOuter != NULL\n");
1631 return DSERR_INVALIDPARAM
;
1635 WARN("invalid parameter: ppDS == NULL\n");
1636 return DSERR_INVALIDPARAM
;
1639 /* Get dsound configuration */
1640 setup_dsound_options();
1642 /* Default device? */
1643 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1644 lpcGUID
= &DSDEVID_DefaultPlayback
;
1646 if (GetDeviceID(lpcGUID
, &devGuid
) != DS_OK
) {
1647 WARN("invalid parameter: lpcGUID\n");
1649 return DSERR_INVALIDPARAM
;
1653 if (IsEqualGUID(&devGuid
, &dsound
->guid
)) {
1654 hr
= IDirectSound_IDirectSound_Create((LPDIRECTSOUND8
)dsound
, ppDS
);
1656 IDirectSound_IDirectSound_AddRef(*ppDS
);
1658 WARN("IDirectSound_IDirectSound_Create failed\n");
1660 ERR("different dsound already opened (only support one sound card at a time now)\n");
1662 hr
= DSERR_ALLOCATED
;
1666 hr
= IDirectSoundImpl_Create(&devGuid
, &pDS
);
1668 hr
= DSOUND_PrimaryCreate((IDirectSoundImpl
*)pDS
);
1670 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1672 IDirectSound_IDirectSound_AddRef(*ppDS
);
1674 dsound
= (IDirectSoundImpl
*)pDS
;
1675 timeBeginPeriod(DS_TIME_RES
);
1676 dsound
->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1677 (DWORD
)dsound
, TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1679 WARN("IDirectSound_IDirectSound_Create failed\n");
1680 IDirectSound8_Release(pDS
);
1683 WARN("DSOUND_PrimaryCreate failed\n");
1684 IDirectSound8_Release(pDS
);
1687 WARN("IDirectSoundImpl_Create failed\n");
1693 /*******************************************************************************
1694 * DirectSoundCreate (DSOUND.1)
1696 * Creates and initializes a DirectSound interface.
1699 * lpcGUID [I] Address of the GUID that identifies the sound device.
1700 * ppDS [O] Address of a variable to receive the interface pointer.
1701 * pUnkOuter [I] Must be NULL.
1705 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1706 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1708 HRESULT WINAPI
DirectSoundCreate(
1710 LPDIRECTSOUND
*ppDS
,
1711 IUnknown
*pUnkOuter
)
1715 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1717 hr
= DSOUND_Create(lpcGUID
, ppDS
, pUnkOuter
);
1719 IDirectSoundImpl_Initialize((LPDIRECTSOUND8
)dsound
, lpcGUID
);
1724 HRESULT WINAPI
DSOUND_Create8(
1726 LPDIRECTSOUND8
*ppDS
,
1727 IUnknown
*pUnkOuter
)
1732 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1734 if (pUnkOuter
!= NULL
) {
1735 WARN("invalid parameter: pUnkOuter != NULL\n");
1736 return DSERR_INVALIDPARAM
;
1740 WARN("invalid parameter: ppDS == NULL\n");
1741 return DSERR_INVALIDPARAM
;
1744 /* Get dsound configuration */
1745 setup_dsound_options();
1747 /* Default device? */
1748 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1749 lpcGUID
= &DSDEVID_DefaultPlayback
;
1751 if (GetDeviceID(lpcGUID
, &devGuid
) != DS_OK
) {
1752 WARN("invalid parameter: lpcGUID\n");
1754 return DSERR_INVALIDPARAM
;
1758 if (IsEqualGUID(&devGuid
, &dsound
->guid
)) {
1759 hr
= IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8
)dsound
, ppDS
);
1761 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1763 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1765 ERR("different dsound already opened (only support one sound card at a time now)\n");
1767 hr
= DSERR_ALLOCATED
;
1771 hr
= IDirectSoundImpl_Create(&devGuid
, &pDS
);
1773 hr
= DSOUND_PrimaryCreate((IDirectSoundImpl
*)pDS
);
1775 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1777 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1779 dsound
= (IDirectSoundImpl
*)pDS
;
1780 timeBeginPeriod(DS_TIME_RES
);
1781 dsound
->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1782 (DWORD
)dsound
, TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1784 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1785 IDirectSound8_Release(pDS
);
1788 WARN("DSOUND_PrimaryCreate failed\n");
1789 IDirectSound8_Release(pDS
);
1792 WARN("IDirectSoundImpl_Create failed\n");
1798 /*******************************************************************************
1799 * DirectSoundCreate8 (DSOUND.11)
1801 * Creates and initializes a DirectSound8 interface.
1804 * lpcGUID [I] Address of the GUID that identifies the sound device.
1805 * ppDS [O] Address of a variable to receive the interface pointer.
1806 * pUnkOuter [I] Must be NULL.
1810 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1811 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1813 HRESULT WINAPI
DirectSoundCreate8(
1815 LPDIRECTSOUND8
*ppDS
,
1816 IUnknown
*pUnkOuter
)
1820 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1822 hr
= DSOUND_Create8(lpcGUID
, ppDS
, pUnkOuter
);
1824 IDirectSoundImpl_Initialize((LPDIRECTSOUND8
)dsound
, lpcGUID
);
1830 * Add secondary buffer to buffer list.
1831 * Gets exclusive access to buffer for writing.
1833 HRESULT
DSOUND_AddBuffer(
1834 IDirectSoundImpl
* pDS
,
1835 IDirectSoundBufferImpl
* pDSB
)
1837 IDirectSoundBufferImpl
**newbuffers
;
1840 TRACE("(%p, %p)\n", pDS
, pDSB
);
1842 RtlAcquireResourceExclusive(&(pDS
->buffer_list_lock
), TRUE
);
1845 newbuffers
= HeapReAlloc(GetProcessHeap(),0,pDS
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(pDS
->nrofbuffers
+1));
1847 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(pDS
->nrofbuffers
+1));
1850 pDS
->buffers
= newbuffers
;
1851 pDS
->buffers
[pDS
->nrofbuffers
] = pDSB
;
1853 TRACE("buffer count is now %d\n", pDS
->nrofbuffers
);
1855 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS
->nrofbuffers
);
1856 hr
= DSERR_OUTOFMEMORY
;
1859 RtlReleaseResource(&(pDS
->buffer_list_lock
));
1865 * Remove secondary buffer from buffer list.
1866 * Gets exclusive access to buffer for writing.
1868 HRESULT
DSOUND_RemoveBuffer(
1869 IDirectSoundImpl
* pDS
,
1870 IDirectSoundBufferImpl
* pDSB
)
1875 TRACE("(%p, %p)\n", pDS
, pDSB
);
1877 RtlAcquireResourceExclusive(&(pDS
->buffer_list_lock
), TRUE
);
1879 for (i
= 0; i
< pDS
->nrofbuffers
; i
++)
1880 if (pDS
->buffers
[i
] == pDSB
)
1883 if (i
< pDS
->nrofbuffers
) {
1884 /* Put the last buffer of the list in the (now empty) position */
1885 pDS
->buffers
[i
] = pDS
->buffers
[pDS
->nrofbuffers
- 1];
1887 pDS
->buffers
= HeapReAlloc(GetProcessHeap(),0,pDS
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*pDS
->nrofbuffers
);
1888 TRACE("buffer count is now %d\n", pDS
->nrofbuffers
);
1891 if (pDS
->nrofbuffers
== 0) {
1892 HeapFree(GetProcessHeap(),0,pDS
->buffers
);
1893 pDS
->buffers
= NULL
;
1896 RtlReleaseResource(&(pDS
->buffer_list_lock
));