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
23 #include "dsound_private.h"
25 /*****************************************************************************
26 * IDirectSound COM components
28 struct IDirectSound_IUnknown
{
29 const IUnknownVtbl
*lpVtbl
;
34 static HRESULT
IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
36 struct IDirectSound_IDirectSound
{
37 const IDirectSoundVtbl
*lpVtbl
;
42 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
44 /*****************************************************************************
45 * IDirectSound8 COM components
47 struct IDirectSound8_IUnknown
{
48 const IUnknownVtbl
*lpVtbl
;
53 static HRESULT
IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
54 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
56 struct IDirectSound8_IDirectSound
{
57 const IDirectSoundVtbl
*lpVtbl
;
62 static HRESULT
IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
63 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
65 struct IDirectSound8_IDirectSound8
{
66 const IDirectSound8Vtbl
*lpVtbl
;
71 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
72 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
74 /*****************************************************************************
75 * IDirectSound implementation structure
77 struct IDirectSoundImpl
81 DirectSoundDevice
*device
;
87 static HRESULT
IDirectSoundImpl_Create(LPDIRECTSOUND8
* ppds
);
89 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
90 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
92 const char * dumpCooperativeLevel(DWORD level
)
94 #define LE(x) case x: return #x
99 LE(DSSCL_WRITEPRIMARY
);
102 return wine_dbg_sprintf("Unknown(%08x)", level
);
105 static void _dump_DSCAPS(DWORD xmask
) {
110 #define FE(x) { x, #x },
111 FE(DSCAPS_PRIMARYMONO
)
112 FE(DSCAPS_PRIMARYSTEREO
)
113 FE(DSCAPS_PRIMARY8BIT
)
114 FE(DSCAPS_PRIMARY16BIT
)
115 FE(DSCAPS_CONTINUOUSRATE
)
116 FE(DSCAPS_EMULDRIVER
)
118 FE(DSCAPS_SECONDARYMONO
)
119 FE(DSCAPS_SECONDARYSTEREO
)
120 FE(DSCAPS_SECONDARY8BIT
)
121 FE(DSCAPS_SECONDARY16BIT
)
126 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
127 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
128 TRACE("%s ",flags
[i
].name
);
131 static void _dump_DSBCAPS(DWORD xmask
) {
136 #define FE(x) { x, #x },
137 FE(DSBCAPS_PRIMARYBUFFER
)
139 FE(DSBCAPS_LOCHARDWARE
)
140 FE(DSBCAPS_LOCSOFTWARE
)
142 FE(DSBCAPS_CTRLFREQUENCY
)
144 FE(DSBCAPS_CTRLVOLUME
)
145 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
146 FE(DSBCAPS_STICKYFOCUS
)
147 FE(DSBCAPS_GLOBALFOCUS
)
148 FE(DSBCAPS_GETCURRENTPOSITION2
)
149 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
154 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
155 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
156 TRACE("%s ",flags
[i
].name
);
159 /*******************************************************************************
160 * IDirectSoundImpl_DirectSound
162 static HRESULT
DSOUND_QueryInterface(
163 LPDIRECTSOUND8 iface
,
167 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
168 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
171 WARN("invalid parameter\n");
175 if (IsEqualIID(riid
, &IID_IUnknown
)) {
176 if (!This
->pUnknown
) {
177 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
178 if (!This
->pUnknown
) {
179 WARN("IDirectSound_IUnknown_Create() failed\n");
181 return E_NOINTERFACE
;
184 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
185 *ppobj
= This
->pUnknown
;
187 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
189 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
191 WARN("IDirectSound_IDirectSound_Create() failed\n");
193 return E_NOINTERFACE
;
196 IDirectSound_IDirectSound_AddRef(This
->pDS
);
202 WARN("Unknown IID %s\n",debugstr_guid(riid
));
203 return E_NOINTERFACE
;
206 static HRESULT
DSOUND_QueryInterface8(
207 LPDIRECTSOUND8 iface
,
211 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
212 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
215 WARN("invalid parameter\n");
219 if (IsEqualIID(riid
, &IID_IUnknown
)) {
220 if (!This
->pUnknown
) {
221 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
222 if (!This
->pUnknown
) {
223 WARN("IDirectSound8_IUnknown_Create() failed\n");
225 return E_NOINTERFACE
;
228 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
229 *ppobj
= This
->pUnknown
;
231 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
233 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
235 WARN("IDirectSound8_IDirectSound_Create() failed\n");
237 return E_NOINTERFACE
;
240 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
243 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
245 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
247 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
249 return E_NOINTERFACE
;
252 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
258 WARN("Unknown IID %s\n",debugstr_guid(riid
));
259 return E_NOINTERFACE
;
262 static ULONG
IDirectSoundImpl_AddRef(
263 LPDIRECTSOUND8 iface
)
265 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
266 ULONG ref
= InterlockedIncrement(&(This
->ref
));
267 TRACE("(%p) ref was %d\n", This
, ref
- 1);
271 static ULONG
IDirectSoundImpl_Release(
272 LPDIRECTSOUND8 iface
)
274 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
275 ULONG ref
= InterlockedDecrement(&(This
->ref
));
276 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
280 DirectSoundDevice_Release(This
->device
);
281 HeapFree(GetProcessHeap(),0,This
);
282 TRACE("(%p) released\n", This
);
287 static HRESULT
IDirectSoundImpl_Create(
288 LPDIRECTSOUND8
* ppDS
)
290 IDirectSoundImpl
* pDS
;
291 TRACE("(%p)\n",ppDS
);
293 /* Allocate memory */
294 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
296 WARN("out of memory\n");
298 return DSERR_OUTOFMEMORY
;
304 *ppDS
= (LPDIRECTSOUND8
)pDS
;
309 /*******************************************************************************
310 * IDirectSound_IUnknown
312 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
317 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
318 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
319 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
322 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
325 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
326 ULONG ref
= InterlockedIncrement(&(This
->ref
));
327 TRACE("(%p) ref was %d\n", This
, ref
- 1);
331 static ULONG WINAPI
IDirectSound_IUnknown_Release(
334 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
335 ULONG ref
= InterlockedDecrement(&(This
->ref
));
336 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
338 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
339 IDirectSoundImpl_Release(This
->pds
);
340 HeapFree(GetProcessHeap(), 0, This
);
341 TRACE("(%p) released\n", This
);
346 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
348 IDirectSound_IUnknown_QueryInterface
,
349 IDirectSound_IUnknown_AddRef
,
350 IDirectSound_IUnknown_Release
353 static HRESULT
IDirectSound_IUnknown_Create(
357 IDirectSound_IUnknown
* pdsunk
;
358 TRACE("(%p,%p)\n",pds
,ppunk
);
361 ERR("invalid parameter: ppunk == NULL\n");
362 return DSERR_INVALIDPARAM
;
366 ERR("invalid parameter: pds == NULL\n");
368 return DSERR_INVALIDPARAM
;
371 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
372 if (pdsunk
== NULL
) {
373 WARN("out of memory\n");
375 return DSERR_OUTOFMEMORY
;
378 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
382 IDirectSoundImpl_AddRef(pds
);
383 *ppunk
= (LPUNKNOWN
)pdsunk
;
388 /*******************************************************************************
389 * IDirectSound_IDirectSound
391 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
396 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
397 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
398 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
401 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
404 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
405 ULONG ref
= InterlockedIncrement(&(This
->ref
));
406 TRACE("(%p) ref was %d\n", This
, ref
- 1);
410 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
413 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
414 ULONG ref
= InterlockedDecrement(&(This
->ref
));
415 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
417 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
418 IDirectSoundImpl_Release(This
->pds
);
419 HeapFree(GetProcessHeap(), 0, This
);
420 TRACE("(%p) released\n", This
);
425 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
427 LPCDSBUFFERDESC dsbd
,
428 LPLPDIRECTSOUNDBUFFER ppdsb
,
431 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
432 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
433 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,FALSE
);
436 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
440 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
441 TRACE("(%p,%p)\n",This
,lpDSCaps
);
442 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
445 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
447 LPDIRECTSOUNDBUFFER psb
,
448 LPLPDIRECTSOUNDBUFFER ppdsb
)
450 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
451 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
452 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
455 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
460 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
461 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
462 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
465 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
468 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
469 TRACE("(%p)\n", This
);
470 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
473 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
475 LPDWORD lpdwSpeakerConfig
)
477 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
478 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
479 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
482 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
486 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
487 TRACE("(%p,0x%08x)\n",This
,config
);
488 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
491 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
495 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
496 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
497 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
500 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
502 IDirectSound_IDirectSound_QueryInterface
,
503 IDirectSound_IDirectSound_AddRef
,
504 IDirectSound_IDirectSound_Release
,
505 IDirectSound_IDirectSound_CreateSoundBuffer
,
506 IDirectSound_IDirectSound_GetCaps
,
507 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
508 IDirectSound_IDirectSound_SetCooperativeLevel
,
509 IDirectSound_IDirectSound_Compact
,
510 IDirectSound_IDirectSound_GetSpeakerConfig
,
511 IDirectSound_IDirectSound_SetSpeakerConfig
,
512 IDirectSound_IDirectSound_Initialize
515 static HRESULT
IDirectSound_IDirectSound_Create(
517 LPDIRECTSOUND
* ppds
)
519 IDirectSound_IDirectSound
* pdsds
;
520 TRACE("(%p,%p)\n",pds
,ppds
);
523 ERR("invalid parameter: ppds == NULL\n");
524 return DSERR_INVALIDPARAM
;
528 ERR("invalid parameter: pds == NULL\n");
530 return DSERR_INVALIDPARAM
;
533 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
535 WARN("out of memory\n");
537 return DSERR_OUTOFMEMORY
;
540 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
544 IDirectSoundImpl_AddRef(pds
);
545 *ppds
= (LPDIRECTSOUND
)pdsds
;
550 /*******************************************************************************
551 * IDirectSound8_IUnknown
553 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
558 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
559 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
560 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
563 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
566 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
567 ULONG ref
= InterlockedIncrement(&(This
->ref
));
568 TRACE("(%p) ref was %d\n", This
, ref
- 1);
572 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
575 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
576 ULONG ref
= InterlockedDecrement(&(This
->ref
));
577 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
579 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
580 IDirectSoundImpl_Release(This
->pds
);
581 HeapFree(GetProcessHeap(), 0, This
);
582 TRACE("(%p) released\n", This
);
587 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
589 IDirectSound8_IUnknown_QueryInterface
,
590 IDirectSound8_IUnknown_AddRef
,
591 IDirectSound8_IUnknown_Release
594 static HRESULT
IDirectSound8_IUnknown_Create(
598 IDirectSound8_IUnknown
* pdsunk
;
599 TRACE("(%p,%p)\n",pds
,ppunk
);
602 ERR("invalid parameter: ppunk == NULL\n");
603 return DSERR_INVALIDPARAM
;
607 ERR("invalid parameter: pds == NULL\n");
609 return DSERR_INVALIDPARAM
;
612 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
613 if (pdsunk
== NULL
) {
614 WARN("out of memory\n");
616 return DSERR_OUTOFMEMORY
;
619 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
623 IDirectSoundImpl_AddRef(pds
);
624 *ppunk
= (LPUNKNOWN
)pdsunk
;
629 /*******************************************************************************
630 * IDirectSound8_IDirectSound
632 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
637 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
638 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
639 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
642 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
645 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
646 ULONG ref
= InterlockedIncrement(&(This
->ref
));
647 TRACE("(%p) ref was %d\n", This
, ref
- 1);
651 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
654 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
655 ULONG ref
= InterlockedDecrement(&(This
->ref
));
656 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
658 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
659 IDirectSoundImpl_Release(This
->pds
);
660 HeapFree(GetProcessHeap(), 0, This
);
661 TRACE("(%p) released\n", This
);
666 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
668 LPCDSBUFFERDESC dsbd
,
669 LPLPDIRECTSOUNDBUFFER ppdsb
,
672 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
673 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
674 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
677 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
681 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
682 TRACE("(%p,%p)\n",This
,lpDSCaps
);
683 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
686 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
688 LPDIRECTSOUNDBUFFER psb
,
689 LPLPDIRECTSOUNDBUFFER ppdsb
)
691 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
692 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
693 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
696 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
701 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
702 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
703 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
706 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
709 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
710 TRACE("(%p)\n", This
);
711 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
714 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
716 LPDWORD lpdwSpeakerConfig
)
718 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
719 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
720 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
723 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
727 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
728 TRACE("(%p,0x%08x)\n",This
,config
);
729 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
732 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
736 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
737 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
738 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
741 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
743 IDirectSound8_IDirectSound_QueryInterface
,
744 IDirectSound8_IDirectSound_AddRef
,
745 IDirectSound8_IDirectSound_Release
,
746 IDirectSound8_IDirectSound_CreateSoundBuffer
,
747 IDirectSound8_IDirectSound_GetCaps
,
748 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
749 IDirectSound8_IDirectSound_SetCooperativeLevel
,
750 IDirectSound8_IDirectSound_Compact
,
751 IDirectSound8_IDirectSound_GetSpeakerConfig
,
752 IDirectSound8_IDirectSound_SetSpeakerConfig
,
753 IDirectSound8_IDirectSound_Initialize
756 static HRESULT
IDirectSound8_IDirectSound_Create(
758 LPDIRECTSOUND
* ppds
)
760 IDirectSound8_IDirectSound
* pdsds
;
761 TRACE("(%p,%p)\n",pds
,ppds
);
764 ERR("invalid parameter: ppds == NULL\n");
765 return DSERR_INVALIDPARAM
;
769 ERR("invalid parameter: pds == NULL\n");
771 return DSERR_INVALIDPARAM
;
774 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
776 WARN("out of memory\n");
778 return DSERR_OUTOFMEMORY
;
781 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
785 IDirectSoundImpl_AddRef(pds
);
786 *ppds
= (LPDIRECTSOUND
)pdsds
;
791 /*******************************************************************************
792 * IDirectSound8_IDirectSound8
794 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
795 LPDIRECTSOUND8 iface
,
799 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
800 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
801 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
804 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
805 LPDIRECTSOUND8 iface
)
807 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
808 ULONG ref
= InterlockedIncrement(&(This
->ref
));
809 TRACE("(%p) ref was %d\n", This
, ref
- 1);
813 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
814 LPDIRECTSOUND8 iface
)
816 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
817 ULONG ref
= InterlockedDecrement(&(This
->ref
));
818 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
820 ((IDirectSoundImpl
*)This
->pds
)->pDS8
= NULL
;
821 IDirectSoundImpl_Release(This
->pds
);
822 HeapFree(GetProcessHeap(), 0, This
);
823 TRACE("(%p) released\n", This
);
828 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
829 LPDIRECTSOUND8 iface
,
830 LPCDSBUFFERDESC dsbd
,
831 LPLPDIRECTSOUNDBUFFER ppdsb
,
834 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
835 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
836 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
839 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
840 LPDIRECTSOUND8 iface
,
843 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
844 TRACE("(%p,%p)\n",This
,lpDSCaps
);
845 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
848 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
849 LPDIRECTSOUND8 iface
,
850 LPDIRECTSOUNDBUFFER psb
,
851 LPLPDIRECTSOUNDBUFFER ppdsb
)
853 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
854 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
855 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
858 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
859 LPDIRECTSOUND8 iface
,
863 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
864 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
865 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
868 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
869 LPDIRECTSOUND8 iface
)
871 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
872 TRACE("(%p)\n", This
);
873 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
876 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
877 LPDIRECTSOUND8 iface
,
878 LPDWORD lpdwSpeakerConfig
)
880 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
881 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
882 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
885 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
886 LPDIRECTSOUND8 iface
,
889 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
890 TRACE("(%p,0x%08x)\n",This
,config
);
891 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
894 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
895 LPDIRECTSOUND8 iface
,
898 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
899 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
900 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
903 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
904 LPDIRECTSOUND8 iface
,
905 LPDWORD pdwCertified
)
907 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
908 TRACE("(%p, %p)\n", This
, pdwCertified
);
909 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
912 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
914 IDirectSound8_IDirectSound8_QueryInterface
,
915 IDirectSound8_IDirectSound8_AddRef
,
916 IDirectSound8_IDirectSound8_Release
,
917 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
918 IDirectSound8_IDirectSound8_GetCaps
,
919 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
920 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
921 IDirectSound8_IDirectSound8_Compact
,
922 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
923 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
924 IDirectSound8_IDirectSound8_Initialize
,
925 IDirectSound8_IDirectSound8_VerifyCertification
928 static HRESULT
IDirectSound8_IDirectSound8_Create(
930 LPDIRECTSOUND8
* ppds
)
932 IDirectSound8_IDirectSound8
* pdsds
;
933 TRACE("(%p,%p)\n",pds
,ppds
);
936 ERR("invalid parameter: ppds == NULL\n");
937 return DSERR_INVALIDPARAM
;
941 ERR("invalid parameter: pds == NULL\n");
943 return DSERR_INVALIDPARAM
;
946 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
948 WARN("out of memory\n");
950 return DSERR_OUTOFMEMORY
;
953 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
957 IDirectSoundImpl_AddRef(pds
);
958 *ppds
= (LPDIRECTSOUND8
)pdsds
;
963 HRESULT
DSOUND_Create(
969 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
971 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
972 !IsEqualIID(riid
, &IID_IDirectSound
)) {
974 return E_NOINTERFACE
;
977 /* Get dsound configuration */
978 setup_dsound_options();
980 hr
= IDirectSoundImpl_Create(&pDS
);
982 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
984 IDirectSound_IDirectSound_AddRef(*ppDS
);
986 WARN("IDirectSound_IDirectSound_Create failed\n");
987 IDirectSound8_Release(pDS
);
990 WARN("IDirectSoundImpl_Create failed\n");
997 /*******************************************************************************
998 * DirectSoundCreate (DSOUND.1)
1000 * Creates and initializes a DirectSound interface.
1003 * lpcGUID [I] Address of the GUID that identifies the sound device.
1004 * ppDS [O] Address of a variable to receive the interface pointer.
1005 * pUnkOuter [I] Must be NULL.
1009 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1010 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1012 HRESULT WINAPI
DirectSoundCreate(
1014 LPDIRECTSOUND
*ppDS
,
1015 IUnknown
*pUnkOuter
)
1020 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1023 WARN("invalid parameter: ppDS == NULL\n");
1024 return DSERR_INVALIDPARAM
;
1027 if (pUnkOuter
!= NULL
) {
1028 WARN("invalid parameter: pUnkOuter != NULL\n");
1030 return DSERR_INVALIDPARAM
;
1033 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
1035 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1037 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1038 IDirectSound_Release(pDS
);
1050 HRESULT
DSOUND_Create8(
1052 LPDIRECTSOUND8
*ppDS
)
1056 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
1058 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1059 !IsEqualIID(riid
, &IID_IDirectSound
) &&
1060 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
1062 return E_NOINTERFACE
;
1065 /* Get dsound configuration */
1066 setup_dsound_options();
1068 hr
= IDirectSoundImpl_Create(&pDS
);
1070 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1072 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1074 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1075 IDirectSound8_Release(pDS
);
1078 WARN("IDirectSoundImpl_Create failed\n");
1085 /*******************************************************************************
1086 * DirectSoundCreate8 (DSOUND.11)
1088 * Creates and initializes a DirectSound8 interface.
1091 * lpcGUID [I] Address of the GUID that identifies the sound device.
1092 * ppDS [O] Address of a variable to receive the interface pointer.
1093 * pUnkOuter [I] Must be NULL.
1097 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1098 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1100 HRESULT WINAPI
DirectSoundCreate8(
1102 LPDIRECTSOUND8
*ppDS
,
1103 IUnknown
*pUnkOuter
)
1108 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1111 WARN("invalid parameter: ppDS == NULL\n");
1112 return DSERR_INVALIDPARAM
;
1115 if (pUnkOuter
!= NULL
) {
1116 WARN("invalid parameter: pUnkOuter != NULL\n");
1118 return DSERR_INVALIDPARAM
;
1121 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
1123 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1125 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1126 IDirectSound8_Release(pDS
);
1138 /*******************************************************************************
1141 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1143 DirectSoundDevice
* device
;
1144 TRACE("(%p)\n", ppDevice
);
1146 /* Allocate memory */
1147 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1148 if (device
== NULL
) {
1149 WARN("out of memory\n");
1150 return DSERR_OUTOFMEMORY
;
1154 device
->priolevel
= DSSCL_NORMAL
;
1155 device
->state
= STATE_STOPPED
;
1156 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
1158 /* 3D listener initial parameters */
1159 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1160 device
->ds3dl
.vPosition
.x
= 0.0;
1161 device
->ds3dl
.vPosition
.y
= 0.0;
1162 device
->ds3dl
.vPosition
.z
= 0.0;
1163 device
->ds3dl
.vVelocity
.x
= 0.0;
1164 device
->ds3dl
.vVelocity
.y
= 0.0;
1165 device
->ds3dl
.vVelocity
.z
= 0.0;
1166 device
->ds3dl
.vOrientFront
.x
= 0.0;
1167 device
->ds3dl
.vOrientFront
.y
= 0.0;
1168 device
->ds3dl
.vOrientFront
.z
= 1.0;
1169 device
->ds3dl
.vOrientTop
.x
= 0.0;
1170 device
->ds3dl
.vOrientTop
.y
= 1.0;
1171 device
->ds3dl
.vOrientTop
.z
= 0.0;
1172 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1173 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1174 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1176 device
->prebuf
= ds_snd_queue_max
;
1177 device
->guid
= GUID_NULL
;
1179 /* Set default wave format (may need it for waveOutOpen) */
1180 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1181 if (device
->pwfx
== NULL
) {
1182 WARN("out of memory\n");
1183 HeapFree(GetProcessHeap(),0,device
);
1184 return DSERR_OUTOFMEMORY
;
1187 /* We rely on the sound driver to return the actual sound format of
1188 * the device if it does not support 22050x8x2 and is given the
1189 * WAVE_DIRECTSOUND flag.
1191 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1192 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1193 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1194 device
->pwfx
->nChannels
= 2;
1195 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1196 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1197 device
->pwfx
->cbSize
= 0;
1199 InitializeCriticalSection(&(device
->mixlock
));
1200 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
1202 RtlInitializeResource(&(device
->buffer_list_lock
));
1209 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1211 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1212 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1216 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1219 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1220 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1223 timeKillEvent(device
->timerID
);
1224 timeEndPeriod(DS_TIME_RES
);
1226 /* The kill event should have allowed the timer process to expire
1227 * but try to grab the lock just in case. Can't hold lock because
1228 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1229 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1230 RtlReleaseResource(&(device
->buffer_list_lock
));
1232 /* It is allowed to release this object even when buffers are playing */
1233 if (device
->buffers
) {
1234 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1235 for( i
=0;i
<device
->nrofbuffers
;i
++)
1236 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1239 if (device
->primary
) {
1240 WARN("primary buffer not released\n");
1241 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1244 hr
= DSOUND_PrimaryDestroy(device
);
1246 WARN("DSOUND_PrimaryDestroy failed\n");
1249 IDsDriver_Close(device
->driver
);
1251 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1252 waveOutClose(device
->hwo
);
1255 IDsDriver_Release(device
->driver
);
1257 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1259 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
1260 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
1261 if (device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
)
1262 HeapFree(GetProcessHeap(), 0, device
->buffer
);
1263 RtlDeleteResource(&device
->buffer_list_lock
);
1264 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1265 DeleteCriticalSection(&device
->mixlock
);
1266 HeapFree(GetProcessHeap(),0,device
);
1267 TRACE("(%p) released\n", device
);
1272 HRESULT
DirectSoundDevice_GetCaps(
1273 DirectSoundDevice
* device
,
1276 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1278 if (device
== NULL
) {
1279 WARN("not initialized\n");
1280 return DSERR_UNINITIALIZED
;
1283 if (lpDSCaps
== NULL
) {
1284 WARN("invalid parameter: lpDSCaps = NULL\n");
1285 return DSERR_INVALIDPARAM
;
1288 /* check if there is enough room */
1289 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1290 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1291 return DSERR_INVALIDPARAM
;
1294 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1295 if (TRACE_ON(dsound
)) {
1296 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1297 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1300 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1301 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1302 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1303 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1304 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1305 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1306 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1307 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1308 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1309 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1310 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1311 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1312 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1313 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1314 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1315 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1316 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1317 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1319 /* driver doesn't have these */
1320 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1321 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1326 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1330 BOOLEAN found
= FALSE
;
1332 DirectSoundDevice
* device
= *ppDevice
;
1333 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1335 if (*ppDevice
!= NULL
) {
1336 WARN("already initialized\n");
1337 return DSERR_ALREADYINITIALIZED
;
1340 /* Default device? */
1341 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1342 lpcGUID
= &DSDEVID_DefaultPlayback
;
1344 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1345 WARN("invalid parameter: lpcGUID\n");
1346 return DSERR_INVALIDPARAM
;
1349 /* Enumerate WINMM audio devices and find the one we want */
1350 wodn
= waveOutGetNumDevs();
1352 WARN("no driver\n");
1353 return DSERR_NODRIVER
;
1356 for (wod
=0; wod
<wodn
; wod
++) {
1357 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1363 if (found
== FALSE
) {
1364 WARN("No device found matching given ID!\n");
1365 return DSERR_NODRIVER
;
1368 if (DSOUND_renderer
[wod
]) {
1369 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1370 device
= DSOUND_renderer
[wod
];
1371 DirectSoundDevice_AddRef(device
);
1375 ERR("device GUID doesn't match\n");
1380 hr
= DirectSoundDevice_Create(&device
);
1382 WARN("DirectSoundDevice_Create failed\n");
1388 device
->guid
= devGUID
;
1389 device
->driver
= NULL
;
1391 device
->drvdesc
.dnDevNode
= wod
;
1392 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1395 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1399 if (device
->driver
) {
1400 /* the driver is now open, so it's now allowed to call GetCaps */
1401 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1403 WARN("IDsDriver_GetCaps failed\n");
1408 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1410 WARN("waveOutGetDevCaps failed\n");
1413 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1414 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1415 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1416 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1417 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1418 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1419 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1420 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1422 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1423 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1424 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1425 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1426 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1427 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1428 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1430 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1431 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1432 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1433 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1434 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1435 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1436 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1438 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1439 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1440 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1441 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1442 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1443 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1444 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1447 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1448 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1449 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1450 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1453 hr
= DSOUND_PrimaryCreate(device
);
1455 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1458 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1459 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1460 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1461 if (triggertime
< time
.wPeriodMin
)
1462 triggertime
= time
.wPeriodMin
;
1463 if (res
< time
.wPeriodMin
)
1464 res
= time
.wPeriodMin
;
1465 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1466 WARN("Could not set minimum resolution, don't expect sound\n");
1467 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1470 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1471 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
);
1472 if (!id
) ERR("Could not create timer, sound playback will not occur\n");
1474 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= id
;
1476 WARN("DSOUND_PrimaryCreate failed\n");
1482 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1483 DirectSoundDevice
* device
,
1484 LPCDSBUFFERDESC dsbd
,
1485 LPLPDIRECTSOUNDBUFFER ppdsb
,
1489 HRESULT hres
= DS_OK
;
1490 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1492 if (device
== NULL
) {
1493 WARN("not initialized\n");
1494 return DSERR_UNINITIALIZED
;
1498 WARN("invalid parameter: dsbd == NULL\n");
1499 return DSERR_INVALIDPARAM
;
1502 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1503 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1504 WARN("invalid parameter: dsbd\n");
1505 return DSERR_INVALIDPARAM
;
1508 if (ppdsb
== NULL
) {
1509 WARN("invalid parameter: ppdsb == NULL\n");
1510 return DSERR_INVALIDPARAM
;
1514 if (TRACE_ON(dsound
)) {
1515 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1516 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1517 _dump_DSBCAPS(dsbd
->dwFlags
);
1519 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1520 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1523 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1524 if (dsbd
->lpwfxFormat
!= NULL
) {
1525 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1526 "primary buffer\n");
1527 return DSERR_INVALIDPARAM
;
1530 if (device
->primary
) {
1531 WARN("Primary Buffer already created\n");
1532 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1533 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1535 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1536 if (device
->primary
) {
1537 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1538 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1540 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCHARDWARE
;
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
));