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
27 #define NONAMELESSSTRUCT
28 #define NONAMELESSUNION
38 #include "wine/debug.h"
40 #include "dsound_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
44 /*****************************************************************************
45 * IDirectSound COM components
47 struct IDirectSound_IUnknown
{
48 const IUnknownVtbl
*lpVtbl
;
53 static HRESULT
IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
55 struct IDirectSound_IDirectSound
{
56 const IDirectSoundVtbl
*lpVtbl
;
61 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
63 /*****************************************************************************
64 * IDirectSound8 COM components
66 struct IDirectSound8_IUnknown
{
67 const IUnknownVtbl
*lpVtbl
;
72 static HRESULT
IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
73 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
75 struct IDirectSound8_IDirectSound
{
76 const IDirectSoundVtbl
*lpVtbl
;
81 static HRESULT
IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
82 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
84 struct IDirectSound8_IDirectSound8
{
85 const IDirectSound8Vtbl
*lpVtbl
;
90 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
91 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
93 /*****************************************************************************
94 * IDirectSound implementation structure
96 struct IDirectSoundImpl
100 DirectSoundDevice
*device
;
106 static HRESULT
IDirectSoundImpl_Create(LPDIRECTSOUND8
* ppds
);
108 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
109 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
111 const char * dumpCooperativeLevel(DWORD level
)
113 #define LE(x) case x: return #x
118 LE(DSSCL_WRITEPRIMARY
);
121 return wine_dbg_sprintf("Unknown(%08x)", level
);
124 static void _dump_DSCAPS(DWORD xmask
) {
129 #define FE(x) { x, #x },
130 FE(DSCAPS_PRIMARYMONO
)
131 FE(DSCAPS_PRIMARYSTEREO
)
132 FE(DSCAPS_PRIMARY8BIT
)
133 FE(DSCAPS_PRIMARY16BIT
)
134 FE(DSCAPS_CONTINUOUSRATE
)
135 FE(DSCAPS_EMULDRIVER
)
137 FE(DSCAPS_SECONDARYMONO
)
138 FE(DSCAPS_SECONDARYSTEREO
)
139 FE(DSCAPS_SECONDARY8BIT
)
140 FE(DSCAPS_SECONDARY16BIT
)
145 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
146 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
147 TRACE("%s ",flags
[i
].name
);
150 static void _dump_DSBCAPS(DWORD xmask
) {
155 #define FE(x) { x, #x },
156 FE(DSBCAPS_PRIMARYBUFFER
)
158 FE(DSBCAPS_LOCHARDWARE
)
159 FE(DSBCAPS_LOCSOFTWARE
)
161 FE(DSBCAPS_CTRLFREQUENCY
)
163 FE(DSBCAPS_CTRLVOLUME
)
164 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
165 FE(DSBCAPS_STICKYFOCUS
)
166 FE(DSBCAPS_GLOBALFOCUS
)
167 FE(DSBCAPS_GETCURRENTPOSITION2
)
168 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
173 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
174 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
175 TRACE("%s ",flags
[i
].name
);
178 /*******************************************************************************
179 * IDirectSoundImpl_DirectSound
181 static HRESULT
DSOUND_QueryInterface(
182 LPDIRECTSOUND8 iface
,
186 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
187 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
190 WARN("invalid parameter\n");
194 if (IsEqualIID(riid
, &IID_IUnknown
)) {
195 if (!This
->pUnknown
) {
196 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
197 if (!This
->pUnknown
) {
198 WARN("IDirectSound_IUnknown_Create() failed\n");
200 return E_NOINTERFACE
;
203 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
204 *ppobj
= This
->pUnknown
;
206 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
208 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
210 WARN("IDirectSound_IDirectSound_Create() failed\n");
212 return E_NOINTERFACE
;
215 IDirectSound_IDirectSound_AddRef(This
->pDS
);
221 WARN("Unknown IID %s\n",debugstr_guid(riid
));
222 return E_NOINTERFACE
;
225 static HRESULT
DSOUND_QueryInterface8(
226 LPDIRECTSOUND8 iface
,
230 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
231 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
234 WARN("invalid parameter\n");
238 if (IsEqualIID(riid
, &IID_IUnknown
)) {
239 if (!This
->pUnknown
) {
240 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
241 if (!This
->pUnknown
) {
242 WARN("IDirectSound8_IUnknown_Create() failed\n");
244 return E_NOINTERFACE
;
247 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
248 *ppobj
= This
->pUnknown
;
250 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
252 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
254 WARN("IDirectSound8_IDirectSound_Create() failed\n");
256 return E_NOINTERFACE
;
259 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
262 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
264 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
266 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
268 return E_NOINTERFACE
;
271 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
277 WARN("Unknown IID %s\n",debugstr_guid(riid
));
278 return E_NOINTERFACE
;
281 static ULONG
IDirectSoundImpl_AddRef(
282 LPDIRECTSOUND8 iface
)
284 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
285 ULONG ref
= InterlockedIncrement(&(This
->ref
));
286 TRACE("(%p) ref was %d\n", This
, ref
- 1);
290 static ULONG
IDirectSoundImpl_Release(
291 LPDIRECTSOUND8 iface
)
293 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
294 ULONG ref
= InterlockedDecrement(&(This
->ref
));
295 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
299 DirectSoundDevice_Release(This
->device
);
300 HeapFree(GetProcessHeap(),0,This
);
301 TRACE("(%p) released\n", This
);
306 static HRESULT
IDirectSoundImpl_Create(
307 LPDIRECTSOUND8
* ppDS
)
309 IDirectSoundImpl
* pDS
;
310 TRACE("(%p)\n",ppDS
);
312 /* Allocate memory */
313 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
315 WARN("out of memory\n");
317 return DSERR_OUTOFMEMORY
;
323 *ppDS
= (LPDIRECTSOUND8
)pDS
;
328 /*******************************************************************************
329 * IDirectSound_IUnknown
331 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
336 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
337 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
338 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
341 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
344 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
345 ULONG ref
= InterlockedIncrement(&(This
->ref
));
346 TRACE("(%p) ref was %d\n", This
, ref
- 1);
350 static ULONG WINAPI
IDirectSound_IUnknown_Release(
353 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
354 ULONG ref
= InterlockedDecrement(&(This
->ref
));
355 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
357 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
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
*)This
->pds
)->pDS
= NULL
;
437 IDirectSoundImpl_Release(This
->pds
);
438 HeapFree(GetProcessHeap(), 0, This
);
439 TRACE("(%p) released\n", This
);
444 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
446 LPCDSBUFFERDESC dsbd
,
447 LPLPDIRECTSOUNDBUFFER ppdsb
,
450 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
451 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
452 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,FALSE
);
455 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
459 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
460 TRACE("(%p,%p)\n",This
,lpDSCaps
);
461 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
464 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
466 LPDIRECTSOUNDBUFFER psb
,
467 LPLPDIRECTSOUNDBUFFER ppdsb
)
469 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
470 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
471 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
474 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
479 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
480 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
481 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
484 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
487 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
488 TRACE("(%p)\n", This
);
489 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
492 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
494 LPDWORD lpdwSpeakerConfig
)
496 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
497 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
498 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
501 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
505 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
506 TRACE("(%p,0x%08x)\n",This
,config
);
507 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
510 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
514 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
515 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
516 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
519 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
521 IDirectSound_IDirectSound_QueryInterface
,
522 IDirectSound_IDirectSound_AddRef
,
523 IDirectSound_IDirectSound_Release
,
524 IDirectSound_IDirectSound_CreateSoundBuffer
,
525 IDirectSound_IDirectSound_GetCaps
,
526 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
527 IDirectSound_IDirectSound_SetCooperativeLevel
,
528 IDirectSound_IDirectSound_Compact
,
529 IDirectSound_IDirectSound_GetSpeakerConfig
,
530 IDirectSound_IDirectSound_SetSpeakerConfig
,
531 IDirectSound_IDirectSound_Initialize
534 static HRESULT
IDirectSound_IDirectSound_Create(
536 LPDIRECTSOUND
* ppds
)
538 IDirectSound_IDirectSound
* pdsds
;
539 TRACE("(%p,%p)\n",pds
,ppds
);
542 ERR("invalid parameter: ppds == NULL\n");
543 return DSERR_INVALIDPARAM
;
547 ERR("invalid parameter: pds == NULL\n");
549 return DSERR_INVALIDPARAM
;
552 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
554 WARN("out of memory\n");
556 return DSERR_OUTOFMEMORY
;
559 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
563 IDirectSoundImpl_AddRef(pds
);
564 *ppds
= (LPDIRECTSOUND
)pdsds
;
569 /*******************************************************************************
570 * IDirectSound8_IUnknown
572 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
577 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
578 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
579 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
582 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
585 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
586 ULONG ref
= InterlockedIncrement(&(This
->ref
));
587 TRACE("(%p) ref was %d\n", This
, ref
- 1);
591 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
594 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
595 ULONG ref
= InterlockedDecrement(&(This
->ref
));
596 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
598 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
599 IDirectSoundImpl_Release(This
->pds
);
600 HeapFree(GetProcessHeap(), 0, This
);
601 TRACE("(%p) released\n", This
);
606 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
608 IDirectSound8_IUnknown_QueryInterface
,
609 IDirectSound8_IUnknown_AddRef
,
610 IDirectSound8_IUnknown_Release
613 static HRESULT
IDirectSound8_IUnknown_Create(
617 IDirectSound8_IUnknown
* pdsunk
;
618 TRACE("(%p,%p)\n",pds
,ppunk
);
621 ERR("invalid parameter: ppunk == NULL\n");
622 return DSERR_INVALIDPARAM
;
626 ERR("invalid parameter: pds == NULL\n");
628 return DSERR_INVALIDPARAM
;
631 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
632 if (pdsunk
== NULL
) {
633 WARN("out of memory\n");
635 return DSERR_OUTOFMEMORY
;
638 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
642 IDirectSoundImpl_AddRef(pds
);
643 *ppunk
= (LPUNKNOWN
)pdsunk
;
648 /*******************************************************************************
649 * IDirectSound8_IDirectSound
651 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
656 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
657 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
658 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
661 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
664 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
665 ULONG ref
= InterlockedIncrement(&(This
->ref
));
666 TRACE("(%p) ref was %d\n", This
, ref
- 1);
670 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
673 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
674 ULONG ref
= InterlockedDecrement(&(This
->ref
));
675 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
677 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
678 IDirectSoundImpl_Release(This
->pds
);
679 HeapFree(GetProcessHeap(), 0, This
);
680 TRACE("(%p) released\n", This
);
685 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
687 LPCDSBUFFERDESC dsbd
,
688 LPLPDIRECTSOUNDBUFFER ppdsb
,
691 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
692 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
693 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
696 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
700 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
701 TRACE("(%p,%p)\n",This
,lpDSCaps
);
702 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
705 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
707 LPDIRECTSOUNDBUFFER psb
,
708 LPLPDIRECTSOUNDBUFFER ppdsb
)
710 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
711 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
712 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
715 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
720 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
721 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
722 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
725 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
728 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
729 TRACE("(%p)\n", This
);
730 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
733 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
735 LPDWORD lpdwSpeakerConfig
)
737 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
738 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
739 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
742 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
746 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
747 TRACE("(%p,0x%08x)\n",This
,config
);
748 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
751 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
755 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
756 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
757 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
760 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
762 IDirectSound8_IDirectSound_QueryInterface
,
763 IDirectSound8_IDirectSound_AddRef
,
764 IDirectSound8_IDirectSound_Release
,
765 IDirectSound8_IDirectSound_CreateSoundBuffer
,
766 IDirectSound8_IDirectSound_GetCaps
,
767 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
768 IDirectSound8_IDirectSound_SetCooperativeLevel
,
769 IDirectSound8_IDirectSound_Compact
,
770 IDirectSound8_IDirectSound_GetSpeakerConfig
,
771 IDirectSound8_IDirectSound_SetSpeakerConfig
,
772 IDirectSound8_IDirectSound_Initialize
775 static HRESULT
IDirectSound8_IDirectSound_Create(
777 LPDIRECTSOUND
* ppds
)
779 IDirectSound8_IDirectSound
* pdsds
;
780 TRACE("(%p,%p)\n",pds
,ppds
);
783 ERR("invalid parameter: ppds == NULL\n");
784 return DSERR_INVALIDPARAM
;
788 ERR("invalid parameter: pds == NULL\n");
790 return DSERR_INVALIDPARAM
;
793 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
795 WARN("out of memory\n");
797 return DSERR_OUTOFMEMORY
;
800 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
804 IDirectSoundImpl_AddRef(pds
);
805 *ppds
= (LPDIRECTSOUND
)pdsds
;
810 /*******************************************************************************
811 * IDirectSound8_IDirectSound8
813 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
814 LPDIRECTSOUND8 iface
,
818 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
819 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
820 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
823 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
824 LPDIRECTSOUND8 iface
)
826 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
827 ULONG ref
= InterlockedIncrement(&(This
->ref
));
828 TRACE("(%p) ref was %d\n", This
, ref
- 1);
832 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
833 LPDIRECTSOUND8 iface
)
835 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
836 ULONG ref
= InterlockedDecrement(&(This
->ref
));
837 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
839 ((IDirectSoundImpl
*)This
->pds
)->pDS8
= NULL
;
840 IDirectSoundImpl_Release(This
->pds
);
841 HeapFree(GetProcessHeap(), 0, This
);
842 TRACE("(%p) released\n", This
);
847 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
848 LPDIRECTSOUND8 iface
,
849 LPCDSBUFFERDESC dsbd
,
850 LPLPDIRECTSOUNDBUFFER ppdsb
,
853 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
854 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
855 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
858 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
859 LPDIRECTSOUND8 iface
,
862 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
863 TRACE("(%p,%p)\n",This
,lpDSCaps
);
864 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
867 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
868 LPDIRECTSOUND8 iface
,
869 LPDIRECTSOUNDBUFFER psb
,
870 LPLPDIRECTSOUNDBUFFER ppdsb
)
872 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
873 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
874 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
877 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
878 LPDIRECTSOUND8 iface
,
882 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
883 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
884 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
887 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
888 LPDIRECTSOUND8 iface
)
890 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
891 TRACE("(%p)\n", This
);
892 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
895 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
896 LPDIRECTSOUND8 iface
,
897 LPDWORD lpdwSpeakerConfig
)
899 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
900 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
901 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
904 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
905 LPDIRECTSOUND8 iface
,
908 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
909 TRACE("(%p,0x%08x)\n",This
,config
);
910 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
913 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
914 LPDIRECTSOUND8 iface
,
917 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
918 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
919 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
922 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
923 LPDIRECTSOUND8 iface
,
924 LPDWORD pdwCertified
)
926 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
927 TRACE("(%p, %p)\n", This
, pdwCertified
);
928 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
931 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
933 IDirectSound8_IDirectSound8_QueryInterface
,
934 IDirectSound8_IDirectSound8_AddRef
,
935 IDirectSound8_IDirectSound8_Release
,
936 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
937 IDirectSound8_IDirectSound8_GetCaps
,
938 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
939 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
940 IDirectSound8_IDirectSound8_Compact
,
941 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
942 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
943 IDirectSound8_IDirectSound8_Initialize
,
944 IDirectSound8_IDirectSound8_VerifyCertification
947 static HRESULT
IDirectSound8_IDirectSound8_Create(
949 LPDIRECTSOUND8
* ppds
)
951 IDirectSound8_IDirectSound8
* pdsds
;
952 TRACE("(%p,%p)\n",pds
,ppds
);
955 ERR("invalid parameter: ppds == NULL\n");
956 return DSERR_INVALIDPARAM
;
960 ERR("invalid parameter: pds == NULL\n");
962 return DSERR_INVALIDPARAM
;
965 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
967 WARN("out of memory\n");
969 return DSERR_OUTOFMEMORY
;
972 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
976 IDirectSoundImpl_AddRef(pds
);
977 *ppds
= (LPDIRECTSOUND8
)pdsds
;
982 HRESULT
DSOUND_Create(
988 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
990 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
991 !IsEqualIID(riid
, &IID_IDirectSound
)) {
993 return E_NOINTERFACE
;
996 /* Get dsound configuration */
997 setup_dsound_options();
999 hr
= IDirectSoundImpl_Create(&pDS
);
1001 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1003 IDirectSound_IDirectSound_AddRef(*ppDS
);
1005 WARN("IDirectSound_IDirectSound_Create failed\n");
1006 IDirectSound8_Release(pDS
);
1009 WARN("IDirectSoundImpl_Create failed\n");
1016 /*******************************************************************************
1017 * DirectSoundCreate (DSOUND.1)
1019 * Creates and initializes a DirectSound interface.
1022 * lpcGUID [I] Address of the GUID that identifies the sound device.
1023 * ppDS [O] Address of a variable to receive the interface pointer.
1024 * pUnkOuter [I] Must be NULL.
1028 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1029 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1031 HRESULT WINAPI
DirectSoundCreate(
1033 LPDIRECTSOUND
*ppDS
,
1034 IUnknown
*pUnkOuter
)
1039 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1042 WARN("invalid parameter: ppDS == NULL\n");
1043 return DSERR_INVALIDPARAM
;
1046 if (pUnkOuter
!= NULL
) {
1047 WARN("invalid parameter: pUnkOuter != NULL\n");
1049 return DSERR_INVALIDPARAM
;
1052 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
1054 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1056 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1057 IDirectSound_Release(pDS
);
1069 HRESULT
DSOUND_Create8(
1071 LPDIRECTSOUND8
*ppDS
)
1075 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
1077 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1078 !IsEqualIID(riid
, &IID_IDirectSound
) &&
1079 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
1081 return E_NOINTERFACE
;
1084 /* Get dsound configuration */
1085 setup_dsound_options();
1087 hr
= IDirectSoundImpl_Create(&pDS
);
1089 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1091 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1093 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1094 IDirectSound8_Release(pDS
);
1097 WARN("IDirectSoundImpl_Create failed\n");
1104 /*******************************************************************************
1105 * DirectSoundCreate8 (DSOUND.11)
1107 * Creates and initializes a DirectSound8 interface.
1110 * lpcGUID [I] Address of the GUID that identifies the sound device.
1111 * ppDS [O] Address of a variable to receive the interface pointer.
1112 * pUnkOuter [I] Must be NULL.
1116 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1117 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1119 HRESULT WINAPI
DirectSoundCreate8(
1121 LPDIRECTSOUND8
*ppDS
,
1122 IUnknown
*pUnkOuter
)
1127 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1130 WARN("invalid parameter: ppDS == NULL\n");
1131 return DSERR_INVALIDPARAM
;
1134 if (pUnkOuter
!= NULL
) {
1135 WARN("invalid parameter: pUnkOuter != NULL\n");
1137 return DSERR_INVALIDPARAM
;
1140 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
1142 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1144 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1145 IDirectSound8_Release(pDS
);
1157 /*******************************************************************************
1160 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1162 DirectSoundDevice
* device
;
1163 TRACE("(%p)\n", ppDevice
);
1165 /* Allocate memory */
1166 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1167 if (device
== NULL
) {
1168 WARN("out of memory\n");
1169 return DSERR_OUTOFMEMORY
;
1173 device
->priolevel
= DSSCL_NORMAL
;
1174 device
->state
= STATE_STOPPED
;
1175 device
->speaker_config
= DSSPEAKER_COMBINED(DSSPEAKER_STEREO
, DSSPEAKER_GEOMETRY_WIDE
);
1177 /* 3D listener initial parameters */
1178 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1179 device
->ds3dl
.vPosition
.x
= 0.0;
1180 device
->ds3dl
.vPosition
.y
= 0.0;
1181 device
->ds3dl
.vPosition
.z
= 0.0;
1182 device
->ds3dl
.vVelocity
.x
= 0.0;
1183 device
->ds3dl
.vVelocity
.y
= 0.0;
1184 device
->ds3dl
.vVelocity
.z
= 0.0;
1185 device
->ds3dl
.vOrientFront
.x
= 0.0;
1186 device
->ds3dl
.vOrientFront
.y
= 0.0;
1187 device
->ds3dl
.vOrientFront
.z
= 1.0;
1188 device
->ds3dl
.vOrientTop
.x
= 0.0;
1189 device
->ds3dl
.vOrientTop
.y
= 1.0;
1190 device
->ds3dl
.vOrientTop
.z
= 0.0;
1191 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1192 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1193 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1195 device
->prebuf
= ds_snd_queue_max
;
1196 device
->guid
= GUID_NULL
;
1198 /* Set default wave format (may need it for waveOutOpen) */
1199 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1200 if (device
->pwfx
== NULL
) {
1201 WARN("out of memory\n");
1202 HeapFree(GetProcessHeap(),0,device
);
1203 return DSERR_OUTOFMEMORY
;
1206 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1207 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1208 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1209 device
->pwfx
->nChannels
= 2;
1210 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1211 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1212 device
->pwfx
->cbSize
= 0;
1214 InitializeCriticalSection(&(device
->mixlock
));
1215 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
1217 RtlInitializeResource(&(device
->buffer_list_lock
));
1224 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1226 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1227 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1231 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1234 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1235 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1238 timeKillEvent(device
->timerID
);
1239 timeEndPeriod(DS_TIME_RES
);
1241 /* The kill event should have allowed the timer process to expire
1242 * but try to grab the lock just in case. Can't hold lock because
1243 * secondarybuffer_destroy also grabs the lock */
1244 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1245 RtlReleaseResource(&(device
->buffer_list_lock
));
1247 EnterCriticalSection(&DSOUND_renderers_lock
);
1248 list_remove(&device
->entry
);
1249 LeaveCriticalSection(&DSOUND_renderers_lock
);
1251 /* It is allowed to release this object even when buffers are playing */
1252 if (device
->buffers
) {
1253 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1254 for( i
=0;i
<device
->nrofbuffers
;i
++)
1255 secondarybuffer_destroy(device
->buffers
[i
]);
1258 if (device
->primary
) {
1259 WARN("primary buffer not released\n");
1260 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1263 hr
= DSOUND_PrimaryDestroy(device
);
1265 WARN("DSOUND_PrimaryDestroy failed\n");
1268 IAudioClient_Release(device
->client
);
1270 IAudioRenderClient_Release(device
->render
);
1272 IAudioClock_Release(device
->clock
);
1274 IAudioStreamVolume_Release(device
->volume
);
1276 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
1277 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
1278 HeapFree(GetProcessHeap(), 0, device
->buffer
);
1279 RtlDeleteResource(&device
->buffer_list_lock
);
1280 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1281 DeleteCriticalSection(&device
->mixlock
);
1282 HeapFree(GetProcessHeap(),0,device
);
1283 TRACE("(%p) released\n", device
);
1288 HRESULT
DirectSoundDevice_GetCaps(
1289 DirectSoundDevice
* device
,
1292 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1294 if (device
== NULL
) {
1295 WARN("not initialized\n");
1296 return DSERR_UNINITIALIZED
;
1299 if (lpDSCaps
== NULL
) {
1300 WARN("invalid parameter: lpDSCaps = NULL\n");
1301 return DSERR_INVALIDPARAM
;
1304 /* check if there is enough room */
1305 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1306 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1307 return DSERR_INVALIDPARAM
;
1310 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1311 if (TRACE_ON(dsound
)) {
1312 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1313 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1316 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1317 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1318 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1319 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1320 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1321 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1322 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1323 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1324 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1325 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1326 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1327 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1328 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1329 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1330 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1331 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1332 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1333 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1334 lpDSCaps
->dwUnlockTransferRateHwBuffers
= device
->drvcaps
.dwUnlockTransferRateHwBuffers
;
1335 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= device
->drvcaps
.dwPlayCpuOverheadSwBuffers
;
1340 BOOL
DSOUND_check_supported(IAudioClient
*client
, DWORD rate
,
1341 DWORD depth
, WORD channels
)
1343 WAVEFORMATEX fmt
, *junk
;
1346 fmt
.wFormatTag
= WAVE_FORMAT_PCM
;
1347 fmt
.nChannels
= channels
;
1348 fmt
.nSamplesPerSec
= rate
;
1349 fmt
.wBitsPerSample
= depth
;
1350 fmt
.nBlockAlign
= (channels
* depth
) / 8;
1351 fmt
.nAvgBytesPerSec
= rate
* fmt
.nBlockAlign
;
1354 hr
= IAudioClient_IsFormatSupported(client
, AUDCLNT_SHAREMODE_SHARED
, &fmt
, &junk
);
1356 CoTaskMemFree(junk
);
1361 UINT
DSOUND_create_timer(LPTIMECALLBACK cb
, DWORD_PTR user
)
1363 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1366 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1367 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1368 if (triggertime
< time
.wPeriodMin
)
1369 triggertime
= time
.wPeriodMin
;
1370 if (res
< time
.wPeriodMin
)
1371 res
= time
.wPeriodMin
;
1372 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1373 WARN("Could not set minimum resolution, don't expect sound\n");
1374 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1377 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1378 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
);
1380 ERR("Could not create timer, sound playback will not occur\n");
1385 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1389 DirectSoundDevice
*device
;
1390 IMMDevice
*mmdevice
;
1392 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1394 if (*ppDevice
!= NULL
) {
1395 WARN("already initialized\n");
1396 return DSERR_ALREADYINITIALIZED
;
1399 /* Default device? */
1400 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1401 lpcGUID
= &DSDEVID_DefaultPlayback
;
1403 if(IsEqualGUID(lpcGUID
, &DSDEVID_DefaultCapture
) ||
1404 IsEqualGUID(lpcGUID
, &DSDEVID_DefaultVoiceCapture
))
1405 return DSERR_NODRIVER
;
1407 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1408 WARN("invalid parameter: lpcGUID\n");
1409 return DSERR_INVALIDPARAM
;
1412 hr
= get_mmdevice(eRender
, &devGUID
, &mmdevice
);
1416 EnterCriticalSection(&DSOUND_renderers_lock
);
1418 LIST_FOR_EACH_ENTRY(device
, &DSOUND_renderers
, DirectSoundDevice
, entry
){
1419 if(IsEqualGUID(&device
->guid
, &devGUID
)){
1420 IMMDevice_Release(mmdevice
);
1421 DirectSoundDevice_AddRef(device
);
1423 LeaveCriticalSection(&DSOUND_renderers_lock
);
1428 hr
= DirectSoundDevice_Create(&device
);
1430 WARN("DirectSoundDevice_Create failed\n");
1431 IMMDevice_Release(mmdevice
);
1432 LeaveCriticalSection(&DSOUND_renderers_lock
);
1436 device
->mmdevice
= mmdevice
;
1437 device
->guid
= devGUID
;
1439 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1442 HeapFree(GetProcessHeap(), 0, device
);
1443 LeaveCriticalSection(&DSOUND_renderers_lock
);
1444 IMMDevice_Release(mmdevice
);
1445 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1449 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1451 if(DSOUND_check_supported(device
->client
, 11025, 8, 1) ||
1452 DSOUND_check_supported(device
->client
, 22050, 8, 1) ||
1453 DSOUND_check_supported(device
->client
, 44100, 8, 1) ||
1454 DSOUND_check_supported(device
->client
, 48000, 8, 1) ||
1455 DSOUND_check_supported(device
->client
, 96000, 8, 1))
1456 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYMONO
;
1458 if(DSOUND_check_supported(device
->client
, 11025, 16, 1) ||
1459 DSOUND_check_supported(device
->client
, 22050, 16, 1) ||
1460 DSOUND_check_supported(device
->client
, 44100, 16, 1) ||
1461 DSOUND_check_supported(device
->client
, 48000, 16, 1) ||
1462 DSOUND_check_supported(device
->client
, 96000, 16, 1))
1463 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYMONO
;
1465 if(DSOUND_check_supported(device
->client
, 11025, 8, 2) ||
1466 DSOUND_check_supported(device
->client
, 22050, 8, 2) ||
1467 DSOUND_check_supported(device
->client
, 44100, 8, 2) ||
1468 DSOUND_check_supported(device
->client
, 48000, 8, 2) ||
1469 DSOUND_check_supported(device
->client
, 96000, 8, 2))
1470 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYSTEREO
;
1472 if(DSOUND_check_supported(device
->client
, 11025, 16, 2) ||
1473 DSOUND_check_supported(device
->client
, 22050, 16, 2) ||
1474 DSOUND_check_supported(device
->client
, 44100, 16, 2) ||
1475 DSOUND_check_supported(device
->client
, 48000, 16, 2) ||
1476 DSOUND_check_supported(device
->client
, 96000, 16, 2))
1477 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYSTEREO
;
1479 /* the dsound mixer supports all of the following */
1480 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARY8BIT
| DSCAPS_SECONDARY16BIT
;
1481 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARYMONO
| DSCAPS_SECONDARYSTEREO
;
1482 device
->drvcaps
.dwFlags
|= DSCAPS_CONTINUOUSRATE
;
1484 device
->drvcaps
.dwPrimaryBuffers
= 1;
1485 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1486 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1487 device
->drvcaps
.dwMaxHwMixingAllBuffers
= 1;
1488 device
->drvcaps
.dwMaxHwMixingStaticBuffers
= 1;
1489 device
->drvcaps
.dwMaxHwMixingStreamingBuffers
= 1;
1491 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1493 hr
= DSOUND_PrimaryCreate(device
);
1495 device
->timerID
= DSOUND_create_timer(DSOUND_timer
, (DWORD_PTR
)device
);
1497 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr
);
1500 list_add_tail(&DSOUND_renderers
, &device
->entry
);
1502 LeaveCriticalSection(&DSOUND_renderers_lock
);
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
;
1539 if (TRACE_ON(dsound
)) {
1540 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1541 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1542 _dump_DSBCAPS(dsbd
->dwFlags
);
1544 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1545 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1548 if (dsbd
->dwFlags
& DSBCAPS_LOCHARDWARE
&&
1549 !(dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
)) {
1550 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1554 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1555 if (dsbd
->lpwfxFormat
!= NULL
) {
1556 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1557 "primary buffer\n");
1558 return DSERR_INVALIDPARAM
;
1561 if (device
->primary
) {
1562 WARN("Primary Buffer already created\n");
1563 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1564 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1566 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1567 if (device
->primary
) {
1568 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1569 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1570 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1572 WARN("primarybuffer_create() failed\n");
1575 IDirectSoundBufferImpl
* dsb
;
1576 WAVEFORMATEXTENSIBLE
*pwfxe
;
1578 if (dsbd
->lpwfxFormat
== NULL
) {
1579 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1580 "secondary buffer\n");
1581 return DSERR_INVALIDPARAM
;
1583 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1585 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1587 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1588 return DSERR_CONTROLUNAVAIL
;
1590 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1592 /* check if cbSize is at least 22 bytes */
1593 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1595 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1596 return DSERR_INVALIDPARAM
;
1599 /* cbSize should be 22 bytes, with one possible exception */
1600 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1601 !((IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) || IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) &&
1602 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1604 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1605 return DSERR_CONTROLUNAVAIL
;
1608 if ((!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) && (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
1610 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1611 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1612 return DSERR_INVALIDPARAM
;
1614 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1616 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1617 return DSERR_INVALIDPARAM
;
1619 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1621 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1622 return DSERR_CONTROLUNAVAIL
;
1626 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1627 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1628 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1629 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1630 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1631 dsbd
->lpwfxFormat
->nBlockAlign
,
1632 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1634 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1635 WARN("invalid parameter: 3D buffer format must be mono\n");
1636 return DSERR_INVALIDPARAM
;
1639 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1641 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1643 WARN("IDirectSoundBufferImpl_Create failed\n");
1649 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1650 DirectSoundDevice
* device
,
1651 LPDIRECTSOUNDBUFFER psb
,
1652 LPLPDIRECTSOUNDBUFFER ppdsb
)
1654 HRESULT hres
= DS_OK
;
1655 IDirectSoundBufferImpl
* dsb
;
1656 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1658 if (device
== NULL
) {
1659 WARN("not initialized\n");
1660 return DSERR_UNINITIALIZED
;
1664 WARN("invalid parameter: psb == NULL\n");
1665 return DSERR_INVALIDPARAM
;
1668 if (ppdsb
== NULL
) {
1669 WARN("invalid parameter: ppdsb == NULL\n");
1670 return DSERR_INVALIDPARAM
;
1673 /* make sure we have a secondary buffer */
1674 if (psb
== (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
) {
1675 WARN("trying to duplicate primary buffer\n");
1677 return DSERR_INVALIDCALL
;
1680 /* duplicate the actual buffer implementation */
1681 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
, (IDirectSoundBufferImpl
*)psb
);
1683 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1685 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1690 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1691 DirectSoundDevice
* device
,
1695 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1697 if (device
== NULL
) {
1698 WARN("not initialized\n");
1699 return DSERR_UNINITIALIZED
;
1702 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1703 WARN("level=%s not fully supported\n",
1704 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1707 device
->priolevel
= level
;
1711 HRESULT
DirectSoundDevice_Compact(
1712 DirectSoundDevice
* device
)
1714 TRACE("(%p)\n", device
);
1716 if (device
== NULL
) {
1717 WARN("not initialized\n");
1718 return DSERR_UNINITIALIZED
;
1721 if (device
->priolevel
< DSSCL_PRIORITY
) {
1722 WARN("incorrect priority level\n");
1723 return DSERR_PRIOLEVELNEEDED
;
1729 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1730 DirectSoundDevice
* device
,
1731 LPDWORD lpdwSpeakerConfig
)
1733 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1735 if (device
== NULL
) {
1736 WARN("not initialized\n");
1737 return DSERR_UNINITIALIZED
;
1740 if (lpdwSpeakerConfig
== NULL
) {
1741 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1742 return DSERR_INVALIDPARAM
;
1745 WARN("not fully functional\n");
1746 *lpdwSpeakerConfig
= device
->speaker_config
;
1750 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1751 DirectSoundDevice
* device
,
1754 TRACE("(%p,0x%08x)\n",device
,config
);
1756 if (device
== NULL
) {
1757 WARN("not initialized\n");
1758 return DSERR_UNINITIALIZED
;
1761 device
->speaker_config
= config
;
1762 WARN("not fully functional\n");
1766 HRESULT
DirectSoundDevice_VerifyCertification(
1767 DirectSoundDevice
* device
,
1768 LPDWORD pdwCertified
)
1770 TRACE("(%p, %p)\n",device
,pdwCertified
);
1772 if (device
== NULL
) {
1773 WARN("not initialized\n");
1774 return DSERR_UNINITIALIZED
;
1777 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1778 *pdwCertified
= DS_CERTIFIED
;
1780 *pdwCertified
= DS_UNCERTIFIED
;
1786 * Add secondary buffer to buffer list.
1787 * Gets exclusive access to buffer for writing.
1789 HRESULT
DirectSoundDevice_AddBuffer(
1790 DirectSoundDevice
* device
,
1791 IDirectSoundBufferImpl
* pDSB
)
1793 IDirectSoundBufferImpl
**newbuffers
;
1796 TRACE("(%p, %p)\n", device
, pDSB
);
1798 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1800 if (device
->buffers
)
1801 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1803 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1806 device
->buffers
= newbuffers
;
1807 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1808 device
->nrofbuffers
++;
1809 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1811 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1812 hr
= DSERR_OUTOFMEMORY
;
1815 RtlReleaseResource(&(device
->buffer_list_lock
));
1821 * Remove secondary buffer from buffer list.
1822 * Gets exclusive access to buffer for writing.
1824 HRESULT
DirectSoundDevice_RemoveBuffer(
1825 DirectSoundDevice
* device
,
1826 IDirectSoundBufferImpl
* pDSB
)
1831 TRACE("(%p, %p)\n", device
, pDSB
);
1833 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1835 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1836 if (device
->buffers
[i
] == pDSB
)
1839 if (i
< device
->nrofbuffers
) {
1840 /* Put the last buffer of the list in the (now empty) position */
1841 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1842 device
->nrofbuffers
--;
1843 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1844 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1847 if (device
->nrofbuffers
== 0) {
1848 HeapFree(GetProcessHeap(),0,device
->buffers
);
1849 device
->buffers
= NULL
;
1852 RtlReleaseResource(&(device
->buffer_list_lock
));