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 ULONG ref = InterlockedIncrement(&(This->ref));
234 TRACE("(%p) ref was %ld\n", This, ref - 1);
238 static ULONG WINAPI IDirectSoundImpl_Release(
239 LPDIRECTSOUND8 iface)
241 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
242 ULONG ref = InterlockedDecrement(&(This->ref));
243 TRACE("(%p) ref was %ld\n", This, ref + 1);
249 timeKillEvent(This->timerID);
250 timeEndPeriod(DS_TIME_RES);
251 /* wait for timer to expire */
252 Sleep(DS_TIME_RES+1);
254 /* The sleep above should have allowed the timer process to expire
255 * but try to grab the lock just in case. Can't hold lock because
256 * IDirectSoundBufferImpl_Destroy also grabs the lock */
257 RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
258 RtlReleaseResource(&(This->buffer_list_lock));
260 /* It is allowed to release this object even when buffers are playing */
262 WARN("%d secondary buffers not released\n", This->nrofbuffers);
263 for( i=0;i<This->nrofbuffers;i++)
264 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
268 WARN("primary buffer not released\n");
269 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
272 hres = DSOUND_PrimaryDestroy(This);
274 WARN("DSOUND_PrimaryDestroy failed\n");
277 IDsDriver_Close(This->driver);
279 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
280 waveOutClose(This->hwo);
283 IDsDriver_Release(This->driver);
285 HeapFree(GetProcessHeap(),0,This->tmp_buffer);
286 HeapFree(GetProcessHeap(),0,This->buffer);
287 RtlDeleteResource(&This->buffer_list_lock);
288 This->mixlock.DebugInfo->Spare[1] = 0;
289 DeleteCriticalSection(&This->mixlock);
290 HeapFree(GetProcessHeap(),0,This);
291 DSOUND_renderer = NULL;
292 TRACE("(%p) released\n", This);
297 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
298 LPDIRECTSOUND8 iface,
299 LPCDSBUFFERDESC dsbd,
300 LPLPDIRECTSOUNDBUFFER ppdsb,
303 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
304 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
305 FIXME("shouldn't be called directly\n");
306 return DSERR_GENERIC;
309 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
310 LPDIRECTSOUND8 iface,
311 LPCDSBUFFERDESC dsbd,
312 LPLPDIRECTSOUNDBUFFER ppdsb,
316 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
317 HRESULT hres = DS_OK;
318 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
321 WARN("invalid parameter: This == NULL\n");
322 return DSERR_INVALIDPARAM;
325 if (This->initialized == FALSE) {
326 WARN("not initialized\n");
327 return DSERR_UNINITIALIZED;
331 WARN("invalid parameter: dsbd == NULL\n");
332 return DSERR_INVALIDPARAM;
335 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
336 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
337 WARN("invalid parameter: dsbd\n");
338 return DSERR_INVALIDPARAM;
342 WARN("invalid parameter: ppdsb == NULL\n");
343 return DSERR_INVALIDPARAM;
346 if (TRACE_ON(dsound)) {
347 TRACE("(structsize=%ld)\n",dsbd->dwSize);
348 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
349 _dump_DSBCAPS(dsbd->dwFlags);
351 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
352 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
355 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
356 if (dsbd->lpwfxFormat != NULL) {
357 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
359 return DSERR_INVALIDPARAM;
363 WARN("Primary Buffer already created\n");
364 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
365 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
368 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
370 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
371 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
373 WARN("PrimaryBufferImpl_Create failed\n");
376 IDirectSoundBufferImpl * dsb;
378 if (dsbd->lpwfxFormat == NULL) {
379 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
380 "secondary buffer\n");
381 return DSERR_INVALIDPARAM;
384 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
385 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
386 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
387 dsbd->lpwfxFormat->nSamplesPerSec,
388 dsbd->lpwfxFormat->nAvgBytesPerSec,
389 dsbd->lpwfxFormat->nBlockAlign,
390 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
392 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
393 WARN("invalid parameter: 3D buffer format must be mono\n");
394 return DSERR_INVALIDPARAM;
397 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
399 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
401 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
402 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
404 WARN("SecondaryBufferImpl_Create failed\n");
406 WARN("IDirectSoundBufferImpl_Create failed\n");
412 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
413 LPDIRECTSOUND8 iface,
416 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
417 TRACE("(%p,%p)\n",This,lpDSCaps);
420 WARN("invalid parameter: This == NULL\n");
421 return DSERR_INVALIDPARAM;
424 if (This->initialized == FALSE) {
425 WARN("not initialized\n");
426 return DSERR_UNINITIALIZED;
429 if (lpDSCaps == NULL) {
430 WARN("invalid parameter: lpDSCaps = NULL\n");
431 return DSERR_INVALIDPARAM;
434 /* check if there is enough room */
435 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
436 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
437 lpDSCaps->dwSize, sizeof(*lpDSCaps));
438 return DSERR_INVALIDPARAM;
441 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
442 if (TRACE_ON(dsound)) {
443 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
444 _dump_DSCAPS(lpDSCaps->dwFlags);
447 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
448 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
449 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
450 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
451 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
452 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
453 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
454 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
455 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
456 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
457 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
458 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
459 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
460 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
461 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
462 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
463 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
464 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
466 /* driver doesn't have these */
467 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
468 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
473 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
474 LPDIRECTSOUND8 iface,
475 LPDIRECTSOUNDBUFFER psb,
476 LPLPDIRECTSOUNDBUFFER ppdsb)
478 IDirectSoundBufferImpl* pdsb;
479 IDirectSoundBufferImpl* dsb;
480 HRESULT hres = DS_OK;
482 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
484 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
487 WARN("invalid parameter: This == NULL\n");
488 return DSERR_INVALIDPARAM;
491 if (This->initialized == FALSE) {
492 WARN("not initialized\n");
493 return DSERR_UNINITIALIZED;
497 WARN("invalid parameter: psb == NULL\n");
498 return DSERR_INVALIDPARAM;
502 WARN("invalid parameter: ppdsb == NULL\n");
503 return DSERR_INVALIDPARAM;
506 /* FIXME: hack to make sure we have a secondary buffer */
507 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
508 WARN("trying to duplicate primary buffer\n");
510 return DSERR_INVALIDCALL;
513 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
515 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
518 WARN("out of memory\n");
520 return DSERR_OUTOFMEMORY;
523 CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
526 TRACE("duplicating hardware buffer\n");
528 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
530 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
532 /* allocate buffer */
533 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
534 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
535 if (dsb->buffer == NULL) {
536 WARN("out of memory\n");
537 HeapFree(GetProcessHeap(),0,dsb);
539 return DSERR_OUTOFMEMORY;
542 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
543 if (dsb->buffer->memory == NULL) {
544 WARN("out of memory\n");
545 HeapFree(GetProcessHeap(),0,dsb->buffer);
546 HeapFree(GetProcessHeap(),0,dsb);
548 return DSERR_OUTOFMEMORY;
550 dsb->buffer->ref = 1;
552 /* FIXME: copy buffer ? */
561 dsb->state = STATE_STOPPED;
566 dsb->iks = NULL; /* FIXME? */
569 /* variable sized struct so calculate size based on format */
570 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
572 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
573 if (dsb->pwfx == NULL) {
574 WARN("out of memory\n");
575 HeapFree(GetProcessHeap(),0,dsb->buffer);
576 HeapFree(GetProcessHeap(),0,dsb);
578 return DSERR_OUTOFMEMORY;
581 CopyMemory(dsb->pwfx, pdsb->pwfx, size);
583 InitializeCriticalSection(&(dsb->lock));
584 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
586 /* register buffer */
587 hres = DSOUND_AddBuffer(This, dsb);
589 IDirectSoundBuffer8_Release(psb);
590 dsb->lock.DebugInfo->Spare[1] = 0;
591 DeleteCriticalSection(&(dsb->lock));
592 HeapFree(GetProcessHeap(),0,dsb->buffer);
593 HeapFree(GetProcessHeap(),0,dsb->pwfx);
594 HeapFree(GetProcessHeap(),0,dsb);
597 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
599 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
600 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
602 WARN("SecondaryBufferImpl_Create failed\n");
608 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
609 LPDIRECTSOUND8 iface,
613 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
614 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
616 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
617 WARN("level=%s not fully supported\n",
618 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
620 This->priolevel = level;
624 static HRESULT WINAPI IDirectSoundImpl_Compact(
625 LPDIRECTSOUND8 iface)
627 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
628 TRACE("(%p)\n",This);
630 if (This->initialized == FALSE) {
631 WARN("not initialized\n");
632 return DSERR_UNINITIALIZED;
635 if (This->priolevel != DSSCL_PRIORITY) {
636 WARN("incorrect priority level\n");
637 return DSERR_PRIOLEVELNEEDED;
643 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
644 LPDIRECTSOUND8 iface,
645 LPDWORD lpdwSpeakerConfig)
647 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
648 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
650 if (This->initialized == FALSE) {
651 WARN("not initialized\n");
652 return DSERR_UNINITIALIZED;
655 if (lpdwSpeakerConfig == NULL) {
656 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
657 return DSERR_INVALIDPARAM;
660 WARN("not fully functional\n");
661 *lpdwSpeakerConfig = This->speaker_config;
665 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
666 LPDIRECTSOUND8 iface,
669 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
670 TRACE("(%p,0x%08lx)\n",This,config);
672 if (This->initialized == FALSE) {
673 WARN("not initialized\n");
674 return DSERR_UNINITIALIZED;
677 This->speaker_config = config;
678 WARN("not fully functional\n");
682 static HRESULT WINAPI IDirectSoundImpl_Initialize(
683 LPDIRECTSOUND8 iface,
686 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
687 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
689 This->initialized = TRUE;
694 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
695 LPDIRECTSOUND8 iface,
696 LPDWORD pdwCertified)
698 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
699 TRACE("(%p, %p)\n",This,pdwCertified);
701 if (This->initialized == FALSE) {
702 WARN("not initialized\n");
703 return DSERR_UNINITIALIZED;
706 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
707 *pdwCertified = DS_CERTIFIED;
709 *pdwCertified = DS_UNCERTIFIED;
713 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
715 IDirectSoundImpl_QueryInterface,
716 IDirectSoundImpl_AddRef,
717 IDirectSoundImpl_Release,
718 IDirectSoundImpl_CreateSoundBuffer,
719 IDirectSoundImpl_GetCaps,
720 IDirectSoundImpl_DuplicateSoundBuffer,
721 IDirectSoundImpl_SetCooperativeLevel,
722 IDirectSoundImpl_Compact,
723 IDirectSoundImpl_GetSpeakerConfig,
724 IDirectSoundImpl_SetSpeakerConfig,
725 IDirectSoundImpl_Initialize,
726 IDirectSoundImpl_VerifyCertification
729 HRESULT WINAPI IDirectSoundImpl_Create(
731 LPDIRECTSOUND8 * ppDS)
734 PIDSDRIVER drv = NULL;
735 IDirectSoundImpl* pDS;
737 BOOLEAN found = FALSE;
738 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
740 /* Enumerate WINMM audio devices and find the one we want */
741 wodn = waveOutGetNumDevs();
745 return DSERR_NODRIVER;
748 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
750 for (wod=0; wod<wodn; wod++) {
751 if (IsEqualGUID( lpcGUID, &DSOUND_renderer_guids[wod])) {
757 if (found == FALSE) {
758 WARN("No device found matching given ID!\n");
760 return DSERR_NODRIVER;
763 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
764 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
766 /* Disable the direct sound driver to force emulation if requested. */
767 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
770 /* Allocate memory */
771 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
773 WARN("out of memory\n");
775 return DSERR_OUTOFMEMORY;
778 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
782 pDS->priolevel = DSSCL_NORMAL;
788 pDS->state = STATE_STOPPED;
789 pDS->nrofbuffers = 0;
792 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
793 pDS->initialized = FALSE;
794 pDS->tmp_buffer = NULL;
795 pDS->tmp_buffer_len = 0;
797 /* 3D listener initial parameters */
798 pDS->listener = NULL;
799 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
800 pDS->ds3dl.vPosition.x = 0.0;
801 pDS->ds3dl.vPosition.y = 0.0;
802 pDS->ds3dl.vPosition.z = 0.0;
803 pDS->ds3dl.vVelocity.x = 0.0;
804 pDS->ds3dl.vVelocity.y = 0.0;
805 pDS->ds3dl.vVelocity.z = 0.0;
806 pDS->ds3dl.vOrientFront.x = 0.0;
807 pDS->ds3dl.vOrientFront.y = 0.0;
808 pDS->ds3dl.vOrientFront.z = 1.0;
809 pDS->ds3dl.vOrientTop.x = 0.0;
810 pDS->ds3dl.vOrientTop.y = 1.0;
811 pDS->ds3dl.vOrientTop.z = 0.0;
812 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
813 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
814 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
816 pDS->prebuf = ds_snd_queue_max;
817 pDS->guid = *lpcGUID;
819 /* Get driver description */
821 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
823 WARN("IDsDriver_GetDriverDesc failed\n");
824 HeapFree(GetProcessHeap(),0,pDS);
829 /* if no DirectSound interface available, use WINMM API instead */
830 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
833 pDS->drvdesc.dnDevNode = wod;
835 /* Set default wave format (may need it for waveOutOpen) */
836 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
837 if (pDS->pwfx == NULL) {
838 WARN("out of memory\n");
839 HeapFree(GetProcessHeap(),0,pDS);
841 return DSERR_OUTOFMEMORY;
844 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
845 /* We rely on the sound driver to return the actual sound format of
846 * the device if it does not support 22050x8x2 and is given the
847 * WAVE_DIRECTSOUND flag.
849 pDS->pwfx->nSamplesPerSec = 22050;
850 pDS->pwfx->wBitsPerSample = 8;
851 pDS->pwfx->nChannels = 2;
852 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
853 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
854 pDS->pwfx->cbSize = 0;
856 /* If the driver requests being opened through MMSYSTEM
857 * (which is recommended by the DDK), it is supposed to happen
858 * before the DirectSound interface is opened */
859 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
861 DWORD flags = CALLBACK_FUNCTION;
863 /* disable direct sound if requested */
864 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
865 flags |= WAVE_DIRECTSOUND;
867 err = mmErr(waveOutOpen(&(pDS->hwo),
868 pDS->drvdesc.dnDevNode, pDS->pwfx,
869 (DWORD)DSOUND_callback, (DWORD)pDS,
872 WARN("waveOutOpen failed\n");
873 HeapFree(GetProcessHeap(),0,pDS);
880 err = IDsDriver_Open(drv);
882 WARN("IDsDriver_Open failed\n");
883 HeapFree(GetProcessHeap(),0,pDS);
888 /* the driver is now open, so it's now allowed to call GetCaps */
889 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
891 WARN("IDsDriver_GetCaps failed\n");
892 HeapFree(GetProcessHeap(),0,pDS);
898 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
900 WARN("waveOutGetDevCaps failed\n");
901 HeapFree(GetProcessHeap(),0,pDS);
905 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
906 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
907 (woc.dwFormats & WAVE_FORMAT_2M08) ||
908 (woc.dwFormats & WAVE_FORMAT_4M08) ||
909 (woc.dwFormats & WAVE_FORMAT_48M08) ||
910 (woc.dwFormats & WAVE_FORMAT_96M08)) {
911 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
912 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
914 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
915 (woc.dwFormats & WAVE_FORMAT_2M16) ||
916 (woc.dwFormats & WAVE_FORMAT_4M16) ||
917 (woc.dwFormats & WAVE_FORMAT_48M16) ||
918 (woc.dwFormats & WAVE_FORMAT_96M16)) {
919 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
920 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
922 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
923 (woc.dwFormats & WAVE_FORMAT_2S08) ||
924 (woc.dwFormats & WAVE_FORMAT_4S08) ||
925 (woc.dwFormats & WAVE_FORMAT_48S08) ||
926 (woc.dwFormats & WAVE_FORMAT_96S08)) {
927 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
928 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
930 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
931 (woc.dwFormats & WAVE_FORMAT_2S16) ||
932 (woc.dwFormats & WAVE_FORMAT_4S16) ||
933 (woc.dwFormats & WAVE_FORMAT_48S16) ||
934 (woc.dwFormats & WAVE_FORMAT_96S16)) {
935 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
936 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
939 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
940 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
941 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
942 pDS->drvcaps.dwPrimaryBuffers = 1;
945 InitializeCriticalSection(&(pDS->mixlock));
946 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
948 RtlInitializeResource(&(pDS->buffer_list_lock));
950 *ppDS = (LPDIRECTSOUND8)pDS;
954 /*******************************************************************************
955 * IDirectSound_IUnknown
957 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
962 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
963 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
964 return DSOUND_QueryInterface(This->pds, riid, ppobj);
967 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
970 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
971 ULONG ref = InterlockedIncrement(&(This->ref));
972 TRACE("(%p) ref was %ld\n", This, ref - 1);
976 static ULONG WINAPI IDirectSound_IUnknown_Release(
979 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
980 ULONG ref = InterlockedDecrement(&(This->ref));
981 TRACE("(%p) ref was %ld\n", This, ref + 1);
983 IDirectSoundImpl_Release(This->pds);
984 HeapFree(GetProcessHeap(), 0, This);
985 TRACE("(%p) released\n", This);
990 static IUnknownVtbl DirectSound_Unknown_Vtbl =
992 IDirectSound_IUnknown_QueryInterface,
993 IDirectSound_IUnknown_AddRef,
994 IDirectSound_IUnknown_Release
997 HRESULT WINAPI IDirectSound_IUnknown_Create(
1001 IDirectSound_IUnknown * pdsunk;
1002 TRACE("(%p,%p)\n",pds,ppunk);
1004 if (ppunk == NULL) {
1005 ERR("invalid parameter: ppunk == NULL\n");
1006 return DSERR_INVALIDPARAM;
1010 ERR("invalid parameter: pds == NULL\n");
1012 return DSERR_INVALIDPARAM;
1015 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1016 if (pdsunk == NULL) {
1017 WARN("out of memory\n");
1019 return DSERR_OUTOFMEMORY;
1022 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1026 IDirectSoundImpl_AddRef(pds);
1027 *ppunk = (LPUNKNOWN)pdsunk;
1032 /*******************************************************************************
1033 * IDirectSound_IDirectSound
1035 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1036 LPDIRECTSOUND iface,
1040 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1041 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1042 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1045 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1046 LPDIRECTSOUND iface)
1048 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1049 ULONG ref = InterlockedIncrement(&(This->ref));
1050 TRACE("(%p) ref was %ld\n", This, ref - 1);
1054 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1055 LPDIRECTSOUND iface)
1057 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1058 ULONG ref = InterlockedDecrement(&(This->ref));
1059 TRACE("(%p) ref was %ld\n", This, ref + 1);
1061 IDirectSoundImpl_Release(This->pds);
1062 HeapFree(GetProcessHeap(), 0, This);
1063 TRACE("(%p) released\n", This);
1068 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1069 LPDIRECTSOUND iface,
1070 LPCDSBUFFERDESC dsbd,
1071 LPLPDIRECTSOUNDBUFFER ppdsb,
1074 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1075 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1076 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1079 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1080 LPDIRECTSOUND iface,
1083 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1084 TRACE("(%p,%p)\n",This,lpDSCaps);
1085 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1088 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1089 LPDIRECTSOUND iface,
1090 LPDIRECTSOUNDBUFFER psb,
1091 LPLPDIRECTSOUNDBUFFER ppdsb)
1093 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1094 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1095 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1098 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1099 LPDIRECTSOUND iface,
1103 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1104 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1105 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1108 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1109 LPDIRECTSOUND iface)
1111 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1112 TRACE("(%p)\n", This);
1113 return IDirectSoundImpl_Compact(This->pds);
1116 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1117 LPDIRECTSOUND iface,
1118 LPDWORD lpdwSpeakerConfig)
1120 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1121 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1122 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1125 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1126 LPDIRECTSOUND iface,
1129 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1130 TRACE("(%p,0x%08lx)\n",This,config);
1131 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1134 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1135 LPDIRECTSOUND iface,
1138 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1139 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1140 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1143 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1145 IDirectSound_IDirectSound_QueryInterface,
1146 IDirectSound_IDirectSound_AddRef,
1147 IDirectSound_IDirectSound_Release,
1148 IDirectSound_IDirectSound_CreateSoundBuffer,
1149 IDirectSound_IDirectSound_GetCaps,
1150 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1151 IDirectSound_IDirectSound_SetCooperativeLevel,
1152 IDirectSound_IDirectSound_Compact,
1153 IDirectSound_IDirectSound_GetSpeakerConfig,
1154 IDirectSound_IDirectSound_SetSpeakerConfig,
1155 IDirectSound_IDirectSound_Initialize
1158 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1160 LPDIRECTSOUND * ppds)
1162 IDirectSound_IDirectSound * pdsds;
1163 TRACE("(%p,%p)\n",pds,ppds);
1166 ERR("invalid parameter: ppds == NULL\n");
1167 return DSERR_INVALIDPARAM;
1171 ERR("invalid parameter: pds == NULL\n");
1173 return DSERR_INVALIDPARAM;
1176 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1177 if (pdsds == NULL) {
1178 WARN("out of memory\n");
1180 return DSERR_OUTOFMEMORY;
1183 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1187 IDirectSoundImpl_AddRef(pds);
1188 *ppds = (LPDIRECTSOUND)pdsds;
1193 /*******************************************************************************
1194 * IDirectSound8_IUnknown
1196 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1201 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1202 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1203 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1206 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1209 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1210 ULONG ref = InterlockedIncrement(&(This->ref));
1211 TRACE("(%p) ref was %ld\n", This, ref - 1);
1215 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1218 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1219 ULONG ref = InterlockedDecrement(&(This->ref));
1220 TRACE("(%p) ref was %ld\n", This, ref + 1);
1222 IDirectSoundImpl_Release(This->pds);
1223 HeapFree(GetProcessHeap(), 0, This);
1224 TRACE("(%p) released\n", This);
1229 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1231 IDirectSound8_IUnknown_QueryInterface,
1232 IDirectSound8_IUnknown_AddRef,
1233 IDirectSound8_IUnknown_Release
1236 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1240 IDirectSound8_IUnknown * pdsunk;
1241 TRACE("(%p,%p)\n",pds,ppunk);
1243 if (ppunk == NULL) {
1244 ERR("invalid parameter: ppunk == NULL\n");
1245 return DSERR_INVALIDPARAM;
1249 ERR("invalid parameter: pds == NULL\n");
1251 return DSERR_INVALIDPARAM;
1254 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1255 if (pdsunk == NULL) {
1256 WARN("out of memory\n");
1258 return DSERR_OUTOFMEMORY;
1261 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1265 IDirectSoundImpl_AddRef(pds);
1266 *ppunk = (LPUNKNOWN)pdsunk;
1271 /*******************************************************************************
1272 * IDirectSound8_IDirectSound
1274 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1275 LPDIRECTSOUND iface,
1279 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1280 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1281 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1284 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1285 LPDIRECTSOUND iface)
1287 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1288 ULONG ref = InterlockedIncrement(&(This->ref));
1289 TRACE("(%p) ref was %ld\n", This, ref - 1);
1293 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1294 LPDIRECTSOUND iface)
1296 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1297 ULONG ref = InterlockedDecrement(&(This->ref));
1298 TRACE("(%p) ref was %ld\n", This, ref + 1);
1300 IDirectSoundImpl_Release(This->pds);
1301 HeapFree(GetProcessHeap(), 0, This);
1302 TRACE("(%p) released\n", This);
1307 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1308 LPDIRECTSOUND iface,
1309 LPCDSBUFFERDESC dsbd,
1310 LPLPDIRECTSOUNDBUFFER ppdsb,
1313 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1314 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1315 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1318 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1319 LPDIRECTSOUND iface,
1322 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1323 TRACE("(%p,%p)\n",This,lpDSCaps);
1324 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1327 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1328 LPDIRECTSOUND iface,
1329 LPDIRECTSOUNDBUFFER psb,
1330 LPLPDIRECTSOUNDBUFFER ppdsb)
1332 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1333 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1334 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1337 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1338 LPDIRECTSOUND iface,
1342 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1343 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1344 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1347 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1348 LPDIRECTSOUND iface)
1350 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1351 TRACE("(%p)\n", This);
1352 return IDirectSoundImpl_Compact(This->pds);
1355 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1356 LPDIRECTSOUND iface,
1357 LPDWORD lpdwSpeakerConfig)
1359 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1360 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1361 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1364 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1365 LPDIRECTSOUND iface,
1368 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1369 TRACE("(%p,0x%08lx)\n",This,config);
1370 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1373 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1374 LPDIRECTSOUND iface,
1377 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1378 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1379 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1382 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1384 IDirectSound8_IDirectSound_QueryInterface,
1385 IDirectSound8_IDirectSound_AddRef,
1386 IDirectSound8_IDirectSound_Release,
1387 IDirectSound8_IDirectSound_CreateSoundBuffer,
1388 IDirectSound8_IDirectSound_GetCaps,
1389 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1390 IDirectSound8_IDirectSound_SetCooperativeLevel,
1391 IDirectSound8_IDirectSound_Compact,
1392 IDirectSound8_IDirectSound_GetSpeakerConfig,
1393 IDirectSound8_IDirectSound_SetSpeakerConfig,
1394 IDirectSound8_IDirectSound_Initialize
1397 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1399 LPDIRECTSOUND * ppds)
1401 IDirectSound8_IDirectSound * pdsds;
1402 TRACE("(%p,%p)\n",pds,ppds);
1405 ERR("invalid parameter: ppds == NULL\n");
1406 return DSERR_INVALIDPARAM;
1410 ERR("invalid parameter: pds == NULL\n");
1412 return DSERR_INVALIDPARAM;
1415 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1416 if (pdsds == NULL) {
1417 WARN("out of memory\n");
1419 return DSERR_OUTOFMEMORY;
1422 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1426 IDirectSoundImpl_AddRef(pds);
1427 *ppds = (LPDIRECTSOUND)pdsds;
1432 /*******************************************************************************
1433 * IDirectSound8_IDirectSound8
1435 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1436 LPDIRECTSOUND8 iface,
1440 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1441 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1442 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1445 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1446 LPDIRECTSOUND8 iface)
1448 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1449 ULONG ref = InterlockedIncrement(&(This->ref));
1450 TRACE("(%p) ref was %ld\n", This, ref - 1);
1454 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1455 LPDIRECTSOUND8 iface)
1457 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1458 ULONG ref = InterlockedDecrement(&(This->ref));
1459 TRACE("(%p) ref was %ld\n", This, ref + 1);
1461 IDirectSoundImpl_Release(This->pds);
1462 HeapFree(GetProcessHeap(), 0, This);
1463 TRACE("(%p) released\n", This);
1468 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1469 LPDIRECTSOUND8 iface,
1470 LPCDSBUFFERDESC dsbd,
1471 LPLPDIRECTSOUNDBUFFER ppdsb,
1474 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1475 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1476 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1479 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1480 LPDIRECTSOUND8 iface,
1483 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1484 TRACE("(%p,%p)\n",This,lpDSCaps);
1485 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1488 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1489 LPDIRECTSOUND8 iface,
1490 LPDIRECTSOUNDBUFFER psb,
1491 LPLPDIRECTSOUNDBUFFER ppdsb)
1493 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1494 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1495 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1498 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1499 LPDIRECTSOUND8 iface,
1503 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1504 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1505 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1508 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1509 LPDIRECTSOUND8 iface)
1511 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1512 TRACE("(%p)\n", This);
1513 return IDirectSoundImpl_Compact(This->pds);
1516 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1517 LPDIRECTSOUND8 iface,
1518 LPDWORD lpdwSpeakerConfig)
1520 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1521 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1522 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1525 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1526 LPDIRECTSOUND8 iface,
1529 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1530 TRACE("(%p,0x%08lx)\n",This,config);
1531 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1534 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1535 LPDIRECTSOUND8 iface,
1538 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1539 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1540 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1543 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1544 LPDIRECTSOUND8 iface,
1545 LPDWORD pdwCertified)
1547 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1548 TRACE("(%p, %p)\n", This, pdwCertified);
1549 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1552 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1554 IDirectSound8_IDirectSound8_QueryInterface,
1555 IDirectSound8_IDirectSound8_AddRef,
1556 IDirectSound8_IDirectSound8_Release,
1557 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1558 IDirectSound8_IDirectSound8_GetCaps,
1559 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1560 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1561 IDirectSound8_IDirectSound8_Compact,
1562 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1563 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1564 IDirectSound8_IDirectSound8_Initialize,
1565 IDirectSound8_IDirectSound8_VerifyCertification
1568 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1570 LPDIRECTSOUND8 * ppds)
1572 IDirectSound8_IDirectSound8 * pdsds;
1573 TRACE("(%p,%p)\n",pds,ppds);
1576 ERR("invalid parameter: ppds == NULL\n");
1577 return DSERR_INVALIDPARAM;
1581 ERR("invalid parameter: pds == NULL\n");
1583 return DSERR_INVALIDPARAM;
1586 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1587 if (pdsds == NULL) {
1588 WARN("out of memory\n");
1590 return DSERR_OUTOFMEMORY;
1593 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1597 IDirectSoundImpl_AddRef(pds);
1598 *ppds = (LPDIRECTSOUND8)pdsds;
1603 HRESULT WINAPI DSOUND_Create(
1605 LPDIRECTSOUND *ppDS,
1606 IUnknown *pUnkOuter)
1611 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1613 if (pUnkOuter != NULL) {
1614 WARN("invalid parameter: pUnkOuter != NULL\n");
1615 return DSERR_INVALIDPARAM;
1619 WARN("invalid parameter: ppDS == NULL\n");
1620 return DSERR_INVALIDPARAM;
1623 /* Get dsound configuration */
1624 setup_dsound_options();
1626 /* Default device? */
1627 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1628 lpcGUID = &DSDEVID_DefaultPlayback;
1630 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1631 WARN("invalid parameter: lpcGUID\n");
1633 return DSERR_INVALIDPARAM;
1636 if (DSOUND_renderer) {
1637 if (IsEqualGUID(&devGuid, &DSOUND_renderer->guid)) {
1638 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)DSOUND_renderer, ppDS);
1640 IDirectSound_IDirectSound_AddRef(*ppDS);
1642 WARN("IDirectSound_IDirectSound_Create failed\n");
1644 ERR("different dsound already opened (only support one sound card at a time now)\n");
1646 hr = DSERR_ALLOCATED;
1650 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1652 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1654 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1656 IDirectSound_IDirectSound_AddRef(*ppDS);
1658 DSOUND_renderer = (IDirectSoundImpl*)pDS;
1659 timeBeginPeriod(DS_TIME_RES);
1660 DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1661 (DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1663 WARN("IDirectSound_IDirectSound_Create failed\n");
1664 IDirectSound8_Release(pDS);
1667 WARN("DSOUND_PrimaryCreate failed\n");
1668 IDirectSound8_Release(pDS);
1671 WARN("IDirectSoundImpl_Create failed\n");
1677 /*******************************************************************************
1678 * DirectSoundCreate (DSOUND.1)
1680 * Creates and initializes a DirectSound interface.
1683 * lpcGUID [I] Address of the GUID that identifies the sound device.
1684 * ppDS [O] Address of a variable to receive the interface pointer.
1685 * pUnkOuter [I] Must be NULL.
1689 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1690 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1692 HRESULT WINAPI DirectSoundCreate(
1694 LPDIRECTSOUND *ppDS,
1695 IUnknown *pUnkOuter)
1699 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1701 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1703 IDirectSound_Initialize(*ppDS, lpcGUID);
1708 HRESULT WINAPI DSOUND_Create8(
1710 LPDIRECTSOUND8 *ppDS,
1711 IUnknown *pUnkOuter)
1716 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1718 if (pUnkOuter != NULL) {
1719 WARN("invalid parameter: pUnkOuter != NULL\n");
1720 return DSERR_INVALIDPARAM;
1724 WARN("invalid parameter: ppDS == NULL\n");
1725 return DSERR_INVALIDPARAM;
1728 /* Get dsound configuration */
1729 setup_dsound_options();
1731 /* Default device? */
1732 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1733 lpcGUID = &DSDEVID_DefaultPlayback;
1735 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1736 WARN("invalid parameter: lpcGUID\n");
1738 return DSERR_INVALIDPARAM;
1741 if (DSOUND_renderer) {
1742 if (IsEqualGUID(&devGuid, &DSOUND_renderer->guid)) {
1743 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)DSOUND_renderer, ppDS);
1745 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1747 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1749 ERR("different dsound already opened (only support one sound card at a time now)\n");
1751 hr = DSERR_ALLOCATED;
1755 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1757 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1759 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1761 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1763 DSOUND_renderer = (IDirectSoundImpl*)pDS;
1764 timeBeginPeriod(DS_TIME_RES);
1765 DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1766 (DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1768 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1769 IDirectSound8_Release(pDS);
1772 WARN("DSOUND_PrimaryCreate failed\n");
1773 IDirectSound8_Release(pDS);
1776 WARN("IDirectSoundImpl_Create failed\n");
1782 /*******************************************************************************
1783 * DirectSoundCreate8 (DSOUND.11)
1785 * Creates and initializes a DirectSound8 interface.
1788 * lpcGUID [I] Address of the GUID that identifies the sound device.
1789 * ppDS [O] Address of a variable to receive the interface pointer.
1790 * pUnkOuter [I] Must be NULL.
1794 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1795 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1797 HRESULT WINAPI DirectSoundCreate8(
1799 LPDIRECTSOUND8 *ppDS,
1800 IUnknown *pUnkOuter)
1804 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1806 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1808 IDirectSound8_Initialize(*ppDS, lpcGUID);
1814 * Add secondary buffer to buffer list.
1815 * Gets exclusive access to buffer for writing.
1817 HRESULT DSOUND_AddBuffer(
1818 IDirectSoundImpl * pDS,
1819 IDirectSoundBufferImpl * pDSB)
1821 IDirectSoundBufferImpl **newbuffers;
1824 TRACE("(%p, %p)\n", pDS, pDSB);
1826 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1829 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1831 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1834 pDS->buffers = newbuffers;
1835 pDS->buffers[pDS->nrofbuffers] = pDSB;
1837 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1839 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
1840 hr = DSERR_OUTOFMEMORY;
1843 RtlReleaseResource(&(pDS->buffer_list_lock));
1849 * Remove secondary buffer from buffer list.
1850 * Gets exclusive access to buffer for writing.
1852 HRESULT DSOUND_RemoveBuffer(
1853 IDirectSoundImpl * pDS,
1854 IDirectSoundBufferImpl * pDSB)
1859 TRACE("(%p, %p)\n", pDS, pDSB);
1861 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1863 for (i = 0; i < pDS->nrofbuffers; i++)
1864 if (pDS->buffers[i] == pDSB)
1867 if (i < pDS->nrofbuffers) {
1868 /* Put the last buffer of the list in the (now empty) position */
1869 pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
1871 pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
1872 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1875 if (pDS->nrofbuffers == 0) {
1876 HeapFree(GetProcessHeap(),0,pDS->buffers);
1877 pDS->buffers = NULL;
1880 RtlReleaseResource(&(pDS->buffer_list_lock));