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)
737 HRESULT err = DSERR_INVALIDPARAM;
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++) {
756 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
758 WARN("waveOutMessage failed; err=%lx\n",err);
762 TRACE("got GUID %s for wod %d.\n", debugstr_guid(&guid), wod);
763 if (IsEqualGUID( lpcGUID, &guid)) {
771 WARN("invalid parameter\n");
773 return DSERR_INVALIDPARAM;
776 if (found == FALSE) {
777 WARN("No device found matching given ID!\n");
779 return DSERR_NODRIVER;
782 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
783 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
785 /* Disable the direct sound driver to force emulation if requested. */
786 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
789 /* Allocate memory */
790 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
792 WARN("out of memory\n");
794 return DSERR_OUTOFMEMORY;
797 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
801 pDS->priolevel = DSSCL_NORMAL;
807 pDS->state = STATE_STOPPED;
808 pDS->nrofbuffers = 0;
811 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
812 pDS->initialized = FALSE;
814 /* 3D listener initial parameters */
815 pDS->listener = NULL;
816 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
817 pDS->ds3dl.vPosition.x = 0.0;
818 pDS->ds3dl.vPosition.y = 0.0;
819 pDS->ds3dl.vPosition.z = 0.0;
820 pDS->ds3dl.vVelocity.x = 0.0;
821 pDS->ds3dl.vVelocity.y = 0.0;
822 pDS->ds3dl.vVelocity.z = 0.0;
823 pDS->ds3dl.vOrientFront.x = 0.0;
824 pDS->ds3dl.vOrientFront.y = 0.0;
825 pDS->ds3dl.vOrientFront.z = 1.0;
826 pDS->ds3dl.vOrientTop.x = 0.0;
827 pDS->ds3dl.vOrientTop.y = 1.0;
828 pDS->ds3dl.vOrientTop.z = 0.0;
829 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
830 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
831 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
833 pDS->prebuf = ds_snd_queue_max;
834 pDS->guid = *lpcGUID;
836 /* Get driver description */
838 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
840 WARN("IDsDriver_GetDriverDesc failed\n");
841 HeapFree(GetProcessHeap(),0,pDS);
846 /* if no DirectSound interface available, use WINMM API instead */
847 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
850 pDS->drvdesc.dnDevNode = wod;
852 /* Set default wave format (may need it for waveOutOpen) */
853 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
854 if (pDS->pwfx == NULL) {
855 WARN("out of memory\n");
856 HeapFree(GetProcessHeap(),0,pDS);
858 return DSERR_OUTOFMEMORY;
861 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
862 /* We rely on the sound driver to return the actual sound format of
863 * the device if it does not support 22050x8x2 and is given the
864 * WAVE_DIRECTSOUND flag.
866 pDS->pwfx->nSamplesPerSec = 22050;
867 pDS->pwfx->wBitsPerSample = 8;
868 pDS->pwfx->nChannels = 2;
869 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
870 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
871 pDS->pwfx->cbSize = 0;
873 /* If the driver requests being opened through MMSYSTEM
874 * (which is recommended by the DDK), it is supposed to happen
875 * before the DirectSound interface is opened */
876 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
878 DWORD flags = CALLBACK_FUNCTION;
880 /* disable direct sound if requested */
881 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
882 flags |= WAVE_DIRECTSOUND;
884 err = mmErr(waveOutOpen(&(pDS->hwo),
885 pDS->drvdesc.dnDevNode, pDS->pwfx,
886 (DWORD)DSOUND_callback, (DWORD)pDS,
889 WARN("waveOutOpen failed\n");
890 HeapFree(GetProcessHeap(),0,pDS);
897 err = IDsDriver_Open(drv);
899 WARN("IDsDriver_Open failed\n");
900 HeapFree(GetProcessHeap(),0,pDS);
905 /* the driver is now open, so it's now allowed to call GetCaps */
906 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
908 WARN("IDsDriver_GetCaps failed\n");
909 HeapFree(GetProcessHeap(),0,pDS);
915 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
917 WARN("waveOutGetDevCaps failed\n");
918 HeapFree(GetProcessHeap(),0,pDS);
922 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
923 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
924 (woc.dwFormats & WAVE_FORMAT_2M08) ||
925 (woc.dwFormats & WAVE_FORMAT_4M08) ||
926 (woc.dwFormats & WAVE_FORMAT_48M08) ||
927 (woc.dwFormats & WAVE_FORMAT_96M08)) {
928 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
929 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
931 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
932 (woc.dwFormats & WAVE_FORMAT_2M16) ||
933 (woc.dwFormats & WAVE_FORMAT_4M16) ||
934 (woc.dwFormats & WAVE_FORMAT_48M16) ||
935 (woc.dwFormats & WAVE_FORMAT_96M16)) {
936 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
937 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
939 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
940 (woc.dwFormats & WAVE_FORMAT_2S08) ||
941 (woc.dwFormats & WAVE_FORMAT_4S08) ||
942 (woc.dwFormats & WAVE_FORMAT_48S08) ||
943 (woc.dwFormats & WAVE_FORMAT_96S08)) {
944 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
945 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
947 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
948 (woc.dwFormats & WAVE_FORMAT_2S16) ||
949 (woc.dwFormats & WAVE_FORMAT_4S16) ||
950 (woc.dwFormats & WAVE_FORMAT_48S16) ||
951 (woc.dwFormats & WAVE_FORMAT_96S16)) {
952 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
953 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
956 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
957 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
958 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
959 pDS->drvcaps.dwPrimaryBuffers = 1;
962 InitializeCriticalSection(&(pDS->mixlock));
963 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
964 RtlInitializeResource(&(pDS->lock));
966 *ppDS = (LPDIRECTSOUND8)pDS;
970 /*******************************************************************************
971 * IDirectSound_IUnknown
973 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
978 ICOM_THIS(IDirectSound_IUnknown,iface);
979 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
980 return DSOUND_QueryInterface(This->pds, riid, ppobj);
983 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
986 ICOM_THIS(IDirectSound_IUnknown,iface);
987 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
988 return InterlockedIncrement(&This->ref);
991 static ULONG WINAPI IDirectSound_IUnknown_Release(
994 ICOM_THIS(IDirectSound_IUnknown,iface);
996 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
997 ulReturn = InterlockedDecrement(&This->ref);
999 IDirectSoundImpl_Release(This->pds);
1000 HeapFree(GetProcessHeap(),0,This);
1001 TRACE("(%p) released\n",This);
1006 static IUnknownVtbl DirectSound_Unknown_Vtbl =
1008 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1009 IDirectSound_IUnknown_QueryInterface,
1010 IDirectSound_IUnknown_AddRef,
1011 IDirectSound_IUnknown_Release
1014 HRESULT WINAPI IDirectSound_IUnknown_Create(
1018 IDirectSound_IUnknown * pdsunk;
1019 TRACE("(%p,%p)\n",pds,ppunk);
1021 if (ppunk == NULL) {
1022 ERR("invalid parameter: ppunk == NULL\n");
1023 return DSERR_INVALIDPARAM;
1027 ERR("invalid parameter: pds == NULL\n");
1029 return DSERR_INVALIDPARAM;
1032 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1033 if (pdsunk == NULL) {
1034 WARN("out of memory\n");
1036 return DSERR_OUTOFMEMORY;
1039 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1043 IDirectSoundImpl_AddRef(pds);
1044 *ppunk = (LPUNKNOWN)pdsunk;
1049 /*******************************************************************************
1050 * IDirectSound_IDirectSound
1052 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1053 LPDIRECTSOUND iface,
1057 ICOM_THIS(IDirectSound_IDirectSound,iface);
1058 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1059 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1062 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1063 LPDIRECTSOUND iface)
1065 ICOM_THIS(IDirectSound_IDirectSound,iface);
1066 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1067 return InterlockedIncrement(&This->ref);
1070 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1071 LPDIRECTSOUND iface)
1073 ICOM_THIS(IDirectSound_IDirectSound,iface);
1075 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1076 ulReturn = InterlockedDecrement(&This->ref);
1077 if (ulReturn == 0) {
1078 IDirectSoundImpl_Release(This->pds);
1079 HeapFree(GetProcessHeap(),0,This);
1080 TRACE("(%p) released\n",This);
1085 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1086 LPDIRECTSOUND iface,
1087 LPCDSBUFFERDESC dsbd,
1088 LPLPDIRECTSOUNDBUFFER ppdsb,
1091 ICOM_THIS(IDirectSound_IDirectSound,iface);
1092 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1093 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1096 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1097 LPDIRECTSOUND iface,
1100 ICOM_THIS(IDirectSound_IDirectSound,iface);
1101 TRACE("(%p,%p)\n",This,lpDSCaps);
1102 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1105 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1106 LPDIRECTSOUND iface,
1107 LPDIRECTSOUNDBUFFER psb,
1108 LPLPDIRECTSOUNDBUFFER ppdsb)
1110 ICOM_THIS(IDirectSound_IDirectSound,iface);
1111 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1112 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1115 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1116 LPDIRECTSOUND iface,
1120 ICOM_THIS(IDirectSound_IDirectSound,iface);
1121 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1122 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1125 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1126 LPDIRECTSOUND iface)
1128 ICOM_THIS(IDirectSound_IDirectSound,iface);
1129 TRACE("(%p)\n", This);
1130 return IDirectSoundImpl_Compact(This->pds);
1133 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1134 LPDIRECTSOUND iface,
1135 LPDWORD lpdwSpeakerConfig)
1137 ICOM_THIS(IDirectSound_IDirectSound,iface);
1138 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1139 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1142 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1143 LPDIRECTSOUND iface,
1146 ICOM_THIS(IDirectSound_IDirectSound,iface);
1147 TRACE("(%p,0x%08lx)\n",This,config);
1148 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1151 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1152 LPDIRECTSOUND iface,
1155 ICOM_THIS(IDirectSound_IDirectSound,iface);
1156 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1157 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1160 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1162 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1163 IDirectSound_IDirectSound_QueryInterface,
1164 IDirectSound_IDirectSound_AddRef,
1165 IDirectSound_IDirectSound_Release,
1166 IDirectSound_IDirectSound_CreateSoundBuffer,
1167 IDirectSound_IDirectSound_GetCaps,
1168 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1169 IDirectSound_IDirectSound_SetCooperativeLevel,
1170 IDirectSound_IDirectSound_Compact,
1171 IDirectSound_IDirectSound_GetSpeakerConfig,
1172 IDirectSound_IDirectSound_SetSpeakerConfig,
1173 IDirectSound_IDirectSound_Initialize
1176 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1178 LPDIRECTSOUND * ppds)
1180 IDirectSound_IDirectSound * pdsds;
1181 TRACE("(%p,%p)\n",pds,ppds);
1184 ERR("invalid parameter: ppds == NULL\n");
1185 return DSERR_INVALIDPARAM;
1189 ERR("invalid parameter: pds == NULL\n");
1191 return DSERR_INVALIDPARAM;
1194 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1195 if (pdsds == NULL) {
1196 WARN("out of memory\n");
1198 return DSERR_OUTOFMEMORY;
1201 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1205 IDirectSoundImpl_AddRef(pds);
1206 *ppds = (LPDIRECTSOUND)pdsds;
1211 /*******************************************************************************
1212 * IDirectSound8_IUnknown
1214 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1219 ICOM_THIS(IDirectSound_IUnknown,iface);
1220 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1221 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1224 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1227 ICOM_THIS(IDirectSound_IUnknown,iface);
1228 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1229 return InterlockedIncrement(&This->ref);
1232 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1235 ICOM_THIS(IDirectSound_IUnknown,iface);
1237 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1238 ulReturn = InterlockedDecrement(&This->ref);
1239 if (ulReturn == 0) {
1240 IDirectSoundImpl_Release(This->pds);
1241 HeapFree(GetProcessHeap(),0,This);
1242 TRACE("(%p) released\n",This);
1247 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1249 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1250 IDirectSound8_IUnknown_QueryInterface,
1251 IDirectSound8_IUnknown_AddRef,
1252 IDirectSound8_IUnknown_Release
1255 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1259 IDirectSound8_IUnknown * pdsunk;
1260 TRACE("(%p,%p)\n",pds,ppunk);
1262 if (ppunk == NULL) {
1263 ERR("invalid parameter: ppunk == NULL\n");
1264 return DSERR_INVALIDPARAM;
1268 ERR("invalid parameter: pds == NULL\n");
1270 return DSERR_INVALIDPARAM;
1273 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1274 if (pdsunk == NULL) {
1275 WARN("out of memory\n");
1277 return DSERR_OUTOFMEMORY;
1280 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1284 IDirectSoundImpl_AddRef(pds);
1285 *ppunk = (LPUNKNOWN)pdsunk;
1290 /*******************************************************************************
1291 * IDirectSound8_IDirectSound
1293 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1294 LPDIRECTSOUND iface,
1298 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1299 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1300 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1303 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1304 LPDIRECTSOUND iface)
1306 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1307 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1308 return InterlockedIncrement(&This->ref);
1311 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1312 LPDIRECTSOUND iface)
1314 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1316 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1317 ulReturn = InterlockedDecrement(&This->ref);
1318 if (ulReturn == 0) {
1319 IDirectSoundImpl_Release(This->pds);
1320 HeapFree(GetProcessHeap(),0,This);
1321 TRACE("(%p) released\n",This);
1326 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1327 LPDIRECTSOUND iface,
1328 LPCDSBUFFERDESC dsbd,
1329 LPLPDIRECTSOUNDBUFFER ppdsb,
1332 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1333 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1334 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1337 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1338 LPDIRECTSOUND iface,
1341 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1342 TRACE("(%p,%p)\n",This,lpDSCaps);
1343 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1346 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1347 LPDIRECTSOUND iface,
1348 LPDIRECTSOUNDBUFFER psb,
1349 LPLPDIRECTSOUNDBUFFER ppdsb)
1351 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1352 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1353 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1356 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1357 LPDIRECTSOUND iface,
1361 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1362 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1363 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1366 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1367 LPDIRECTSOUND iface)
1369 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1370 TRACE("(%p)\n", This);
1371 return IDirectSoundImpl_Compact(This->pds);
1374 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1375 LPDIRECTSOUND iface,
1376 LPDWORD lpdwSpeakerConfig)
1378 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1379 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1380 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1383 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1384 LPDIRECTSOUND iface,
1387 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1388 TRACE("(%p,0x%08lx)\n",This,config);
1389 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1392 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1393 LPDIRECTSOUND iface,
1396 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1397 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1398 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1401 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1403 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1404 IDirectSound8_IDirectSound_QueryInterface,
1405 IDirectSound8_IDirectSound_AddRef,
1406 IDirectSound8_IDirectSound_Release,
1407 IDirectSound8_IDirectSound_CreateSoundBuffer,
1408 IDirectSound8_IDirectSound_GetCaps,
1409 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1410 IDirectSound8_IDirectSound_SetCooperativeLevel,
1411 IDirectSound8_IDirectSound_Compact,
1412 IDirectSound8_IDirectSound_GetSpeakerConfig,
1413 IDirectSound8_IDirectSound_SetSpeakerConfig,
1414 IDirectSound8_IDirectSound_Initialize
1417 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1419 LPDIRECTSOUND * ppds)
1421 IDirectSound8_IDirectSound * pdsds;
1422 TRACE("(%p,%p)\n",pds,ppds);
1425 ERR("invalid parameter: ppds == NULL\n");
1426 return DSERR_INVALIDPARAM;
1430 ERR("invalid parameter: pds == NULL\n");
1432 return DSERR_INVALIDPARAM;
1435 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1436 if (pdsds == NULL) {
1437 WARN("out of memory\n");
1439 return DSERR_OUTOFMEMORY;
1442 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1446 IDirectSoundImpl_AddRef(pds);
1447 *ppds = (LPDIRECTSOUND)pdsds;
1452 /*******************************************************************************
1453 * IDirectSound8_IDirectSound8
1455 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1456 LPDIRECTSOUND8 iface,
1460 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1461 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1462 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1465 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1466 LPDIRECTSOUND8 iface)
1468 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1469 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1470 return InterlockedIncrement(&This->ref);
1473 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1474 LPDIRECTSOUND8 iface)
1476 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1478 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1479 ulReturn = InterlockedDecrement(&This->ref);
1480 if (ulReturn == 0) {
1481 IDirectSoundImpl_Release(This->pds);
1482 HeapFree(GetProcessHeap(),0,This);
1483 TRACE("(%p) released\n",This);
1488 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1489 LPDIRECTSOUND8 iface,
1490 LPCDSBUFFERDESC dsbd,
1491 LPLPDIRECTSOUNDBUFFER ppdsb,
1494 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1495 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1496 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1499 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1500 LPDIRECTSOUND8 iface,
1503 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1504 TRACE("(%p,%p)\n",This,lpDSCaps);
1505 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1508 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1509 LPDIRECTSOUND8 iface,
1510 LPDIRECTSOUNDBUFFER psb,
1511 LPLPDIRECTSOUNDBUFFER ppdsb)
1513 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1514 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1515 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1518 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1519 LPDIRECTSOUND8 iface,
1523 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1524 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1525 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1528 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1529 LPDIRECTSOUND8 iface)
1531 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1532 TRACE("(%p)\n", This);
1533 return IDirectSoundImpl_Compact(This->pds);
1536 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1537 LPDIRECTSOUND8 iface,
1538 LPDWORD lpdwSpeakerConfig)
1540 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1541 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1542 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1545 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1546 LPDIRECTSOUND8 iface,
1549 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1550 TRACE("(%p,0x%08lx)\n",This,config);
1551 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1554 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1555 LPDIRECTSOUND8 iface,
1558 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1559 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1560 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1563 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1564 LPDIRECTSOUND8 iface,
1565 LPDWORD pdwCertified)
1567 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1568 TRACE("(%p, %p)\n", This, pdwCertified);
1569 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1572 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1574 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1575 IDirectSound8_IDirectSound8_QueryInterface,
1576 IDirectSound8_IDirectSound8_AddRef,
1577 IDirectSound8_IDirectSound8_Release,
1578 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1579 IDirectSound8_IDirectSound8_GetCaps,
1580 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1581 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1582 IDirectSound8_IDirectSound8_Compact,
1583 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1584 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1585 IDirectSound8_IDirectSound8_Initialize,
1586 IDirectSound8_IDirectSound8_VerifyCertification
1589 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1591 LPDIRECTSOUND8 * ppds)
1593 IDirectSound8_IDirectSound8 * pdsds;
1594 TRACE("(%p,%p)\n",pds,ppds);
1597 ERR("invalid parameter: ppds == NULL\n");
1598 return DSERR_INVALIDPARAM;
1602 ERR("invalid parameter: pds == NULL\n");
1604 return DSERR_INVALIDPARAM;
1607 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1608 if (pdsds == NULL) {
1609 WARN("out of memory\n");
1611 return DSERR_OUTOFMEMORY;
1614 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1618 IDirectSoundImpl_AddRef(pds);
1619 *ppds = (LPDIRECTSOUND8)pdsds;
1624 HRESULT WINAPI DSOUND_Create(
1626 LPDIRECTSOUND *ppDS,
1627 IUnknown *pUnkOuter)
1632 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1634 if (pUnkOuter != NULL) {
1635 WARN("invalid parameter: pUnkOuter != NULL\n");
1636 return DSERR_INVALIDPARAM;
1640 WARN("invalid parameter: ppDS == NULL\n");
1641 return DSERR_INVALIDPARAM;
1644 /* Get dsound configuration */
1645 setup_dsound_options();
1647 /* Default device? */
1648 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1649 lpcGUID = &DSDEVID_DefaultPlayback;
1651 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1652 WARN("invalid parameter: lpcGUID\n");
1654 return DSERR_INVALIDPARAM;
1658 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1659 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1661 IDirectSound_IDirectSound_AddRef(*ppDS);
1663 WARN("IDirectSound_IDirectSound_Create failed\n");
1665 ERR("different dsound already opened (only support one sound card at a time now)\n");
1667 hr = DSERR_ALLOCATED;
1671 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1673 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1675 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1677 IDirectSound_IDirectSound_AddRef(*ppDS);
1679 dsound = (IDirectSoundImpl*)pDS;
1680 timeBeginPeriod(DS_TIME_RES);
1681 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1682 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1684 WARN("IDirectSound_IDirectSound_Create failed\n");
1685 IDirectSound8_Release(pDS);
1688 WARN("DSOUND_PrimaryCreate failed\n");
1689 IDirectSound8_Release(pDS);
1692 WARN("IDirectSoundImpl_Create failed\n");
1698 /*******************************************************************************
1699 * DirectSoundCreate (DSOUND.1)
1701 * Creates and initializes a DirectSound interface.
1704 * lpcGUID [I] Address of the GUID that identifies the sound device.
1705 * ppDS [O] Address of a variable to receive the interface pointer.
1706 * pUnkOuter [I] Must be NULL.
1710 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1711 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1713 HRESULT WINAPI DirectSoundCreate(
1715 LPDIRECTSOUND *ppDS,
1716 IUnknown *pUnkOuter)
1720 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1722 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1724 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1729 HRESULT WINAPI DSOUND_Create8(
1731 LPDIRECTSOUND8 *ppDS,
1732 IUnknown *pUnkOuter)
1737 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1739 if (pUnkOuter != NULL) {
1740 WARN("invalid parameter: pUnkOuter != NULL\n");
1741 return DSERR_INVALIDPARAM;
1745 WARN("invalid parameter: ppDS == NULL\n");
1746 return DSERR_INVALIDPARAM;
1749 /* Get dsound configuration */
1750 setup_dsound_options();
1752 /* Default device? */
1753 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1754 lpcGUID = &DSDEVID_DefaultPlayback;
1756 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1757 WARN("invalid parameter: lpcGUID\n");
1759 return DSERR_INVALIDPARAM;
1763 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1764 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1766 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1768 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1770 ERR("different dsound already opened (only support one sound card at a time now)\n");
1772 hr = DSERR_ALLOCATED;
1776 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1778 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1780 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1782 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1784 dsound = (IDirectSoundImpl*)pDS;
1785 timeBeginPeriod(DS_TIME_RES);
1786 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1787 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1789 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1790 IDirectSound8_Release(pDS);
1793 WARN("DSOUND_PrimaryCreate failed\n");
1794 IDirectSound8_Release(pDS);
1797 WARN("IDirectSoundImpl_Create failed\n");
1803 /*******************************************************************************
1804 * DirectSoundCreate8 (DSOUND.11)
1806 * Creates and initializes a DirectSound8 interface.
1809 * lpcGUID [I] Address of the GUID that identifies the sound device.
1810 * ppDS [O] Address of a variable to receive the interface pointer.
1811 * pUnkOuter [I] Must be NULL.
1815 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1816 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1818 HRESULT WINAPI DirectSoundCreate8(
1820 LPDIRECTSOUND8 *ppDS,
1821 IUnknown *pUnkOuter)
1825 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1827 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1829 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);