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;
470 ICOM_THIS(IDirectSoundImpl,iface);
472 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
475 WARN("invalid parameter: This == NULL\n");
476 return DSERR_INVALIDPARAM;
479 if (This->initialized == FALSE) {
480 WARN("not initialized\n");
481 return DSERR_UNINITIALIZED;
485 WARN("invalid parameter: psb == NULL\n");
486 return DSERR_INVALIDPARAM;
490 WARN("invalid parameter: ppdsb == NULL\n");
491 return DSERR_INVALIDPARAM;
494 /* FIXME: hack to make sure we have a secondary buffer */
495 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
496 WARN("trying to duplicate primary buffer\n");
498 return DSERR_INVALIDCALL;
501 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
503 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
506 WARN("out of memory\n");
508 return DSERR_OUTOFMEMORY;
511 memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
514 TRACE("duplicating hardware buffer\n");
516 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
518 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
520 /* allocate buffer */
521 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
522 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
523 if (dsb->buffer == NULL) {
524 WARN("out of memory\n");
525 HeapFree(GetProcessHeap(),0,dsb);
527 return DSERR_OUTOFMEMORY;
530 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
531 if (dsb->buffer->memory == NULL) {
532 WARN("out of memory\n");
533 HeapFree(GetProcessHeap(),0,dsb->buffer);
534 HeapFree(GetProcessHeap(),0,dsb);
536 return DSERR_OUTOFMEMORY;
538 dsb->buffer->ref = 1;
540 /* FIXME: copy buffer ? */
549 dsb->state = STATE_STOPPED;
554 dsb->iks = NULL; /* FIXME? */
556 memcpy(&(dsb->wfx), &(pdsb->wfx), sizeof(dsb->wfx));
557 InitializeCriticalSection(&(dsb->lock));
558 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
559 /* register buffer */
560 RtlAcquireResourceExclusive(&(This->lock), TRUE);
562 IDirectSoundBufferImpl **newbuffers;
564 newbuffers = HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
566 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
569 This->buffers = newbuffers;
570 This->buffers[This->nrofbuffers] = dsb;
572 TRACE("buffer count is now %d\n", This->nrofbuffers);
574 ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
575 IDirectSoundBuffer8_Release(psb);
576 DeleteCriticalSection(&(dsb->lock));
577 RtlReleaseResource(&(This->lock));
578 HeapFree(GetProcessHeap(),0,dsb);
580 return DSERR_OUTOFMEMORY;
583 RtlReleaseResource(&(This->lock));
584 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
586 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
587 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
589 WARN("SecondaryBufferImpl_Create failed\n");
594 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
595 LPDIRECTSOUND8 iface,
599 ICOM_THIS(IDirectSoundImpl,iface);
600 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
602 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
603 FIXME("level=%s not fully supported\n",
604 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
606 This->priolevel = level;
610 static HRESULT WINAPI IDirectSoundImpl_Compact(
611 LPDIRECTSOUND8 iface)
613 ICOM_THIS(IDirectSoundImpl,iface);
614 TRACE("(%p)\n",This);
616 if (This->initialized == FALSE) {
617 WARN("not initialized\n");
618 return DSERR_UNINITIALIZED;
621 if (This->priolevel != DSSCL_PRIORITY) {
622 WARN("incorrect priority level\n");
623 return DSERR_PRIOLEVELNEEDED;
629 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
630 LPDIRECTSOUND8 iface,
631 LPDWORD lpdwSpeakerConfig)
633 ICOM_THIS(IDirectSoundImpl,iface);
634 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
636 if (This->initialized == FALSE) {
637 WARN("not initialized\n");
638 return DSERR_UNINITIALIZED;
641 if (lpdwSpeakerConfig == NULL) {
642 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
643 return DSERR_INVALIDPARAM;
646 WARN("not fully functional\n");
647 *lpdwSpeakerConfig = This->speaker_config;
651 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
652 LPDIRECTSOUND8 iface,
655 ICOM_THIS(IDirectSoundImpl,iface);
656 TRACE("(%p,0x%08lx)\n",This,config);
658 if (This->initialized == FALSE) {
659 WARN("not initialized\n");
660 return DSERR_UNINITIALIZED;
663 This->speaker_config = config;
664 WARN("not fully functional\n");
668 static HRESULT WINAPI IDirectSoundImpl_Initialize(
669 LPDIRECTSOUND8 iface,
672 ICOM_THIS(IDirectSoundImpl,iface);
673 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
675 This->initialized = TRUE;
680 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
681 LPDIRECTSOUND8 iface,
682 LPDWORD pdwCertified)
684 ICOM_THIS(IDirectSoundImpl,iface);
685 TRACE("(%p, %p)\n",This,pdwCertified);
687 if (This->initialized == FALSE) {
688 WARN("not initialized\n");
689 return DSERR_UNINITIALIZED;
692 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
693 *pdwCertified = DS_CERTIFIED;
695 *pdwCertified = DS_UNCERTIFIED;
699 static ICOM_VTABLE(IDirectSound8) IDirectSoundImpl_Vtbl =
701 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
702 IDirectSoundImpl_QueryInterface,
703 IDirectSoundImpl_AddRef,
704 IDirectSoundImpl_Release,
705 IDirectSoundImpl_CreateSoundBuffer,
706 IDirectSoundImpl_GetCaps,
707 IDirectSoundImpl_DuplicateSoundBuffer,
708 IDirectSoundImpl_SetCooperativeLevel,
709 IDirectSoundImpl_Compact,
710 IDirectSoundImpl_GetSpeakerConfig,
711 IDirectSoundImpl_SetSpeakerConfig,
712 IDirectSoundImpl_Initialize,
713 IDirectSoundImpl_VerifyCertification
716 HRESULT WINAPI IDirectSoundImpl_Create(
718 LPDIRECTSOUND8 * ppDS)
720 HRESULT err = DSERR_INVALIDPARAM;
721 PIDSDRIVER drv = NULL;
722 IDirectSoundImpl* pDS;
724 BOOLEAN found = FALSE;
725 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
727 /* Enumerate WINMM audio devices and find the one we want */
728 wodn = waveOutGetNumDevs();
732 return DSERR_NODRIVER;
735 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
737 for (wod=0; wod<wodn; wod++) {
739 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
741 WARN("waveOutMessage failed; err=%lx\n",err);
745 TRACE("got GUID %s for wod %d.\n", debugstr_guid(&guid), wod);
746 if (IsEqualGUID( lpcGUID, &guid)) {
754 WARN("invalid parameter\n");
756 return DSERR_INVALIDPARAM;
759 if (found == FALSE) {
760 WARN("No device found matching given ID!\n");
762 return DSERR_NODRIVER;
765 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
766 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
768 /* Disable the direct sound driver to force emulation if requested. */
769 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
772 /* Allocate memory */
773 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
775 WARN("out of memory\n");
777 return DSERR_OUTOFMEMORY;
780 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
784 pDS->priolevel = DSSCL_NORMAL;
790 pDS->state = STATE_STOPPED;
791 pDS->nrofbuffers = 0;
794 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
795 pDS->initialized = FALSE;
797 /* 3D listener initial parameters */
798 pDS->listener = NULL;
799 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
800 pDS->ds3dl.vPosition.x = 0.0;
801 pDS->ds3dl.vPosition.y = 0.0;
802 pDS->ds3dl.vPosition.z = 0.0;
803 pDS->ds3dl.vVelocity.x = 0.0;
804 pDS->ds3dl.vVelocity.y = 0.0;
805 pDS->ds3dl.vVelocity.z = 0.0;
806 pDS->ds3dl.vOrientFront.x = 0.0;
807 pDS->ds3dl.vOrientFront.y = 0.0;
808 pDS->ds3dl.vOrientFront.z = 1.0;
809 pDS->ds3dl.vOrientTop.x = 0.0;
810 pDS->ds3dl.vOrientTop.y = 1.0;
811 pDS->ds3dl.vOrientTop.z = 0.0;
812 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
813 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
814 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
816 pDS->prebuf = ds_snd_queue_max;
817 pDS->guid = *lpcGUID;
819 /* Get driver description */
821 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
823 WARN("IDsDriver_GetDriverDesc failed\n");
824 HeapFree(GetProcessHeap(),0,pDS);
829 /* if no DirectSound interface available, use WINMM API instead */
830 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
833 pDS->drvdesc.dnDevNode = wod;
835 /* Set default wave format (may need it for waveOutOpen) */
836 pDS->wfx.wFormatTag = WAVE_FORMAT_PCM;
837 /* We rely on the sound driver to return the actual sound format of
838 * the device if it does not support 22050x8x2 and is given the
839 * WAVE_DIRECTSOUND flag.
841 pDS->wfx.nSamplesPerSec = 22050;
842 pDS->wfx.wBitsPerSample = 8;
843 pDS->wfx.nChannels = 2;
844 pDS->wfx.nBlockAlign = pDS->wfx.wBitsPerSample * pDS->wfx.nChannels / 8;
845 pDS->wfx.nAvgBytesPerSec = pDS->wfx.nSamplesPerSec * pDS->wfx.nBlockAlign;
848 /* If the driver requests being opened through MMSYSTEM
849 * (which is recommended by the DDK), it is supposed to happen
850 * before the DirectSound interface is opened */
851 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
853 DWORD flags = CALLBACK_FUNCTION;
855 /* disable direct sound if requested */
856 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
857 flags |= WAVE_DIRECTSOUND;
859 err = mmErr(waveOutOpen(&(pDS->hwo),
860 pDS->drvdesc.dnDevNode, &(pDS->wfx),
861 (DWORD)DSOUND_callback, (DWORD)pDS,
864 WARN("waveOutOpen failed\n");
865 HeapFree(GetProcessHeap(),0,pDS);
872 err = IDsDriver_Open(drv);
874 WARN("IDsDriver_Open failed\n");
875 HeapFree(GetProcessHeap(),0,pDS);
880 /* the driver is now open, so it's now allowed to call GetCaps */
881 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
883 WARN("IDsDriver_GetCaps failed\n");
884 HeapFree(GetProcessHeap(),0,pDS);
890 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
892 WARN("waveOutGetDevCaps failed\n");
893 HeapFree(GetProcessHeap(),0,pDS);
897 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
898 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
899 (woc.dwFormats & WAVE_FORMAT_2M08) ||
900 (woc.dwFormats & WAVE_FORMAT_4M08) ||
901 (woc.dwFormats & WAVE_FORMAT_48M08) ||
902 (woc.dwFormats & WAVE_FORMAT_96M08)) {
903 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
904 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
906 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
907 (woc.dwFormats & WAVE_FORMAT_2M16) ||
908 (woc.dwFormats & WAVE_FORMAT_4M16) ||
909 (woc.dwFormats & WAVE_FORMAT_48M16) ||
910 (woc.dwFormats & WAVE_FORMAT_96M16)) {
911 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
912 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
914 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
915 (woc.dwFormats & WAVE_FORMAT_2S08) ||
916 (woc.dwFormats & WAVE_FORMAT_4S08) ||
917 (woc.dwFormats & WAVE_FORMAT_48S08) ||
918 (woc.dwFormats & WAVE_FORMAT_96S08)) {
919 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
920 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
922 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
923 (woc.dwFormats & WAVE_FORMAT_2S16) ||
924 (woc.dwFormats & WAVE_FORMAT_4S16) ||
925 (woc.dwFormats & WAVE_FORMAT_48S16) ||
926 (woc.dwFormats & WAVE_FORMAT_96S16)) {
927 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
928 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
931 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
932 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
933 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
934 pDS->drvcaps.dwPrimaryBuffers = 1;
937 InitializeCriticalSection(&(pDS->mixlock));
938 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
939 RtlInitializeResource(&(pDS->lock));
941 *ppDS = (LPDIRECTSOUND8)pDS;
945 /*******************************************************************************
946 * IDirectSound_IUnknown
948 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
953 ICOM_THIS(IDirectSound_IUnknown,iface);
954 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
955 return DSOUND_QueryInterface(This->pds, riid, ppobj);
958 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
961 ICOM_THIS(IDirectSound_IUnknown,iface);
962 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
963 return InterlockedIncrement(&This->ref);
966 static ULONG WINAPI IDirectSound_IUnknown_Release(
969 ICOM_THIS(IDirectSound_IUnknown,iface);
971 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
972 ulReturn = InterlockedDecrement(&This->ref);
974 IDirectSoundImpl_Release(This->pds);
975 HeapFree(GetProcessHeap(),0,This);
976 TRACE("(%p) released\n",This);
981 static ICOM_VTABLE(IUnknown) DirectSound_Unknown_Vtbl =
983 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
984 IDirectSound_IUnknown_QueryInterface,
985 IDirectSound_IUnknown_AddRef,
986 IDirectSound_IUnknown_Release
989 HRESULT WINAPI IDirectSound_IUnknown_Create(
993 IDirectSound_IUnknown * pdsunk;
994 TRACE("(%p,%p)\n",pds,ppunk);
997 ERR("invalid parameter: ppunk == NULL\n");
998 return DSERR_INVALIDPARAM;
1002 ERR("invalid parameter: pds == NULL\n");
1004 return DSERR_INVALIDPARAM;
1007 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1008 if (pdsunk == NULL) {
1009 WARN("out of memory\n");
1011 return DSERR_OUTOFMEMORY;
1014 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1018 IDirectSoundImpl_AddRef(pds);
1019 *ppunk = (LPUNKNOWN)pdsunk;
1024 /*******************************************************************************
1025 * IDirectSound_IDirectSound
1027 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1028 LPDIRECTSOUND iface,
1032 ICOM_THIS(IDirectSound_IDirectSound,iface);
1033 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1034 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1037 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1038 LPDIRECTSOUND iface)
1040 ICOM_THIS(IDirectSound_IDirectSound,iface);
1041 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1042 return InterlockedIncrement(&This->ref);
1045 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1046 LPDIRECTSOUND iface)
1048 ICOM_THIS(IDirectSound_IDirectSound,iface);
1050 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1051 ulReturn = InterlockedDecrement(&This->ref);
1052 if (ulReturn == 0) {
1053 IDirectSoundImpl_Release(This->pds);
1054 HeapFree(GetProcessHeap(),0,This);
1055 TRACE("(%p) released\n",This);
1060 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1061 LPDIRECTSOUND iface,
1062 LPCDSBUFFERDESC dsbd,
1063 LPLPDIRECTSOUNDBUFFER ppdsb,
1066 ICOM_THIS(IDirectSound_IDirectSound,iface);
1067 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1068 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1071 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1072 LPDIRECTSOUND iface,
1075 ICOM_THIS(IDirectSound_IDirectSound,iface);
1076 TRACE("(%p,%p)\n",This,lpDSCaps);
1077 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1080 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1081 LPDIRECTSOUND iface,
1082 LPDIRECTSOUNDBUFFER psb,
1083 LPLPDIRECTSOUNDBUFFER ppdsb)
1085 ICOM_THIS(IDirectSound_IDirectSound,iface);
1086 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1087 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1090 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1091 LPDIRECTSOUND iface,
1095 ICOM_THIS(IDirectSound_IDirectSound,iface);
1096 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1097 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1100 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1101 LPDIRECTSOUND iface)
1103 ICOM_THIS(IDirectSound_IDirectSound,iface);
1104 TRACE("(%p)\n", This);
1105 return IDirectSoundImpl_Compact(This->pds);
1108 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1109 LPDIRECTSOUND iface,
1110 LPDWORD lpdwSpeakerConfig)
1112 ICOM_THIS(IDirectSound_IDirectSound,iface);
1113 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1114 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1117 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1118 LPDIRECTSOUND iface,
1121 ICOM_THIS(IDirectSound_IDirectSound,iface);
1122 TRACE("(%p,0x%08lx)\n",This,config);
1123 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1126 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1127 LPDIRECTSOUND iface,
1130 ICOM_THIS(IDirectSound_IDirectSound,iface);
1131 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1132 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1135 static ICOM_VTABLE(IDirectSound) DirectSound_DirectSound_Vtbl =
1137 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1138 IDirectSound_IDirectSound_QueryInterface,
1139 IDirectSound_IDirectSound_AddRef,
1140 IDirectSound_IDirectSound_Release,
1141 IDirectSound_IDirectSound_CreateSoundBuffer,
1142 IDirectSound_IDirectSound_GetCaps,
1143 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1144 IDirectSound_IDirectSound_SetCooperativeLevel,
1145 IDirectSound_IDirectSound_Compact,
1146 IDirectSound_IDirectSound_GetSpeakerConfig,
1147 IDirectSound_IDirectSound_SetSpeakerConfig,
1148 IDirectSound_IDirectSound_Initialize
1151 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1153 LPDIRECTSOUND * ppds)
1155 IDirectSound_IDirectSound * pdsds;
1156 TRACE("(%p,%p)\n",pds,ppds);
1159 ERR("invalid parameter: ppds == NULL\n");
1160 return DSERR_INVALIDPARAM;
1164 ERR("invalid parameter: pds == NULL\n");
1166 return DSERR_INVALIDPARAM;
1169 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1170 if (pdsds == NULL) {
1171 WARN("out of memory\n");
1173 return DSERR_OUTOFMEMORY;
1176 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1180 IDirectSoundImpl_AddRef(pds);
1181 *ppds = (LPDIRECTSOUND)pdsds;
1186 /*******************************************************************************
1187 * IDirectSound8_IUnknown
1189 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1194 ICOM_THIS(IDirectSound_IUnknown,iface);
1195 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1196 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1199 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1202 ICOM_THIS(IDirectSound_IUnknown,iface);
1203 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1204 return InterlockedIncrement(&This->ref);
1207 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1210 ICOM_THIS(IDirectSound_IUnknown,iface);
1212 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1213 ulReturn = InterlockedDecrement(&This->ref);
1214 if (ulReturn == 0) {
1215 IDirectSoundImpl_Release(This->pds);
1216 HeapFree(GetProcessHeap(),0,This);
1217 TRACE("(%p) released\n",This);
1222 static ICOM_VTABLE(IUnknown) DirectSound8_Unknown_Vtbl =
1224 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1225 IDirectSound8_IUnknown_QueryInterface,
1226 IDirectSound8_IUnknown_AddRef,
1227 IDirectSound8_IUnknown_Release
1230 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1234 IDirectSound8_IUnknown * pdsunk;
1235 TRACE("(%p,%p)\n",pds,ppunk);
1237 if (ppunk == NULL) {
1238 ERR("invalid parameter: ppunk == NULL\n");
1239 return DSERR_INVALIDPARAM;
1243 ERR("invalid parameter: pds == NULL\n");
1245 return DSERR_INVALIDPARAM;
1248 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1249 if (pdsunk == NULL) {
1250 WARN("out of memory\n");
1252 return DSERR_OUTOFMEMORY;
1255 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1259 IDirectSoundImpl_AddRef(pds);
1260 *ppunk = (LPUNKNOWN)pdsunk;
1265 /*******************************************************************************
1266 * IDirectSound8_IDirectSound
1268 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1269 LPDIRECTSOUND iface,
1273 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1274 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1275 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1278 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1279 LPDIRECTSOUND iface)
1281 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1282 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1283 return InterlockedIncrement(&This->ref);
1286 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1287 LPDIRECTSOUND iface)
1289 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1291 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1292 ulReturn = InterlockedDecrement(&This->ref);
1293 if (ulReturn == 0) {
1294 IDirectSoundImpl_Release(This->pds);
1295 HeapFree(GetProcessHeap(),0,This);
1296 TRACE("(%p) released\n",This);
1301 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1302 LPDIRECTSOUND iface,
1303 LPCDSBUFFERDESC dsbd,
1304 LPLPDIRECTSOUNDBUFFER ppdsb,
1307 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1308 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1309 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1312 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1313 LPDIRECTSOUND iface,
1316 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1317 TRACE("(%p,%p)\n",This,lpDSCaps);
1318 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1321 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1322 LPDIRECTSOUND iface,
1323 LPDIRECTSOUNDBUFFER psb,
1324 LPLPDIRECTSOUNDBUFFER ppdsb)
1326 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1327 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1328 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1331 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1332 LPDIRECTSOUND iface,
1336 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1337 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1338 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1341 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1342 LPDIRECTSOUND iface)
1344 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1345 TRACE("(%p)\n", This);
1346 return IDirectSoundImpl_Compact(This->pds);
1349 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1350 LPDIRECTSOUND iface,
1351 LPDWORD lpdwSpeakerConfig)
1353 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1354 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1355 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1358 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1359 LPDIRECTSOUND iface,
1362 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1363 TRACE("(%p,0x%08lx)\n",This,config);
1364 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1367 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1368 LPDIRECTSOUND iface,
1371 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1372 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1373 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1376 static ICOM_VTABLE(IDirectSound) DirectSound8_DirectSound_Vtbl =
1378 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1379 IDirectSound8_IDirectSound_QueryInterface,
1380 IDirectSound8_IDirectSound_AddRef,
1381 IDirectSound8_IDirectSound_Release,
1382 IDirectSound8_IDirectSound_CreateSoundBuffer,
1383 IDirectSound8_IDirectSound_GetCaps,
1384 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1385 IDirectSound8_IDirectSound_SetCooperativeLevel,
1386 IDirectSound8_IDirectSound_Compact,
1387 IDirectSound8_IDirectSound_GetSpeakerConfig,
1388 IDirectSound8_IDirectSound_SetSpeakerConfig,
1389 IDirectSound8_IDirectSound_Initialize
1392 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1394 LPDIRECTSOUND * ppds)
1396 IDirectSound8_IDirectSound * pdsds;
1397 TRACE("(%p,%p)\n",pds,ppds);
1400 ERR("invalid parameter: ppds == NULL\n");
1401 return DSERR_INVALIDPARAM;
1405 ERR("invalid parameter: pds == NULL\n");
1407 return DSERR_INVALIDPARAM;
1410 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1411 if (pdsds == NULL) {
1412 WARN("out of memory\n");
1414 return DSERR_OUTOFMEMORY;
1417 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1421 IDirectSoundImpl_AddRef(pds);
1422 *ppds = (LPDIRECTSOUND)pdsds;
1427 /*******************************************************************************
1428 * IDirectSound8_IDirectSound8
1430 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1431 LPDIRECTSOUND8 iface,
1435 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1436 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1437 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1440 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1441 LPDIRECTSOUND8 iface)
1443 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1444 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1445 return InterlockedIncrement(&This->ref);
1448 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1449 LPDIRECTSOUND8 iface)
1451 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1453 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1454 ulReturn = InterlockedDecrement(&This->ref);
1455 if (ulReturn == 0) {
1456 IDirectSoundImpl_Release(This->pds);
1457 HeapFree(GetProcessHeap(),0,This);
1458 TRACE("(%p) released\n",This);
1463 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1464 LPDIRECTSOUND8 iface,
1465 LPCDSBUFFERDESC dsbd,
1466 LPLPDIRECTSOUNDBUFFER ppdsb,
1469 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1470 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1471 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1474 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1475 LPDIRECTSOUND8 iface,
1478 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1479 TRACE("(%p,%p)\n",This,lpDSCaps);
1480 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1483 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1484 LPDIRECTSOUND8 iface,
1485 LPDIRECTSOUNDBUFFER psb,
1486 LPLPDIRECTSOUNDBUFFER ppdsb)
1488 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1489 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1490 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1493 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1494 LPDIRECTSOUND8 iface,
1498 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1499 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1500 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1503 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1504 LPDIRECTSOUND8 iface)
1506 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1507 TRACE("(%p)\n", This);
1508 return IDirectSoundImpl_Compact(This->pds);
1511 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1512 LPDIRECTSOUND8 iface,
1513 LPDWORD lpdwSpeakerConfig)
1515 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1516 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1517 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1520 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1521 LPDIRECTSOUND8 iface,
1524 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1525 TRACE("(%p,0x%08lx)\n",This,config);
1526 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1529 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1530 LPDIRECTSOUND8 iface,
1533 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1534 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1535 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1538 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1539 LPDIRECTSOUND8 iface,
1540 LPDWORD pdwCertified)
1542 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1543 TRACE("(%p, %p)\n", This, pdwCertified);
1544 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1547 static ICOM_VTABLE(IDirectSound8) DirectSound8_DirectSound8_Vtbl =
1549 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1550 IDirectSound8_IDirectSound8_QueryInterface,
1551 IDirectSound8_IDirectSound8_AddRef,
1552 IDirectSound8_IDirectSound8_Release,
1553 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1554 IDirectSound8_IDirectSound8_GetCaps,
1555 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1556 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1557 IDirectSound8_IDirectSound8_Compact,
1558 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1559 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1560 IDirectSound8_IDirectSound8_Initialize,
1561 IDirectSound8_IDirectSound8_VerifyCertification
1564 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1566 LPDIRECTSOUND8 * ppds)
1568 IDirectSound8_IDirectSound8 * pdsds;
1569 TRACE("(%p,%p)\n",pds,ppds);
1572 ERR("invalid parameter: ppds == NULL\n");
1573 return DSERR_INVALIDPARAM;
1577 ERR("invalid parameter: pds == NULL\n");
1579 return DSERR_INVALIDPARAM;
1582 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1583 if (pdsds == NULL) {
1584 WARN("out of memory\n");
1586 return DSERR_OUTOFMEMORY;
1589 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1593 IDirectSoundImpl_AddRef(pds);
1594 *ppds = (LPDIRECTSOUND8)pdsds;
1599 HRESULT WINAPI DSOUND_Create(
1601 LPDIRECTSOUND *ppDS,
1602 IUnknown *pUnkOuter)
1607 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1609 if (pUnkOuter != NULL) {
1610 WARN("invalid parameter: pUnkOuter != NULL\n");
1611 return DSERR_INVALIDPARAM;
1615 WARN("invalid parameter: ppDS == NULL\n");
1616 return DSERR_INVALIDPARAM;
1619 /* Get dsound configuration */
1620 setup_dsound_options();
1622 /* Default device? */
1623 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1624 lpcGUID = &DSDEVID_DefaultPlayback;
1626 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1627 WARN("invalid parameter: lpcGUID\n");
1629 return DSERR_INVALIDPARAM;
1633 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1634 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1636 IDirectSound_IDirectSound_AddRef(*ppDS);
1638 WARN("IDirectSound_IDirectSound_Create failed\n");
1640 ERR("different dsound already opened (only support one sound card at a time now)\n");
1642 hr = DSERR_ALLOCATED;
1646 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1648 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1650 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1652 IDirectSound_IDirectSound_AddRef(*ppDS);
1654 dsound = (IDirectSoundImpl*)pDS;
1655 timeBeginPeriod(DS_TIME_RES);
1656 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1657 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1659 WARN("IDirectSound_IDirectSound_Create failed\n");
1660 IDirectSound8_Release(pDS);
1663 WARN("DSOUND_PrimaryCreate failed\n");
1664 IDirectSound8_Release(pDS);
1667 WARN("IDirectSoundImpl_Create failed\n");
1673 /*******************************************************************************
1674 * DirectSoundCreate (DSOUND.1)
1676 * Creates and initializes a DirectSound interface.
1679 * lpcGUID [I] Address of the GUID that identifies the sound device.
1680 * ppDS [O] Address of a variable to receive the interface pointer.
1681 * pUnkOuter [I] Must be NULL.
1685 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1686 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1688 HRESULT WINAPI DirectSoundCreate(
1690 LPDIRECTSOUND *ppDS,
1691 IUnknown *pUnkOuter)
1695 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1697 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1699 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1704 HRESULT WINAPI DSOUND_Create8(
1706 LPDIRECTSOUND8 *ppDS,
1707 IUnknown *pUnkOuter)
1712 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1714 if (pUnkOuter != NULL) {
1715 WARN("invalid parameter: pUnkOuter != NULL\n");
1716 return DSERR_INVALIDPARAM;
1720 WARN("invalid parameter: ppDS == NULL\n");
1721 return DSERR_INVALIDPARAM;
1724 /* Get dsound configuration */
1725 setup_dsound_options();
1727 /* Default device? */
1728 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1729 lpcGUID = &DSDEVID_DefaultPlayback;
1731 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1732 WARN("invalid parameter: lpcGUID\n");
1734 return DSERR_INVALIDPARAM;
1738 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1739 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1741 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1743 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1745 ERR("different dsound already opened (only support one sound card at a time now)\n");
1747 hr = DSERR_ALLOCATED;
1751 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1753 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1755 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1757 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1759 dsound = (IDirectSoundImpl*)pDS;
1760 timeBeginPeriod(DS_TIME_RES);
1761 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1762 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1764 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1765 IDirectSound8_Release(pDS);
1768 WARN("DSOUND_PrimaryCreate failed\n");
1769 IDirectSound8_Release(pDS);
1772 WARN("IDirectSoundImpl_Create failed\n");
1778 /*******************************************************************************
1779 * DirectSoundCreate8 (DSOUND.11)
1781 * Creates and initializes a DirectSound8 interface.
1784 * lpcGUID [I] Address of the GUID that identifies the sound device.
1785 * ppDS [O] Address of a variable to receive the interface pointer.
1786 * pUnkOuter [I] Must be NULL.
1790 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1791 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1793 HRESULT WINAPI DirectSoundCreate8(
1795 LPDIRECTSOUND8 *ppDS,
1796 IUnknown *pUnkOuter)
1800 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1802 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1804 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);