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 static HRESULT
DirectSoundDevice_VerifyCertification(DirectSoundDevice
* device
, LPDWORD pdwCertified
);
114 const char * dumpCooperativeLevel(DWORD level
)
116 static char unknown
[32];
117 #define LE(x) case x: return #x
122 LE(DSSCL_WRITEPRIMARY
);
125 sprintf(unknown
, "Unknown(%08x)", level
);
129 static void _dump_DSCAPS(DWORD xmask
) {
134 #define FE(x) { x, #x },
135 FE(DSCAPS_PRIMARYMONO
)
136 FE(DSCAPS_PRIMARYSTEREO
)
137 FE(DSCAPS_PRIMARY8BIT
)
138 FE(DSCAPS_PRIMARY16BIT
)
139 FE(DSCAPS_CONTINUOUSRATE
)
140 FE(DSCAPS_EMULDRIVER
)
142 FE(DSCAPS_SECONDARYMONO
)
143 FE(DSCAPS_SECONDARYSTEREO
)
144 FE(DSCAPS_SECONDARY8BIT
)
145 FE(DSCAPS_SECONDARY16BIT
)
150 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
151 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
152 TRACE("%s ",flags
[i
].name
);
155 static void _dump_DSBCAPS(DWORD xmask
) {
160 #define FE(x) { x, #x },
161 FE(DSBCAPS_PRIMARYBUFFER
)
163 FE(DSBCAPS_LOCHARDWARE
)
164 FE(DSBCAPS_LOCSOFTWARE
)
166 FE(DSBCAPS_CTRLFREQUENCY
)
168 FE(DSBCAPS_CTRLVOLUME
)
169 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
170 FE(DSBCAPS_STICKYFOCUS
)
171 FE(DSBCAPS_GLOBALFOCUS
)
172 FE(DSBCAPS_GETCURRENTPOSITION2
)
173 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
178 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
179 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
180 TRACE("%s ",flags
[i
].name
);
183 /*******************************************************************************
184 * IDirectSoundImpl_DirectSound
186 static HRESULT
DSOUND_QueryInterface(
187 LPDIRECTSOUND8 iface
,
191 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
192 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
195 WARN("invalid parameter\n");
199 if (IsEqualIID(riid
, &IID_IUnknown
)) {
200 if (!This
->pUnknown
) {
201 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
202 if (!This
->pUnknown
) {
203 WARN("IDirectSound_IUnknown_Create() failed\n");
205 return E_NOINTERFACE
;
208 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
209 *ppobj
= This
->pUnknown
;
211 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
213 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
215 WARN("IDirectSound_IDirectSound_Create() failed\n");
217 return E_NOINTERFACE
;
220 IDirectSound_IDirectSound_AddRef(This
->pDS
);
226 WARN("Unknown IID %s\n",debugstr_guid(riid
));
227 return E_NOINTERFACE
;
230 static HRESULT
DSOUND_QueryInterface8(
231 LPDIRECTSOUND8 iface
,
235 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
236 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
239 WARN("invalid parameter\n");
243 if (IsEqualIID(riid
, &IID_IUnknown
)) {
244 if (!This
->pUnknown
) {
245 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
246 if (!This
->pUnknown
) {
247 WARN("IDirectSound8_IUnknown_Create() failed\n");
249 return E_NOINTERFACE
;
252 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
253 *ppobj
= This
->pUnknown
;
255 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
257 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
259 WARN("IDirectSound8_IDirectSound_Create() failed\n");
261 return E_NOINTERFACE
;
264 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
267 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
269 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
271 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
273 return E_NOINTERFACE
;
276 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
282 WARN("Unknown IID %s\n",debugstr_guid(riid
));
283 return E_NOINTERFACE
;
286 static ULONG
IDirectSoundImpl_AddRef(
287 LPDIRECTSOUND8 iface
)
289 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
290 ULONG ref
= InterlockedIncrement(&(This
->ref
));
291 TRACE("(%p) ref was %d\n", This
, ref
- 1);
295 static ULONG
IDirectSoundImpl_Release(
296 LPDIRECTSOUND8 iface
)
298 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
299 ULONG ref
= InterlockedDecrement(&(This
->ref
));
300 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
304 DirectSoundDevice_Release(This
->device
);
305 HeapFree(GetProcessHeap(),0,This
);
306 TRACE("(%p) released\n", This
);
311 static HRESULT
IDirectSoundImpl_Create(
312 LPDIRECTSOUND8
* ppDS
)
314 IDirectSoundImpl
* pDS
;
315 TRACE("(%p)\n",ppDS
);
317 /* Allocate memory */
318 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
320 WARN("out of memory\n");
322 return DSERR_OUTOFMEMORY
;
328 *ppDS
= (LPDIRECTSOUND8
)pDS
;
333 /*******************************************************************************
334 * IDirectSound_IUnknown
336 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
341 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
342 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
343 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
346 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
349 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
350 ULONG ref
= InterlockedIncrement(&(This
->ref
));
351 TRACE("(%p) ref was %d\n", This
, ref
- 1);
355 static ULONG WINAPI
IDirectSound_IUnknown_Release(
358 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
359 ULONG ref
= InterlockedDecrement(&(This
->ref
));
360 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
362 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
363 IDirectSoundImpl_Release(This
->pds
);
364 HeapFree(GetProcessHeap(), 0, This
);
365 TRACE("(%p) released\n", This
);
370 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
372 IDirectSound_IUnknown_QueryInterface
,
373 IDirectSound_IUnknown_AddRef
,
374 IDirectSound_IUnknown_Release
377 static HRESULT
IDirectSound_IUnknown_Create(
381 IDirectSound_IUnknown
* pdsunk
;
382 TRACE("(%p,%p)\n",pds
,ppunk
);
385 ERR("invalid parameter: ppunk == NULL\n");
386 return DSERR_INVALIDPARAM
;
390 ERR("invalid parameter: pds == NULL\n");
392 return DSERR_INVALIDPARAM
;
395 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
396 if (pdsunk
== NULL
) {
397 WARN("out of memory\n");
399 return DSERR_OUTOFMEMORY
;
402 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
406 IDirectSoundImpl_AddRef(pds
);
407 *ppunk
= (LPUNKNOWN
)pdsunk
;
412 /*******************************************************************************
413 * IDirectSound_IDirectSound
415 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
420 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
421 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
422 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
425 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
428 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
429 ULONG ref
= InterlockedIncrement(&(This
->ref
));
430 TRACE("(%p) ref was %d\n", This
, ref
- 1);
434 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
437 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
438 ULONG ref
= InterlockedDecrement(&(This
->ref
));
439 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
441 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
442 IDirectSoundImpl_Release(This
->pds
);
443 HeapFree(GetProcessHeap(), 0, This
);
444 TRACE("(%p) released\n", This
);
449 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
451 LPCDSBUFFERDESC dsbd
,
452 LPLPDIRECTSOUNDBUFFER ppdsb
,
455 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
456 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
457 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,FALSE
);
460 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
464 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
465 TRACE("(%p,%p)\n",This
,lpDSCaps
);
466 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
469 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
471 LPDIRECTSOUNDBUFFER psb
,
472 LPLPDIRECTSOUNDBUFFER ppdsb
)
474 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
475 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
476 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
479 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
484 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
485 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
486 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
489 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
492 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
493 TRACE("(%p)\n", This
);
494 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
497 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
499 LPDWORD lpdwSpeakerConfig
)
501 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
502 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
503 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
506 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
510 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
511 TRACE("(%p,0x%08x)\n",This
,config
);
512 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
515 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
519 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
520 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
521 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
524 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
526 IDirectSound_IDirectSound_QueryInterface
,
527 IDirectSound_IDirectSound_AddRef
,
528 IDirectSound_IDirectSound_Release
,
529 IDirectSound_IDirectSound_CreateSoundBuffer
,
530 IDirectSound_IDirectSound_GetCaps
,
531 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
532 IDirectSound_IDirectSound_SetCooperativeLevel
,
533 IDirectSound_IDirectSound_Compact
,
534 IDirectSound_IDirectSound_GetSpeakerConfig
,
535 IDirectSound_IDirectSound_SetSpeakerConfig
,
536 IDirectSound_IDirectSound_Initialize
539 static HRESULT
IDirectSound_IDirectSound_Create(
541 LPDIRECTSOUND
* ppds
)
543 IDirectSound_IDirectSound
* pdsds
;
544 TRACE("(%p,%p)\n",pds
,ppds
);
547 ERR("invalid parameter: ppds == NULL\n");
548 return DSERR_INVALIDPARAM
;
552 ERR("invalid parameter: pds == NULL\n");
554 return DSERR_INVALIDPARAM
;
557 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
559 WARN("out of memory\n");
561 return DSERR_OUTOFMEMORY
;
564 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
568 IDirectSoundImpl_AddRef(pds
);
569 *ppds
= (LPDIRECTSOUND
)pdsds
;
574 /*******************************************************************************
575 * IDirectSound8_IUnknown
577 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
582 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
583 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
584 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
587 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
590 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
591 ULONG ref
= InterlockedIncrement(&(This
->ref
));
592 TRACE("(%p) ref was %d\n", This
, ref
- 1);
596 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
599 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
600 ULONG ref
= InterlockedDecrement(&(This
->ref
));
601 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
603 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
604 IDirectSoundImpl_Release(This
->pds
);
605 HeapFree(GetProcessHeap(), 0, This
);
606 TRACE("(%p) released\n", This
);
611 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
613 IDirectSound8_IUnknown_QueryInterface
,
614 IDirectSound8_IUnknown_AddRef
,
615 IDirectSound8_IUnknown_Release
618 static HRESULT
IDirectSound8_IUnknown_Create(
622 IDirectSound8_IUnknown
* pdsunk
;
623 TRACE("(%p,%p)\n",pds
,ppunk
);
626 ERR("invalid parameter: ppunk == NULL\n");
627 return DSERR_INVALIDPARAM
;
631 ERR("invalid parameter: pds == NULL\n");
633 return DSERR_INVALIDPARAM
;
636 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
637 if (pdsunk
== NULL
) {
638 WARN("out of memory\n");
640 return DSERR_OUTOFMEMORY
;
643 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
647 IDirectSoundImpl_AddRef(pds
);
648 *ppunk
= (LPUNKNOWN
)pdsunk
;
653 /*******************************************************************************
654 * IDirectSound8_IDirectSound
656 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
661 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
662 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
663 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
666 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
669 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
670 ULONG ref
= InterlockedIncrement(&(This
->ref
));
671 TRACE("(%p) ref was %d\n", This
, ref
- 1);
675 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
678 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
679 ULONG ref
= InterlockedDecrement(&(This
->ref
));
680 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
682 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
683 IDirectSoundImpl_Release(This
->pds
);
684 HeapFree(GetProcessHeap(), 0, This
);
685 TRACE("(%p) released\n", This
);
690 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
692 LPCDSBUFFERDESC dsbd
,
693 LPLPDIRECTSOUNDBUFFER ppdsb
,
696 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
697 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
698 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
701 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
705 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
706 TRACE("(%p,%p)\n",This
,lpDSCaps
);
707 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
710 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
712 LPDIRECTSOUNDBUFFER psb
,
713 LPLPDIRECTSOUNDBUFFER ppdsb
)
715 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
716 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
717 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
720 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
725 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
726 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
727 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
730 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
733 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
734 TRACE("(%p)\n", This
);
735 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
738 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
740 LPDWORD lpdwSpeakerConfig
)
742 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
743 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
744 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
747 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
751 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
752 TRACE("(%p,0x%08x)\n",This
,config
);
753 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
756 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
760 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
761 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
762 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
765 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
767 IDirectSound8_IDirectSound_QueryInterface
,
768 IDirectSound8_IDirectSound_AddRef
,
769 IDirectSound8_IDirectSound_Release
,
770 IDirectSound8_IDirectSound_CreateSoundBuffer
,
771 IDirectSound8_IDirectSound_GetCaps
,
772 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
773 IDirectSound8_IDirectSound_SetCooperativeLevel
,
774 IDirectSound8_IDirectSound_Compact
,
775 IDirectSound8_IDirectSound_GetSpeakerConfig
,
776 IDirectSound8_IDirectSound_SetSpeakerConfig
,
777 IDirectSound8_IDirectSound_Initialize
780 static HRESULT
IDirectSound8_IDirectSound_Create(
782 LPDIRECTSOUND
* ppds
)
784 IDirectSound8_IDirectSound
* pdsds
;
785 TRACE("(%p,%p)\n",pds
,ppds
);
788 ERR("invalid parameter: ppds == NULL\n");
789 return DSERR_INVALIDPARAM
;
793 ERR("invalid parameter: pds == NULL\n");
795 return DSERR_INVALIDPARAM
;
798 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
800 WARN("out of memory\n");
802 return DSERR_OUTOFMEMORY
;
805 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
809 IDirectSoundImpl_AddRef(pds
);
810 *ppds
= (LPDIRECTSOUND
)pdsds
;
815 /*******************************************************************************
816 * IDirectSound8_IDirectSound8
818 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
819 LPDIRECTSOUND8 iface
,
823 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
824 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
825 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
828 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
829 LPDIRECTSOUND8 iface
)
831 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
832 ULONG ref
= InterlockedIncrement(&(This
->ref
));
833 TRACE("(%p) ref was %d\n", This
, ref
- 1);
837 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
838 LPDIRECTSOUND8 iface
)
840 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
841 ULONG ref
= InterlockedDecrement(&(This
->ref
));
842 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
844 ((IDirectSoundImpl
*)This
->pds
)->pDS8
= NULL
;
845 IDirectSoundImpl_Release(This
->pds
);
846 HeapFree(GetProcessHeap(), 0, This
);
847 TRACE("(%p) released\n", This
);
852 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
853 LPDIRECTSOUND8 iface
,
854 LPCDSBUFFERDESC dsbd
,
855 LPLPDIRECTSOUNDBUFFER ppdsb
,
858 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
859 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
860 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
863 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
864 LPDIRECTSOUND8 iface
,
867 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
868 TRACE("(%p,%p)\n",This
,lpDSCaps
);
869 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
872 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
873 LPDIRECTSOUND8 iface
,
874 LPDIRECTSOUNDBUFFER psb
,
875 LPLPDIRECTSOUNDBUFFER ppdsb
)
877 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
878 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
879 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
882 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
883 LPDIRECTSOUND8 iface
,
887 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
888 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
889 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
892 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
893 LPDIRECTSOUND8 iface
)
895 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
896 TRACE("(%p)\n", This
);
897 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
900 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
901 LPDIRECTSOUND8 iface
,
902 LPDWORD lpdwSpeakerConfig
)
904 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
905 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
906 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
909 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
910 LPDIRECTSOUND8 iface
,
913 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
914 TRACE("(%p,0x%08x)\n",This
,config
);
915 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
918 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
919 LPDIRECTSOUND8 iface
,
922 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
923 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
924 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
927 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
928 LPDIRECTSOUND8 iface
,
929 LPDWORD pdwCertified
)
931 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
932 TRACE("(%p, %p)\n", This
, pdwCertified
);
933 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
936 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
938 IDirectSound8_IDirectSound8_QueryInterface
,
939 IDirectSound8_IDirectSound8_AddRef
,
940 IDirectSound8_IDirectSound8_Release
,
941 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
942 IDirectSound8_IDirectSound8_GetCaps
,
943 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
944 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
945 IDirectSound8_IDirectSound8_Compact
,
946 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
947 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
948 IDirectSound8_IDirectSound8_Initialize
,
949 IDirectSound8_IDirectSound8_VerifyCertification
952 static HRESULT
IDirectSound8_IDirectSound8_Create(
954 LPDIRECTSOUND8
* ppds
)
956 IDirectSound8_IDirectSound8
* pdsds
;
957 TRACE("(%p,%p)\n",pds
,ppds
);
960 ERR("invalid parameter: ppds == NULL\n");
961 return DSERR_INVALIDPARAM
;
965 ERR("invalid parameter: pds == NULL\n");
967 return DSERR_INVALIDPARAM
;
970 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
972 WARN("out of memory\n");
974 return DSERR_OUTOFMEMORY
;
977 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
981 IDirectSoundImpl_AddRef(pds
);
982 *ppds
= (LPDIRECTSOUND8
)pdsds
;
987 HRESULT
DSOUND_Create(
993 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
995 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
996 !IsEqualIID(riid
, &IID_IDirectSound
)) {
998 return E_NOINTERFACE
;
1001 /* Get dsound configuration */
1002 setup_dsound_options();
1004 hr
= IDirectSoundImpl_Create(&pDS
);
1006 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1008 IDirectSound_IDirectSound_AddRef(*ppDS
);
1010 WARN("IDirectSound_IDirectSound_Create failed\n");
1011 IDirectSound8_Release(pDS
);
1014 WARN("IDirectSoundImpl_Create failed\n");
1021 /*******************************************************************************
1022 * DirectSoundCreate (DSOUND.1)
1024 * Creates and initializes a DirectSound interface.
1027 * lpcGUID [I] Address of the GUID that identifies the sound device.
1028 * ppDS [O] Address of a variable to receive the interface pointer.
1029 * pUnkOuter [I] Must be NULL.
1033 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1034 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1036 HRESULT WINAPI
DirectSoundCreate(
1038 LPDIRECTSOUND
*ppDS
,
1039 IUnknown
*pUnkOuter
)
1044 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1047 WARN("invalid parameter: ppDS == NULL\n");
1048 return DSERR_INVALIDPARAM
;
1051 if (pUnkOuter
!= NULL
) {
1052 WARN("invalid parameter: pUnkOuter != NULL\n");
1054 return DSERR_INVALIDPARAM
;
1057 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
1059 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
1061 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1062 IDirectSound_Release(pDS
);
1074 HRESULT
DSOUND_Create8(
1076 LPDIRECTSOUND8
*ppDS
)
1080 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
1082 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1083 !IsEqualIID(riid
, &IID_IDirectSound
) &&
1084 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
1086 return E_NOINTERFACE
;
1089 /* Get dsound configuration */
1090 setup_dsound_options();
1092 hr
= IDirectSoundImpl_Create(&pDS
);
1094 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1096 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1098 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1099 IDirectSound8_Release(pDS
);
1102 WARN("IDirectSoundImpl_Create failed\n");
1109 /*******************************************************************************
1110 * DirectSoundCreate8 (DSOUND.11)
1112 * Creates and initializes a DirectSound8 interface.
1115 * lpcGUID [I] Address of the GUID that identifies the sound device.
1116 * ppDS [O] Address of a variable to receive the interface pointer.
1117 * pUnkOuter [I] Must be NULL.
1121 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1122 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1124 HRESULT WINAPI
DirectSoundCreate8(
1126 LPDIRECTSOUND8
*ppDS
,
1127 IUnknown
*pUnkOuter
)
1132 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1135 WARN("invalid parameter: ppDS == NULL\n");
1136 return DSERR_INVALIDPARAM
;
1139 if (pUnkOuter
!= NULL
) {
1140 WARN("invalid parameter: pUnkOuter != NULL\n");
1142 return DSERR_INVALIDPARAM
;
1145 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
1147 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1149 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1150 IDirectSound8_Release(pDS
);
1162 /*******************************************************************************
1165 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1167 DirectSoundDevice
* device
;
1168 TRACE("(%p)\n", ppDevice
);
1170 /* Allocate memory */
1171 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1172 if (device
== NULL
) {
1173 WARN("out of memory\n");
1174 return DSERR_OUTOFMEMORY
;
1178 device
->priolevel
= DSSCL_NORMAL
;
1179 device
->state
= STATE_STOPPED
;
1180 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
1182 /* 3D listener initial parameters */
1183 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1184 device
->ds3dl
.vPosition
.x
= 0.0;
1185 device
->ds3dl
.vPosition
.y
= 0.0;
1186 device
->ds3dl
.vPosition
.z
= 0.0;
1187 device
->ds3dl
.vVelocity
.x
= 0.0;
1188 device
->ds3dl
.vVelocity
.y
= 0.0;
1189 device
->ds3dl
.vVelocity
.z
= 0.0;
1190 device
->ds3dl
.vOrientFront
.x
= 0.0;
1191 device
->ds3dl
.vOrientFront
.y
= 0.0;
1192 device
->ds3dl
.vOrientFront
.z
= 1.0;
1193 device
->ds3dl
.vOrientTop
.x
= 0.0;
1194 device
->ds3dl
.vOrientTop
.y
= 1.0;
1195 device
->ds3dl
.vOrientTop
.z
= 0.0;
1196 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1197 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1198 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1200 device
->prebuf
= ds_snd_queue_max
;
1201 device
->guid
= GUID_NULL
;
1203 /* Set default wave format (may need it for waveOutOpen) */
1204 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1205 if (device
->pwfx
== NULL
) {
1206 WARN("out of memory\n");
1207 HeapFree(GetProcessHeap(),0,device
);
1208 return DSERR_OUTOFMEMORY
;
1211 /* We rely on the sound driver to return the actual sound format of
1212 * the device if it does not support 22050x8x2 and is given the
1213 * WAVE_DIRECTSOUND flag.
1215 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1216 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
1217 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
1218 device
->pwfx
->nChannels
= 2;
1219 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1220 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1221 device
->pwfx
->cbSize
= 0;
1223 InitializeCriticalSection(&(device
->mixlock
));
1224 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
1226 RtlInitializeResource(&(device
->buffer_list_lock
));
1233 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1235 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1236 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1240 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1243 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1244 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
1247 timeKillEvent(device
->timerID
);
1248 timeEndPeriod(DS_TIME_RES
);
1250 /* The kill event should have allowed the timer process to expire
1251 * but try to grab the lock just in case. Can't hold lock because
1252 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1253 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1254 RtlReleaseResource(&(device
->buffer_list_lock
));
1256 /* It is allowed to release this object even when buffers are playing */
1257 if (device
->buffers
) {
1258 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1259 for( i
=0;i
<device
->nrofbuffers
;i
++)
1260 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1263 if (device
->primary
) {
1264 WARN("primary buffer not released\n");
1265 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1268 hr
= DSOUND_PrimaryDestroy(device
);
1270 WARN("DSOUND_PrimaryDestroy failed\n");
1273 IDsDriver_Close(device
->driver
);
1275 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1276 waveOutClose(device
->hwo
);
1279 IDsDriver_Release(device
->driver
);
1281 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1283 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
1284 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
1285 HeapFree(GetProcessHeap(), 0, device
->buffer
);
1286 RtlDeleteResource(&device
->buffer_list_lock
);
1287 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1288 DeleteCriticalSection(&device
->mixlock
);
1289 HeapFree(GetProcessHeap(),0,device
);
1290 TRACE("(%p) released\n", device
);
1295 HRESULT
DirectSoundDevice_GetCaps(
1296 DirectSoundDevice
* device
,
1299 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1301 if (device
== NULL
) {
1302 WARN("not initialized\n");
1303 return DSERR_UNINITIALIZED
;
1306 if (lpDSCaps
== NULL
) {
1307 WARN("invalid parameter: lpDSCaps = NULL\n");
1308 return DSERR_INVALIDPARAM
;
1311 /* check if there is enough room */
1312 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1313 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1314 return DSERR_INVALIDPARAM
;
1317 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1318 if (TRACE_ON(dsound
)) {
1319 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1320 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1323 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1324 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1325 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1326 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1327 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1328 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1329 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1330 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1331 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1332 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1333 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1334 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1335 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1336 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1337 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1338 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1339 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1340 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1342 /* driver doesn't have these */
1343 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1344 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1349 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1353 BOOLEAN found
= FALSE
;
1355 DirectSoundDevice
* device
= *ppDevice
;
1356 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1358 if (*ppDevice
!= NULL
) {
1359 WARN("already initialized\n");
1360 return DSERR_ALREADYINITIALIZED
;
1363 /* Default device? */
1364 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1365 lpcGUID
= &DSDEVID_DefaultPlayback
;
1367 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1368 WARN("invalid parameter: lpcGUID\n");
1369 return DSERR_INVALIDPARAM
;
1372 /* Enumerate WINMM audio devices and find the one we want */
1373 wodn
= waveOutGetNumDevs();
1375 WARN("no driver\n");
1376 return DSERR_NODRIVER
;
1379 for (wod
=0; wod
<wodn
; wod
++) {
1380 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1386 if (found
== FALSE
) {
1387 WARN("No device found matching given ID!\n");
1388 return DSERR_NODRIVER
;
1391 if (DSOUND_renderer
[wod
]) {
1392 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1393 device
= DSOUND_renderer
[wod
];
1394 DirectSoundDevice_AddRef(device
);
1398 ERR("device GUID doesn't match\n");
1403 hr
= DirectSoundDevice_Create(&device
);
1405 WARN("DirectSoundDevice_Create failed\n");
1411 device
->guid
= devGUID
;
1412 device
->driver
= NULL
;
1414 device
->drvdesc
.dnDevNode
= wod
;
1415 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1418 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1422 if (device
->driver
) {
1423 /* the driver is now open, so it's now allowed to call GetCaps */
1424 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1426 WARN("IDsDriver_GetCaps failed\n");
1431 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1433 WARN("waveOutGetDevCaps failed\n");
1436 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1437 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1438 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1439 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1440 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1441 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1442 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1443 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1445 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1446 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1447 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1448 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1449 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1450 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1451 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1453 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1454 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1455 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1456 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1457 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1458 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1459 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1461 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1462 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1463 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1464 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1465 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1466 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1467 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1470 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1471 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1472 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1473 device
->drvcaps
.dwPrimaryBuffers
= 1;
1476 hr
= DSOUND_PrimaryCreate(device
);
1478 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1481 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1482 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1483 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1484 if (triggertime
< time
.wPeriodMin
)
1485 triggertime
= time
.wPeriodMin
;
1486 if (res
< time
.wPeriodMin
)
1487 res
= time
.wPeriodMin
;
1488 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1489 WARN("Could not set minimum resolution, don't expect sound\n");
1490 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1493 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1494 id
= timeSetEvent(triggertime
, res
, DSOUND_timer
, (DWORD_PTR
)device
, TIME_PERIODIC
);
1495 if (!id
) ERR("Could not create timer, sound playback will not occur\n");
1497 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= id
;
1499 WARN("DSOUND_PrimaryCreate failed\n");
1505 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1506 DirectSoundDevice
* device
,
1507 LPCDSBUFFERDESC dsbd
,
1508 LPLPDIRECTSOUNDBUFFER ppdsb
,
1512 HRESULT hres
= DS_OK
;
1513 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1515 if (device
== NULL
) {
1516 WARN("not initialized\n");
1517 return DSERR_UNINITIALIZED
;
1521 WARN("invalid parameter: dsbd == NULL\n");
1522 return DSERR_INVALIDPARAM
;
1525 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1526 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1527 WARN("invalid parameter: dsbd\n");
1528 return DSERR_INVALIDPARAM
;
1531 if (ppdsb
== NULL
) {
1532 WARN("invalid parameter: ppdsb == NULL\n");
1533 return DSERR_INVALIDPARAM
;
1537 if (TRACE_ON(dsound
)) {
1538 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1539 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1540 _dump_DSBCAPS(dsbd
->dwFlags
);
1542 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1543 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1546 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1547 if (dsbd
->lpwfxFormat
!= NULL
) {
1548 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1549 "primary buffer\n");
1550 return DSERR_INVALIDPARAM
;
1553 if (device
->primary
) {
1554 WARN("Primary Buffer already created\n");
1555 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1556 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1558 device
->dsbd
= *dsbd
;
1559 device
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1561 device
->dsbd
.dwFlags
|= DSBCAPS_LOCHARDWARE
;
1562 else device
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1563 hres
= PrimaryBufferImpl_Create(device
, &(device
->primary
), &(device
->dsbd
));
1564 if (device
->primary
) {
1565 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1566 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1568 WARN("PrimaryBufferImpl_Create failed\n");
1571 IDirectSoundBufferImpl
* dsb
;
1572 WAVEFORMATEXTENSIBLE
*pwfxe
;
1574 if (dsbd
->lpwfxFormat
== NULL
) {
1575 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1576 "secondary buffer\n");
1577 return DSERR_INVALIDPARAM
;
1579 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1581 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1583 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1584 return DSERR_CONTROLUNAVAIL
;
1586 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1588 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1590 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1591 return DSERR_INVALIDPARAM
;
1594 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1596 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1597 return DSERR_CONTROLUNAVAIL
;
1600 if (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
1602 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1603 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1604 return DSERR_INVALIDPARAM
;
1606 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1608 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1609 return DSERR_INVALIDPARAM
;
1611 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1613 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1614 return DSERR_CONTROLUNAVAIL
;
1618 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1619 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1620 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1621 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1622 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1623 dsbd
->lpwfxFormat
->nBlockAlign
,
1624 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1626 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1627 WARN("invalid parameter: 3D buffer format must be mono\n");
1628 return DSERR_INVALIDPARAM
;
1631 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1633 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1635 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1636 IDirectSoundBuffer_AddRef(*ppdsb
);
1638 WARN("SecondaryBufferImpl_Create failed\n");
1640 WARN("IDirectSoundBufferImpl_Create failed\n");
1646 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1647 DirectSoundDevice
* device
,
1648 LPDIRECTSOUNDBUFFER psb
,
1649 LPLPDIRECTSOUNDBUFFER ppdsb
)
1651 HRESULT hres
= DS_OK
;
1652 IDirectSoundBufferImpl
* dsb
;
1653 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1655 if (device
== NULL
) {
1656 WARN("not initialized\n");
1657 return DSERR_UNINITIALIZED
;
1661 WARN("invalid parameter: psb == NULL\n");
1662 return DSERR_INVALIDPARAM
;
1665 if (ppdsb
== NULL
) {
1666 WARN("invalid parameter: ppdsb == NULL\n");
1667 return DSERR_INVALIDPARAM
;
1670 /* make sure we have a secondary buffer */
1671 if ((PrimaryBufferImpl
*)psb
== device
->primary
) {
1672 WARN("trying to duplicate primary buffer\n");
1674 return DSERR_INVALIDCALL
;
1677 /* duplicate the actual buffer implementation */
1678 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
,
1679 ((SecondaryBufferImpl
*)psb
)->dsb
);
1681 if (hres
== DS_OK
) {
1682 /* create a new secondary buffer using the new implementation */
1683 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1685 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1686 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
1688 WARN("SecondaryBufferImpl_Create failed\n");
1689 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)dsb
);
1690 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8
)dsb
);
1697 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1698 DirectSoundDevice
* device
,
1702 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1704 if (device
== NULL
) {
1705 WARN("not initialized\n");
1706 return DSERR_UNINITIALIZED
;
1709 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1710 WARN("level=%s not fully supported\n",
1711 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1714 device
->priolevel
= level
;
1718 HRESULT
DirectSoundDevice_Compact(
1719 DirectSoundDevice
* device
)
1721 TRACE("(%p)\n", device
);
1723 if (device
== NULL
) {
1724 WARN("not initialized\n");
1725 return DSERR_UNINITIALIZED
;
1728 if (device
->priolevel
< DSSCL_PRIORITY
) {
1729 WARN("incorrect priority level\n");
1730 return DSERR_PRIOLEVELNEEDED
;
1736 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1737 DirectSoundDevice
* device
,
1738 LPDWORD lpdwSpeakerConfig
)
1740 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1742 if (device
== NULL
) {
1743 WARN("not initialized\n");
1744 return DSERR_UNINITIALIZED
;
1747 if (lpdwSpeakerConfig
== NULL
) {
1748 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1749 return DSERR_INVALIDPARAM
;
1752 WARN("not fully functional\n");
1753 *lpdwSpeakerConfig
= device
->speaker_config
;
1757 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1758 DirectSoundDevice
* device
,
1761 TRACE("(%p,0x%08x)\n",device
,config
);
1763 if (device
== NULL
) {
1764 WARN("not initialized\n");
1765 return DSERR_UNINITIALIZED
;
1768 device
->speaker_config
= config
;
1769 WARN("not fully functional\n");
1773 static HRESULT
DirectSoundDevice_VerifyCertification(
1774 DirectSoundDevice
* device
,
1775 LPDWORD pdwCertified
)
1777 TRACE("(%p, %p)\n",device
,pdwCertified
);
1779 if (device
== NULL
) {
1780 WARN("not initialized\n");
1781 return DSERR_UNINITIALIZED
;
1784 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1785 *pdwCertified
= DS_CERTIFIED
;
1787 *pdwCertified
= DS_UNCERTIFIED
;
1793 * Add secondary buffer to buffer list.
1794 * Gets exclusive access to buffer for writing.
1796 HRESULT
DirectSoundDevice_AddBuffer(
1797 DirectSoundDevice
* device
,
1798 IDirectSoundBufferImpl
* pDSB
)
1800 IDirectSoundBufferImpl
**newbuffers
;
1803 TRACE("(%p, %p)\n", device
, pDSB
);
1805 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1807 if (device
->buffers
)
1808 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1810 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1813 device
->buffers
= newbuffers
;
1814 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1815 device
->nrofbuffers
++;
1816 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1818 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1819 hr
= DSERR_OUTOFMEMORY
;
1822 RtlReleaseResource(&(device
->buffer_list_lock
));
1828 * Remove secondary buffer from buffer list.
1829 * Gets exclusive access to buffer for writing.
1831 HRESULT
DirectSoundDevice_RemoveBuffer(
1832 DirectSoundDevice
* device
,
1833 IDirectSoundBufferImpl
* pDSB
)
1838 TRACE("(%p, %p)\n", device
, pDSB
);
1840 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1842 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1843 if (device
->buffers
[i
] == pDSB
)
1846 if (i
< device
->nrofbuffers
) {
1847 /* Put the last buffer of the list in the (now empty) position */
1848 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1849 device
->nrofbuffers
--;
1850 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1851 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1854 if (device
->nrofbuffers
== 0) {
1855 HeapFree(GetProcessHeap(),0,device
->buffers
);
1856 device
->buffers
= NULL
;
1859 RtlReleaseResource(&(device
->buffer_list_lock
));