3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 * Copyright 2004 Robert Reif
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
38 #include "dsound_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
42 /*****************************************************************************
43 * IDirectSound COM components
45 struct IDirectSound_IUnknown
{
46 const IUnknownVtbl
*lpVtbl
;
51 static HRESULT
IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
53 struct IDirectSound_IDirectSound
{
54 const IDirectSoundVtbl
*lpVtbl
;
59 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
61 /*****************************************************************************
62 * IDirectSound8 COM components
64 struct IDirectSound8_IUnknown
{
65 const IUnknownVtbl
*lpVtbl
;
70 static HRESULT
IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
71 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
73 struct IDirectSound8_IDirectSound
{
74 const IDirectSoundVtbl
*lpVtbl
;
79 static HRESULT
IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
80 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
82 struct IDirectSound8_IDirectSound8
{
83 const IDirectSound8Vtbl
*lpVtbl
;
88 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
89 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
91 /*****************************************************************************
92 * IDirectSound implementation structure
94 struct IDirectSoundImpl
98 DirectSoundDevice
*device
;
104 static HRESULT
IDirectSoundImpl_Create(LPDIRECTSOUND8
* ppds
);
106 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
107 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
109 static HRESULT
DirectSoundDevice_VerifyCertification(DirectSoundDevice
* device
, LPDWORD pdwCertified
);
111 const char * dumpCooperativeLevel(DWORD level
)
113 static char unknown
[32];
114 #define LE(x) case x: return #x
119 LE(DSSCL_WRITEPRIMARY
);
122 sprintf(unknown
, "Unknown(%08x)", level
);
126 static void _dump_DSCAPS(DWORD xmask
) {
131 #define FE(x) { x, #x },
132 FE(DSCAPS_PRIMARYMONO
)
133 FE(DSCAPS_PRIMARYSTEREO
)
134 FE(DSCAPS_PRIMARY8BIT
)
135 FE(DSCAPS_PRIMARY16BIT
)
136 FE(DSCAPS_CONTINUOUSRATE
)
137 FE(DSCAPS_EMULDRIVER
)
139 FE(DSCAPS_SECONDARYMONO
)
140 FE(DSCAPS_SECONDARYSTEREO
)
141 FE(DSCAPS_SECONDARY8BIT
)
142 FE(DSCAPS_SECONDARY16BIT
)
147 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
148 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
149 DPRINTF("%s ",flags
[i
].name
);
152 static void _dump_DSBCAPS(DWORD xmask
) {
157 #define FE(x) { x, #x },
158 FE(DSBCAPS_PRIMARYBUFFER
)
160 FE(DSBCAPS_LOCHARDWARE
)
161 FE(DSBCAPS_LOCSOFTWARE
)
163 FE(DSBCAPS_CTRLFREQUENCY
)
165 FE(DSBCAPS_CTRLVOLUME
)
166 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
167 FE(DSBCAPS_STICKYFOCUS
)
168 FE(DSBCAPS_GLOBALFOCUS
)
169 FE(DSBCAPS_GETCURRENTPOSITION2
)
170 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
175 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
176 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
177 DPRINTF("%s ",flags
[i
].name
);
180 /*******************************************************************************
181 * IDirectSoundImpl_DirectSound
183 static HRESULT
DSOUND_QueryInterface(
184 LPDIRECTSOUND8 iface
,
188 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
189 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
192 WARN("invalid parameter\n");
196 if (IsEqualIID(riid
, &IID_IUnknown
)) {
197 if (!This
->pUnknown
) {
198 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
199 if (!This
->pUnknown
) {
200 WARN("IDirectSound_IUnknown_Create() failed\n");
202 return E_NOINTERFACE
;
205 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
206 *ppobj
= This
->pUnknown
;
208 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
210 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
212 WARN("IDirectSound_IDirectSound_Create() failed\n");
214 return E_NOINTERFACE
;
217 IDirectSound_IDirectSound_AddRef(This
->pDS
);
223 WARN("Unknown IID %s\n",debugstr_guid(riid
));
224 return E_NOINTERFACE
;
227 static HRESULT
DSOUND_QueryInterface8(
228 LPDIRECTSOUND8 iface
,
232 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
233 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
236 WARN("invalid parameter\n");
240 if (IsEqualIID(riid
, &IID_IUnknown
)) {
241 if (!This
->pUnknown
) {
242 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
243 if (!This
->pUnknown
) {
244 WARN("IDirectSound8_IUnknown_Create() failed\n");
246 return E_NOINTERFACE
;
249 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
250 *ppobj
= This
->pUnknown
;
252 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
254 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
256 WARN("IDirectSound8_IDirectSound_Create() failed\n");
258 return E_NOINTERFACE
;
261 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
264 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
266 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
268 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
270 return E_NOINTERFACE
;
273 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
279 WARN("Unknown IID %s\n",debugstr_guid(riid
));
280 return E_NOINTERFACE
;
283 static ULONG
IDirectSoundImpl_AddRef(
284 LPDIRECTSOUND8 iface
)
286 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
287 ULONG ref
= InterlockedIncrement(&(This
->ref
));
288 TRACE("(%p) ref was %d\n", This
, ref
- 1);
292 static ULONG
IDirectSoundImpl_Release(
293 LPDIRECTSOUND8 iface
)
295 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
296 ULONG ref
= InterlockedDecrement(&(This
->ref
));
297 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
301 DirectSoundDevice_Release(This
->device
);
302 HeapFree(GetProcessHeap(),0,This
);
303 TRACE("(%p) released\n", This
);
308 static HRESULT
IDirectSoundImpl_Create(
309 LPDIRECTSOUND8
* ppDS
)
311 IDirectSoundImpl
* pDS
;
312 TRACE("(%p)\n",ppDS
);
314 /* Allocate memory */
315 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
317 WARN("out of memory\n");
319 return DSERR_OUTOFMEMORY
;
325 *ppDS
= (LPDIRECTSOUND8
)pDS
;
330 /*******************************************************************************
331 * IDirectSound_IUnknown
333 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
338 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
339 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
340 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
343 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
346 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
347 ULONG ref
= InterlockedIncrement(&(This
->ref
));
348 TRACE("(%p) ref was %d\n", This
, ref
- 1);
352 static ULONG WINAPI
IDirectSound_IUnknown_Release(
355 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
356 ULONG ref
= InterlockedDecrement(&(This
->ref
));
357 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
359 IDirectSoundImpl_Release(This
->pds
);
360 HeapFree(GetProcessHeap(), 0, This
);
361 TRACE("(%p) released\n", This
);
366 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
368 IDirectSound_IUnknown_QueryInterface
,
369 IDirectSound_IUnknown_AddRef
,
370 IDirectSound_IUnknown_Release
373 static HRESULT
IDirectSound_IUnknown_Create(
377 IDirectSound_IUnknown
* pdsunk
;
378 TRACE("(%p,%p)\n",pds
,ppunk
);
381 ERR("invalid parameter: ppunk == NULL\n");
382 return DSERR_INVALIDPARAM
;
386 ERR("invalid parameter: pds == NULL\n");
388 return DSERR_INVALIDPARAM
;
391 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
392 if (pdsunk
== NULL
) {
393 WARN("out of memory\n");
395 return DSERR_OUTOFMEMORY
;
398 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
402 IDirectSoundImpl_AddRef(pds
);
403 *ppunk
= (LPUNKNOWN
)pdsunk
;
408 /*******************************************************************************
409 * IDirectSound_IDirectSound
411 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
416 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
417 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
418 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
421 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
424 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
425 ULONG ref
= InterlockedIncrement(&(This
->ref
));
426 TRACE("(%p) ref was %d\n", This
, ref
- 1);
430 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
433 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
434 ULONG ref
= InterlockedDecrement(&(This
->ref
));
435 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
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_Release(This
->pds
);
599 HeapFree(GetProcessHeap(), 0, This
);
600 TRACE("(%p) released\n", This
);
605 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
607 IDirectSound8_IUnknown_QueryInterface
,
608 IDirectSound8_IUnknown_AddRef
,
609 IDirectSound8_IUnknown_Release
612 static HRESULT
IDirectSound8_IUnknown_Create(
616 IDirectSound8_IUnknown
* pdsunk
;
617 TRACE("(%p,%p)\n",pds
,ppunk
);
620 ERR("invalid parameter: ppunk == NULL\n");
621 return DSERR_INVALIDPARAM
;
625 ERR("invalid parameter: pds == NULL\n");
627 return DSERR_INVALIDPARAM
;
630 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
631 if (pdsunk
== NULL
) {
632 WARN("out of memory\n");
634 return DSERR_OUTOFMEMORY
;
637 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
641 IDirectSoundImpl_AddRef(pds
);
642 *ppunk
= (LPUNKNOWN
)pdsunk
;
647 /*******************************************************************************
648 * IDirectSound8_IDirectSound
650 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
655 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
656 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
657 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
660 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
663 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
664 ULONG ref
= InterlockedIncrement(&(This
->ref
));
665 TRACE("(%p) ref was %d\n", This
, ref
- 1);
669 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
672 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
673 ULONG ref
= InterlockedDecrement(&(This
->ref
));
674 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
676 IDirectSoundImpl_Release(This
->pds
);
677 HeapFree(GetProcessHeap(), 0, This
);
678 TRACE("(%p) released\n", This
);
683 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
685 LPCDSBUFFERDESC dsbd
,
686 LPLPDIRECTSOUNDBUFFER ppdsb
,
689 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
690 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
691 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
694 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
698 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
699 TRACE("(%p,%p)\n",This
,lpDSCaps
);
700 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
703 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
705 LPDIRECTSOUNDBUFFER psb
,
706 LPLPDIRECTSOUNDBUFFER ppdsb
)
708 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
709 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
710 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
713 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
718 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
719 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
720 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
723 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
726 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
727 TRACE("(%p)\n", This
);
728 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
731 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
733 LPDWORD lpdwSpeakerConfig
)
735 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
736 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
737 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
740 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
744 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
745 TRACE("(%p,0x%08x)\n",This
,config
);
746 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
749 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
753 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
754 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
755 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
758 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
760 IDirectSound8_IDirectSound_QueryInterface
,
761 IDirectSound8_IDirectSound_AddRef
,
762 IDirectSound8_IDirectSound_Release
,
763 IDirectSound8_IDirectSound_CreateSoundBuffer
,
764 IDirectSound8_IDirectSound_GetCaps
,
765 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
766 IDirectSound8_IDirectSound_SetCooperativeLevel
,
767 IDirectSound8_IDirectSound_Compact
,
768 IDirectSound8_IDirectSound_GetSpeakerConfig
,
769 IDirectSound8_IDirectSound_SetSpeakerConfig
,
770 IDirectSound8_IDirectSound_Initialize
773 static HRESULT
IDirectSound8_IDirectSound_Create(
775 LPDIRECTSOUND
* ppds
)
777 IDirectSound8_IDirectSound
* pdsds
;
778 TRACE("(%p,%p)\n",pds
,ppds
);
781 ERR("invalid parameter: ppds == NULL\n");
782 return DSERR_INVALIDPARAM
;
786 ERR("invalid parameter: pds == NULL\n");
788 return DSERR_INVALIDPARAM
;
791 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
793 WARN("out of memory\n");
795 return DSERR_OUTOFMEMORY
;
798 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
802 IDirectSoundImpl_AddRef(pds
);
803 *ppds
= (LPDIRECTSOUND
)pdsds
;
808 /*******************************************************************************
809 * IDirectSound8_IDirectSound8
811 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
812 LPDIRECTSOUND8 iface
,
816 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
817 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
818 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
821 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
822 LPDIRECTSOUND8 iface
)
824 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
825 ULONG ref
= InterlockedIncrement(&(This
->ref
));
826 TRACE("(%p) ref was %d\n", This
, ref
- 1);
830 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
831 LPDIRECTSOUND8 iface
)
833 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
834 ULONG ref
= InterlockedDecrement(&(This
->ref
));
835 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
837 IDirectSoundImpl_Release(This
->pds
);
838 HeapFree(GetProcessHeap(), 0, This
);
839 TRACE("(%p) released\n", This
);
844 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
845 LPDIRECTSOUND8 iface
,
846 LPCDSBUFFERDESC dsbd
,
847 LPLPDIRECTSOUNDBUFFER ppdsb
,
850 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
851 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
852 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
855 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
856 LPDIRECTSOUND8 iface
,
859 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
860 TRACE("(%p,%p)\n",This
,lpDSCaps
);
861 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
864 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
865 LPDIRECTSOUND8 iface
,
866 LPDIRECTSOUNDBUFFER psb
,
867 LPLPDIRECTSOUNDBUFFER ppdsb
)
869 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
870 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
871 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
874 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
875 LPDIRECTSOUND8 iface
,
879 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
880 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
881 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
884 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
885 LPDIRECTSOUND8 iface
)
887 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
888 TRACE("(%p)\n", This
);
889 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
892 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
893 LPDIRECTSOUND8 iface
,
894 LPDWORD lpdwSpeakerConfig
)
896 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
897 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
898 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
901 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
902 LPDIRECTSOUND8 iface
,
905 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
906 TRACE("(%p,0x%08x)\n",This
,config
);
907 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
910 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
911 LPDIRECTSOUND8 iface
,
914 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
915 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
916 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
919 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
920 LPDIRECTSOUND8 iface
,
921 LPDWORD pdwCertified
)
923 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
924 TRACE("(%p, %p)\n", This
, pdwCertified
);
925 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
928 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
930 IDirectSound8_IDirectSound8_QueryInterface
,
931 IDirectSound8_IDirectSound8_AddRef
,
932 IDirectSound8_IDirectSound8_Release
,
933 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
934 IDirectSound8_IDirectSound8_GetCaps
,
935 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
936 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
937 IDirectSound8_IDirectSound8_Compact
,
938 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
939 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
940 IDirectSound8_IDirectSound8_Initialize
,
941 IDirectSound8_IDirectSound8_VerifyCertification
944 static HRESULT
IDirectSound8_IDirectSound8_Create(
946 LPDIRECTSOUND8
* ppds
)
948 IDirectSound8_IDirectSound8
* pdsds
;
949 TRACE("(%p,%p)\n",pds
,ppds
);
952 ERR("invalid parameter: ppds == NULL\n");
953 return DSERR_INVALIDPARAM
;
957 ERR("invalid parameter: pds == NULL\n");
959 return DSERR_INVALIDPARAM
;
962 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
964 WARN("out of memory\n");
966 return DSERR_OUTOFMEMORY
;
969 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
973 IDirectSoundImpl_AddRef(pds
);
974 *ppds
= (LPDIRECTSOUND8
)pdsds
;
979 HRESULT
DSOUND_Create(
985 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
987 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
988 !IsEqualIID(riid
, &IID_IDirectSound
)) {
990 return E_NOINTERFACE
;
993 /* Get dsound configuration */
994 setup_dsound_options();
996 hr
= IDirectSoundImpl_Create(&pDS
);
998 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1000 IDirectSound_IDirectSound_AddRef(*ppDS
);
1002 WARN("IDirectSound_IDirectSound_Create failed\n");
1003 IDirectSound8_Release(pDS
);
1006 WARN("IDirectSoundImpl_Create failed\n");
1013 /*******************************************************************************
1014 * DirectSoundCreate (DSOUND.1)
1016 * Creates and initializes a DirectSound interface.
1019 * lpcGUID [I] Address of the GUID that identifies the sound device.
1020 * ppDS [O] Address of a variable to receive the interface pointer.
1021 * pUnkOuter [I] Must be NULL.
1025 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1026 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1028 HRESULT WINAPI
DirectSoundCreate(
1030 LPDIRECTSOUND
*ppDS
,
1031 IUnknown
*pUnkOuter
)
1036 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1039 WARN("invalid parameter: ppDS == NULL\n");
1040 return DSERR_INVALIDPARAM
;
1043 if (pUnkOuter
!= NULL
) {
1044 WARN("invalid parameter: pUnkOuter != NULL\n");
1046 return DSERR_INVALIDPARAM
;
1049 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
1051 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1053 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1054 IDirectSound_Release(pDS
);
1066 HRESULT
DSOUND_Create8(
1068 LPDIRECTSOUND8
*ppDS
)
1072 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
1074 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1075 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
1077 return E_NOINTERFACE
;
1080 /* Get dsound configuration */
1081 setup_dsound_options();
1083 hr
= IDirectSoundImpl_Create(&pDS
);
1085 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1087 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1089 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1090 IDirectSound8_Release(pDS
);
1093 WARN("IDirectSoundImpl_Create failed\n");
1100 /*******************************************************************************
1101 * DirectSoundCreate8 (DSOUND.11)
1103 * Creates and initializes a DirectSound8 interface.
1106 * lpcGUID [I] Address of the GUID that identifies the sound device.
1107 * ppDS [O] Address of a variable to receive the interface pointer.
1108 * pUnkOuter [I] Must be NULL.
1112 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1113 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1115 HRESULT WINAPI
DirectSoundCreate8(
1117 LPDIRECTSOUND8
*ppDS
,
1118 IUnknown
*pUnkOuter
)
1123 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1126 WARN("invalid parameter: ppDS == NULL\n");
1127 return DSERR_INVALIDPARAM
;
1130 if (pUnkOuter
!= NULL
) {
1131 WARN("invalid parameter: pUnkOuter != NULL\n");
1133 return DSERR_INVALIDPARAM
;
1136 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
1138 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1140 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1141 IDirectSound8_Release(pDS
);
1153 /*******************************************************************************
1156 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1158 DirectSoundDevice
* device
;
1159 TRACE("(%p)\n", ppDevice
);
1161 /* Allocate memory */
1162 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1163 if (device
== NULL
) {
1164 WARN("out of memory\n");
1165 return DSERR_OUTOFMEMORY
;
1169 device
->driver
= NULL
;
1170 device
->priolevel
= DSSCL_NORMAL
;
1171 device
->fraglen
= 0;
1172 device
->hwbuf
= NULL
;
1173 device
->buffer
= NULL
;
1175 device
->writelead
= 0;
1176 device
->state
= STATE_STOPPED
;
1177 device
->nrofbuffers
= 0;
1178 device
->buffers
= NULL
;
1179 device
->primary
= NULL
;
1180 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
1181 device
->tmp_buffer
= NULL
;
1182 device
->tmp_buffer_len
= 0;
1184 /* 3D listener initial parameters */
1185 device
->listener
= NULL
;
1186 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1187 device
->ds3dl
.vPosition
.x
= 0.0;
1188 device
->ds3dl
.vPosition
.y
= 0.0;
1189 device
->ds3dl
.vPosition
.z
= 0.0;
1190 device
->ds3dl
.vVelocity
.x
= 0.0;
1191 device
->ds3dl
.vVelocity
.y
= 0.0;
1192 device
->ds3dl
.vVelocity
.z
= 0.0;
1193 device
->ds3dl
.vOrientFront
.x
= 0.0;
1194 device
->ds3dl
.vOrientFront
.y
= 0.0;
1195 device
->ds3dl
.vOrientFront
.z
= 1.0;
1196 device
->ds3dl
.vOrientTop
.x
= 0.0;
1197 device
->ds3dl
.vOrientTop
.y
= 1.0;
1198 device
->ds3dl
.vOrientTop
.z
= 0.0;
1199 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1200 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1201 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1203 device
->prebuf
= ds_snd_queue_max
;
1204 device
->guid
= GUID_NULL
;
1206 /* Set default wave format (may need it for waveOutOpen) */
1207 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1208 if (device
->pwfx
== NULL
) {
1209 WARN("out of memory\n");
1210 HeapFree(GetProcessHeap(),0,device
);
1211 return DSERR_OUTOFMEMORY
;
1214 /* We rely on the sound driver to return the actual sound format of
1215 * the device if it does not support 22050x8x2 and is given the
1216 * WAVE_DIRECTSOUND flag.
1218 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1219 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1220 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1221 device
->pwfx
->nChannels
= 2;
1222 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1223 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1224 device
->pwfx
->cbSize
= 0;
1226 InitializeCriticalSection(&(device
->mixlock
));
1227 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSOUND_mixlock";
1229 RtlInitializeResource(&(device
->buffer_list_lock
));
1236 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1238 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1239 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1243 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1246 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1247 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1250 timeKillEvent(device
->timerID
);
1251 timeEndPeriod(DS_TIME_RES
);
1252 /* wait for timer to expire */
1253 Sleep(DS_TIME_RES
+1);
1255 /* The sleep above should have allowed the timer process to expire
1256 * but try to grab the lock just in case. Can't hold lock because
1257 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1258 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1259 RtlReleaseResource(&(device
->buffer_list_lock
));
1261 /* It is allowed to release this object even when buffers are playing */
1262 if (device
->buffers
) {
1263 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1264 for( i
=0;i
<device
->nrofbuffers
;i
++)
1265 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1268 if (device
->primary
) {
1269 WARN("primary buffer not released\n");
1270 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1273 hr
= DSOUND_PrimaryDestroy(device
);
1275 WARN("DSOUND_PrimaryDestroy failed\n");
1278 IDsDriver_Close(device
->driver
);
1280 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1281 waveOutClose(device
->hwo
);
1284 IDsDriver_Release(device
->driver
);
1286 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1288 HeapFree(GetProcessHeap(),0,device
->tmp_buffer
);
1289 HeapFree(GetProcessHeap(),0,device
->buffer
);
1290 RtlDeleteResource(&device
->buffer_list_lock
);
1291 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1292 DeleteCriticalSection(&device
->mixlock
);
1293 HeapFree(GetProcessHeap(),0,device
);
1294 TRACE("(%p) released\n", device
);
1299 HRESULT
DirectSoundDevice_GetCaps(
1300 DirectSoundDevice
* device
,
1303 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1305 if (device
== NULL
) {
1306 WARN("not initialized\n");
1307 return DSERR_UNINITIALIZED
;
1310 if (lpDSCaps
== NULL
) {
1311 WARN("invalid parameter: lpDSCaps = NULL\n");
1312 return DSERR_INVALIDPARAM
;
1315 /* check if there is enough room */
1316 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1317 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1318 return DSERR_INVALIDPARAM
;
1321 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1322 if (TRACE_ON(dsound
)) {
1323 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1324 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1327 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1328 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1329 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1330 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1331 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1332 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1333 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1334 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1335 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1336 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1337 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1338 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1339 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1340 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1341 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1342 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1343 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1344 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1346 /* driver doesn't have these */
1347 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1348 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1353 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1357 BOOLEAN found
= FALSE
;
1359 DirectSoundDevice
* device
= *ppDevice
;
1360 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1362 if (*ppDevice
!= NULL
) {
1363 WARN("already initialized\n");
1364 return DSERR_ALREADYINITIALIZED
;
1367 /* Default device? */
1368 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1369 lpcGUID
= &DSDEVID_DefaultPlayback
;
1371 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1372 WARN("invalid parameter: lpcGUID\n");
1373 return DSERR_INVALIDPARAM
;
1376 /* Enumerate WINMM audio devices and find the one we want */
1377 wodn
= waveOutGetNumDevs();
1379 WARN("no driver\n");
1380 return DSERR_NODRIVER
;
1383 for (wod
=0; wod
<wodn
; wod
++) {
1384 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1390 if (found
== FALSE
) {
1391 WARN("No device found matching given ID!\n");
1392 return DSERR_NODRIVER
;
1395 if (DSOUND_renderer
[wod
]) {
1396 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1397 device
= DSOUND_renderer
[wod
];
1398 DirectSoundDevice_AddRef(device
);
1402 ERR("device GUID doesn't match\n");
1407 hr
= DirectSoundDevice_Create(&device
);
1409 WARN("DirectSoundDevice_Create failed\n");
1415 device
->guid
= devGUID
;
1417 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
1418 waveOutMessage((HWAVEOUT
)wod
, DRV_QUERYDSOUNDIFACE
, (DWORD_PTR
)&device
->driver
, 0);
1420 /* Disable the direct sound driver to force emulation if requested. */
1421 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
1422 device
->driver
= NULL
;
1424 /* Get driver description */
1425 if (device
->driver
) {
1426 hr
= IDsDriver_GetDriverDesc(device
->driver
,&(device
->drvdesc
));
1428 WARN("IDsDriver_GetDriverDesc failed\n");
1432 /* if no DirectSound interface available, use WINMM API instead */
1433 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
| DSDDESC_DOMMSYSTEMSETFORMAT
;
1436 device
->drvdesc
.dnDevNode
= wod
;
1438 /* If the driver requests being opened through MMSYSTEM
1439 * (which is recommended by the DDK), it is supposed to happen
1440 * before the DirectSound interface is opened */
1441 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1443 DWORD flags
= CALLBACK_FUNCTION
;
1445 /* disable direct sound if requested */
1446 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1447 flags
|= WAVE_DIRECTSOUND
;
1449 hr
= mmErr(waveOutOpen(&(device
->hwo
),
1450 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1451 (DWORD_PTR
)DSOUND_callback
, (DWORD
)device
,
1454 WARN("waveOutOpen failed\n");
1459 if (device
->driver
) {
1460 hr
= IDsDriver_Open(device
->driver
);
1462 WARN("IDsDriver_Open failed\n");
1466 /* the driver is now open, so it's now allowed to call GetCaps */
1467 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1469 WARN("IDsDriver_GetCaps failed\n");
1474 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1476 WARN("waveOutGetDevCaps failed\n");
1479 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1480 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1481 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1482 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1483 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1484 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1485 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1486 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1488 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1489 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1490 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1491 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1492 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1493 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1494 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1496 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1497 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1498 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1499 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1500 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1501 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1502 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1504 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1505 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1506 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1507 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1508 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1509 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1510 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1513 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1514 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1515 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1516 device
->drvcaps
.dwPrimaryBuffers
= 1;
1519 hr
= DSOUND_PrimaryCreate(device
);
1521 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1522 timeBeginPeriod(DS_TIME_RES
);
1523 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1524 (DWORD_PTR
)DSOUND_renderer
[device
->drvdesc
.dnDevNode
], TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1526 WARN("DSOUND_PrimaryCreate failed\n");
1532 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1533 DirectSoundDevice
* device
,
1534 LPCDSBUFFERDESC dsbd
,
1535 LPLPDIRECTSOUNDBUFFER ppdsb
,
1539 HRESULT hres
= DS_OK
;
1540 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1542 if (device
== NULL
) {
1543 WARN("not initialized\n");
1544 return DSERR_UNINITIALIZED
;
1548 WARN("invalid parameter: dsbd == NULL\n");
1549 return DSERR_INVALIDPARAM
;
1552 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1553 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1554 WARN("invalid parameter: dsbd\n");
1555 return DSERR_INVALIDPARAM
;
1558 if (ppdsb
== NULL
) {
1559 WARN("invalid parameter: ppdsb == NULL\n");
1560 return DSERR_INVALIDPARAM
;
1563 if (TRACE_ON(dsound
)) {
1564 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1565 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1566 _dump_DSBCAPS(dsbd
->dwFlags
);
1568 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1569 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1572 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1573 if (dsbd
->lpwfxFormat
!= NULL
) {
1574 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1575 "primary buffer\n");
1576 return DSERR_INVALIDPARAM
;
1579 if (device
->primary
) {
1580 WARN("Primary Buffer already created\n");
1581 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1582 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1584 device
->dsbd
= *dsbd
;
1585 hres
= PrimaryBufferImpl_Create(device
, (PrimaryBufferImpl
**)&(device
->primary
), &(device
->dsbd
));
1586 if (device
->primary
) {
1587 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1588 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1590 WARN("PrimaryBufferImpl_Create failed\n");
1593 IDirectSoundBufferImpl
* dsb
;
1595 if (dsbd
->lpwfxFormat
== NULL
) {
1596 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1597 "secondary buffer\n");
1598 return DSERR_INVALIDPARAM
;
1601 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1602 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1603 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1604 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1605 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1606 dsbd
->lpwfxFormat
->nBlockAlign
,
1607 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1609 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1610 WARN("invalid parameter: 3D buffer format must be mono\n");
1611 return DSERR_INVALIDPARAM
;
1614 hres
= IDirectSoundBufferImpl_Create(device
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
1616 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1618 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1619 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
1621 WARN("SecondaryBufferImpl_Create failed\n");
1623 WARN("IDirectSoundBufferImpl_Create failed\n");
1629 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1630 DirectSoundDevice
* device
,
1631 LPDIRECTSOUNDBUFFER psb
,
1632 LPLPDIRECTSOUNDBUFFER ppdsb
)
1634 HRESULT hres
= DS_OK
;
1635 IDirectSoundBufferImpl
* dsb
;
1636 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1638 if (device
== NULL
) {
1639 WARN("not initialized\n");
1640 return DSERR_UNINITIALIZED
;
1644 WARN("invalid parameter: psb == NULL\n");
1645 return DSERR_INVALIDPARAM
;
1648 if (ppdsb
== NULL
) {
1649 WARN("invalid parameter: ppdsb == NULL\n");
1650 return DSERR_INVALIDPARAM
;
1653 /* make sure we have a secondary buffer */
1654 if ((PrimaryBufferImpl
*)psb
== device
->primary
) {
1655 WARN("trying to duplicate primary buffer\n");
1657 return DSERR_INVALIDCALL
;
1660 /* duplicate the actual buffer implementation */
1661 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
,
1662 ((SecondaryBufferImpl
*)psb
)->dsb
);
1664 if (hres
== DS_OK
) {
1665 /* create a new secondary buffer using the new implementation */
1666 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1668 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1669 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
1671 WARN("SecondaryBufferImpl_Create failed\n");
1672 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)dsb
);
1673 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8
)dsb
);
1680 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1681 DirectSoundDevice
* device
,
1685 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1687 if (device
== NULL
) {
1688 WARN("not initialized\n");
1689 return DSERR_UNINITIALIZED
;
1692 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1693 WARN("level=%s not fully supported\n",
1694 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1697 device
->priolevel
= level
;
1701 HRESULT
DirectSoundDevice_Compact(
1702 DirectSoundDevice
* device
)
1704 TRACE("(%p)\n", device
);
1706 if (device
== NULL
) {
1707 WARN("not initialized\n");
1708 return DSERR_UNINITIALIZED
;
1711 if (device
->priolevel
!= DSSCL_PRIORITY
) {
1712 WARN("incorrect priority level\n");
1713 return DSERR_PRIOLEVELNEEDED
;
1719 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1720 DirectSoundDevice
* device
,
1721 LPDWORD lpdwSpeakerConfig
)
1723 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1725 if (device
== NULL
) {
1726 WARN("not initialized\n");
1727 return DSERR_UNINITIALIZED
;
1730 if (lpdwSpeakerConfig
== NULL
) {
1731 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1732 return DSERR_INVALIDPARAM
;
1735 WARN("not fully functional\n");
1736 *lpdwSpeakerConfig
= device
->speaker_config
;
1740 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1741 DirectSoundDevice
* device
,
1744 TRACE("(%p,0x%08x)\n",device
,config
);
1746 if (device
== NULL
) {
1747 WARN("not initialized\n");
1748 return DSERR_UNINITIALIZED
;
1751 device
->speaker_config
= config
;
1752 WARN("not fully functional\n");
1756 static HRESULT
DirectSoundDevice_VerifyCertification(
1757 DirectSoundDevice
* device
,
1758 LPDWORD pdwCertified
)
1760 TRACE("(%p, %p)\n",device
,pdwCertified
);
1762 if (device
== NULL
) {
1763 WARN("not initialized\n");
1764 return DSERR_UNINITIALIZED
;
1767 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1768 *pdwCertified
= DS_CERTIFIED
;
1770 *pdwCertified
= DS_UNCERTIFIED
;
1776 * Add secondary buffer to buffer list.
1777 * Gets exclusive access to buffer for writing.
1779 HRESULT
DirectSoundDevice_AddBuffer(
1780 DirectSoundDevice
* device
,
1781 IDirectSoundBufferImpl
* pDSB
)
1783 IDirectSoundBufferImpl
**newbuffers
;
1786 TRACE("(%p, %p)\n", device
, pDSB
);
1788 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1790 if (device
->buffers
)
1791 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1793 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1796 device
->buffers
= newbuffers
;
1797 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1798 device
->nrofbuffers
++;
1799 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1801 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1802 hr
= DSERR_OUTOFMEMORY
;
1805 RtlReleaseResource(&(device
->buffer_list_lock
));
1811 * Remove secondary buffer from buffer list.
1812 * Gets exclusive access to buffer for writing.
1814 HRESULT
DirectSoundDevice_RemoveBuffer(
1815 DirectSoundDevice
* device
,
1816 IDirectSoundBufferImpl
* pDSB
)
1821 TRACE("(%p, %p)\n", device
, pDSB
);
1823 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1825 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1826 if (device
->buffers
[i
] == pDSB
)
1829 if (i
< device
->nrofbuffers
) {
1830 /* Put the last buffer of the list in the (now empty) position */
1831 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1832 device
->nrofbuffers
--;
1833 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1834 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1837 if (device
->nrofbuffers
== 0) {
1838 HeapFree(GetProcessHeap(),0,device
->buffers
);
1839 device
->buffers
= NULL
;
1842 RtlReleaseResource(&(device
->buffer_list_lock
));