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
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 /* It is allowed to release this object even when buffers are playing */
1252 if (device
->buffers
) {
1253 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1254 for( i
=0;i
<device
->nrofbuffers
;i
++)
1255 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1258 if (device
->primary
) {
1259 WARN("primary buffer not released\n");
1260 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1263 hr
= DSOUND_PrimaryDestroy(device
);
1265 WARN("DSOUND_PrimaryDestroy failed\n");
1267 waveOutClose(device
->hwo
);
1269 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1271 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
1272 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
1273 HeapFree(GetProcessHeap(), 0, device
->buffer
);
1274 RtlDeleteResource(&device
->buffer_list_lock
);
1275 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1276 DeleteCriticalSection(&device
->mixlock
);
1277 HeapFree(GetProcessHeap(),0,device
);
1278 TRACE("(%p) released\n", device
);
1283 HRESULT
DirectSoundDevice_GetCaps(
1284 DirectSoundDevice
* device
,
1287 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1289 if (device
== NULL
) {
1290 WARN("not initialized\n");
1291 return DSERR_UNINITIALIZED
;
1294 if (lpDSCaps
== NULL
) {
1295 WARN("invalid parameter: lpDSCaps = NULL\n");
1296 return DSERR_INVALIDPARAM
;
1299 /* check if there is enough room */
1300 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1301 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1302 return DSERR_INVALIDPARAM
;
1305 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1306 if (TRACE_ON(dsound
)) {
1307 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1308 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1311 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1312 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1313 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1314 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1315 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1316 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1317 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1318 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1319 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1320 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1321 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1322 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1323 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1324 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1325 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1326 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1327 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1328 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1330 /* driver doesn't have these */
1331 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1332 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1337 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1341 BOOLEAN found
= FALSE
;
1343 DirectSoundDevice
* device
= *ppDevice
;
1346 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1348 if (*ppDevice
!= NULL
) {
1349 WARN("already initialized\n");
1350 return DSERR_ALREADYINITIALIZED
;
1353 /* Default device? */
1354 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1355 lpcGUID
= &DSDEVID_DefaultPlayback
;
1357 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1358 WARN("invalid parameter: lpcGUID\n");
1359 return DSERR_INVALIDPARAM
;
1362 /* Enumerate WINMM audio devices and find the one we want */
1363 wodn
= waveOutGetNumDevs();
1365 WARN("no driver\n");
1366 return DSERR_NODRIVER
;
1369 for (wod
=0; wod
<wodn
; wod
++) {
1370 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1376 if (found
== FALSE
) {
1377 WARN("No device found matching given ID!\n");
1378 return DSERR_NODRIVER
;
1381 if (DSOUND_renderer
[wod
]) {
1382 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1383 device
= DSOUND_renderer
[wod
];
1384 DirectSoundDevice_AddRef(device
);
1388 ERR("device GUID doesn't match\n");
1393 hr
= DirectSoundDevice_Create(&device
);
1395 WARN("DirectSoundDevice_Create failed\n");
1401 device
->guid
= devGUID
;
1403 device
->drvdesc
.dnDevNode
= wod
;
1404 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1407 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1411 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1413 WARN("waveOutGetDevCaps failed\n");
1416 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1417 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1418 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1419 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1420 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1421 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1422 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1423 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1425 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1426 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1427 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1428 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1429 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1430 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1431 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1433 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1434 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1435 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1436 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1437 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1438 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1439 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1441 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1442 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1443 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1444 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1445 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1446 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1447 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1451 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1452 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1453 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1454 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1456 hr
= DSOUND_PrimaryCreate(device
);
1458 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1461 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1462 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1463 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1464 if (triggertime
< time
.wPeriodMin
)
1465 triggertime
= time
.wPeriodMin
;
1466 if (res
< time
.wPeriodMin
)
1467 res
= time
.wPeriodMin
;
1468 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1469 WARN("Could not set minimum resolution, don't expect sound\n");
1470 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1473 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1474 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
);
1475 if (!id
) ERR("Could not create timer, sound playback will not occur\n");
1477 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= id
;
1479 WARN("DSOUND_PrimaryCreate failed\n");
1485 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1486 DirectSoundDevice
* device
,
1487 LPCDSBUFFERDESC dsbd
,
1488 LPLPDIRECTSOUNDBUFFER ppdsb
,
1492 HRESULT hres
= DS_OK
;
1493 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1495 if (device
== NULL
) {
1496 WARN("not initialized\n");
1497 return DSERR_UNINITIALIZED
;
1501 WARN("invalid parameter: dsbd == NULL\n");
1502 return DSERR_INVALIDPARAM
;
1505 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1506 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1507 WARN("invalid parameter: dsbd\n");
1508 return DSERR_INVALIDPARAM
;
1511 if (ppdsb
== NULL
) {
1512 WARN("invalid parameter: ppdsb == NULL\n");
1513 return DSERR_INVALIDPARAM
;
1517 if (TRACE_ON(dsound
)) {
1518 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1519 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1520 _dump_DSBCAPS(dsbd
->dwFlags
);
1522 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1523 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1526 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1527 if (dsbd
->lpwfxFormat
!= NULL
) {
1528 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1529 "primary buffer\n");
1530 return DSERR_INVALIDPARAM
;
1533 if (device
->primary
) {
1534 WARN("Primary Buffer already created\n");
1535 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1536 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1538 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1539 if (device
->primary
) {
1540 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1541 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1542 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1544 WARN("primarybuffer_create() failed\n");
1547 IDirectSoundBufferImpl
* dsb
;
1548 WAVEFORMATEXTENSIBLE
*pwfxe
;
1550 if (dsbd
->lpwfxFormat
== NULL
) {
1551 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1552 "secondary buffer\n");
1553 return DSERR_INVALIDPARAM
;
1555 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1557 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1559 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1560 return DSERR_CONTROLUNAVAIL
;
1562 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1564 /* check if cbSize is at least 22 bytes */
1565 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1567 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1568 return DSERR_INVALIDPARAM
;
1571 /* cbSize should be 22 bytes, with one possible exception */
1572 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1573 !((IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) || IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) &&
1574 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1576 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1577 return DSERR_CONTROLUNAVAIL
;
1580 if ((!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) && (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
1582 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1583 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1584 return DSERR_INVALIDPARAM
;
1586 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1588 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1589 return DSERR_INVALIDPARAM
;
1591 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1593 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1594 return DSERR_CONTROLUNAVAIL
;
1598 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1599 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1600 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1601 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1602 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1603 dsbd
->lpwfxFormat
->nBlockAlign
,
1604 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1606 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1607 WARN("invalid parameter: 3D buffer format must be mono\n");
1608 return DSERR_INVALIDPARAM
;
1611 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1613 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1615 WARN("IDirectSoundBufferImpl_Create failed\n");
1621 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1622 DirectSoundDevice
* device
,
1623 LPDIRECTSOUNDBUFFER psb
,
1624 LPLPDIRECTSOUNDBUFFER ppdsb
)
1626 HRESULT hres
= DS_OK
;
1627 IDirectSoundBufferImpl
* dsb
;
1628 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1630 if (device
== NULL
) {
1631 WARN("not initialized\n");
1632 return DSERR_UNINITIALIZED
;
1636 WARN("invalid parameter: psb == NULL\n");
1637 return DSERR_INVALIDPARAM
;
1640 if (ppdsb
== NULL
) {
1641 WARN("invalid parameter: ppdsb == NULL\n");
1642 return DSERR_INVALIDPARAM
;
1645 /* make sure we have a secondary buffer */
1646 if (psb
== (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
) {
1647 WARN("trying to duplicate primary buffer\n");
1649 return DSERR_INVALIDCALL
;
1652 /* duplicate the actual buffer implementation */
1653 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
, (IDirectSoundBufferImpl
*)psb
);
1655 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1657 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1662 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1663 DirectSoundDevice
* device
,
1667 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1669 if (device
== NULL
) {
1670 WARN("not initialized\n");
1671 return DSERR_UNINITIALIZED
;
1674 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1675 WARN("level=%s not fully supported\n",
1676 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1679 device
->priolevel
= level
;
1683 HRESULT
DirectSoundDevice_Compact(
1684 DirectSoundDevice
* device
)
1686 TRACE("(%p)\n", device
);
1688 if (device
== NULL
) {
1689 WARN("not initialized\n");
1690 return DSERR_UNINITIALIZED
;
1693 if (device
->priolevel
< DSSCL_PRIORITY
) {
1694 WARN("incorrect priority level\n");
1695 return DSERR_PRIOLEVELNEEDED
;
1701 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1702 DirectSoundDevice
* device
,
1703 LPDWORD lpdwSpeakerConfig
)
1705 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1707 if (device
== NULL
) {
1708 WARN("not initialized\n");
1709 return DSERR_UNINITIALIZED
;
1712 if (lpdwSpeakerConfig
== NULL
) {
1713 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1714 return DSERR_INVALIDPARAM
;
1717 WARN("not fully functional\n");
1718 *lpdwSpeakerConfig
= device
->speaker_config
;
1722 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1723 DirectSoundDevice
* device
,
1726 TRACE("(%p,0x%08x)\n",device
,config
);
1728 if (device
== NULL
) {
1729 WARN("not initialized\n");
1730 return DSERR_UNINITIALIZED
;
1733 device
->speaker_config
= config
;
1734 WARN("not fully functional\n");
1738 HRESULT
DirectSoundDevice_VerifyCertification(
1739 DirectSoundDevice
* device
,
1740 LPDWORD pdwCertified
)
1742 TRACE("(%p, %p)\n",device
,pdwCertified
);
1744 if (device
== NULL
) {
1745 WARN("not initialized\n");
1746 return DSERR_UNINITIALIZED
;
1749 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1750 *pdwCertified
= DS_CERTIFIED
;
1752 *pdwCertified
= DS_UNCERTIFIED
;
1758 * Add secondary buffer to buffer list.
1759 * Gets exclusive access to buffer for writing.
1761 HRESULT
DirectSoundDevice_AddBuffer(
1762 DirectSoundDevice
* device
,
1763 IDirectSoundBufferImpl
* pDSB
)
1765 IDirectSoundBufferImpl
**newbuffers
;
1768 TRACE("(%p, %p)\n", device
, pDSB
);
1770 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1772 if (device
->buffers
)
1773 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1775 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1778 device
->buffers
= newbuffers
;
1779 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1780 device
->nrofbuffers
++;
1781 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1783 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1784 hr
= DSERR_OUTOFMEMORY
;
1787 RtlReleaseResource(&(device
->buffer_list_lock
));
1793 * Remove secondary buffer from buffer list.
1794 * Gets exclusive access to buffer for writing.
1796 HRESULT
DirectSoundDevice_RemoveBuffer(
1797 DirectSoundDevice
* device
,
1798 IDirectSoundBufferImpl
* pDSB
)
1803 TRACE("(%p, %p)\n", device
, pDSB
);
1805 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1807 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1808 if (device
->buffers
[i
] == pDSB
)
1811 if (i
< device
->nrofbuffers
) {
1812 /* Put the last buffer of the list in the (now empty) position */
1813 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1814 device
->nrofbuffers
--;
1815 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1816 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1819 if (device
->nrofbuffers
== 0) {
1820 HeapFree(GetProcessHeap(),0,device
->buffers
);
1821 device
->buffers
= NULL
;
1824 RtlReleaseResource(&(device
->buffer_list_lock
));