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_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
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 /* We rely on the sound driver to return the actual sound format of
1207 * the device if it does not support 22050x8x2 and is given the
1208 * WAVE_DIRECTSOUND flag.
1210 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1211 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1212 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1213 device
->pwfx
->nChannels
= 2;
1214 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1215 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1216 device
->pwfx
->cbSize
= 0;
1218 InitializeCriticalSection(&(device
->mixlock
));
1219 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
1221 RtlInitializeResource(&(device
->buffer_list_lock
));
1228 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1230 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1231 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1235 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1238 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1239 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1242 timeKillEvent(device
->timerID
);
1243 timeEndPeriod(DS_TIME_RES
);
1245 /* The kill event should have allowed the timer process to expire
1246 * but try to grab the lock just in case. Can't hold lock because
1247 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1248 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1249 RtlReleaseResource(&(device
->buffer_list_lock
));
1251 EnterCriticalSection(&DSOUND_renderers_lock
);
1252 list_remove(&device
->entry
);
1253 LeaveCriticalSection(&DSOUND_renderers_lock
);
1255 /* It is allowed to release this object even when buffers are playing */
1256 if (device
->buffers
) {
1257 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1258 for( i
=0;i
<device
->nrofbuffers
;i
++)
1259 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1262 if (device
->primary
) {
1263 WARN("primary buffer not released\n");
1264 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1267 hr
= DSOUND_PrimaryDestroy(device
);
1269 WARN("DSOUND_PrimaryDestroy failed\n");
1272 IAudioClient_Release(device
->client
);
1274 IAudioRenderClient_Release(device
->render
);
1276 IAudioClock_Release(device
->clock
);
1278 IAudioStreamVolume_Release(device
->volume
);
1280 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
1281 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
1282 HeapFree(GetProcessHeap(), 0, device
->buffer
);
1283 RtlDeleteResource(&device
->buffer_list_lock
);
1284 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1285 DeleteCriticalSection(&device
->mixlock
);
1286 HeapFree(GetProcessHeap(),0,device
);
1287 TRACE("(%p) released\n", device
);
1292 HRESULT
DirectSoundDevice_GetCaps(
1293 DirectSoundDevice
* device
,
1296 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1298 if (device
== NULL
) {
1299 WARN("not initialized\n");
1300 return DSERR_UNINITIALIZED
;
1303 if (lpDSCaps
== NULL
) {
1304 WARN("invalid parameter: lpDSCaps = NULL\n");
1305 return DSERR_INVALIDPARAM
;
1308 /* check if there is enough room */
1309 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1310 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1311 return DSERR_INVALIDPARAM
;
1314 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1315 if (TRACE_ON(dsound
)) {
1316 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1317 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1320 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1321 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1322 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1323 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1324 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1325 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1326 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1327 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1328 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1329 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1330 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1331 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1332 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1333 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1334 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1335 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1336 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1337 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1338 lpDSCaps
->dwUnlockTransferRateHwBuffers
= device
->drvcaps
.dwUnlockTransferRateHwBuffers
;
1339 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= device
->drvcaps
.dwPlayCpuOverheadSwBuffers
;
1344 BOOL
DSOUND_check_supported(IAudioClient
*client
, DWORD rate
,
1345 DWORD depth
, WORD channels
)
1347 WAVEFORMATEX fmt
, *junk
;
1350 fmt
.wFormatTag
= WAVE_FORMAT_PCM
;
1351 fmt
.nChannels
= channels
;
1352 fmt
.nSamplesPerSec
= rate
;
1353 fmt
.wBitsPerSample
= depth
;
1354 fmt
.nBlockAlign
= (channels
* depth
) / 8;
1355 fmt
.nAvgBytesPerSec
= rate
* fmt
.nBlockAlign
;
1358 hr
= IAudioClient_IsFormatSupported(client
, AUDCLNT_SHAREMODE_SHARED
, &fmt
, &junk
);
1360 CoTaskMemFree(junk
);
1365 UINT
DSOUND_create_timer(LPTIMECALLBACK cb
, DWORD_PTR user
)
1367 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1370 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1371 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1372 if (triggertime
< time
.wPeriodMin
)
1373 triggertime
= time
.wPeriodMin
;
1374 if (res
< time
.wPeriodMin
)
1375 res
= time
.wPeriodMin
;
1376 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1377 WARN("Could not set minimum resolution, don't expect sound\n");
1378 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1381 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1382 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
);
1384 ERR("Could not create timer, sound playback will not occur\n");
1389 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1393 DirectSoundDevice
*device
;
1394 IMMDevice
*mmdevice
;
1396 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1398 if (*ppDevice
!= NULL
) {
1399 WARN("already initialized\n");
1400 return DSERR_ALREADYINITIALIZED
;
1403 /* Default device? */
1404 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1405 lpcGUID
= &DSDEVID_DefaultPlayback
;
1407 if(IsEqualGUID(lpcGUID
, &DSDEVID_DefaultCapture
) ||
1408 IsEqualGUID(lpcGUID
, &DSDEVID_DefaultVoiceCapture
))
1409 return DSERR_NODRIVER
;
1411 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1412 WARN("invalid parameter: lpcGUID\n");
1413 return DSERR_INVALIDPARAM
;
1416 hr
= get_mmdevice(eRender
, &devGUID
, &mmdevice
);
1420 EnterCriticalSection(&DSOUND_renderers_lock
);
1422 LIST_FOR_EACH_ENTRY(device
, &DSOUND_renderers
, DirectSoundDevice
, entry
){
1423 if(IsEqualGUID(&device
->guid
, &devGUID
)){
1424 IMMDevice_Release(mmdevice
);
1425 DirectSoundDevice_AddRef(device
);
1427 LeaveCriticalSection(&DSOUND_renderers_lock
);
1432 hr
= DirectSoundDevice_Create(&device
);
1434 WARN("DirectSoundDevice_Create failed\n");
1435 IMMDevice_Release(mmdevice
);
1436 LeaveCriticalSection(&DSOUND_renderers_lock
);
1440 device
->mmdevice
= mmdevice
;
1441 device
->guid
= devGUID
;
1443 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1446 HeapFree(GetProcessHeap(), 0, device
);
1447 LeaveCriticalSection(&DSOUND_renderers_lock
);
1448 IMMDevice_Release(mmdevice
);
1449 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1453 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1455 if(DSOUND_check_supported(device
->client
, 11025, 8, 1) ||
1456 DSOUND_check_supported(device
->client
, 22050, 8, 1) ||
1457 DSOUND_check_supported(device
->client
, 44100, 8, 1) ||
1458 DSOUND_check_supported(device
->client
, 48000, 8, 1) ||
1459 DSOUND_check_supported(device
->client
, 96000, 8, 1))
1460 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYMONO
;
1462 if(DSOUND_check_supported(device
->client
, 11025, 16, 1) ||
1463 DSOUND_check_supported(device
->client
, 22050, 16, 1) ||
1464 DSOUND_check_supported(device
->client
, 44100, 16, 1) ||
1465 DSOUND_check_supported(device
->client
, 48000, 16, 1) ||
1466 DSOUND_check_supported(device
->client
, 96000, 16, 1))
1467 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYMONO
;
1469 if(DSOUND_check_supported(device
->client
, 11025, 8, 2) ||
1470 DSOUND_check_supported(device
->client
, 22050, 8, 2) ||
1471 DSOUND_check_supported(device
->client
, 44100, 8, 2) ||
1472 DSOUND_check_supported(device
->client
, 48000, 8, 2) ||
1473 DSOUND_check_supported(device
->client
, 96000, 8, 2))
1474 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYSTEREO
;
1476 if(DSOUND_check_supported(device
->client
, 11025, 16, 2) ||
1477 DSOUND_check_supported(device
->client
, 22050, 16, 2) ||
1478 DSOUND_check_supported(device
->client
, 44100, 16, 2) ||
1479 DSOUND_check_supported(device
->client
, 48000, 16, 2) ||
1480 DSOUND_check_supported(device
->client
, 96000, 16, 2))
1481 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYSTEREO
;
1483 device
->drvcaps
.dwPrimaryBuffers
= 1;
1484 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1485 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1486 device
->drvcaps
.dwMaxHwMixingAllBuffers
= 1;
1487 device
->drvcaps
.dwMaxHwMixingStaticBuffers
= 1;
1488 device
->drvcaps
.dwMaxHwMixingStreamingBuffers
= 1;
1490 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1492 hr
= DSOUND_PrimaryCreate(device
);
1494 device
->timerID
= DSOUND_create_timer(DSOUND_timer
, (DWORD_PTR
)device
);
1496 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr
);
1499 list_add_tail(&DSOUND_renderers
, &device
->entry
);
1501 LeaveCriticalSection(&DSOUND_renderers_lock
);
1506 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1507 DirectSoundDevice
* device
,
1508 LPCDSBUFFERDESC dsbd
,
1509 LPLPDIRECTSOUNDBUFFER ppdsb
,
1513 HRESULT hres
= DS_OK
;
1514 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1516 if (device
== NULL
) {
1517 WARN("not initialized\n");
1518 return DSERR_UNINITIALIZED
;
1522 WARN("invalid parameter: dsbd == NULL\n");
1523 return DSERR_INVALIDPARAM
;
1526 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1527 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1528 WARN("invalid parameter: dsbd\n");
1529 return DSERR_INVALIDPARAM
;
1532 if (ppdsb
== NULL
) {
1533 WARN("invalid parameter: ppdsb == NULL\n");
1534 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_LOCHARDWARE
&&
1548 !(dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
)) {
1549 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1553 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1554 if (dsbd
->lpwfxFormat
!= NULL
) {
1555 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1556 "primary buffer\n");
1557 return DSERR_INVALIDPARAM
;
1560 if (device
->primary
) {
1561 WARN("Primary Buffer already created\n");
1562 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1563 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1565 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1566 if (device
->primary
) {
1567 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1568 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1569 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1571 WARN("primarybuffer_create() failed\n");
1574 IDirectSoundBufferImpl
* dsb
;
1575 WAVEFORMATEXTENSIBLE
*pwfxe
;
1577 if (dsbd
->lpwfxFormat
== NULL
) {
1578 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1579 "secondary buffer\n");
1580 return DSERR_INVALIDPARAM
;
1582 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1584 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1586 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1587 return DSERR_CONTROLUNAVAIL
;
1589 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1591 /* check if cbSize is at least 22 bytes */
1592 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1594 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1595 return DSERR_INVALIDPARAM
;
1598 /* cbSize should be 22 bytes, with one possible exception */
1599 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1600 !((IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) || IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) &&
1601 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1603 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1604 return DSERR_CONTROLUNAVAIL
;
1607 if ((!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) && (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
1609 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1610 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1611 return DSERR_INVALIDPARAM
;
1613 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1615 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1616 return DSERR_INVALIDPARAM
;
1618 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1620 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1621 return DSERR_CONTROLUNAVAIL
;
1625 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1626 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1627 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1628 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1629 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1630 dsbd
->lpwfxFormat
->nBlockAlign
,
1631 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1633 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1634 WARN("invalid parameter: 3D buffer format must be mono\n");
1635 return DSERR_INVALIDPARAM
;
1638 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1640 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1642 WARN("IDirectSoundBufferImpl_Create failed\n");
1648 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1649 DirectSoundDevice
* device
,
1650 LPDIRECTSOUNDBUFFER psb
,
1651 LPLPDIRECTSOUNDBUFFER ppdsb
)
1653 HRESULT hres
= DS_OK
;
1654 IDirectSoundBufferImpl
* dsb
;
1655 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1657 if (device
== NULL
) {
1658 WARN("not initialized\n");
1659 return DSERR_UNINITIALIZED
;
1663 WARN("invalid parameter: psb == NULL\n");
1664 return DSERR_INVALIDPARAM
;
1667 if (ppdsb
== NULL
) {
1668 WARN("invalid parameter: ppdsb == NULL\n");
1669 return DSERR_INVALIDPARAM
;
1672 /* make sure we have a secondary buffer */
1673 if (psb
== (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
) {
1674 WARN("trying to duplicate primary buffer\n");
1676 return DSERR_INVALIDCALL
;
1679 /* duplicate the actual buffer implementation */
1680 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
, (IDirectSoundBufferImpl
*)psb
);
1682 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1684 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1689 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1690 DirectSoundDevice
* device
,
1694 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1696 if (device
== NULL
) {
1697 WARN("not initialized\n");
1698 return DSERR_UNINITIALIZED
;
1701 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1702 WARN("level=%s not fully supported\n",
1703 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1706 device
->priolevel
= level
;
1710 HRESULT
DirectSoundDevice_Compact(
1711 DirectSoundDevice
* device
)
1713 TRACE("(%p)\n", device
);
1715 if (device
== NULL
) {
1716 WARN("not initialized\n");
1717 return DSERR_UNINITIALIZED
;
1720 if (device
->priolevel
< DSSCL_PRIORITY
) {
1721 WARN("incorrect priority level\n");
1722 return DSERR_PRIOLEVELNEEDED
;
1728 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1729 DirectSoundDevice
* device
,
1730 LPDWORD lpdwSpeakerConfig
)
1732 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1734 if (device
== NULL
) {
1735 WARN("not initialized\n");
1736 return DSERR_UNINITIALIZED
;
1739 if (lpdwSpeakerConfig
== NULL
) {
1740 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1741 return DSERR_INVALIDPARAM
;
1744 WARN("not fully functional\n");
1745 *lpdwSpeakerConfig
= device
->speaker_config
;
1749 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1750 DirectSoundDevice
* device
,
1753 TRACE("(%p,0x%08x)\n",device
,config
);
1755 if (device
== NULL
) {
1756 WARN("not initialized\n");
1757 return DSERR_UNINITIALIZED
;
1760 device
->speaker_config
= config
;
1761 WARN("not fully functional\n");
1765 HRESULT
DirectSoundDevice_VerifyCertification(
1766 DirectSoundDevice
* device
,
1767 LPDWORD pdwCertified
)
1769 TRACE("(%p, %p)\n",device
,pdwCertified
);
1771 if (device
== NULL
) {
1772 WARN("not initialized\n");
1773 return DSERR_UNINITIALIZED
;
1776 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1777 *pdwCertified
= DS_CERTIFIED
;
1779 *pdwCertified
= DS_UNCERTIFIED
;
1785 * Add secondary buffer to buffer list.
1786 * Gets exclusive access to buffer for writing.
1788 HRESULT
DirectSoundDevice_AddBuffer(
1789 DirectSoundDevice
* device
,
1790 IDirectSoundBufferImpl
* pDSB
)
1792 IDirectSoundBufferImpl
**newbuffers
;
1795 TRACE("(%p, %p)\n", device
, pDSB
);
1797 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1799 if (device
->buffers
)
1800 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1802 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1805 device
->buffers
= newbuffers
;
1806 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1807 device
->nrofbuffers
++;
1808 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1810 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1811 hr
= DSERR_OUTOFMEMORY
;
1814 RtlReleaseResource(&(device
->buffer_list_lock
));
1820 * Remove secondary buffer from buffer list.
1821 * Gets exclusive access to buffer for writing.
1823 HRESULT
DirectSoundDevice_RemoveBuffer(
1824 DirectSoundDevice
* device
,
1825 IDirectSoundBufferImpl
* pDSB
)
1830 TRACE("(%p, %p)\n", device
, pDSB
);
1832 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1834 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1835 if (device
->buffers
[i
] == pDSB
)
1838 if (i
< device
->nrofbuffers
) {
1839 /* Put the last buffer of the list in the (now empty) position */
1840 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1841 device
->nrofbuffers
--;
1842 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1843 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1846 if (device
->nrofbuffers
== 0) {
1847 HeapFree(GetProcessHeap(),0,device
->buffers
);
1848 device
->buffers
= NULL
;
1851 RtlReleaseResource(&(device
->buffer_list_lock
));