3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 * Copyright 2004 Robert Reif
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wine/port.h"
28 #include <sys/types.h>
29 #include <sys/fcntl.h>
36 #define NONAMELESSSTRUCT
37 #define NONAMELESSUNION
48 #include "wine/windef16.h"
49 #include "wine/winbase16.h"
50 #include "wine/debug.h"
53 #include "dsound_private.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
58 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(LPUNKNOWN iface
);
59 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface
);
60 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface
);
61 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface
);
62 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface
);
64 static const char * dumpCooperativeLevel(DWORD level
)
66 static char unknown
[32];
67 #define LE(x) case x: return #x
72 LE(DSSCL_WRITEPRIMARY
);
75 sprintf(unknown
, "Unknown(%08lx)", 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 DPRINTF("%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_CTRLDEFAULT
)
122 FE(DSBCAPS_STICKYFOCUS
)
123 FE(DSBCAPS_GLOBALFOCUS
)
124 FE(DSBCAPS_GETCURRENTPOSITION2
)
125 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
130 for (i
=0;i
<sizeof(flags
)/sizeof(flags
[0]);i
++)
131 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
)
132 DPRINTF("%s ",flags
[i
].name
);
135 /*******************************************************************************
136 * IDirectSoundImpl_DirectSound
138 static HRESULT WINAPI
IDirectSoundImpl_QueryInterface(
139 LPDIRECTSOUND8 iface
,
143 TRACE("(%p,%s,%p)\n",iface
,debugstr_guid(riid
),ppobj
);
144 FIXME("shouldn't be called directly\n");
145 return E_NOINTERFACE
;
148 static HRESULT WINAPI
DSOUND_QueryInterface(
149 LPDIRECTSOUND8 iface
,
153 ICOM_THIS(IDirectSoundImpl
,iface
);
154 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
157 WARN("invalid parameter\n");
161 if (IsEqualIID(riid
, &IID_IUnknown
)) {
162 if (!This
->pUnknown
) {
163 IDirectSound_IUnknown_Create(iface
, &This
->pUnknown
);
164 if (!This
->pUnknown
) {
165 WARN("IDirectSound_IUnknown_Create() failed\n");
167 return E_NOINTERFACE
;
170 IDirectSound_IUnknown_AddRef(This
->pUnknown
);
171 *ppobj
= This
->pUnknown
;
173 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
175 IDirectSound_IDirectSound_Create(iface
, &This
->pDS
);
177 WARN("IDirectSound_IDirectSound_Create() failed\n");
179 return E_NOINTERFACE
;
182 IDirectSound_IDirectSound_AddRef(This
->pDS
);
188 WARN("Unknown IID %s\n",debugstr_guid(riid
));
189 return E_NOINTERFACE
;
192 static HRESULT WINAPI
DSOUND_QueryInterface8(
193 LPDIRECTSOUND8 iface
,
197 ICOM_THIS(IDirectSoundImpl
,iface
);
198 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
201 WARN("invalid parameter\n");
205 if (IsEqualIID(riid
, &IID_IUnknown
)) {
206 if (!This
->pUnknown
) {
207 IDirectSound8_IUnknown_Create(iface
, &This
->pUnknown
);
208 if (!This
->pUnknown
) {
209 WARN("IDirectSound8_IUnknown_Create() failed\n");
211 return E_NOINTERFACE
;
214 IDirectSound8_IUnknown_AddRef(This
->pUnknown
);
215 *ppobj
= This
->pUnknown
;
217 } else if (IsEqualIID(riid
, &IID_IDirectSound
)) {
219 IDirectSound8_IDirectSound_Create(iface
, &This
->pDS
);
221 WARN("IDirectSound8_IDirectSound_Create() failed\n");
223 return E_NOINTERFACE
;
226 IDirectSound8_IDirectSound_AddRef(This
->pDS
);
229 } else if (IsEqualIID(riid
, &IID_IDirectSound8
)) {
231 IDirectSound8_IDirectSound8_Create(iface
, &This
->pDS8
);
233 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
235 return E_NOINTERFACE
;
238 IDirectSound8_IDirectSound8_AddRef(This
->pDS8
);
244 WARN("Unknown IID %s\n",debugstr_guid(riid
));
245 return E_NOINTERFACE
;
248 static ULONG WINAPI
IDirectSoundImpl_AddRef(
249 LPDIRECTSOUND8 iface
)
251 ICOM_THIS(IDirectSoundImpl
,iface
);
252 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
254 return InterlockedIncrement(&This
->ref
);
257 static ULONG WINAPI
IDirectSoundImpl_Release(
258 LPDIRECTSOUND8 iface
)
260 ICOM_THIS(IDirectSoundImpl
,iface
);
262 TRACE("(%p) ref was %ld, thread is %04lx\n",
263 This
, This
->ref
, GetCurrentThreadId());
265 ref
= InterlockedDecrement(&This
->ref
);
270 timeKillEvent(This
->timerID
);
271 timeEndPeriod(DS_TIME_RES
);
272 /* wait for timer to expire */
273 Sleep(DS_TIME_RES
+1);
275 /* The sleep above should have allowed the timer process to expire
276 * but try to grab the lock just in case. Can't hold lock because
277 * IDirectSoundBufferImpl_Destroy also grabs the lock */
278 RtlAcquireResourceShared(&(This
->lock
), TRUE
);
279 RtlReleaseResource(&(This
->lock
));
281 /* It is allowed to release this object even when buffers are playing */
283 WARN("%d secondary buffers not released\n", This
->nrofbuffers
);
284 for( i
=0;i
<This
->nrofbuffers
;i
++)
285 IDirectSoundBufferImpl_Destroy(This
->buffers
[i
]);
289 WARN("primary buffer not released\n");
290 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8
)This
->primary
);
293 hres
= DSOUND_PrimaryDestroy(This
);
295 WARN("DSOUND_PrimaryDestroy failed\n");
298 IDsDriver_Close(This
->driver
);
300 if (This
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
301 waveOutClose(This
->hwo
);
304 IDsDriver_Release(This
->driver
);
306 RtlDeleteResource(&This
->lock
);
307 DeleteCriticalSection(&This
->mixlock
);
308 HeapFree(GetProcessHeap(),0,This
);
310 TRACE("(%p) released\n",This
);
316 static HRESULT WINAPI
IDirectSoundImpl_CreateSoundBuffer(
317 LPDIRECTSOUND8 iface
,
318 LPCDSBUFFERDESC dsbd
,
319 LPLPDIRECTSOUNDBUFFER ppdsb
,
322 ICOM_THIS(IDirectSoundImpl
,iface
);
324 HRESULT hres
= DS_OK
;
325 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
328 WARN("invalid parameter: This == NULL\n");
329 return DSERR_INVALIDPARAM
;
332 if (This
->initialized
== FALSE
) {
333 WARN("not initialized\n");
334 return DSERR_UNINITIALIZED
;
338 WARN("invalid parameter: dsbd == NULL\n");
339 return DSERR_INVALIDPARAM
;
342 if (dsbd
->dwSize
!= sizeof(DSBUFFERDESC
) && dsbd
->dwSize
!= sizeof(DSBUFFERDESC1
)) {
343 WARN("invalid parameter: dsbd\n");
344 return DSERR_INVALIDPARAM
;
348 WARN("invalid parameter: ppdsb == NULL\n");
349 return DSERR_INVALIDPARAM
;
352 if (TRACE_ON(dsound
)) {
353 TRACE("(structsize=%ld)\n",dsbd
->dwSize
);
354 TRACE("(flags=0x%08lx:\n",dsbd
->dwFlags
);
355 _dump_DSBCAPS(dsbd
->dwFlags
);
357 TRACE("(bufferbytes=%ld)\n",dsbd
->dwBufferBytes
);
358 TRACE("(lpwfxFormat=%p)\n",dsbd
->lpwfxFormat
);
361 wfex
= dsbd
->lpwfxFormat
;
364 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
365 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
366 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
367 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
368 wfex
->wBitsPerSample
, wfex
->cbSize
);
370 if (dsbd
->dwFlags
& DSBCAPS_PRIMARYBUFFER
) {
372 WARN("Primary Buffer already created\n");
373 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->primary
));
374 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->primary
);
377 hres
= PrimaryBufferImpl_Create(This
, (PrimaryBufferImpl
**)&(This
->primary
), &(This
->dsbd
));
379 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)(This
->primary
));
380 *ppdsb
= (LPDIRECTSOUNDBUFFER
)(This
->primary
);
382 WARN("PrimaryBufferImpl_Create failed\n");
385 IDirectSoundBufferImpl
* dsb
;
386 hres
= IDirectSoundBufferImpl_Create(This
, (IDirectSoundBufferImpl
**)&dsb
, dsbd
);
388 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
390 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
391 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER
)*ppdsb
);
393 WARN("SecondaryBufferImpl_Create failed\n");
395 WARN("IDirectSoundBufferImpl_Create failed\n");
401 static HRESULT WINAPI
IDirectSoundImpl_GetCaps(
402 LPDIRECTSOUND8 iface
,
405 ICOM_THIS(IDirectSoundImpl
,iface
);
406 TRACE("(%p,%p)\n",This
,lpDSCaps
);
409 WARN("invalid parameter: This == NULL\n");
410 return DSERR_INVALIDPARAM
;
413 if (This
->initialized
== FALSE
) {
414 WARN("not initialized\n");
415 return DSERR_UNINITIALIZED
;
418 if (lpDSCaps
== NULL
) {
419 WARN("invalid parameter: lpDSCaps = NULL\n");
420 return DSERR_INVALIDPARAM
;
423 /* check if there is enough room */
424 if (lpDSCaps
->dwSize
< sizeof(*lpDSCaps
)) {
425 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
426 lpDSCaps
->dwSize
, sizeof(*lpDSCaps
));
427 return DSERR_INVALIDPARAM
;
430 lpDSCaps
->dwFlags
= This
->drvcaps
.dwFlags
;
431 if (TRACE_ON(dsound
)) {
432 TRACE("(flags=0x%08lx:\n",lpDSCaps
->dwFlags
);
433 _dump_DSCAPS(lpDSCaps
->dwFlags
);
436 lpDSCaps
->dwMinSecondarySampleRate
= This
->drvcaps
.dwMinSecondarySampleRate
;
437 lpDSCaps
->dwMaxSecondarySampleRate
= This
->drvcaps
.dwMaxSecondarySampleRate
;
438 lpDSCaps
->dwPrimaryBuffers
= This
->drvcaps
.dwPrimaryBuffers
;
439 lpDSCaps
->dwMaxHwMixingAllBuffers
= This
->drvcaps
.dwMaxHwMixingAllBuffers
;
440 lpDSCaps
->dwMaxHwMixingStaticBuffers
= This
->drvcaps
.dwMaxHwMixingStaticBuffers
;
441 lpDSCaps
->dwMaxHwMixingStreamingBuffers
= This
->drvcaps
.dwMaxHwMixingStreamingBuffers
;
442 lpDSCaps
->dwFreeHwMixingAllBuffers
= This
->drvcaps
.dwFreeHwMixingAllBuffers
;
443 lpDSCaps
->dwFreeHwMixingStaticBuffers
= This
->drvcaps
.dwFreeHwMixingStaticBuffers
;
444 lpDSCaps
->dwFreeHwMixingStreamingBuffers
= This
->drvcaps
.dwFreeHwMixingStreamingBuffers
;
445 lpDSCaps
->dwMaxHw3DAllBuffers
= This
->drvcaps
.dwMaxHw3DAllBuffers
;
446 lpDSCaps
->dwMaxHw3DStaticBuffers
= This
->drvcaps
.dwMaxHw3DStaticBuffers
;
447 lpDSCaps
->dwMaxHw3DStreamingBuffers
= This
->drvcaps
.dwMaxHw3DStreamingBuffers
;
448 lpDSCaps
->dwFreeHw3DAllBuffers
= This
->drvcaps
.dwFreeHw3DAllBuffers
;
449 lpDSCaps
->dwFreeHw3DStaticBuffers
= This
->drvcaps
.dwFreeHw3DStaticBuffers
;
450 lpDSCaps
->dwFreeHw3DStreamingBuffers
= This
->drvcaps
.dwFreeHw3DStreamingBuffers
;
451 lpDSCaps
->dwTotalHwMemBytes
= This
->drvcaps
.dwTotalHwMemBytes
;
452 lpDSCaps
->dwFreeHwMemBytes
= This
->drvcaps
.dwFreeHwMemBytes
;
453 lpDSCaps
->dwMaxContigFreeHwMemBytes
= This
->drvcaps
.dwMaxContigFreeHwMemBytes
;
455 /* driver doesn't have these */
456 lpDSCaps
->dwUnlockTransferRateHwBuffers
= 4096; /* But we have none... */
457 lpDSCaps
->dwPlayCpuOverheadSwBuffers
= 1; /* 1% */
462 static HRESULT WINAPI
IDirectSoundImpl_DuplicateSoundBuffer(
463 LPDIRECTSOUND8 iface
,
464 LPDIRECTSOUNDBUFFER psb
,
465 LPLPDIRECTSOUNDBUFFER ppdsb
)
467 IDirectSoundBufferImpl
* pdsb
;
468 IDirectSoundBufferImpl
* dsb
;
469 HRESULT hres
= DS_OK
;
471 ICOM_THIS(IDirectSoundImpl
,iface
);
473 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
476 WARN("invalid parameter: This == NULL\n");
477 return DSERR_INVALIDPARAM
;
480 if (This
->initialized
== FALSE
) {
481 WARN("not initialized\n");
482 return DSERR_UNINITIALIZED
;
486 WARN("invalid parameter: psb == NULL\n");
487 return DSERR_INVALIDPARAM
;
491 WARN("invalid parameter: ppdsb == NULL\n");
492 return DSERR_INVALIDPARAM
;
495 /* FIXME: hack to make sure we have a secondary buffer */
496 if ((DWORD
)((SecondaryBufferImpl
*)psb
)->dsb
== (DWORD
)This
) {
497 WARN("trying to duplicate primary buffer\n");
499 return DSERR_INVALIDCALL
;
502 pdsb
= ((SecondaryBufferImpl
*)psb
)->dsb
;
504 dsb
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(*dsb
));
507 WARN("out of memory\n");
509 return DSERR_OUTOFMEMORY
;
512 memcpy(dsb
, pdsb
, sizeof(IDirectSoundBufferImpl
));
515 TRACE("duplicating hardware buffer\n");
517 hres
= IDsDriver_DuplicateSoundBuffer(This
->driver
, pdsb
->hwbuf
, (LPVOID
*)&dsb
->hwbuf
);
519 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
521 /* allocate buffer */
522 if (This
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
523 dsb
->buffer
= HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb
->buffer
)));
524 if (dsb
->buffer
== NULL
) {
525 WARN("out of memory\n");
526 HeapFree(GetProcessHeap(),0,dsb
);
528 return DSERR_OUTOFMEMORY
;
531 dsb
->buffer
->memory
= HeapAlloc(GetProcessHeap(),0,dsb
->buflen
);
532 if (dsb
->buffer
->memory
== NULL
) {
533 WARN("out of memory\n");
534 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
535 HeapFree(GetProcessHeap(),0,dsb
);
537 return DSERR_OUTOFMEMORY
;
539 dsb
->buffer
->ref
= 1;
541 /* FIXME: copy buffer ? */
550 dsb
->state
= STATE_STOPPED
;
555 dsb
->iks
= NULL
; /* FIXME? */
558 /* variable sized struct so calculate size based on format */
559 size
= sizeof(WAVEFORMATEX
) + pdsb
->pwfx
->cbSize
;
561 dsb
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
);
562 if (dsb
->pwfx
== NULL
) {
563 WARN("out of memory\n");
564 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
565 HeapFree(GetProcessHeap(),0,dsb
);
567 return DSERR_OUTOFMEMORY
;
570 memcpy(dsb
->pwfx
, pdsb
->pwfx
, size
);
572 InitializeCriticalSection(&(dsb
->lock
));
573 dsb
->lock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUNDBUFFER_lock";
574 /* register buffer */
575 RtlAcquireResourceExclusive(&(This
->lock
), TRUE
);
577 IDirectSoundBufferImpl
**newbuffers
;
579 newbuffers
= HeapReAlloc(GetProcessHeap(),0,This
->buffers
,sizeof(IDirectSoundBufferImpl
**)*(This
->nrofbuffers
+1));
581 newbuffers
= HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl
**)*(This
->nrofbuffers
+1));
584 This
->buffers
= newbuffers
;
585 This
->buffers
[This
->nrofbuffers
] = dsb
;
587 TRACE("buffer count is now %d\n", This
->nrofbuffers
);
589 ERR("out of memory for buffer list! Current buffer count is %d\n", This
->nrofbuffers
);
590 IDirectSoundBuffer8_Release(psb
);
591 DeleteCriticalSection(&(dsb
->lock
));
592 RtlReleaseResource(&(This
->lock
));
593 HeapFree(GetProcessHeap(),0,dsb
->buffer
);
594 HeapFree(GetProcessHeap(),0,dsb
->pwfx
);
595 HeapFree(GetProcessHeap(),0,dsb
);
597 return DSERR_OUTOFMEMORY
;
600 RtlReleaseResource(&(This
->lock
));
601 hres
= SecondaryBufferImpl_Create(dsb
, (SecondaryBufferImpl
**)ppdsb
);
603 dsb
->dsb
= (SecondaryBufferImpl
*)*ppdsb
;
604 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8
)*ppdsb
);
606 WARN("SecondaryBufferImpl_Create failed\n");
611 static HRESULT WINAPI
IDirectSoundImpl_SetCooperativeLevel(
612 LPDIRECTSOUND8 iface
,
616 ICOM_THIS(IDirectSoundImpl
,iface
);
617 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
619 if (level
==DSSCL_PRIORITY
|| level
==DSSCL_EXCLUSIVE
) {
620 FIXME("level=%s not fully supported\n",
621 level
==DSSCL_PRIORITY
? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
623 This
->priolevel
= level
;
627 static HRESULT WINAPI
IDirectSoundImpl_Compact(
628 LPDIRECTSOUND8 iface
)
630 ICOM_THIS(IDirectSoundImpl
,iface
);
631 TRACE("(%p)\n",This
);
633 if (This
->initialized
== FALSE
) {
634 WARN("not initialized\n");
635 return DSERR_UNINITIALIZED
;
638 if (This
->priolevel
!= DSSCL_PRIORITY
) {
639 WARN("incorrect priority level\n");
640 return DSERR_PRIOLEVELNEEDED
;
646 static HRESULT WINAPI
IDirectSoundImpl_GetSpeakerConfig(
647 LPDIRECTSOUND8 iface
,
648 LPDWORD lpdwSpeakerConfig
)
650 ICOM_THIS(IDirectSoundImpl
,iface
);
651 TRACE("(%p, %p)\n",This
,lpdwSpeakerConfig
);
653 if (This
->initialized
== FALSE
) {
654 WARN("not initialized\n");
655 return DSERR_UNINITIALIZED
;
658 if (lpdwSpeakerConfig
== NULL
) {
659 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
660 return DSERR_INVALIDPARAM
;
663 WARN("not fully functional\n");
664 *lpdwSpeakerConfig
= This
->speaker_config
;
668 static HRESULT WINAPI
IDirectSoundImpl_SetSpeakerConfig(
669 LPDIRECTSOUND8 iface
,
672 ICOM_THIS(IDirectSoundImpl
,iface
);
673 TRACE("(%p,0x%08lx)\n",This
,config
);
675 if (This
->initialized
== FALSE
) {
676 WARN("not initialized\n");
677 return DSERR_UNINITIALIZED
;
680 This
->speaker_config
= config
;
681 WARN("not fully functional\n");
685 static HRESULT WINAPI
IDirectSoundImpl_Initialize(
686 LPDIRECTSOUND8 iface
,
689 ICOM_THIS(IDirectSoundImpl
,iface
);
690 TRACE("(%p,%s)\n",This
,debugstr_guid(lpcGuid
));
692 This
->initialized
= TRUE
;
697 static HRESULT WINAPI
IDirectSoundImpl_VerifyCertification(
698 LPDIRECTSOUND8 iface
,
699 LPDWORD pdwCertified
)
701 ICOM_THIS(IDirectSoundImpl
,iface
);
702 TRACE("(%p, %p)\n",This
,pdwCertified
);
704 if (This
->initialized
== FALSE
) {
705 WARN("not initialized\n");
706 return DSERR_UNINITIALIZED
;
709 if (This
->drvcaps
.dwFlags
& DSCAPS_CERTIFIED
)
710 *pdwCertified
= DS_CERTIFIED
;
712 *pdwCertified
= DS_UNCERTIFIED
;
716 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl
=
718 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
719 IDirectSoundImpl_QueryInterface
,
720 IDirectSoundImpl_AddRef
,
721 IDirectSoundImpl_Release
,
722 IDirectSoundImpl_CreateSoundBuffer
,
723 IDirectSoundImpl_GetCaps
,
724 IDirectSoundImpl_DuplicateSoundBuffer
,
725 IDirectSoundImpl_SetCooperativeLevel
,
726 IDirectSoundImpl_Compact
,
727 IDirectSoundImpl_GetSpeakerConfig
,
728 IDirectSoundImpl_SetSpeakerConfig
,
729 IDirectSoundImpl_Initialize
,
730 IDirectSoundImpl_VerifyCertification
733 HRESULT WINAPI
IDirectSoundImpl_Create(
735 LPDIRECTSOUND8
* ppDS
)
738 PIDSDRIVER drv
= NULL
;
739 IDirectSoundImpl
* pDS
;
741 BOOLEAN found
= FALSE
;
742 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID
),ppDS
);
744 /* Enumerate WINMM audio devices and find the one we want */
745 wodn
= waveOutGetNumDevs();
749 return DSERR_NODRIVER
;
752 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID
));
754 for (wod
=0; wod
<wodn
; wod
++) {
755 if (IsEqualGUID( lpcGUID
, &renderer_guids
[wod
])) {
761 if (found
== FALSE
) {
762 WARN("No device found matching given ID!\n");
764 return DSERR_NODRIVER
;
767 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
768 waveOutMessage((HWAVEOUT
)wod
, DRV_QUERYDSOUNDIFACE
, (DWORD
)&drv
, 0);
770 /* Disable the direct sound driver to force emulation if requested. */
771 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
774 /* Allocate memory */
775 pDS
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundImpl
));
777 WARN("out of memory\n");
779 return DSERR_OUTOFMEMORY
;
782 pDS
->lpVtbl
= &IDirectSoundImpl_Vtbl
;
786 pDS
->priolevel
= DSSCL_NORMAL
;
792 pDS
->state
= STATE_STOPPED
;
793 pDS
->nrofbuffers
= 0;
796 pDS
->speaker_config
= DSSPEAKER_STEREO
| (DSSPEAKER_GEOMETRY_NARROW
<< 16);
797 pDS
->initialized
= FALSE
;
799 /* 3D listener initial parameters */
800 pDS
->listener
= NULL
;
801 pDS
->ds3dl
.dwSize
= sizeof(DS3DLISTENER
);
802 pDS
->ds3dl
.vPosition
.x
= 0.0;
803 pDS
->ds3dl
.vPosition
.y
= 0.0;
804 pDS
->ds3dl
.vPosition
.z
= 0.0;
805 pDS
->ds3dl
.vVelocity
.x
= 0.0;
806 pDS
->ds3dl
.vVelocity
.y
= 0.0;
807 pDS
->ds3dl
.vVelocity
.z
= 0.0;
808 pDS
->ds3dl
.vOrientFront
.x
= 0.0;
809 pDS
->ds3dl
.vOrientFront
.y
= 0.0;
810 pDS
->ds3dl
.vOrientFront
.z
= 1.0;
811 pDS
->ds3dl
.vOrientTop
.x
= 0.0;
812 pDS
->ds3dl
.vOrientTop
.y
= 1.0;
813 pDS
->ds3dl
.vOrientTop
.z
= 0.0;
814 pDS
->ds3dl
.flDistanceFactor
= DS3D_DEFAULTDISTANCEFACTOR
;
815 pDS
->ds3dl
.flRolloffFactor
= DS3D_DEFAULTROLLOFFFACTOR
;
816 pDS
->ds3dl
.flDopplerFactor
= DS3D_DEFAULTDOPPLERFACTOR
;
818 pDS
->prebuf
= ds_snd_queue_max
;
819 pDS
->guid
= *lpcGUID
;
821 /* Get driver description */
823 err
= IDsDriver_GetDriverDesc(drv
,&(pDS
->drvdesc
));
825 WARN("IDsDriver_GetDriverDesc failed\n");
826 HeapFree(GetProcessHeap(),0,pDS
);
831 /* if no DirectSound interface available, use WINMM API instead */
832 pDS
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
| DSDDESC_DOMMSYSTEMSETFORMAT
;
835 pDS
->drvdesc
.dnDevNode
= wod
;
837 /* Set default wave format (may need it for waveOutOpen) */
838 pDS
->pwfx
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(WAVEFORMATEX
));
839 if (pDS
->pwfx
== NULL
) {
840 WARN("out of memory\n");
841 HeapFree(GetProcessHeap(),0,pDS
);
843 return DSERR_OUTOFMEMORY
;
846 pDS
->pwfx
->wFormatTag
= WAVE_FORMAT_PCM
;
847 /* We rely on the sound driver to return the actual sound format of
848 * the device if it does not support 22050x8x2 and is given the
849 * WAVE_DIRECTSOUND flag.
851 pDS
->pwfx
->nSamplesPerSec
= 22050;
852 pDS
->pwfx
->wBitsPerSample
= 8;
853 pDS
->pwfx
->nChannels
= 2;
854 pDS
->pwfx
->nBlockAlign
= pDS
->pwfx
->wBitsPerSample
* pDS
->pwfx
->nChannels
/ 8;
855 pDS
->pwfx
->nAvgBytesPerSec
= pDS
->pwfx
->nSamplesPerSec
* pDS
->pwfx
->nBlockAlign
;
856 pDS
->pwfx
->cbSize
= 0;
858 /* If the driver requests being opened through MMSYSTEM
859 * (which is recommended by the DDK), it is supposed to happen
860 * before the DirectSound interface is opened */
861 if (pDS
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
863 DWORD flags
= CALLBACK_FUNCTION
;
865 /* disable direct sound if requested */
866 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
867 flags
|= WAVE_DIRECTSOUND
;
869 err
= mmErr(waveOutOpen(&(pDS
->hwo
),
870 pDS
->drvdesc
.dnDevNode
, pDS
->pwfx
,
871 (DWORD
)DSOUND_callback
, (DWORD
)pDS
,
874 WARN("waveOutOpen failed\n");
875 HeapFree(GetProcessHeap(),0,pDS
);
882 err
= IDsDriver_Open(drv
);
884 WARN("IDsDriver_Open failed\n");
885 HeapFree(GetProcessHeap(),0,pDS
);
890 /* the driver is now open, so it's now allowed to call GetCaps */
891 err
= IDsDriver_GetCaps(drv
,&(pDS
->drvcaps
));
893 WARN("IDsDriver_GetCaps failed\n");
894 HeapFree(GetProcessHeap(),0,pDS
);
900 err
= mmErr(waveOutGetDevCapsA(pDS
->drvdesc
.dnDevNode
, &woc
, sizeof(woc
)));
902 WARN("waveOutGetDevCaps failed\n");
903 HeapFree(GetProcessHeap(),0,pDS
);
907 ZeroMemory(&pDS
->drvcaps
, sizeof(pDS
->drvcaps
));
908 if ((woc
.dwFormats
& WAVE_FORMAT_1M08
) ||
909 (woc
.dwFormats
& WAVE_FORMAT_2M08
) ||
910 (woc
.dwFormats
& WAVE_FORMAT_4M08
) ||
911 (woc
.dwFormats
& WAVE_FORMAT_48M08
) ||
912 (woc
.dwFormats
& WAVE_FORMAT_96M08
)) {
913 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
914 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
916 if ((woc
.dwFormats
& WAVE_FORMAT_1M16
) ||
917 (woc
.dwFormats
& WAVE_FORMAT_2M16
) ||
918 (woc
.dwFormats
& WAVE_FORMAT_4M16
) ||
919 (woc
.dwFormats
& WAVE_FORMAT_48M16
) ||
920 (woc
.dwFormats
& WAVE_FORMAT_96M16
)) {
921 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
922 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYMONO
;
924 if ((woc
.dwFormats
& WAVE_FORMAT_1S08
) ||
925 (woc
.dwFormats
& WAVE_FORMAT_2S08
) ||
926 (woc
.dwFormats
& WAVE_FORMAT_4S08
) ||
927 (woc
.dwFormats
& WAVE_FORMAT_48S08
) ||
928 (woc
.dwFormats
& WAVE_FORMAT_96S08
)) {
929 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY8BIT
;
930 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
932 if ((woc
.dwFormats
& WAVE_FORMAT_1S16
) ||
933 (woc
.dwFormats
& WAVE_FORMAT_2S16
) ||
934 (woc
.dwFormats
& WAVE_FORMAT_4S16
) ||
935 (woc
.dwFormats
& WAVE_FORMAT_48S16
) ||
936 (woc
.dwFormats
& WAVE_FORMAT_96S16
)) {
937 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARY16BIT
;
938 pDS
->drvcaps
.dwFlags
|= DSCAPS_PRIMARYSTEREO
;
941 pDS
->drvcaps
.dwFlags
|= DSCAPS_EMULDRIVER
;
942 pDS
->drvcaps
.dwMinSecondarySampleRate
= DSBFREQUENCY_MIN
;
943 pDS
->drvcaps
.dwMaxSecondarySampleRate
= DSBFREQUENCY_MAX
;
944 pDS
->drvcaps
.dwPrimaryBuffers
= 1;
947 InitializeCriticalSection(&(pDS
->mixlock
));
948 pDS
->mixlock
.DebugInfo
->Spare
[1] = (DWORD
)"DSOUND_mixlock";
949 RtlInitializeResource(&(pDS
->lock
));
951 *ppDS
= (LPDIRECTSOUND8
)pDS
;
955 /*******************************************************************************
956 * IDirectSound_IUnknown
958 static HRESULT WINAPI
IDirectSound_IUnknown_QueryInterface(
963 ICOM_THIS(IDirectSound_IUnknown
,iface
);
964 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
965 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
968 static ULONG WINAPI
IDirectSound_IUnknown_AddRef(
971 ICOM_THIS(IDirectSound_IUnknown
,iface
);
972 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
973 return InterlockedIncrement(&This
->ref
);
976 static ULONG WINAPI
IDirectSound_IUnknown_Release(
979 ICOM_THIS(IDirectSound_IUnknown
,iface
);
981 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
982 ulReturn
= InterlockedDecrement(&This
->ref
);
984 IDirectSoundImpl_Release(This
->pds
);
985 HeapFree(GetProcessHeap(),0,This
);
986 TRACE("(%p) released\n",This
);
991 static IUnknownVtbl DirectSound_Unknown_Vtbl
=
993 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
994 IDirectSound_IUnknown_QueryInterface
,
995 IDirectSound_IUnknown_AddRef
,
996 IDirectSound_IUnknown_Release
999 HRESULT WINAPI
IDirectSound_IUnknown_Create(
1003 IDirectSound_IUnknown
* pdsunk
;
1004 TRACE("(%p,%p)\n",pds
,ppunk
);
1006 if (ppunk
== NULL
) {
1007 ERR("invalid parameter: ppunk == NULL\n");
1008 return DSERR_INVALIDPARAM
;
1012 ERR("invalid parameter: pds == NULL\n");
1014 return DSERR_INVALIDPARAM
;
1017 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1018 if (pdsunk
== NULL
) {
1019 WARN("out of memory\n");
1021 return DSERR_OUTOFMEMORY
;
1024 pdsunk
->lpVtbl
= &DirectSound_Unknown_Vtbl
;
1028 IDirectSoundImpl_AddRef(pds
);
1029 *ppunk
= (LPUNKNOWN
)pdsunk
;
1034 /*******************************************************************************
1035 * IDirectSound_IDirectSound
1037 static HRESULT WINAPI
IDirectSound_IDirectSound_QueryInterface(
1038 LPDIRECTSOUND iface
,
1042 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1043 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1044 return DSOUND_QueryInterface(This
->pds
, riid
, ppobj
);
1047 static ULONG WINAPI
IDirectSound_IDirectSound_AddRef(
1048 LPDIRECTSOUND iface
)
1050 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1051 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1052 return InterlockedIncrement(&This
->ref
);
1055 static ULONG WINAPI
IDirectSound_IDirectSound_Release(
1056 LPDIRECTSOUND iface
)
1058 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1060 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1061 ulReturn
= InterlockedDecrement(&This
->ref
);
1062 if (ulReturn
== 0) {
1063 IDirectSoundImpl_Release(This
->pds
);
1064 HeapFree(GetProcessHeap(),0,This
);
1065 TRACE("(%p) released\n",This
);
1070 static HRESULT WINAPI
IDirectSound_IDirectSound_CreateSoundBuffer(
1071 LPDIRECTSOUND iface
,
1072 LPCDSBUFFERDESC dsbd
,
1073 LPLPDIRECTSOUNDBUFFER ppdsb
,
1076 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1077 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1078 return IDirectSoundImpl_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
);
1081 static HRESULT WINAPI
IDirectSound_IDirectSound_GetCaps(
1082 LPDIRECTSOUND iface
,
1085 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1086 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1087 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1090 static HRESULT WINAPI
IDirectSound_IDirectSound_DuplicateSoundBuffer(
1091 LPDIRECTSOUND iface
,
1092 LPDIRECTSOUNDBUFFER psb
,
1093 LPLPDIRECTSOUNDBUFFER ppdsb
)
1095 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1096 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1097 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1100 static HRESULT WINAPI
IDirectSound_IDirectSound_SetCooperativeLevel(
1101 LPDIRECTSOUND iface
,
1105 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1106 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1107 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1110 static HRESULT WINAPI
IDirectSound_IDirectSound_Compact(
1111 LPDIRECTSOUND iface
)
1113 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1114 TRACE("(%p)\n", This
);
1115 return IDirectSoundImpl_Compact(This
->pds
);
1118 static HRESULT WINAPI
IDirectSound_IDirectSound_GetSpeakerConfig(
1119 LPDIRECTSOUND iface
,
1120 LPDWORD lpdwSpeakerConfig
)
1122 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1123 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1124 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1127 static HRESULT WINAPI
IDirectSound_IDirectSound_SetSpeakerConfig(
1128 LPDIRECTSOUND iface
,
1131 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1132 TRACE("(%p,0x%08lx)\n",This
,config
);
1133 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1136 static HRESULT WINAPI
IDirectSound_IDirectSound_Initialize(
1137 LPDIRECTSOUND iface
,
1140 ICOM_THIS(IDirectSound_IDirectSound
,iface
);
1141 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1142 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1145 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl
=
1147 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1148 IDirectSound_IDirectSound_QueryInterface
,
1149 IDirectSound_IDirectSound_AddRef
,
1150 IDirectSound_IDirectSound_Release
,
1151 IDirectSound_IDirectSound_CreateSoundBuffer
,
1152 IDirectSound_IDirectSound_GetCaps
,
1153 IDirectSound_IDirectSound_DuplicateSoundBuffer
,
1154 IDirectSound_IDirectSound_SetCooperativeLevel
,
1155 IDirectSound_IDirectSound_Compact
,
1156 IDirectSound_IDirectSound_GetSpeakerConfig
,
1157 IDirectSound_IDirectSound_SetSpeakerConfig
,
1158 IDirectSound_IDirectSound_Initialize
1161 HRESULT WINAPI
IDirectSound_IDirectSound_Create(
1163 LPDIRECTSOUND
* ppds
)
1165 IDirectSound_IDirectSound
* pdsds
;
1166 TRACE("(%p,%p)\n",pds
,ppds
);
1169 ERR("invalid parameter: ppds == NULL\n");
1170 return DSERR_INVALIDPARAM
;
1174 ERR("invalid parameter: pds == NULL\n");
1176 return DSERR_INVALIDPARAM
;
1179 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1180 if (pdsds
== NULL
) {
1181 WARN("out of memory\n");
1183 return DSERR_OUTOFMEMORY
;
1186 pdsds
->lpVtbl
= &DirectSound_DirectSound_Vtbl
;
1190 IDirectSoundImpl_AddRef(pds
);
1191 *ppds
= (LPDIRECTSOUND
)pdsds
;
1196 /*******************************************************************************
1197 * IDirectSound8_IUnknown
1199 static HRESULT WINAPI
IDirectSound8_IUnknown_QueryInterface(
1204 ICOM_THIS(IDirectSound_IUnknown
,iface
);
1205 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1206 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1209 static ULONG WINAPI
IDirectSound8_IUnknown_AddRef(
1212 ICOM_THIS(IDirectSound_IUnknown
,iface
);
1213 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1214 return InterlockedIncrement(&This
->ref
);
1217 static ULONG WINAPI
IDirectSound8_IUnknown_Release(
1220 ICOM_THIS(IDirectSound_IUnknown
,iface
);
1222 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1223 ulReturn
= InterlockedDecrement(&This
->ref
);
1224 if (ulReturn
== 0) {
1225 IDirectSoundImpl_Release(This
->pds
);
1226 HeapFree(GetProcessHeap(),0,This
);
1227 TRACE("(%p) released\n",This
);
1232 static IUnknownVtbl DirectSound8_Unknown_Vtbl
=
1234 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1235 IDirectSound8_IUnknown_QueryInterface
,
1236 IDirectSound8_IUnknown_AddRef
,
1237 IDirectSound8_IUnknown_Release
1240 HRESULT WINAPI
IDirectSound8_IUnknown_Create(
1244 IDirectSound8_IUnknown
* pdsunk
;
1245 TRACE("(%p,%p)\n",pds
,ppunk
);
1247 if (ppunk
== NULL
) {
1248 ERR("invalid parameter: ppunk == NULL\n");
1249 return DSERR_INVALIDPARAM
;
1253 ERR("invalid parameter: pds == NULL\n");
1255 return DSERR_INVALIDPARAM
;
1258 pdsunk
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk
));
1259 if (pdsunk
== NULL
) {
1260 WARN("out of memory\n");
1262 return DSERR_OUTOFMEMORY
;
1265 pdsunk
->lpVtbl
= &DirectSound8_Unknown_Vtbl
;
1269 IDirectSoundImpl_AddRef(pds
);
1270 *ppunk
= (LPUNKNOWN
)pdsunk
;
1275 /*******************************************************************************
1276 * IDirectSound8_IDirectSound
1278 static HRESULT WINAPI
IDirectSound8_IDirectSound_QueryInterface(
1279 LPDIRECTSOUND iface
,
1283 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1284 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1285 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1288 static ULONG WINAPI
IDirectSound8_IDirectSound_AddRef(
1289 LPDIRECTSOUND iface
)
1291 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1292 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1293 return InterlockedIncrement(&This
->ref
);
1296 static ULONG WINAPI
IDirectSound8_IDirectSound_Release(
1297 LPDIRECTSOUND iface
)
1299 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1301 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1302 ulReturn
= InterlockedDecrement(&This
->ref
);
1303 if (ulReturn
== 0) {
1304 IDirectSoundImpl_Release(This
->pds
);
1305 HeapFree(GetProcessHeap(),0,This
);
1306 TRACE("(%p) released\n",This
);
1311 static HRESULT WINAPI
IDirectSound8_IDirectSound_CreateSoundBuffer(
1312 LPDIRECTSOUND iface
,
1313 LPCDSBUFFERDESC dsbd
,
1314 LPLPDIRECTSOUNDBUFFER ppdsb
,
1317 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1318 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1319 return IDirectSoundImpl_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
);
1322 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetCaps(
1323 LPDIRECTSOUND iface
,
1326 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1327 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1328 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1331 static HRESULT WINAPI
IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1332 LPDIRECTSOUND iface
,
1333 LPDIRECTSOUNDBUFFER psb
,
1334 LPLPDIRECTSOUNDBUFFER ppdsb
)
1336 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1337 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1338 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1341 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetCooperativeLevel(
1342 LPDIRECTSOUND iface
,
1346 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1347 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1348 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1351 static HRESULT WINAPI
IDirectSound8_IDirectSound_Compact(
1352 LPDIRECTSOUND iface
)
1354 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1355 TRACE("(%p)\n", This
);
1356 return IDirectSoundImpl_Compact(This
->pds
);
1359 static HRESULT WINAPI
IDirectSound8_IDirectSound_GetSpeakerConfig(
1360 LPDIRECTSOUND iface
,
1361 LPDWORD lpdwSpeakerConfig
)
1363 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1364 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1365 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1368 static HRESULT WINAPI
IDirectSound8_IDirectSound_SetSpeakerConfig(
1369 LPDIRECTSOUND iface
,
1372 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1373 TRACE("(%p,0x%08lx)\n",This
,config
);
1374 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1377 static HRESULT WINAPI
IDirectSound8_IDirectSound_Initialize(
1378 LPDIRECTSOUND iface
,
1381 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1382 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1383 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1386 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl
=
1388 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1389 IDirectSound8_IDirectSound_QueryInterface
,
1390 IDirectSound8_IDirectSound_AddRef
,
1391 IDirectSound8_IDirectSound_Release
,
1392 IDirectSound8_IDirectSound_CreateSoundBuffer
,
1393 IDirectSound8_IDirectSound_GetCaps
,
1394 IDirectSound8_IDirectSound_DuplicateSoundBuffer
,
1395 IDirectSound8_IDirectSound_SetCooperativeLevel
,
1396 IDirectSound8_IDirectSound_Compact
,
1397 IDirectSound8_IDirectSound_GetSpeakerConfig
,
1398 IDirectSound8_IDirectSound_SetSpeakerConfig
,
1399 IDirectSound8_IDirectSound_Initialize
1402 HRESULT WINAPI
IDirectSound8_IDirectSound_Create(
1404 LPDIRECTSOUND
* ppds
)
1406 IDirectSound8_IDirectSound
* pdsds
;
1407 TRACE("(%p,%p)\n",pds
,ppds
);
1410 ERR("invalid parameter: ppds == NULL\n");
1411 return DSERR_INVALIDPARAM
;
1415 ERR("invalid parameter: pds == NULL\n");
1417 return DSERR_INVALIDPARAM
;
1420 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1421 if (pdsds
== NULL
) {
1422 WARN("out of memory\n");
1424 return DSERR_OUTOFMEMORY
;
1427 pdsds
->lpVtbl
= &DirectSound8_DirectSound_Vtbl
;
1431 IDirectSoundImpl_AddRef(pds
);
1432 *ppds
= (LPDIRECTSOUND
)pdsds
;
1437 /*******************************************************************************
1438 * IDirectSound8_IDirectSound8
1440 static HRESULT WINAPI
IDirectSound8_IDirectSound8_QueryInterface(
1441 LPDIRECTSOUND8 iface
,
1445 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1446 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
1447 return DSOUND_QueryInterface8(This
->pds
, riid
, ppobj
);
1450 static ULONG WINAPI
IDirectSound8_IDirectSound8_AddRef(
1451 LPDIRECTSOUND8 iface
)
1453 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1454 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1455 return InterlockedIncrement(&This
->ref
);
1458 static ULONG WINAPI
IDirectSound8_IDirectSound8_Release(
1459 LPDIRECTSOUND8 iface
)
1461 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1463 TRACE("(%p) ref was %ld, thread is %04lx\n", This
, This
->ref
, GetCurrentThreadId());
1464 ulReturn
= InterlockedDecrement(&This
->ref
);
1465 if (ulReturn
== 0) {
1466 IDirectSoundImpl_Release(This
->pds
);
1467 HeapFree(GetProcessHeap(),0,This
);
1468 TRACE("(%p) released\n",This
);
1473 static HRESULT WINAPI
IDirectSound8_IDirectSound8_CreateSoundBuffer(
1474 LPDIRECTSOUND8 iface
,
1475 LPCDSBUFFERDESC dsbd
,
1476 LPLPDIRECTSOUNDBUFFER ppdsb
,
1479 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1480 TRACE("(%p,%p,%p,%p)\n",This
,dsbd
,ppdsb
,lpunk
);
1481 return IDirectSoundImpl_CreateSoundBuffer(This
->pds
,dsbd
,ppdsb
,lpunk
);
1484 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetCaps(
1485 LPDIRECTSOUND8 iface
,
1488 ICOM_THIS(IDirectSound8_IDirectSound
,iface
);
1489 TRACE("(%p,%p)\n",This
,lpDSCaps
);
1490 return IDirectSoundImpl_GetCaps(This
->pds
, lpDSCaps
);
1493 static HRESULT WINAPI
IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1494 LPDIRECTSOUND8 iface
,
1495 LPDIRECTSOUNDBUFFER psb
,
1496 LPLPDIRECTSOUNDBUFFER ppdsb
)
1498 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1499 TRACE("(%p,%p,%p)\n",This
,psb
,ppdsb
);
1500 return IDirectSoundImpl_DuplicateSoundBuffer(This
->pds
,psb
,ppdsb
);
1503 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetCooperativeLevel(
1504 LPDIRECTSOUND8 iface
,
1508 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1509 TRACE("(%p,%08lx,%s)\n",This
,(DWORD
)hwnd
,dumpCooperativeLevel(level
));
1510 return IDirectSoundImpl_SetCooperativeLevel(This
->pds
,hwnd
,level
);
1513 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Compact(
1514 LPDIRECTSOUND8 iface
)
1516 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1517 TRACE("(%p)\n", This
);
1518 return IDirectSoundImpl_Compact(This
->pds
);
1521 static HRESULT WINAPI
IDirectSound8_IDirectSound8_GetSpeakerConfig(
1522 LPDIRECTSOUND8 iface
,
1523 LPDWORD lpdwSpeakerConfig
)
1525 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1526 TRACE("(%p, %p)\n", This
, lpdwSpeakerConfig
);
1527 return IDirectSoundImpl_GetSpeakerConfig(This
->pds
,lpdwSpeakerConfig
);
1530 static HRESULT WINAPI
IDirectSound8_IDirectSound8_SetSpeakerConfig(
1531 LPDIRECTSOUND8 iface
,
1534 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1535 TRACE("(%p,0x%08lx)\n",This
,config
);
1536 return IDirectSoundImpl_SetSpeakerConfig(This
->pds
,config
);
1539 static HRESULT WINAPI
IDirectSound8_IDirectSound8_Initialize(
1540 LPDIRECTSOUND8 iface
,
1543 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1544 TRACE("(%p, %s)\n", This
, debugstr_guid(lpcGuid
));
1545 return IDirectSoundImpl_Initialize(This
->pds
,lpcGuid
);
1548 static HRESULT WINAPI
IDirectSound8_IDirectSound8_VerifyCertification(
1549 LPDIRECTSOUND8 iface
,
1550 LPDWORD pdwCertified
)
1552 ICOM_THIS(IDirectSound8_IDirectSound8
,iface
);
1553 TRACE("(%p, %p)\n", This
, pdwCertified
);
1554 return IDirectSoundImpl_VerifyCertification(This
->pds
,pdwCertified
);
1557 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl
=
1559 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1560 IDirectSound8_IDirectSound8_QueryInterface
,
1561 IDirectSound8_IDirectSound8_AddRef
,
1562 IDirectSound8_IDirectSound8_Release
,
1563 IDirectSound8_IDirectSound8_CreateSoundBuffer
,
1564 IDirectSound8_IDirectSound8_GetCaps
,
1565 IDirectSound8_IDirectSound8_DuplicateSoundBuffer
,
1566 IDirectSound8_IDirectSound8_SetCooperativeLevel
,
1567 IDirectSound8_IDirectSound8_Compact
,
1568 IDirectSound8_IDirectSound8_GetSpeakerConfig
,
1569 IDirectSound8_IDirectSound8_SetSpeakerConfig
,
1570 IDirectSound8_IDirectSound8_Initialize
,
1571 IDirectSound8_IDirectSound8_VerifyCertification
1574 HRESULT WINAPI
IDirectSound8_IDirectSound8_Create(
1576 LPDIRECTSOUND8
* ppds
)
1578 IDirectSound8_IDirectSound8
* pdsds
;
1579 TRACE("(%p,%p)\n",pds
,ppds
);
1582 ERR("invalid parameter: ppds == NULL\n");
1583 return DSERR_INVALIDPARAM
;
1587 ERR("invalid parameter: pds == NULL\n");
1589 return DSERR_INVALIDPARAM
;
1592 pdsds
= HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds
));
1593 if (pdsds
== NULL
) {
1594 WARN("out of memory\n");
1596 return DSERR_OUTOFMEMORY
;
1599 pdsds
->lpVtbl
= &DirectSound8_DirectSound8_Vtbl
;
1603 IDirectSoundImpl_AddRef(pds
);
1604 *ppds
= (LPDIRECTSOUND8
)pdsds
;
1609 HRESULT WINAPI
DSOUND_Create(
1611 LPDIRECTSOUND
*ppDS
,
1612 IUnknown
*pUnkOuter
)
1617 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1619 if (pUnkOuter
!= NULL
) {
1620 WARN("invalid parameter: pUnkOuter != NULL\n");
1621 return DSERR_INVALIDPARAM
;
1625 WARN("invalid parameter: ppDS == NULL\n");
1626 return DSERR_INVALIDPARAM
;
1629 /* Get dsound configuration */
1630 setup_dsound_options();
1632 /* Default device? */
1633 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1634 lpcGUID
= &DSDEVID_DefaultPlayback
;
1636 if (GetDeviceID(lpcGUID
, &devGuid
) != DS_OK
) {
1637 WARN("invalid parameter: lpcGUID\n");
1639 return DSERR_INVALIDPARAM
;
1643 if (IsEqualGUID(&devGuid
, &dsound
->guid
)) {
1644 hr
= IDirectSound_IDirectSound_Create((LPDIRECTSOUND8
)dsound
, ppDS
);
1646 IDirectSound_IDirectSound_AddRef(*ppDS
);
1648 WARN("IDirectSound_IDirectSound_Create failed\n");
1650 ERR("different dsound already opened (only support one sound card at a time now)\n");
1652 hr
= DSERR_ALLOCATED
;
1656 hr
= IDirectSoundImpl_Create(&devGuid
, &pDS
);
1658 hr
= DSOUND_PrimaryCreate((IDirectSoundImpl
*)pDS
);
1660 hr
= IDirectSound_IDirectSound_Create(pDS
, ppDS
);
1662 IDirectSound_IDirectSound_AddRef(*ppDS
);
1664 dsound
= (IDirectSoundImpl
*)pDS
;
1665 timeBeginPeriod(DS_TIME_RES
);
1666 dsound
->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1667 (DWORD
)dsound
, TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1669 WARN("IDirectSound_IDirectSound_Create failed\n");
1670 IDirectSound8_Release(pDS
);
1673 WARN("DSOUND_PrimaryCreate failed\n");
1674 IDirectSound8_Release(pDS
);
1677 WARN("IDirectSoundImpl_Create failed\n");
1683 /*******************************************************************************
1684 * DirectSoundCreate (DSOUND.1)
1686 * Creates and initializes a DirectSound interface.
1689 * lpcGUID [I] Address of the GUID that identifies the sound device.
1690 * ppDS [O] Address of a variable to receive the interface pointer.
1691 * pUnkOuter [I] Must be NULL.
1695 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1696 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1698 HRESULT WINAPI
DirectSoundCreate(
1700 LPDIRECTSOUND
*ppDS
,
1701 IUnknown
*pUnkOuter
)
1705 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1707 hr
= DSOUND_Create(lpcGUID
, ppDS
, pUnkOuter
);
1709 IDirectSoundImpl_Initialize((LPDIRECTSOUND8
)dsound
, lpcGUID
);
1714 HRESULT WINAPI
DSOUND_Create8(
1716 LPDIRECTSOUND8
*ppDS
,
1717 IUnknown
*pUnkOuter
)
1722 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1724 if (pUnkOuter
!= NULL
) {
1725 WARN("invalid parameter: pUnkOuter != NULL\n");
1726 return DSERR_INVALIDPARAM
;
1730 WARN("invalid parameter: ppDS == NULL\n");
1731 return DSERR_INVALIDPARAM
;
1734 /* Get dsound configuration */
1735 setup_dsound_options();
1737 /* Default device? */
1738 if (!lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
))
1739 lpcGUID
= &DSDEVID_DefaultPlayback
;
1741 if (GetDeviceID(lpcGUID
, &devGuid
) != DS_OK
) {
1742 WARN("invalid parameter: lpcGUID\n");
1744 return DSERR_INVALIDPARAM
;
1748 if (IsEqualGUID(&devGuid
, &dsound
->guid
)) {
1749 hr
= IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8
)dsound
, ppDS
);
1751 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1753 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1755 ERR("different dsound already opened (only support one sound card at a time now)\n");
1757 hr
= DSERR_ALLOCATED
;
1761 hr
= IDirectSoundImpl_Create(&devGuid
, &pDS
);
1763 hr
= DSOUND_PrimaryCreate((IDirectSoundImpl
*)pDS
);
1765 hr
= IDirectSound8_IDirectSound8_Create(pDS
, ppDS
);
1767 IDirectSound8_IDirectSound8_AddRef(*ppDS
);
1769 dsound
= (IDirectSoundImpl
*)pDS
;
1770 timeBeginPeriod(DS_TIME_RES
);
1771 dsound
->timerID
= timeSetEvent(DS_TIME_DEL
, DS_TIME_RES
, DSOUND_timer
,
1772 (DWORD
)dsound
, TIME_PERIODIC
| TIME_CALLBACK_FUNCTION
);
1774 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1775 IDirectSound8_Release(pDS
);
1778 WARN("DSOUND_PrimaryCreate failed\n");
1779 IDirectSound8_Release(pDS
);
1782 WARN("IDirectSoundImpl_Create failed\n");
1788 /*******************************************************************************
1789 * DirectSoundCreate8 (DSOUND.11)
1791 * Creates and initializes a DirectSound8 interface.
1794 * lpcGUID [I] Address of the GUID that identifies the sound device.
1795 * ppDS [O] Address of a variable to receive the interface pointer.
1796 * pUnkOuter [I] Must be NULL.
1800 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1801 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1803 HRESULT WINAPI
DirectSoundCreate8(
1805 LPDIRECTSOUND8
*ppDS
,
1806 IUnknown
*pUnkOuter
)
1810 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID
),ppDS
,pUnkOuter
);
1812 hr
= DSOUND_Create8(lpcGUID
, ppDS
, pUnkOuter
);
1814 IDirectSoundImpl_Initialize((LPDIRECTSOUND8
)dsound
, lpcGUID
);