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"
41 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
45 /*****************************************************************************
46 * IDirectSound COM components
48 struct IDirectSound_IUnknown
{
49 const IUnknownVtbl
*lpVtbl
;
54 static HRESULT
IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
56 struct IDirectSound_IDirectSound
{
57 const IDirectSoundVtbl
*lpVtbl
;
62 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
64 /*****************************************************************************
65 * IDirectSound8 COM components
67 struct IDirectSound8_IUnknown
{
68 const IUnknownVtbl
*lpVtbl
;
73 static HRESULT
IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
74 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
76 struct IDirectSound8_IDirectSound
{
77 const IDirectSoundVtbl
*lpVtbl
;
82 static HRESULT
IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
83 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
85 struct IDirectSound8_IDirectSound8
{
86 const IDirectSound8Vtbl
*lpVtbl
;
91 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
92 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
94 /*****************************************************************************
95 * IDirectSound implementation structure
97 struct IDirectSoundImpl
101 DirectSoundDevice
*device
;
107 static HRESULT
IDirectSoundImpl_Create(LPDIRECTSOUND8
* ppds
);
109 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
110 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
112 const char * dumpCooperativeLevel(DWORD level
)
114 #define LE(x) case x: return #x
119 LE(DSSCL_WRITEPRIMARY
);
122 return wine_dbg_sprintf("Unknown(%08x)", level
);
125 static void _dump_DSCAPS(DWORD xmask
) {
130 #define FE(x) { x, #x },
131 FE(DSCAPS_PRIMARYMONO
)
132 FE(DSCAPS_PRIMARYSTEREO
)
133 FE(DSCAPS_PRIMARY8BIT
)
134 FE(DSCAPS_PRIMARY16BIT
)
135 FE(DSCAPS_CONTINUOUSRATE
)
136 FE(DSCAPS_EMULDRIVER
)
138 FE(DSCAPS_SECONDARYMONO
)
139 FE(DSCAPS_SECONDARYSTEREO
)
140 FE(DSCAPS_SECONDARY8BIT
)
141 FE(DSCAPS_SECONDARY16BIT
)
146 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
147 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
148 TRACE("%s ",flags
[i
].name
);
151 static void _dump_DSBCAPS(DWORD xmask
) {
156 #define FE(x) { x, #x },
157 FE(DSBCAPS_PRIMARYBUFFER
)
159 FE(DSBCAPS_LOCHARDWARE
)
160 FE(DSBCAPS_LOCSOFTWARE
)
162 FE(DSBCAPS_CTRLFREQUENCY
)
164 FE(DSBCAPS_CTRLVOLUME
)
165 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
166 FE(DSBCAPS_STICKYFOCUS
)
167 FE(DSBCAPS_GLOBALFOCUS
)
168 FE(DSBCAPS_GETCURRENTPOSITION2
)
169 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
174 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
175 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
176 TRACE("%s ",flags
[i
].name
);
179 /*******************************************************************************
180 * IDirectSoundImpl_DirectSound
182 static HRESULT
DSOUND_QueryInterface(
183 LPDIRECTSOUND8 iface
,
187 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
188 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
191 WARN("invalid parameter\n");
195 if (IsEqualIID(riid
, &IID_IUnknown
)) {
196 if (!This
->pUnknown
) {
197 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
198 if (!This
->pUnknown
) {
199 WARN("IDirectSound_IUnknown_Create() failed\n");
201 return E_NOINTERFACE
;
204 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
205 *ppobj
= This
->pUnknown
;
207 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
209 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
211 WARN("IDirectSound_IDirectSound_Create() failed\n");
213 return E_NOINTERFACE
;
216 IDirectSound_IDirectSound_AddRef(This
->pDS
);
222 WARN("Unknown IID %s\n",debugstr_guid(riid
));
223 return E_NOINTERFACE
;
226 static HRESULT
DSOUND_QueryInterface8(
227 LPDIRECTSOUND8 iface
,
231 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
232 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
235 WARN("invalid parameter\n");
239 if (IsEqualIID(riid
, &IID_IUnknown
)) {
240 if (!This
->pUnknown
) {
241 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
242 if (!This
->pUnknown
) {
243 WARN("IDirectSound8_IUnknown_Create() failed\n");
245 return E_NOINTERFACE
;
248 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
249 *ppobj
= This
->pUnknown
;
251 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
253 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
255 WARN("IDirectSound8_IDirectSound_Create() failed\n");
257 return E_NOINTERFACE
;
260 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
263 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
265 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
267 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
269 return E_NOINTERFACE
;
272 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
278 WARN("Unknown IID %s\n",debugstr_guid(riid
));
279 return E_NOINTERFACE
;
282 static ULONG
IDirectSoundImpl_AddRef(
283 LPDIRECTSOUND8 iface
)
285 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
286 ULONG ref
= InterlockedIncrement(&(This
->ref
));
287 TRACE("(%p) ref was %d\n", This
, ref
- 1);
291 static ULONG
IDirectSoundImpl_Release(
292 LPDIRECTSOUND8 iface
)
294 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
295 ULONG ref
= InterlockedDecrement(&(This
->ref
));
296 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
300 DirectSoundDevice_Release(This
->device
);
301 HeapFree(GetProcessHeap(),0,This
);
302 TRACE("(%p) released\n", This
);
307 static HRESULT
IDirectSoundImpl_Create(
308 LPDIRECTSOUND8
* ppDS
)
310 IDirectSoundImpl
* pDS
;
311 TRACE("(%p)\n",ppDS
);
313 /* Allocate memory */
314 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
316 WARN("out of memory\n");
318 return DSERR_OUTOFMEMORY
;
324 *ppDS
= (LPDIRECTSOUND8
)pDS
;
329 /*******************************************************************************
330 * IDirectSound_IUnknown
332 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
337 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
338 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
339 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
342 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
345 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
346 ULONG ref
= InterlockedIncrement(&(This
->ref
));
347 TRACE("(%p) ref was %d\n", This
, ref
- 1);
351 static ULONG WINAPI
IDirectSound_IUnknown_Release(
354 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
355 ULONG ref
= InterlockedDecrement(&(This
->ref
));
356 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
358 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
359 IDirectSoundImpl_Release(This
->pds
);
360 HeapFree(GetProcessHeap(), 0, This
);
361 TRACE("(%p) released\n", This
);
366 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
368 IDirectSound_IUnknown_QueryInterface
,
369 IDirectSound_IUnknown_AddRef
,
370 IDirectSound_IUnknown_Release
373 static HRESULT
IDirectSound_IUnknown_Create(
377 IDirectSound_IUnknown
* pdsunk
;
378 TRACE("(%p,%p)\n",pds
,ppunk
);
381 ERR("invalid parameter: ppunk == NULL\n");
382 return DSERR_INVALIDPARAM
;
386 ERR("invalid parameter: pds == NULL\n");
388 return DSERR_INVALIDPARAM
;
391 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
392 if (pdsunk
== NULL
) {
393 WARN("out of memory\n");
395 return DSERR_OUTOFMEMORY
;
398 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
402 IDirectSoundImpl_AddRef(pds
);
403 *ppunk
= (LPUNKNOWN
)pdsunk
;
408 /*******************************************************************************
409 * IDirectSound_IDirectSound
411 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
416 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
417 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
418 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
421 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
424 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
425 ULONG ref
= InterlockedIncrement(&(This
->ref
));
426 TRACE("(%p) ref was %d\n", This
, ref
- 1);
430 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
433 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
434 ULONG ref
= InterlockedDecrement(&(This
->ref
));
435 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
437 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
438 IDirectSoundImpl_Release(This
->pds
);
439 HeapFree(GetProcessHeap(), 0, This
);
440 TRACE("(%p) released\n", This
);
445 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
447 LPCDSBUFFERDESC dsbd
,
448 LPLPDIRECTSOUNDBUFFER ppdsb
,
451 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
452 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
453 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,FALSE
);
456 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
460 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
461 TRACE("(%p,%p)\n",This
,lpDSCaps
);
462 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
465 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
467 LPDIRECTSOUNDBUFFER psb
,
468 LPLPDIRECTSOUNDBUFFER ppdsb
)
470 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
471 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
472 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
475 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
480 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
481 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
482 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
485 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
488 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
489 TRACE("(%p)\n", This
);
490 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
493 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
495 LPDWORD lpdwSpeakerConfig
)
497 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
498 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
499 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
502 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
506 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
507 TRACE("(%p,0x%08x)\n",This
,config
);
508 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
511 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
515 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
516 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
517 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
520 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
522 IDirectSound_IDirectSound_QueryInterface
,
523 IDirectSound_IDirectSound_AddRef
,
524 IDirectSound_IDirectSound_Release
,
525 IDirectSound_IDirectSound_CreateSoundBuffer
,
526 IDirectSound_IDirectSound_GetCaps
,
527 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
528 IDirectSound_IDirectSound_SetCooperativeLevel
,
529 IDirectSound_IDirectSound_Compact
,
530 IDirectSound_IDirectSound_GetSpeakerConfig
,
531 IDirectSound_IDirectSound_SetSpeakerConfig
,
532 IDirectSound_IDirectSound_Initialize
535 static HRESULT
IDirectSound_IDirectSound_Create(
537 LPDIRECTSOUND
* ppds
)
539 IDirectSound_IDirectSound
* pdsds
;
540 TRACE("(%p,%p)\n",pds
,ppds
);
543 ERR("invalid parameter: ppds == NULL\n");
544 return DSERR_INVALIDPARAM
;
548 ERR("invalid parameter: pds == NULL\n");
550 return DSERR_INVALIDPARAM
;
553 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
555 WARN("out of memory\n");
557 return DSERR_OUTOFMEMORY
;
560 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
564 IDirectSoundImpl_AddRef(pds
);
565 *ppds
= (LPDIRECTSOUND
)pdsds
;
570 /*******************************************************************************
571 * IDirectSound8_IUnknown
573 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
578 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
579 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
580 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
583 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
586 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
587 ULONG ref
= InterlockedIncrement(&(This
->ref
));
588 TRACE("(%p) ref was %d\n", This
, ref
- 1);
592 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
595 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
596 ULONG ref
= InterlockedDecrement(&(This
->ref
));
597 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
599 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
600 IDirectSoundImpl_Release(This
->pds
);
601 HeapFree(GetProcessHeap(), 0, This
);
602 TRACE("(%p) released\n", This
);
607 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
609 IDirectSound8_IUnknown_QueryInterface
,
610 IDirectSound8_IUnknown_AddRef
,
611 IDirectSound8_IUnknown_Release
614 static HRESULT
IDirectSound8_IUnknown_Create(
618 IDirectSound8_IUnknown
* pdsunk
;
619 TRACE("(%p,%p)\n",pds
,ppunk
);
622 ERR("invalid parameter: ppunk == NULL\n");
623 return DSERR_INVALIDPARAM
;
627 ERR("invalid parameter: pds == NULL\n");
629 return DSERR_INVALIDPARAM
;
632 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
633 if (pdsunk
== NULL
) {
634 WARN("out of memory\n");
636 return DSERR_OUTOFMEMORY
;
639 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
643 IDirectSoundImpl_AddRef(pds
);
644 *ppunk
= (LPUNKNOWN
)pdsunk
;
649 /*******************************************************************************
650 * IDirectSound8_IDirectSound
652 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
657 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
658 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
659 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
662 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
665 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
666 ULONG ref
= InterlockedIncrement(&(This
->ref
));
667 TRACE("(%p) ref was %d\n", This
, ref
- 1);
671 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
674 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
675 ULONG ref
= InterlockedDecrement(&(This
->ref
));
676 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
678 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
679 IDirectSoundImpl_Release(This
->pds
);
680 HeapFree(GetProcessHeap(), 0, This
);
681 TRACE("(%p) released\n", This
);
686 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
688 LPCDSBUFFERDESC dsbd
,
689 LPLPDIRECTSOUNDBUFFER ppdsb
,
692 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
693 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
694 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
697 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
701 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
702 TRACE("(%p,%p)\n",This
,lpDSCaps
);
703 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
706 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
708 LPDIRECTSOUNDBUFFER psb
,
709 LPLPDIRECTSOUNDBUFFER ppdsb
)
711 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
712 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
713 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
716 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
721 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
722 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
723 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
726 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
729 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
730 TRACE("(%p)\n", This
);
731 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
734 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
736 LPDWORD lpdwSpeakerConfig
)
738 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
739 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
740 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
743 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
747 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
748 TRACE("(%p,0x%08x)\n",This
,config
);
749 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
752 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
756 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
757 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
758 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
761 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
763 IDirectSound8_IDirectSound_QueryInterface
,
764 IDirectSound8_IDirectSound_AddRef
,
765 IDirectSound8_IDirectSound_Release
,
766 IDirectSound8_IDirectSound_CreateSoundBuffer
,
767 IDirectSound8_IDirectSound_GetCaps
,
768 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
769 IDirectSound8_IDirectSound_SetCooperativeLevel
,
770 IDirectSound8_IDirectSound_Compact
,
771 IDirectSound8_IDirectSound_GetSpeakerConfig
,
772 IDirectSound8_IDirectSound_SetSpeakerConfig
,
773 IDirectSound8_IDirectSound_Initialize
776 static HRESULT
IDirectSound8_IDirectSound_Create(
778 LPDIRECTSOUND
* ppds
)
780 IDirectSound8_IDirectSound
* pdsds
;
781 TRACE("(%p,%p)\n",pds
,ppds
);
784 ERR("invalid parameter: ppds == NULL\n");
785 return DSERR_INVALIDPARAM
;
789 ERR("invalid parameter: pds == NULL\n");
791 return DSERR_INVALIDPARAM
;
794 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
796 WARN("out of memory\n");
798 return DSERR_OUTOFMEMORY
;
801 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
805 IDirectSoundImpl_AddRef(pds
);
806 *ppds
= (LPDIRECTSOUND
)pdsds
;
811 /*******************************************************************************
812 * IDirectSound8_IDirectSound8
814 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
815 LPDIRECTSOUND8 iface
,
819 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
820 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
821 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
824 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
825 LPDIRECTSOUND8 iface
)
827 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
828 ULONG ref
= InterlockedIncrement(&(This
->ref
));
829 TRACE("(%p) ref was %d\n", This
, ref
- 1);
833 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
834 LPDIRECTSOUND8 iface
)
836 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
837 ULONG ref
= InterlockedDecrement(&(This
->ref
));
838 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
840 ((IDirectSoundImpl
*)This
->pds
)->pDS8
= NULL
;
841 IDirectSoundImpl_Release(This
->pds
);
842 HeapFree(GetProcessHeap(), 0, This
);
843 TRACE("(%p) released\n", This
);
848 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
849 LPDIRECTSOUND8 iface
,
850 LPCDSBUFFERDESC dsbd
,
851 LPLPDIRECTSOUNDBUFFER ppdsb
,
854 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
855 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
856 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
859 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
860 LPDIRECTSOUND8 iface
,
863 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
864 TRACE("(%p,%p)\n",This
,lpDSCaps
);
865 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
868 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
869 LPDIRECTSOUND8 iface
,
870 LPDIRECTSOUNDBUFFER psb
,
871 LPLPDIRECTSOUNDBUFFER ppdsb
)
873 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
874 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
875 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
878 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
879 LPDIRECTSOUND8 iface
,
883 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
884 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
885 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
888 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
889 LPDIRECTSOUND8 iface
)
891 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
892 TRACE("(%p)\n", This
);
893 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
896 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
897 LPDIRECTSOUND8 iface
,
898 LPDWORD lpdwSpeakerConfig
)
900 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
901 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
902 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
905 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
906 LPDIRECTSOUND8 iface
,
909 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
910 TRACE("(%p,0x%08x)\n",This
,config
);
911 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
914 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
915 LPDIRECTSOUND8 iface
,
918 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
919 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
920 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
923 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
924 LPDIRECTSOUND8 iface
,
925 LPDWORD pdwCertified
)
927 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
928 TRACE("(%p, %p)\n", This
, pdwCertified
);
929 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
932 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
934 IDirectSound8_IDirectSound8_QueryInterface
,
935 IDirectSound8_IDirectSound8_AddRef
,
936 IDirectSound8_IDirectSound8_Release
,
937 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
938 IDirectSound8_IDirectSound8_GetCaps
,
939 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
940 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
941 IDirectSound8_IDirectSound8_Compact
,
942 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
943 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
944 IDirectSound8_IDirectSound8_Initialize
,
945 IDirectSound8_IDirectSound8_VerifyCertification
948 static HRESULT
IDirectSound8_IDirectSound8_Create(
950 LPDIRECTSOUND8
* ppds
)
952 IDirectSound8_IDirectSound8
* pdsds
;
953 TRACE("(%p,%p)\n",pds
,ppds
);
956 ERR("invalid parameter: ppds == NULL\n");
957 return DSERR_INVALIDPARAM
;
961 ERR("invalid parameter: pds == NULL\n");
963 return DSERR_INVALIDPARAM
;
966 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
968 WARN("out of memory\n");
970 return DSERR_OUTOFMEMORY
;
973 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
977 IDirectSoundImpl_AddRef(pds
);
978 *ppds
= (LPDIRECTSOUND8
)pdsds
;
983 HRESULT
DSOUND_Create(
989 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
991 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
992 !IsEqualIID(riid
, &IID_IDirectSound
)) {
994 return E_NOINTERFACE
;
997 /* Get dsound configuration */
998 setup_dsound_options();
1000 hr
= IDirectSoundImpl_Create(&pDS
);
1002 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1004 IDirectSound_IDirectSound_AddRef(*ppDS
);
1006 WARN("IDirectSound_IDirectSound_Create failed\n");
1007 IDirectSound8_Release(pDS
);
1010 WARN("IDirectSoundImpl_Create failed\n");
1017 /*******************************************************************************
1018 * DirectSoundCreate (DSOUND.1)
1020 * Creates and initializes a DirectSound interface.
1023 * lpcGUID [I] Address of the GUID that identifies the sound device.
1024 * ppDS [O] Address of a variable to receive the interface pointer.
1025 * pUnkOuter [I] Must be NULL.
1029 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1030 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1032 HRESULT WINAPI
DirectSoundCreate(
1034 LPDIRECTSOUND
*ppDS
,
1035 IUnknown
*pUnkOuter
)
1040 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1043 WARN("invalid parameter: ppDS == NULL\n");
1044 return DSERR_INVALIDPARAM
;
1047 if (pUnkOuter
!= NULL
) {
1048 WARN("invalid parameter: pUnkOuter != NULL\n");
1050 return DSERR_INVALIDPARAM
;
1053 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
1055 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1057 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1058 IDirectSound_Release(pDS
);
1070 HRESULT
DSOUND_Create8(
1072 LPDIRECTSOUND8
*ppDS
)
1076 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
1078 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1079 !IsEqualIID(riid
, &IID_IDirectSound
) &&
1080 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
1082 return E_NOINTERFACE
;
1085 /* Get dsound configuration */
1086 setup_dsound_options();
1088 hr
= IDirectSoundImpl_Create(&pDS
);
1090 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1092 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1094 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1095 IDirectSound8_Release(pDS
);
1098 WARN("IDirectSoundImpl_Create failed\n");
1105 /*******************************************************************************
1106 * DirectSoundCreate8 (DSOUND.11)
1108 * Creates and initializes a DirectSound8 interface.
1111 * lpcGUID [I] Address of the GUID that identifies the sound device.
1112 * ppDS [O] Address of a variable to receive the interface pointer.
1113 * pUnkOuter [I] Must be NULL.
1117 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1118 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1120 HRESULT WINAPI
DirectSoundCreate8(
1122 LPDIRECTSOUND8
*ppDS
,
1123 IUnknown
*pUnkOuter
)
1128 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1131 WARN("invalid parameter: ppDS == NULL\n");
1132 return DSERR_INVALIDPARAM
;
1135 if (pUnkOuter
!= NULL
) {
1136 WARN("invalid parameter: pUnkOuter != NULL\n");
1138 return DSERR_INVALIDPARAM
;
1141 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
1143 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1145 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1146 IDirectSound8_Release(pDS
);
1158 /*******************************************************************************
1161 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1163 DirectSoundDevice
* device
;
1164 TRACE("(%p)\n", ppDevice
);
1166 /* Allocate memory */
1167 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1168 if (device
== NULL
) {
1169 WARN("out of memory\n");
1170 return DSERR_OUTOFMEMORY
;
1174 device
->priolevel
= DSSCL_NORMAL
;
1175 device
->state
= STATE_STOPPED
;
1176 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
1178 /* 3D listener initial parameters */
1179 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1180 device
->ds3dl
.vPosition
.x
= 0.0;
1181 device
->ds3dl
.vPosition
.y
= 0.0;
1182 device
->ds3dl
.vPosition
.z
= 0.0;
1183 device
->ds3dl
.vVelocity
.x
= 0.0;
1184 device
->ds3dl
.vVelocity
.y
= 0.0;
1185 device
->ds3dl
.vVelocity
.z
= 0.0;
1186 device
->ds3dl
.vOrientFront
.x
= 0.0;
1187 device
->ds3dl
.vOrientFront
.y
= 0.0;
1188 device
->ds3dl
.vOrientFront
.z
= 1.0;
1189 device
->ds3dl
.vOrientTop
.x
= 0.0;
1190 device
->ds3dl
.vOrientTop
.y
= 1.0;
1191 device
->ds3dl
.vOrientTop
.z
= 0.0;
1192 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1193 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1194 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1196 device
->prebuf
= ds_snd_queue_max
;
1197 device
->guid
= GUID_NULL
;
1199 /* Set default wave format (may need it for waveOutOpen) */
1200 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1201 if (device
->pwfx
== NULL
) {
1202 WARN("out of memory\n");
1203 HeapFree(GetProcessHeap(),0,device
);
1204 return DSERR_OUTOFMEMORY
;
1207 /* We rely on the sound driver to return the actual sound format of
1208 * the device if it does not support 22050x8x2 and is given the
1209 * WAVE_DIRECTSOUND flag.
1211 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1212 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1213 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1214 device
->pwfx
->nChannels
= 2;
1215 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1216 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1217 device
->pwfx
->cbSize
= 0;
1219 InitializeCriticalSection(&(device
->mixlock
));
1220 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
1222 RtlInitializeResource(&(device
->buffer_list_lock
));
1229 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1231 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1232 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1236 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1239 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1240 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1243 timeKillEvent(device
->timerID
);
1244 timeEndPeriod(DS_TIME_RES
);
1246 /* The kill event should have allowed the timer process to expire
1247 * but try to grab the lock just in case. Can't hold lock because
1248 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1249 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1250 RtlReleaseResource(&(device
->buffer_list_lock
));
1252 /* It is allowed to release this object even when buffers are playing */
1253 if (device
->buffers
) {
1254 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1255 for( i
=0;i
<device
->nrofbuffers
;i
++)
1256 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1259 if (device
->primary
) {
1260 WARN("primary buffer not released\n");
1261 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1264 hr
= DSOUND_PrimaryDestroy(device
);
1266 WARN("DSOUND_PrimaryDestroy failed\n");
1269 IDsDriver_Close(device
->driver
);
1271 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1272 waveOutClose(device
->hwo
);
1275 IDsDriver_Release(device
->driver
);
1277 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1279 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
1280 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
1281 if (device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
)
1282 HeapFree(GetProcessHeap(), 0, device
->buffer
);
1283 RtlDeleteResource(&device
->buffer_list_lock
);
1284 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1285 DeleteCriticalSection(&device
->mixlock
);
1286 HeapFree(GetProcessHeap(),0,device
);
1287 TRACE("(%p) released\n", device
);
1292 HRESULT
DirectSoundDevice_GetCaps(
1293 DirectSoundDevice
* device
,
1296 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1298 if (device
== NULL
) {
1299 WARN("not initialized\n");
1300 return DSERR_UNINITIALIZED
;
1303 if (lpDSCaps
== NULL
) {
1304 WARN("invalid parameter: lpDSCaps = NULL\n");
1305 return DSERR_INVALIDPARAM
;
1308 /* check if there is enough room */
1309 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1310 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1311 return DSERR_INVALIDPARAM
;
1314 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1315 if (TRACE_ON(dsound
)) {
1316 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1317 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1320 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1321 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1322 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1323 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1324 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1325 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1326 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1327 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1328 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1329 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1330 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1331 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1332 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1333 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1334 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1335 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1336 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1337 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1339 /* driver doesn't have these */
1340 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1341 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1346 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1350 BOOLEAN found
= FALSE
;
1352 DirectSoundDevice
* device
= *ppDevice
;
1353 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1355 if (*ppDevice
!= NULL
) {
1356 WARN("already initialized\n");
1357 return DSERR_ALREADYINITIALIZED
;
1360 /* Default device? */
1361 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1362 lpcGUID
= &DSDEVID_DefaultPlayback
;
1364 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1365 WARN("invalid parameter: lpcGUID\n");
1366 return DSERR_INVALIDPARAM
;
1369 /* Enumerate WINMM audio devices and find the one we want */
1370 wodn
= waveOutGetNumDevs();
1372 WARN("no driver\n");
1373 return DSERR_NODRIVER
;
1376 for (wod
=0; wod
<wodn
; wod
++) {
1377 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1383 if (found
== FALSE
) {
1384 WARN("No device found matching given ID!\n");
1385 return DSERR_NODRIVER
;
1388 if (DSOUND_renderer
[wod
]) {
1389 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1390 device
= DSOUND_renderer
[wod
];
1391 DirectSoundDevice_AddRef(device
);
1395 ERR("device GUID doesn't match\n");
1400 hr
= DirectSoundDevice_Create(&device
);
1402 WARN("DirectSoundDevice_Create failed\n");
1408 device
->guid
= devGUID
;
1409 device
->driver
= NULL
;
1411 device
->drvdesc
.dnDevNode
= wod
;
1412 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1415 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1419 if (device
->driver
) {
1420 /* the driver is now open, so it's now allowed to call GetCaps */
1421 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1423 WARN("IDsDriver_GetCaps failed\n");
1428 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1430 WARN("waveOutGetDevCaps failed\n");
1433 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1434 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1435 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1436 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1437 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1438 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1439 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1440 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1442 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1443 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1444 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1445 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1446 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1447 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1448 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1450 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1451 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1452 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1453 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1454 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1455 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1456 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1458 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1459 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1460 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1461 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1462 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1463 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1464 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1467 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1468 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1469 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1470 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1473 hr
= DSOUND_PrimaryCreate(device
);
1475 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1478 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1479 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1480 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1481 if (triggertime
< time
.wPeriodMin
)
1482 triggertime
= time
.wPeriodMin
;
1483 if (res
< time
.wPeriodMin
)
1484 res
= time
.wPeriodMin
;
1485 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1486 WARN("Could not set minimum resolution, don't expect sound\n");
1487 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1490 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1491 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
);
1492 if (!id
) ERR("Could not create timer, sound playback will not occur\n");
1494 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= id
;
1496 WARN("DSOUND_PrimaryCreate failed\n");
1502 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1503 DirectSoundDevice
* device
,
1504 LPCDSBUFFERDESC dsbd
,
1505 LPLPDIRECTSOUNDBUFFER ppdsb
,
1509 HRESULT hres
= DS_OK
;
1510 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1512 if (device
== NULL
) {
1513 WARN("not initialized\n");
1514 return DSERR_UNINITIALIZED
;
1518 WARN("invalid parameter: dsbd == NULL\n");
1519 return DSERR_INVALIDPARAM
;
1522 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1523 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1524 WARN("invalid parameter: dsbd\n");
1525 return DSERR_INVALIDPARAM
;
1528 if (ppdsb
== NULL
) {
1529 WARN("invalid parameter: ppdsb == NULL\n");
1530 return DSERR_INVALIDPARAM
;
1534 if (TRACE_ON(dsound
)) {
1535 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1536 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1537 _dump_DSBCAPS(dsbd
->dwFlags
);
1539 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1540 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1543 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1544 if (dsbd
->lpwfxFormat
!= NULL
) {
1545 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1546 "primary buffer\n");
1547 return DSERR_INVALIDPARAM
;
1550 if (device
->primary
) {
1551 WARN("Primary Buffer already created\n");
1552 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1553 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1555 device
->dsbd
= *dsbd
;
1556 device
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1558 device
->dsbd
.dwFlags
|= DSBCAPS_LOCHARDWARE
;
1559 else device
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1560 hres
= PrimaryBufferImpl_Create(device
, &(device
->primary
), &(device
->dsbd
));
1561 if (device
->primary
) {
1562 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1563 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1565 WARN("PrimaryBufferImpl_Create failed\n");
1568 IDirectSoundBufferImpl
* dsb
;
1569 WAVEFORMATEXTENSIBLE
*pwfxe
;
1571 if (dsbd
->lpwfxFormat
== NULL
) {
1572 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1573 "secondary buffer\n");
1574 return DSERR_INVALIDPARAM
;
1576 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1578 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1580 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1581 return DSERR_CONTROLUNAVAIL
;
1583 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1585 /* check if cbSize is at least 22 bytes */
1586 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1588 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1589 return DSERR_INVALIDPARAM
;
1592 /* cbSize should be 22 bytes, with one possible exception */
1593 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1594 !(IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) &&
1595 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1597 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1598 return DSERR_CONTROLUNAVAIL
;
1601 if (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
1603 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1604 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1605 return DSERR_INVALIDPARAM
;
1607 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1609 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1610 return DSERR_INVALIDPARAM
;
1612 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1614 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1615 return DSERR_CONTROLUNAVAIL
;
1619 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1620 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1621 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1622 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1623 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1624 dsbd
->lpwfxFormat
->nBlockAlign
,
1625 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1627 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1628 WARN("invalid parameter: 3D buffer format must be mono\n");
1629 return DSERR_INVALIDPARAM
;
1632 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1634 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1636 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1637 IDirectSoundBuffer_AddRef(*ppdsb
);
1639 WARN("SecondaryBufferImpl_Create failed\n");
1641 WARN("IDirectSoundBufferImpl_Create failed\n");
1647 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1648 DirectSoundDevice
* device
,
1649 LPDIRECTSOUNDBUFFER psb
,
1650 LPLPDIRECTSOUNDBUFFER ppdsb
)
1652 HRESULT hres
= DS_OK
;
1653 IDirectSoundBufferImpl
* dsb
;
1654 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1656 if (device
== NULL
) {
1657 WARN("not initialized\n");
1658 return DSERR_UNINITIALIZED
;
1662 WARN("invalid parameter: psb == NULL\n");
1663 return DSERR_INVALIDPARAM
;
1666 if (ppdsb
== NULL
) {
1667 WARN("invalid parameter: ppdsb == NULL\n");
1668 return DSERR_INVALIDPARAM
;
1671 /* make sure we have a secondary buffer */
1672 if ((PrimaryBufferImpl
*)psb
== device
->primary
) {
1673 WARN("trying to duplicate primary buffer\n");
1675 return DSERR_INVALIDCALL
;
1678 /* duplicate the actual buffer implementation */
1679 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
,
1680 ((SecondaryBufferImpl
*)psb
)->dsb
);
1682 if (hres
== DS_OK
) {
1683 /* create a new secondary buffer using the new implementation */
1684 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1686 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1687 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
1689 WARN("SecondaryBufferImpl_Create failed\n");
1690 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)dsb
);
1691 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8
)dsb
);
1698 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1699 DirectSoundDevice
* device
,
1703 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1705 if (device
== NULL
) {
1706 WARN("not initialized\n");
1707 return DSERR_UNINITIALIZED
;
1710 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1711 WARN("level=%s not fully supported\n",
1712 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1715 device
->priolevel
= level
;
1719 HRESULT
DirectSoundDevice_Compact(
1720 DirectSoundDevice
* device
)
1722 TRACE("(%p)\n", device
);
1724 if (device
== NULL
) {
1725 WARN("not initialized\n");
1726 return DSERR_UNINITIALIZED
;
1729 if (device
->priolevel
< DSSCL_PRIORITY
) {
1730 WARN("incorrect priority level\n");
1731 return DSERR_PRIOLEVELNEEDED
;
1737 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1738 DirectSoundDevice
* device
,
1739 LPDWORD lpdwSpeakerConfig
)
1741 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1743 if (device
== NULL
) {
1744 WARN("not initialized\n");
1745 return DSERR_UNINITIALIZED
;
1748 if (lpdwSpeakerConfig
== NULL
) {
1749 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1750 return DSERR_INVALIDPARAM
;
1753 WARN("not fully functional\n");
1754 *lpdwSpeakerConfig
= device
->speaker_config
;
1758 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1759 DirectSoundDevice
* device
,
1762 TRACE("(%p,0x%08x)\n",device
,config
);
1764 if (device
== NULL
) {
1765 WARN("not initialized\n");
1766 return DSERR_UNINITIALIZED
;
1769 device
->speaker_config
= config
;
1770 WARN("not fully functional\n");
1774 HRESULT
DirectSoundDevice_VerifyCertification(
1775 DirectSoundDevice
* device
,
1776 LPDWORD pdwCertified
)
1778 TRACE("(%p, %p)\n",device
,pdwCertified
);
1780 if (device
== NULL
) {
1781 WARN("not initialized\n");
1782 return DSERR_UNINITIALIZED
;
1785 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1786 *pdwCertified
= DS_CERTIFIED
;
1788 *pdwCertified
= DS_UNCERTIFIED
;
1794 * Add secondary buffer to buffer list.
1795 * Gets exclusive access to buffer for writing.
1797 HRESULT
DirectSoundDevice_AddBuffer(
1798 DirectSoundDevice
* device
,
1799 IDirectSoundBufferImpl
* pDSB
)
1801 IDirectSoundBufferImpl
**newbuffers
;
1804 TRACE("(%p, %p)\n", device
, pDSB
);
1806 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1808 if (device
->buffers
)
1809 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1811 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1814 device
->buffers
= newbuffers
;
1815 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1816 device
->nrofbuffers
++;
1817 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1819 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1820 hr
= DSERR_OUTOFMEMORY
;
1823 RtlReleaseResource(&(device
->buffer_list_lock
));
1829 * Remove secondary buffer from buffer list.
1830 * Gets exclusive access to buffer for writing.
1832 HRESULT
DirectSoundDevice_RemoveBuffer(
1833 DirectSoundDevice
* device
,
1834 IDirectSoundBufferImpl
* pDSB
)
1839 TRACE("(%p, %p)\n", device
, pDSB
);
1841 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1843 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1844 if (device
->buffers
[i
] == pDSB
)
1847 if (i
< device
->nrofbuffers
) {
1848 /* Put the last buffer of the list in the (now empty) position */
1849 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1850 device
->nrofbuffers
--;
1851 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1852 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1855 if (device
->nrofbuffers
== 0) {
1856 HeapFree(GetProcessHeap(),0,device
->buffers
);
1857 device
->buffers
= NULL
;
1860 RtlReleaseResource(&(device
->buffer_list_lock
));