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 HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice);
48 static ULONG DirectSoundDevice_Release(DirectSoundDevice * device);
50 static const char * dumpCooperativeLevel(DWORD level)
52 static char unknown[32];
53 #define LE(x) case x: return #x
58 LE(DSSCL_WRITEPRIMARY);
61 sprintf(unknown, "Unknown(%08lx)", level);
65 static void _dump_DSCAPS(DWORD xmask) {
70 #define FE(x) { x, #x },
71 FE(DSCAPS_PRIMARYMONO)
72 FE(DSCAPS_PRIMARYSTEREO)
73 FE(DSCAPS_PRIMARY8BIT)
74 FE(DSCAPS_PRIMARY16BIT)
75 FE(DSCAPS_CONTINUOUSRATE)
78 FE(DSCAPS_SECONDARYMONO)
79 FE(DSCAPS_SECONDARYSTEREO)
80 FE(DSCAPS_SECONDARY8BIT)
81 FE(DSCAPS_SECONDARY16BIT)
86 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
87 if ((flags[i].mask & xmask) == flags[i].mask)
88 DPRINTF("%s ",flags[i].name);
91 static void _dump_DSBCAPS(DWORD xmask) {
96 #define FE(x) { x, #x },
97 FE(DSBCAPS_PRIMARYBUFFER)
99 FE(DSBCAPS_LOCHARDWARE)
100 FE(DSBCAPS_LOCSOFTWARE)
102 FE(DSBCAPS_CTRLFREQUENCY)
104 FE(DSBCAPS_CTRLVOLUME)
105 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
106 FE(DSBCAPS_STICKYFOCUS)
107 FE(DSBCAPS_GLOBALFOCUS)
108 FE(DSBCAPS_GETCURRENTPOSITION2)
109 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
114 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
115 if ((flags[i].mask & xmask) == flags[i].mask)
116 DPRINTF("%s ",flags[i].name);
119 /*******************************************************************************
120 * IDirectSoundImpl_DirectSound
122 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
123 LPDIRECTSOUND8 iface,
127 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
128 FIXME("shouldn't be called directly\n");
129 return E_NOINTERFACE;
132 static HRESULT WINAPI DSOUND_QueryInterface(
133 LPDIRECTSOUND8 iface,
137 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
138 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
141 WARN("invalid parameter\n");
145 if (IsEqualIID(riid, &IID_IUnknown)) {
146 if (!This->pUnknown) {
147 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
148 if (!This->pUnknown) {
149 WARN("IDirectSound_IUnknown_Create() failed\n");
151 return E_NOINTERFACE;
154 IDirectSound_IUnknown_AddRef(This->pUnknown);
155 *ppobj = This->pUnknown;
157 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
159 IDirectSound_IDirectSound_Create(iface, &This->pDS);
161 WARN("IDirectSound_IDirectSound_Create() failed\n");
163 return E_NOINTERFACE;
166 IDirectSound_IDirectSound_AddRef(This->pDS);
172 WARN("Unknown IID %s\n",debugstr_guid(riid));
173 return E_NOINTERFACE;
176 static HRESULT WINAPI DSOUND_QueryInterface8(
177 LPDIRECTSOUND8 iface,
181 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
182 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
185 WARN("invalid parameter\n");
189 if (IsEqualIID(riid, &IID_IUnknown)) {
190 if (!This->pUnknown) {
191 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
192 if (!This->pUnknown) {
193 WARN("IDirectSound8_IUnknown_Create() failed\n");
195 return E_NOINTERFACE;
198 IDirectSound8_IUnknown_AddRef(This->pUnknown);
199 *ppobj = This->pUnknown;
201 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
203 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
205 WARN("IDirectSound8_IDirectSound_Create() failed\n");
207 return E_NOINTERFACE;
210 IDirectSound8_IDirectSound_AddRef(This->pDS);
213 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
215 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
217 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
219 return E_NOINTERFACE;
222 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
228 WARN("Unknown IID %s\n",debugstr_guid(riid));
229 return E_NOINTERFACE;
232 static ULONG WINAPI IDirectSoundImpl_AddRef(
233 LPDIRECTSOUND8 iface)
235 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
236 ULONG ref = InterlockedIncrement(&(This->ref));
237 TRACE("(%p) ref was %ld\n", This, ref - 1);
241 static ULONG WINAPI IDirectSoundImpl_Release(
242 LPDIRECTSOUND8 iface)
244 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
245 ULONG ref = InterlockedDecrement(&(This->ref));
246 TRACE("(%p) ref was %ld\n", This, ref + 1);
250 DirectSoundDevice_Release(This->device);
252 HeapFree(GetProcessHeap(),0,This);
253 TRACE("(%p) released\n", This);
258 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
259 LPDIRECTSOUND8 iface,
260 LPCDSBUFFERDESC dsbd,
261 LPLPDIRECTSOUNDBUFFER ppdsb,
264 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
265 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
266 FIXME("shouldn't be called directly\n");
267 return DSERR_GENERIC;
270 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
271 LPDIRECTSOUND8 iface,
272 LPCDSBUFFERDESC dsbd,
273 LPLPDIRECTSOUNDBUFFER ppdsb,
277 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
278 HRESULT hres = DS_OK;
279 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
282 WARN("invalid parameter: This == NULL\n");
283 return DSERR_INVALIDPARAM;
286 if (This->device == NULL) {
287 WARN("not initialized\n");
288 return DSERR_UNINITIALIZED;
292 WARN("invalid parameter: dsbd == NULL\n");
293 return DSERR_INVALIDPARAM;
296 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
297 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
298 WARN("invalid parameter: dsbd\n");
299 return DSERR_INVALIDPARAM;
303 WARN("invalid parameter: ppdsb == NULL\n");
304 return DSERR_INVALIDPARAM;
307 if (TRACE_ON(dsound)) {
308 TRACE("(structsize=%ld)\n",dsbd->dwSize);
309 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
310 _dump_DSBCAPS(dsbd->dwFlags);
312 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
313 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
316 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
317 if (dsbd->lpwfxFormat != NULL) {
318 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
320 return DSERR_INVALIDPARAM;
323 if (This->device->primary) {
324 WARN("Primary Buffer already created\n");
325 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
326 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
328 This->device->dsbd = *dsbd;
329 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd));
330 if (This->device->primary) {
331 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
332 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
334 WARN("PrimaryBufferImpl_Create failed\n");
337 IDirectSoundBufferImpl * dsb;
339 if (dsbd->lpwfxFormat == NULL) {
340 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
341 "secondary buffer\n");
342 return DSERR_INVALIDPARAM;
345 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
346 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
347 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
348 dsbd->lpwfxFormat->nSamplesPerSec,
349 dsbd->lpwfxFormat->nAvgBytesPerSec,
350 dsbd->lpwfxFormat->nBlockAlign,
351 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
353 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
354 WARN("invalid parameter: 3D buffer format must be mono\n");
355 return DSERR_INVALIDPARAM;
358 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
360 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
362 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
363 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
365 WARN("SecondaryBufferImpl_Create failed\n");
367 WARN("IDirectSoundBufferImpl_Create failed\n");
373 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
374 LPDIRECTSOUND8 iface,
377 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
378 DirectSoundDevice *device;
379 TRACE("(%p,%p)\n",This,lpDSCaps);
382 WARN("invalid parameter: This == NULL\n");
383 return DSERR_INVALIDPARAM;
386 device = This->device;
388 if (device == NULL) {
389 WARN("not initialized\n");
390 return DSERR_UNINITIALIZED;
393 if (lpDSCaps == NULL) {
394 WARN("invalid parameter: lpDSCaps = NULL\n");
395 return DSERR_INVALIDPARAM;
398 /* check if there is enough room */
399 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
400 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
401 lpDSCaps->dwSize, sizeof(*lpDSCaps));
402 return DSERR_INVALIDPARAM;
405 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
406 if (TRACE_ON(dsound)) {
407 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
408 _dump_DSCAPS(lpDSCaps->dwFlags);
411 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
412 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
413 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
414 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
415 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
416 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
417 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
418 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
419 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
420 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
421 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
422 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
423 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
424 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
425 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
426 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
427 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
428 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
430 /* driver doesn't have these */
431 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
432 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
437 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
438 LPDIRECTSOUND8 iface,
439 LPDIRECTSOUNDBUFFER psb,
440 LPLPDIRECTSOUNDBUFFER ppdsb)
442 IDirectSoundBufferImpl* pdsb;
443 IDirectSoundBufferImpl* dsb;
444 HRESULT hres = DS_OK;
446 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
448 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
451 WARN("invalid parameter: This == NULL\n");
452 return DSERR_INVALIDPARAM;
455 if (This->device == NULL) {
456 WARN("not initialized\n");
457 return DSERR_UNINITIALIZED;
461 WARN("invalid parameter: psb == NULL\n");
462 return DSERR_INVALIDPARAM;
466 WARN("invalid parameter: ppdsb == NULL\n");
467 return DSERR_INVALIDPARAM;
470 /* FIXME: hack to make sure we have a secondary buffer */
471 if ((IDirectSoundImpl *)((SecondaryBufferImpl *)psb)->dsb == This) {
472 WARN("trying to duplicate primary buffer\n");
474 return DSERR_INVALIDCALL;
477 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
479 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
482 WARN("out of memory\n");
484 return DSERR_OUTOFMEMORY;
487 CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
490 TRACE("duplicating hardware buffer\n");
492 hres = IDsDriver_DuplicateSoundBuffer(This->device->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
494 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
496 /* allocate buffer */
497 if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
498 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
499 if (dsb->buffer == NULL) {
500 WARN("out of memory\n");
501 HeapFree(GetProcessHeap(),0,dsb);
503 return DSERR_OUTOFMEMORY;
506 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
507 if (dsb->buffer->memory == NULL) {
508 WARN("out of memory\n");
509 HeapFree(GetProcessHeap(),0,dsb->buffer);
510 HeapFree(GetProcessHeap(),0,dsb);
512 return DSERR_OUTOFMEMORY;
514 dsb->buffer->ref = 1;
516 /* FIXME: copy buffer ? */
525 dsb->state = STATE_STOPPED;
530 dsb->iks = NULL; /* FIXME? */
533 /* variable sized struct so calculate size based on format */
534 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
536 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
537 if (dsb->pwfx == NULL) {
538 WARN("out of memory\n");
539 HeapFree(GetProcessHeap(),0,dsb->buffer);
540 HeapFree(GetProcessHeap(),0,dsb);
542 return DSERR_OUTOFMEMORY;
545 CopyMemory(dsb->pwfx, pdsb->pwfx, size);
547 InitializeCriticalSection(&(dsb->lock));
548 dsb->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUNDBUFFER_lock";
550 /* register buffer */
551 hres = DSOUND_AddBuffer(This, dsb);
553 IDirectSoundBuffer8_Release(psb);
554 dsb->lock.DebugInfo->Spare[0] = 0;
555 DeleteCriticalSection(&(dsb->lock));
556 HeapFree(GetProcessHeap(),0,dsb->buffer);
557 HeapFree(GetProcessHeap(),0,dsb->pwfx);
558 HeapFree(GetProcessHeap(),0,dsb);
561 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
563 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
564 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
566 WARN("SecondaryBufferImpl_Create failed\n");
572 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
573 LPDIRECTSOUND8 iface,
577 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
578 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
580 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
581 WARN("level=%s not fully supported\n",
582 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
584 This->device->priolevel = level;
588 static HRESULT WINAPI IDirectSoundImpl_Compact(
589 LPDIRECTSOUND8 iface)
591 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
592 TRACE("(%p)\n",This);
594 if (This->device == NULL) {
595 WARN("not initialized\n");
596 return DSERR_UNINITIALIZED;
599 if (This->device->priolevel != DSSCL_PRIORITY) {
600 WARN("incorrect priority level\n");
601 return DSERR_PRIOLEVELNEEDED;
607 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
608 LPDIRECTSOUND8 iface,
609 LPDWORD lpdwSpeakerConfig)
611 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
612 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
614 if (This->device == NULL) {
615 WARN("not initialized\n");
616 return DSERR_UNINITIALIZED;
619 if (lpdwSpeakerConfig == NULL) {
620 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
621 return DSERR_INVALIDPARAM;
624 WARN("not fully functional\n");
625 *lpdwSpeakerConfig = This->device->speaker_config;
629 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
630 LPDIRECTSOUND8 iface,
633 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
634 TRACE("(%p,0x%08lx)\n",This,config);
636 if (This->device == NULL) {
637 WARN("not initialized\n");
638 return DSERR_UNINITIALIZED;
641 This->device->speaker_config = config;
642 WARN("not fully functional\n");
646 static HRESULT WINAPI IDirectSoundImpl_Initialize(
647 LPDIRECTSOUND8 iface,
650 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
651 DirectSoundDevice *device = This->device;
654 BOOLEAN found = FALSE;
656 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID));
658 if (device != NULL) {
659 WARN("already initialized\n");
660 return DSERR_ALREADYINITIALIZED;
663 /* Default device? */
664 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
665 lpcGUID = &DSDEVID_DefaultPlayback;
667 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
668 WARN("invalid parameter: lpcGUID\n");
669 return DSERR_INVALIDPARAM;
672 /* Enumerate WINMM audio devices and find the one we want */
673 wodn = waveOutGetNumDevs();
676 return DSERR_NODRIVER;
679 for (wod=0; wod<wodn; wod++) {
680 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
686 if (found == FALSE) {
687 WARN("No device found matching given ID!\n");
688 return DSERR_NODRIVER;
691 if (DSOUND_renderer[wod]) {
692 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
693 device = DSOUND_renderer[wod];
695 This->device = device;
698 ERR("device GUID doesn't match\n");
703 hr = DirectSoundDevice_Create(&(device));
705 WARN("DirectSoundDevice_Create failed\n");
710 This->device = device;
711 device->guid = devGUID;
713 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
714 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
716 /* Disable the direct sound driver to force emulation if requested. */
717 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
718 device->driver = NULL;
720 /* Get driver description */
721 if (device->driver) {
722 hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
724 WARN("IDsDriver_GetDriverDesc failed\n");
728 /* if no DirectSound interface available, use WINMM API instead */
729 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
732 device->drvdesc.dnDevNode = wod;
734 /* If the driver requests being opened through MMSYSTEM
735 * (which is recommended by the DDK), it is supposed to happen
736 * before the DirectSound interface is opened */
737 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
739 DWORD flags = CALLBACK_FUNCTION;
741 /* disable direct sound if requested */
742 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
743 flags |= WAVE_DIRECTSOUND;
745 hr = mmErr(waveOutOpen(&(device->hwo),
746 device->drvdesc.dnDevNode, device->pwfx,
747 (DWORD_PTR)DSOUND_callback, (DWORD)device,
750 WARN("waveOutOpen failed\n");
755 if (device->driver) {
756 hr = IDsDriver_Open(device->driver);
758 WARN("IDsDriver_Open failed\n");
762 /* the driver is now open, so it's now allowed to call GetCaps */
763 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
765 WARN("IDsDriver_GetCaps failed\n");
770 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
772 WARN("waveOutGetDevCaps failed\n");
775 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
776 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
777 (woc.dwFormats & WAVE_FORMAT_2M08) ||
778 (woc.dwFormats & WAVE_FORMAT_4M08) ||
779 (woc.dwFormats & WAVE_FORMAT_48M08) ||
780 (woc.dwFormats & WAVE_FORMAT_96M08)) {
781 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
782 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
784 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
785 (woc.dwFormats & WAVE_FORMAT_2M16) ||
786 (woc.dwFormats & WAVE_FORMAT_4M16) ||
787 (woc.dwFormats & WAVE_FORMAT_48M16) ||
788 (woc.dwFormats & WAVE_FORMAT_96M16)) {
789 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
790 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
792 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
793 (woc.dwFormats & WAVE_FORMAT_2S08) ||
794 (woc.dwFormats & WAVE_FORMAT_4S08) ||
795 (woc.dwFormats & WAVE_FORMAT_48S08) ||
796 (woc.dwFormats & WAVE_FORMAT_96S08)) {
797 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
798 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
800 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
801 (woc.dwFormats & WAVE_FORMAT_2S16) ||
802 (woc.dwFormats & WAVE_FORMAT_4S16) ||
803 (woc.dwFormats & WAVE_FORMAT_48S16) ||
804 (woc.dwFormats & WAVE_FORMAT_96S16)) {
805 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
806 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
809 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
810 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
811 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
812 device->drvcaps.dwPrimaryBuffers = 1;
815 hr = DSOUND_PrimaryCreate(device);
817 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
818 timeBeginPeriod(DS_TIME_RES);
819 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
820 (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
822 WARN("DSOUND_PrimaryCreate failed\n");
828 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
829 LPDIRECTSOUND8 iface,
830 LPDWORD pdwCertified)
832 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
833 TRACE("(%p, %p)\n",This,pdwCertified);
835 if (This->device == NULL) {
836 WARN("not initialized\n");
837 return DSERR_UNINITIALIZED;
840 if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
841 *pdwCertified = DS_CERTIFIED;
843 *pdwCertified = DS_UNCERTIFIED;
847 static const IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
849 IDirectSoundImpl_QueryInterface,
850 IDirectSoundImpl_AddRef,
851 IDirectSoundImpl_Release,
852 IDirectSoundImpl_CreateSoundBuffer,
853 IDirectSoundImpl_GetCaps,
854 IDirectSoundImpl_DuplicateSoundBuffer,
855 IDirectSoundImpl_SetCooperativeLevel,
856 IDirectSoundImpl_Compact,
857 IDirectSoundImpl_GetSpeakerConfig,
858 IDirectSoundImpl_SetSpeakerConfig,
859 IDirectSoundImpl_Initialize,
860 IDirectSoundImpl_VerifyCertification
863 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
865 DirectSoundDevice * device;
866 TRACE("(%p)\n", ppDevice);
868 /* Allocate memory */
869 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
870 if (device == NULL) {
871 WARN("out of memory\n");
872 return DSERR_OUTOFMEMORY;
876 device->driver = NULL;
877 device->priolevel = DSSCL_NORMAL;
879 device->hwbuf = NULL;
880 device->buffer = NULL;
882 device->writelead = 0;
883 device->state = STATE_STOPPED;
884 device->nrofbuffers = 0;
885 device->buffers = NULL;
886 device->primary = NULL;
887 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
888 device->tmp_buffer = NULL;
889 device->tmp_buffer_len = 0;
891 /* 3D listener initial parameters */
892 device->listener = NULL;
893 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
894 device->ds3dl.vPosition.x = 0.0;
895 device->ds3dl.vPosition.y = 0.0;
896 device->ds3dl.vPosition.z = 0.0;
897 device->ds3dl.vVelocity.x = 0.0;
898 device->ds3dl.vVelocity.y = 0.0;
899 device->ds3dl.vVelocity.z = 0.0;
900 device->ds3dl.vOrientFront.x = 0.0;
901 device->ds3dl.vOrientFront.y = 0.0;
902 device->ds3dl.vOrientFront.z = 1.0;
903 device->ds3dl.vOrientTop.x = 0.0;
904 device->ds3dl.vOrientTop.y = 1.0;
905 device->ds3dl.vOrientTop.z = 0.0;
906 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
907 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
908 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
910 device->prebuf = ds_snd_queue_max;
911 device->guid = GUID_NULL;
913 /* Set default wave format (may need it for waveOutOpen) */
914 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
915 if (device->pwfx == NULL) {
916 WARN("out of memory\n");
917 HeapFree(GetProcessHeap(),0,device);
918 return DSERR_OUTOFMEMORY;
921 /* We rely on the sound driver to return the actual sound format of
922 * the device if it does not support 22050x8x2 and is given the
923 * WAVE_DIRECTSOUND flag.
925 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
926 device->pwfx->nSamplesPerSec = 22050;
927 device->pwfx->wBitsPerSample = 8;
928 device->pwfx->nChannels = 2;
929 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
930 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
931 device->pwfx->cbSize = 0;
933 InitializeCriticalSection(&(device->mixlock));
934 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock";
936 RtlInitializeResource(&(device->buffer_list_lock));
943 static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
947 TRACE("(%p) ref was %lu\n", device, device->ref);
950 if (device->ref == 0) {
951 timeKillEvent(device->timerID);
952 timeEndPeriod(DS_TIME_RES);
953 /* wait for timer to expire */
954 Sleep(DS_TIME_RES+1);
956 /* The sleep above should have allowed the timer process to expire
957 * but try to grab the lock just in case. Can't hold lock because
958 * IDirectSoundBufferImpl_Destroy also grabs the lock */
959 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
960 RtlReleaseResource(&(device->buffer_list_lock));
962 /* It is allowed to release this object even when buffers are playing */
963 if (device->buffers) {
964 WARN("%d secondary buffers not released\n", device->nrofbuffers);
965 for( i=0;i<device->nrofbuffers;i++)
966 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
969 if (device->primary) {
970 WARN("primary buffer not released\n");
971 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
974 hr = DSOUND_PrimaryDestroy(device);
976 WARN("DSOUND_PrimaryDestroy failed\n");
979 IDsDriver_Close(device->driver);
981 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
982 waveOutClose(device->hwo);
985 IDsDriver_Release(device->driver);
987 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
989 HeapFree(GetProcessHeap(),0,device->tmp_buffer);
990 HeapFree(GetProcessHeap(),0,device->buffer);
991 RtlDeleteResource(&device->buffer_list_lock);
992 device->mixlock.DebugInfo->Spare[0] = 0;
993 DeleteCriticalSection(&device->mixlock);
994 HeapFree(GetProcessHeap(),0,device);
995 TRACE("(%p) released\n", device);
1000 HRESULT WINAPI IDirectSoundImpl_Create(
1001 LPDIRECTSOUND8 * ppDS)
1003 IDirectSoundImpl* pDS;
1004 TRACE("(%p)\n",ppDS);
1006 /* Allocate memory */
1007 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
1009 WARN("out of memory\n");
1011 return DSERR_OUTOFMEMORY;
1014 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
1018 *ppDS = (LPDIRECTSOUND8)pDS;
1023 /*******************************************************************************
1024 * IDirectSound_IUnknown
1026 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
1031 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1032 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1033 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1036 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
1039 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1040 ULONG ref = InterlockedIncrement(&(This->ref));
1041 TRACE("(%p) ref was %ld\n", This, ref - 1);
1045 static ULONG WINAPI IDirectSound_IUnknown_Release(
1048 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1049 ULONG ref = InterlockedDecrement(&(This->ref));
1050 TRACE("(%p) ref was %ld\n", This, ref + 1);
1052 IDirectSoundImpl_Release(This->pds);
1053 HeapFree(GetProcessHeap(), 0, This);
1054 TRACE("(%p) released\n", This);
1059 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
1061 IDirectSound_IUnknown_QueryInterface,
1062 IDirectSound_IUnknown_AddRef,
1063 IDirectSound_IUnknown_Release
1066 HRESULT WINAPI IDirectSound_IUnknown_Create(
1070 IDirectSound_IUnknown * pdsunk;
1071 TRACE("(%p,%p)\n",pds,ppunk);
1073 if (ppunk == NULL) {
1074 ERR("invalid parameter: ppunk == NULL\n");
1075 return DSERR_INVALIDPARAM;
1079 ERR("invalid parameter: pds == NULL\n");
1081 return DSERR_INVALIDPARAM;
1084 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1085 if (pdsunk == NULL) {
1086 WARN("out of memory\n");
1088 return DSERR_OUTOFMEMORY;
1091 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1095 IDirectSoundImpl_AddRef(pds);
1096 *ppunk = (LPUNKNOWN)pdsunk;
1101 /*******************************************************************************
1102 * IDirectSound_IDirectSound
1104 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1105 LPDIRECTSOUND iface,
1109 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1110 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1111 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1114 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1115 LPDIRECTSOUND iface)
1117 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1118 ULONG ref = InterlockedIncrement(&(This->ref));
1119 TRACE("(%p) ref was %ld\n", This, ref - 1);
1123 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1124 LPDIRECTSOUND iface)
1126 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1127 ULONG ref = InterlockedDecrement(&(This->ref));
1128 TRACE("(%p) ref was %ld\n", This, ref + 1);
1130 IDirectSoundImpl_Release(This->pds);
1131 HeapFree(GetProcessHeap(), 0, This);
1132 TRACE("(%p) released\n", This);
1137 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1138 LPDIRECTSOUND iface,
1139 LPCDSBUFFERDESC dsbd,
1140 LPLPDIRECTSOUNDBUFFER ppdsb,
1143 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1144 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1145 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1148 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1149 LPDIRECTSOUND iface,
1152 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1153 TRACE("(%p,%p)\n",This,lpDSCaps);
1154 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1157 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1158 LPDIRECTSOUND iface,
1159 LPDIRECTSOUNDBUFFER psb,
1160 LPLPDIRECTSOUNDBUFFER ppdsb)
1162 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1163 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1164 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1167 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1168 LPDIRECTSOUND iface,
1172 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1173 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1174 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1177 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1178 LPDIRECTSOUND iface)
1180 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1181 TRACE("(%p)\n", This);
1182 return IDirectSoundImpl_Compact(This->pds);
1185 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1186 LPDIRECTSOUND iface,
1187 LPDWORD lpdwSpeakerConfig)
1189 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1190 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1191 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1194 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1195 LPDIRECTSOUND iface,
1198 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1199 TRACE("(%p,0x%08lx)\n",This,config);
1200 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1203 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1204 LPDIRECTSOUND iface,
1207 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1208 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1209 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1212 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1214 IDirectSound_IDirectSound_QueryInterface,
1215 IDirectSound_IDirectSound_AddRef,
1216 IDirectSound_IDirectSound_Release,
1217 IDirectSound_IDirectSound_CreateSoundBuffer,
1218 IDirectSound_IDirectSound_GetCaps,
1219 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1220 IDirectSound_IDirectSound_SetCooperativeLevel,
1221 IDirectSound_IDirectSound_Compact,
1222 IDirectSound_IDirectSound_GetSpeakerConfig,
1223 IDirectSound_IDirectSound_SetSpeakerConfig,
1224 IDirectSound_IDirectSound_Initialize
1227 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1229 LPDIRECTSOUND * ppds)
1231 IDirectSound_IDirectSound * pdsds;
1232 TRACE("(%p,%p)\n",pds,ppds);
1235 ERR("invalid parameter: ppds == NULL\n");
1236 return DSERR_INVALIDPARAM;
1240 ERR("invalid parameter: pds == NULL\n");
1242 return DSERR_INVALIDPARAM;
1245 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1246 if (pdsds == NULL) {
1247 WARN("out of memory\n");
1249 return DSERR_OUTOFMEMORY;
1252 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1256 IDirectSoundImpl_AddRef(pds);
1257 *ppds = (LPDIRECTSOUND)pdsds;
1262 /*******************************************************************************
1263 * IDirectSound8_IUnknown
1265 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1270 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1271 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1272 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1275 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1278 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1279 ULONG ref = InterlockedIncrement(&(This->ref));
1280 TRACE("(%p) ref was %ld\n", This, ref - 1);
1284 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1287 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1288 ULONG ref = InterlockedDecrement(&(This->ref));
1289 TRACE("(%p) ref was %ld\n", This, ref + 1);
1291 IDirectSoundImpl_Release(This->pds);
1292 HeapFree(GetProcessHeap(), 0, This);
1293 TRACE("(%p) released\n", This);
1298 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
1300 IDirectSound8_IUnknown_QueryInterface,
1301 IDirectSound8_IUnknown_AddRef,
1302 IDirectSound8_IUnknown_Release
1305 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1309 IDirectSound8_IUnknown * pdsunk;
1310 TRACE("(%p,%p)\n",pds,ppunk);
1312 if (ppunk == NULL) {
1313 ERR("invalid parameter: ppunk == NULL\n");
1314 return DSERR_INVALIDPARAM;
1318 ERR("invalid parameter: pds == NULL\n");
1320 return DSERR_INVALIDPARAM;
1323 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1324 if (pdsunk == NULL) {
1325 WARN("out of memory\n");
1327 return DSERR_OUTOFMEMORY;
1330 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1334 IDirectSoundImpl_AddRef(pds);
1335 *ppunk = (LPUNKNOWN)pdsunk;
1340 /*******************************************************************************
1341 * IDirectSound8_IDirectSound
1343 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1344 LPDIRECTSOUND iface,
1348 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1349 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1350 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1353 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1354 LPDIRECTSOUND iface)
1356 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1357 ULONG ref = InterlockedIncrement(&(This->ref));
1358 TRACE("(%p) ref was %ld\n", This, ref - 1);
1362 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1363 LPDIRECTSOUND iface)
1365 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1366 ULONG ref = InterlockedDecrement(&(This->ref));
1367 TRACE("(%p) ref was %ld\n", This, ref + 1);
1369 IDirectSoundImpl_Release(This->pds);
1370 HeapFree(GetProcessHeap(), 0, This);
1371 TRACE("(%p) released\n", This);
1376 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1377 LPDIRECTSOUND iface,
1378 LPCDSBUFFERDESC dsbd,
1379 LPLPDIRECTSOUNDBUFFER ppdsb,
1382 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1383 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1384 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1387 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1388 LPDIRECTSOUND iface,
1391 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1392 TRACE("(%p,%p)\n",This,lpDSCaps);
1393 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1396 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1397 LPDIRECTSOUND iface,
1398 LPDIRECTSOUNDBUFFER psb,
1399 LPLPDIRECTSOUNDBUFFER ppdsb)
1401 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1402 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1403 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1406 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1407 LPDIRECTSOUND iface,
1411 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1412 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1413 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1416 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1417 LPDIRECTSOUND iface)
1419 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1420 TRACE("(%p)\n", This);
1421 return IDirectSoundImpl_Compact(This->pds);
1424 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1425 LPDIRECTSOUND iface,
1426 LPDWORD lpdwSpeakerConfig)
1428 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1429 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1430 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1433 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1434 LPDIRECTSOUND iface,
1437 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1438 TRACE("(%p,0x%08lx)\n",This,config);
1439 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1442 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1443 LPDIRECTSOUND iface,
1446 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1447 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1448 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1451 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1453 IDirectSound8_IDirectSound_QueryInterface,
1454 IDirectSound8_IDirectSound_AddRef,
1455 IDirectSound8_IDirectSound_Release,
1456 IDirectSound8_IDirectSound_CreateSoundBuffer,
1457 IDirectSound8_IDirectSound_GetCaps,
1458 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1459 IDirectSound8_IDirectSound_SetCooperativeLevel,
1460 IDirectSound8_IDirectSound_Compact,
1461 IDirectSound8_IDirectSound_GetSpeakerConfig,
1462 IDirectSound8_IDirectSound_SetSpeakerConfig,
1463 IDirectSound8_IDirectSound_Initialize
1466 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1468 LPDIRECTSOUND * ppds)
1470 IDirectSound8_IDirectSound * pdsds;
1471 TRACE("(%p,%p)\n",pds,ppds);
1474 ERR("invalid parameter: ppds == NULL\n");
1475 return DSERR_INVALIDPARAM;
1479 ERR("invalid parameter: pds == NULL\n");
1481 return DSERR_INVALIDPARAM;
1484 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1485 if (pdsds == NULL) {
1486 WARN("out of memory\n");
1488 return DSERR_OUTOFMEMORY;
1491 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1495 IDirectSoundImpl_AddRef(pds);
1496 *ppds = (LPDIRECTSOUND)pdsds;
1501 /*******************************************************************************
1502 * IDirectSound8_IDirectSound8
1504 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1505 LPDIRECTSOUND8 iface,
1509 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1510 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1511 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1514 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1515 LPDIRECTSOUND8 iface)
1517 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1518 ULONG ref = InterlockedIncrement(&(This->ref));
1519 TRACE("(%p) ref was %ld\n", This, ref - 1);
1523 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1524 LPDIRECTSOUND8 iface)
1526 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1527 ULONG ref = InterlockedDecrement(&(This->ref));
1528 TRACE("(%p) ref was %ld\n", This, ref + 1);
1530 IDirectSoundImpl_Release(This->pds);
1531 HeapFree(GetProcessHeap(), 0, This);
1532 TRACE("(%p) released\n", This);
1537 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1538 LPDIRECTSOUND8 iface,
1539 LPCDSBUFFERDESC dsbd,
1540 LPLPDIRECTSOUNDBUFFER ppdsb,
1543 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1544 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1545 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1548 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1549 LPDIRECTSOUND8 iface,
1552 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1553 TRACE("(%p,%p)\n",This,lpDSCaps);
1554 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1557 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1558 LPDIRECTSOUND8 iface,
1559 LPDIRECTSOUNDBUFFER psb,
1560 LPLPDIRECTSOUNDBUFFER ppdsb)
1562 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1563 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1564 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1567 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1568 LPDIRECTSOUND8 iface,
1572 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1573 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1574 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1577 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1578 LPDIRECTSOUND8 iface)
1580 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1581 TRACE("(%p)\n", This);
1582 return IDirectSoundImpl_Compact(This->pds);
1585 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1586 LPDIRECTSOUND8 iface,
1587 LPDWORD lpdwSpeakerConfig)
1589 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1590 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1591 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1594 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1595 LPDIRECTSOUND8 iface,
1598 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1599 TRACE("(%p,0x%08lx)\n",This,config);
1600 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1603 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1604 LPDIRECTSOUND8 iface,
1607 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1608 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1609 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1612 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1613 LPDIRECTSOUND8 iface,
1614 LPDWORD pdwCertified)
1616 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1617 TRACE("(%p, %p)\n", This, pdwCertified);
1618 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1621 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1623 IDirectSound8_IDirectSound8_QueryInterface,
1624 IDirectSound8_IDirectSound8_AddRef,
1625 IDirectSound8_IDirectSound8_Release,
1626 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1627 IDirectSound8_IDirectSound8_GetCaps,
1628 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1629 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1630 IDirectSound8_IDirectSound8_Compact,
1631 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1632 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1633 IDirectSound8_IDirectSound8_Initialize,
1634 IDirectSound8_IDirectSound8_VerifyCertification
1637 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1639 LPDIRECTSOUND8 * ppds)
1641 IDirectSound8_IDirectSound8 * pdsds;
1642 TRACE("(%p,%p)\n",pds,ppds);
1645 ERR("invalid parameter: ppds == NULL\n");
1646 return DSERR_INVALIDPARAM;
1650 ERR("invalid parameter: pds == NULL\n");
1652 return DSERR_INVALIDPARAM;
1655 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1656 if (pdsds == NULL) {
1657 WARN("out of memory\n");
1659 return DSERR_OUTOFMEMORY;
1662 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1666 IDirectSoundImpl_AddRef(pds);
1667 *ppds = (LPDIRECTSOUND8)pdsds;
1672 HRESULT WINAPI DSOUND_Create(
1673 LPDIRECTSOUND *ppDS,
1674 IUnknown *pUnkOuter)
1678 TRACE("(%p,%p)\n",ppDS,pUnkOuter);
1680 /* Get dsound configuration */
1681 setup_dsound_options();
1683 hr = IDirectSoundImpl_Create(&pDS);
1685 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1687 IDirectSound_IDirectSound_AddRef(*ppDS);
1689 WARN("IDirectSound_IDirectSound_Create failed\n");
1690 IDirectSound8_Release(pDS);
1693 WARN("IDirectSoundImpl_Create failed\n");
1700 /*******************************************************************************
1701 * DirectSoundCreate (DSOUND.1)
1703 * Creates and initializes a DirectSound interface.
1706 * lpcGUID [I] Address of the GUID that identifies the sound device.
1707 * ppDS [O] Address of a variable to receive the interface pointer.
1708 * pUnkOuter [I] Must be NULL.
1712 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1713 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1715 HRESULT WINAPI DirectSoundCreate(
1717 LPDIRECTSOUND *ppDS,
1718 IUnknown *pUnkOuter)
1723 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1726 WARN("invalid parameter: ppDS == NULL\n");
1727 return DSERR_INVALIDPARAM;
1730 if (pUnkOuter != NULL) {
1731 WARN("invalid parameter: pUnkOuter != NULL\n");
1733 return DSERR_INVALIDPARAM;
1736 hr = DSOUND_Create(&pDS, pUnkOuter);
1738 hr = IDirectSound_Initialize(pDS, lpcGUID);
1740 if (hr != DSERR_ALREADYINITIALIZED) {
1741 IDirectSound_Release(pDS);
1753 HRESULT WINAPI DSOUND_Create8(
1754 LPDIRECTSOUND8 *ppDS,
1755 IUnknown *pUnkOuter)
1759 TRACE("(%p,%p)\n",ppDS,pUnkOuter);
1761 /* Get dsound configuration */
1762 setup_dsound_options();
1764 hr = IDirectSoundImpl_Create(&pDS);
1766 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1768 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1770 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1771 IDirectSound8_Release(pDS);
1774 WARN("IDirectSoundImpl_Create failed\n");
1781 /*******************************************************************************
1782 * DirectSoundCreate8 (DSOUND.11)
1784 * Creates and initializes a DirectSound8 interface.
1787 * lpcGUID [I] Address of the GUID that identifies the sound device.
1788 * ppDS [O] Address of a variable to receive the interface pointer.
1789 * pUnkOuter [I] Must be NULL.
1793 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1794 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1796 HRESULT WINAPI DirectSoundCreate8(
1798 LPDIRECTSOUND8 *ppDS,
1799 IUnknown *pUnkOuter)
1804 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1807 WARN("invalid parameter: ppDS == NULL\n");
1808 return DSERR_INVALIDPARAM;
1811 if (pUnkOuter != NULL) {
1812 WARN("invalid parameter: pUnkOuter != NULL\n");
1814 return DSERR_INVALIDPARAM;
1817 hr = DSOUND_Create8(&pDS, pUnkOuter);
1819 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1821 if (hr != DSERR_ALREADYINITIALIZED) {
1822 IDirectSound8_Release(pDS);
1835 * Add secondary buffer to buffer list.
1836 * Gets exclusive access to buffer for writing.
1838 HRESULT DSOUND_AddBuffer(
1839 IDirectSoundImpl * pDS,
1840 IDirectSoundBufferImpl * pDSB)
1842 IDirectSoundBufferImpl **newbuffers;
1845 TRACE("(%p, %p)\n", pDS, pDSB);
1847 RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
1849 if (pDS->device->buffers)
1850 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
1852 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
1855 pDS->device->buffers = newbuffers;
1856 pDS->device->buffers[pDS->device->nrofbuffers] = pDSB;
1857 pDS->device->nrofbuffers++;
1858 TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
1860 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->device->nrofbuffers);
1861 hr = DSERR_OUTOFMEMORY;
1864 RtlReleaseResource(&(pDS->device->buffer_list_lock));
1870 * Remove secondary buffer from buffer list.
1871 * Gets exclusive access to buffer for writing.
1873 HRESULT DSOUND_RemoveBuffer(
1874 IDirectSoundImpl * pDS,
1875 IDirectSoundBufferImpl * pDSB)
1880 TRACE("(%p, %p)\n", pDS, pDSB);
1882 RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
1884 for (i = 0; i < pDS->device->nrofbuffers; i++)
1885 if (pDS->device->buffers[i] == pDSB)
1888 if (i < pDS->device->nrofbuffers) {
1889 /* Put the last buffer of the list in the (now empty) position */
1890 pDS->device->buffers[i] = pDS->device->buffers[pDS->device->nrofbuffers - 1];
1891 pDS->device->nrofbuffers--;
1892 pDS->device->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->device->nrofbuffers);
1893 TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
1896 if (pDS->device->nrofbuffers == 0) {
1897 HeapFree(GetProcessHeap(),0,pDS->device->buffers);
1898 pDS->device->buffers = NULL;
1901 RtlReleaseResource(&(pDS->device->buffer_list_lock));