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
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
34 #include "wine/debug.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
41 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
42 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
43 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
44 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
45 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
47 static const char * dumpCooperativeLevel(DWORD level)
49 static char unknown[32];
50 #define LE(x) case x: return #x
55 LE(DSSCL_WRITEPRIMARY);
58 sprintf(unknown, "Unknown(%08lx)", level);
62 static void _dump_DSCAPS(DWORD xmask) {
67 #define FE(x) { x, #x },
68 FE(DSCAPS_PRIMARYMONO)
69 FE(DSCAPS_PRIMARYSTEREO)
70 FE(DSCAPS_PRIMARY8BIT)
71 FE(DSCAPS_PRIMARY16BIT)
72 FE(DSCAPS_CONTINUOUSRATE)
75 FE(DSCAPS_SECONDARYMONO)
76 FE(DSCAPS_SECONDARYSTEREO)
77 FE(DSCAPS_SECONDARY8BIT)
78 FE(DSCAPS_SECONDARY16BIT)
83 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
84 if ((flags[i].mask & xmask) == flags[i].mask)
85 DPRINTF("%s ",flags[i].name);
88 static void _dump_DSBCAPS(DWORD xmask) {
93 #define FE(x) { x, #x },
94 FE(DSBCAPS_PRIMARYBUFFER)
96 FE(DSBCAPS_LOCHARDWARE)
97 FE(DSBCAPS_LOCSOFTWARE)
99 FE(DSBCAPS_CTRLFREQUENCY)
101 FE(DSBCAPS_CTRLVOLUME)
102 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
103 FE(DSBCAPS_STICKYFOCUS)
104 FE(DSBCAPS_GLOBALFOCUS)
105 FE(DSBCAPS_GETCURRENTPOSITION2)
106 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
111 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
112 if ((flags[i].mask & xmask) == flags[i].mask)
113 DPRINTF("%s ",flags[i].name);
116 /*******************************************************************************
117 * IDirectSoundImpl_DirectSound
119 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
120 LPDIRECTSOUND8 iface,
124 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
125 FIXME("shouldn't be called directly\n");
126 return E_NOINTERFACE;
129 static HRESULT WINAPI DSOUND_QueryInterface(
130 LPDIRECTSOUND8 iface,
134 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
135 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
138 WARN("invalid parameter\n");
142 if (IsEqualIID(riid, &IID_IUnknown)) {
143 if (!This->pUnknown) {
144 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
145 if (!This->pUnknown) {
146 WARN("IDirectSound_IUnknown_Create() failed\n");
148 return E_NOINTERFACE;
151 IDirectSound_IUnknown_AddRef(This->pUnknown);
152 *ppobj = This->pUnknown;
154 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
156 IDirectSound_IDirectSound_Create(iface, &This->pDS);
158 WARN("IDirectSound_IDirectSound_Create() failed\n");
160 return E_NOINTERFACE;
163 IDirectSound_IDirectSound_AddRef(This->pDS);
169 WARN("Unknown IID %s\n",debugstr_guid(riid));
170 return E_NOINTERFACE;
173 static HRESULT WINAPI DSOUND_QueryInterface8(
174 LPDIRECTSOUND8 iface,
178 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
179 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
182 WARN("invalid parameter\n");
186 if (IsEqualIID(riid, &IID_IUnknown)) {
187 if (!This->pUnknown) {
188 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
189 if (!This->pUnknown) {
190 WARN("IDirectSound8_IUnknown_Create() failed\n");
192 return E_NOINTERFACE;
195 IDirectSound8_IUnknown_AddRef(This->pUnknown);
196 *ppobj = This->pUnknown;
198 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
200 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
202 WARN("IDirectSound8_IDirectSound_Create() failed\n");
204 return E_NOINTERFACE;
207 IDirectSound8_IDirectSound_AddRef(This->pDS);
210 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
212 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
214 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
216 return E_NOINTERFACE;
219 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
225 WARN("Unknown IID %s\n",debugstr_guid(riid));
226 return E_NOINTERFACE;
229 static ULONG WINAPI IDirectSoundImpl_AddRef(
230 LPDIRECTSOUND8 iface)
232 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
233 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
235 return InterlockedIncrement(&(This->ref));
238 static ULONG WINAPI IDirectSoundImpl_Release(
239 LPDIRECTSOUND8 iface)
241 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
243 TRACE("(%p) ref was %ld, thread is %04lx\n",
244 This, This->ref, GetCurrentThreadId());
246 ref = InterlockedDecrement(&(This->ref));
251 timeKillEvent(This->timerID);
252 timeEndPeriod(DS_TIME_RES);
253 /* wait for timer to expire */
254 Sleep(DS_TIME_RES+1);
256 /* The sleep above should have allowed the timer process to expire
257 * but try to grab the lock just in case. Can't hold lock because
258 * IDirectSoundBufferImpl_Destroy also grabs the lock */
259 RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
260 RtlReleaseResource(&(This->buffer_list_lock));
262 /* It is allowed to release this object even when buffers are playing */
264 WARN("%d secondary buffers not released\n", This->nrofbuffers);
265 for( i=0;i<This->nrofbuffers;i++)
266 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
270 WARN("primary buffer not released\n");
271 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
274 hres = DSOUND_PrimaryDestroy(This);
276 WARN("DSOUND_PrimaryDestroy failed\n");
279 IDsDriver_Close(This->driver);
281 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
282 waveOutClose(This->hwo);
285 IDsDriver_Release(This->driver);
287 HeapFree(GetProcessHeap(),0,This->tmp_buffer);
288 HeapFree(GetProcessHeap(),0,This->buffer);
289 RtlDeleteResource(&This->buffer_list_lock);
290 This->mixlock.DebugInfo->Spare[1] = 0;
291 DeleteCriticalSection(&This->mixlock);
292 HeapFree(GetProcessHeap(),0,This);
294 TRACE("(%p) released\n",This);
300 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
301 LPDIRECTSOUND8 iface,
302 LPCDSBUFFERDESC dsbd,
303 LPLPDIRECTSOUNDBUFFER ppdsb,
306 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
307 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
308 FIXME("shouldn't be called directly\n");
309 return DSERR_GENERIC;
312 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
313 LPDIRECTSOUND8 iface,
314 LPCDSBUFFERDESC dsbd,
315 LPLPDIRECTSOUNDBUFFER ppdsb,
319 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
320 HRESULT hres = DS_OK;
321 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
324 WARN("invalid parameter: This == NULL\n");
325 return DSERR_INVALIDPARAM;
328 if (This->initialized == FALSE) {
329 WARN("not initialized\n");
330 return DSERR_UNINITIALIZED;
334 WARN("invalid parameter: dsbd == NULL\n");
335 return DSERR_INVALIDPARAM;
338 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
339 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
340 WARN("invalid parameter: dsbd\n");
341 return DSERR_INVALIDPARAM;
345 WARN("invalid parameter: ppdsb == NULL\n");
346 return DSERR_INVALIDPARAM;
349 if (TRACE_ON(dsound)) {
350 TRACE("(structsize=%ld)\n",dsbd->dwSize);
351 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
352 _dump_DSBCAPS(dsbd->dwFlags);
354 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
355 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
358 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
359 if (dsbd->lpwfxFormat != NULL) {
360 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
362 return DSERR_INVALIDPARAM;
366 WARN("Primary Buffer already created\n");
367 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
368 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
371 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
373 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
374 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
376 WARN("PrimaryBufferImpl_Create failed\n");
379 IDirectSoundBufferImpl * dsb;
381 if (dsbd->lpwfxFormat == NULL) {
382 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
383 "secondary buffer\n");
384 return DSERR_INVALIDPARAM;
387 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
388 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
389 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
390 dsbd->lpwfxFormat->nSamplesPerSec,
391 dsbd->lpwfxFormat->nAvgBytesPerSec,
392 dsbd->lpwfxFormat->nBlockAlign,
393 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
395 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
396 WARN("invalid parameter: 3D buffer format must be mono\n");
397 return DSERR_INVALIDPARAM;
400 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
402 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
404 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
405 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
407 WARN("SecondaryBufferImpl_Create failed\n");
409 WARN("IDirectSoundBufferImpl_Create failed\n");
415 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
416 LPDIRECTSOUND8 iface,
419 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
420 TRACE("(%p,%p)\n",This,lpDSCaps);
423 WARN("invalid parameter: This == NULL\n");
424 return DSERR_INVALIDPARAM;
427 if (This->initialized == FALSE) {
428 WARN("not initialized\n");
429 return DSERR_UNINITIALIZED;
432 if (lpDSCaps == NULL) {
433 WARN("invalid parameter: lpDSCaps = NULL\n");
434 return DSERR_INVALIDPARAM;
437 /* check if there is enough room */
438 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
439 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
440 lpDSCaps->dwSize, sizeof(*lpDSCaps));
441 return DSERR_INVALIDPARAM;
444 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
445 if (TRACE_ON(dsound)) {
446 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
447 _dump_DSCAPS(lpDSCaps->dwFlags);
450 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
451 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
452 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
453 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
454 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
455 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
456 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
457 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
458 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
459 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
460 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
461 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
462 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
463 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
464 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
465 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
466 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
467 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
469 /* driver doesn't have these */
470 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
471 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
476 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
477 LPDIRECTSOUND8 iface,
478 LPDIRECTSOUNDBUFFER psb,
479 LPLPDIRECTSOUNDBUFFER ppdsb)
481 IDirectSoundBufferImpl* pdsb;
482 IDirectSoundBufferImpl* dsb;
483 HRESULT hres = DS_OK;
485 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
487 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
490 WARN("invalid parameter: This == NULL\n");
491 return DSERR_INVALIDPARAM;
494 if (This->initialized == FALSE) {
495 WARN("not initialized\n");
496 return DSERR_UNINITIALIZED;
500 WARN("invalid parameter: psb == NULL\n");
501 return DSERR_INVALIDPARAM;
505 WARN("invalid parameter: ppdsb == NULL\n");
506 return DSERR_INVALIDPARAM;
509 /* FIXME: hack to make sure we have a secondary buffer */
510 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
511 WARN("trying to duplicate primary buffer\n");
513 return DSERR_INVALIDCALL;
516 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
518 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
521 WARN("out of memory\n");
523 return DSERR_OUTOFMEMORY;
526 CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
529 TRACE("duplicating hardware buffer\n");
531 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
533 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
535 /* allocate buffer */
536 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
537 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
538 if (dsb->buffer == NULL) {
539 WARN("out of memory\n");
540 HeapFree(GetProcessHeap(),0,dsb);
542 return DSERR_OUTOFMEMORY;
545 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
546 if (dsb->buffer->memory == NULL) {
547 WARN("out of memory\n");
548 HeapFree(GetProcessHeap(),0,dsb->buffer);
549 HeapFree(GetProcessHeap(),0,dsb);
551 return DSERR_OUTOFMEMORY;
553 dsb->buffer->ref = 1;
555 /* FIXME: copy buffer ? */
564 dsb->state = STATE_STOPPED;
569 dsb->iks = NULL; /* FIXME? */
572 /* variable sized struct so calculate size based on format */
573 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
575 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
576 if (dsb->pwfx == NULL) {
577 WARN("out of memory\n");
578 HeapFree(GetProcessHeap(),0,dsb->buffer);
579 HeapFree(GetProcessHeap(),0,dsb);
581 return DSERR_OUTOFMEMORY;
584 CopyMemory(dsb->pwfx, pdsb->pwfx, size);
586 InitializeCriticalSection(&(dsb->lock));
587 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
589 /* register buffer */
590 hres = DSOUND_AddBuffer(This, dsb);
592 IDirectSoundBuffer8_Release(psb);
593 dsb->lock.DebugInfo->Spare[1] = 0;
594 DeleteCriticalSection(&(dsb->lock));
595 HeapFree(GetProcessHeap(),0,dsb->buffer);
596 HeapFree(GetProcessHeap(),0,dsb->pwfx);
597 HeapFree(GetProcessHeap(),0,dsb);
600 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
602 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
603 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
605 WARN("SecondaryBufferImpl_Create failed\n");
611 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
612 LPDIRECTSOUND8 iface,
616 IDirectSoundImpl *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 IDirectSoundImpl *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 IDirectSoundImpl *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 IDirectSoundImpl *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 IDirectSoundImpl *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 IDirectSoundImpl *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 IDirectSoundImpl_QueryInterface,
719 IDirectSoundImpl_AddRef,
720 IDirectSoundImpl_Release,
721 IDirectSoundImpl_CreateSoundBuffer,
722 IDirectSoundImpl_GetCaps,
723 IDirectSoundImpl_DuplicateSoundBuffer,
724 IDirectSoundImpl_SetCooperativeLevel,
725 IDirectSoundImpl_Compact,
726 IDirectSoundImpl_GetSpeakerConfig,
727 IDirectSoundImpl_SetSpeakerConfig,
728 IDirectSoundImpl_Initialize,
729 IDirectSoundImpl_VerifyCertification
732 HRESULT WINAPI IDirectSoundImpl_Create(
734 LPDIRECTSOUND8 * ppDS)
737 PIDSDRIVER drv = NULL;
738 IDirectSoundImpl* pDS;
740 BOOLEAN found = FALSE;
741 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
743 /* Enumerate WINMM audio devices and find the one we want */
744 wodn = waveOutGetNumDevs();
748 return DSERR_NODRIVER;
751 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
753 for (wod=0; wod<wodn; wod++) {
754 if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
760 if (found == FALSE) {
761 WARN("No device found matching given ID!\n");
763 return DSERR_NODRIVER;
766 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
767 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
769 /* Disable the direct sound driver to force emulation if requested. */
770 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
773 /* Allocate memory */
774 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
776 WARN("out of memory\n");
778 return DSERR_OUTOFMEMORY;
781 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
785 pDS->priolevel = DSSCL_NORMAL;
791 pDS->state = STATE_STOPPED;
792 pDS->nrofbuffers = 0;
795 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
796 pDS->initialized = FALSE;
797 pDS->tmp_buffer = NULL;
798 pDS->tmp_buffer_len = 0;
800 /* 3D listener initial parameters */
801 pDS->listener = NULL;
802 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
803 pDS->ds3dl.vPosition.x = 0.0;
804 pDS->ds3dl.vPosition.y = 0.0;
805 pDS->ds3dl.vPosition.z = 0.0;
806 pDS->ds3dl.vVelocity.x = 0.0;
807 pDS->ds3dl.vVelocity.y = 0.0;
808 pDS->ds3dl.vVelocity.z = 0.0;
809 pDS->ds3dl.vOrientFront.x = 0.0;
810 pDS->ds3dl.vOrientFront.y = 0.0;
811 pDS->ds3dl.vOrientFront.z = 1.0;
812 pDS->ds3dl.vOrientTop.x = 0.0;
813 pDS->ds3dl.vOrientTop.y = 1.0;
814 pDS->ds3dl.vOrientTop.z = 0.0;
815 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
816 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
817 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
819 pDS->prebuf = ds_snd_queue_max;
820 pDS->guid = *lpcGUID;
822 /* Get driver description */
824 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
826 WARN("IDsDriver_GetDriverDesc failed\n");
827 HeapFree(GetProcessHeap(),0,pDS);
832 /* if no DirectSound interface available, use WINMM API instead */
833 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
836 pDS->drvdesc.dnDevNode = wod;
838 /* Set default wave format (may need it for waveOutOpen) */
839 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
840 if (pDS->pwfx == NULL) {
841 WARN("out of memory\n");
842 HeapFree(GetProcessHeap(),0,pDS);
844 return DSERR_OUTOFMEMORY;
847 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
848 /* We rely on the sound driver to return the actual sound format of
849 * the device if it does not support 22050x8x2 and is given the
850 * WAVE_DIRECTSOUND flag.
852 pDS->pwfx->nSamplesPerSec = 22050;
853 pDS->pwfx->wBitsPerSample = 8;
854 pDS->pwfx->nChannels = 2;
855 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
856 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
857 pDS->pwfx->cbSize = 0;
859 /* If the driver requests being opened through MMSYSTEM
860 * (which is recommended by the DDK), it is supposed to happen
861 * before the DirectSound interface is opened */
862 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
864 DWORD flags = CALLBACK_FUNCTION;
866 /* disable direct sound if requested */
867 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
868 flags |= WAVE_DIRECTSOUND;
870 err = mmErr(waveOutOpen(&(pDS->hwo),
871 pDS->drvdesc.dnDevNode, pDS->pwfx,
872 (DWORD)DSOUND_callback, (DWORD)pDS,
875 WARN("waveOutOpen failed\n");
876 HeapFree(GetProcessHeap(),0,pDS);
883 err = IDsDriver_Open(drv);
885 WARN("IDsDriver_Open failed\n");
886 HeapFree(GetProcessHeap(),0,pDS);
891 /* the driver is now open, so it's now allowed to call GetCaps */
892 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
894 WARN("IDsDriver_GetCaps failed\n");
895 HeapFree(GetProcessHeap(),0,pDS);
901 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
903 WARN("waveOutGetDevCaps failed\n");
904 HeapFree(GetProcessHeap(),0,pDS);
908 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
909 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
910 (woc.dwFormats & WAVE_FORMAT_2M08) ||
911 (woc.dwFormats & WAVE_FORMAT_4M08) ||
912 (woc.dwFormats & WAVE_FORMAT_48M08) ||
913 (woc.dwFormats & WAVE_FORMAT_96M08)) {
914 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
915 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
917 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
918 (woc.dwFormats & WAVE_FORMAT_2M16) ||
919 (woc.dwFormats & WAVE_FORMAT_4M16) ||
920 (woc.dwFormats & WAVE_FORMAT_48M16) ||
921 (woc.dwFormats & WAVE_FORMAT_96M16)) {
922 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
923 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
925 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
926 (woc.dwFormats & WAVE_FORMAT_2S08) ||
927 (woc.dwFormats & WAVE_FORMAT_4S08) ||
928 (woc.dwFormats & WAVE_FORMAT_48S08) ||
929 (woc.dwFormats & WAVE_FORMAT_96S08)) {
930 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
931 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
933 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
934 (woc.dwFormats & WAVE_FORMAT_2S16) ||
935 (woc.dwFormats & WAVE_FORMAT_4S16) ||
936 (woc.dwFormats & WAVE_FORMAT_48S16) ||
937 (woc.dwFormats & WAVE_FORMAT_96S16)) {
938 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
939 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
942 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
943 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
944 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
945 pDS->drvcaps.dwPrimaryBuffers = 1;
948 InitializeCriticalSection(&(pDS->mixlock));
949 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
951 RtlInitializeResource(&(pDS->buffer_list_lock));
953 *ppDS = (LPDIRECTSOUND8)pDS;
957 /*******************************************************************************
958 * IDirectSound_IUnknown
960 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
965 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
966 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
967 return DSOUND_QueryInterface(This->pds, riid, ppobj);
970 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
973 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
974 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
975 return InterlockedIncrement(&(This->ref));
978 static ULONG WINAPI IDirectSound_IUnknown_Release(
981 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
983 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
984 ulReturn = InterlockedDecrement(&(This->ref));
986 IDirectSoundImpl_Release(This->pds);
987 HeapFree(GetProcessHeap(),0,This);
988 TRACE("(%p) released\n",This);
993 static IUnknownVtbl DirectSound_Unknown_Vtbl =
995 IDirectSound_IUnknown_QueryInterface,
996 IDirectSound_IUnknown_AddRef,
997 IDirectSound_IUnknown_Release
1000 HRESULT WINAPI IDirectSound_IUnknown_Create(
1004 IDirectSound_IUnknown * pdsunk;
1005 TRACE("(%p,%p)\n",pds,ppunk);
1007 if (ppunk == NULL) {
1008 ERR("invalid parameter: ppunk == NULL\n");
1009 return DSERR_INVALIDPARAM;
1013 ERR("invalid parameter: pds == NULL\n");
1015 return DSERR_INVALIDPARAM;
1018 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1019 if (pdsunk == NULL) {
1020 WARN("out of memory\n");
1022 return DSERR_OUTOFMEMORY;
1025 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1029 IDirectSoundImpl_AddRef(pds);
1030 *ppunk = (LPUNKNOWN)pdsunk;
1035 /*******************************************************************************
1036 * IDirectSound_IDirectSound
1038 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1039 LPDIRECTSOUND iface,
1043 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1044 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1045 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1048 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1049 LPDIRECTSOUND iface)
1051 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1052 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1053 return InterlockedIncrement(&(This->ref));
1056 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1057 LPDIRECTSOUND iface)
1059 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1061 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1062 ulReturn = InterlockedDecrement(&This->ref);
1063 if (ulReturn == 0) {
1064 IDirectSoundImpl_Release(This->pds);
1065 HeapFree(GetProcessHeap(),0,This);
1066 TRACE("(%p) released\n",This);
1071 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1072 LPDIRECTSOUND iface,
1073 LPCDSBUFFERDESC dsbd,
1074 LPLPDIRECTSOUNDBUFFER ppdsb,
1077 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1078 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1079 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1082 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1083 LPDIRECTSOUND iface,
1086 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1087 TRACE("(%p,%p)\n",This,lpDSCaps);
1088 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1091 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1092 LPDIRECTSOUND iface,
1093 LPDIRECTSOUNDBUFFER psb,
1094 LPLPDIRECTSOUNDBUFFER ppdsb)
1096 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1097 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1098 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1101 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1102 LPDIRECTSOUND iface,
1106 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1107 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1108 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1111 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1112 LPDIRECTSOUND iface)
1114 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1115 TRACE("(%p)\n", This);
1116 return IDirectSoundImpl_Compact(This->pds);
1119 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1120 LPDIRECTSOUND iface,
1121 LPDWORD lpdwSpeakerConfig)
1123 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1124 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1125 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1128 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1129 LPDIRECTSOUND iface,
1132 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1133 TRACE("(%p,0x%08lx)\n",This,config);
1134 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1137 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1138 LPDIRECTSOUND iface,
1141 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1142 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1143 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1146 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1148 IDirectSound_IDirectSound_QueryInterface,
1149 IDirectSound_IDirectSound_AddRef,
1150 IDirectSound_IDirectSound_Release,
1151 IDirectSound_IDirectSound_CreateSoundBuffer,
1152 IDirectSound_IDirectSound_GetCaps,
1153 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1154 IDirectSound_IDirectSound_SetCooperativeLevel,
1155 IDirectSound_IDirectSound_Compact,
1156 IDirectSound_IDirectSound_GetSpeakerConfig,
1157 IDirectSound_IDirectSound_SetSpeakerConfig,
1158 IDirectSound_IDirectSound_Initialize
1161 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1163 LPDIRECTSOUND * ppds)
1165 IDirectSound_IDirectSound * pdsds;
1166 TRACE("(%p,%p)\n",pds,ppds);
1169 ERR("invalid parameter: ppds == NULL\n");
1170 return DSERR_INVALIDPARAM;
1174 ERR("invalid parameter: pds == NULL\n");
1176 return DSERR_INVALIDPARAM;
1179 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1180 if (pdsds == NULL) {
1181 WARN("out of memory\n");
1183 return DSERR_OUTOFMEMORY;
1186 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1190 IDirectSoundImpl_AddRef(pds);
1191 *ppds = (LPDIRECTSOUND)pdsds;
1196 /*******************************************************************************
1197 * IDirectSound8_IUnknown
1199 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1204 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1205 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1206 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1209 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1212 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1213 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1214 return InterlockedIncrement(&(This->ref));
1217 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1220 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1222 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1223 ulReturn = InterlockedDecrement(&(This->ref));
1224 if (ulReturn == 0) {
1225 IDirectSoundImpl_Release(This->pds);
1226 HeapFree(GetProcessHeap(),0,This);
1227 TRACE("(%p) released\n",This);
1232 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1234 IDirectSound8_IUnknown_QueryInterface,
1235 IDirectSound8_IUnknown_AddRef,
1236 IDirectSound8_IUnknown_Release
1239 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1243 IDirectSound8_IUnknown * pdsunk;
1244 TRACE("(%p,%p)\n",pds,ppunk);
1246 if (ppunk == NULL) {
1247 ERR("invalid parameter: ppunk == NULL\n");
1248 return DSERR_INVALIDPARAM;
1252 ERR("invalid parameter: pds == NULL\n");
1254 return DSERR_INVALIDPARAM;
1257 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1258 if (pdsunk == NULL) {
1259 WARN("out of memory\n");
1261 return DSERR_OUTOFMEMORY;
1264 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1268 IDirectSoundImpl_AddRef(pds);
1269 *ppunk = (LPUNKNOWN)pdsunk;
1274 /*******************************************************************************
1275 * IDirectSound8_IDirectSound
1277 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1278 LPDIRECTSOUND iface,
1282 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1283 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1284 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1287 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1288 LPDIRECTSOUND iface)
1290 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1291 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1292 return InterlockedIncrement(&(This->ref));
1295 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1296 LPDIRECTSOUND iface)
1298 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1300 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1301 ulReturn = InterlockedDecrement(&(This->ref));
1302 if (ulReturn == 0) {
1303 IDirectSoundImpl_Release(This->pds);
1304 HeapFree(GetProcessHeap(),0,This);
1305 TRACE("(%p) released\n",This);
1310 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1311 LPDIRECTSOUND iface,
1312 LPCDSBUFFERDESC dsbd,
1313 LPLPDIRECTSOUNDBUFFER ppdsb,
1316 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1317 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1318 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1321 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1322 LPDIRECTSOUND iface,
1325 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1326 TRACE("(%p,%p)\n",This,lpDSCaps);
1327 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1330 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1331 LPDIRECTSOUND iface,
1332 LPDIRECTSOUNDBUFFER psb,
1333 LPLPDIRECTSOUNDBUFFER ppdsb)
1335 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1336 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1337 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1340 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1341 LPDIRECTSOUND iface,
1345 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1346 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1347 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1350 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1351 LPDIRECTSOUND iface)
1353 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1354 TRACE("(%p)\n", This);
1355 return IDirectSoundImpl_Compact(This->pds);
1358 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1359 LPDIRECTSOUND iface,
1360 LPDWORD lpdwSpeakerConfig)
1362 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1363 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1364 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1367 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1368 LPDIRECTSOUND iface,
1371 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1372 TRACE("(%p,0x%08lx)\n",This,config);
1373 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1376 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1377 LPDIRECTSOUND iface,
1380 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1381 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1382 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1385 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1387 IDirectSound8_IDirectSound_QueryInterface,
1388 IDirectSound8_IDirectSound_AddRef,
1389 IDirectSound8_IDirectSound_Release,
1390 IDirectSound8_IDirectSound_CreateSoundBuffer,
1391 IDirectSound8_IDirectSound_GetCaps,
1392 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1393 IDirectSound8_IDirectSound_SetCooperativeLevel,
1394 IDirectSound8_IDirectSound_Compact,
1395 IDirectSound8_IDirectSound_GetSpeakerConfig,
1396 IDirectSound8_IDirectSound_SetSpeakerConfig,
1397 IDirectSound8_IDirectSound_Initialize
1400 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1402 LPDIRECTSOUND * ppds)
1404 IDirectSound8_IDirectSound * pdsds;
1405 TRACE("(%p,%p)\n",pds,ppds);
1408 ERR("invalid parameter: ppds == NULL\n");
1409 return DSERR_INVALIDPARAM;
1413 ERR("invalid parameter: pds == NULL\n");
1415 return DSERR_INVALIDPARAM;
1418 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1419 if (pdsds == NULL) {
1420 WARN("out of memory\n");
1422 return DSERR_OUTOFMEMORY;
1425 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1429 IDirectSoundImpl_AddRef(pds);
1430 *ppds = (LPDIRECTSOUND)pdsds;
1435 /*******************************************************************************
1436 * IDirectSound8_IDirectSound8
1438 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1439 LPDIRECTSOUND8 iface,
1443 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1444 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1445 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1448 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1449 LPDIRECTSOUND8 iface)
1451 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1452 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1453 return InterlockedIncrement(&(This->ref));
1456 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1457 LPDIRECTSOUND8 iface)
1459 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1461 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1462 ulReturn = InterlockedDecrement(&(This->ref));
1463 if (ulReturn == 0) {
1464 IDirectSoundImpl_Release(This->pds);
1465 HeapFree(GetProcessHeap(),0,This);
1466 TRACE("(%p) released\n",This);
1471 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1472 LPDIRECTSOUND8 iface,
1473 LPCDSBUFFERDESC dsbd,
1474 LPLPDIRECTSOUNDBUFFER ppdsb,
1477 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1478 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1479 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1482 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1483 LPDIRECTSOUND8 iface,
1486 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1487 TRACE("(%p,%p)\n",This,lpDSCaps);
1488 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1491 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1492 LPDIRECTSOUND8 iface,
1493 LPDIRECTSOUNDBUFFER psb,
1494 LPLPDIRECTSOUNDBUFFER ppdsb)
1496 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1497 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1498 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1501 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1502 LPDIRECTSOUND8 iface,
1506 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1507 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1508 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1511 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1512 LPDIRECTSOUND8 iface)
1514 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1515 TRACE("(%p)\n", This);
1516 return IDirectSoundImpl_Compact(This->pds);
1519 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1520 LPDIRECTSOUND8 iface,
1521 LPDWORD lpdwSpeakerConfig)
1523 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1524 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1525 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1528 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1529 LPDIRECTSOUND8 iface,
1532 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1533 TRACE("(%p,0x%08lx)\n",This,config);
1534 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1537 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1538 LPDIRECTSOUND8 iface,
1541 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1542 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1543 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1546 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1547 LPDIRECTSOUND8 iface,
1548 LPDWORD pdwCertified)
1550 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1551 TRACE("(%p, %p)\n", This, pdwCertified);
1552 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1555 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1557 IDirectSound8_IDirectSound8_QueryInterface,
1558 IDirectSound8_IDirectSound8_AddRef,
1559 IDirectSound8_IDirectSound8_Release,
1560 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1561 IDirectSound8_IDirectSound8_GetCaps,
1562 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1563 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1564 IDirectSound8_IDirectSound8_Compact,
1565 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1566 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1567 IDirectSound8_IDirectSound8_Initialize,
1568 IDirectSound8_IDirectSound8_VerifyCertification
1571 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1573 LPDIRECTSOUND8 * ppds)
1575 IDirectSound8_IDirectSound8 * pdsds;
1576 TRACE("(%p,%p)\n",pds,ppds);
1579 ERR("invalid parameter: ppds == NULL\n");
1580 return DSERR_INVALIDPARAM;
1584 ERR("invalid parameter: pds == NULL\n");
1586 return DSERR_INVALIDPARAM;
1589 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1590 if (pdsds == NULL) {
1591 WARN("out of memory\n");
1593 return DSERR_OUTOFMEMORY;
1596 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1600 IDirectSoundImpl_AddRef(pds);
1601 *ppds = (LPDIRECTSOUND8)pdsds;
1606 HRESULT WINAPI DSOUND_Create(
1608 LPDIRECTSOUND *ppDS,
1609 IUnknown *pUnkOuter)
1614 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1616 if (pUnkOuter != NULL) {
1617 WARN("invalid parameter: pUnkOuter != NULL\n");
1618 return DSERR_INVALIDPARAM;
1622 WARN("invalid parameter: ppDS == NULL\n");
1623 return DSERR_INVALIDPARAM;
1626 /* Get dsound configuration */
1627 setup_dsound_options();
1629 /* Default device? */
1630 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1631 lpcGUID = &DSDEVID_DefaultPlayback;
1633 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1634 WARN("invalid parameter: lpcGUID\n");
1636 return DSERR_INVALIDPARAM;
1640 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1641 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1643 IDirectSound_IDirectSound_AddRef(*ppDS);
1645 WARN("IDirectSound_IDirectSound_Create failed\n");
1647 ERR("different dsound already opened (only support one sound card at a time now)\n");
1649 hr = DSERR_ALLOCATED;
1653 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1655 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1657 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1659 IDirectSound_IDirectSound_AddRef(*ppDS);
1661 dsound = (IDirectSoundImpl*)pDS;
1662 timeBeginPeriod(DS_TIME_RES);
1663 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1664 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1666 WARN("IDirectSound_IDirectSound_Create failed\n");
1667 IDirectSound8_Release(pDS);
1670 WARN("DSOUND_PrimaryCreate failed\n");
1671 IDirectSound8_Release(pDS);
1674 WARN("IDirectSoundImpl_Create failed\n");
1680 /*******************************************************************************
1681 * DirectSoundCreate (DSOUND.1)
1683 * Creates and initializes a DirectSound interface.
1686 * lpcGUID [I] Address of the GUID that identifies the sound device.
1687 * ppDS [O] Address of a variable to receive the interface pointer.
1688 * pUnkOuter [I] Must be NULL.
1692 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1693 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1695 HRESULT WINAPI DirectSoundCreate(
1697 LPDIRECTSOUND *ppDS,
1698 IUnknown *pUnkOuter)
1702 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1704 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1706 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1711 HRESULT WINAPI DSOUND_Create8(
1713 LPDIRECTSOUND8 *ppDS,
1714 IUnknown *pUnkOuter)
1719 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1721 if (pUnkOuter != NULL) {
1722 WARN("invalid parameter: pUnkOuter != NULL\n");
1723 return DSERR_INVALIDPARAM;
1727 WARN("invalid parameter: ppDS == NULL\n");
1728 return DSERR_INVALIDPARAM;
1731 /* Get dsound configuration */
1732 setup_dsound_options();
1734 /* Default device? */
1735 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1736 lpcGUID = &DSDEVID_DefaultPlayback;
1738 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1739 WARN("invalid parameter: lpcGUID\n");
1741 return DSERR_INVALIDPARAM;
1745 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1746 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1748 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1750 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1752 ERR("different dsound already opened (only support one sound card at a time now)\n");
1754 hr = DSERR_ALLOCATED;
1758 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1760 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1762 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1764 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1766 dsound = (IDirectSoundImpl*)pDS;
1767 timeBeginPeriod(DS_TIME_RES);
1768 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1769 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1771 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1772 IDirectSound8_Release(pDS);
1775 WARN("DSOUND_PrimaryCreate failed\n");
1776 IDirectSound8_Release(pDS);
1779 WARN("IDirectSoundImpl_Create failed\n");
1785 /*******************************************************************************
1786 * DirectSoundCreate8 (DSOUND.11)
1788 * Creates and initializes a DirectSound8 interface.
1791 * lpcGUID [I] Address of the GUID that identifies the sound device.
1792 * ppDS [O] Address of a variable to receive the interface pointer.
1793 * pUnkOuter [I] Must be NULL.
1797 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1798 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1800 HRESULT WINAPI DirectSoundCreate8(
1802 LPDIRECTSOUND8 *ppDS,
1803 IUnknown *pUnkOuter)
1807 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1809 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1811 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1817 * Add secondary buffer to buffer list.
1818 * Gets exclusive access to buffer for writing.
1820 HRESULT DSOUND_AddBuffer(
1821 IDirectSoundImpl * pDS,
1822 IDirectSoundBufferImpl * pDSB)
1824 IDirectSoundBufferImpl **newbuffers;
1827 TRACE("(%p, %p)\n", pDS, pDSB);
1829 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1832 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1834 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1837 pDS->buffers = newbuffers;
1838 pDS->buffers[pDS->nrofbuffers] = pDSB;
1840 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1842 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
1843 hr = DSERR_OUTOFMEMORY;
1846 RtlReleaseResource(&(pDS->buffer_list_lock));
1852 * Remove secondary buffer from buffer list.
1853 * Gets exclusive access to buffer for writing.
1855 HRESULT DSOUND_RemoveBuffer(
1856 IDirectSoundImpl * pDS,
1857 IDirectSoundBufferImpl * pDSB)
1862 TRACE("(%p, %p)\n", pDS, pDSB);
1864 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1866 for (i = 0; i < pDS->nrofbuffers; i++)
1867 if (pDS->buffers[i] == pDSB)
1870 if (i < pDS->nrofbuffers) {
1871 /* Put the last buffer of the list in the (now empty) position */
1872 pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
1874 pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
1875 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1878 if (pDS->nrofbuffers == 0) {
1879 HeapFree(GetProcessHeap(),0,pDS->buffers);
1880 pDS->buffers = NULL;
1883 RtlReleaseResource(&(pDS->buffer_list_lock));