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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #define NONAMELESSSTRUCT
28 #define NONAMELESSUNION
38 #include "wine/debug.h"
40 #include "dsound_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
44 /*****************************************************************************
45 * IDirectSound COM components
47 struct IDirectSound_IUnknown {
48 const IUnknownVtbl *lpVtbl;
53 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
55 struct IDirectSound_IDirectSound {
56 const IDirectSoundVtbl *lpVtbl;
61 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
63 /*****************************************************************************
64 * IDirectSound8 COM components
66 struct IDirectSound8_IUnknown {
67 const IUnknownVtbl *lpVtbl;
72 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
73 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
75 struct IDirectSound8_IDirectSound {
76 const IDirectSoundVtbl *lpVtbl;
81 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
82 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
84 struct IDirectSound8_IDirectSound8 {
85 const IDirectSound8Vtbl *lpVtbl;
90 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
91 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
93 /*****************************************************************************
94 * IDirectSound implementation structure
96 struct IDirectSoundImpl
100 DirectSoundDevice *device;
106 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
108 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
109 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
111 const char * dumpCooperativeLevel(DWORD level)
113 #define LE(x) case x: return #x
118 LE(DSSCL_WRITEPRIMARY);
121 return wine_dbg_sprintf("Unknown(%08x)", level);
124 static void _dump_DSCAPS(DWORD xmask) {
129 #define FE(x) { x, #x },
130 FE(DSCAPS_PRIMARYMONO)
131 FE(DSCAPS_PRIMARYSTEREO)
132 FE(DSCAPS_PRIMARY8BIT)
133 FE(DSCAPS_PRIMARY16BIT)
134 FE(DSCAPS_CONTINUOUSRATE)
135 FE(DSCAPS_EMULDRIVER)
137 FE(DSCAPS_SECONDARYMONO)
138 FE(DSCAPS_SECONDARYSTEREO)
139 FE(DSCAPS_SECONDARY8BIT)
140 FE(DSCAPS_SECONDARY16BIT)
145 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
146 if ((flags[i].mask & xmask) == flags[i].mask)
147 TRACE("%s ",flags[i].name);
150 static void _dump_DSBCAPS(DWORD xmask) {
155 #define FE(x) { x, #x },
156 FE(DSBCAPS_PRIMARYBUFFER)
158 FE(DSBCAPS_LOCHARDWARE)
159 FE(DSBCAPS_LOCSOFTWARE)
161 FE(DSBCAPS_CTRLFREQUENCY)
163 FE(DSBCAPS_CTRLVOLUME)
164 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
165 FE(DSBCAPS_STICKYFOCUS)
166 FE(DSBCAPS_GLOBALFOCUS)
167 FE(DSBCAPS_GETCURRENTPOSITION2)
168 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
173 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
174 if ((flags[i].mask & xmask) == flags[i].mask)
175 TRACE("%s ",flags[i].name);
178 /*******************************************************************************
179 * IDirectSoundImpl_DirectSound
181 static HRESULT DSOUND_QueryInterface(
182 LPDIRECTSOUND8 iface,
186 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
187 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
190 WARN("invalid parameter\n");
194 if (IsEqualIID(riid, &IID_IUnknown)) {
195 if (!This->pUnknown) {
196 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
197 if (!This->pUnknown) {
198 WARN("IDirectSound_IUnknown_Create() failed\n");
200 return E_NOINTERFACE;
203 IDirectSound_IUnknown_AddRef(This->pUnknown);
204 *ppobj = This->pUnknown;
206 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
208 IDirectSound_IDirectSound_Create(iface, &This->pDS);
210 WARN("IDirectSound_IDirectSound_Create() failed\n");
212 return E_NOINTERFACE;
215 IDirectSound_IDirectSound_AddRef(This->pDS);
221 WARN("Unknown IID %s\n",debugstr_guid(riid));
222 return E_NOINTERFACE;
225 static HRESULT DSOUND_QueryInterface8(
226 LPDIRECTSOUND8 iface,
230 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
231 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
234 WARN("invalid parameter\n");
238 if (IsEqualIID(riid, &IID_IUnknown)) {
239 if (!This->pUnknown) {
240 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
241 if (!This->pUnknown) {
242 WARN("IDirectSound8_IUnknown_Create() failed\n");
244 return E_NOINTERFACE;
247 IDirectSound8_IUnknown_AddRef(This->pUnknown);
248 *ppobj = This->pUnknown;
250 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
252 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
254 WARN("IDirectSound8_IDirectSound_Create() failed\n");
256 return E_NOINTERFACE;
259 IDirectSound8_IDirectSound_AddRef(This->pDS);
262 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
264 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
266 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
268 return E_NOINTERFACE;
271 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
277 WARN("Unknown IID %s\n",debugstr_guid(riid));
278 return E_NOINTERFACE;
281 static ULONG IDirectSoundImpl_AddRef(
282 LPDIRECTSOUND8 iface)
284 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
285 ULONG ref = InterlockedIncrement(&(This->ref));
286 TRACE("(%p) ref was %d\n", This, ref - 1);
290 static ULONG IDirectSoundImpl_Release(
291 LPDIRECTSOUND8 iface)
293 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
294 ULONG ref = InterlockedDecrement(&(This->ref));
295 TRACE("(%p) ref was %d\n", This, ref + 1);
299 DirectSoundDevice_Release(This->device);
300 HeapFree(GetProcessHeap(),0,This);
301 TRACE("(%p) released\n", This);
306 static HRESULT IDirectSoundImpl_Create(
307 LPDIRECTSOUND8 * ppDS)
309 IDirectSoundImpl* pDS;
310 TRACE("(%p)\n",ppDS);
312 /* Allocate memory */
313 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
315 WARN("out of memory\n");
317 return DSERR_OUTOFMEMORY;
323 *ppDS = (LPDIRECTSOUND8)pDS;
328 /*******************************************************************************
329 * IDirectSound_IUnknown
331 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
336 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
337 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
338 return DSOUND_QueryInterface(This->pds, riid, ppobj);
341 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
344 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
345 ULONG ref = InterlockedIncrement(&(This->ref));
346 TRACE("(%p) ref was %d\n", This, ref - 1);
350 static ULONG WINAPI IDirectSound_IUnknown_Release(
353 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
354 ULONG ref = InterlockedDecrement(&(This->ref));
355 TRACE("(%p) ref was %d\n", This, ref + 1);
357 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
358 IDirectSoundImpl_Release(This->pds);
359 HeapFree(GetProcessHeap(), 0, This);
360 TRACE("(%p) released\n", This);
365 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
367 IDirectSound_IUnknown_QueryInterface,
368 IDirectSound_IUnknown_AddRef,
369 IDirectSound_IUnknown_Release
372 static HRESULT IDirectSound_IUnknown_Create(
376 IDirectSound_IUnknown * pdsunk;
377 TRACE("(%p,%p)\n",pds,ppunk);
380 ERR("invalid parameter: ppunk == NULL\n");
381 return DSERR_INVALIDPARAM;
385 ERR("invalid parameter: pds == NULL\n");
387 return DSERR_INVALIDPARAM;
390 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
391 if (pdsunk == NULL) {
392 WARN("out of memory\n");
394 return DSERR_OUTOFMEMORY;
397 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
401 IDirectSoundImpl_AddRef(pds);
402 *ppunk = (LPUNKNOWN)pdsunk;
407 /*******************************************************************************
408 * IDirectSound_IDirectSound
410 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
415 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
416 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
417 return DSOUND_QueryInterface(This->pds, riid, ppobj);
420 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
423 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
424 ULONG ref = InterlockedIncrement(&(This->ref));
425 TRACE("(%p) ref was %d\n", This, ref - 1);
429 static ULONG WINAPI IDirectSound_IDirectSound_Release(
432 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
433 ULONG ref = InterlockedDecrement(&(This->ref));
434 TRACE("(%p) ref was %d\n", This, ref + 1);
436 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
437 IDirectSoundImpl_Release(This->pds);
438 HeapFree(GetProcessHeap(), 0, This);
439 TRACE("(%p) released\n", This);
444 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
446 LPCDSBUFFERDESC dsbd,
447 LPLPDIRECTSOUNDBUFFER ppdsb,
450 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
451 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
452 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
455 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
459 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
460 TRACE("(%p,%p)\n",This,lpDSCaps);
461 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
464 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
466 LPDIRECTSOUNDBUFFER psb,
467 LPLPDIRECTSOUNDBUFFER ppdsb)
469 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
470 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
471 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
474 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
479 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
480 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
481 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
484 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
487 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
488 TRACE("(%p)\n", This);
489 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
492 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
494 LPDWORD lpdwSpeakerConfig)
496 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
497 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
498 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
501 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
505 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
506 TRACE("(%p,0x%08x)\n",This,config);
507 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
510 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
514 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
515 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
516 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
519 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
521 IDirectSound_IDirectSound_QueryInterface,
522 IDirectSound_IDirectSound_AddRef,
523 IDirectSound_IDirectSound_Release,
524 IDirectSound_IDirectSound_CreateSoundBuffer,
525 IDirectSound_IDirectSound_GetCaps,
526 IDirectSound_IDirectSound_DuplicateSoundBuffer,
527 IDirectSound_IDirectSound_SetCooperativeLevel,
528 IDirectSound_IDirectSound_Compact,
529 IDirectSound_IDirectSound_GetSpeakerConfig,
530 IDirectSound_IDirectSound_SetSpeakerConfig,
531 IDirectSound_IDirectSound_Initialize
534 static HRESULT IDirectSound_IDirectSound_Create(
536 LPDIRECTSOUND * ppds)
538 IDirectSound_IDirectSound * pdsds;
539 TRACE("(%p,%p)\n",pds,ppds);
542 ERR("invalid parameter: ppds == NULL\n");
543 return DSERR_INVALIDPARAM;
547 ERR("invalid parameter: pds == NULL\n");
549 return DSERR_INVALIDPARAM;
552 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
554 WARN("out of memory\n");
556 return DSERR_OUTOFMEMORY;
559 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
563 IDirectSoundImpl_AddRef(pds);
564 *ppds = (LPDIRECTSOUND)pdsds;
569 /*******************************************************************************
570 * IDirectSound8_IUnknown
572 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
577 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
578 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
579 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
582 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
585 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
586 ULONG ref = InterlockedIncrement(&(This->ref));
587 TRACE("(%p) ref was %d\n", This, ref - 1);
591 static ULONG WINAPI IDirectSound8_IUnknown_Release(
594 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
595 ULONG ref = InterlockedDecrement(&(This->ref));
596 TRACE("(%p) ref was %d\n", This, ref + 1);
598 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
599 IDirectSoundImpl_Release(This->pds);
600 HeapFree(GetProcessHeap(), 0, This);
601 TRACE("(%p) released\n", This);
606 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
608 IDirectSound8_IUnknown_QueryInterface,
609 IDirectSound8_IUnknown_AddRef,
610 IDirectSound8_IUnknown_Release
613 static HRESULT IDirectSound8_IUnknown_Create(
617 IDirectSound8_IUnknown * pdsunk;
618 TRACE("(%p,%p)\n",pds,ppunk);
621 ERR("invalid parameter: ppunk == NULL\n");
622 return DSERR_INVALIDPARAM;
626 ERR("invalid parameter: pds == NULL\n");
628 return DSERR_INVALIDPARAM;
631 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
632 if (pdsunk == NULL) {
633 WARN("out of memory\n");
635 return DSERR_OUTOFMEMORY;
638 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
642 IDirectSoundImpl_AddRef(pds);
643 *ppunk = (LPUNKNOWN)pdsunk;
648 /*******************************************************************************
649 * IDirectSound8_IDirectSound
651 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
656 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
657 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
658 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
661 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
664 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
665 ULONG ref = InterlockedIncrement(&(This->ref));
666 TRACE("(%p) ref was %d\n", This, ref - 1);
670 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
673 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
674 ULONG ref = InterlockedDecrement(&(This->ref));
675 TRACE("(%p) ref was %d\n", This, ref + 1);
677 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
678 IDirectSoundImpl_Release(This->pds);
679 HeapFree(GetProcessHeap(), 0, This);
680 TRACE("(%p) released\n", This);
685 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
687 LPCDSBUFFERDESC dsbd,
688 LPLPDIRECTSOUNDBUFFER ppdsb,
691 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
692 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
693 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
696 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
700 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
701 TRACE("(%p,%p)\n",This,lpDSCaps);
702 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
705 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
707 LPDIRECTSOUNDBUFFER psb,
708 LPLPDIRECTSOUNDBUFFER ppdsb)
710 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
711 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
712 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
715 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
720 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
721 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
722 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
725 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
728 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
729 TRACE("(%p)\n", This);
730 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
733 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
735 LPDWORD lpdwSpeakerConfig)
737 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
738 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
739 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
742 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
746 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
747 TRACE("(%p,0x%08x)\n",This,config);
748 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
751 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
755 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
756 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
757 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
760 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
762 IDirectSound8_IDirectSound_QueryInterface,
763 IDirectSound8_IDirectSound_AddRef,
764 IDirectSound8_IDirectSound_Release,
765 IDirectSound8_IDirectSound_CreateSoundBuffer,
766 IDirectSound8_IDirectSound_GetCaps,
767 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
768 IDirectSound8_IDirectSound_SetCooperativeLevel,
769 IDirectSound8_IDirectSound_Compact,
770 IDirectSound8_IDirectSound_GetSpeakerConfig,
771 IDirectSound8_IDirectSound_SetSpeakerConfig,
772 IDirectSound8_IDirectSound_Initialize
775 static HRESULT IDirectSound8_IDirectSound_Create(
777 LPDIRECTSOUND * ppds)
779 IDirectSound8_IDirectSound * pdsds;
780 TRACE("(%p,%p)\n",pds,ppds);
783 ERR("invalid parameter: ppds == NULL\n");
784 return DSERR_INVALIDPARAM;
788 ERR("invalid parameter: pds == NULL\n");
790 return DSERR_INVALIDPARAM;
793 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
795 WARN("out of memory\n");
797 return DSERR_OUTOFMEMORY;
800 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
804 IDirectSoundImpl_AddRef(pds);
805 *ppds = (LPDIRECTSOUND)pdsds;
810 /*******************************************************************************
811 * IDirectSound8_IDirectSound8
813 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
814 LPDIRECTSOUND8 iface,
818 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
819 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
820 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
823 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
824 LPDIRECTSOUND8 iface)
826 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
827 ULONG ref = InterlockedIncrement(&(This->ref));
828 TRACE("(%p) ref was %d\n", This, ref - 1);
832 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
833 LPDIRECTSOUND8 iface)
835 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
836 ULONG ref = InterlockedDecrement(&(This->ref));
837 TRACE("(%p) ref was %d\n", This, ref + 1);
839 ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
840 IDirectSoundImpl_Release(This->pds);
841 HeapFree(GetProcessHeap(), 0, This);
842 TRACE("(%p) released\n", This);
847 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
848 LPDIRECTSOUND8 iface,
849 LPCDSBUFFERDESC dsbd,
850 LPLPDIRECTSOUNDBUFFER ppdsb,
853 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
854 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
855 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
858 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
859 LPDIRECTSOUND8 iface,
862 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
863 TRACE("(%p,%p)\n",This,lpDSCaps);
864 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
867 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
868 LPDIRECTSOUND8 iface,
869 LPDIRECTSOUNDBUFFER psb,
870 LPLPDIRECTSOUNDBUFFER ppdsb)
872 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
873 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
874 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
877 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
878 LPDIRECTSOUND8 iface,
882 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
883 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
884 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
887 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
888 LPDIRECTSOUND8 iface)
890 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
891 TRACE("(%p)\n", This);
892 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
895 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
896 LPDIRECTSOUND8 iface,
897 LPDWORD lpdwSpeakerConfig)
899 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
900 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
901 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
904 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
905 LPDIRECTSOUND8 iface,
908 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
909 TRACE("(%p,0x%08x)\n",This,config);
910 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
913 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
914 LPDIRECTSOUND8 iface,
917 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
918 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
919 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
922 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
923 LPDIRECTSOUND8 iface,
924 LPDWORD pdwCertified)
926 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
927 TRACE("(%p, %p)\n", This, pdwCertified);
928 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
931 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
933 IDirectSound8_IDirectSound8_QueryInterface,
934 IDirectSound8_IDirectSound8_AddRef,
935 IDirectSound8_IDirectSound8_Release,
936 IDirectSound8_IDirectSound8_CreateSoundBuffer,
937 IDirectSound8_IDirectSound8_GetCaps,
938 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
939 IDirectSound8_IDirectSound8_SetCooperativeLevel,
940 IDirectSound8_IDirectSound8_Compact,
941 IDirectSound8_IDirectSound8_GetSpeakerConfig,
942 IDirectSound8_IDirectSound8_SetSpeakerConfig,
943 IDirectSound8_IDirectSound8_Initialize,
944 IDirectSound8_IDirectSound8_VerifyCertification
947 static HRESULT IDirectSound8_IDirectSound8_Create(
949 LPDIRECTSOUND8 * ppds)
951 IDirectSound8_IDirectSound8 * pdsds;
952 TRACE("(%p,%p)\n",pds,ppds);
955 ERR("invalid parameter: ppds == NULL\n");
956 return DSERR_INVALIDPARAM;
960 ERR("invalid parameter: pds == NULL\n");
962 return DSERR_INVALIDPARAM;
965 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
967 WARN("out of memory\n");
969 return DSERR_OUTOFMEMORY;
972 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
976 IDirectSoundImpl_AddRef(pds);
977 *ppds = (LPDIRECTSOUND8)pdsds;
982 HRESULT DSOUND_Create(
988 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
990 if (!IsEqualIID(riid, &IID_IUnknown) &&
991 !IsEqualIID(riid, &IID_IDirectSound)) {
993 return E_NOINTERFACE;
996 /* Get dsound configuration */
997 setup_dsound_options();
999 hr = IDirectSoundImpl_Create(&pDS);
1001 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1003 IDirectSound_IDirectSound_AddRef(*ppDS);
1005 WARN("IDirectSound_IDirectSound_Create failed\n");
1006 IDirectSound8_Release(pDS);
1009 WARN("IDirectSoundImpl_Create failed\n");
1016 /*******************************************************************************
1017 * DirectSoundCreate (DSOUND.1)
1019 * Creates and initializes a DirectSound interface.
1022 * lpcGUID [I] Address of the GUID that identifies the sound device.
1023 * ppDS [O] Address of a variable to receive the interface pointer.
1024 * pUnkOuter [I] Must be NULL.
1028 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1029 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1031 HRESULT WINAPI DirectSoundCreate(
1033 LPDIRECTSOUND *ppDS,
1034 IUnknown *pUnkOuter)
1039 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1042 WARN("invalid parameter: ppDS == NULL\n");
1043 return DSERR_INVALIDPARAM;
1046 if (pUnkOuter != NULL) {
1047 WARN("invalid parameter: pUnkOuter != NULL\n");
1049 return DSERR_INVALIDPARAM;
1052 hr = DSOUND_Create(&IID_IDirectSound, &pDS);
1054 hr = IDirectSound_Initialize(pDS, lpcGUID);
1056 if (hr != DSERR_ALREADYINITIALIZED) {
1057 IDirectSound_Release(pDS);
1069 HRESULT DSOUND_Create8(
1071 LPDIRECTSOUND8 *ppDS)
1075 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
1077 if (!IsEqualIID(riid, &IID_IUnknown) &&
1078 !IsEqualIID(riid, &IID_IDirectSound) &&
1079 !IsEqualIID(riid, &IID_IDirectSound8)) {
1081 return E_NOINTERFACE;
1084 /* Get dsound configuration */
1085 setup_dsound_options();
1087 hr = IDirectSoundImpl_Create(&pDS);
1089 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1091 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1093 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1094 IDirectSound8_Release(pDS);
1097 WARN("IDirectSoundImpl_Create failed\n");
1104 /*******************************************************************************
1105 * DirectSoundCreate8 (DSOUND.11)
1107 * Creates and initializes a DirectSound8 interface.
1110 * lpcGUID [I] Address of the GUID that identifies the sound device.
1111 * ppDS [O] Address of a variable to receive the interface pointer.
1112 * pUnkOuter [I] Must be NULL.
1116 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1117 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1119 HRESULT WINAPI DirectSoundCreate8(
1121 LPDIRECTSOUND8 *ppDS,
1122 IUnknown *pUnkOuter)
1127 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1130 WARN("invalid parameter: ppDS == NULL\n");
1131 return DSERR_INVALIDPARAM;
1134 if (pUnkOuter != NULL) {
1135 WARN("invalid parameter: pUnkOuter != NULL\n");
1137 return DSERR_INVALIDPARAM;
1140 hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
1142 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1144 if (hr != DSERR_ALREADYINITIALIZED) {
1145 IDirectSound8_Release(pDS);
1157 /*******************************************************************************
1160 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
1162 DirectSoundDevice * device;
1163 TRACE("(%p)\n", ppDevice);
1165 /* Allocate memory */
1166 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
1167 if (device == NULL) {
1168 WARN("out of memory\n");
1169 return DSERR_OUTOFMEMORY;
1173 device->priolevel = DSSCL_NORMAL;
1174 device->state = STATE_STOPPED;
1175 device->speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, DSSPEAKER_GEOMETRY_WIDE);
1177 /* 3D listener initial parameters */
1178 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1179 device->ds3dl.vPosition.x = 0.0;
1180 device->ds3dl.vPosition.y = 0.0;
1181 device->ds3dl.vPosition.z = 0.0;
1182 device->ds3dl.vVelocity.x = 0.0;
1183 device->ds3dl.vVelocity.y = 0.0;
1184 device->ds3dl.vVelocity.z = 0.0;
1185 device->ds3dl.vOrientFront.x = 0.0;
1186 device->ds3dl.vOrientFront.y = 0.0;
1187 device->ds3dl.vOrientFront.z = 1.0;
1188 device->ds3dl.vOrientTop.x = 0.0;
1189 device->ds3dl.vOrientTop.y = 1.0;
1190 device->ds3dl.vOrientTop.z = 0.0;
1191 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1192 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1193 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1195 device->prebuf = ds_snd_queue_max;
1196 device->guid = GUID_NULL;
1198 /* Set default wave format (may need it for waveOutOpen) */
1199 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
1200 if (device->pwfx == NULL) {
1201 WARN("out of memory\n");
1202 HeapFree(GetProcessHeap(),0,device);
1203 return DSERR_OUTOFMEMORY;
1206 /* We rely on the sound driver to return the actual sound format of
1207 * the device if it does not support 22050x8x2 and is given the
1208 * WAVE_DIRECTSOUND flag.
1210 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1211 device->pwfx->nSamplesPerSec = ds_default_sample_rate;
1212 device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
1213 device->pwfx->nChannels = 2;
1214 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
1215 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
1216 device->pwfx->cbSize = 0;
1218 InitializeCriticalSection(&(device->mixlock));
1219 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
1221 RtlInitializeResource(&(device->buffer_list_lock));
1228 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
1230 ULONG ref = InterlockedIncrement(&(device->ref));
1231 TRACE("(%p) ref was %d\n", device, ref - 1);
1235 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
1238 ULONG ref = InterlockedDecrement(&(device->ref));
1239 TRACE("(%p) ref was %u\n", device, ref + 1);
1242 timeKillEvent(device->timerID);
1243 timeEndPeriod(DS_TIME_RES);
1245 /* The kill event should have allowed the timer process to expire
1246 * but try to grab the lock just in case. Can't hold lock because
1247 * secondarybuffer_destroy also grabs the lock */
1248 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1249 RtlReleaseResource(&(device->buffer_list_lock));
1251 EnterCriticalSection(&DSOUND_renderers_lock);
1252 list_remove(&device->entry);
1253 LeaveCriticalSection(&DSOUND_renderers_lock);
1255 /* It is allowed to release this object even when buffers are playing */
1256 if (device->buffers) {
1257 WARN("%d secondary buffers not released\n", device->nrofbuffers);
1258 for( i=0;i<device->nrofbuffers;i++)
1259 secondarybuffer_destroy(device->buffers[i]);
1262 if (device->primary) {
1263 WARN("primary buffer not released\n");
1264 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
1267 hr = DSOUND_PrimaryDestroy(device);
1269 WARN("DSOUND_PrimaryDestroy failed\n");
1272 IAudioClient_Release(device->client);
1274 IAudioRenderClient_Release(device->render);
1276 IAudioClock_Release(device->clock);
1278 IAudioStreamVolume_Release(device->volume);
1280 HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
1281 HeapFree(GetProcessHeap(), 0, device->mix_buffer);
1282 HeapFree(GetProcessHeap(), 0, device->buffer);
1283 RtlDeleteResource(&device->buffer_list_lock);
1284 device->mixlock.DebugInfo->Spare[0] = 0;
1285 DeleteCriticalSection(&device->mixlock);
1286 HeapFree(GetProcessHeap(),0,device);
1287 TRACE("(%p) released\n", device);
1292 HRESULT DirectSoundDevice_GetCaps(
1293 DirectSoundDevice * device,
1296 TRACE("(%p,%p)\n",device,lpDSCaps);
1298 if (device == NULL) {
1299 WARN("not initialized\n");
1300 return DSERR_UNINITIALIZED;
1303 if (lpDSCaps == NULL) {
1304 WARN("invalid parameter: lpDSCaps = NULL\n");
1305 return DSERR_INVALIDPARAM;
1308 /* check if there is enough room */
1309 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
1310 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
1311 return DSERR_INVALIDPARAM;
1314 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
1315 if (TRACE_ON(dsound)) {
1316 TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
1317 _dump_DSCAPS(lpDSCaps->dwFlags);
1320 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
1321 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
1322 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
1323 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
1324 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
1325 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
1326 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
1327 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
1328 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
1329 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
1330 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
1331 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
1332 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
1333 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
1334 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
1335 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
1336 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
1337 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
1338 lpDSCaps->dwUnlockTransferRateHwBuffers = device->drvcaps.dwUnlockTransferRateHwBuffers;
1339 lpDSCaps->dwPlayCpuOverheadSwBuffers = device->drvcaps.dwPlayCpuOverheadSwBuffers;
1344 BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
1345 DWORD depth, WORD channels)
1347 WAVEFORMATEX fmt, *junk;
1350 fmt.wFormatTag = WAVE_FORMAT_PCM;
1351 fmt.nChannels = channels;
1352 fmt.nSamplesPerSec = rate;
1353 fmt.wBitsPerSample = depth;
1354 fmt.nBlockAlign = (channels * depth) / 8;
1355 fmt.nAvgBytesPerSec = rate * fmt.nBlockAlign;
1358 hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &fmt, &junk);
1360 CoTaskMemFree(junk);
1365 UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user)
1367 UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
1370 timeGetDevCaps(&time, sizeof(TIMECAPS));
1371 TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
1372 if (triggertime < time.wPeriodMin)
1373 triggertime = time.wPeriodMin;
1374 if (res < time.wPeriodMin)
1375 res = time.wPeriodMin;
1376 if (timeBeginPeriod(res) == TIMERR_NOCANDO)
1377 WARN("Could not set minimum resolution, don't expect sound\n");
1378 id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
1381 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1382 id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC);
1384 ERR("Could not create timer, sound playback will not occur\n");
1389 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
1393 DirectSoundDevice *device;
1394 IMMDevice *mmdevice;
1396 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
1398 if (*ppDevice != NULL) {
1399 WARN("already initialized\n");
1400 return DSERR_ALREADYINITIALIZED;
1403 /* Default device? */
1404 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1405 lpcGUID = &DSDEVID_DefaultPlayback;
1407 if(IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) ||
1408 IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture))
1409 return DSERR_NODRIVER;
1411 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1412 WARN("invalid parameter: lpcGUID\n");
1413 return DSERR_INVALIDPARAM;
1416 hr = get_mmdevice(eRender, &devGUID, &mmdevice);
1420 EnterCriticalSection(&DSOUND_renderers_lock);
1422 LIST_FOR_EACH_ENTRY(device, &DSOUND_renderers, DirectSoundDevice, entry){
1423 if(IsEqualGUID(&device->guid, &devGUID)){
1424 IMMDevice_Release(mmdevice);
1425 DirectSoundDevice_AddRef(device);
1427 LeaveCriticalSection(&DSOUND_renderers_lock);
1432 hr = DirectSoundDevice_Create(&device);
1434 WARN("DirectSoundDevice_Create failed\n");
1435 IMMDevice_Release(mmdevice);
1436 LeaveCriticalSection(&DSOUND_renderers_lock);
1440 device->mmdevice = mmdevice;
1441 device->guid = devGUID;
1443 hr = DSOUND_ReopenDevice(device, FALSE);
1446 HeapFree(GetProcessHeap(), 0, device);
1447 LeaveCriticalSection(&DSOUND_renderers_lock);
1448 IMMDevice_Release(mmdevice);
1449 WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
1453 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
1455 if(DSOUND_check_supported(device->client, 11025, 8, 1) ||
1456 DSOUND_check_supported(device->client, 22050, 8, 1) ||
1457 DSOUND_check_supported(device->client, 44100, 8, 1) ||
1458 DSOUND_check_supported(device->client, 48000, 8, 1) ||
1459 DSOUND_check_supported(device->client, 96000, 8, 1))
1460 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYMONO;
1462 if(DSOUND_check_supported(device->client, 11025, 16, 1) ||
1463 DSOUND_check_supported(device->client, 22050, 16, 1) ||
1464 DSOUND_check_supported(device->client, 44100, 16, 1) ||
1465 DSOUND_check_supported(device->client, 48000, 16, 1) ||
1466 DSOUND_check_supported(device->client, 96000, 16, 1))
1467 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYMONO;
1469 if(DSOUND_check_supported(device->client, 11025, 8, 2) ||
1470 DSOUND_check_supported(device->client, 22050, 8, 2) ||
1471 DSOUND_check_supported(device->client, 44100, 8, 2) ||
1472 DSOUND_check_supported(device->client, 48000, 8, 2) ||
1473 DSOUND_check_supported(device->client, 96000, 8, 2))
1474 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYSTEREO;
1476 if(DSOUND_check_supported(device->client, 11025, 16, 2) ||
1477 DSOUND_check_supported(device->client, 22050, 16, 2) ||
1478 DSOUND_check_supported(device->client, 44100, 16, 2) ||
1479 DSOUND_check_supported(device->client, 48000, 16, 2) ||
1480 DSOUND_check_supported(device->client, 96000, 16, 2))
1481 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO;
1483 /* the dsound mixer supports all of the following */
1484 device->drvcaps.dwFlags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
1485 device->drvcaps.dwFlags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
1486 device->drvcaps.dwFlags |= DSCAPS_CONTINUOUSRATE;
1488 device->drvcaps.dwPrimaryBuffers = 1;
1489 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
1490 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
1491 device->drvcaps.dwMaxHwMixingAllBuffers = 1;
1492 device->drvcaps.dwMaxHwMixingStaticBuffers = 1;
1493 device->drvcaps.dwMaxHwMixingStreamingBuffers = 1;
1495 ZeroMemory(&device->volpan, sizeof(device->volpan));
1497 hr = DSOUND_PrimaryCreate(device);
1499 device->timerID = DSOUND_create_timer(DSOUND_timer, (DWORD_PTR)device);
1501 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr);
1504 list_add_tail(&DSOUND_renderers, &device->entry);
1506 LeaveCriticalSection(&DSOUND_renderers_lock);
1511 HRESULT DirectSoundDevice_CreateSoundBuffer(
1512 DirectSoundDevice * device,
1513 LPCDSBUFFERDESC dsbd,
1514 LPLPDIRECTSOUNDBUFFER ppdsb,
1518 HRESULT hres = DS_OK;
1519 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
1521 if (device == NULL) {
1522 WARN("not initialized\n");
1523 return DSERR_UNINITIALIZED;
1527 WARN("invalid parameter: dsbd == NULL\n");
1528 return DSERR_INVALIDPARAM;
1531 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
1532 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
1533 WARN("invalid parameter: dsbd\n");
1534 return DSERR_INVALIDPARAM;
1537 if (ppdsb == NULL) {
1538 WARN("invalid parameter: ppdsb == NULL\n");
1539 return DSERR_INVALIDPARAM;
1543 if (TRACE_ON(dsound)) {
1544 TRACE("(structsize=%d)\n",dsbd->dwSize);
1545 TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
1546 _dump_DSBCAPS(dsbd->dwFlags);
1548 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
1549 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
1552 if (dsbd->dwFlags & DSBCAPS_LOCHARDWARE &&
1553 !(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
1554 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1558 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
1559 if (dsbd->lpwfxFormat != NULL) {
1560 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1561 "primary buffer\n");
1562 return DSERR_INVALIDPARAM;
1565 if (device->primary) {
1566 WARN("Primary Buffer already created\n");
1567 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1568 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1570 hres = primarybuffer_create(device, &device->primary, dsbd);
1571 if (device->primary) {
1572 *ppdsb = (IDirectSoundBuffer*)&device->primary->IDirectSoundBuffer8_iface;
1573 device->primary->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
1574 device->primary->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
1576 WARN("primarybuffer_create() failed\n");
1579 IDirectSoundBufferImpl * dsb;
1580 WAVEFORMATEXTENSIBLE *pwfxe;
1582 if (dsbd->lpwfxFormat == NULL) {
1583 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1584 "secondary buffer\n");
1585 return DSERR_INVALIDPARAM;
1587 pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
1589 if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
1591 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
1592 return DSERR_CONTROLUNAVAIL;
1594 if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
1596 /* check if cbSize is at least 22 bytes */
1597 if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
1599 WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize);
1600 return DSERR_INVALIDPARAM;
1603 /* cbSize should be 22 bytes, with one possible exception */
1604 if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) &&
1605 !((IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) &&
1606 pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
1608 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
1609 return DSERR_CONTROLUNAVAIL;
1612 if ((!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) && (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
1614 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
1615 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
1616 return DSERR_INVALIDPARAM;
1618 if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample)
1620 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample);
1621 return DSERR_INVALIDPARAM;
1623 if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample)
1625 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample);
1626 return DSERR_CONTROLUNAVAIL;
1630 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1631 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1632 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
1633 dsbd->lpwfxFormat->nSamplesPerSec,
1634 dsbd->lpwfxFormat->nAvgBytesPerSec,
1635 dsbd->lpwfxFormat->nBlockAlign,
1636 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
1638 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
1639 WARN("invalid parameter: 3D buffer format must be mono\n");
1640 return DSERR_INVALIDPARAM;
1643 hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd);
1645 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
1647 WARN("IDirectSoundBufferImpl_Create failed\n");
1653 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
1654 DirectSoundDevice * device,
1655 LPDIRECTSOUNDBUFFER psb,
1656 LPLPDIRECTSOUNDBUFFER ppdsb)
1658 HRESULT hres = DS_OK;
1659 IDirectSoundBufferImpl* dsb;
1660 TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
1662 if (device == NULL) {
1663 WARN("not initialized\n");
1664 return DSERR_UNINITIALIZED;
1668 WARN("invalid parameter: psb == NULL\n");
1669 return DSERR_INVALIDPARAM;
1672 if (ppdsb == NULL) {
1673 WARN("invalid parameter: ppdsb == NULL\n");
1674 return DSERR_INVALIDPARAM;
1677 /* make sure we have a secondary buffer */
1678 if (psb == (IDirectSoundBuffer *)&device->primary->IDirectSoundBuffer8_iface) {
1679 WARN("trying to duplicate primary buffer\n");
1681 return DSERR_INVALIDCALL;
1684 /* duplicate the actual buffer implementation */
1685 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb, (IDirectSoundBufferImpl*)psb);
1687 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
1689 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1694 HRESULT DirectSoundDevice_SetCooperativeLevel(
1695 DirectSoundDevice * device,
1699 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
1701 if (device == NULL) {
1702 WARN("not initialized\n");
1703 return DSERR_UNINITIALIZED;
1706 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
1707 WARN("level=%s not fully supported\n",
1708 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1711 device->priolevel = level;
1715 HRESULT DirectSoundDevice_Compact(
1716 DirectSoundDevice * device)
1718 TRACE("(%p)\n", device);
1720 if (device == NULL) {
1721 WARN("not initialized\n");
1722 return DSERR_UNINITIALIZED;
1725 if (device->priolevel < DSSCL_PRIORITY) {
1726 WARN("incorrect priority level\n");
1727 return DSERR_PRIOLEVELNEEDED;
1733 HRESULT DirectSoundDevice_GetSpeakerConfig(
1734 DirectSoundDevice * device,
1735 LPDWORD lpdwSpeakerConfig)
1737 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
1739 if (device == NULL) {
1740 WARN("not initialized\n");
1741 return DSERR_UNINITIALIZED;
1744 if (lpdwSpeakerConfig == NULL) {
1745 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1746 return DSERR_INVALIDPARAM;
1749 WARN("not fully functional\n");
1750 *lpdwSpeakerConfig = device->speaker_config;
1754 HRESULT DirectSoundDevice_SetSpeakerConfig(
1755 DirectSoundDevice * device,
1758 TRACE("(%p,0x%08x)\n",device,config);
1760 if (device == NULL) {
1761 WARN("not initialized\n");
1762 return DSERR_UNINITIALIZED;
1765 device->speaker_config = config;
1766 WARN("not fully functional\n");
1770 HRESULT DirectSoundDevice_VerifyCertification(
1771 DirectSoundDevice * device,
1772 LPDWORD pdwCertified)
1774 TRACE("(%p, %p)\n",device,pdwCertified);
1776 if (device == NULL) {
1777 WARN("not initialized\n");
1778 return DSERR_UNINITIALIZED;
1781 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
1782 *pdwCertified = DS_CERTIFIED;
1784 *pdwCertified = DS_UNCERTIFIED;
1790 * Add secondary buffer to buffer list.
1791 * Gets exclusive access to buffer for writing.
1793 HRESULT DirectSoundDevice_AddBuffer(
1794 DirectSoundDevice * device,
1795 IDirectSoundBufferImpl * pDSB)
1797 IDirectSoundBufferImpl **newbuffers;
1800 TRACE("(%p, %p)\n", device, pDSB);
1802 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1804 if (device->buffers)
1805 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1807 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1810 device->buffers = newbuffers;
1811 device->buffers[device->nrofbuffers] = pDSB;
1812 device->nrofbuffers++;
1813 TRACE("buffer count is now %d\n", device->nrofbuffers);
1815 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
1816 hr = DSERR_OUTOFMEMORY;
1819 RtlReleaseResource(&(device->buffer_list_lock));
1825 * Remove secondary buffer from buffer list.
1826 * Gets exclusive access to buffer for writing.
1828 HRESULT DirectSoundDevice_RemoveBuffer(
1829 DirectSoundDevice * device,
1830 IDirectSoundBufferImpl * pDSB)
1835 TRACE("(%p, %p)\n", device, pDSB);
1837 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1839 for (i = 0; i < device->nrofbuffers; i++)
1840 if (device->buffers[i] == pDSB)
1843 if (i < device->nrofbuffers) {
1844 /* Put the last buffer of the list in the (now empty) position */
1845 device->buffers[i] = device->buffers[device->nrofbuffers - 1];
1846 device->nrofbuffers--;
1847 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
1848 TRACE("buffer count is now %d\n", device->nrofbuffers);
1851 if (device->nrofbuffers == 0) {
1852 HeapFree(GetProcessHeap(),0,device->buffers);
1853 device->buffers = NULL;
1856 RtlReleaseResource(&(device->buffer_list_lock));