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_STICKYFOCUS)
121 FE(DSBCAPS_GLOBALFOCUS)
122 FE(DSBCAPS_GETCURRENTPOSITION2)
123 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
128 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
129 if ((flags[i].mask & xmask) == flags[i].mask)
130 DPRINTF("%s ",flags[i].name);
133 /*******************************************************************************
134 * IDirectSoundImpl_DirectSound
136 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
137 LPDIRECTSOUND8 iface,
141 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
142 FIXME("shouldn't be called directly\n");
143 return E_NOINTERFACE;
146 static HRESULT WINAPI DSOUND_QueryInterface(
147 LPDIRECTSOUND8 iface,
151 ICOM_THIS(IDirectSoundImpl,iface);
152 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
155 WARN("invalid parameter\n");
159 if (IsEqualIID(riid, &IID_IUnknown)) {
160 if (!This->pUnknown) {
161 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
162 if (!This->pUnknown) {
163 WARN("IDirectSound_IUnknown_Create() failed\n");
165 return E_NOINTERFACE;
168 IDirectSound_IUnknown_AddRef(This->pUnknown);
169 *ppobj = This->pUnknown;
171 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
173 IDirectSound_IDirectSound_Create(iface, &This->pDS);
175 WARN("IDirectSound_IDirectSound_Create() failed\n");
177 return E_NOINTERFACE;
180 IDirectSound_IDirectSound_AddRef(This->pDS);
186 WARN("Unknown IID %s\n",debugstr_guid(riid));
187 return E_NOINTERFACE;
190 static HRESULT WINAPI DSOUND_QueryInterface8(
191 LPDIRECTSOUND8 iface,
195 ICOM_THIS(IDirectSoundImpl,iface);
196 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
199 WARN("invalid parameter\n");
203 if (IsEqualIID(riid, &IID_IUnknown)) {
204 if (!This->pUnknown) {
205 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
206 if (!This->pUnknown) {
207 WARN("IDirectSound8_IUnknown_Create() failed\n");
209 return E_NOINTERFACE;
212 IDirectSound8_IUnknown_AddRef(This->pUnknown);
213 *ppobj = This->pUnknown;
215 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
217 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
219 WARN("IDirectSound8_IDirectSound_Create() failed\n");
221 return E_NOINTERFACE;
224 IDirectSound8_IDirectSound_AddRef(This->pDS);
227 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
229 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
231 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
233 return E_NOINTERFACE;
236 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
242 WARN("Unknown IID %s\n",debugstr_guid(riid));
243 return E_NOINTERFACE;
246 static ULONG WINAPI IDirectSoundImpl_AddRef(
247 LPDIRECTSOUND8 iface)
249 ICOM_THIS(IDirectSoundImpl,iface);
250 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
252 return InterlockedIncrement(&This->ref);
255 static ULONG WINAPI IDirectSoundImpl_Release(
256 LPDIRECTSOUND8 iface)
258 ICOM_THIS(IDirectSoundImpl,iface);
260 TRACE("(%p) ref was %ld, thread is %04lx\n",
261 This, This->ref, GetCurrentThreadId());
263 ref = InterlockedDecrement(&This->ref);
268 timeKillEvent(This->timerID);
269 timeEndPeriod(DS_TIME_RES);
270 /* wait for timer to expire */
271 Sleep(DS_TIME_RES+1);
273 /* The sleep above should have allowed the timer process to expire
274 * but try to grab the lock just in case. Can't hold lock because
275 * IDirectSoundBufferImpl_Destroy also grabs the lock */
276 RtlAcquireResourceShared(&(This->lock), TRUE);
277 RtlReleaseResource(&(This->lock));
279 /* It is allowed to release this object even when buffers are playing */
281 WARN("%d secondary buffers not released\n", This->nrofbuffers);
282 for( i=0;i<This->nrofbuffers;i++)
283 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
287 WARN("primary buffer not released\n");
288 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
291 hres = DSOUND_PrimaryDestroy(This);
293 WARN("DSOUND_PrimaryDestroy failed\n");
296 IDsDriver_Close(This->driver);
298 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
299 waveOutClose(This->hwo);
302 IDsDriver_Release(This->driver);
304 RtlDeleteResource(&This->lock);
305 DeleteCriticalSection(&This->mixlock);
306 HeapFree(GetProcessHeap(),0,This);
308 TRACE("(%p) released\n",This);
314 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
315 LPDIRECTSOUND8 iface,
316 LPCDSBUFFERDESC dsbd,
317 LPLPDIRECTSOUNDBUFFER ppdsb,
320 ICOM_THIS(IDirectSoundImpl,iface);
321 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
322 FIXME("shouldn't be called directly\n");
323 return DSERR_GENERIC;
326 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
327 LPDIRECTSOUND8 iface,
328 LPCDSBUFFERDESC dsbd,
329 LPLPDIRECTSOUNDBUFFER ppdsb,
333 ICOM_THIS(IDirectSoundImpl,iface);
334 HRESULT hres = DS_OK;
335 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
338 WARN("invalid parameter: This == NULL\n");
339 return DSERR_INVALIDPARAM;
342 if (This->initialized == FALSE) {
343 WARN("not initialized\n");
344 return DSERR_UNINITIALIZED;
348 WARN("invalid parameter: dsbd == NULL\n");
349 return DSERR_INVALIDPARAM;
352 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
353 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
354 WARN("invalid parameter: dsbd\n");
355 return DSERR_INVALIDPARAM;
359 WARN("invalid parameter: ppdsb == NULL\n");
360 return DSERR_INVALIDPARAM;
363 if (TRACE_ON(dsound)) {
364 TRACE("(structsize=%ld)\n",dsbd->dwSize);
365 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
366 _dump_DSBCAPS(dsbd->dwFlags);
368 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
369 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
372 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
373 if (dsbd->lpwfxFormat != NULL) {
374 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
376 return DSERR_INVALIDPARAM;
380 WARN("Primary Buffer already created\n");
381 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
382 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
385 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
387 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
388 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
390 WARN("PrimaryBufferImpl_Create failed\n");
393 IDirectSoundBufferImpl * dsb;
395 if (dsbd->lpwfxFormat == NULL) {
396 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
397 "secondary buffer\n");
398 return DSERR_INVALIDPARAM;
401 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
402 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
403 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
404 dsbd->lpwfxFormat->nSamplesPerSec,
405 dsbd->lpwfxFormat->nAvgBytesPerSec,
406 dsbd->lpwfxFormat->nBlockAlign,
407 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
409 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
410 WARN("invalid parameter: 3D buffer format must be mono\n");
411 return DSERR_INVALIDPARAM;
414 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
416 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
418 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
419 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
421 WARN("SecondaryBufferImpl_Create failed\n");
423 WARN("IDirectSoundBufferImpl_Create failed\n");
429 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
430 LPDIRECTSOUND8 iface,
433 ICOM_THIS(IDirectSoundImpl,iface);
434 TRACE("(%p,%p)\n",This,lpDSCaps);
437 WARN("invalid parameter: This == NULL\n");
438 return DSERR_INVALIDPARAM;
441 if (This->initialized == FALSE) {
442 WARN("not initialized\n");
443 return DSERR_UNINITIALIZED;
446 if (lpDSCaps == NULL) {
447 WARN("invalid parameter: lpDSCaps = NULL\n");
448 return DSERR_INVALIDPARAM;
451 /* check if there is enough room */
452 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
453 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
454 lpDSCaps->dwSize, sizeof(*lpDSCaps));
455 return DSERR_INVALIDPARAM;
458 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
459 if (TRACE_ON(dsound)) {
460 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
461 _dump_DSCAPS(lpDSCaps->dwFlags);
464 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
465 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
466 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
467 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
468 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
469 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
470 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
471 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
472 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
473 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
474 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
475 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
476 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
477 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
478 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
479 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
480 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
481 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
483 /* driver doesn't have these */
484 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
485 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
490 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
491 LPDIRECTSOUND8 iface,
492 LPDIRECTSOUNDBUFFER psb,
493 LPLPDIRECTSOUNDBUFFER ppdsb)
495 IDirectSoundBufferImpl* pdsb;
496 IDirectSoundBufferImpl* dsb;
497 HRESULT hres = DS_OK;
499 ICOM_THIS(IDirectSoundImpl,iface);
501 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
504 WARN("invalid parameter: This == NULL\n");
505 return DSERR_INVALIDPARAM;
508 if (This->initialized == FALSE) {
509 WARN("not initialized\n");
510 return DSERR_UNINITIALIZED;
514 WARN("invalid parameter: psb == NULL\n");
515 return DSERR_INVALIDPARAM;
519 WARN("invalid parameter: ppdsb == NULL\n");
520 return DSERR_INVALIDPARAM;
523 /* FIXME: hack to make sure we have a secondary buffer */
524 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
525 WARN("trying to duplicate primary buffer\n");
527 return DSERR_INVALIDCALL;
530 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
532 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
535 WARN("out of memory\n");
537 return DSERR_OUTOFMEMORY;
540 memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
543 TRACE("duplicating hardware buffer\n");
545 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
547 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
549 /* allocate buffer */
550 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
551 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
552 if (dsb->buffer == NULL) {
553 WARN("out of memory\n");
554 HeapFree(GetProcessHeap(),0,dsb);
556 return DSERR_OUTOFMEMORY;
559 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
560 if (dsb->buffer->memory == NULL) {
561 WARN("out of memory\n");
562 HeapFree(GetProcessHeap(),0,dsb->buffer);
563 HeapFree(GetProcessHeap(),0,dsb);
565 return DSERR_OUTOFMEMORY;
567 dsb->buffer->ref = 1;
569 /* FIXME: copy buffer ? */
578 dsb->state = STATE_STOPPED;
583 dsb->iks = NULL; /* FIXME? */
586 /* variable sized struct so calculate size based on format */
587 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
589 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
590 if (dsb->pwfx == NULL) {
591 WARN("out of memory\n");
592 HeapFree(GetProcessHeap(),0,dsb->buffer);
593 HeapFree(GetProcessHeap(),0,dsb);
595 return DSERR_OUTOFMEMORY;
598 memcpy(dsb->pwfx, pdsb->pwfx, size);
600 InitializeCriticalSection(&(dsb->lock));
601 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
602 /* register buffer */
603 RtlAcquireResourceExclusive(&(This->lock), TRUE);
605 IDirectSoundBufferImpl **newbuffers;
607 newbuffers = HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
609 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
612 This->buffers = newbuffers;
613 This->buffers[This->nrofbuffers] = dsb;
615 TRACE("buffer count is now %d\n", This->nrofbuffers);
617 ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
618 IDirectSoundBuffer8_Release(psb);
619 DeleteCriticalSection(&(dsb->lock));
620 RtlReleaseResource(&(This->lock));
621 HeapFree(GetProcessHeap(),0,dsb->buffer);
622 HeapFree(GetProcessHeap(),0,dsb->pwfx);
623 HeapFree(GetProcessHeap(),0,dsb);
625 return DSERR_OUTOFMEMORY;
628 RtlReleaseResource(&(This->lock));
629 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
631 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
632 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
634 WARN("SecondaryBufferImpl_Create failed\n");
639 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
640 LPDIRECTSOUND8 iface,
644 ICOM_THIS(IDirectSoundImpl,iface);
645 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
647 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
648 FIXME("level=%s not fully supported\n",
649 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
651 This->priolevel = level;
655 static HRESULT WINAPI IDirectSoundImpl_Compact(
656 LPDIRECTSOUND8 iface)
658 ICOM_THIS(IDirectSoundImpl,iface);
659 TRACE("(%p)\n",This);
661 if (This->initialized == FALSE) {
662 WARN("not initialized\n");
663 return DSERR_UNINITIALIZED;
666 if (This->priolevel != DSSCL_PRIORITY) {
667 WARN("incorrect priority level\n");
668 return DSERR_PRIOLEVELNEEDED;
674 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
675 LPDIRECTSOUND8 iface,
676 LPDWORD lpdwSpeakerConfig)
678 ICOM_THIS(IDirectSoundImpl,iface);
679 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
681 if (This->initialized == FALSE) {
682 WARN("not initialized\n");
683 return DSERR_UNINITIALIZED;
686 if (lpdwSpeakerConfig == NULL) {
687 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
688 return DSERR_INVALIDPARAM;
691 WARN("not fully functional\n");
692 *lpdwSpeakerConfig = This->speaker_config;
696 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
697 LPDIRECTSOUND8 iface,
700 ICOM_THIS(IDirectSoundImpl,iface);
701 TRACE("(%p,0x%08lx)\n",This,config);
703 if (This->initialized == FALSE) {
704 WARN("not initialized\n");
705 return DSERR_UNINITIALIZED;
708 This->speaker_config = config;
709 WARN("not fully functional\n");
713 static HRESULT WINAPI IDirectSoundImpl_Initialize(
714 LPDIRECTSOUND8 iface,
717 ICOM_THIS(IDirectSoundImpl,iface);
718 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
720 This->initialized = TRUE;
725 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
726 LPDIRECTSOUND8 iface,
727 LPDWORD pdwCertified)
729 ICOM_THIS(IDirectSoundImpl,iface);
730 TRACE("(%p, %p)\n",This,pdwCertified);
732 if (This->initialized == FALSE) {
733 WARN("not initialized\n");
734 return DSERR_UNINITIALIZED;
737 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
738 *pdwCertified = DS_CERTIFIED;
740 *pdwCertified = DS_UNCERTIFIED;
744 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
746 IDirectSoundImpl_QueryInterface,
747 IDirectSoundImpl_AddRef,
748 IDirectSoundImpl_Release,
749 IDirectSoundImpl_CreateSoundBuffer,
750 IDirectSoundImpl_GetCaps,
751 IDirectSoundImpl_DuplicateSoundBuffer,
752 IDirectSoundImpl_SetCooperativeLevel,
753 IDirectSoundImpl_Compact,
754 IDirectSoundImpl_GetSpeakerConfig,
755 IDirectSoundImpl_SetSpeakerConfig,
756 IDirectSoundImpl_Initialize,
757 IDirectSoundImpl_VerifyCertification
760 HRESULT WINAPI IDirectSoundImpl_Create(
762 LPDIRECTSOUND8 * ppDS)
765 PIDSDRIVER drv = NULL;
766 IDirectSoundImpl* pDS;
768 BOOLEAN found = FALSE;
769 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
771 /* Enumerate WINMM audio devices and find the one we want */
772 wodn = waveOutGetNumDevs();
776 return DSERR_NODRIVER;
779 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
781 for (wod=0; wod<wodn; wod++) {
782 if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
788 if (found == FALSE) {
789 WARN("No device found matching given ID!\n");
791 return DSERR_NODRIVER;
794 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
795 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
797 /* Disable the direct sound driver to force emulation if requested. */
798 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
801 /* Allocate memory */
802 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
804 WARN("out of memory\n");
806 return DSERR_OUTOFMEMORY;
809 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
813 pDS->priolevel = DSSCL_NORMAL;
819 pDS->state = STATE_STOPPED;
820 pDS->nrofbuffers = 0;
823 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
824 pDS->initialized = FALSE;
826 /* 3D listener initial parameters */
827 pDS->listener = NULL;
828 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
829 pDS->ds3dl.vPosition.x = 0.0;
830 pDS->ds3dl.vPosition.y = 0.0;
831 pDS->ds3dl.vPosition.z = 0.0;
832 pDS->ds3dl.vVelocity.x = 0.0;
833 pDS->ds3dl.vVelocity.y = 0.0;
834 pDS->ds3dl.vVelocity.z = 0.0;
835 pDS->ds3dl.vOrientFront.x = 0.0;
836 pDS->ds3dl.vOrientFront.y = 0.0;
837 pDS->ds3dl.vOrientFront.z = 1.0;
838 pDS->ds3dl.vOrientTop.x = 0.0;
839 pDS->ds3dl.vOrientTop.y = 1.0;
840 pDS->ds3dl.vOrientTop.z = 0.0;
841 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
842 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
843 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
845 pDS->prebuf = ds_snd_queue_max;
846 pDS->guid = *lpcGUID;
848 /* Get driver description */
850 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
852 WARN("IDsDriver_GetDriverDesc failed\n");
853 HeapFree(GetProcessHeap(),0,pDS);
858 /* if no DirectSound interface available, use WINMM API instead */
859 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
862 pDS->drvdesc.dnDevNode = wod;
864 /* Set default wave format (may need it for waveOutOpen) */
865 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
866 if (pDS->pwfx == NULL) {
867 WARN("out of memory\n");
868 HeapFree(GetProcessHeap(),0,pDS);
870 return DSERR_OUTOFMEMORY;
873 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
874 /* We rely on the sound driver to return the actual sound format of
875 * the device if it does not support 22050x8x2 and is given the
876 * WAVE_DIRECTSOUND flag.
878 pDS->pwfx->nSamplesPerSec = 22050;
879 pDS->pwfx->wBitsPerSample = 8;
880 pDS->pwfx->nChannels = 2;
881 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
882 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
883 pDS->pwfx->cbSize = 0;
885 /* If the driver requests being opened through MMSYSTEM
886 * (which is recommended by the DDK), it is supposed to happen
887 * before the DirectSound interface is opened */
888 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
890 DWORD flags = CALLBACK_FUNCTION;
892 /* disable direct sound if requested */
893 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
894 flags |= WAVE_DIRECTSOUND;
896 err = mmErr(waveOutOpen(&(pDS->hwo),
897 pDS->drvdesc.dnDevNode, pDS->pwfx,
898 (DWORD)DSOUND_callback, (DWORD)pDS,
901 WARN("waveOutOpen failed\n");
902 HeapFree(GetProcessHeap(),0,pDS);
909 err = IDsDriver_Open(drv);
911 WARN("IDsDriver_Open failed\n");
912 HeapFree(GetProcessHeap(),0,pDS);
917 /* the driver is now open, so it's now allowed to call GetCaps */
918 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
920 WARN("IDsDriver_GetCaps failed\n");
921 HeapFree(GetProcessHeap(),0,pDS);
927 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
929 WARN("waveOutGetDevCaps failed\n");
930 HeapFree(GetProcessHeap(),0,pDS);
934 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
935 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
936 (woc.dwFormats & WAVE_FORMAT_2M08) ||
937 (woc.dwFormats & WAVE_FORMAT_4M08) ||
938 (woc.dwFormats & WAVE_FORMAT_48M08) ||
939 (woc.dwFormats & WAVE_FORMAT_96M08)) {
940 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
941 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
943 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
944 (woc.dwFormats & WAVE_FORMAT_2M16) ||
945 (woc.dwFormats & WAVE_FORMAT_4M16) ||
946 (woc.dwFormats & WAVE_FORMAT_48M16) ||
947 (woc.dwFormats & WAVE_FORMAT_96M16)) {
948 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
949 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
951 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
952 (woc.dwFormats & WAVE_FORMAT_2S08) ||
953 (woc.dwFormats & WAVE_FORMAT_4S08) ||
954 (woc.dwFormats & WAVE_FORMAT_48S08) ||
955 (woc.dwFormats & WAVE_FORMAT_96S08)) {
956 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
957 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
959 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
960 (woc.dwFormats & WAVE_FORMAT_2S16) ||
961 (woc.dwFormats & WAVE_FORMAT_4S16) ||
962 (woc.dwFormats & WAVE_FORMAT_48S16) ||
963 (woc.dwFormats & WAVE_FORMAT_96S16)) {
964 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
965 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
968 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
969 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
970 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
971 pDS->drvcaps.dwPrimaryBuffers = 1;
974 InitializeCriticalSection(&(pDS->mixlock));
975 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
976 RtlInitializeResource(&(pDS->lock));
978 *ppDS = (LPDIRECTSOUND8)pDS;
982 /*******************************************************************************
983 * IDirectSound_IUnknown
985 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
990 ICOM_THIS(IDirectSound_IUnknown,iface);
991 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
992 return DSOUND_QueryInterface(This->pds, riid, ppobj);
995 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
998 ICOM_THIS(IDirectSound_IUnknown,iface);
999 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1000 return InterlockedIncrement(&This->ref);
1003 static ULONG WINAPI IDirectSound_IUnknown_Release(
1006 ICOM_THIS(IDirectSound_IUnknown,iface);
1008 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1009 ulReturn = InterlockedDecrement(&This->ref);
1010 if (ulReturn == 0) {
1011 IDirectSoundImpl_Release(This->pds);
1012 HeapFree(GetProcessHeap(),0,This);
1013 TRACE("(%p) released\n",This);
1018 static IUnknownVtbl DirectSound_Unknown_Vtbl =
1020 IDirectSound_IUnknown_QueryInterface,
1021 IDirectSound_IUnknown_AddRef,
1022 IDirectSound_IUnknown_Release
1025 HRESULT WINAPI IDirectSound_IUnknown_Create(
1029 IDirectSound_IUnknown * pdsunk;
1030 TRACE("(%p,%p)\n",pds,ppunk);
1032 if (ppunk == NULL) {
1033 ERR("invalid parameter: ppunk == NULL\n");
1034 return DSERR_INVALIDPARAM;
1038 ERR("invalid parameter: pds == NULL\n");
1040 return DSERR_INVALIDPARAM;
1043 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1044 if (pdsunk == NULL) {
1045 WARN("out of memory\n");
1047 return DSERR_OUTOFMEMORY;
1050 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1054 IDirectSoundImpl_AddRef(pds);
1055 *ppunk = (LPUNKNOWN)pdsunk;
1060 /*******************************************************************************
1061 * IDirectSound_IDirectSound
1063 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1064 LPDIRECTSOUND iface,
1068 ICOM_THIS(IDirectSound_IDirectSound,iface);
1069 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1070 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1073 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1074 LPDIRECTSOUND iface)
1076 ICOM_THIS(IDirectSound_IDirectSound,iface);
1077 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1078 return InterlockedIncrement(&This->ref);
1081 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1082 LPDIRECTSOUND iface)
1084 ICOM_THIS(IDirectSound_IDirectSound,iface);
1086 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1087 ulReturn = InterlockedDecrement(&This->ref);
1088 if (ulReturn == 0) {
1089 IDirectSoundImpl_Release(This->pds);
1090 HeapFree(GetProcessHeap(),0,This);
1091 TRACE("(%p) released\n",This);
1096 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1097 LPDIRECTSOUND iface,
1098 LPCDSBUFFERDESC dsbd,
1099 LPLPDIRECTSOUNDBUFFER ppdsb,
1102 ICOM_THIS(IDirectSound_IDirectSound,iface);
1103 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1104 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1107 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1108 LPDIRECTSOUND iface,
1111 ICOM_THIS(IDirectSound_IDirectSound,iface);
1112 TRACE("(%p,%p)\n",This,lpDSCaps);
1113 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1116 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1117 LPDIRECTSOUND iface,
1118 LPDIRECTSOUNDBUFFER psb,
1119 LPLPDIRECTSOUNDBUFFER ppdsb)
1121 ICOM_THIS(IDirectSound_IDirectSound,iface);
1122 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1123 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1126 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1127 LPDIRECTSOUND iface,
1131 ICOM_THIS(IDirectSound_IDirectSound,iface);
1132 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1133 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1136 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1137 LPDIRECTSOUND iface)
1139 ICOM_THIS(IDirectSound_IDirectSound,iface);
1140 TRACE("(%p)\n", This);
1141 return IDirectSoundImpl_Compact(This->pds);
1144 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1145 LPDIRECTSOUND iface,
1146 LPDWORD lpdwSpeakerConfig)
1148 ICOM_THIS(IDirectSound_IDirectSound,iface);
1149 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1150 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1153 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1154 LPDIRECTSOUND iface,
1157 ICOM_THIS(IDirectSound_IDirectSound,iface);
1158 TRACE("(%p,0x%08lx)\n",This,config);
1159 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1162 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1163 LPDIRECTSOUND iface,
1166 ICOM_THIS(IDirectSound_IDirectSound,iface);
1167 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1168 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1171 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1173 IDirectSound_IDirectSound_QueryInterface,
1174 IDirectSound_IDirectSound_AddRef,
1175 IDirectSound_IDirectSound_Release,
1176 IDirectSound_IDirectSound_CreateSoundBuffer,
1177 IDirectSound_IDirectSound_GetCaps,
1178 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1179 IDirectSound_IDirectSound_SetCooperativeLevel,
1180 IDirectSound_IDirectSound_Compact,
1181 IDirectSound_IDirectSound_GetSpeakerConfig,
1182 IDirectSound_IDirectSound_SetSpeakerConfig,
1183 IDirectSound_IDirectSound_Initialize
1186 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1188 LPDIRECTSOUND * ppds)
1190 IDirectSound_IDirectSound * pdsds;
1191 TRACE("(%p,%p)\n",pds,ppds);
1194 ERR("invalid parameter: ppds == NULL\n");
1195 return DSERR_INVALIDPARAM;
1199 ERR("invalid parameter: pds == NULL\n");
1201 return DSERR_INVALIDPARAM;
1204 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1205 if (pdsds == NULL) {
1206 WARN("out of memory\n");
1208 return DSERR_OUTOFMEMORY;
1211 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1215 IDirectSoundImpl_AddRef(pds);
1216 *ppds = (LPDIRECTSOUND)pdsds;
1221 /*******************************************************************************
1222 * IDirectSound8_IUnknown
1224 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1229 ICOM_THIS(IDirectSound_IUnknown,iface);
1230 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1231 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1234 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1237 ICOM_THIS(IDirectSound_IUnknown,iface);
1238 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1239 return InterlockedIncrement(&This->ref);
1242 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1245 ICOM_THIS(IDirectSound_IUnknown,iface);
1247 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1248 ulReturn = InterlockedDecrement(&This->ref);
1249 if (ulReturn == 0) {
1250 IDirectSoundImpl_Release(This->pds);
1251 HeapFree(GetProcessHeap(),0,This);
1252 TRACE("(%p) released\n",This);
1257 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1259 IDirectSound8_IUnknown_QueryInterface,
1260 IDirectSound8_IUnknown_AddRef,
1261 IDirectSound8_IUnknown_Release
1264 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1268 IDirectSound8_IUnknown * pdsunk;
1269 TRACE("(%p,%p)\n",pds,ppunk);
1271 if (ppunk == NULL) {
1272 ERR("invalid parameter: ppunk == NULL\n");
1273 return DSERR_INVALIDPARAM;
1277 ERR("invalid parameter: pds == NULL\n");
1279 return DSERR_INVALIDPARAM;
1282 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1283 if (pdsunk == NULL) {
1284 WARN("out of memory\n");
1286 return DSERR_OUTOFMEMORY;
1289 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1293 IDirectSoundImpl_AddRef(pds);
1294 *ppunk = (LPUNKNOWN)pdsunk;
1299 /*******************************************************************************
1300 * IDirectSound8_IDirectSound
1302 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1303 LPDIRECTSOUND iface,
1307 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1308 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1309 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1312 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1313 LPDIRECTSOUND iface)
1315 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1316 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1317 return InterlockedIncrement(&This->ref);
1320 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1321 LPDIRECTSOUND iface)
1323 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1325 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1326 ulReturn = InterlockedDecrement(&This->ref);
1327 if (ulReturn == 0) {
1328 IDirectSoundImpl_Release(This->pds);
1329 HeapFree(GetProcessHeap(),0,This);
1330 TRACE("(%p) released\n",This);
1335 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1336 LPDIRECTSOUND iface,
1337 LPCDSBUFFERDESC dsbd,
1338 LPLPDIRECTSOUNDBUFFER ppdsb,
1341 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1342 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1343 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1346 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1347 LPDIRECTSOUND iface,
1350 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1351 TRACE("(%p,%p)\n",This,lpDSCaps);
1352 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1355 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1356 LPDIRECTSOUND iface,
1357 LPDIRECTSOUNDBUFFER psb,
1358 LPLPDIRECTSOUNDBUFFER ppdsb)
1360 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1361 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1362 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1365 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1366 LPDIRECTSOUND iface,
1370 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1371 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1372 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1375 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1376 LPDIRECTSOUND iface)
1378 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1379 TRACE("(%p)\n", This);
1380 return IDirectSoundImpl_Compact(This->pds);
1383 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1384 LPDIRECTSOUND iface,
1385 LPDWORD lpdwSpeakerConfig)
1387 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1388 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1389 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1392 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1393 LPDIRECTSOUND iface,
1396 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1397 TRACE("(%p,0x%08lx)\n",This,config);
1398 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1401 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1402 LPDIRECTSOUND iface,
1405 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1406 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1407 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1410 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1412 IDirectSound8_IDirectSound_QueryInterface,
1413 IDirectSound8_IDirectSound_AddRef,
1414 IDirectSound8_IDirectSound_Release,
1415 IDirectSound8_IDirectSound_CreateSoundBuffer,
1416 IDirectSound8_IDirectSound_GetCaps,
1417 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1418 IDirectSound8_IDirectSound_SetCooperativeLevel,
1419 IDirectSound8_IDirectSound_Compact,
1420 IDirectSound8_IDirectSound_GetSpeakerConfig,
1421 IDirectSound8_IDirectSound_SetSpeakerConfig,
1422 IDirectSound8_IDirectSound_Initialize
1425 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1427 LPDIRECTSOUND * ppds)
1429 IDirectSound8_IDirectSound * pdsds;
1430 TRACE("(%p,%p)\n",pds,ppds);
1433 ERR("invalid parameter: ppds == NULL\n");
1434 return DSERR_INVALIDPARAM;
1438 ERR("invalid parameter: pds == NULL\n");
1440 return DSERR_INVALIDPARAM;
1443 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1444 if (pdsds == NULL) {
1445 WARN("out of memory\n");
1447 return DSERR_OUTOFMEMORY;
1450 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1454 IDirectSoundImpl_AddRef(pds);
1455 *ppds = (LPDIRECTSOUND)pdsds;
1460 /*******************************************************************************
1461 * IDirectSound8_IDirectSound8
1463 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1464 LPDIRECTSOUND8 iface,
1468 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1469 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1470 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1473 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1474 LPDIRECTSOUND8 iface)
1476 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1477 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1478 return InterlockedIncrement(&This->ref);
1481 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1482 LPDIRECTSOUND8 iface)
1484 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1486 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1487 ulReturn = InterlockedDecrement(&This->ref);
1488 if (ulReturn == 0) {
1489 IDirectSoundImpl_Release(This->pds);
1490 HeapFree(GetProcessHeap(),0,This);
1491 TRACE("(%p) released\n",This);
1496 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1497 LPDIRECTSOUND8 iface,
1498 LPCDSBUFFERDESC dsbd,
1499 LPLPDIRECTSOUNDBUFFER ppdsb,
1502 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1503 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1504 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1507 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1508 LPDIRECTSOUND8 iface,
1511 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1512 TRACE("(%p,%p)\n",This,lpDSCaps);
1513 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1516 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1517 LPDIRECTSOUND8 iface,
1518 LPDIRECTSOUNDBUFFER psb,
1519 LPLPDIRECTSOUNDBUFFER ppdsb)
1521 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1522 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1523 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1526 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1527 LPDIRECTSOUND8 iface,
1531 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1532 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1533 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1536 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1537 LPDIRECTSOUND8 iface)
1539 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1540 TRACE("(%p)\n", This);
1541 return IDirectSoundImpl_Compact(This->pds);
1544 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1545 LPDIRECTSOUND8 iface,
1546 LPDWORD lpdwSpeakerConfig)
1548 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1549 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1550 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1553 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1554 LPDIRECTSOUND8 iface,
1557 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1558 TRACE("(%p,0x%08lx)\n",This,config);
1559 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1562 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1563 LPDIRECTSOUND8 iface,
1566 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1567 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1568 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1571 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1572 LPDIRECTSOUND8 iface,
1573 LPDWORD pdwCertified)
1575 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1576 TRACE("(%p, %p)\n", This, pdwCertified);
1577 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1580 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1582 IDirectSound8_IDirectSound8_QueryInterface,
1583 IDirectSound8_IDirectSound8_AddRef,
1584 IDirectSound8_IDirectSound8_Release,
1585 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1586 IDirectSound8_IDirectSound8_GetCaps,
1587 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1588 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1589 IDirectSound8_IDirectSound8_Compact,
1590 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1591 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1592 IDirectSound8_IDirectSound8_Initialize,
1593 IDirectSound8_IDirectSound8_VerifyCertification
1596 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1598 LPDIRECTSOUND8 * ppds)
1600 IDirectSound8_IDirectSound8 * pdsds;
1601 TRACE("(%p,%p)\n",pds,ppds);
1604 ERR("invalid parameter: ppds == NULL\n");
1605 return DSERR_INVALIDPARAM;
1609 ERR("invalid parameter: pds == NULL\n");
1611 return DSERR_INVALIDPARAM;
1614 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1615 if (pdsds == NULL) {
1616 WARN("out of memory\n");
1618 return DSERR_OUTOFMEMORY;
1621 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1625 IDirectSoundImpl_AddRef(pds);
1626 *ppds = (LPDIRECTSOUND8)pdsds;
1631 HRESULT WINAPI DSOUND_Create(
1633 LPDIRECTSOUND *ppDS,
1634 IUnknown *pUnkOuter)
1639 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1641 if (pUnkOuter != NULL) {
1642 WARN("invalid parameter: pUnkOuter != NULL\n");
1643 return DSERR_INVALIDPARAM;
1647 WARN("invalid parameter: ppDS == NULL\n");
1648 return DSERR_INVALIDPARAM;
1651 /* Get dsound configuration */
1652 setup_dsound_options();
1654 /* Default device? */
1655 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1656 lpcGUID = &DSDEVID_DefaultPlayback;
1658 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1659 WARN("invalid parameter: lpcGUID\n");
1661 return DSERR_INVALIDPARAM;
1665 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1666 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1668 IDirectSound_IDirectSound_AddRef(*ppDS);
1670 WARN("IDirectSound_IDirectSound_Create failed\n");
1672 ERR("different dsound already opened (only support one sound card at a time now)\n");
1674 hr = DSERR_ALLOCATED;
1678 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1680 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1682 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1684 IDirectSound_IDirectSound_AddRef(*ppDS);
1686 dsound = (IDirectSoundImpl*)pDS;
1687 timeBeginPeriod(DS_TIME_RES);
1688 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1689 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1691 WARN("IDirectSound_IDirectSound_Create failed\n");
1692 IDirectSound8_Release(pDS);
1695 WARN("DSOUND_PrimaryCreate failed\n");
1696 IDirectSound8_Release(pDS);
1699 WARN("IDirectSoundImpl_Create failed\n");
1705 /*******************************************************************************
1706 * DirectSoundCreate (DSOUND.1)
1708 * Creates and initializes a DirectSound interface.
1711 * lpcGUID [I] Address of the GUID that identifies the sound device.
1712 * ppDS [O] Address of a variable to receive the interface pointer.
1713 * pUnkOuter [I] Must be NULL.
1717 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1718 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1720 HRESULT WINAPI DirectSoundCreate(
1722 LPDIRECTSOUND *ppDS,
1723 IUnknown *pUnkOuter)
1727 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1729 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1731 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1736 HRESULT WINAPI DSOUND_Create8(
1738 LPDIRECTSOUND8 *ppDS,
1739 IUnknown *pUnkOuter)
1744 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1746 if (pUnkOuter != NULL) {
1747 WARN("invalid parameter: pUnkOuter != NULL\n");
1748 return DSERR_INVALIDPARAM;
1752 WARN("invalid parameter: ppDS == NULL\n");
1753 return DSERR_INVALIDPARAM;
1756 /* Get dsound configuration */
1757 setup_dsound_options();
1759 /* Default device? */
1760 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1761 lpcGUID = &DSDEVID_DefaultPlayback;
1763 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1764 WARN("invalid parameter: lpcGUID\n");
1766 return DSERR_INVALIDPARAM;
1770 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1771 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1773 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1775 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1777 ERR("different dsound already opened (only support one sound card at a time now)\n");
1779 hr = DSERR_ALLOCATED;
1783 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1785 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1787 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1789 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1791 dsound = (IDirectSoundImpl*)pDS;
1792 timeBeginPeriod(DS_TIME_RES);
1793 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1794 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1796 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1797 IDirectSound8_Release(pDS);
1800 WARN("DSOUND_PrimaryCreate failed\n");
1801 IDirectSound8_Release(pDS);
1804 WARN("IDirectSoundImpl_Create failed\n");
1810 /*******************************************************************************
1811 * DirectSoundCreate8 (DSOUND.11)
1813 * Creates and initializes a DirectSound8 interface.
1816 * lpcGUID [I] Address of the GUID that identifies the sound device.
1817 * ppDS [O] Address of a variable to receive the interface pointer.
1818 * pUnkOuter [I] Must be NULL.
1822 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1823 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1825 HRESULT WINAPI DirectSoundCreate8(
1827 LPDIRECTSOUND8 *ppDS,
1828 IUnknown *pUnkOuter)
1832 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1834 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1836 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);