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 typedef struct IDirectSoundImpl
{
56 IUnknown IUnknown_iface
; /* Separate refcount, not for COM aggregation */
57 IDirectSound8 IDirectSound8_iface
;
58 LONG ref
, refds
, numIfaces
;
59 DirectSoundDevice
*device
;
64 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
66 const char * dumpCooperativeLevel(DWORD level
)
68 #define LE(x) case x: return #x
73 LE(DSSCL_WRITEPRIMARY
);
76 return wine_dbg_sprintf("Unknown(%08x)", level
);
79 static void _dump_DSCAPS(DWORD xmask
) {
84 #define FE(x) { x, #x },
85 FE(DSCAPS_PRIMARYMONO
)
86 FE(DSCAPS_PRIMARYSTEREO
)
87 FE(DSCAPS_PRIMARY8BIT
)
88 FE(DSCAPS_PRIMARY16BIT
)
89 FE(DSCAPS_CONTINUOUSRATE
)
92 FE(DSCAPS_SECONDARYMONO
)
93 FE(DSCAPS_SECONDARYSTEREO
)
94 FE(DSCAPS_SECONDARY8BIT
)
95 FE(DSCAPS_SECONDARY16BIT
)
100 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
101 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
102 TRACE("%s ",flags
[i
].name
);
105 static void _dump_DSBCAPS(DWORD xmask
) {
110 #define FE(x) { x, #x },
111 FE(DSBCAPS_PRIMARYBUFFER
)
113 FE(DSBCAPS_LOCHARDWARE
)
114 FE(DSBCAPS_LOCSOFTWARE
)
116 FE(DSBCAPS_CTRLFREQUENCY
)
118 FE(DSBCAPS_CTRLVOLUME
)
119 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
120 FE(DSBCAPS_STICKYFOCUS
)
121 FE(DSBCAPS_GLOBALFOCUS
)
122 FE(DSBCAPS_GETCURRENTPOSITION2
)
123 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
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 /*******************************************************************************
134 * IDirectSoundImpl_DirectSound
136 static HRESULT
DSOUND_QueryInterface(
137 LPDIRECTSOUND8 iface
,
141 IDirectSoundImpl
*This
= (IDirectSoundImpl
*)iface
;
142 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
145 WARN("invalid parameter\n");
149 if (IsEqualIID(riid
, &IID_IUnknown
)) {
150 IUnknown_AddRef(&This
->IUnknown_iface
);
151 *ppobj
= &This
->IUnknown_iface
;
153 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
155 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
157 WARN("IDirectSound_IDirectSound_Create() failed\n");
159 return E_NOINTERFACE
;
162 IDirectSound_IDirectSound_AddRef(This
->pDS
);
165 } else if (This
->has_ds8
&& IsEqualIID(riid
, &IID_IDirectSound8
)) {
166 IDirectSound8_AddRef(&This
->IDirectSound8_iface
);
167 *ppobj
= &This
->IDirectSound8_iface
;
172 WARN("Unknown IID %s\n",debugstr_guid(riid
));
173 return E_NOINTERFACE
;
176 static void directsound_destroy(IDirectSoundImpl
*This
)
179 DirectSoundDevice_Release(This
->device
);
180 HeapFree(GetProcessHeap(),0,This
);
181 TRACE("(%p) released\n", This
);
184 /*******************************************************************************
185 * IUnknown Implementation for DirectSound
187 static inline IDirectSoundImpl
*impl_from_IUnknown(IUnknown
*iface
)
189 return CONTAINING_RECORD(iface
, IDirectSoundImpl
, IUnknown_iface
);
192 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
194 IDirectSoundImpl
*This
= impl_from_IUnknown(iface
);
195 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
196 return DSOUND_QueryInterface((IDirectSound8
*)This
, riid
, ppv
);
199 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
*iface
)
201 IDirectSoundImpl
*This
= impl_from_IUnknown(iface
);
202 ULONG ref
= InterlockedIncrement(&This
->ref
);
204 TRACE("(%p) ref=%d\n", This
, ref
);
207 InterlockedIncrement(&This
->numIfaces
);
212 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
*iface
)
214 IDirectSoundImpl
*This
= impl_from_IUnknown(iface
);
215 ULONG ref
= InterlockedDecrement(&This
->ref
);
217 TRACE("(%p) ref=%d\n", This
, ref
);
219 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
220 directsound_destroy(This
);
225 static const IUnknownVtbl unk_vtbl
=
227 IUnknownImpl_QueryInterface
,
232 /*******************************************************************************
233 * IDirectSound_IDirectSound
235 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
240 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
241 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
242 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
245 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
248 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
249 ULONG ref
= InterlockedIncrement(&(This
->ref
));
250 TRACE("(%p) ref was %d\n", This
, ref
- 1);
254 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
257 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
258 ULONG ref
= InterlockedDecrement(&(This
->ref
));
259 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
260 if (!ref
&& !InterlockedDecrement(&((IDirectSoundImpl
*)This
->pds
)->numIfaces
)) {
261 ((IDirectSoundImpl
*)This
->pds
)->pDS
= NULL
;
262 directsound_destroy((IDirectSoundImpl
*)This
->pds
);
263 HeapFree(GetProcessHeap(), 0, This
);
264 TRACE("(%p) released\n", This
);
269 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
271 LPCDSBUFFERDESC dsbd
,
272 LPLPDIRECTSOUNDBUFFER ppdsb
,
275 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
276 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
277 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,dsbd
,ppdsb
,lpunk
,((IDirectSoundImpl
*)This
->pds
)->has_ds8
);
280 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
284 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
285 TRACE("(%p,%p)\n",This
,lpDSCaps
);
286 return DirectSoundDevice_GetCaps(((IDirectSoundImpl
*)This
->pds
)->device
, lpDSCaps
);
289 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
291 LPDIRECTSOUNDBUFFER psb
,
292 LPLPDIRECTSOUNDBUFFER ppdsb
)
294 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
295 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
296 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl
*)This
->pds
)->device
,psb
,ppdsb
);
299 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
304 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
305 TRACE("(%p,%p,%s)\n",This
,hwnd
,dumpCooperativeLevel(level
));
306 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl
*)This
->pds
)->device
, hwnd
, level
);
309 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
312 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
313 TRACE("(%p)\n", This
);
314 return DirectSoundDevice_Compact(((IDirectSoundImpl
*)This
->pds
)->device
);
317 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
319 LPDWORD lpdwSpeakerConfig
)
321 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
322 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
323 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,lpdwSpeakerConfig
);
326 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
330 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
331 TRACE("(%p,0x%08x)\n",This
,config
);
332 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl
*)This
->pds
)->device
,config
);
335 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
339 IDirectSound_IDirectSound
*This
= (IDirectSound_IDirectSound
*)iface
;
340 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
341 return DirectSoundDevice_Initialize(&((IDirectSoundImpl
*)This
->pds
)->device
,lpcGuid
);
344 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
346 IDirectSound_IDirectSound_QueryInterface
,
347 IDirectSound_IDirectSound_AddRef
,
348 IDirectSound_IDirectSound_Release
,
349 IDirectSound_IDirectSound_CreateSoundBuffer
,
350 IDirectSound_IDirectSound_GetCaps
,
351 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
352 IDirectSound_IDirectSound_SetCooperativeLevel
,
353 IDirectSound_IDirectSound_Compact
,
354 IDirectSound_IDirectSound_GetSpeakerConfig
,
355 IDirectSound_IDirectSound_SetSpeakerConfig
,
356 IDirectSound_IDirectSound_Initialize
359 static HRESULT
IDirectSound_IDirectSound_Create(
361 LPDIRECTSOUND
* ppds
)
363 IDirectSound_IDirectSound
* pdsds
;
364 TRACE("(%p,%p)\n",pds
,ppds
);
367 ERR("invalid parameter: ppds == NULL\n");
368 return DSERR_INVALIDPARAM
;
372 ERR("invalid parameter: pds == NULL\n");
374 return DSERR_INVALIDPARAM
;
377 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
379 WARN("out of memory\n");
381 return DSERR_OUTOFMEMORY
;
384 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
388 InterlockedIncrement(&((IDirectSoundImpl
*)pds
)->numIfaces
);
389 *ppds
= (LPDIRECTSOUND
)pdsds
;
394 /*******************************************************************************
395 * IDirectSound8 Implementation
397 static inline IDirectSoundImpl
*impl_from_IDirectSound8(IDirectSound8
*iface
)
399 return CONTAINING_RECORD(iface
, IDirectSoundImpl
, IDirectSound8_iface
);
402 static HRESULT WINAPI
IDirectSound8Impl_QueryInterface(IDirectSound8
*iface
, REFIID riid
,
405 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
406 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
407 return IUnknown_QueryInterface(&This
->IUnknown_iface
, riid
, ppv
);
410 static ULONG WINAPI
IDirectSound8Impl_AddRef(IDirectSound8
*iface
)
412 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
413 ULONG ref
= InterlockedIncrement(&This
->refds
);
415 TRACE("(%p) refds=%d\n", This
, ref
);
418 InterlockedIncrement(&This
->numIfaces
);
423 static ULONG WINAPI
IDirectSound8Impl_Release(IDirectSound8
*iface
)
425 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
426 ULONG ref
= InterlockedDecrement(&(This
->refds
));
428 TRACE("(%p) refds=%d\n", This
, ref
);
430 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
431 directsound_destroy(This
);
436 static HRESULT WINAPI
IDirectSound8Impl_CreateSoundBuffer(IDirectSound8
*iface
,
437 const DSBUFFERDESC
*dsbd
, IDirectSoundBuffer
**ppdsb
, IUnknown
*lpunk
)
439 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
440 TRACE("(%p,%p,%p,%p)\n", This
, dsbd
, ppdsb
, lpunk
);
441 return DirectSoundDevice_CreateSoundBuffer(This
->device
, dsbd
, ppdsb
, lpunk
, TRUE
);
444 static HRESULT WINAPI
IDirectSound8Impl_GetCaps(IDirectSound8
*iface
, DSCAPS
*lpDSCaps
)
446 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
447 TRACE("(%p,%p)\n", This
, lpDSCaps
);
448 return DirectSoundDevice_GetCaps(This
->device
, lpDSCaps
);
451 static HRESULT WINAPI
IDirectSound8Impl_DuplicateSoundBuffer(IDirectSound8
*iface
,
452 IDirectSoundBuffer
*psb
, IDirectSoundBuffer
**ppdsb
)
454 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
455 TRACE("(%p,%p,%p)\n", This
, psb
, ppdsb
);
456 return DirectSoundDevice_DuplicateSoundBuffer(This
->device
, psb
, ppdsb
);
459 static HRESULT WINAPI
IDirectSound8Impl_SetCooperativeLevel(IDirectSound8
*iface
, HWND hwnd
,
462 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
463 TRACE("(%p,%p,%s)\n", This
, hwnd
, dumpCooperativeLevel(level
));
464 return DirectSoundDevice_SetCooperativeLevel(This
->device
, hwnd
, level
);
467 static HRESULT WINAPI
IDirectSound8Impl_Compact(IDirectSound8
*iface
)
469 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
470 TRACE("(%p)\n", This
);
471 return DirectSoundDevice_Compact(This
->device
);
474 static HRESULT WINAPI
IDirectSound8Impl_GetSpeakerConfig(IDirectSound8
*iface
,
475 DWORD
*lpdwSpeakerConfig
)
477 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
478 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
479 return DirectSoundDevice_GetSpeakerConfig(This
->device
, lpdwSpeakerConfig
);
482 static HRESULT WINAPI
IDirectSound8Impl_SetSpeakerConfig(IDirectSound8
*iface
, DWORD config
)
484 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
485 TRACE("(%p,0x%08x)\n", This
, config
);
486 return DirectSoundDevice_SetSpeakerConfig(This
->device
, config
);
489 static HRESULT WINAPI
IDirectSound8Impl_Initialize(IDirectSound8
*iface
, const GUID
*lpcGuid
)
491 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
492 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
493 return DirectSoundDevice_Initialize(&This
->device
, lpcGuid
);
496 static HRESULT WINAPI
IDirectSound8Impl_VerifyCertification(IDirectSound8
*iface
,
499 IDirectSoundImpl
*This
= impl_from_IDirectSound8(iface
);
500 TRACE("(%p, %p)\n", This
, pdwCertified
);
501 return DirectSoundDevice_VerifyCertification(This
->device
, pdwCertified
);
504 static const IDirectSound8Vtbl ds8_vtbl
=
506 IDirectSound8Impl_QueryInterface
,
507 IDirectSound8Impl_AddRef
,
508 IDirectSound8Impl_Release
,
509 IDirectSound8Impl_CreateSoundBuffer
,
510 IDirectSound8Impl_GetCaps
,
511 IDirectSound8Impl_DuplicateSoundBuffer
,
512 IDirectSound8Impl_SetCooperativeLevel
,
513 IDirectSound8Impl_Compact
,
514 IDirectSound8Impl_GetSpeakerConfig
,
515 IDirectSound8Impl_SetSpeakerConfig
,
516 IDirectSound8Impl_Initialize
,
517 IDirectSound8Impl_VerifyCertification
520 static HRESULT
IDirectSoundImpl_Create(REFIID riid
, void **ppv
, BOOL has_ds8
)
522 IDirectSoundImpl
*obj
;
525 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
528 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
530 WARN("out of memory\n");
531 return DSERR_OUTOFMEMORY
;
534 setup_dsound_options();
536 obj
->IUnknown_iface
.lpVtbl
= &unk_vtbl
;
537 obj
->IDirectSound8_iface
.lpVtbl
= &ds8_vtbl
;
542 obj
->has_ds8
= has_ds8
;
544 hr
= IUnknown_QueryInterface(&obj
->IUnknown_iface
, riid
, ppv
);
545 IUnknown_Release(&obj
->IUnknown_iface
);
550 HRESULT
DSOUND_Create(REFIID riid
, void **ppv
)
552 return IDirectSoundImpl_Create(riid
, ppv
, FALSE
);
555 HRESULT
DSOUND_Create8(REFIID riid
, void **ppv
)
557 return IDirectSoundImpl_Create(riid
, ppv
, TRUE
);
560 /*******************************************************************************
561 * DirectSoundCreate (DSOUND.1)
563 * Creates and initializes a DirectSound interface.
566 * lpcGUID [I] Address of the GUID that identifies the sound device.
567 * ppDS [O] Address of a variable to receive the interface pointer.
568 * pUnkOuter [I] Must be NULL.
572 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
573 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
575 HRESULT WINAPI
DirectSoundCreate(
583 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
586 WARN("invalid parameter: ppDS == NULL\n");
587 return DSERR_INVALIDPARAM
;
590 if (pUnkOuter
!= NULL
) {
591 WARN("invalid parameter: pUnkOuter != NULL\n");
593 return DSERR_INVALIDPARAM
;
596 hr
= DSOUND_Create(&IID_IDirectSound
, (void **)&pDS
);
598 hr
= IDirectSound_Initialize(pDS
, lpcGUID
);
600 if (hr
!= DSERR_ALREADYINITIALIZED
) {
601 IDirectSound_Release(pDS
);
613 /*******************************************************************************
614 * DirectSoundCreate8 (DSOUND.11)
616 * Creates and initializes a DirectSound8 interface.
619 * lpcGUID [I] Address of the GUID that identifies the sound device.
620 * ppDS [O] Address of a variable to receive the interface pointer.
621 * pUnkOuter [I] Must be NULL.
625 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
626 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
628 HRESULT WINAPI
DirectSoundCreate8(
630 LPDIRECTSOUND8
*ppDS
,
636 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
639 WARN("invalid parameter: ppDS == NULL\n");
640 return DSERR_INVALIDPARAM
;
643 if (pUnkOuter
!= NULL
) {
644 WARN("invalid parameter: pUnkOuter != NULL\n");
646 return DSERR_INVALIDPARAM
;
649 hr
= DSOUND_Create8(&IID_IDirectSound8
, (void **)&pDS
);
651 hr
= IDirectSound8_Initialize(pDS
, lpcGUID
);
653 if (hr
!= DSERR_ALREADYINITIALIZED
) {
654 IDirectSound8_Release(pDS
);
666 /*******************************************************************************
669 static HRESULT
DirectSoundDevice_Create(DirectSoundDevice
** ppDevice
)
671 DirectSoundDevice
* device
;
672 TRACE("(%p)\n", ppDevice
);
674 /* Allocate memory */
675 device
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DirectSoundDevice
));
676 if (device
== NULL
) {
677 WARN("out of memory\n");
678 return DSERR_OUTOFMEMORY
;
682 device
->priolevel
= DSSCL_NORMAL
;
683 device
->state
= STATE_STOPPED
;
684 device
->speaker_config
= DSSPEAKER_COMBINED(DSSPEAKER_STEREO
, DSSPEAKER_GEOMETRY_WIDE
);
686 /* 3D listener initial parameters */
687 device
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
688 device
->ds3dl
.vPosition
.x
= 0.0;
689 device
->ds3dl
.vPosition
.y
= 0.0;
690 device
->ds3dl
.vPosition
.z
= 0.0;
691 device
->ds3dl
.vVelocity
.x
= 0.0;
692 device
->ds3dl
.vVelocity
.y
= 0.0;
693 device
->ds3dl
.vVelocity
.z
= 0.0;
694 device
->ds3dl
.vOrientFront
.x
= 0.0;
695 device
->ds3dl
.vOrientFront
.y
= 0.0;
696 device
->ds3dl
.vOrientFront
.z
= 1.0;
697 device
->ds3dl
.vOrientTop
.x
= 0.0;
698 device
->ds3dl
.vOrientTop
.y
= 1.0;
699 device
->ds3dl
.vOrientTop
.z
= 0.0;
700 device
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
701 device
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
702 device
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
704 device
->prebuf
= ds_snd_queue_max
;
705 device
->guid
= GUID_NULL
;
707 /* Set default wave format (may need it for waveOutOpen) */
708 device
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
709 if (device
->pwfx
== NULL
) {
710 WARN("out of memory\n");
711 HeapFree(GetProcessHeap(),0,device
);
712 return DSERR_OUTOFMEMORY
;
715 device
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
716 device
->pwfx
->nSamplesPerSec
= ds_default_sample_rate
;
717 device
->pwfx
->wBitsPerSample
= ds_default_bits_per_sample
;
718 device
->pwfx
->nChannels
= 2;
719 device
->pwfx
->nBlockAlign
= device
->pwfx
->wBitsPerSample
* device
->pwfx
->nChannels
/ 8;
720 device
->pwfx
->nAvgBytesPerSec
= device
->pwfx
->nSamplesPerSec
* device
->pwfx
->nBlockAlign
;
721 device
->pwfx
->cbSize
= 0;
723 InitializeCriticalSection(&(device
->mixlock
));
724 device
->mixlock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundDevice.mixlock");
726 RtlInitializeResource(&(device
->buffer_list_lock
));
733 static ULONG
DirectSoundDevice_AddRef(DirectSoundDevice
* device
)
735 ULONG ref
= InterlockedIncrement(&(device
->ref
));
736 TRACE("(%p) ref was %d\n", device
, ref
- 1);
740 ULONG
DirectSoundDevice_Release(DirectSoundDevice
* device
)
743 ULONG ref
= InterlockedDecrement(&(device
->ref
));
744 TRACE("(%p) ref was %u\n", device
, ref
+ 1);
747 timeKillEvent(device
->timerID
);
748 timeEndPeriod(DS_TIME_RES
);
750 /* The kill event should have allowed the timer process to expire
751 * but try to grab the lock just in case. Can't hold lock because
752 * secondarybuffer_destroy also grabs the lock */
753 RtlAcquireResourceShared(&(device
->buffer_list_lock
), TRUE
);
754 RtlReleaseResource(&(device
->buffer_list_lock
));
756 EnterCriticalSection(&DSOUND_renderers_lock
);
757 list_remove(&device
->entry
);
758 LeaveCriticalSection(&DSOUND_renderers_lock
);
760 /* It is allowed to release this object even when buffers are playing */
761 if (device
->buffers
) {
762 WARN("%d secondary buffers not released\n", device
->nrofbuffers
);
763 for( i
=0;i
<device
->nrofbuffers
;i
++)
764 secondarybuffer_destroy(device
->buffers
[i
]);
767 hr
= DSOUND_PrimaryDestroy(device
);
769 WARN("DSOUND_PrimaryDestroy failed\n");
772 IAudioClient_Release(device
->client
);
774 IAudioRenderClient_Release(device
->render
);
776 IAudioClock_Release(device
->clock
);
778 IAudioStreamVolume_Release(device
->volume
);
780 HeapFree(GetProcessHeap(), 0, device
->tmp_buffer
);
781 HeapFree(GetProcessHeap(), 0, device
->mix_buffer
);
782 HeapFree(GetProcessHeap(), 0, device
->buffer
);
783 RtlDeleteResource(&device
->buffer_list_lock
);
784 device
->mixlock
.DebugInfo
->Spare
[0] = 0;
785 DeleteCriticalSection(&device
->mixlock
);
786 HeapFree(GetProcessHeap(),0,device
);
787 TRACE("(%p) released\n", device
);
792 HRESULT
DirectSoundDevice_GetCaps(
793 DirectSoundDevice
* device
,
796 TRACE("(%p,%p)\n",device
,lpDSCaps
);
798 if (device
== NULL
) {
799 WARN("not initialized\n");
800 return DSERR_UNINITIALIZED
;
803 if (lpDSCaps
== NULL
) {
804 WARN("invalid parameter: lpDSCaps = NULL\n");
805 return DSERR_INVALIDPARAM
;
808 /* check if there is enough room */
809 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
810 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps
->dwSize
);
811 return DSERR_INVALIDPARAM
;
814 lpDSCaps
->dwFlags
= device
->drvcaps
.dwFlags
;
815 if (TRACE_ON(dsound
)) {
816 TRACE("(flags=0x%08x:\n",lpDSCaps
->dwFlags
);
817 _dump_DSCAPS(lpDSCaps
->dwFlags
);
820 lpDSCaps
->dwMinSecondarySampleRate
= device
->drvcaps
.dwMinSecondarySampleRate
;
821 lpDSCaps
->dwMaxSecondarySampleRate
= device
->drvcaps
.dwMaxSecondarySampleRate
;
822 lpDSCaps
->dwPrimaryBuffers
= device
->drvcaps
.dwPrimaryBuffers
;
823 lpDSCaps
->dwMaxHwMixingAllBuffers
= device
->drvcaps
.dwMaxHwMixingAllBuffers
;
824 lpDSCaps
->dwMaxHwMixingStaticBuffers
= device
->drvcaps
.dwMaxHwMixingStaticBuffers
;
825 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= device
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
826 lpDSCaps
->dwFreeHwMixingAllBuffers
= device
->drvcaps
.dwFreeHwMixingAllBuffers
;
827 lpDSCaps
->dwFreeHwMixingStaticBuffers
= device
->drvcaps
.dwFreeHwMixingStaticBuffers
;
828 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= device
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
829 lpDSCaps
->dwMaxHw3DAllBuffers
= device
->drvcaps
.dwMaxHw3DAllBuffers
;
830 lpDSCaps
->dwMaxHw3DStaticBuffers
= device
->drvcaps
.dwMaxHw3DStaticBuffers
;
831 lpDSCaps
->dwMaxHw3DStreamingBuffers
= device
->drvcaps
.dwMaxHw3DStreamingBuffers
;
832 lpDSCaps
->dwFreeHw3DAllBuffers
= device
->drvcaps
.dwFreeHw3DAllBuffers
;
833 lpDSCaps
->dwFreeHw3DStaticBuffers
= device
->drvcaps
.dwFreeHw3DStaticBuffers
;
834 lpDSCaps
->dwFreeHw3DStreamingBuffers
= device
->drvcaps
.dwFreeHw3DStreamingBuffers
;
835 lpDSCaps
->dwTotalHwMemBytes
= device
->drvcaps
.dwTotalHwMemBytes
;
836 lpDSCaps
->dwFreeHwMemBytes
= device
->drvcaps
.dwFreeHwMemBytes
;
837 lpDSCaps
->dwMaxContigFreeHwMemBytes
= device
->drvcaps
.dwMaxContigFreeHwMemBytes
;
838 lpDSCaps
->dwUnlockTransferRateHwBuffers
= device
->drvcaps
.dwUnlockTransferRateHwBuffers
;
839 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= device
->drvcaps
.dwPlayCpuOverheadSwBuffers
;
844 BOOL
DSOUND_check_supported(IAudioClient
*client
, DWORD rate
,
845 DWORD depth
, WORD channels
)
847 WAVEFORMATEX fmt
, *junk
;
850 fmt
.wFormatTag
= WAVE_FORMAT_PCM
;
851 fmt
.nChannels
= channels
;
852 fmt
.nSamplesPerSec
= rate
;
853 fmt
.wBitsPerSample
= depth
;
854 fmt
.nBlockAlign
= (channels
* depth
) / 8;
855 fmt
.nAvgBytesPerSec
= rate
* fmt
.nBlockAlign
;
858 hr
= IAudioClient_IsFormatSupported(client
, AUDCLNT_SHAREMODE_SHARED
, &fmt
, &junk
);
865 UINT
DSOUND_create_timer(LPTIMECALLBACK cb
, DWORD_PTR user
)
867 UINT triggertime
= DS_TIME_DEL
, res
= DS_TIME_RES
, id
;
870 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
871 TRACE("Minimum timer resolution: %u, max timer: %u\n", time
.wPeriodMin
, time
.wPeriodMax
);
872 if (triggertime
< time
.wPeriodMin
)
873 triggertime
= time
.wPeriodMin
;
874 if (res
< time
.wPeriodMin
)
875 res
= time
.wPeriodMin
;
876 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
877 WARN("Could not set minimum resolution, don't expect sound\n");
878 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
881 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
882 id
= timeSetEvent(triggertime
, res
, cb
, user
, TIME_PERIODIC
);
884 ERR("Could not create timer, sound playback will not occur\n");
889 HRESULT
DirectSoundDevice_Initialize(DirectSoundDevice
** ppDevice
, LPCGUID lpcGUID
)
893 DirectSoundDevice
*device
;
896 TRACE("(%p,%s)\n",ppDevice
,debugstr_guid(lpcGUID
));
898 if (*ppDevice
!= NULL
) {
899 WARN("already initialized\n");
900 return DSERR_ALREADYINITIALIZED
;
903 /* Default device? */
904 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
905 lpcGUID
= &DSDEVID_DefaultPlayback
;
907 if(IsEqualGUID(lpcGUID
, &DSDEVID_DefaultCapture
) ||
908 IsEqualGUID(lpcGUID
, &DSDEVID_DefaultVoiceCapture
))
909 return DSERR_NODRIVER
;
911 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
912 WARN("invalid parameter: lpcGUID\n");
913 return DSERR_INVALIDPARAM
;
916 hr
= get_mmdevice(eRender
, &devGUID
, &mmdevice
);
920 EnterCriticalSection(&DSOUND_renderers_lock
);
922 LIST_FOR_EACH_ENTRY(device
, &DSOUND_renderers
, DirectSoundDevice
, entry
){
923 if(IsEqualGUID(&device
->guid
, &devGUID
)){
924 IMMDevice_Release(mmdevice
);
925 DirectSoundDevice_AddRef(device
);
927 LeaveCriticalSection(&DSOUND_renderers_lock
);
932 hr
= DirectSoundDevice_Create(&device
);
934 WARN("DirectSoundDevice_Create failed\n");
935 IMMDevice_Release(mmdevice
);
936 LeaveCriticalSection(&DSOUND_renderers_lock
);
940 device
->mmdevice
= mmdevice
;
941 device
->guid
= devGUID
;
943 hr
= DSOUND_ReopenDevice(device
, FALSE
);
946 HeapFree(GetProcessHeap(), 0, device
);
947 LeaveCriticalSection(&DSOUND_renderers_lock
);
948 IMMDevice_Release(mmdevice
);
949 WARN("DSOUND_ReopenDevice failed: %08x\n", hr
);
953 ZeroMemory(&device
->drvcaps
, sizeof(device
->drvcaps
));
955 if(DSOUND_check_supported(device
->client
, 11025, 8, 1) ||
956 DSOUND_check_supported(device
->client
, 22050, 8, 1) ||
957 DSOUND_check_supported(device
->client
, 44100, 8, 1) ||
958 DSOUND_check_supported(device
->client
, 48000, 8, 1) ||
959 DSOUND_check_supported(device
->client
, 96000, 8, 1))
960 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYMONO
;
962 if(DSOUND_check_supported(device
->client
, 11025, 16, 1) ||
963 DSOUND_check_supported(device
->client
, 22050, 16, 1) ||
964 DSOUND_check_supported(device
->client
, 44100, 16, 1) ||
965 DSOUND_check_supported(device
->client
, 48000, 16, 1) ||
966 DSOUND_check_supported(device
->client
, 96000, 16, 1))
967 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYMONO
;
969 if(DSOUND_check_supported(device
->client
, 11025, 8, 2) ||
970 DSOUND_check_supported(device
->client
, 22050, 8, 2) ||
971 DSOUND_check_supported(device
->client
, 44100, 8, 2) ||
972 DSOUND_check_supported(device
->client
, 48000, 8, 2) ||
973 DSOUND_check_supported(device
->client
, 96000, 8, 2))
974 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
| DSCAPS_PRIMARYSTEREO
;
976 if(DSOUND_check_supported(device
->client
, 11025, 16, 2) ||
977 DSOUND_check_supported(device
->client
, 22050, 16, 2) ||
978 DSOUND_check_supported(device
->client
, 44100, 16, 2) ||
979 DSOUND_check_supported(device
->client
, 48000, 16, 2) ||
980 DSOUND_check_supported(device
->client
, 96000, 16, 2))
981 device
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
| DSCAPS_PRIMARYSTEREO
;
983 /* the dsound mixer supports all of the following */
984 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARY8BIT
| DSCAPS_SECONDARY16BIT
;
985 device
->drvcaps
.dwFlags
|= DSCAPS_SECONDARYMONO
| DSCAPS_SECONDARYSTEREO
;
986 device
->drvcaps
.dwFlags
|= DSCAPS_CONTINUOUSRATE
;
988 device
->drvcaps
.dwPrimaryBuffers
= 1;
989 device
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
990 device
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
991 device
->drvcaps
.dwMaxHwMixingAllBuffers
= 1;
992 device
->drvcaps
.dwMaxHwMixingStaticBuffers
= 1;
993 device
->drvcaps
.dwMaxHwMixingStreamingBuffers
= 1;
995 ZeroMemory(&device
->volpan
, sizeof(device
->volpan
));
997 hr
= DSOUND_PrimaryCreate(device
);
999 device
->timerID
= DSOUND_create_timer(DSOUND_timer
, (DWORD_PTR
)device
);
1001 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr
);
1004 list_add_tail(&DSOUND_renderers
, &device
->entry
);
1006 LeaveCriticalSection(&DSOUND_renderers_lock
);
1011 HRESULT
DirectSoundDevice_CreateSoundBuffer(
1012 DirectSoundDevice
* device
,
1013 LPCDSBUFFERDESC dsbd
,
1014 LPLPDIRECTSOUNDBUFFER ppdsb
,
1018 HRESULT hres
= DS_OK
;
1019 TRACE("(%p,%p,%p,%p)\n",device
,dsbd
,ppdsb
,lpunk
);
1021 if (device
== NULL
) {
1022 WARN("not initialized\n");
1023 return DSERR_UNINITIALIZED
;
1027 WARN("invalid parameter: dsbd == NULL\n");
1028 return DSERR_INVALIDPARAM
;
1031 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) &&
1032 dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
1033 WARN("invalid parameter: dsbd\n");
1034 return DSERR_INVALIDPARAM
;
1037 if (ppdsb
== NULL
) {
1038 WARN("invalid parameter: ppdsb == NULL\n");
1039 return DSERR_INVALIDPARAM
;
1043 if (TRACE_ON(dsound
)) {
1044 TRACE("(structsize=%d)\n",dsbd
->dwSize
);
1045 TRACE("(flags=0x%08x:\n",dsbd
->dwFlags
);
1046 _dump_DSBCAPS(dsbd
->dwFlags
);
1048 TRACE("(bufferbytes=%d)\n",dsbd
->dwBufferBytes
);
1049 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
1052 if (dsbd
->dwFlags
& DSBCAPS_LOCHARDWARE
&&
1053 !(dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
)) {
1054 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1058 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
1059 if (dsbd
->lpwfxFormat
!= NULL
) {
1060 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1061 "primary buffer\n");
1062 return DSERR_INVALIDPARAM
;
1065 if (device
->primary
) {
1066 WARN("Primary Buffer already created\n");
1067 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(device
->primary
));
1068 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(device
->primary
);
1070 hres
= primarybuffer_create(device
, &device
->primary
, dsbd
);
1071 if (device
->primary
) {
1072 *ppdsb
= (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
;
1073 device
->primary
->dsbd
.dwFlags
&= ~(DSBCAPS_LOCHARDWARE
| DSBCAPS_LOCSOFTWARE
);
1074 device
->primary
->dsbd
.dwFlags
|= DSBCAPS_LOCSOFTWARE
;
1076 WARN("primarybuffer_create() failed\n");
1079 IDirectSoundBufferImpl
* dsb
;
1080 WAVEFORMATEXTENSIBLE
*pwfxe
;
1082 if (dsbd
->lpwfxFormat
== NULL
) {
1083 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1084 "secondary buffer\n");
1085 return DSERR_INVALIDPARAM
;
1087 pwfxe
= (WAVEFORMATEXTENSIBLE
*)dsbd
->lpwfxFormat
;
1089 if (pwfxe
->Format
.wBitsPerSample
!= 16 && pwfxe
->Format
.wBitsPerSample
!= 8 && pwfxe
->Format
.wFormatTag
!= WAVE_FORMAT_EXTENSIBLE
)
1091 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd
->lpwfxFormat
->wBitsPerSample
);
1092 return DSERR_CONTROLUNAVAIL
;
1094 if (pwfxe
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
1096 /* check if cbSize is at least 22 bytes */
1097 if (pwfxe
->Format
.cbSize
< (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)))
1099 WARN("Too small a cbSize %u\n", pwfxe
->Format
.cbSize
);
1100 return DSERR_INVALIDPARAM
;
1103 /* cbSize should be 22 bytes, with one possible exception */
1104 if (pwfxe
->Format
.cbSize
> (sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
)) &&
1105 !((IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
) || IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) &&
1106 pwfxe
->Format
.cbSize
== sizeof(WAVEFORMATEXTENSIBLE
)))
1108 WARN("Too big a cbSize %u\n", pwfxe
->Format
.cbSize
);
1109 return DSERR_CONTROLUNAVAIL
;
1112 if ((!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)) && (!IsEqualGUID(&pwfxe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)))
1114 if (!IsEqualGUID(&pwfxe
->SubFormat
, &GUID_NULL
))
1115 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe
->SubFormat
));
1116 return DSERR_INVALIDPARAM
;
1118 if (pwfxe
->Samples
.wValidBitsPerSample
> dsbd
->lpwfxFormat
->wBitsPerSample
)
1120 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe
->Samples
.wValidBitsPerSample
, pwfxe
->Format
.wBitsPerSample
);
1121 return DSERR_INVALIDPARAM
;
1123 if (pwfxe
->Samples
.wValidBitsPerSample
&& pwfxe
->Samples
.wValidBitsPerSample
< dsbd
->lpwfxFormat
->wBitsPerSample
)
1125 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe
->Samples
.wValidBitsPerSample
, dsbd
->lpwfxFormat
->wBitsPerSample
);
1126 return DSERR_CONTROLUNAVAIL
;
1130 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1131 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1132 dsbd
->lpwfxFormat
->wFormatTag
, dsbd
->lpwfxFormat
->nChannels
,
1133 dsbd
->lpwfxFormat
->nSamplesPerSec
,
1134 dsbd
->lpwfxFormat
->nAvgBytesPerSec
,
1135 dsbd
->lpwfxFormat
->nBlockAlign
,
1136 dsbd
->lpwfxFormat
->wBitsPerSample
, dsbd
->lpwfxFormat
->cbSize
);
1138 if (from8
&& (dsbd
->dwFlags
& DSBCAPS_CTRL3D
) && (dsbd
->lpwfxFormat
->nChannels
!= 1)) {
1139 WARN("invalid parameter: 3D buffer format must be mono\n");
1140 return DSERR_INVALIDPARAM
;
1143 hres
= IDirectSoundBufferImpl_Create(device
, &dsb
, dsbd
);
1145 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1147 WARN("IDirectSoundBufferImpl_Create failed\n");
1153 HRESULT
DirectSoundDevice_DuplicateSoundBuffer(
1154 DirectSoundDevice
* device
,
1155 LPDIRECTSOUNDBUFFER psb
,
1156 LPLPDIRECTSOUNDBUFFER ppdsb
)
1158 HRESULT hres
= DS_OK
;
1159 IDirectSoundBufferImpl
* dsb
;
1160 TRACE("(%p,%p,%p)\n",device
,psb
,ppdsb
);
1162 if (device
== NULL
) {
1163 WARN("not initialized\n");
1164 return DSERR_UNINITIALIZED
;
1168 WARN("invalid parameter: psb == NULL\n");
1169 return DSERR_INVALIDPARAM
;
1172 if (ppdsb
== NULL
) {
1173 WARN("invalid parameter: ppdsb == NULL\n");
1174 return DSERR_INVALIDPARAM
;
1177 /* make sure we have a secondary buffer */
1178 if (psb
== (IDirectSoundBuffer
*)&device
->primary
->IDirectSoundBuffer8_iface
) {
1179 WARN("trying to duplicate primary buffer\n");
1181 return DSERR_INVALIDCALL
;
1184 /* duplicate the actual buffer implementation */
1185 hres
= IDirectSoundBufferImpl_Duplicate(device
, &dsb
, (IDirectSoundBufferImpl
*)psb
);
1187 *ppdsb
= (IDirectSoundBuffer
*)&dsb
->IDirectSoundBuffer8_iface
;
1189 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1194 HRESULT
DirectSoundDevice_SetCooperativeLevel(
1195 DirectSoundDevice
* device
,
1199 TRACE("(%p,%p,%s)\n",device
,hwnd
,dumpCooperativeLevel(level
));
1201 if (device
== NULL
) {
1202 WARN("not initialized\n");
1203 return DSERR_UNINITIALIZED
;
1206 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
1207 WARN("level=%s not fully supported\n",
1208 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1211 device
->priolevel
= level
;
1215 HRESULT
DirectSoundDevice_Compact(
1216 DirectSoundDevice
* device
)
1218 TRACE("(%p)\n", device
);
1220 if (device
== NULL
) {
1221 WARN("not initialized\n");
1222 return DSERR_UNINITIALIZED
;
1225 if (device
->priolevel
< DSSCL_PRIORITY
) {
1226 WARN("incorrect priority level\n");
1227 return DSERR_PRIOLEVELNEEDED
;
1233 HRESULT
DirectSoundDevice_GetSpeakerConfig(
1234 DirectSoundDevice
* device
,
1235 LPDWORD lpdwSpeakerConfig
)
1237 TRACE("(%p, %p)\n", device
, lpdwSpeakerConfig
);
1239 if (device
== NULL
) {
1240 WARN("not initialized\n");
1241 return DSERR_UNINITIALIZED
;
1244 if (lpdwSpeakerConfig
== NULL
) {
1245 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1246 return DSERR_INVALIDPARAM
;
1249 WARN("not fully functional\n");
1250 *lpdwSpeakerConfig
= device
->speaker_config
;
1254 HRESULT
DirectSoundDevice_SetSpeakerConfig(
1255 DirectSoundDevice
* device
,
1258 TRACE("(%p,0x%08x)\n",device
,config
);
1260 if (device
== NULL
) {
1261 WARN("not initialized\n");
1262 return DSERR_UNINITIALIZED
;
1265 device
->speaker_config
= config
;
1266 WARN("not fully functional\n");
1270 HRESULT
DirectSoundDevice_VerifyCertification(
1271 DirectSoundDevice
* device
,
1272 LPDWORD pdwCertified
)
1274 TRACE("(%p, %p)\n",device
,pdwCertified
);
1276 if (device
== NULL
) {
1277 WARN("not initialized\n");
1278 return DSERR_UNINITIALIZED
;
1281 if (device
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
1282 *pdwCertified
= DS_CERTIFIED
;
1284 *pdwCertified
= DS_UNCERTIFIED
;
1290 * Add secondary buffer to buffer list.
1291 * Gets exclusive access to buffer for writing.
1293 HRESULT
DirectSoundDevice_AddBuffer(
1294 DirectSoundDevice
* device
,
1295 IDirectSoundBufferImpl
* pDSB
)
1297 IDirectSoundBufferImpl
**newbuffers
;
1300 TRACE("(%p, %p)\n", device
, pDSB
);
1302 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1304 if (device
->buffers
)
1305 newbuffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1307 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
*)*(device
->nrofbuffers
+1));
1310 device
->buffers
= newbuffers
;
1311 device
->buffers
[device
->nrofbuffers
] = pDSB
;
1312 device
->nrofbuffers
++;
1313 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1315 ERR("out of memory for buffer list! Current buffer count is %d\n", device
->nrofbuffers
);
1316 hr
= DSERR_OUTOFMEMORY
;
1319 RtlReleaseResource(&(device
->buffer_list_lock
));
1325 * Remove secondary buffer from buffer list.
1326 * Gets exclusive access to buffer for writing.
1328 HRESULT
DirectSoundDevice_RemoveBuffer(
1329 DirectSoundDevice
* device
,
1330 IDirectSoundBufferImpl
* pDSB
)
1335 TRACE("(%p, %p)\n", device
, pDSB
);
1337 RtlAcquireResourceExclusive(&(device
->buffer_list_lock
), TRUE
);
1339 for (i
= 0; i
< device
->nrofbuffers
; i
++)
1340 if (device
->buffers
[i
] == pDSB
)
1343 if (i
< device
->nrofbuffers
) {
1344 /* Put the last buffer of the list in the (now empty) position */
1345 device
->buffers
[i
] = device
->buffers
[device
->nrofbuffers
- 1];
1346 device
->nrofbuffers
--;
1347 device
->buffers
= HeapReAlloc(GetProcessHeap(),0,device
->buffers
,sizeof(LPDIRECTSOUNDBUFFER8
)*device
->nrofbuffers
);
1348 TRACE("buffer count is now %d\n", device
->nrofbuffers
);
1351 if (device
->nrofbuffers
== 0) {
1352 HeapFree(GetProcessHeap(),0,device
->buffers
);
1353 device
->buffers
= NULL
;
1356 RtlReleaseResource(&(device
->buffer_list_lock
));