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_IDirectSound
{
48 const IDirectSoundVtbl
*lpVtbl
;
53 static HRESULT
IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND
* ppds
);
55 /*****************************************************************************
56 * IDirectSound8 COM components
58 struct IDirectSound8_IDirectSound8
{
59 const IDirectSound8Vtbl
*lpVtbl
;
64 static HRESULT
IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds
, LPDIRECTSOUND8
* ppds
);
66 typedef struct IDirectSoundImpl
{
67 IUnknown IUnknown_iface
; /* Separate refcount, not for COM aggregation */
69 DirectSoundDevice
*device
;
75 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
77 const char * dumpCooperativeLevel(DWORD level
)
79 #define LE(x) case x: return #x
84 LE(DSSCL_WRITEPRIMARY
);
87 return wine_dbg_sprintf("Unknown(%08x)", level
);
90 static void _dump_DSCAPS(DWORD xmask
) {
95 #define FE(x) { x, #x },
96 FE(DSCAPS_PRIMARYMONO
)
97 FE(DSCAPS_PRIMARYSTEREO
)
98 FE(DSCAPS_PRIMARY8BIT
)
99 FE(DSCAPS_PRIMARY16BIT
)
100 FE(DSCAPS_CONTINUOUSRATE
)
101 FE(DSCAPS_EMULDRIVER
)
103 FE(DSCAPS_SECONDARYMONO
)
104 FE(DSCAPS_SECONDARYSTEREO
)
105 FE(DSCAPS_SECONDARY8BIT
)
106 FE(DSCAPS_SECONDARY16BIT
)
111 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
112 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
113 TRACE("%s ",flags
[i
].name
);
116 static void _dump_DSBCAPS(DWORD xmask
) {
121 #define FE(x) { x, #x },
122 FE(DSBCAPS_PRIMARYBUFFER
)
124 FE(DSBCAPS_LOCHARDWARE
)
125 FE(DSBCAPS_LOCSOFTWARE
)
127 FE(DSBCAPS_CTRLFREQUENCY
)
129 FE(DSBCAPS_CTRLVOLUME
)
130 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
131 FE(DSBCAPS_STICKYFOCUS
)
132 FE(DSBCAPS_GLOBALFOCUS
)
133 FE(DSBCAPS_GETCURRENTPOSITION2
)
134 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
139 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
140 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
141 TRACE("%s ",flags
[i
].name
);
144 /*******************************************************************************
145 * IDirectSoundImpl_DirectSound
147 static HRESULT
DSOUND_QueryInterface(
148 LPDIRECTSOUND8 iface
,
152 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
153 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
156 WARN("invalid parameter\n");
160 if (IsEqualIID(riid
, &IID_IUnknown
)) {
161 IUnknown_AddRef(&This
->IUnknown_iface
);
162 *ppobj
= &This
->IUnknown_iface
;
164 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
166 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
168 WARN("IDirectSound_IDirectSound_Create() failed\n");
170 return E_NOINTERFACE
;
173 IDirectSound_IDirectSound_AddRef(This
->pDS
);
176 } else if (This
->has_ds8
&& IsEqualIID(riid
, &IID_IDirectSound8
)) {
178 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
180 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
182 return E_NOINTERFACE
;
185 IDirectSound8_AddRef(This
->pDS8
);
191 WARN("Unknown IID %s\n",debugstr_guid(riid
));
192 return E_NOINTERFACE
;
195 static void directsound_destroy(IDirectSoundImpl
*This
)
198 DirectSoundDevice_Release(This
->device
);
199 HeapFree(GetProcessHeap(),0,This
);
200 TRACE("(%p) released\n", This
);
203 /*******************************************************************************
204 * IUnknown Implementation for DirectSound
206 static inline IDirectSoundImpl
*impl_from_IUnknown(IUnknown
*iface
)
208 return CONTAINING_RECORD(iface
, IDirectSoundImpl
, IUnknown_iface
);
211 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
213 IDirectSoundImpl
*This
= impl_from_IUnknown(iface
);
214 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
215 return DSOUND_QueryInterface((IDirectSound8
*)This
, riid
, ppv
);
218 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
*iface
)
220 IDirectSoundImpl
*This
= impl_from_IUnknown(iface
);
221 ULONG ref
= InterlockedIncrement(&This
->ref
);
223 TRACE("(%p) ref=%d\n", This
, ref
);
226 InterlockedIncrement(&This
->numIfaces
);
231 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
*iface
)
233 IDirectSoundImpl
*This
= impl_from_IUnknown(iface
);
234 ULONG ref
= InterlockedDecrement(&This
->ref
);
236 TRACE("(%p) ref=%d\n", This
, ref
);
238 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
239 directsound_destroy(This
);
244 static const IUnknownVtbl unk_vtbl
=
246 IUnknownImpl_QueryInterface
,
251 /*******************************************************************************
252 * IDirectSound_IDirectSound
254 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
259 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
260 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
261 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
264 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
267 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
268 ULONG ref
= InterlockedIncrement(&(This
->ref
));
269 TRACE("(%p) ref was %d\n", This
, ref
- 1);
273 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
276 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
277 ULONG ref
= InterlockedDecrement(&(This
->ref
));
278 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
279 if (!ref
&& !InterlockedDecrement(&((IDirectSoundImpl
*)This
->pds
)->numIfaces
)) {
280 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
281 directsound_destroy((IDirectSoundImpl
*)This
->pds
);
282 HeapFree(GetProcessHeap(), 0, This
);
283 TRACE("(%p) released\n", This
);
288 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
290 LPCDSBUFFERDESC dsbd
,
291 LPLPDIRECTSOUNDBUFFER ppdsb
,
294 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
295 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
296 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,((IDirectSoundImpl
*)This
->pds
)->has_ds8
);
299 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
303 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
304 TRACE("(%p,%p)\n",This
,lpDSCaps
);
305 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
308 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
310 LPDIRECTSOUNDBUFFER psb
,
311 LPLPDIRECTSOUNDBUFFER ppdsb
)
313 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
314 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
315 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
318 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
323 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
324 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
325 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
328 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
331 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
332 TRACE("(%p)\n", This
);
333 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
336 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
338 LPDWORD lpdwSpeakerConfig
)
340 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
341 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
342 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
345 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
349 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
350 TRACE("(%p,0x%08x)\n",This
,config
);
351 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
354 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
358 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
359 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
360 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
363 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
365 IDirectSound_IDirectSound_QueryInterface
,
366 IDirectSound_IDirectSound_AddRef
,
367 IDirectSound_IDirectSound_Release
,
368 IDirectSound_IDirectSound_CreateSoundBuffer
,
369 IDirectSound_IDirectSound_GetCaps
,
370 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
371 IDirectSound_IDirectSound_SetCooperativeLevel
,
372 IDirectSound_IDirectSound_Compact
,
373 IDirectSound_IDirectSound_GetSpeakerConfig
,
374 IDirectSound_IDirectSound_SetSpeakerConfig
,
375 IDirectSound_IDirectSound_Initialize
378 static HRESULT
IDirectSound_IDirectSound_Create(
380 LPDIRECTSOUND
* ppds
)
382 IDirectSound_IDirectSound
* pdsds
;
383 TRACE("(%p,%p)\n",pds
,ppds
);
386 ERR("invalid parameter: ppds == NULL\n");
387 return DSERR_INVALIDPARAM
;
391 ERR("invalid parameter: pds == NULL\n");
393 return DSERR_INVALIDPARAM
;
396 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
398 WARN("out of memory\n");
400 return DSERR_OUTOFMEMORY
;
403 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
407 InterlockedIncrement(&((IDirectSoundImpl
*)pds
)->numIfaces
);
408 *ppds
= (LPDIRECTSOUND
)pdsds
;
413 /*******************************************************************************
414 * IDirectSound8 Implementation
416 static HRESULT WINAPI
IDirectSound8Impl_QueryInterface(IDirectSound8
*iface
, REFIID riid
,
419 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
420 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
421 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
424 static ULONG WINAPI
IDirectSound8Impl_AddRef(IDirectSound8
*iface
)
426 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
427 ULONG ref
= InterlockedIncrement(&(This
->ref
));
428 TRACE("(%p) ref was %d\n", This
, ref
- 1);
432 static ULONG WINAPI
IDirectSound8Impl_Release(IDirectSound8
*iface
)
434 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
435 ULONG ref
= InterlockedDecrement(&(This
->ref
));
436 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
437 if (!ref
&& !InterlockedDecrement(&((IDirectSoundImpl
*)This
->pds
)->numIfaces
)) {
438 ((IDirectSoundImpl
*)This
->pds
)->pDS8
= NULL
;
439 directsound_destroy((IDirectSoundImpl
*)This
->pds
);
440 HeapFree(GetProcessHeap(), 0, This
);
441 TRACE("(%p) released\n", This
);
446 static HRESULT WINAPI
IDirectSound8Impl_CreateSoundBuffer(IDirectSound8
*iface
,
447 const DSBUFFERDESC
*dsbd
, IDirectSoundBuffer
**ppdsb
, IUnknown
*lpunk
)
449 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
450 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
451 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,TRUE
);
454 static HRESULT WINAPI
IDirectSound8Impl_GetCaps(IDirectSound8
*iface
, DSCAPS
*lpDSCaps
)
456 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
457 TRACE("(%p,%p)\n",This
,lpDSCaps
);
458 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
461 static HRESULT WINAPI
IDirectSound8Impl_DuplicateSoundBuffer(IDirectSound8
*iface
,
462 IDirectSoundBuffer
*psb
, IDirectSoundBuffer
**ppdsb
)
464 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
465 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
466 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
469 static HRESULT WINAPI
IDirectSound8Impl_SetCooperativeLevel(IDirectSound8
*iface
, HWND hwnd
,
472 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
473 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
474 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
477 static HRESULT WINAPI
IDirectSound8Impl_Compact(IDirectSound8
*iface
)
479 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
480 TRACE("(%p)\n", This
);
481 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
484 static HRESULT WINAPI
IDirectSound8Impl_GetSpeakerConfig(IDirectSound8
*iface
,
485 DWORD
*lpdwSpeakerConfig
)
487 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
488 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
489 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
492 static HRESULT WINAPI
IDirectSound8Impl_SetSpeakerConfig(IDirectSound8
*iface
, DWORD config
)
494 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
495 TRACE("(%p,0x%08x)\n",This
,config
);
496 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
499 static HRESULT WINAPI
IDirectSound8Impl_Initialize(IDirectSound8
*iface
, const GUID
*lpcGuid
)
501 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
502 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
503 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
506 static HRESULT WINAPI
IDirectSound8Impl_VerifyCertification(IDirectSound8
*iface
,
509 IDirectSound8_IDirectSound8
*This
= (IDirectSound8_IDirectSound8
*)iface
;
510 TRACE("(%p, %p)\n", This
, pdwCertified
);
511 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl
*)This
->pds
)->device
,pdwCertified
);
514 static const IDirectSound8Vtbl ds8_vtbl
=
516 IDirectSound8Impl_QueryInterface
,
517 IDirectSound8Impl_AddRef
,
518 IDirectSound8Impl_Release
,
519 IDirectSound8Impl_CreateSoundBuffer
,
520 IDirectSound8Impl_GetCaps
,
521 IDirectSound8Impl_DuplicateSoundBuffer
,
522 IDirectSound8Impl_SetCooperativeLevel
,
523 IDirectSound8Impl_Compact
,
524 IDirectSound8Impl_GetSpeakerConfig
,
525 IDirectSound8Impl_SetSpeakerConfig
,
526 IDirectSound8Impl_Initialize
,
527 IDirectSound8Impl_VerifyCertification
530 static HRESULT
IDirectSound8_IDirectSound8_Create(
532 LPDIRECTSOUND8
* ppds
)
534 IDirectSound8_IDirectSound8
* pdsds
;
535 TRACE("(%p,%p)\n",pds
,ppds
);
538 ERR("invalid parameter: ppds == NULL\n");
539 return DSERR_INVALIDPARAM
;
543 ERR("invalid parameter: pds == NULL\n");
545 return DSERR_INVALIDPARAM
;
548 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
550 WARN("out of memory\n");
552 return DSERR_OUTOFMEMORY
;
555 pdsds
->lpVtbl
= &ds8_vtbl
;
559 InterlockedIncrement(&((IDirectSoundImpl
*)pds
)->numIfaces
);
560 *ppds
= (LPDIRECTSOUND8
)pdsds
;
565 static HRESULT
IDirectSoundImpl_Create(REFIID riid
, void **ppv
, BOOL has_ds8
)
567 IDirectSoundImpl
*obj
;
570 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
573 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
575 WARN("out of memory\n");
576 return DSERR_OUTOFMEMORY
;
579 setup_dsound_options();
581 obj
->IUnknown_iface
.lpVtbl
= &unk_vtbl
;
585 obj
->has_ds8
= has_ds8
;
587 hr
= IUnknown_QueryInterface(&obj
->IUnknown_iface
, riid
, ppv
);
588 IUnknown_Release(&obj
->IUnknown_iface
);
593 HRESULT
DSOUND_Create(REFIID riid
, void **ppv
)
595 return IDirectSoundImpl_Create(riid
, ppv
, FALSE
);
598 HRESULT
DSOUND_Create8(REFIID riid
, void **ppv
)
600 return IDirectSoundImpl_Create(riid
, ppv
, TRUE
);
603 /*******************************************************************************
604 * DirectSoundCreate (DSOUND.1)
606 * Creates and initializes a DirectSound interface.
609 * lpcGUID [I] Address of the GUID that identifies the sound device.
610 * ppDS [O] Address of a variable to receive the interface pointer.
611 * pUnkOuter [I] Must be NULL.
615 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
616 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
618 HRESULT WINAPI
DirectSoundCreate(
626 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
629 WARN("invalid parameter: ppDS == NULL\n");
630 return DSERR_INVALIDPARAM
;
633 if (pUnkOuter
!= NULL
) {
634 WARN("invalid parameter: pUnkOuter != NULL\n");
636 return DSERR_INVALIDPARAM
;
639 hr
= DSOUND_Create(&IID_IDirectSound
, (void **)&pDS
);
641 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
643 if (hr
!= DSERR_ALREADYINITIALIZED
) {
644 IDirectSound_Release(pDS
);
656 /*******************************************************************************
657 * DirectSoundCreate8 (DSOUND.11)
659 * Creates and initializes a DirectSound8 interface.
662 * lpcGUID [I] Address of the GUID that identifies the sound device.
663 * ppDS [O] Address of a variable to receive the interface pointer.
664 * pUnkOuter [I] Must be NULL.
668 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
669 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
671 HRESULT WINAPI
DirectSoundCreate8(
673 LPDIRECTSOUND8
*ppDS
,
679 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
682 WARN("invalid parameter: ppDS == NULL\n");
683 return DSERR_INVALIDPARAM
;
686 if (pUnkOuter
!= NULL
) {
687 WARN("invalid parameter: pUnkOuter != NULL\n");
689 return DSERR_INVALIDPARAM
;
692 hr
= DSOUND_Create8(&IID_IDirectSound8
, (void **)&pDS
);
694 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
696 if (hr
!= DSERR_ALREADYINITIALIZED
) {
697 IDirectSound8_Release(pDS
);
709 /*******************************************************************************
712 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
714 DirectSoundDevice
* device
;
715 TRACE("(%p)\n", ppDevice
);
717 /* Allocate memory */
718 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
719 if (device
== NULL
) {
720 WARN("out of memory\n");
721 return DSERR_OUTOFMEMORY
;
725 device
->priolevel
= DSSCL_NORMAL
;
726 device
->state
= STATE_STOPPED
;
727 device
->speaker_config
= DSSPEAKER_COMBINED(DSSPEAKER_STEREO
, DSSPEAKER_GEOMETRY_WIDE
);
729 /* 3D listener initial parameters */
730 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
731 device
->ds3dl
.vPosition
.x
= 0.0;
732 device
->ds3dl
.vPosition
.y
= 0.0;
733 device
->ds3dl
.vPosition
.z
= 0.0;
734 device
->ds3dl
.vVelocity
.x
= 0.0;
735 device
->ds3dl
.vVelocity
.y
= 0.0;
736 device
->ds3dl
.vVelocity
.z
= 0.0;
737 device
->ds3dl
.vOrientFront
.x
= 0.0;
738 device
->ds3dl
.vOrientFront
.y
= 0.0;
739 device
->ds3dl
.vOrientFront
.z
= 1.0;
740 device
->ds3dl
.vOrientTop
.x
= 0.0;
741 device
->ds3dl
.vOrientTop
.y
= 1.0;
742 device
->ds3dl
.vOrientTop
.z
= 0.0;
743 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
744 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
745 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
747 device
->prebuf
= ds_snd_queue_max
;
748 device
->guid
= GUID_NULL
;
750 /* Set default wave format (may need it for waveOutOpen) */
751 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
752 if (device
->pwfx
== NULL
) {
753 WARN("out of memory\n");
754 HeapFree(GetProcessHeap(),0,device
);
755 return DSERR_OUTOFMEMORY
;
758 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
759 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
760 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
761 device
->pwfx
->nChannels
= 2;
762 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
763 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
764 device
->pwfx
->cbSize
= 0;
766 InitializeCriticalSection(&(device
->mixlock
));
767 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
769 RtlInitializeResource(&(device
->buffer_list_lock
));
776 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
778 ULONG ref
= InterlockedIncrement(&(device
->ref
));
779 TRACE("(%p) ref was %d\n", device
, ref
- 1);
783 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
786 ULONG ref
= InterlockedDecrement(&(device
->ref
));
787 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
790 timeKillEvent(device
->timerID
);
791 timeEndPeriod(DS_TIME_RES
);
793 /* The kill event should have allowed the timer process to expire
794 * but try to grab the lock just in case. Can't hold lock because
795 * secondarybuffer_destroy also grabs the lock */
796 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
797 RtlReleaseResource(&(device
->buffer_list_lock
));
799 EnterCriticalSection(&DSOUND_renderers_lock
);
800 list_remove(&device
->entry
);
801 LeaveCriticalSection(&DSOUND_renderers_lock
);
803 /* It is allowed to release this object even when buffers are playing */
804 if (device
->buffers
) {
805 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
806 for( i
=0;i
<device
->nrofbuffers
;i
++)
807 secondarybuffer_destroy(device
->buffers
[i
]);
810 hr
= DSOUND_PrimaryDestroy(device
);
812 WARN("DSOUND_PrimaryDestroy failed\n");
815 IAudioClient_Release(device
->client
);
817 IAudioRenderClient_Release(device
->render
);
819 IAudioClock_Release(device
->clock
);
821 IAudioStreamVolume_Release(device
->volume
);
823 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
824 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
825 HeapFree(GetProcessHeap(), 0, device
->buffer
);
826 RtlDeleteResource(&device
->buffer_list_lock
);
827 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
828 DeleteCriticalSection(&device
->mixlock
);
829 HeapFree(GetProcessHeap(),0,device
);
830 TRACE("(%p) released\n", device
);
835 HRESULT
DirectSoundDevice_GetCaps(
836 DirectSoundDevice
* device
,
839 TRACE("(%p,%p)\n",device
,lpDSCaps
);
841 if (device
== NULL
) {
842 WARN("not initialized\n");
843 return DSERR_UNINITIALIZED
;
846 if (lpDSCaps
== NULL
) {
847 WARN("invalid parameter: lpDSCaps = NULL\n");
848 return DSERR_INVALIDPARAM
;
851 /* check if there is enough room */
852 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
853 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
854 return DSERR_INVALIDPARAM
;
857 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
858 if (TRACE_ON(dsound
)) {
859 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
860 _dump_DSCAPS(lpDSCaps
->dwFlags
);
863 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
864 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
865 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
866 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
867 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
868 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
869 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
870 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
871 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
872 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
873 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
874 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
875 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
876 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
877 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
878 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
879 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
880 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
881 lpDSCaps
->dwUnlockTransferRateHwBuffers
= device
->drvcaps
.dwUnlockTransferRateHwBuffers
;
882 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= device
->drvcaps
.dwPlayCpuOverheadSwBuffers
;
887 BOOL
DSOUND_check_supported(IAudioClient
*client
, DWORD rate
,
888 DWORD depth
, WORD channels
)
890 WAVEFORMATEX fmt
, *junk
;
893 fmt
.wFormatTag
= WAVE_FORMAT_PCM
;
894 fmt
.nChannels
= channels
;
895 fmt
.nSamplesPerSec
= rate
;
896 fmt
.wBitsPerSample
= depth
;
897 fmt
.nBlockAlign
= (channels
* depth
) / 8;
898 fmt
.nAvgBytesPerSec
= rate
* fmt
.nBlockAlign
;
901 hr
= IAudioClient_IsFormatSupported(client
, AUDCLNT_SHAREMODE_SHARED
, &fmt
, &junk
);
908 UINT
DSOUND_create_timer(LPTIMECALLBACK cb
, DWORD_PTR user
)
910 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
913 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
914 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
915 if (triggertime
< time
.wPeriodMin
)
916 triggertime
= time
.wPeriodMin
;
917 if (res
< time
.wPeriodMin
)
918 res
= time
.wPeriodMin
;
919 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
920 WARN("Could not set minimum resolution, don't expect sound\n");
921 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
924 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
925 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
);
927 ERR("Could not create timer, sound playback will not occur\n");
932 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
936 DirectSoundDevice
*device
;
939 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
941 if (*ppDevice
!= NULL
) {
942 WARN("already initialized\n");
943 return DSERR_ALREADYINITIALIZED
;
946 /* Default device? */
947 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
948 lpcGUID
= &DSDEVID_DefaultPlayback
;
950 if(IsEqualGUID(lpcGUID
, &DSDEVID_DefaultCapture
) ||
951 IsEqualGUID(lpcGUID
, &DSDEVID_DefaultVoiceCapture
))
952 return DSERR_NODRIVER
;
954 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
955 WARN("invalid parameter: lpcGUID\n");
956 return DSERR_INVALIDPARAM
;
959 hr
= get_mmdevice(eRender
, &devGUID
, &mmdevice
);
963 EnterCriticalSection(&DSOUND_renderers_lock
);
965 LIST_FOR_EACH_ENTRY(device
, &DSOUND_renderers
, DirectSoundDevice
, entry
){
966 if(IsEqualGUID(&device
->guid
, &devGUID
)){
967 IMMDevice_Release(mmdevice
);
968 DirectSoundDevice_AddRef(device
);
970 LeaveCriticalSection(&DSOUND_renderers_lock
);
975 hr
= DirectSoundDevice_Create(&device
);
977 WARN("DirectSoundDevice_Create failed\n");
978 IMMDevice_Release(mmdevice
);
979 LeaveCriticalSection(&DSOUND_renderers_lock
);
983 device
->mmdevice
= mmdevice
;
984 device
->guid
= devGUID
;
986 hr
= DSOUND_ReopenDevice(device
, FALSE
);
989 HeapFree(GetProcessHeap(), 0, device
);
990 LeaveCriticalSection(&DSOUND_renderers_lock
);
991 IMMDevice_Release(mmdevice
);
992 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
996 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
998 if(DSOUND_check_supported(device
->client
, 11025, 8, 1) ||
999 DSOUND_check_supported(device
->client
, 22050, 8, 1) ||
1000 DSOUND_check_supported(device
->client
, 44100, 8, 1) ||
1001 DSOUND_check_supported(device
->client
, 48000, 8, 1) ||
1002 DSOUND_check_supported(device
->client
, 96000, 8, 1))
1003 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYMONO
;
1005 if(DSOUND_check_supported(device
->client
, 11025, 16, 1) ||
1006 DSOUND_check_supported(device
->client
, 22050, 16, 1) ||
1007 DSOUND_check_supported(device
->client
, 44100, 16, 1) ||
1008 DSOUND_check_supported(device
->client
, 48000, 16, 1) ||
1009 DSOUND_check_supported(device
->client
, 96000, 16, 1))
1010 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYMONO
;
1012 if(DSOUND_check_supported(device
->client
, 11025, 8, 2) ||
1013 DSOUND_check_supported(device
->client
, 22050, 8, 2) ||
1014 DSOUND_check_supported(device
->client
, 44100, 8, 2) ||
1015 DSOUND_check_supported(device
->client
, 48000, 8, 2) ||
1016 DSOUND_check_supported(device
->client
, 96000, 8, 2))
1017 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYSTEREO
;
1019 if(DSOUND_check_supported(device
->client
, 11025, 16, 2) ||
1020 DSOUND_check_supported(device
->client
, 22050, 16, 2) ||
1021 DSOUND_check_supported(device
->client
, 44100, 16, 2) ||
1022 DSOUND_check_supported(device
->client
, 48000, 16, 2) ||
1023 DSOUND_check_supported(device
->client
, 96000, 16, 2))
1024 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYSTEREO
;
1026 /* the dsound mixer supports all of the following */
1027 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARY8BIT
| DSCAPS_SECONDARY16BIT
;
1028 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARYMONO
| DSCAPS_SECONDARYSTEREO
;
1029 device
->drvcaps
.dwFlags
|= DSCAPS_CONTINUOUSRATE
;
1031 device
->drvcaps
.dwPrimaryBuffers
= 1;
1032 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
1033 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
1034 device
->drvcaps
.dwMaxHwMixingAllBuffers
= 1;
1035 device
->drvcaps
.dwMaxHwMixingStaticBuffers
= 1;
1036 device
->drvcaps
.dwMaxHwMixingStreamingBuffers
= 1;
1038 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
1040 hr
= DSOUND_PrimaryCreate(device
);
1042 device
->timerID
= DSOUND_create_timer(DSOUND_timer
, (DWORD_PTR
)device
);
1044 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr
);
1047 list_add_tail(&DSOUND_renderers
, &device
->entry
);
1049 LeaveCriticalSection(&DSOUND_renderers_lock
);
1054 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1055 DirectSoundDevice
* device
,
1056 LPCDSBUFFERDESC dsbd
,
1057 LPLPDIRECTSOUNDBUFFER ppdsb
,
1061 HRESULT hres
= DS_OK
;
1062 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1064 if (device
== NULL
) {
1065 WARN("not initialized\n");
1066 return DSERR_UNINITIALIZED
;
1070 WARN("invalid parameter: dsbd == NULL\n");
1071 return DSERR_INVALIDPARAM
;
1074 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1075 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1076 WARN("invalid parameter: dsbd\n");
1077 return DSERR_INVALIDPARAM
;
1080 if (ppdsb
== NULL
) {
1081 WARN("invalid parameter: ppdsb == NULL\n");
1082 return DSERR_INVALIDPARAM
;
1086 if (TRACE_ON(dsound
)) {
1087 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1088 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1089 _dump_DSBCAPS(dsbd
->dwFlags
);
1091 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1092 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1095 if (dsbd
->dwFlags
& DSBCAPS_LOCHARDWARE
&&
1096 !(dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
)) {
1097 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1101 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1102 if (dsbd
->lpwfxFormat
!= NULL
) {
1103 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1104 "primary buffer\n");
1105 return DSERR_INVALIDPARAM
;
1108 if (device
->primary
) {
1109 WARN("Primary Buffer already created\n");
1110 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1111 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1113 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1114 if (device
->primary
) {
1115 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1116 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1117 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1119 WARN("primarybuffer_create() failed\n");
1122 IDirectSoundBufferImpl
* dsb
;
1123 WAVEFORMATEXTENSIBLE
*pwfxe
;
1125 if (dsbd
->lpwfxFormat
== NULL
) {
1126 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1127 "secondary buffer\n");
1128 return DSERR_INVALIDPARAM
;
1130 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1132 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1134 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1135 return DSERR_CONTROLUNAVAIL
;
1137 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1139 /* check if cbSize is at least 22 bytes */
1140 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1142 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1143 return DSERR_INVALIDPARAM
;
1146 /* cbSize should be 22 bytes, with one possible exception */
1147 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1148 !((IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) || IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) &&
1149 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1151 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1152 return DSERR_CONTROLUNAVAIL
;
1155 if ((!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) && (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
1157 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1158 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1159 return DSERR_INVALIDPARAM
;
1161 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1163 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1164 return DSERR_INVALIDPARAM
;
1166 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1168 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1169 return DSERR_CONTROLUNAVAIL
;
1173 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1174 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1175 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1176 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1177 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1178 dsbd
->lpwfxFormat
->nBlockAlign
,
1179 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1181 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1182 WARN("invalid parameter: 3D buffer format must be mono\n");
1183 return DSERR_INVALIDPARAM
;
1186 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1188 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1190 WARN("IDirectSoundBufferImpl_Create failed\n");
1196 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1197 DirectSoundDevice
* device
,
1198 LPDIRECTSOUNDBUFFER psb
,
1199 LPLPDIRECTSOUNDBUFFER ppdsb
)
1201 HRESULT hres
= DS_OK
;
1202 IDirectSoundBufferImpl
* dsb
;
1203 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1205 if (device
== NULL
) {
1206 WARN("not initialized\n");
1207 return DSERR_UNINITIALIZED
;
1211 WARN("invalid parameter: psb == NULL\n");
1212 return DSERR_INVALIDPARAM
;
1215 if (ppdsb
== NULL
) {
1216 WARN("invalid parameter: ppdsb == NULL\n");
1217 return DSERR_INVALIDPARAM
;
1220 /* make sure we have a secondary buffer */
1221 if (psb
== (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
) {
1222 WARN("trying to duplicate primary buffer\n");
1224 return DSERR_INVALIDCALL
;
1227 /* duplicate the actual buffer implementation */
1228 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
, (IDirectSoundBufferImpl
*)psb
);
1230 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1232 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1237 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1238 DirectSoundDevice
* device
,
1242 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1244 if (device
== NULL
) {
1245 WARN("not initialized\n");
1246 return DSERR_UNINITIALIZED
;
1249 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1250 WARN("level=%s not fully supported\n",
1251 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1254 device
->priolevel
= level
;
1258 HRESULT
DirectSoundDevice_Compact(
1259 DirectSoundDevice
* device
)
1261 TRACE("(%p)\n", device
);
1263 if (device
== NULL
) {
1264 WARN("not initialized\n");
1265 return DSERR_UNINITIALIZED
;
1268 if (device
->priolevel
< DSSCL_PRIORITY
) {
1269 WARN("incorrect priority level\n");
1270 return DSERR_PRIOLEVELNEEDED
;
1276 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1277 DirectSoundDevice
* device
,
1278 LPDWORD lpdwSpeakerConfig
)
1280 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1282 if (device
== NULL
) {
1283 WARN("not initialized\n");
1284 return DSERR_UNINITIALIZED
;
1287 if (lpdwSpeakerConfig
== NULL
) {
1288 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1289 return DSERR_INVALIDPARAM
;
1292 WARN("not fully functional\n");
1293 *lpdwSpeakerConfig
= device
->speaker_config
;
1297 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1298 DirectSoundDevice
* device
,
1301 TRACE("(%p,0x%08x)\n",device
,config
);
1303 if (device
== NULL
) {
1304 WARN("not initialized\n");
1305 return DSERR_UNINITIALIZED
;
1308 device
->speaker_config
= config
;
1309 WARN("not fully functional\n");
1313 HRESULT
DirectSoundDevice_VerifyCertification(
1314 DirectSoundDevice
* device
,
1315 LPDWORD pdwCertified
)
1317 TRACE("(%p, %p)\n",device
,pdwCertified
);
1319 if (device
== NULL
) {
1320 WARN("not initialized\n");
1321 return DSERR_UNINITIALIZED
;
1324 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1325 *pdwCertified
= DS_CERTIFIED
;
1327 *pdwCertified
= DS_UNCERTIFIED
;
1333 * Add secondary buffer to buffer list.
1334 * Gets exclusive access to buffer for writing.
1336 HRESULT
DirectSoundDevice_AddBuffer(
1337 DirectSoundDevice
* device
,
1338 IDirectSoundBufferImpl
* pDSB
)
1340 IDirectSoundBufferImpl
**newbuffers
;
1343 TRACE("(%p, %p)\n", device
, pDSB
);
1345 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1347 if (device
->buffers
)
1348 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1350 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1353 device
->buffers
= newbuffers
;
1354 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1355 device
->nrofbuffers
++;
1356 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1358 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1359 hr
= DSERR_OUTOFMEMORY
;
1362 RtlReleaseResource(&(device
->buffer_list_lock
));
1368 * Remove secondary buffer from buffer list.
1369 * Gets exclusive access to buffer for writing.
1371 HRESULT
DirectSoundDevice_RemoveBuffer(
1372 DirectSoundDevice
* device
,
1373 IDirectSoundBufferImpl
* pDSB
)
1378 TRACE("(%p, %p)\n", device
, pDSB
);
1380 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1382 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1383 if (device
->buffers
[i
] == pDSB
)
1386 if (i
< device
->nrofbuffers
) {
1387 /* Put the last buffer of the list in the (now empty) position */
1388 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1389 device
->nrofbuffers
--;
1390 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1391 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1394 if (device
->nrofbuffers
== 0) {
1395 HeapFree(GetProcessHeap(),0,device
->buffers
);
1396 device
->buffers
= NULL
;
1399 RtlReleaseResource(&(device
->buffer_list_lock
));