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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
38 #include "dsound_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
42 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
43 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
44 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
45 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
46 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
48 const char * dumpCooperativeLevel(DWORD level
)
50 static char unknown
[32];
51 #define LE(x) case x: return #x
56 LE(DSSCL_WRITEPRIMARY
);
59 sprintf(unknown
, "Unknown(%08lx)", level
);
63 static void _dump_DSCAPS(DWORD xmask
) {
68 #define FE(x) { x, #x },
69 FE(DSCAPS_PRIMARYMONO
)
70 FE(DSCAPS_PRIMARYSTEREO
)
71 FE(DSCAPS_PRIMARY8BIT
)
72 FE(DSCAPS_PRIMARY16BIT
)
73 FE(DSCAPS_CONTINUOUSRATE
)
76 FE(DSCAPS_SECONDARYMONO
)
77 FE(DSCAPS_SECONDARYSTEREO
)
78 FE(DSCAPS_SECONDARY8BIT
)
79 FE(DSCAPS_SECONDARY16BIT
)
84 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
85 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
86 DPRINTF("%s ",flags
[i
].name
);
89 static void _dump_DSBCAPS(DWORD xmask
) {
94 #define FE(x) { x, #x },
95 FE(DSBCAPS_PRIMARYBUFFER
)
97 FE(DSBCAPS_LOCHARDWARE
)
98 FE(DSBCAPS_LOCSOFTWARE
)
100 FE(DSBCAPS_CTRLFREQUENCY
)
102 FE(DSBCAPS_CTRLVOLUME
)
103 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
104 FE(DSBCAPS_STICKYFOCUS
)
105 FE(DSBCAPS_GLOBALFOCUS
)
106 FE(DSBCAPS_GETCURRENTPOSITION2
)
107 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
112 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
113 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
114 DPRINTF("%s ",flags
[i
].name
);
117 /*******************************************************************************
118 * IDirectSoundImpl_DirectSound
120 static HRESULT
DSOUND_QueryInterface(
121 LPDIRECTSOUND8 iface
,
125 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
126 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
129 WARN("invalid parameter\n");
133 if (IsEqualIID(riid
, &IID_IUnknown
)) {
134 if (!This
->pUnknown
) {
135 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
136 if (!This
->pUnknown
) {
137 WARN("IDirectSound_IUnknown_Create() failed\n");
139 return E_NOINTERFACE
;
142 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
143 *ppobj
= This
->pUnknown
;
145 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
147 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
149 WARN("IDirectSound_IDirectSound_Create() failed\n");
151 return E_NOINTERFACE
;
154 IDirectSound_IDirectSound_AddRef(This
->pDS
);
160 WARN("Unknown IID %s\n",debugstr_guid(riid
));
161 return E_NOINTERFACE
;
164 static HRESULT
DSOUND_QueryInterface8(
165 LPDIRECTSOUND8 iface
,
169 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
170 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
173 WARN("invalid parameter\n");
177 if (IsEqualIID(riid
, &IID_IUnknown
)) {
178 if (!This
->pUnknown
) {
179 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
180 if (!This
->pUnknown
) {
181 WARN("IDirectSound8_IUnknown_Create() failed\n");
183 return E_NOINTERFACE
;
186 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
187 *ppobj
= This
->pUnknown
;
189 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
191 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
193 WARN("IDirectSound8_IDirectSound_Create() failed\n");
195 return E_NOINTERFACE
;
198 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
201 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
203 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
205 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
207 return E_NOINTERFACE
;
210 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
216 WARN("Unknown IID %s\n",debugstr_guid(riid
));
217 return E_NOINTERFACE
;
220 static ULONG
IDirectSoundImpl_AddRef(
221 LPDIRECTSOUND8 iface
)
223 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
224 ULONG ref
= InterlockedIncrement(&(This
->ref
));
225 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
229 static ULONG
IDirectSoundImpl_Release(
230 LPDIRECTSOUND8 iface
)
232 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
233 ULONG ref
= InterlockedDecrement(&(This
->ref
));
234 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
238 DirectSoundDevice_Release(This
->device
);
239 HeapFree(GetProcessHeap(),0,This
);
240 TRACE("(%p) released\n", This
);
245 HRESULT
IDirectSoundImpl_Create(
246 LPDIRECTSOUND8
* ppDS
)
248 IDirectSoundImpl
* pDS
;
249 TRACE("(%p)\n",ppDS
);
251 /* Allocate memory */
252 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
254 WARN("out of memory\n");
256 return DSERR_OUTOFMEMORY
;
262 *ppDS
= (LPDIRECTSOUND8
)pDS
;
267 /*******************************************************************************
268 * IDirectSound_IUnknown
270 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
275 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
276 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
277 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
280 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
283 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
284 ULONG ref
= InterlockedIncrement(&(This
->ref
));
285 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
289 static ULONG WINAPI
IDirectSound_IUnknown_Release(
292 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
293 ULONG ref
= InterlockedDecrement(&(This
->ref
));
294 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
296 IDirectSoundImpl_Release(This
->pds
);
297 HeapFree(GetProcessHeap(), 0, This
);
298 TRACE("(%p) released\n", This
);
303 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
305 IDirectSound_IUnknown_QueryInterface
,
306 IDirectSound_IUnknown_AddRef
,
307 IDirectSound_IUnknown_Release
310 HRESULT
IDirectSound_IUnknown_Create(
314 IDirectSound_IUnknown
* pdsunk
;
315 TRACE("(%p,%p)\n",pds
,ppunk
);
318 ERR("invalid parameter: ppunk == NULL\n");
319 return DSERR_INVALIDPARAM
;
323 ERR("invalid parameter: pds == NULL\n");
325 return DSERR_INVALIDPARAM
;
328 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
329 if (pdsunk
== NULL
) {
330 WARN("out of memory\n");
332 return DSERR_OUTOFMEMORY
;
335 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
339 IDirectSoundImpl_AddRef(pds
);
340 *ppunk
= (LPUNKNOWN
)pdsunk
;
345 /*******************************************************************************
346 * IDirectSound_IDirectSound
348 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
353 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
354 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
355 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
358 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
361 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
362 ULONG ref
= InterlockedIncrement(&(This
->ref
));
363 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
367 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
370 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
371 ULONG ref
= InterlockedDecrement(&(This
->ref
));
372 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
374 IDirectSoundImpl_Release(This
->pds
);
375 HeapFree(GetProcessHeap(), 0, This
);
376 TRACE("(%p) released\n", This
);
381 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
383 LPCDSBUFFERDESC dsbd
,
384 LPLPDIRECTSOUNDBUFFER ppdsb
,
387 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
388 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
389 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,FALSE
);
392 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
396 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
397 TRACE("(%p,%p)\n",This
,lpDSCaps
);
398 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
401 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
403 LPDIRECTSOUNDBUFFER psb
,
404 LPLPDIRECTSOUNDBUFFER ppdsb
)
406 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
407 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
408 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
411 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
416 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
417 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
418 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
421 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
424 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
425 TRACE("(%p)\n", This
);
426 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
429 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
431 LPDWORD lpdwSpeakerConfig
)
433 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
434 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
435 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
438 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
442 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
443 TRACE("(%p,0x%08lx)\n",This
,config
);
444 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
447 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
451 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
452 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
453 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
456 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
458 IDirectSound_IDirectSound_QueryInterface
,
459 IDirectSound_IDirectSound_AddRef
,
460 IDirectSound_IDirectSound_Release
,
461 IDirectSound_IDirectSound_CreateSoundBuffer
,
462 IDirectSound_IDirectSound_GetCaps
,
463 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
464 IDirectSound_IDirectSound_SetCooperativeLevel
,
465 IDirectSound_IDirectSound_Compact
,
466 IDirectSound_IDirectSound_GetSpeakerConfig
,
467 IDirectSound_IDirectSound_SetSpeakerConfig
,
468 IDirectSound_IDirectSound_Initialize
471 HRESULT
IDirectSound_IDirectSound_Create(
473 LPDIRECTSOUND
* ppds
)
475 IDirectSound_IDirectSound
* pdsds
;
476 TRACE("(%p,%p)\n",pds
,ppds
);
479 ERR("invalid parameter: ppds == NULL\n");
480 return DSERR_INVALIDPARAM
;
484 ERR("invalid parameter: pds == NULL\n");
486 return DSERR_INVALIDPARAM
;
489 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
491 WARN("out of memory\n");
493 return DSERR_OUTOFMEMORY
;
496 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
500 IDirectSoundImpl_AddRef(pds
);
501 *ppds
= (LPDIRECTSOUND
)pdsds
;
506 /*******************************************************************************
507 * IDirectSound8_IUnknown
509 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
514 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
515 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
516 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
519 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
522 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
523 ULONG ref
= InterlockedIncrement(&(This
->ref
));
524 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
528 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
531 IDirectSound_IUnknown
*This
= (IDirectSound_IUnknown
*)iface
;
532 ULONG ref
= InterlockedDecrement(&(This
->ref
));
533 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
535 IDirectSoundImpl_Release(This
->pds
);
536 HeapFree(GetProcessHeap(), 0, This
);
537 TRACE("(%p) released\n", This
);
542 static const IUnknownVtbl DirectSound8_Unknown_Vtbl
=
544 IDirectSound8_IUnknown_QueryInterface
,
545 IDirectSound8_IUnknown_AddRef
,
546 IDirectSound8_IUnknown_Release
549 HRESULT
IDirectSound8_IUnknown_Create(
553 IDirectSound8_IUnknown
* pdsunk
;
554 TRACE("(%p,%p)\n",pds
,ppunk
);
557 ERR("invalid parameter: ppunk == NULL\n");
558 return DSERR_INVALIDPARAM
;
562 ERR("invalid parameter: pds == NULL\n");
564 return DSERR_INVALIDPARAM
;
567 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
568 if (pdsunk
== NULL
) {
569 WARN("out of memory\n");
571 return DSERR_OUTOFMEMORY
;
574 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
578 IDirectSoundImpl_AddRef(pds
);
579 *ppunk
= (LPUNKNOWN
)pdsunk
;
584 /*******************************************************************************
585 * IDirectSound8_IDirectSound
587 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
592 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
593 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
594 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
597 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
600 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
601 ULONG ref
= InterlockedIncrement(&(This
->ref
));
602 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
606 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
609 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
610 ULONG ref
= InterlockedDecrement(&(This
->ref
));
611 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
613 IDirectSoundImpl_Release(This
->pds
);
614 HeapFree(GetProcessHeap(), 0, This
);
615 TRACE("(%p) released\n", This
);
620 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
622 LPCDSBUFFERDESC dsbd
,
623 LPLPDIRECTSOUNDBUFFER ppdsb
,
626 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
627 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
628 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
631 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
635 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
636 TRACE("(%p,%p)\n",This
,lpDSCaps
);
637 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
640 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
642 LPDIRECTSOUNDBUFFER psb
,
643 LPLPDIRECTSOUNDBUFFER ppdsb
)
645 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
646 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
647 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
650 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
655 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
656 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
657 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
660 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
663 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
664 TRACE("(%p)\n", This
);
665 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
668 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
670 LPDWORD lpdwSpeakerConfig
)
672 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
673 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
674 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
677 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
681 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
682 TRACE("(%p,0x%08lx)\n",This
,config
);
683 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
686 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
690 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
691 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
692 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
695 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
697 IDirectSound8_IDirectSound_QueryInterface
,
698 IDirectSound8_IDirectSound_AddRef
,
699 IDirectSound8_IDirectSound_Release
,
700 IDirectSound8_IDirectSound_CreateSoundBuffer
,
701 IDirectSound8_IDirectSound_GetCaps
,
702 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
703 IDirectSound8_IDirectSound_SetCooperativeLevel
,
704 IDirectSound8_IDirectSound_Compact
,
705 IDirectSound8_IDirectSound_GetSpeakerConfig
,
706 IDirectSound8_IDirectSound_SetSpeakerConfig
,
707 IDirectSound8_IDirectSound_Initialize
710 HRESULT
IDirectSound8_IDirectSound_Create(
712 LPDIRECTSOUND
* ppds
)
714 IDirectSound8_IDirectSound
* pdsds
;
715 TRACE("(%p,%p)\n",pds
,ppds
);
718 ERR("invalid parameter: ppds == NULL\n");
719 return DSERR_INVALIDPARAM
;
723 ERR("invalid parameter: pds == NULL\n");
725 return DSERR_INVALIDPARAM
;
728 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
730 WARN("out of memory\n");
732 return DSERR_OUTOFMEMORY
;
735 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
739 IDirectSoundImpl_AddRef(pds
);
740 *ppds
= (LPDIRECTSOUND
)pdsds
;
745 /*******************************************************************************
746 * IDirectSound8_IDirectSound8
748 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
749 LPDIRECTSOUND8 iface
,
753 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
754 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
755 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
758 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
759 LPDIRECTSOUND8 iface
)
761 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
762 ULONG ref
= InterlockedIncrement(&(This
->ref
));
763 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
767 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
768 LPDIRECTSOUND8 iface
)
770 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
771 ULONG ref
= InterlockedDecrement(&(This
->ref
));
772 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
774 IDirectSoundImpl_Release(This
->pds
);
775 HeapFree(GetProcessHeap(), 0, This
);
776 TRACE("(%p) released\n", This
);
781 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
782 LPDIRECTSOUND8 iface
,
783 LPCDSBUFFERDESC dsbd
,
784 LPLPDIRECTSOUNDBUFFER ppdsb
,
787 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
788 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
789 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
792 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
793 LPDIRECTSOUND8 iface
,
796 IDirectSound8_IDirectSound
*This
= (IDirectSound8_IDirectSound
*)iface
;
797 TRACE("(%p,%p)\n",This
,lpDSCaps
);
798 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
801 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
802 LPDIRECTSOUND8 iface
,
803 LPDIRECTSOUNDBUFFER psb
,
804 LPLPDIRECTSOUNDBUFFER ppdsb
)
806 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
807 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
808 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
811 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
812 LPDIRECTSOUND8 iface
,
816 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
817 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
818 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
821 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
822 LPDIRECTSOUND8 iface
)
824 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
825 TRACE("(%p)\n", This
);
826 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
829 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
830 LPDIRECTSOUND8 iface
,
831 LPDWORD lpdwSpeakerConfig
)
833 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
834 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
835 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
838 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
839 LPDIRECTSOUND8 iface
,
842 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
843 TRACE("(%p,0x%08lx)\n",This
,config
);
844 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
847 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
848 LPDIRECTSOUND8 iface
,
851 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
852 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
853 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
856 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
857 LPDIRECTSOUND8 iface
,
858 LPDWORD pdwCertified
)
860 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
861 TRACE("(%p, %p)\n", This
, pdwCertified
);
862 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
865 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
867 IDirectSound8_IDirectSound8_QueryInterface
,
868 IDirectSound8_IDirectSound8_AddRef
,
869 IDirectSound8_IDirectSound8_Release
,
870 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
871 IDirectSound8_IDirectSound8_GetCaps
,
872 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
873 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
874 IDirectSound8_IDirectSound8_Compact
,
875 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
876 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
877 IDirectSound8_IDirectSound8_Initialize
,
878 IDirectSound8_IDirectSound8_VerifyCertification
881 HRESULT
IDirectSound8_IDirectSound8_Create(
883 LPDIRECTSOUND8
* ppds
)
885 IDirectSound8_IDirectSound8
* pdsds
;
886 TRACE("(%p,%p)\n",pds
,ppds
);
889 ERR("invalid parameter: ppds == NULL\n");
890 return DSERR_INVALIDPARAM
;
894 ERR("invalid parameter: pds == NULL\n");
896 return DSERR_INVALIDPARAM
;
899 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
901 WARN("out of memory\n");
903 return DSERR_OUTOFMEMORY
;
906 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
910 IDirectSoundImpl_AddRef(pds
);
911 *ppds
= (LPDIRECTSOUND8
)pdsds
;
916 HRESULT
DSOUND_Create(
922 TRACE("(%p,%p)\n",ppDS
,pUnkOuter
);
924 /* Get dsound configuration */
925 setup_dsound_options();
927 hr
= IDirectSoundImpl_Create(&pDS
);
929 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
931 IDirectSound_IDirectSound_AddRef(*ppDS
);
933 WARN("IDirectSound_IDirectSound_Create failed\n");
934 IDirectSound8_Release(pDS
);
937 WARN("IDirectSoundImpl_Create failed\n");
944 /*******************************************************************************
945 * DirectSoundCreate (DSOUND.1)
947 * Creates and initializes a DirectSound interface.
950 * lpcGUID [I] Address of the GUID that identifies the sound device.
951 * ppDS [O] Address of a variable to receive the interface pointer.
952 * pUnkOuter [I] Must be NULL.
956 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
957 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
959 HRESULT WINAPI
DirectSoundCreate(
967 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
970 WARN("invalid parameter: ppDS == NULL\n");
971 return DSERR_INVALIDPARAM
;
974 if (pUnkOuter
!= NULL
) {
975 WARN("invalid parameter: pUnkOuter != NULL\n");
977 return DSERR_INVALIDPARAM
;
980 hr
= DSOUND_Create(&pDS
, pUnkOuter
);
982 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
984 if (hr
!= DSERR_ALREADYINITIALIZED
) {
985 IDirectSound_Release(pDS
);
997 HRESULT
DSOUND_Create8(
998 LPDIRECTSOUND8
*ppDS
,
1003 TRACE("(%p,%p)\n",ppDS
,pUnkOuter
);
1005 /* Get dsound configuration */
1006 setup_dsound_options();
1008 hr
= IDirectSoundImpl_Create(&pDS
);
1010 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1012 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1014 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1015 IDirectSound8_Release(pDS
);
1018 WARN("IDirectSoundImpl_Create failed\n");
1025 /*******************************************************************************
1026 * DirectSoundCreate8 (DSOUND.11)
1028 * Creates and initializes a DirectSound8 interface.
1031 * lpcGUID [I] Address of the GUID that identifies the sound device.
1032 * ppDS [O] Address of a variable to receive the interface pointer.
1033 * pUnkOuter [I] Must be NULL.
1037 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1038 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1040 HRESULT WINAPI
DirectSoundCreate8(
1042 LPDIRECTSOUND8
*ppDS
,
1043 IUnknown
*pUnkOuter
)
1048 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1051 WARN("invalid parameter: ppDS == NULL\n");
1052 return DSERR_INVALIDPARAM
;
1055 if (pUnkOuter
!= NULL
) {
1056 WARN("invalid parameter: pUnkOuter != NULL\n");
1058 return DSERR_INVALIDPARAM
;
1061 hr
= DSOUND_Create8(&pDS
, pUnkOuter
);
1063 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
1065 if (hr
!= DSERR_ALREADYINITIALIZED
) {
1066 IDirectSound8_Release(pDS
);
1078 /*******************************************************************************
1081 HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
1083 DirectSoundDevice
* device
;
1084 TRACE("(%p)\n", ppDevice
);
1086 /* Allocate memory */
1087 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
1088 if (device
== NULL
) {
1089 WARN("out of memory\n");
1090 return DSERR_OUTOFMEMORY
;
1094 device
->driver
= NULL
;
1095 device
->priolevel
= DSSCL_NORMAL
;
1096 device
->fraglen
= 0;
1097 device
->hwbuf
= NULL
;
1098 device
->buffer
= NULL
;
1100 device
->writelead
= 0;
1101 device
->state
= STATE_STOPPED
;
1102 device
->nrofbuffers
= 0;
1103 device
->buffers
= NULL
;
1104 device
->primary
= NULL
;
1105 device
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
1106 device
->tmp_buffer
= NULL
;
1107 device
->tmp_buffer_len
= 0;
1109 /* 3D listener initial parameters */
1110 device
->listener
= NULL
;
1111 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
1112 device
->ds3dl
.vPosition
.x
= 0.0;
1113 device
->ds3dl
.vPosition
.y
= 0.0;
1114 device
->ds3dl
.vPosition
.z
= 0.0;
1115 device
->ds3dl
.vVelocity
.x
= 0.0;
1116 device
->ds3dl
.vVelocity
.y
= 0.0;
1117 device
->ds3dl
.vVelocity
.z
= 0.0;
1118 device
->ds3dl
.vOrientFront
.x
= 0.0;
1119 device
->ds3dl
.vOrientFront
.y
= 0.0;
1120 device
->ds3dl
.vOrientFront
.z
= 1.0;
1121 device
->ds3dl
.vOrientTop
.x
= 0.0;
1122 device
->ds3dl
.vOrientTop
.y
= 1.0;
1123 device
->ds3dl
.vOrientTop
.z
= 0.0;
1124 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
1125 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
1126 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
1128 device
->prebuf
= ds_snd_queue_max
;
1129 device
->guid
= GUID_NULL
;
1131 /* Set default wave format (may need it for waveOutOpen) */
1132 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
1133 if (device
->pwfx
== NULL
) {
1134 WARN("out of memory\n");
1135 HeapFree(GetProcessHeap(),0,device
);
1136 return DSERR_OUTOFMEMORY
;
1139 /* We rely on the sound driver to return the actual sound format of
1140 * the device if it does not support 22050x8x2 and is given the
1141 * WAVE_DIRECTSOUND flag.
1143 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
1144 device
->pwfx
->nSamplesPerSec
= 22050;
1145 device
->pwfx
->wBitsPerSample
= 8;
1146 device
->pwfx
->nChannels
= 2;
1147 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
1148 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
1149 device
->pwfx
->cbSize
= 0;
1151 InitializeCriticalSection(&(device
->mixlock
));
1152 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSOUND_mixlock";
1154 RtlInitializeResource(&(device
->buffer_list_lock
));
1161 ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
1163 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1164 TRACE("(%p) ref was %ld\n", device
, ref
- 1);
1168 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
1171 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1172 TRACE("(%p) ref was %lu\n", device
, ref
+ 1);
1175 timeKillEvent(device
->timerID
);
1176 timeEndPeriod(DS_TIME_RES
);
1177 /* wait for timer to expire */
1178 Sleep(DS_TIME_RES
+1);
1180 /* The sleep above should have allowed the timer process to expire
1181 * but try to grab the lock just in case. Can't hold lock because
1182 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1183 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
1184 RtlReleaseResource(&(device
->buffer_list_lock
));
1186 /* It is allowed to release this object even when buffers are playing */
1187 if (device
->buffers
) {
1188 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
1189 for( i
=0;i
<device
->nrofbuffers
;i
++)
1190 IDirectSoundBufferImpl_Destroy(device
->buffers
[i
]);
1193 if (device
->primary
) {
1194 WARN("primary buffer not released\n");
1195 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)device
->primary
);
1198 hr
= DSOUND_PrimaryDestroy(device
);
1200 WARN("DSOUND_PrimaryDestroy failed\n");
1203 IDsDriver_Close(device
->driver
);
1205 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1206 waveOutClose(device
->hwo
);
1209 IDsDriver_Release(device
->driver
);
1211 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = NULL
;
1213 HeapFree(GetProcessHeap(),0,device
->tmp_buffer
);
1214 HeapFree(GetProcessHeap(),0,device
->buffer
);
1215 RtlDeleteResource(&device
->buffer_list_lock
);
1216 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
1217 DeleteCriticalSection(&device
->mixlock
);
1218 HeapFree(GetProcessHeap(),0,device
);
1219 TRACE("(%p) released\n", device
);
1224 HRESULT
DirectSoundDevice_GetCaps(
1225 DirectSoundDevice
* device
,
1228 TRACE("(%p,%p)\n",device
,lpDSCaps
);
1230 if (device
== NULL
) {
1231 WARN("not initialized\n");
1232 return DSERR_UNINITIALIZED
;
1235 if (lpDSCaps
== NULL
) {
1236 WARN("invalid parameter: lpDSCaps = NULL\n");
1237 return DSERR_INVALIDPARAM
;
1240 /* check if there is enough room */
1241 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
1242 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
1243 lpDSCaps
->dwSize
, sizeof(*lpDSCaps
));
1244 return DSERR_INVALIDPARAM
;
1247 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1248 if (TRACE_ON(dsound
)) {
1249 TRACE("(flags=0x%08lx:\n",lpDSCaps
->dwFlags
);
1250 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1253 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1254 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1255 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1256 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1257 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1258 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1259 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1260 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1261 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1262 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1263 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1264 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1265 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1266 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1267 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1268 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1269 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1270 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1272 /* driver doesn't have these */
1273 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
1274 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
1279 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1283 BOOLEAN found
= FALSE
;
1285 DirectSoundDevice
* device
= *ppDevice
;
1286 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1288 if (*ppDevice
!= NULL
) {
1289 WARN("already initialized\n");
1290 return DSERR_ALREADYINITIALIZED
;
1293 /* Default device? */
1294 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1295 lpcGUID
= &DSDEVID_DefaultPlayback
;
1297 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1298 WARN("invalid parameter: lpcGUID\n");
1299 return DSERR_INVALIDPARAM
;
1302 /* Enumerate WINMM audio devices and find the one we want */
1303 wodn
= waveOutGetNumDevs();
1305 WARN("no driver\n");
1306 return DSERR_NODRIVER
;
1309 for (wod
=0; wod
<wodn
; wod
++) {
1310 if (IsEqualGUID( &devGUID
, &DSOUND_renderer_guids
[wod
])) {
1316 if (found
== FALSE
) {
1317 WARN("No device found matching given ID!\n");
1318 return DSERR_NODRIVER
;
1321 if (DSOUND_renderer
[wod
]) {
1322 if (IsEqualGUID(&devGUID
, &DSOUND_renderer
[wod
]->guid
)) {
1323 device
= DSOUND_renderer
[wod
];
1324 DirectSoundDevice_AddRef(device
);
1328 ERR("device GUID doesn't match\n");
1333 hr
= DirectSoundDevice_Create(&device
);
1335 WARN("DirectSoundDevice_Create failed\n");
1341 device
->guid
= devGUID
;
1343 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
1344 waveOutMessage((HWAVEOUT
)wod
, DRV_QUERYDSOUNDIFACE
, (DWORD_PTR
)&device
->driver
, 0);
1346 /* Disable the direct sound driver to force emulation if requested. */
1347 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
1348 device
->driver
= NULL
;
1350 /* Get driver description */
1351 if (device
->driver
) {
1352 hr
= IDsDriver_GetDriverDesc(device
->driver
,&(device
->drvdesc
));
1354 WARN("IDsDriver_GetDriverDesc failed\n");
1358 /* if no DirectSound interface available, use WINMM API instead */
1359 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
| DSDDESC_DOMMSYSTEMSETFORMAT
;
1362 device
->drvdesc
.dnDevNode
= wod
;
1364 /* If the driver requests being opened through MMSYSTEM
1365 * (which is recommended by the DDK), it is supposed to happen
1366 * before the DirectSound interface is opened */
1367 if (device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1369 DWORD flags
= CALLBACK_FUNCTION
;
1371 /* disable direct sound if requested */
1372 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1373 flags
|= WAVE_DIRECTSOUND
;
1375 hr
= mmErr(waveOutOpen(&(device
->hwo
),
1376 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1377 (DWORD_PTR
)DSOUND_callback
, (DWORD
)device
,
1380 WARN("waveOutOpen failed\n");
1385 if (device
->driver
) {
1386 hr
= IDsDriver_Open(device
->driver
);
1388 WARN("IDsDriver_Open failed\n");
1392 /* the driver is now open, so it's now allowed to call GetCaps */
1393 hr
= IDsDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1395 WARN("IDsDriver_GetCaps failed\n");
1400 hr
= mmErr(waveOutGetDevCapsA(device
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
1402 WARN("waveOutGetDevCaps failed\n");
1405 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1406 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
1407 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
1408 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
1409 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
1410 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
1411 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1412 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1414 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
1415 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
1416 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
1417 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
1418 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
1419 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1420 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
1422 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
1423 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
1424 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
1425 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
1426 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
1427 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
1428 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1430 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
1431 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
1432 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
1433 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
1434 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
1435 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
1436 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
1439 device
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
1440 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1441 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1442 device
->drvcaps
.dwPrimaryBuffers
= 1;
1445 hr
= DSOUND_PrimaryCreate(device
);
1447 DSOUND_renderer
[device
->drvdesc
.dnDevNode
] = device
;
1448 timeBeginPeriod(DS_TIME_RES
);
1449 DSOUND_renderer
[device
->drvdesc
.dnDevNode
]->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1450 (DWORD_PTR
)DSOUND_renderer
[device
->drvdesc
.dnDevNode
], TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1452 WARN("DSOUND_PrimaryCreate failed\n");
1458 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1459 DirectSoundDevice
* device
,
1460 LPCDSBUFFERDESC dsbd
,
1461 LPLPDIRECTSOUNDBUFFER ppdsb
,
1465 HRESULT hres
= DS_OK
;
1466 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1468 if (device
== NULL
) {
1469 WARN("not initialized\n");
1470 return DSERR_UNINITIALIZED
;
1474 WARN("invalid parameter: dsbd == NULL\n");
1475 return DSERR_INVALIDPARAM
;
1478 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1479 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1480 WARN("invalid parameter: dsbd\n");
1481 return DSERR_INVALIDPARAM
;
1484 if (ppdsb
== NULL
) {
1485 WARN("invalid parameter: ppdsb == NULL\n");
1486 return DSERR_INVALIDPARAM
;
1489 if (TRACE_ON(dsound
)) {
1490 TRACE("(structsize=%ld)\n",dsbd
->dwSize
);
1491 TRACE("(flags=0x%08lx:\n",dsbd
->dwFlags
);
1492 _dump_DSBCAPS(dsbd
->dwFlags
);
1494 TRACE("(bufferbytes=%ld)\n",dsbd
->dwBufferBytes
);
1495 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1498 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1499 if (dsbd
->lpwfxFormat
!= NULL
) {
1500 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1501 "primary buffer\n");
1502 return DSERR_INVALIDPARAM
;
1505 if (device
->primary
) {
1506 WARN("Primary Buffer already created\n");
1507 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1508 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1510 device
->dsbd
= *dsbd
;
1511 hres
= PrimaryBufferImpl_Create(device
, (PrimaryBufferImpl
**)&(device
->primary
), &(device
->dsbd
));
1512 if (device
->primary
) {
1513 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1514 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1516 WARN("PrimaryBufferImpl_Create failed\n");
1519 IDirectSoundBufferImpl
* dsb
;
1521 if (dsbd
->lpwfxFormat
== NULL
) {
1522 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1523 "secondary buffer\n");
1524 return DSERR_INVALIDPARAM
;
1527 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
1528 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1529 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1530 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1531 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1532 dsbd
->lpwfxFormat
->nBlockAlign
,
1533 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1535 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1536 WARN("invalid parameter: 3D buffer format must be mono\n");
1537 return DSERR_INVALIDPARAM
;
1540 hres
= IDirectSoundBufferImpl_Create(device
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
1542 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1544 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1545 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
1547 WARN("SecondaryBufferImpl_Create failed\n");
1549 WARN("IDirectSoundBufferImpl_Create failed\n");
1555 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1556 DirectSoundDevice
* device
,
1557 LPDIRECTSOUNDBUFFER psb
,
1558 LPLPDIRECTSOUNDBUFFER ppdsb
)
1560 HRESULT hres
= DS_OK
;
1561 IDirectSoundBufferImpl
* dsb
;
1562 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1564 if (device
== NULL
) {
1565 WARN("not initialized\n");
1566 return DSERR_UNINITIALIZED
;
1570 WARN("invalid parameter: psb == NULL\n");
1571 return DSERR_INVALIDPARAM
;
1574 if (ppdsb
== NULL
) {
1575 WARN("invalid parameter: ppdsb == NULL\n");
1576 return DSERR_INVALIDPARAM
;
1579 /* make sure we have a secondary buffer */
1580 if ((PrimaryBufferImpl
*)psb
== device
->primary
) {
1581 WARN("trying to duplicate primary buffer\n");
1583 return DSERR_INVALIDCALL
;
1586 /* duplicate the actual buffer implementation */
1587 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
,
1588 ((SecondaryBufferImpl
*)psb
)->dsb
);
1590 if (hres
== DS_OK
) {
1591 /* create a new secondary buffer using the new implementation */
1592 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
1594 dsb
->secondary
= (SecondaryBufferImpl
*)*ppdsb
;
1595 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
1597 WARN("SecondaryBufferImpl_Create failed\n");
1598 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)dsb
);
1599 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8
)dsb
);
1606 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1607 DirectSoundDevice
* device
,
1611 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1613 if (device
== NULL
) {
1614 WARN("not initialized\n");
1615 return DSERR_UNINITIALIZED
;
1618 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1619 WARN("level=%s not fully supported\n",
1620 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1623 device
->priolevel
= level
;
1627 HRESULT
DirectSoundDevice_Compact(
1628 DirectSoundDevice
* device
)
1630 TRACE("(%p)\n", device
);
1632 if (device
== NULL
) {
1633 WARN("not initialized\n");
1634 return DSERR_UNINITIALIZED
;
1637 if (device
->priolevel
!= DSSCL_PRIORITY
) {
1638 WARN("incorrect priority level\n");
1639 return DSERR_PRIOLEVELNEEDED
;
1645 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1646 DirectSoundDevice
* device
,
1647 LPDWORD lpdwSpeakerConfig
)
1649 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1651 if (device
== NULL
) {
1652 WARN("not initialized\n");
1653 return DSERR_UNINITIALIZED
;
1656 if (lpdwSpeakerConfig
== NULL
) {
1657 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1658 return DSERR_INVALIDPARAM
;
1661 WARN("not fully functional\n");
1662 *lpdwSpeakerConfig
= device
->speaker_config
;
1666 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1667 DirectSoundDevice
* device
,
1670 TRACE("(%p,0x%08lx)\n",device
,config
);
1672 if (device
== NULL
) {
1673 WARN("not initialized\n");
1674 return DSERR_UNINITIALIZED
;
1677 device
->speaker_config
= config
;
1678 WARN("not fully functional\n");
1682 HRESULT
DirectSoundDevice_VerifyCertification(
1683 DirectSoundDevice
* device
,
1684 LPDWORD pdwCertified
)
1686 TRACE("(%p, %p)\n",device
,pdwCertified
);
1688 if (device
== NULL
) {
1689 WARN("not initialized\n");
1690 return DSERR_UNINITIALIZED
;
1693 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1694 *pdwCertified
= DS_CERTIFIED
;
1696 *pdwCertified
= DS_UNCERTIFIED
;
1702 * Add secondary buffer to buffer list.
1703 * Gets exclusive access to buffer for writing.
1705 HRESULT
DirectSoundDevice_AddBuffer(
1706 DirectSoundDevice
* device
,
1707 IDirectSoundBufferImpl
* pDSB
)
1709 IDirectSoundBufferImpl
**newbuffers
;
1712 TRACE("(%p, %p)\n", device
, pDSB
);
1714 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1716 if (device
->buffers
)
1717 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1719 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1722 device
->buffers
= newbuffers
;
1723 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1724 device
->nrofbuffers
++;
1725 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1727 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1728 hr
= DSERR_OUTOFMEMORY
;
1731 RtlReleaseResource(&(device
->buffer_list_lock
));
1737 * Remove secondary buffer from buffer list.
1738 * Gets exclusive access to buffer for writing.
1740 HRESULT
DirectSoundDevice_RemoveBuffer(
1741 DirectSoundDevice
* device
,
1742 IDirectSoundBufferImpl
* pDSB
)
1747 TRACE("(%p, %p)\n", device
, pDSB
);
1749 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1751 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1752 if (device
->buffers
[i
] == pDSB
)
1755 if (i
< device
->nrofbuffers
) {
1756 /* Put the last buffer of the list in the (now empty) position */
1757 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1758 device
->nrofbuffers
--;
1759 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1760 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1763 if (device
->nrofbuffers
== 0) {
1764 HeapFree(GetProcessHeap(),0,device
->buffers
);
1765 device
->buffers
= NULL
;
1768 RtlReleaseResource(&(device
->buffer_list_lock
));