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
27 #define NONAMELESSSTRUCT
28 #define NONAMELESSUNION
38 #include "wine/debug.h"
40 #include "dsound_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
44 /*****************************************************************************
45 * IDirectSound COM components
47 struct IDirectSound_IUnknown
{
48 const IUnknownVtbl
*lpVtbl
;
53 static HRESULT
IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds
, LPUNKNOWN
* ppunk
);
55 struct IDirectSound_IDirectSound
{
56 const IDirectSoundVtbl
*lpVtbl
;
61 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
63 /*****************************************************************************
64 * IDirectSound8 COM components
66 struct IDirectSound8_IDirectSound8
{
67 const IDirectSound8Vtbl
*lpVtbl
;
72 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
73 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
75 /*****************************************************************************
76 * IDirectSound implementation structure
78 struct IDirectSoundImpl
82 DirectSoundDevice
*device
;
89 static HRESULT
IDirectSoundImpl_Create(IDirectSound8
**ppds
, BOOL has_ds8
);
91 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
92 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
94 const char * dumpCooperativeLevel(DWORD level
)
96 #define LE(x) case x: return #x
101 LE(DSSCL_WRITEPRIMARY
);
104 return wine_dbg_sprintf("Unknown(%08x)", level
);
107 static void _dump_DSCAPS(DWORD xmask
) {
112 #define FE(x) { x, #x },
113 FE(DSCAPS_PRIMARYMONO
)
114 FE(DSCAPS_PRIMARYSTEREO
)
115 FE(DSCAPS_PRIMARY8BIT
)
116 FE(DSCAPS_PRIMARY16BIT
)
117 FE(DSCAPS_CONTINUOUSRATE
)
118 FE(DSCAPS_EMULDRIVER
)
120 FE(DSCAPS_SECONDARYMONO
)
121 FE(DSCAPS_SECONDARYSTEREO
)
122 FE(DSCAPS_SECONDARY8BIT
)
123 FE(DSCAPS_SECONDARY16BIT
)
128 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
129 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
130 TRACE("%s ",flags
[i
].name
);
133 static void _dump_DSBCAPS(DWORD xmask
) {
138 #define FE(x) { x, #x },
139 FE(DSBCAPS_PRIMARYBUFFER
)
141 FE(DSBCAPS_LOCHARDWARE
)
142 FE(DSBCAPS_LOCSOFTWARE
)
144 FE(DSBCAPS_CTRLFREQUENCY
)
146 FE(DSBCAPS_CTRLVOLUME
)
147 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
148 FE(DSBCAPS_STICKYFOCUS
)
149 FE(DSBCAPS_GLOBALFOCUS
)
150 FE(DSBCAPS_GETCURRENTPOSITION2
)
151 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
156 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
157 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
158 TRACE("%s ",flags
[i
].name
);
161 /*******************************************************************************
162 * IDirectSoundImpl_DirectSound
164 static HRESULT
DSOUND_QueryInterface(
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 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
180 if (!This
->pUnknown
) {
181 WARN("IDirectSound_IUnknown_Create() failed\n");
183 return E_NOINTERFACE
;
186 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
187 *ppobj
= This
->pUnknown
;
189 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
191 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
193 WARN("IDirectSound_IDirectSound_Create() failed\n");
195 return E_NOINTERFACE
;
198 IDirectSound_IDirectSound_AddRef(This
->pDS
);
201 } else if (This
->has_ds8
&& 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 %d\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 %d\n", This
, ref
+ 1);
238 DirectSoundDevice_Release(This
->device
);
239 HeapFree(GetProcessHeap(),0,This
);
240 TRACE("(%p) released\n", This
);
245 static HRESULT
IDirectSoundImpl_Create(IDirectSound8
**ppDS
, BOOL has_ds8
)
247 IDirectSoundImpl
* pDS
;
248 TRACE("(%p)\n",ppDS
);
250 /* Allocate memory */
251 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
253 WARN("out of memory\n");
255 return DSERR_OUTOFMEMORY
;
260 pDS
->has_ds8
= has_ds8
;
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 %d\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 %d\n", This
, ref
+ 1);
296 ((IDirectSoundImpl
*)This
->pds
)->pUnknown
= NULL
;
297 IDirectSoundImpl_Release(This
->pds
);
298 HeapFree(GetProcessHeap(), 0, This
);
299 TRACE("(%p) released\n", This
);
304 static const IUnknownVtbl DirectSound_Unknown_Vtbl
=
306 IDirectSound_IUnknown_QueryInterface
,
307 IDirectSound_IUnknown_AddRef
,
308 IDirectSound_IUnknown_Release
311 static HRESULT
IDirectSound_IUnknown_Create(
315 IDirectSound_IUnknown
* pdsunk
;
316 TRACE("(%p,%p)\n",pds
,ppunk
);
319 ERR("invalid parameter: ppunk == NULL\n");
320 return DSERR_INVALIDPARAM
;
324 ERR("invalid parameter: pds == NULL\n");
326 return DSERR_INVALIDPARAM
;
329 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
330 if (pdsunk
== NULL
) {
331 WARN("out of memory\n");
333 return DSERR_OUTOFMEMORY
;
336 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
340 IDirectSoundImpl_AddRef(pds
);
341 *ppunk
= (LPUNKNOWN
)pdsunk
;
346 /*******************************************************************************
347 * IDirectSound_IDirectSound
349 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
354 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
355 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
356 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
359 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
362 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
363 ULONG ref
= InterlockedIncrement(&(This
->ref
));
364 TRACE("(%p) ref was %d\n", This
, ref
- 1);
368 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
371 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
372 ULONG ref
= InterlockedDecrement(&(This
->ref
));
373 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
375 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
376 IDirectSoundImpl_Release(This
->pds
);
377 HeapFree(GetProcessHeap(), 0, This
);
378 TRACE("(%p) released\n", This
);
383 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
385 LPCDSBUFFERDESC dsbd
,
386 LPLPDIRECTSOUNDBUFFER ppdsb
,
389 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
390 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
391 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,((IDirectSoundImpl
*)This
->pds
)->has_ds8
);
394 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
398 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
399 TRACE("(%p,%p)\n",This
,lpDSCaps
);
400 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
403 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
405 LPDIRECTSOUNDBUFFER psb
,
406 LPLPDIRECTSOUNDBUFFER ppdsb
)
408 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
409 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
410 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
413 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
418 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
419 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
420 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
423 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
426 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
427 TRACE("(%p)\n", This
);
428 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
431 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
433 LPDWORD lpdwSpeakerConfig
)
435 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
436 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
437 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
440 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
444 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
445 TRACE("(%p,0x%08x)\n",This
,config
);
446 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
449 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
453 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
454 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
455 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
458 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
460 IDirectSound_IDirectSound_QueryInterface
,
461 IDirectSound_IDirectSound_AddRef
,
462 IDirectSound_IDirectSound_Release
,
463 IDirectSound_IDirectSound_CreateSoundBuffer
,
464 IDirectSound_IDirectSound_GetCaps
,
465 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
466 IDirectSound_IDirectSound_SetCooperativeLevel
,
467 IDirectSound_IDirectSound_Compact
,
468 IDirectSound_IDirectSound_GetSpeakerConfig
,
469 IDirectSound_IDirectSound_SetSpeakerConfig
,
470 IDirectSound_IDirectSound_Initialize
473 static HRESULT
IDirectSound_IDirectSound_Create(
475 LPDIRECTSOUND
* ppds
)
477 IDirectSound_IDirectSound
* pdsds
;
478 TRACE("(%p,%p)\n",pds
,ppds
);
481 ERR("invalid parameter: ppds == NULL\n");
482 return DSERR_INVALIDPARAM
;
486 ERR("invalid parameter: pds == NULL\n");
488 return DSERR_INVALIDPARAM
;
491 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
493 WARN("out of memory\n");
495 return DSERR_OUTOFMEMORY
;
498 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
502 IDirectSoundImpl_AddRef(pds
);
503 *ppds
= (LPDIRECTSOUND
)pdsds
;
508 /*******************************************************************************
509 * IDirectSound8_IDirectSound8
511 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
512 LPDIRECTSOUND8 iface
,
516 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
517 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
518 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
521 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
522 LPDIRECTSOUND8 iface
)
524 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
525 ULONG ref
= InterlockedIncrement(&(This
->ref
));
526 TRACE("(%p) ref was %d\n", This
, ref
- 1);
530 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
531 LPDIRECTSOUND8 iface
)
533 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
534 ULONG ref
= InterlockedDecrement(&(This
->ref
));
535 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
537 ((IDirectSoundImpl
*)This
->pds
)->pDS8
= NULL
;
538 IDirectSoundImpl_Release(This
->pds
);
539 HeapFree(GetProcessHeap(), 0, This
);
540 TRACE("(%p) released\n", This
);
545 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
546 LPDIRECTSOUND8 iface
,
547 LPCDSBUFFERDESC dsbd
,
548 LPLPDIRECTSOUNDBUFFER ppdsb
,
551 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
552 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
553 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
556 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
557 LPDIRECTSOUND8 iface
,
560 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
561 TRACE("(%p,%p)\n",This
,lpDSCaps
);
562 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
565 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
566 LPDIRECTSOUND8 iface
,
567 LPDIRECTSOUNDBUFFER psb
,
568 LPLPDIRECTSOUNDBUFFER ppdsb
)
570 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
571 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
572 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
575 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
576 LPDIRECTSOUND8 iface
,
580 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
581 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
582 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
585 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
586 LPDIRECTSOUND8 iface
)
588 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
589 TRACE("(%p)\n", This
);
590 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
593 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
594 LPDIRECTSOUND8 iface
,
595 LPDWORD lpdwSpeakerConfig
)
597 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
598 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
599 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
602 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
603 LPDIRECTSOUND8 iface
,
606 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
607 TRACE("(%p,0x%08x)\n",This
,config
);
608 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
611 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
612 LPDIRECTSOUND8 iface
,
615 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
616 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
617 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
620 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
621 LPDIRECTSOUND8 iface
,
622 LPDWORD pdwCertified
)
624 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
625 TRACE("(%p, %p)\n", This
, pdwCertified
);
626 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
629 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
631 IDirectSound8_IDirectSound8_QueryInterface
,
632 IDirectSound8_IDirectSound8_AddRef
,
633 IDirectSound8_IDirectSound8_Release
,
634 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
635 IDirectSound8_IDirectSound8_GetCaps
,
636 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
637 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
638 IDirectSound8_IDirectSound8_Compact
,
639 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
640 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
641 IDirectSound8_IDirectSound8_Initialize
,
642 IDirectSound8_IDirectSound8_VerifyCertification
645 static HRESULT
IDirectSound8_IDirectSound8_Create(
647 LPDIRECTSOUND8
* ppds
)
649 IDirectSound8_IDirectSound8
* pdsds
;
650 TRACE("(%p,%p)\n",pds
,ppds
);
653 ERR("invalid parameter: ppds == NULL\n");
654 return DSERR_INVALIDPARAM
;
658 ERR("invalid parameter: pds == NULL\n");
660 return DSERR_INVALIDPARAM
;
663 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
665 WARN("out of memory\n");
667 return DSERR_OUTOFMEMORY
;
670 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
674 IDirectSoundImpl_AddRef(pds
);
675 *ppds
= (LPDIRECTSOUND8
)pdsds
;
680 HRESULT
DSOUND_Create(
686 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
688 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
689 !IsEqualIID(riid
, &IID_IDirectSound
)) {
691 return E_NOINTERFACE
;
694 /* Get dsound configuration */
695 setup_dsound_options();
697 hr
= IDirectSoundImpl_Create(&pDS
, FALSE
);
699 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
701 IDirectSound_IDirectSound_AddRef(*ppDS
);
703 WARN("IDirectSound_IDirectSound_Create failed\n");
704 IDirectSound8_Release(pDS
);
707 WARN("IDirectSoundImpl_Create failed\n");
714 /*******************************************************************************
715 * DirectSoundCreate (DSOUND.1)
717 * Creates and initializes a DirectSound interface.
720 * lpcGUID [I] Address of the GUID that identifies the sound device.
721 * ppDS [O] Address of a variable to receive the interface pointer.
722 * pUnkOuter [I] Must be NULL.
726 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
727 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
729 HRESULT WINAPI
DirectSoundCreate(
737 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
740 WARN("invalid parameter: ppDS == NULL\n");
741 return DSERR_INVALIDPARAM
;
744 if (pUnkOuter
!= NULL
) {
745 WARN("invalid parameter: pUnkOuter != NULL\n");
747 return DSERR_INVALIDPARAM
;
750 hr
= DSOUND_Create(&IID_IDirectSound
, &pDS
);
752 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
754 if (hr
!= DSERR_ALREADYINITIALIZED
) {
755 IDirectSound_Release(pDS
);
767 HRESULT
DSOUND_Create8(
769 LPDIRECTSOUND8
*ppDS
)
773 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDS
);
775 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
776 !IsEqualIID(riid
, &IID_IDirectSound
) &&
777 !IsEqualIID(riid
, &IID_IDirectSound8
)) {
779 return E_NOINTERFACE
;
782 /* Get dsound configuration */
783 setup_dsound_options();
785 hr
= IDirectSoundImpl_Create(&pDS
, TRUE
);
787 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
789 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
791 WARN("IDirectSound8_IDirectSound8_Create failed\n");
792 IDirectSound8_Release(pDS
);
795 WARN("IDirectSoundImpl_Create failed\n");
802 /*******************************************************************************
803 * DirectSoundCreate8 (DSOUND.11)
805 * Creates and initializes a DirectSound8 interface.
808 * lpcGUID [I] Address of the GUID that identifies the sound device.
809 * ppDS [O] Address of a variable to receive the interface pointer.
810 * pUnkOuter [I] Must be NULL.
814 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
815 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
817 HRESULT WINAPI
DirectSoundCreate8(
819 LPDIRECTSOUND8
*ppDS
,
825 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
828 WARN("invalid parameter: ppDS == NULL\n");
829 return DSERR_INVALIDPARAM
;
832 if (pUnkOuter
!= NULL
) {
833 WARN("invalid parameter: pUnkOuter != NULL\n");
835 return DSERR_INVALIDPARAM
;
838 hr
= DSOUND_Create8(&IID_IDirectSound8
, &pDS
);
840 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
842 if (hr
!= DSERR_ALREADYINITIALIZED
) {
843 IDirectSound8_Release(pDS
);
855 /*******************************************************************************
858 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
860 DirectSoundDevice
* device
;
861 TRACE("(%p)\n", ppDevice
);
863 /* Allocate memory */
864 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
865 if (device
== NULL
) {
866 WARN("out of memory\n");
867 return DSERR_OUTOFMEMORY
;
871 device
->priolevel
= DSSCL_NORMAL
;
872 device
->state
= STATE_STOPPED
;
873 device
->speaker_config
= DSSPEAKER_COMBINED(DSSPEAKER_STEREO
, DSSPEAKER_GEOMETRY_WIDE
);
875 /* 3D listener initial parameters */
876 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
877 device
->ds3dl
.vPosition
.x
= 0.0;
878 device
->ds3dl
.vPosition
.y
= 0.0;
879 device
->ds3dl
.vPosition
.z
= 0.0;
880 device
->ds3dl
.vVelocity
.x
= 0.0;
881 device
->ds3dl
.vVelocity
.y
= 0.0;
882 device
->ds3dl
.vVelocity
.z
= 0.0;
883 device
->ds3dl
.vOrientFront
.x
= 0.0;
884 device
->ds3dl
.vOrientFront
.y
= 0.0;
885 device
->ds3dl
.vOrientFront
.z
= 1.0;
886 device
->ds3dl
.vOrientTop
.x
= 0.0;
887 device
->ds3dl
.vOrientTop
.y
= 1.0;
888 device
->ds3dl
.vOrientTop
.z
= 0.0;
889 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
890 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
891 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
893 device
->prebuf
= ds_snd_queue_max
;
894 device
->guid
= GUID_NULL
;
896 /* Set default wave format (may need it for waveOutOpen) */
897 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
898 if (device
->pwfx
== NULL
) {
899 WARN("out of memory\n");
900 HeapFree(GetProcessHeap(),0,device
);
901 return DSERR_OUTOFMEMORY
;
904 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
905 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
906 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
907 device
->pwfx
->nChannels
= 2;
908 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
909 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
910 device
->pwfx
->cbSize
= 0;
912 InitializeCriticalSection(&(device
->mixlock
));
913 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
915 RtlInitializeResource(&(device
->buffer_list_lock
));
922 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
924 ULONG ref
= InterlockedIncrement(&(device
->ref
));
925 TRACE("(%p) ref was %d\n", device
, ref
- 1);
929 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
932 ULONG ref
= InterlockedDecrement(&(device
->ref
));
933 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
936 timeKillEvent(device
->timerID
);
937 timeEndPeriod(DS_TIME_RES
);
939 /* The kill event should have allowed the timer process to expire
940 * but try to grab the lock just in case. Can't hold lock because
941 * secondarybuffer_destroy also grabs the lock */
942 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
943 RtlReleaseResource(&(device
->buffer_list_lock
));
945 EnterCriticalSection(&DSOUND_renderers_lock
);
946 list_remove(&device
->entry
);
947 LeaveCriticalSection(&DSOUND_renderers_lock
);
949 /* It is allowed to release this object even when buffers are playing */
950 if (device
->buffers
) {
951 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
952 for( i
=0;i
<device
->nrofbuffers
;i
++)
953 secondarybuffer_destroy(device
->buffers
[i
]);
956 hr
= DSOUND_PrimaryDestroy(device
);
958 WARN("DSOUND_PrimaryDestroy failed\n");
961 IAudioClient_Release(device
->client
);
963 IAudioRenderClient_Release(device
->render
);
965 IAudioClock_Release(device
->clock
);
967 IAudioStreamVolume_Release(device
->volume
);
969 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
970 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
971 HeapFree(GetProcessHeap(), 0, device
->buffer
);
972 RtlDeleteResource(&device
->buffer_list_lock
);
973 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
974 DeleteCriticalSection(&device
->mixlock
);
975 HeapFree(GetProcessHeap(),0,device
);
976 TRACE("(%p) released\n", device
);
981 HRESULT
DirectSoundDevice_GetCaps(
982 DirectSoundDevice
* device
,
985 TRACE("(%p,%p)\n",device
,lpDSCaps
);
987 if (device
== NULL
) {
988 WARN("not initialized\n");
989 return DSERR_UNINITIALIZED
;
992 if (lpDSCaps
== NULL
) {
993 WARN("invalid parameter: lpDSCaps = NULL\n");
994 return DSERR_INVALIDPARAM
;
997 /* check if there is enough room */
998 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
999 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
1000 return DSERR_INVALIDPARAM
;
1003 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
1004 if (TRACE_ON(dsound
)) {
1005 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
1006 _dump_DSCAPS(lpDSCaps
->dwFlags
);
1009 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
1010 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
1011 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
1012 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
1013 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
1014 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
1015 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
1016 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
1017 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
1018 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
1019 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
1020 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
1021 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
1022 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
1023 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
1024 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
1025 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
1026 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
1027 lpDSCaps
->dwUnlockTransferRateHwBuffers
= device
->drvcaps
.dwUnlockTransferRateHwBuffers
;
1028 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= device
->drvcaps
.dwPlayCpuOverheadSwBuffers
;
1033 BOOL
DSOUND_check_supported(IAudioClient
*client
, DWORD rate
,
1034 DWORD depth
, WORD channels
)
1036 WAVEFORMATEX fmt
, *junk
;
1039 fmt
.wFormatTag
= WAVE_FORMAT_PCM
;
1040 fmt
.nChannels
= channels
;
1041 fmt
.nSamplesPerSec
= rate
;
1042 fmt
.wBitsPerSample
= depth
;
1043 fmt
.nBlockAlign
= (channels
* depth
) / 8;
1044 fmt
.nAvgBytesPerSec
= rate
* fmt
.nBlockAlign
;
1047 hr
= IAudioClient_IsFormatSupported(client
, AUDCLNT_SHAREMODE_SHARED
, &fmt
, &junk
);
1049 CoTaskMemFree(junk
);
1054 UINT
DSOUND_create_timer(LPTIMECALLBACK cb
, DWORD_PTR user
)
1056 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
1059 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
1060 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
1061 if (triggertime
< time
.wPeriodMin
)
1062 triggertime
= time
.wPeriodMin
;
1063 if (res
< time
.wPeriodMin
)
1064 res
= time
.wPeriodMin
;
1065 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
1066 WARN("Could not set minimum resolution, don't expect sound\n");
1067 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
1070 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1071 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
);
1073 ERR("Could not create timer, sound playback will not occur\n");
1078 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
1082 DirectSoundDevice
*device
;
1083 IMMDevice
*mmdevice
;
1085 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
1087 if (*ppDevice
!= NULL
) {
1088 WARN("already initialized\n");
1089 return DSERR_ALREADYINITIALIZED
;
1092 /* Default device? */
1093 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1094 lpcGUID
= &DSDEVID_DefaultPlayback
;
1096 if(IsEqualGUID(lpcGUID
, &DSDEVID_DefaultCapture
) ||
1097 IsEqualGUID(lpcGUID
, &DSDEVID_DefaultVoiceCapture
))
1098 return DSERR_NODRIVER
;
1100 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1101 WARN("invalid parameter: lpcGUID\n");
1102 return DSERR_INVALIDPARAM
;
1105 hr
= get_mmdevice(eRender
, &devGUID
, &mmdevice
);
1109 EnterCriticalSection(&DSOUND_renderers_lock
);
1111 LIST_FOR_EACH_ENTRY(device
, &DSOUND_renderers
, DirectSoundDevice
, entry
){
1112 if(IsEqualGUID(&device
->guid
, &devGUID
)){
1113 IMMDevice_Release(mmdevice
);
1114 DirectSoundDevice_AddRef(device
);
1116 LeaveCriticalSection(&DSOUND_renderers_lock
);
1121 hr
= DirectSoundDevice_Create(&device
);
1123 WARN("DirectSoundDevice_Create failed\n");
1124 IMMDevice_Release(mmdevice
);
1125 LeaveCriticalSection(&DSOUND_renderers_lock
);
1129 device
->mmdevice
= mmdevice
;
1130 device
->guid
= devGUID
;
1132 hr
= DSOUND_ReopenDevice(device
, FALSE
);
1135 HeapFree(GetProcessHeap(), 0, device
);
1136 LeaveCriticalSection(&DSOUND_renderers_lock
);
1137 IMMDevice_Release(mmdevice
);
1138 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
1142 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
1144 if(DSOUND_check_supported(device
->client
, 11025, 8, 1) ||
1145 DSOUND_check_supported(device
->client
, 22050, 8, 1) ||
1146 DSOUND_check_supported(device
->client
, 44100, 8, 1) ||
1147 DSOUND_check_supported(device
->client
, 48000, 8, 1) ||
1148 DSOUND_check_supported(device
->client
, 96000, 8, 1))
1149 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYMONO
;
1151 if(DSOUND_check_supported(device
->client
, 11025, 16, 1) ||
1152 DSOUND_check_supported(device
->client
, 22050, 16, 1) ||
1153 DSOUND_check_supported(device
->client
, 44100, 16, 1) ||
1154 DSOUND_check_supported(device
->client
, 48000, 16, 1) ||
1155 DSOUND_check_supported(device
->client
, 96000, 16, 1))
1156 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYMONO
;
1158 if(DSOUND_check_supported(device
->client
, 11025, 8, 2) ||
1159 DSOUND_check_supported(device
->client
, 22050, 8, 2) ||
1160 DSOUND_check_supported(device
->client
, 44100, 8, 2) ||
1161 DSOUND_check_supported(device
->client
, 48000, 8, 2) ||
1162 DSOUND_check_supported(device
->client
, 96000, 8, 2))
1163 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYSTEREO
;
1165 if(DSOUND_check_supported(device
->client
, 11025, 16, 2) ||
1166 DSOUND_check_supported(device
->client
, 22050, 16, 2) ||
1167 DSOUND_check_supported(device
->client
, 44100, 16, 2) ||
1168 DSOUND_check_supported(device
->client
, 48000, 16, 2) ||
1169 DSOUND_check_supported(device
->client
, 96000, 16, 2))
1170 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYSTEREO
;
1172 /* the dsound mixer supports all of the following */
1173 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARY8BIT
| DSCAPS_SECONDARY16BIT
;
1174 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARYMONO
| DSCAPS_SECONDARYSTEREO
;
1175 device
->drvcaps
.dwFlags
|= DSCAPS_CONTINUOUSRATE
;
1177 device
->drvcaps
.dwPrimaryBuffers
= 1;
1178 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1179 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1180 device
->drvcaps
.dwMaxHwMixingAllBuffers
= 1;
1181 device
->drvcaps
.dwMaxHwMixingStaticBuffers
= 1;
1182 device
->drvcaps
.dwMaxHwMixingStreamingBuffers
= 1;
1184 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1186 hr
= DSOUND_PrimaryCreate(device
);
1188 device
->timerID
= DSOUND_create_timer(DSOUND_timer
, (DWORD_PTR
)device
);
1190 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr
);
1193 list_add_tail(&DSOUND_renderers
, &device
->entry
);
1195 LeaveCriticalSection(&DSOUND_renderers_lock
);
1200 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1201 DirectSoundDevice
* device
,
1202 LPCDSBUFFERDESC dsbd
,
1203 LPLPDIRECTSOUNDBUFFER ppdsb
,
1207 HRESULT hres
= DS_OK
;
1208 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1210 if (device
== NULL
) {
1211 WARN("not initialized\n");
1212 return DSERR_UNINITIALIZED
;
1216 WARN("invalid parameter: dsbd == NULL\n");
1217 return DSERR_INVALIDPARAM
;
1220 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1221 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1222 WARN("invalid parameter: dsbd\n");
1223 return DSERR_INVALIDPARAM
;
1226 if (ppdsb
== NULL
) {
1227 WARN("invalid parameter: ppdsb == NULL\n");
1228 return DSERR_INVALIDPARAM
;
1232 if (TRACE_ON(dsound
)) {
1233 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1234 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1235 _dump_DSBCAPS(dsbd
->dwFlags
);
1237 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1238 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1241 if (dsbd
->dwFlags
& DSBCAPS_LOCHARDWARE
&&
1242 !(dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
)) {
1243 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1247 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1248 if (dsbd
->lpwfxFormat
!= NULL
) {
1249 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1250 "primary buffer\n");
1251 return DSERR_INVALIDPARAM
;
1254 if (device
->primary
) {
1255 WARN("Primary Buffer already created\n");
1256 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1257 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1259 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1260 if (device
->primary
) {
1261 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1262 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1263 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1265 WARN("primarybuffer_create() failed\n");
1268 IDirectSoundBufferImpl
* dsb
;
1269 WAVEFORMATEXTENSIBLE
*pwfxe
;
1271 if (dsbd
->lpwfxFormat
== NULL
) {
1272 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1273 "secondary buffer\n");
1274 return DSERR_INVALIDPARAM
;
1276 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1278 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1280 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1281 return DSERR_CONTROLUNAVAIL
;
1283 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1285 /* check if cbSize is at least 22 bytes */
1286 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1288 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1289 return DSERR_INVALIDPARAM
;
1292 /* cbSize should be 22 bytes, with one possible exception */
1293 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1294 !((IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) || IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) &&
1295 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1297 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1298 return DSERR_CONTROLUNAVAIL
;
1301 if ((!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) && (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
1303 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1304 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1305 return DSERR_INVALIDPARAM
;
1307 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1309 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1310 return DSERR_INVALIDPARAM
;
1312 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1314 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1315 return DSERR_CONTROLUNAVAIL
;
1319 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1320 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1321 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1322 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1323 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1324 dsbd
->lpwfxFormat
->nBlockAlign
,
1325 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1327 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1328 WARN("invalid parameter: 3D buffer format must be mono\n");
1329 return DSERR_INVALIDPARAM
;
1332 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1334 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1336 WARN("IDirectSoundBufferImpl_Create failed\n");
1342 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1343 DirectSoundDevice
* device
,
1344 LPDIRECTSOUNDBUFFER psb
,
1345 LPLPDIRECTSOUNDBUFFER ppdsb
)
1347 HRESULT hres
= DS_OK
;
1348 IDirectSoundBufferImpl
* dsb
;
1349 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1351 if (device
== NULL
) {
1352 WARN("not initialized\n");
1353 return DSERR_UNINITIALIZED
;
1357 WARN("invalid parameter: psb == NULL\n");
1358 return DSERR_INVALIDPARAM
;
1361 if (ppdsb
== NULL
) {
1362 WARN("invalid parameter: ppdsb == NULL\n");
1363 return DSERR_INVALIDPARAM
;
1366 /* make sure we have a secondary buffer */
1367 if (psb
== (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
) {
1368 WARN("trying to duplicate primary buffer\n");
1370 return DSERR_INVALIDCALL
;
1373 /* duplicate the actual buffer implementation */
1374 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
, (IDirectSoundBufferImpl
*)psb
);
1376 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1378 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1383 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1384 DirectSoundDevice
* device
,
1388 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1390 if (device
== NULL
) {
1391 WARN("not initialized\n");
1392 return DSERR_UNINITIALIZED
;
1395 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1396 WARN("level=%s not fully supported\n",
1397 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1400 device
->priolevel
= level
;
1404 HRESULT
DirectSoundDevice_Compact(
1405 DirectSoundDevice
* device
)
1407 TRACE("(%p)\n", device
);
1409 if (device
== NULL
) {
1410 WARN("not initialized\n");
1411 return DSERR_UNINITIALIZED
;
1414 if (device
->priolevel
< DSSCL_PRIORITY
) {
1415 WARN("incorrect priority level\n");
1416 return DSERR_PRIOLEVELNEEDED
;
1422 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1423 DirectSoundDevice
* device
,
1424 LPDWORD lpdwSpeakerConfig
)
1426 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1428 if (device
== NULL
) {
1429 WARN("not initialized\n");
1430 return DSERR_UNINITIALIZED
;
1433 if (lpdwSpeakerConfig
== NULL
) {
1434 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1435 return DSERR_INVALIDPARAM
;
1438 WARN("not fully functional\n");
1439 *lpdwSpeakerConfig
= device
->speaker_config
;
1443 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1444 DirectSoundDevice
* device
,
1447 TRACE("(%p,0x%08x)\n",device
,config
);
1449 if (device
== NULL
) {
1450 WARN("not initialized\n");
1451 return DSERR_UNINITIALIZED
;
1454 device
->speaker_config
= config
;
1455 WARN("not fully functional\n");
1459 HRESULT
DirectSoundDevice_VerifyCertification(
1460 DirectSoundDevice
* device
,
1461 LPDWORD pdwCertified
)
1463 TRACE("(%p, %p)\n",device
,pdwCertified
);
1465 if (device
== NULL
) {
1466 WARN("not initialized\n");
1467 return DSERR_UNINITIALIZED
;
1470 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1471 *pdwCertified
= DS_CERTIFIED
;
1473 *pdwCertified
= DS_UNCERTIFIED
;
1479 * Add secondary buffer to buffer list.
1480 * Gets exclusive access to buffer for writing.
1482 HRESULT
DirectSoundDevice_AddBuffer(
1483 DirectSoundDevice
* device
,
1484 IDirectSoundBufferImpl
* pDSB
)
1486 IDirectSoundBufferImpl
**newbuffers
;
1489 TRACE("(%p, %p)\n", device
, pDSB
);
1491 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1493 if (device
->buffers
)
1494 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1496 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1499 device
->buffers
= newbuffers
;
1500 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1501 device
->nrofbuffers
++;
1502 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1504 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1505 hr
= DSERR_OUTOFMEMORY
;
1508 RtlReleaseResource(&(device
->buffer_list_lock
));
1514 * Remove secondary buffer from buffer list.
1515 * Gets exclusive access to buffer for writing.
1517 HRESULT
DirectSoundDevice_RemoveBuffer(
1518 DirectSoundDevice
* device
,
1519 IDirectSoundBufferImpl
* pDSB
)
1524 TRACE("(%p, %p)\n", device
, pDSB
);
1526 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1528 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1529 if (device
->buffers
[i
] == pDSB
)
1532 if (i
< device
->nrofbuffers
) {
1533 /* Put the last buffer of the list in the (now empty) position */
1534 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1535 device
->nrofbuffers
--;
1536 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1537 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1540 if (device
->nrofbuffers
== 0) {
1541 HeapFree(GetProcessHeap(),0,device
->buffers
);
1542 device
->buffers
= NULL
;
1545 RtlReleaseResource(&(device
->buffer_list_lock
));