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
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
34 #include "wine/debug.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
41 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
42 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
43 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
44 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
45 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
47 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
);
48 static ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
);
50 static const char * dumpCooperativeLevel(DWORD level
)
52 static char unknown
[32];
53 #define LE(x) case x: return #x
58 LE(DSSCL_WRITEPRIMARY
);
61 sprintf(unknown
, "Unknown(%08lx)", level
);
65 static void _dump_DSCAPS(DWORD xmask
) {
70 #define FE(x) { x, #x },
71 FE(DSCAPS_PRIMARYMONO
)
72 FE(DSCAPS_PRIMARYSTEREO
)
73 FE(DSCAPS_PRIMARY8BIT
)
74 FE(DSCAPS_PRIMARY16BIT
)
75 FE(DSCAPS_CONTINUOUSRATE
)
78 FE(DSCAPS_SECONDARYMONO
)
79 FE(DSCAPS_SECONDARYSTEREO
)
80 FE(DSCAPS_SECONDARY8BIT
)
81 FE(DSCAPS_SECONDARY16BIT
)
86 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
87 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
88 DPRINTF("%s ",flags
[i
].name
);
91 static void _dump_DSBCAPS(DWORD xmask
) {
96 #define FE(x) { x, #x },
97 FE(DSBCAPS_PRIMARYBUFFER
)
99 FE(DSBCAPS_LOCHARDWARE
)
100 FE(DSBCAPS_LOCSOFTWARE
)
102 FE(DSBCAPS_CTRLFREQUENCY
)
104 FE(DSBCAPS_CTRLVOLUME
)
105 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
106 FE(DSBCAPS_STICKYFOCUS
)
107 FE(DSBCAPS_GLOBALFOCUS
)
108 FE(DSBCAPS_GETCURRENTPOSITION2
)
109 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
114 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
115 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
116 DPRINTF("%s ",flags
[i
].name
);
119 /*******************************************************************************
120 * IDirectSoundImpl_DirectSound
122 static HRESULT WINAPI
IDirectSoundImpl_QueryInterface(
123 LPDIRECTSOUND8 iface
,
127 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppobj
);
128 FIXME("shouldn't be called directly\n");
129 return E_NOINTERFACE
;
132 static HRESULT WINAPI
DSOUND_QueryInterface(
133 LPDIRECTSOUND8 iface
,
137 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
138 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
141 WARN("invalid parameter\n");
145 if (IsEqualIID(riid
, &IID_IUnknown
)) {
146 if (!This
->pUnknown
) {
147 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
148 if (!This
->pUnknown
) {
149 WARN("IDirectSound_IUnknown_Create() failed\n");
151 return E_NOINTERFACE
;
154 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
155 *ppobj
= This
->pUnknown
;
157 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
159 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
161 WARN("IDirectSound_IDirectSound_Create() failed\n");
163 return E_NOINTERFACE
;
166 IDirectSound_IDirectSound_AddRef(This
->pDS
);
172 WARN("Unknown IID %s\n",debugstr_guid(riid
));
173 return E_NOINTERFACE
;
176 static HRESULT WINAPI
DSOUND_QueryInterface8(
177 LPDIRECTSOUND8 iface
,
181 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
182 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
185 WARN("invalid parameter\n");
189 if (IsEqualIID(riid
, &IID_IUnknown
)) {
190 if (!This
->pUnknown
) {
191 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
192 if (!This
->pUnknown
) {
193 WARN("IDirectSound8_IUnknown_Create() failed\n");
195 return E_NOINTERFACE
;
198 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
199 *ppobj
= This
->pUnknown
;
201 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
203 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
205 WARN("IDirectSound8_IDirectSound_Create() failed\n");
207 return E_NOINTERFACE
;
210 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
213 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
215 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
217 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
219 return E_NOINTERFACE
;
222 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
228 WARN("Unknown IID %s\n",debugstr_guid(riid
));
229 return E_NOINTERFACE
;
232 static ULONG WINAPI
IDirectSoundImpl_AddRef(
233 LPDIRECTSOUND8 iface
)
235 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
236 ULONG ref
= InterlockedIncrement(&(This
->ref
));
237 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
241 static ULONG WINAPI
IDirectSoundImpl_Release(
242 LPDIRECTSOUND8 iface
)
244 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
245 ULONG ref
= InterlockedDecrement(&(This
->ref
));
246 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
250 DirectSoundDevice_Release(This
->device
);
252 HeapFree(GetProcessHeap(),0,This
);
253 TRACE("(%p) released\n", This
);
258 static HRESULT WINAPI
IDirectSoundImpl_CreateSoundBuffer(
259 LPDIRECTSOUND8 iface
,
260 LPCDSBUFFERDESC dsbd
,
261 LPLPDIRECTSOUNDBUFFER ppdsb
,
264 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
265 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
266 FIXME("shouldn't be called directly\n");
267 return DSERR_GENERIC
;
270 static HRESULT WINAPI
DSOUND_CreateSoundBuffer(
271 LPDIRECTSOUND8 iface
,
272 LPCDSBUFFERDESC dsbd
,
273 LPLPDIRECTSOUNDBUFFER ppdsb
,
277 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
278 HRESULT hres
= DS_OK
;
279 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
282 WARN("invalid parameter: This == NULL\n");
283 return DSERR_INVALIDPARAM
;
286 if (This
->device
== NULL
) {
287 WARN("not initialized\n");
288 return DSERR_UNINITIALIZED
;
292 WARN("invalid parameter: dsbd == NULL\n");
293 return DSERR_INVALIDPARAM
;
296 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
297 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
298 WARN("invalid parameter: dsbd\n");
299 return DSERR_INVALIDPARAM
;
303 WARN("invalid parameter: ppdsb == NULL\n");
304 return DSERR_INVALIDPARAM
;
307 if (TRACE_ON(dsound
)) {
308 TRACE("(structsize=%ld)\n",dsbd
->dwSize
);
309 TRACE("(flags=0x%08lx:\n",dsbd
->dwFlags
);
310 _dump_DSBCAPS(dsbd
->dwFlags
);
312 TRACE("(bufferbytes=%ld)\n",dsbd
->dwBufferBytes
);
313 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
316 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
317 if (dsbd
->lpwfxFormat
!= NULL
) {
318 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
320 return DSERR_INVALIDPARAM
;
323 if (This
->device
->primary
) {
324 WARN("Primary Buffer already created\n");
325 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->device
->primary
));
326 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->device
->primary
);
328 This
->device
->dsbd
= *dsbd
;
329 hres
= PrimaryBufferImpl_Create(This
, (PrimaryBufferImpl
**)&(This
->device
->primary
), &(This
->device
->dsbd
));
330 if (This
->device
->primary
) {
331 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->device
->primary
));
332 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->device
->primary
);
334 WARN("PrimaryBufferImpl_Create failed\n");
337 IDirectSoundBufferImpl
* dsb
;
339 if (dsbd
->lpwfxFormat
== NULL
) {
340 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
341 "secondary buffer\n");
342 return DSERR_INVALIDPARAM
;
345 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
346 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
347 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
348 dsbd
->lpwfxFormat
->nSamplesPerSec
,
349 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
350 dsbd
->lpwfxFormat
->nBlockAlign
,
351 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
353 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
354 WARN("invalid parameter: 3D buffer format must be mono\n");
355 return DSERR_INVALIDPARAM
;
358 hres
= IDirectSoundBufferImpl_Create(This
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
360 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
362 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
363 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
365 WARN("SecondaryBufferImpl_Create failed\n");
367 WARN("IDirectSoundBufferImpl_Create failed\n");
373 static HRESULT WINAPI
IDirectSoundImpl_GetCaps(
374 LPDIRECTSOUND8 iface
,
377 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
378 DirectSoundDevice
*device
;
379 TRACE("(%p,%p)\n",This
,lpDSCaps
);
382 WARN("invalid parameter: This == NULL\n");
383 return DSERR_INVALIDPARAM
;
386 device
= This
->device
;
388 if (device
== NULL
) {
389 WARN("not initialized\n");
390 return DSERR_UNINITIALIZED
;
393 if (lpDSCaps
== NULL
) {
394 WARN("invalid parameter: lpDSCaps = NULL\n");
395 return DSERR_INVALIDPARAM
;
398 /* check if there is enough room */
399 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
400 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
401 lpDSCaps
->dwSize
, sizeof(*lpDSCaps
));
402 return DSERR_INVALIDPARAM
;
405 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
406 if (TRACE_ON(dsound
)) {
407 TRACE("(flags=0x%08lx:\n",lpDSCaps
->dwFlags
);
408 _dump_DSCAPS(lpDSCaps
->dwFlags
);
411 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
412 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
413 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
414 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
415 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
416 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
417 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
418 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
419 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
420 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
421 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
422 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
423 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
424 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
425 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
426 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
427 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
428 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
430 /* driver doesn't have these */
431 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
432 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
437 static HRESULT WINAPI
IDirectSoundImpl_DuplicateSoundBuffer(
438 LPDIRECTSOUND8 iface
,
439 LPDIRECTSOUNDBUFFER psb
,
440 LPLPDIRECTSOUNDBUFFER ppdsb
)
442 IDirectSoundBufferImpl
* pdsb
;
443 IDirectSoundBufferImpl
* dsb
;
444 HRESULT hres
= DS_OK
;
446 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
448 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
451 WARN("invalid parameter: This == NULL\n");
452 return DSERR_INVALIDPARAM
;
455 if (This
->device
== NULL
) {
456 WARN("not initialized\n");
457 return DSERR_UNINITIALIZED
;
461 WARN("invalid parameter: psb == NULL\n");
462 return DSERR_INVALIDPARAM
;
466 WARN("invalid parameter: ppdsb == NULL\n");
467 return DSERR_INVALIDPARAM
;
470 /* FIXME: hack to make sure we have a secondary buffer */
471 if ((DWORD
)((SecondaryBufferImpl
*)psb
)->dsb
== (DWORD
)This
) {
472 WARN("trying to duplicate primary buffer\n");
474 return DSERR_INVALIDCALL
;
477 pdsb
= ((SecondaryBufferImpl
*)psb
)->dsb
;
479 dsb
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(*dsb
));
482 WARN("out of memory\n");
484 return DSERR_OUTOFMEMORY
;
487 CopyMemory(dsb
, pdsb
, sizeof(IDirectSoundBufferImpl
));
490 TRACE("duplicating hardware buffer\n");
492 hres
= IDsDriver_DuplicateSoundBuffer(This
->device
->driver
, pdsb
->hwbuf
, (LPVOID
*)&dsb
->hwbuf
);
494 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
496 /* allocate buffer */
497 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
498 dsb
->buffer
= HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb
->buffer
)));
499 if (dsb
->buffer
== NULL
) {
500 WARN("out of memory\n");
501 HeapFree(GetProcessHeap(),0,dsb
);
503 return DSERR_OUTOFMEMORY
;
506 dsb
->buffer
->memory
= HeapAlloc(GetProcessHeap(),0,dsb
->buflen
);
507 if (dsb
->buffer
->memory
== NULL
) {
508 WARN("out of memory\n");
509 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
510 HeapFree(GetProcessHeap(),0,dsb
);
512 return DSERR_OUTOFMEMORY
;
514 dsb
->buffer
->ref
= 1;
516 /* FIXME: copy buffer ? */
525 dsb
->state
= STATE_STOPPED
;
530 dsb
->iks
= NULL
; /* FIXME? */
533 /* variable sized struct so calculate size based on format */
534 size
= sizeof(WAVEFORMATEX
) + pdsb
->pwfx
->cbSize
;
536 dsb
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
537 if (dsb
->pwfx
== NULL
) {
538 WARN("out of memory\n");
539 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
540 HeapFree(GetProcessHeap(),0,dsb
);
542 return DSERR_OUTOFMEMORY
;
545 CopyMemory(dsb
->pwfx
, pdsb
->pwfx
, size
);
547 InitializeCriticalSection(&(dsb
->lock
));
548 dsb
->lock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUNDBUFFER_lock";
550 /* register buffer */
551 hres
= DSOUND_AddBuffer(This
, dsb
);
553 IDirectSoundBuffer8_Release(psb
);
554 dsb
->lock
.DebugInfo
->Spare
[1] = 0;
555 DeleteCriticalSection(&(dsb
->lock
));
556 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
557 HeapFree(GetProcessHeap(),0,dsb
->pwfx
);
558 HeapFree(GetProcessHeap(),0,dsb
);
561 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
563 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
564 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
566 WARN("SecondaryBufferImpl_Create failed\n");
572 static HRESULT WINAPI
IDirectSoundImpl_SetCooperativeLevel(
573 LPDIRECTSOUND8 iface
,
577 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
578 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
580 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
581 WARN("level=%s not fully supported\n",
582 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
584 This
->device
->priolevel
= level
;
588 static HRESULT WINAPI
IDirectSoundImpl_Compact(
589 LPDIRECTSOUND8 iface
)
591 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
592 TRACE("(%p)\n",This
);
594 if (This
->device
== NULL
) {
595 WARN("not initialized\n");
596 return DSERR_UNINITIALIZED
;
599 if (This
->device
->priolevel
!= DSSCL_PRIORITY
) {
600 WARN("incorrect priority level\n");
601 return DSERR_PRIOLEVELNEEDED
;
607 static HRESULT WINAPI
IDirectSoundImpl_GetSpeakerConfig(
608 LPDIRECTSOUND8 iface
,
609 LPDWORD lpdwSpeakerConfig
)
611 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
612 TRACE("(%p, %p)\n",This
,lpdwSpeakerConfig
);
614 if (This
->device
== NULL
) {
615 WARN("not initialized\n");
616 return DSERR_UNINITIALIZED
;
619 if (lpdwSpeakerConfig
== NULL
) {
620 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
621 return DSERR_INVALIDPARAM
;
624 WARN("not fully functional\n");
625 *lpdwSpeakerConfig
= This
->device
->speaker_config
;
629 static HRESULT WINAPI
IDirectSoundImpl_SetSpeakerConfig(
630 LPDIRECTSOUND8 iface
,
633 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
634 TRACE("(%p,0x%08lx)\n",This
,config
);
636 if (This
->device
== NULL
) {
637 WARN("not initialized\n");
638 return DSERR_UNINITIALIZED
;
641 This
->device
->speaker_config
= config
;
642 WARN("not fully functional\n");
646 static HRESULT WINAPI
IDirectSoundImpl_Initialize(
647 LPDIRECTSOUND8 iface
,
650 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
651 DirectSoundDevice
*device
= This
->device
;
654 BOOLEAN found
= FALSE
;
656 TRACE("(%p,%s)\n",This
,debugstr_guid(lpcGUID
));
658 if (device
!= NULL
) {
659 WARN("already initialized\n");
660 return DSERR_ALREADYINITIALIZED
;
663 /* Default device? */
664 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
665 lpcGUID
= &DSDEVID_DefaultPlayback
;
667 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
668 WARN("invalid parameter: lpcGUID\n");
669 return DSERR_INVALIDPARAM
;
672 /* Enumerate WINMM audio devices and find the one we want */
673 wodn
= waveOutGetNumDevs();
676 return DSERR_NODRIVER
;
679 for (wod
=0; wod
<wodn
; wod
++) {
680 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
686 if (found
== FALSE
) {
687 WARN("No device found matching given ID!\n");
688 return DSERR_NODRIVER
;
691 if (DSOUND_renderer
[wod
]) {
692 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
693 device
= DSOUND_renderer
[wod
];
695 This
->device
= device
;
698 ERR("device GUID doesn't match\n");
703 hr
= DirectSoundDevice_Create(&(device
));
705 WARN("DirectSoundDevice_Create failed\n");
710 This
->device
= device
;
711 device
->guid
= devGUID
;
713 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
714 waveOutMessage((HWAVEOUT
)wod
, DRV_QUERYDSOUNDIFACE
, (DWORD
)&device
->driver
, 0);
716 /* Disable the direct sound driver to force emulation if requested. */
717 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
718 device
->driver
= NULL
;
720 /* Get driver description */
721 if (device
->driver
) {
722 hr
= IDsDriver_GetDriverDesc(device
->driver
,&(device
->drvdesc
));
724 WARN("IDsDriver_GetDriverDesc failed\n");
728 /* if no DirectSound interface available, use WINMM API instead */
729 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
| DSDDESC_DOMMSYSTEMSETFORMAT
;
732 device
->drvdesc
.dnDevNode
= wod
;
734 /* If the driver requests being opened through MMSYSTEM
735 * (which is recommended by the DDK), it is supposed to happen
736 * before the DirectSound interface is opened */
737 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
739 DWORD flags
= CALLBACK_FUNCTION
;
741 /* disable direct sound if requested */
742 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
743 flags
|= WAVE_DIRECTSOUND
;
745 hr
= mmErr(waveOutOpen(&(device
->hwo
),
746 device
->drvdesc
.dnDevNode
, device
->pwfx
,
747 (DWORD
)DSOUND_callback
, (DWORD
)device
,
750 WARN("waveOutOpen failed\n");
755 if (device
->driver
) {
756 hr
= IDsDriver_Open(device
->driver
);
758 WARN("IDsDriver_Open failed\n");
762 /* the driver is now open, so it's now allowed to call GetCaps */
763 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
765 WARN("IDsDriver_GetCaps failed\n");
770 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
772 WARN("waveOutGetDevCaps failed\n");
775 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
776 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
777 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
778 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
779 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
780 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
781 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
782 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
784 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
785 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
786 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
787 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
788 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
789 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
790 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
792 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
793 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
794 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
795 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
796 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
797 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
798 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
800 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
801 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
802 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
803 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
804 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
805 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
806 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
809 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
810 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
811 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
812 device
->drvcaps
.dwPrimaryBuffers
= 1;
815 hr
= DSOUND_PrimaryCreate(device
);
817 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
818 timeBeginPeriod(DS_TIME_RES
);
819 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
820 (DWORD
)DSOUND_renderer
[device
->drvdesc
.dnDevNode
], TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
822 WARN("DSOUND_PrimaryCreate failed\n");
828 static HRESULT WINAPI
IDirectSoundImpl_VerifyCertification(
829 LPDIRECTSOUND8 iface
,
830 LPDWORD pdwCertified
)
832 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
833 TRACE("(%p, %p)\n",This
,pdwCertified
);
835 if (This
->device
== NULL
) {
836 WARN("not initialized\n");
837 return DSERR_UNINITIALIZED
;
840 if (This
->device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
841 *pdwCertified
= DS_CERTIFIED
;
843 *pdwCertified
= DS_UNCERTIFIED
;
847 static const IDirectSound8Vtbl IDirectSoundImpl_Vtbl
=
849 IDirectSoundImpl_QueryInterface
,
850 IDirectSoundImpl_AddRef
,
851 IDirectSoundImpl_Release
,
852 IDirectSoundImpl_CreateSoundBuffer
,
853 IDirectSoundImpl_GetCaps
,
854 IDirectSoundImpl_DuplicateSoundBuffer
,
855 IDirectSoundImpl_SetCooperativeLevel
,
856 IDirectSoundImpl_Compact
,
857 IDirectSoundImpl_GetSpeakerConfig
,
858 IDirectSoundImpl_SetSpeakerConfig
,
859 IDirectSoundImpl_Initialize
,
860 IDirectSoundImpl_VerifyCertification
863 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
865 DirectSoundDevice
* device
;
866 TRACE("(%p)\n", ppDevice
);
868 /* Allocate memory */
869 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
870 if (device
== NULL
) {
871 WARN("out of memory\n");
872 return DSERR_OUTOFMEMORY
;
876 device
->driver
= NULL
;
877 device
->priolevel
= DSSCL_NORMAL
;
879 device
->hwbuf
= NULL
;
880 device
->buffer
= NULL
;
882 device
->writelead
= 0;
883 device
->state
= STATE_STOPPED
;
884 device
->nrofbuffers
= 0;
885 device
->buffers
= NULL
;
886 device
->primary
= NULL
;
887 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
888 device
->tmp_buffer
= NULL
;
889 device
->tmp_buffer_len
= 0;
891 /* 3D listener initial parameters */
892 device
->listener
= NULL
;
893 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
894 device
->ds3dl
.vPosition
.x
= 0.0;
895 device
->ds3dl
.vPosition
.y
= 0.0;
896 device
->ds3dl
.vPosition
.z
= 0.0;
897 device
->ds3dl
.vVelocity
.x
= 0.0;
898 device
->ds3dl
.vVelocity
.y
= 0.0;
899 device
->ds3dl
.vVelocity
.z
= 0.0;
900 device
->ds3dl
.vOrientFront
.x
= 0.0;
901 device
->ds3dl
.vOrientFront
.y
= 0.0;
902 device
->ds3dl
.vOrientFront
.z
= 1.0;
903 device
->ds3dl
.vOrientTop
.x
= 0.0;
904 device
->ds3dl
.vOrientTop
.y
= 1.0;
905 device
->ds3dl
.vOrientTop
.z
= 0.0;
906 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
907 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
908 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
910 device
->prebuf
= ds_snd_queue_max
;
911 device
->guid
= GUID_NULL
;
913 /* Set default wave format (may need it for waveOutOpen) */
914 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
915 if (device
->pwfx
== NULL
) {
916 WARN("out of memory\n");
917 HeapFree(GetProcessHeap(),0,device
);
918 return DSERR_OUTOFMEMORY
;
921 /* We rely on the sound driver to return the actual sound format of
922 * the device if it does not support 22050x8x2 and is given the
923 * WAVE_DIRECTSOUND flag.
925 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
926 device
->pwfx
->nSamplesPerSec
= 22050;
927 device
->pwfx
->wBitsPerSample
= 8;
928 device
->pwfx
->nChannels
= 2;
929 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
930 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
931 device
->pwfx
->cbSize
= 0;
933 InitializeCriticalSection(&(device
->mixlock
));
934 device
->mixlock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUND_mixlock";
936 RtlInitializeResource(&(device
->buffer_list_lock
));
943 static ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
947 TRACE("(%p) ref was %lu\n", device
, device
->ref
);
950 if (device
->ref
== 0) {
951 timeKillEvent(device
->timerID
);
952 timeEndPeriod(DS_TIME_RES
);
953 /* wait for timer to expire */
954 Sleep(DS_TIME_RES
+1);
956 /* The sleep above should have allowed the timer process to expire
957 * but try to grab the lock just in case. Can't hold lock because
958 * IDirectSoundBufferImpl_Destroy also grabs the lock */
959 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
960 RtlReleaseResource(&(device
->buffer_list_lock
));
962 /* It is allowed to release this object even when buffers are playing */
963 if (device
->buffers
) {
964 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
965 for( i
=0;i
<device
->nrofbuffers
;i
++)
966 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
969 if (device
->primary
) {
970 WARN("primary buffer not released\n");
971 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
974 hr
= DSOUND_PrimaryDestroy(device
);
976 WARN("DSOUND_PrimaryDestroy failed\n");
979 IDsDriver_Close(device
->driver
);
981 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
982 waveOutClose(device
->hwo
);
985 IDsDriver_Release(device
->driver
);
987 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
989 HeapFree(GetProcessHeap(),0,device
->tmp_buffer
);
990 HeapFree(GetProcessHeap(),0,device
->buffer
);
991 RtlDeleteResource(&device
->buffer_list_lock
);
992 device
->mixlock
.DebugInfo
->Spare
[1] = 0;
993 DeleteCriticalSection(&device
->mixlock
);
994 HeapFree(GetProcessHeap(),0,device
);
995 TRACE("(%p) released\n", device
);
1000 HRESULT WINAPI
IDirectSoundImpl_Create(
1001 LPDIRECTSOUND8
* ppDS
)
1003 IDirectSoundImpl
* pDS
;
1004 TRACE("(%p)\n",ppDS
);
1006 /* Allocate memory */
1007 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
1009 WARN("out of memory\n");
1011 return DSERR_OUTOFMEMORY
;
1014 pDS
->lpVtbl
= &IDirectSoundImpl_Vtbl
;
1018 *ppDS
= (LPDIRECTSOUND8
)pDS
;
1023 /*******************************************************************************
1024 * IDirectSound_IUnknown
1026 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
1031 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1032 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1033 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
1036 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
1039 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1040 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1041 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1045 static ULONG WINAPI
IDirectSound_IUnknown_Release(
1048 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1049 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1050 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1052 IDirectSoundImpl_Release(This
->pds
);
1053 HeapFree(GetProcessHeap(), 0, This
);
1054 TRACE("(%p) released\n", This
);
1059 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
1061 IDirectSound_IUnknown_QueryInterface
,
1062 IDirectSound_IUnknown_AddRef
,
1063 IDirectSound_IUnknown_Release
1066 HRESULT WINAPI
IDirectSound_IUnknown_Create(
1070 IDirectSound_IUnknown
* pdsunk
;
1071 TRACE("(%p,%p)\n",pds
,ppunk
);
1073 if (ppunk
== NULL
) {
1074 ERR("invalid parameter: ppunk == NULL\n");
1075 return DSERR_INVALIDPARAM
;
1079 ERR("invalid parameter: pds == NULL\n");
1081 return DSERR_INVALIDPARAM
;
1084 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1085 if (pdsunk
== NULL
) {
1086 WARN("out of memory\n");
1088 return DSERR_OUTOFMEMORY
;
1091 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
1095 IDirectSoundImpl_AddRef(pds
);
1096 *ppunk
= (LPUNKNOWN
)pdsunk
;
1101 /*******************************************************************************
1102 * IDirectSound_IDirectSound
1104 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
1105 LPDIRECTSOUND iface
,
1109 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1110 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1111 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
1114 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
1115 LPDIRECTSOUND iface
)
1117 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1118 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1119 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1123 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
1124 LPDIRECTSOUND iface
)
1126 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1127 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1128 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1130 IDirectSoundImpl_Release(This
->pds
);
1131 HeapFree(GetProcessHeap(), 0, This
);
1132 TRACE("(%p) released\n", This
);
1137 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
1138 LPDIRECTSOUND iface
,
1139 LPCDSBUFFERDESC dsbd
,
1140 LPLPDIRECTSOUNDBUFFER ppdsb
,
1143 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1144 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1145 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,FALSE
);
1148 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
1149 LPDIRECTSOUND iface
,
1152 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1153 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1154 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1157 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
1158 LPDIRECTSOUND iface
,
1159 LPDIRECTSOUNDBUFFER psb
,
1160 LPLPDIRECTSOUNDBUFFER ppdsb
)
1162 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1163 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1164 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1167 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
1168 LPDIRECTSOUND iface
,
1172 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1173 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1174 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1177 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
1178 LPDIRECTSOUND iface
)
1180 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1181 TRACE("(%p)\n", This
);
1182 return IDirectSoundImpl_Compact(This
->pds
);
1185 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
1186 LPDIRECTSOUND iface
,
1187 LPDWORD lpdwSpeakerConfig
)
1189 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1190 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1191 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1194 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
1195 LPDIRECTSOUND iface
,
1198 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1199 TRACE("(%p,0x%08lx)\n",This
,config
);
1200 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1203 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
1204 LPDIRECTSOUND iface
,
1207 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
1208 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1209 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1212 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
1214 IDirectSound_IDirectSound_QueryInterface
,
1215 IDirectSound_IDirectSound_AddRef
,
1216 IDirectSound_IDirectSound_Release
,
1217 IDirectSound_IDirectSound_CreateSoundBuffer
,
1218 IDirectSound_IDirectSound_GetCaps
,
1219 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
1220 IDirectSound_IDirectSound_SetCooperativeLevel
,
1221 IDirectSound_IDirectSound_Compact
,
1222 IDirectSound_IDirectSound_GetSpeakerConfig
,
1223 IDirectSound_IDirectSound_SetSpeakerConfig
,
1224 IDirectSound_IDirectSound_Initialize
1227 HRESULT WINAPI
IDirectSound_IDirectSound_Create(
1229 LPDIRECTSOUND
* ppds
)
1231 IDirectSound_IDirectSound
* pdsds
;
1232 TRACE("(%p,%p)\n",pds
,ppds
);
1235 ERR("invalid parameter: ppds == NULL\n");
1236 return DSERR_INVALIDPARAM
;
1240 ERR("invalid parameter: pds == NULL\n");
1242 return DSERR_INVALIDPARAM
;
1245 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1246 if (pdsds
== NULL
) {
1247 WARN("out of memory\n");
1249 return DSERR_OUTOFMEMORY
;
1252 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
1256 IDirectSoundImpl_AddRef(pds
);
1257 *ppds
= (LPDIRECTSOUND
)pdsds
;
1262 /*******************************************************************************
1263 * IDirectSound8_IUnknown
1265 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
1270 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1271 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1272 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1275 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
1278 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1279 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1280 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1284 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
1287 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
1288 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1289 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1291 IDirectSoundImpl_Release(This
->pds
);
1292 HeapFree(GetProcessHeap(), 0, This
);
1293 TRACE("(%p) released\n", This
);
1298 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
1300 IDirectSound8_IUnknown_QueryInterface
,
1301 IDirectSound8_IUnknown_AddRef
,
1302 IDirectSound8_IUnknown_Release
1305 HRESULT WINAPI
IDirectSound8_IUnknown_Create(
1309 IDirectSound8_IUnknown
* pdsunk
;
1310 TRACE("(%p,%p)\n",pds
,ppunk
);
1312 if (ppunk
== NULL
) {
1313 ERR("invalid parameter: ppunk == NULL\n");
1314 return DSERR_INVALIDPARAM
;
1318 ERR("invalid parameter: pds == NULL\n");
1320 return DSERR_INVALIDPARAM
;
1323 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1324 if (pdsunk
== NULL
) {
1325 WARN("out of memory\n");
1327 return DSERR_OUTOFMEMORY
;
1330 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
1334 IDirectSoundImpl_AddRef(pds
);
1335 *ppunk
= (LPUNKNOWN
)pdsunk
;
1340 /*******************************************************************************
1341 * IDirectSound8_IDirectSound
1343 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
1344 LPDIRECTSOUND iface
,
1348 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1349 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1350 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1353 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
1354 LPDIRECTSOUND iface
)
1356 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1357 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1358 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1362 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
1363 LPDIRECTSOUND iface
)
1365 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1366 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1367 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1369 IDirectSoundImpl_Release(This
->pds
);
1370 HeapFree(GetProcessHeap(), 0, This
);
1371 TRACE("(%p) released\n", This
);
1376 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
1377 LPDIRECTSOUND iface
,
1378 LPCDSBUFFERDESC dsbd
,
1379 LPLPDIRECTSOUNDBUFFER ppdsb
,
1382 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1383 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1384 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,TRUE
);
1387 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
1388 LPDIRECTSOUND iface
,
1391 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1392 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1393 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1396 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1397 LPDIRECTSOUND iface
,
1398 LPDIRECTSOUNDBUFFER psb
,
1399 LPLPDIRECTSOUNDBUFFER ppdsb
)
1401 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1402 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1403 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1406 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
1407 LPDIRECTSOUND iface
,
1411 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1412 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1413 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1416 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
1417 LPDIRECTSOUND iface
)
1419 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1420 TRACE("(%p)\n", This
);
1421 return IDirectSoundImpl_Compact(This
->pds
);
1424 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
1425 LPDIRECTSOUND iface
,
1426 LPDWORD lpdwSpeakerConfig
)
1428 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1429 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1430 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1433 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
1434 LPDIRECTSOUND iface
,
1437 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1438 TRACE("(%p,0x%08lx)\n",This
,config
);
1439 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1442 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
1443 LPDIRECTSOUND iface
,
1446 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1447 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1448 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1451 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
1453 IDirectSound8_IDirectSound_QueryInterface
,
1454 IDirectSound8_IDirectSound_AddRef
,
1455 IDirectSound8_IDirectSound_Release
,
1456 IDirectSound8_IDirectSound_CreateSoundBuffer
,
1457 IDirectSound8_IDirectSound_GetCaps
,
1458 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
1459 IDirectSound8_IDirectSound_SetCooperativeLevel
,
1460 IDirectSound8_IDirectSound_Compact
,
1461 IDirectSound8_IDirectSound_GetSpeakerConfig
,
1462 IDirectSound8_IDirectSound_SetSpeakerConfig
,
1463 IDirectSound8_IDirectSound_Initialize
1466 HRESULT WINAPI
IDirectSound8_IDirectSound_Create(
1468 LPDIRECTSOUND
* ppds
)
1470 IDirectSound8_IDirectSound
* pdsds
;
1471 TRACE("(%p,%p)\n",pds
,ppds
);
1474 ERR("invalid parameter: ppds == NULL\n");
1475 return DSERR_INVALIDPARAM
;
1479 ERR("invalid parameter: pds == NULL\n");
1481 return DSERR_INVALIDPARAM
;
1484 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1485 if (pdsds
== NULL
) {
1486 WARN("out of memory\n");
1488 return DSERR_OUTOFMEMORY
;
1491 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
1495 IDirectSoundImpl_AddRef(pds
);
1496 *ppds
= (LPDIRECTSOUND
)pdsds
;
1501 /*******************************************************************************
1502 * IDirectSound8_IDirectSound8
1504 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
1505 LPDIRECTSOUND8 iface
,
1509 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1510 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1511 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1514 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
1515 LPDIRECTSOUND8 iface
)
1517 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1518 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1519 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1523 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
1524 LPDIRECTSOUND8 iface
)
1526 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1527 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1528 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1530 IDirectSoundImpl_Release(This
->pds
);
1531 HeapFree(GetProcessHeap(), 0, This
);
1532 TRACE("(%p) released\n", This
);
1537 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
1538 LPDIRECTSOUND8 iface
,
1539 LPCDSBUFFERDESC dsbd
,
1540 LPLPDIRECTSOUNDBUFFER ppdsb
,
1543 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1544 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1545 return DSOUND_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
,TRUE
);
1548 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
1549 LPDIRECTSOUND8 iface
,
1552 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
1553 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1554 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1557 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1558 LPDIRECTSOUND8 iface
,
1559 LPDIRECTSOUNDBUFFER psb
,
1560 LPLPDIRECTSOUNDBUFFER ppdsb
)
1562 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1563 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1564 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1567 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
1568 LPDIRECTSOUND8 iface
,
1572 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1573 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1574 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1577 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
1578 LPDIRECTSOUND8 iface
)
1580 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1581 TRACE("(%p)\n", This
);
1582 return IDirectSoundImpl_Compact(This
->pds
);
1585 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
1586 LPDIRECTSOUND8 iface
,
1587 LPDWORD lpdwSpeakerConfig
)
1589 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1590 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1591 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1594 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
1595 LPDIRECTSOUND8 iface
,
1598 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1599 TRACE("(%p,0x%08lx)\n",This
,config
);
1600 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1603 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
1604 LPDIRECTSOUND8 iface
,
1607 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1608 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1609 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1612 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
1613 LPDIRECTSOUND8 iface
,
1614 LPDWORD pdwCertified
)
1616 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
1617 TRACE("(%p, %p)\n", This
, pdwCertified
);
1618 return IDirectSoundImpl_VerifyCertification(This
->pds
,pdwCertified
);
1621 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
1623 IDirectSound8_IDirectSound8_QueryInterface
,
1624 IDirectSound8_IDirectSound8_AddRef
,
1625 IDirectSound8_IDirectSound8_Release
,
1626 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
1627 IDirectSound8_IDirectSound8_GetCaps
,
1628 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
1629 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
1630 IDirectSound8_IDirectSound8_Compact
,
1631 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
1632 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
1633 IDirectSound8_IDirectSound8_Initialize
,
1634 IDirectSound8_IDirectSound8_VerifyCertification
1637 HRESULT WINAPI
IDirectSound8_IDirectSound8_Create(
1639 LPDIRECTSOUND8
* ppds
)
1641 IDirectSound8_IDirectSound8
* pdsds
;
1642 TRACE("(%p,%p)\n",pds
,ppds
);
1645 ERR("invalid parameter: ppds == NULL\n");
1646 return DSERR_INVALIDPARAM
;
1650 ERR("invalid parameter: pds == NULL\n");
1652 return DSERR_INVALIDPARAM
;
1655 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1656 if (pdsds
== NULL
) {
1657 WARN("out of memory\n");
1659 return DSERR_OUTOFMEMORY
;
1662 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
1666 IDirectSoundImpl_AddRef(pds
);
1667 *ppds
= (LPDIRECTSOUND8
)pdsds
;
1672 HRESULT WINAPI
DSOUND_Create(
1673 LPDIRECTSOUND
*ppDS
,
1674 IUnknown
*pUnkOuter
)
1678 TRACE("(%p,%p)\n",ppDS
,pUnkOuter
);
1680 /* Get dsound configuration */
1681 setup_dsound_options();
1683 hr
= IDirectSoundImpl_Create(&pDS
);
1685 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1687 IDirectSound_IDirectSound_AddRef(*ppDS
);
1689 WARN("IDirectSound_IDirectSound_Create failed\n");
1690 IDirectSound8_Release(pDS
);
1693 WARN("IDirectSoundImpl_Create failed\n");
1700 /*******************************************************************************
1701 * DirectSoundCreate (DSOUND.1)
1703 * Creates and initializes a DirectSound interface.
1706 * lpcGUID [I] Address of the GUID that identifies the sound device.
1707 * ppDS [O] Address of a variable to receive the interface pointer.
1708 * pUnkOuter [I] Must be NULL.
1712 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1713 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1715 HRESULT WINAPI
DirectSoundCreate(
1717 LPDIRECTSOUND
*ppDS
,
1718 IUnknown
*pUnkOuter
)
1723 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1726 WARN("invalid parameter: ppDS == NULL\n");
1727 return DSERR_INVALIDPARAM
;
1730 if (pUnkOuter
!= NULL
) {
1731 WARN("invalid parameter: pUnkOuter != NULL\n");
1733 return DSERR_INVALIDPARAM
;
1736 hr
= DSOUND_Create(&pDS
, pUnkOuter
);
1738 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1740 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1741 IDirectSound_Release(pDS
);
1753 HRESULT WINAPI
DSOUND_Create8(
1754 LPDIRECTSOUND8
*ppDS
,
1755 IUnknown
*pUnkOuter
)
1759 TRACE("(%p,%p)\n",ppDS
,pUnkOuter
);
1761 /* Get dsound configuration */
1762 setup_dsound_options();
1764 hr
= IDirectSoundImpl_Create(&pDS
);
1766 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1768 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1770 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1771 IDirectSound8_Release(pDS
);
1774 WARN("IDirectSoundImpl_Create failed\n");
1781 /*******************************************************************************
1782 * DirectSoundCreate8 (DSOUND.11)
1784 * Creates and initializes a DirectSound8 interface.
1787 * lpcGUID [I] Address of the GUID that identifies the sound device.
1788 * ppDS [O] Address of a variable to receive the interface pointer.
1789 * pUnkOuter [I] Must be NULL.
1793 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1794 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1796 HRESULT WINAPI
DirectSoundCreate8(
1798 LPDIRECTSOUND8
*ppDS
,
1799 IUnknown
*pUnkOuter
)
1804 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1807 WARN("invalid parameter: ppDS == NULL\n");
1808 return DSERR_INVALIDPARAM
;
1811 if (pUnkOuter
!= NULL
) {
1812 WARN("invalid parameter: pUnkOuter != NULL\n");
1814 return DSERR_INVALIDPARAM
;
1817 hr
= DSOUND_Create8(&pDS
, pUnkOuter
);
1819 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1821 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1822 IDirectSound8_Release(pDS
);
1835 * Add secondary buffer to buffer list.
1836 * Gets exclusive access to buffer for writing.
1838 HRESULT
DSOUND_AddBuffer(
1839 IDirectSoundImpl
* pDS
,
1840 IDirectSoundBufferImpl
* pDSB
)
1842 IDirectSoundBufferImpl
**newbuffers
;
1845 TRACE("(%p, %p)\n", pDS
, pDSB
);
1847 RtlAcquireResourceExclusive(&(pDS
->device
->buffer_list_lock
), TRUE
);
1849 if (pDS
->device
->buffers
)
1850 newbuffers
= HeapReAlloc(GetProcessHeap(),0,pDS
->device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(pDS
->device
->nrofbuffers
+1));
1852 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(pDS
->device
->nrofbuffers
+1));
1855 pDS
->device
->buffers
= newbuffers
;
1856 pDS
->device
->buffers
[pDS
->device
->nrofbuffers
] = pDSB
;
1857 pDS
->device
->nrofbuffers
++;
1858 TRACE("buffer count is now %d\n", pDS
->device
->nrofbuffers
);
1860 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS
->device
->nrofbuffers
);
1861 hr
= DSERR_OUTOFMEMORY
;
1864 RtlReleaseResource(&(pDS
->device
->buffer_list_lock
));
1870 * Remove secondary buffer from buffer list.
1871 * Gets exclusive access to buffer for writing.
1873 HRESULT
DSOUND_RemoveBuffer(
1874 IDirectSoundImpl
* pDS
,
1875 IDirectSoundBufferImpl
* pDSB
)
1880 TRACE("(%p, %p)\n", pDS
, pDSB
);
1882 RtlAcquireResourceExclusive(&(pDS
->device
->buffer_list_lock
), TRUE
);
1884 for (i
= 0; i
< pDS
->device
->nrofbuffers
; i
++)
1885 if (pDS
->device
->buffers
[i
] == pDSB
)
1888 if (i
< pDS
->device
->nrofbuffers
) {
1889 /* Put the last buffer of the list in the (now empty) position */
1890 pDS
->device
->buffers
[i
] = pDS
->device
->buffers
[pDS
->device
->nrofbuffers
- 1];
1891 pDS
->device
->nrofbuffers
--;
1892 pDS
->device
->buffers
= HeapReAlloc(GetProcessHeap(),0,pDS
->device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*pDS
->device
->nrofbuffers
);
1893 TRACE("buffer count is now %d\n", pDS
->device
->nrofbuffers
);
1896 if (pDS
->device
->nrofbuffers
== 0) {
1897 HeapFree(GetProcessHeap(),0,pDS
->device
->buffers
);
1898 pDS
->device
->buffers
= NULL
;
1901 RtlReleaseResource(&(pDS
->device
->buffer_list_lock
));