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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
34 #include "wine/debug.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
41 /*****************************************************************************
42 * IDirectSound COM components
44 struct IDirectSound_IUnknown
{
45 const IUnknownVtbl
*lpVtbl
;
50 static HRESULT
IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
52 struct IDirectSound_IDirectSound
{
53 const IDirectSoundVtbl
*lpVtbl
;
58 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
60 /*****************************************************************************
61 * IDirectSound8 COM components
63 struct IDirectSound8_IUnknown
{
64 const IUnknownVtbl
*lpVtbl
;
69 static HRESULT
IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
70 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
72 struct IDirectSound8_IDirectSound
{
73 const IDirectSoundVtbl
*lpVtbl
;
78 static HRESULT
IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
79 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
81 struct IDirectSound8_IDirectSound8
{
82 const IDirectSound8Vtbl
*lpVtbl
;
87 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
88 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
90 /*****************************************************************************
91 * IDirectSound implementation structure
93 struct IDirectSoundImpl
97 DirectSoundDevice
*device
;
103 static HRESULT
IDirectSoundImpl_Create(LPDIRECTSOUND8
* ppds
);
105 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
106 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
108 static HRESULT
DirectSoundDevice_VerifyCertification(DirectSoundDevice
* device
, LPDWORD pdwCertified
);
110 const char * dumpCooperativeLevel(DWORD level
)
112 static char unknown
[32];
113 #define LE(x) case x: return #x
118 LE(DSSCL_WRITEPRIMARY
);
121 sprintf(unknown
, "Unknown(%08x)", level
);
125 static void _dump_DSCAPS(DWORD xmask
) {
130 #define FE(x) { x, #x },
131 FE(DSCAPS_PRIMARYMONO
)
132 FE(DSCAPS_PRIMARYSTEREO
)
133 FE(DSCAPS_PRIMARY8BIT
)
134 FE(DSCAPS_PRIMARY16BIT
)
135 FE(DSCAPS_CONTINUOUSRATE
)
136 FE(DSCAPS_EMULDRIVER
)
138 FE(DSCAPS_SECONDARYMONO
)
139 FE(DSCAPS_SECONDARYSTEREO
)
140 FE(DSCAPS_SECONDARY8BIT
)
141 FE(DSCAPS_SECONDARY16BIT
)
146 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
147 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
148 TRACE("%s ",flags
[i
].name
);
151 static void _dump_DSBCAPS(DWORD xmask
) {
156 #define FE(x) { x, #x },
157 FE(DSBCAPS_PRIMARYBUFFER
)
159 FE(DSBCAPS_LOCHARDWARE
)
160 FE(DSBCAPS_LOCSOFTWARE
)
162 FE(DSBCAPS_CTRLFREQUENCY
)
164 FE(DSBCAPS_CTRLVOLUME
)
165 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
166 FE(DSBCAPS_STICKYFOCUS
)
167 FE(DSBCAPS_GLOBALFOCUS
)
168 FE(DSBCAPS_GETCURRENTPOSITION2
)
169 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
174 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
175 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
176 TRACE("%s ",flags
[i
].name
);
179 /*******************************************************************************
180 * IDirectSoundImpl_DirectSound
182 static HRESULT
DSOUND_QueryInterface(
183 LPDIRECTSOUND8 iface
,
187 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
188 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
191 WARN("invalid parameter\n");
195 if (IsEqualIID(riid
, &IID_IUnknown
)) {
196 if (!This
->pUnknown
) {
197 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
198 if (!This
->pUnknown
) {
199 WARN("IDirectSound_IUnknown_Create() failed\n");
201 return E_NOINTERFACE
;
204 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
205 *ppobj
= This
->pUnknown
;
207 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
209 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
211 WARN("IDirectSound_IDirectSound_Create() failed\n");
213 return E_NOINTERFACE
;
216 IDirectSound_IDirectSound_AddRef(This
->pDS
);
222 WARN("Unknown IID %s\n",debugstr_guid(riid
));
223 return E_NOINTERFACE
;
226 static HRESULT
DSOUND_QueryInterface8(
227 LPDIRECTSOUND8 iface
,
231 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
232 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
235 WARN("invalid parameter\n");
239 if (IsEqualIID(riid
, &IID_IUnknown
)) {
240 if (!This
->pUnknown
) {
241 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
242 if (!This
->pUnknown
) {
243 WARN("IDirectSound8_IUnknown_Create() failed\n");
245 return E_NOINTERFACE
;
248 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
249 *ppobj
= This
->pUnknown
;
251 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
253 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
255 WARN("IDirectSound8_IDirectSound_Create() failed\n");
257 return E_NOINTERFACE
;
260 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
263 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
265 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
267 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
269 return E_NOINTERFACE
;
272 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
278 WARN("Unknown IID %s\n",debugstr_guid(riid
));
279 return E_NOINTERFACE
;
282 static ULONG
IDirectSoundImpl_AddRef(
283 LPDIRECTSOUND8 iface
)
285 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
286 ULONG ref
= InterlockedIncrement(&(This
->ref
));
287 TRACE("(%p) ref was %d\n", This
, ref
- 1);
291 static ULONG
IDirectSoundImpl_Release(
292 LPDIRECTSOUND8 iface
)
294 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
295 ULONG ref
= InterlockedDecrement(&(This
->ref
));
296 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
300 DirectSoundDevice_Release(This
->device
);
301 HeapFree(GetProcessHeap(),0,This
);
302 TRACE("(%p) released\n", This
);
307 static HRESULT
IDirectSoundImpl_Create(
308 LPDIRECTSOUND8
* ppDS
)
310 IDirectSoundImpl
* pDS
;
311 TRACE("(%p)\n",ppDS
);
313 /* Allocate memory */
314 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
316 WARN("out of memory\n");
318 return DSERR_OUTOFMEMORY
;
324 *ppDS
= (LPDIRECTSOUND8
)pDS
;
329 /*******************************************************************************
330 * IDirectSound_IUnknown
332 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
337 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
338 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
339 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
342 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
345 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
346 ULONG ref
= InterlockedIncrement(&(This
->ref
));
347 TRACE("(%p) ref was %d\n", This
, ref
- 1);
351 static ULONG WINAPI
IDirectSound_IUnknown_Release(
354 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
355 ULONG ref
= InterlockedDecrement(&(This
->ref
));
356 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
358 IDirectSoundImpl_Release(This
->pds
);
359 HeapFree(GetProcessHeap(), 0, This
);
360 TRACE("(%p) released\n", This
);
365 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
367 IDirectSound_IUnknown_QueryInterface
,
368 IDirectSound_IUnknown_AddRef
,
369 IDirectSound_IUnknown_Release
372 static HRESULT
IDirectSound_IUnknown_Create(
376 IDirectSound_IUnknown
* pdsunk
;
377 TRACE("(%p,%p)\n",pds
,ppunk
);
380 ERR("invalid parameter: ppunk == NULL\n");
381 return DSERR_INVALIDPARAM
;
385 ERR("invalid parameter: pds == NULL\n");
387 return DSERR_INVALIDPARAM
;
390 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
391 if (pdsunk
== NULL
) {
392 WARN("out of memory\n");
394 return DSERR_OUTOFMEMORY
;
397 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
401 IDirectSoundImpl_AddRef(pds
);
402 *ppunk
= (LPUNKNOWN
)pdsunk
;
407 /*******************************************************************************
408 * IDirectSound_IDirectSound
410 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
415 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
416 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
417 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
420 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
423 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
424 ULONG ref
= InterlockedIncrement(&(This
->ref
));
425 TRACE("(%p) ref was %d\n", This
, ref
- 1);
429 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
432 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
433 ULONG ref
= InterlockedDecrement(&(This
->ref
));
434 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
436 IDirectSoundImpl_Release(This
->pds
);
437 HeapFree(GetProcessHeap(), 0, This
);
438 TRACE("(%p) released\n", This
);
443 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
445 LPCDSBUFFERDESC dsbd
,
446 LPLPDIRECTSOUNDBUFFER ppdsb
,
449 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
450 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
451 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,FALSE
);
454 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
458 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
459 TRACE("(%p,%p)\n",This
,lpDSCaps
);
460 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
463 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
465 LPDIRECTSOUNDBUFFER psb
,
466 LPLPDIRECTSOUNDBUFFER ppdsb
)
468 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
469 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
470 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
473 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
478 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
479 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
480 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
483 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
486 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
487 TRACE("(%p)\n", This
);
488 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
491 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
493 LPDWORD lpdwSpeakerConfig
)
495 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
496 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
497 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
500 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
504 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
505 TRACE("(%p,0x%08x)\n",This
,config
);
506 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
509 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
513 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
514 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
515 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
518 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
520 IDirectSound_IDirectSound_QueryInterface
,
521 IDirectSound_IDirectSound_AddRef
,
522 IDirectSound_IDirectSound_Release
,
523 IDirectSound_IDirectSound_CreateSoundBuffer
,
524 IDirectSound_IDirectSound_GetCaps
,
525 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
526 IDirectSound_IDirectSound_SetCooperativeLevel
,
527 IDirectSound_IDirectSound_Compact
,
528 IDirectSound_IDirectSound_GetSpeakerConfig
,
529 IDirectSound_IDirectSound_SetSpeakerConfig
,
530 IDirectSound_IDirectSound_Initialize
533 static HRESULT
IDirectSound_IDirectSound_Create(
535 LPDIRECTSOUND
* ppds
)
537 IDirectSound_IDirectSound
* pdsds
;
538 TRACE("(%p,%p)\n",pds
,ppds
);
541 ERR("invalid parameter: ppds == NULL\n");
542 return DSERR_INVALIDPARAM
;
546 ERR("invalid parameter: pds == NULL\n");
548 return DSERR_INVALIDPARAM
;
551 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
553 WARN("out of memory\n");
555 return DSERR_OUTOFMEMORY
;
558 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
562 IDirectSoundImpl_AddRef(pds
);
563 *ppds
= (LPDIRECTSOUND
)pdsds
;
568 /*******************************************************************************
569 * IDirectSound8_IUnknown
571 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
576 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
577 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
578 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
581 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
584 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
585 ULONG ref
= InterlockedIncrement(&(This
->ref
));
586 TRACE("(%p) ref was %d\n", This
, ref
- 1);
590 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
593 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
594 ULONG ref
= InterlockedDecrement(&(This
->ref
));
595 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
597 IDirectSoundImpl_Release(This
->pds
);
598 HeapFree(GetProcessHeap(), 0, This
);
599 TRACE("(%p) released\n", This
);
604 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
606 IDirectSound8_IUnknown_QueryInterface
,
607 IDirectSound8_IUnknown_AddRef
,
608 IDirectSound8_IUnknown_Release
611 static HRESULT
IDirectSound8_IUnknown_Create(
615 IDirectSound8_IUnknown
* pdsunk
;
616 TRACE("(%p,%p)\n",pds
,ppunk
);
619 ERR("invalid parameter: ppunk == NULL\n");
620 return DSERR_INVALIDPARAM
;
624 ERR("invalid parameter: pds == NULL\n");
626 return DSERR_INVALIDPARAM
;
629 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
630 if (pdsunk
== NULL
) {
631 WARN("out of memory\n");
633 return DSERR_OUTOFMEMORY
;
636 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
640 IDirectSoundImpl_AddRef(pds
);
641 *ppunk
= (LPUNKNOWN
)pdsunk
;
646 /*******************************************************************************
647 * IDirectSound8_IDirectSound
649 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
654 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
655 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
656 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
659 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
662 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
663 ULONG ref
= InterlockedIncrement(&(This
->ref
));
664 TRACE("(%p) ref was %d\n", This
, ref
- 1);
668 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
671 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
672 ULONG ref
= InterlockedDecrement(&(This
->ref
));
673 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
675 IDirectSoundImpl_Release(This
->pds
);
676 HeapFree(GetProcessHeap(), 0, This
);
677 TRACE("(%p) released\n", This
);
682 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
684 LPCDSBUFFERDESC dsbd
,
685 LPLPDIRECTSOUNDBUFFER ppdsb
,
688 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
689 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
690 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
693 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
697 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
698 TRACE("(%p,%p)\n",This
,lpDSCaps
);
699 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
702 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
704 LPDIRECTSOUNDBUFFER psb
,
705 LPLPDIRECTSOUNDBUFFER ppdsb
)
707 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
708 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
709 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
712 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
717 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
718 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
719 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
722 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
725 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
726 TRACE("(%p)\n", This
);
727 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
730 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
732 LPDWORD lpdwSpeakerConfig
)
734 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
735 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
736 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
739 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
743 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
744 TRACE("(%p,0x%08x)\n",This
,config
);
745 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
748 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
752 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
753 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
754 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
757 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
759 IDirectSound8_IDirectSound_QueryInterface
,
760 IDirectSound8_IDirectSound_AddRef
,
761 IDirectSound8_IDirectSound_Release
,
762 IDirectSound8_IDirectSound_CreateSoundBuffer
,
763 IDirectSound8_IDirectSound_GetCaps
,
764 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
765 IDirectSound8_IDirectSound_SetCooperativeLevel
,
766 IDirectSound8_IDirectSound_Compact
,
767 IDirectSound8_IDirectSound_GetSpeakerConfig
,
768 IDirectSound8_IDirectSound_SetSpeakerConfig
,
769 IDirectSound8_IDirectSound_Initialize
772 static HRESULT
IDirectSound8_IDirectSound_Create(
774 LPDIRECTSOUND
* ppds
)
776 IDirectSound8_IDirectSound
* pdsds
;
777 TRACE("(%p,%p)\n",pds
,ppds
);
780 ERR("invalid parameter: ppds == NULL\n");
781 return DSERR_INVALIDPARAM
;
785 ERR("invalid parameter: pds == NULL\n");
787 return DSERR_INVALIDPARAM
;
790 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
792 WARN("out of memory\n");
794 return DSERR_OUTOFMEMORY
;
797 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
801 IDirectSoundImpl_AddRef(pds
);
802 *ppds
= (LPDIRECTSOUND
)pdsds
;
807 /*******************************************************************************
808 * IDirectSound8_IDirectSound8
810 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
811 LPDIRECTSOUND8 iface
,
815 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
816 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
817 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
820 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
821 LPDIRECTSOUND8 iface
)
823 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
824 ULONG ref
= InterlockedIncrement(&(This
->ref
));
825 TRACE("(%p) ref was %d\n", This
, ref
- 1);
829 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
830 LPDIRECTSOUND8 iface
)
832 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
833 ULONG ref
= InterlockedDecrement(&(This
->ref
));
834 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
836 IDirectSoundImpl_Release(This
->pds
);
837 HeapFree(GetProcessHeap(), 0, This
);
838 TRACE("(%p) released\n", This
);
843 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
844 LPDIRECTSOUND8 iface
,
845 LPCDSBUFFERDESC dsbd
,
846 LPLPDIRECTSOUNDBUFFER ppdsb
,
849 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
850 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
851 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
854 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
855 LPDIRECTSOUND8 iface
,
858 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
859 TRACE("(%p,%p)\n",This
,lpDSCaps
);
860 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
863 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
864 LPDIRECTSOUND8 iface
,
865 LPDIRECTSOUNDBUFFER psb
,
866 LPLPDIRECTSOUNDBUFFER ppdsb
)
868 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
869 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
870 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
873 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
874 LPDIRECTSOUND8 iface
,
878 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
879 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
880 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
883 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
884 LPDIRECTSOUND8 iface
)
886 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
887 TRACE("(%p)\n", This
);
888 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
891 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
892 LPDIRECTSOUND8 iface
,
893 LPDWORD lpdwSpeakerConfig
)
895 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
896 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
897 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
900 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
901 LPDIRECTSOUND8 iface
,
904 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
905 TRACE("(%p,0x%08x)\n",This
,config
);
906 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
909 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
910 LPDIRECTSOUND8 iface
,
913 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
914 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
915 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
918 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
919 LPDIRECTSOUND8 iface
,
920 LPDWORD pdwCertified
)
922 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
923 TRACE("(%p, %p)\n", This
, pdwCertified
);
924 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
927 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
929 IDirectSound8_IDirectSound8_QueryInterface
,
930 IDirectSound8_IDirectSound8_AddRef
,
931 IDirectSound8_IDirectSound8_Release
,
932 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
933 IDirectSound8_IDirectSound8_GetCaps
,
934 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
935 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
936 IDirectSound8_IDirectSound8_Compact
,
937 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
938 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
939 IDirectSound8_IDirectSound8_Initialize
,
940 IDirectSound8_IDirectSound8_VerifyCertification
943 static HRESULT
IDirectSound8_IDirectSound8_Create(
945 LPDIRECTSOUND8
* ppds
)
947 IDirectSound8_IDirectSound8
* pdsds
;
948 TRACE("(%p,%p)\n",pds
,ppds
);
951 ERR("invalid parameter: ppds == NULL\n");
952 return DSERR_INVALIDPARAM
;
956 ERR("invalid parameter: pds == NULL\n");
958 return DSERR_INVALIDPARAM
;
961 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
963 WARN("out of memory\n");
965 return DSERR_OUTOFMEMORY
;
968 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
972 IDirectSoundImpl_AddRef(pds
);
973 *ppds
= (LPDIRECTSOUND8
)pdsds
;
978 HRESULT
DSOUND_Create(
984 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
986 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
987 !IsEqualIID(riid
, &IID_IDirectSound
)) {
989 return E_NOINTERFACE
;
992 /* Get dsound configuration */
993 setup_dsound_options();
995 hr
= IDirectSoundImpl_Create(&pDS
);
997 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
999 IDirectSound_IDirectSound_AddRef(*ppDS
);
1001 WARN("IDirectSound_IDirectSound_Create failed\n");
1002 IDirectSound8_Release(pDS
);
1005 WARN("IDirectSoundImpl_Create failed\n");
1012 /*******************************************************************************
1013 * DirectSoundCreate (DSOUND.1)
1015 * Creates and initializes a DirectSound interface.
1018 * lpcGUID [I] Address of the GUID that identifies the sound device.
1019 * ppDS [O] Address of a variable to receive the interface pointer.
1020 * pUnkOuter [I] Must be NULL.
1024 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1025 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1027 HRESULT WINAPI
DirectSoundCreate(
1029 LPDIRECTSOUND
*ppDS
,
1030 IUnknown
*pUnkOuter
)
1035 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1038 WARN("invalid parameter: ppDS == NULL\n");
1039 return DSERR_INVALIDPARAM
;
1042 if (pUnkOuter
!= NULL
) {
1043 WARN("invalid parameter: pUnkOuter != NULL\n");
1045 return DSERR_INVALIDPARAM
;
1048 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
1050 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1052 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1053 IDirectSound_Release(pDS
);
1065 HRESULT
DSOUND_Create8(
1067 LPDIRECTSOUND8
*ppDS
)
1071 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
1073 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1074 !IsEqualIID(riid
, &IID_IDirectSound
) &&
1075 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
1077 return E_NOINTERFACE
;
1080 /* Get dsound configuration */
1081 setup_dsound_options();
1083 hr
= IDirectSoundImpl_Create(&pDS
);
1085 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1087 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1089 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1090 IDirectSound8_Release(pDS
);
1093 WARN("IDirectSoundImpl_Create failed\n");
1100 /*******************************************************************************
1101 * DirectSoundCreate8 (DSOUND.11)
1103 * Creates and initializes a DirectSound8 interface.
1106 * lpcGUID [I] Address of the GUID that identifies the sound device.
1107 * ppDS [O] Address of a variable to receive the interface pointer.
1108 * pUnkOuter [I] Must be NULL.
1112 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1113 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1115 HRESULT WINAPI
DirectSoundCreate8(
1117 LPDIRECTSOUND8
*ppDS
,
1118 IUnknown
*pUnkOuter
)
1123 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1126 WARN("invalid parameter: ppDS == NULL\n");
1127 return DSERR_INVALIDPARAM
;
1130 if (pUnkOuter
!= NULL
) {
1131 WARN("invalid parameter: pUnkOuter != NULL\n");
1133 return DSERR_INVALIDPARAM
;
1136 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
1138 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1140 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1141 IDirectSound8_Release(pDS
);
1153 /*******************************************************************************
1156 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1158 DirectSoundDevice
* device
;
1159 TRACE("(%p)\n", ppDevice
);
1161 /* Allocate memory */
1162 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1163 if (device
== NULL
) {
1164 WARN("out of memory\n");
1165 return DSERR_OUTOFMEMORY
;
1169 device
->driver
= NULL
;
1170 device
->priolevel
= DSSCL_NORMAL
;
1171 device
->fraglen
= 0;
1172 device
->hwbuf
= NULL
;
1173 device
->buffer
= NULL
;
1175 device
->writelead
= 0;
1176 device
->state
= STATE_STOPPED
;
1177 device
->nrofbuffers
= 0;
1178 device
->buffers
= NULL
;
1179 device
->primary
= NULL
;
1180 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
1181 device
->tmp_buffer
= NULL
;
1182 device
->tmp_buffer_len
= 0;
1184 /* 3D listener initial parameters */
1185 device
->listener
= NULL
;
1186 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1187 device
->ds3dl
.vPosition
.x
= 0.0;
1188 device
->ds3dl
.vPosition
.y
= 0.0;
1189 device
->ds3dl
.vPosition
.z
= 0.0;
1190 device
->ds3dl
.vVelocity
.x
= 0.0;
1191 device
->ds3dl
.vVelocity
.y
= 0.0;
1192 device
->ds3dl
.vVelocity
.z
= 0.0;
1193 device
->ds3dl
.vOrientFront
.x
= 0.0;
1194 device
->ds3dl
.vOrientFront
.y
= 0.0;
1195 device
->ds3dl
.vOrientFront
.z
= 1.0;
1196 device
->ds3dl
.vOrientTop
.x
= 0.0;
1197 device
->ds3dl
.vOrientTop
.y
= 1.0;
1198 device
->ds3dl
.vOrientTop
.z
= 0.0;
1199 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1200 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1201 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1203 device
->prebuf
= ds_snd_queue_max
;
1204 device
->guid
= GUID_NULL
;
1206 /* Set default wave format (may need it for waveOutOpen) */
1207 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1208 if (device
->pwfx
== NULL
) {
1209 WARN("out of memory\n");
1210 HeapFree(GetProcessHeap(),0,device
);
1211 return DSERR_OUTOFMEMORY
;
1214 /* We rely on the sound driver to return the actual sound format of
1215 * the device if it does not support 22050x8x2 and is given the
1216 * WAVE_DIRECTSOUND flag.
1218 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1219 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1220 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1221 device
->pwfx
->nChannels
= 2;
1222 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1223 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1224 device
->pwfx
->cbSize
= 0;
1226 InitializeCriticalSection(&(device
->mixlock
));
1227 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
1229 RtlInitializeResource(&(device
->buffer_list_lock
));
1236 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1238 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1239 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1243 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1246 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1247 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1250 timeKillEvent(device
->timerID
);
1251 timeEndPeriod(DS_TIME_RES
);
1253 /* The kill event should have allowed the timer process to expire
1254 * but try to grab the lock just in case. Can't hold lock because
1255 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1256 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1257 RtlReleaseResource(&(device
->buffer_list_lock
));
1259 /* It is allowed to release this object even when buffers are playing */
1260 if (device
->buffers
) {
1261 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1262 for( i
=0;i
<device
->nrofbuffers
;i
++)
1263 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1266 if (device
->primary
) {
1267 WARN("primary buffer not released\n");
1268 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1271 hr
= DSOUND_PrimaryDestroy(device
);
1273 WARN("DSOUND_PrimaryDestroy failed\n");
1276 IDsDriver_Close(device
->driver
);
1278 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1279 waveOutClose(device
->hwo
);
1282 IDsDriver_Release(device
->driver
);
1284 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1286 HeapFree(GetProcessHeap(),0,device
->tmp_buffer
);
1287 HeapFree(GetProcessHeap(),0,device
->buffer
);
1288 RtlDeleteResource(&device
->buffer_list_lock
);
1289 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1290 DeleteCriticalSection(&device
->mixlock
);
1291 HeapFree(GetProcessHeap(),0,device
);
1292 TRACE("(%p) released\n", device
);
1297 HRESULT
DirectSoundDevice_GetCaps(
1298 DirectSoundDevice
* device
,
1301 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1303 if (device
== NULL
) {
1304 WARN("not initialized\n");
1305 return DSERR_UNINITIALIZED
;
1308 if (lpDSCaps
== NULL
) {
1309 WARN("invalid parameter: lpDSCaps = NULL\n");
1310 return DSERR_INVALIDPARAM
;
1313 /* check if there is enough room */
1314 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1315 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1316 return DSERR_INVALIDPARAM
;
1319 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1320 if (TRACE_ON(dsound
)) {
1321 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1322 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1325 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1326 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1327 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1328 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1329 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1330 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1331 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1332 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1333 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1334 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1335 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1336 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1337 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1338 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1339 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1340 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1341 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1342 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1344 /* driver doesn't have these */
1345 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1346 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1351 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1355 BOOLEAN found
= FALSE
;
1357 DirectSoundDevice
* device
= *ppDevice
;
1358 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1360 if (*ppDevice
!= NULL
) {
1361 WARN("already initialized\n");
1362 return DSERR_ALREADYINITIALIZED
;
1365 /* Default device? */
1366 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1367 lpcGUID
= &DSDEVID_DefaultPlayback
;
1369 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1370 WARN("invalid parameter: lpcGUID\n");
1371 return DSERR_INVALIDPARAM
;
1374 /* Enumerate WINMM audio devices and find the one we want */
1375 wodn
= waveOutGetNumDevs();
1377 WARN("no driver\n");
1378 return DSERR_NODRIVER
;
1381 for (wod
=0; wod
<wodn
; wod
++) {
1382 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1388 if (found
== FALSE
) {
1389 WARN("No device found matching given ID!\n");
1390 return DSERR_NODRIVER
;
1393 if (DSOUND_renderer
[wod
]) {
1394 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1395 device
= DSOUND_renderer
[wod
];
1396 DirectSoundDevice_AddRef(device
);
1400 ERR("device GUID doesn't match\n");
1405 hr
= DirectSoundDevice_Create(&device
);
1407 WARN("DirectSoundDevice_Create failed\n");
1413 device
->guid
= devGUID
;
1414 device
->driver
= NULL
;
1416 device
->drvdesc
.dnDevNode
= wod
;
1417 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1420 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1424 if (device
->driver
) {
1425 /* the driver is now open, so it's now allowed to call GetCaps */
1426 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1428 WARN("IDsDriver_GetCaps failed\n");
1433 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1435 WARN("waveOutGetDevCaps failed\n");
1438 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1439 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1440 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1441 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1442 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1443 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1444 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1445 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1447 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1448 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1449 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1450 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1451 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1452 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1453 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1455 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1456 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1457 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1458 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1459 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1460 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1461 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1463 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1464 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1465 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1466 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1467 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1468 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1469 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1472 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1473 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1474 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1475 device
->drvcaps
.dwPrimaryBuffers
= 1;
1478 hr
= DSOUND_PrimaryCreate(device
);
1480 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1483 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1484 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1485 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1486 if (triggertime
< time
.wPeriodMin
)
1487 triggertime
= time
.wPeriodMin
;
1488 if (res
< time
.wPeriodMin
)
1489 res
= time
.wPeriodMin
;
1490 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1491 WARN("Could not set minimum resolution, don't expect sound\n");
1492 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1495 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1496 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
);
1497 if (!id
) ERR("Could not create timer, sound playback will not occur\n");
1499 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= id
;
1501 WARN("DSOUND_PrimaryCreate failed\n");
1507 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1508 DirectSoundDevice
* device
,
1509 LPCDSBUFFERDESC dsbd
,
1510 LPLPDIRECTSOUNDBUFFER ppdsb
,
1514 HRESULT hres
= DS_OK
;
1515 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1517 if (device
== NULL
) {
1518 WARN("not initialized\n");
1519 return DSERR_UNINITIALIZED
;
1523 WARN("invalid parameter: dsbd == NULL\n");
1524 return DSERR_INVALIDPARAM
;
1527 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1528 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1529 WARN("invalid parameter: dsbd\n");
1530 return DSERR_INVALIDPARAM
;
1533 if (ppdsb
== NULL
) {
1534 WARN("invalid parameter: ppdsb == NULL\n");
1535 return DSERR_INVALIDPARAM
;
1538 if (TRACE_ON(dsound
)) {
1539 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1540 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1541 _dump_DSBCAPS(dsbd
->dwFlags
);
1543 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1544 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1547 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1548 if (dsbd
->lpwfxFormat
!= NULL
) {
1549 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1550 "primary buffer\n");
1551 return DSERR_INVALIDPARAM
;
1554 if (device
->primary
) {
1555 WARN("Primary Buffer already created\n");
1556 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1557 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1559 device
->dsbd
= *dsbd
;
1560 device
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1562 device
->dsbd
.dwFlags
|= DSBCAPS_LOCHARDWARE
;
1563 else device
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1564 hres
= PrimaryBufferImpl_Create(device
, (PrimaryBufferImpl
**)&(device
->primary
), &(device
->dsbd
));
1565 if (device
->primary
) {
1566 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1567 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1569 WARN("PrimaryBufferImpl_Create failed\n");
1572 IDirectSoundBufferImpl
* dsb
;
1574 if (dsbd
->lpwfxFormat
== NULL
) {
1575 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1576 "secondary buffer\n");
1577 return DSERR_INVALIDPARAM
;
1580 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1581 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1582 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1583 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1584 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1585 dsbd
->lpwfxFormat
->nBlockAlign
,
1586 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1588 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1589 WARN("invalid parameter: 3D buffer format must be mono\n");
1590 return DSERR_INVALIDPARAM
;
1593 hres
= IDirectSoundBufferImpl_Create(device
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
1595 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1597 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1598 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
1600 WARN("SecondaryBufferImpl_Create failed\n");
1602 WARN("IDirectSoundBufferImpl_Create failed\n");
1608 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1609 DirectSoundDevice
* device
,
1610 LPDIRECTSOUNDBUFFER psb
,
1611 LPLPDIRECTSOUNDBUFFER ppdsb
)
1613 HRESULT hres
= DS_OK
;
1614 IDirectSoundBufferImpl
* dsb
;
1615 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1617 if (device
== NULL
) {
1618 WARN("not initialized\n");
1619 return DSERR_UNINITIALIZED
;
1623 WARN("invalid parameter: psb == NULL\n");
1624 return DSERR_INVALIDPARAM
;
1627 if (ppdsb
== NULL
) {
1628 WARN("invalid parameter: ppdsb == NULL\n");
1629 return DSERR_INVALIDPARAM
;
1632 /* make sure we have a secondary buffer */
1633 if ((PrimaryBufferImpl
*)psb
== device
->primary
) {
1634 WARN("trying to duplicate primary buffer\n");
1636 return DSERR_INVALIDCALL
;
1639 /* duplicate the actual buffer implementation */
1640 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
,
1641 ((SecondaryBufferImpl
*)psb
)->dsb
);
1643 if (hres
== DS_OK
) {
1644 /* create a new secondary buffer using the new implementation */
1645 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1647 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1648 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
1650 WARN("SecondaryBufferImpl_Create failed\n");
1651 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)dsb
);
1652 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8
)dsb
);
1659 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1660 DirectSoundDevice
* device
,
1664 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1666 if (device
== NULL
) {
1667 WARN("not initialized\n");
1668 return DSERR_UNINITIALIZED
;
1671 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1672 WARN("level=%s not fully supported\n",
1673 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1676 device
->priolevel
= level
;
1680 HRESULT
DirectSoundDevice_Compact(
1681 DirectSoundDevice
* device
)
1683 TRACE("(%p)\n", device
);
1685 if (device
== NULL
) {
1686 WARN("not initialized\n");
1687 return DSERR_UNINITIALIZED
;
1690 if (device
->priolevel
< DSSCL_PRIORITY
) {
1691 WARN("incorrect priority level\n");
1692 return DSERR_PRIOLEVELNEEDED
;
1698 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1699 DirectSoundDevice
* device
,
1700 LPDWORD lpdwSpeakerConfig
)
1702 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1704 if (device
== NULL
) {
1705 WARN("not initialized\n");
1706 return DSERR_UNINITIALIZED
;
1709 if (lpdwSpeakerConfig
== NULL
) {
1710 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1711 return DSERR_INVALIDPARAM
;
1714 WARN("not fully functional\n");
1715 *lpdwSpeakerConfig
= device
->speaker_config
;
1719 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1720 DirectSoundDevice
* device
,
1723 TRACE("(%p,0x%08x)\n",device
,config
);
1725 if (device
== NULL
) {
1726 WARN("not initialized\n");
1727 return DSERR_UNINITIALIZED
;
1730 device
->speaker_config
= config
;
1731 WARN("not fully functional\n");
1735 static HRESULT
DirectSoundDevice_VerifyCertification(
1736 DirectSoundDevice
* device
,
1737 LPDWORD pdwCertified
)
1739 TRACE("(%p, %p)\n",device
,pdwCertified
);
1741 if (device
== NULL
) {
1742 WARN("not initialized\n");
1743 return DSERR_UNINITIALIZED
;
1746 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1747 *pdwCertified
= DS_CERTIFIED
;
1749 *pdwCertified
= DS_UNCERTIFIED
;
1755 * Add secondary buffer to buffer list.
1756 * Gets exclusive access to buffer for writing.
1758 HRESULT
DirectSoundDevice_AddBuffer(
1759 DirectSoundDevice
* device
,
1760 IDirectSoundBufferImpl
* pDSB
)
1762 IDirectSoundBufferImpl
**newbuffers
;
1765 TRACE("(%p, %p)\n", device
, pDSB
);
1767 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1769 if (device
->buffers
)
1770 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1772 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1775 device
->buffers
= newbuffers
;
1776 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1777 device
->nrofbuffers
++;
1778 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1780 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1781 hr
= DSERR_OUTOFMEMORY
;
1784 RtlReleaseResource(&(device
->buffer_list_lock
));
1790 * Remove secondary buffer from buffer list.
1791 * Gets exclusive access to buffer for writing.
1793 HRESULT
DirectSoundDevice_RemoveBuffer(
1794 DirectSoundDevice
* device
,
1795 IDirectSoundBufferImpl
* pDSB
)
1800 TRACE("(%p, %p)\n", device
, pDSB
);
1802 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1804 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1805 if (device
->buffers
[i
] == pDSB
)
1808 if (i
< device
->nrofbuffers
) {
1809 /* Put the last buffer of the list in the (now empty) position */
1810 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1811 device
->nrofbuffers
--;
1812 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1813 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1816 if (device
->nrofbuffers
== 0) {
1817 HeapFree(GetProcessHeap(),0,device
->buffers
);
1818 device
->buffers
= NULL
;
1821 RtlReleaseResource(&(device
->buffer_list_lock
));