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
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
38 #include "dsound_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
42 /*****************************************************************************
43 * IDirectSound COM components
45 struct IDirectSound_IUnknown {
46 const IUnknownVtbl *lpVtbl;
51 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
53 struct IDirectSound_IDirectSound {
54 const IDirectSoundVtbl *lpVtbl;
59 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
61 /*****************************************************************************
62 * IDirectSound8 COM components
64 struct IDirectSound8_IUnknown {
65 const IUnknownVtbl *lpVtbl;
70 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
71 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
73 struct IDirectSound8_IDirectSound {
74 const IDirectSoundVtbl *lpVtbl;
79 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
80 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
82 struct IDirectSound8_IDirectSound8 {
83 const IDirectSound8Vtbl *lpVtbl;
88 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
89 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
91 /*****************************************************************************
92 * IDirectSound implementation structure
94 struct IDirectSoundImpl
98 DirectSoundDevice *device;
104 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
106 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
107 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
109 static HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device, LPDWORD pdwCertified);
111 const char * dumpCooperativeLevel(DWORD level)
113 static char unknown[32];
114 #define LE(x) case x: return #x
119 LE(DSSCL_WRITEPRIMARY);
122 sprintf(unknown, "Unknown(%08x)", level);
126 static void _dump_DSCAPS(DWORD xmask) {
131 #define FE(x) { x, #x },
132 FE(DSCAPS_PRIMARYMONO)
133 FE(DSCAPS_PRIMARYSTEREO)
134 FE(DSCAPS_PRIMARY8BIT)
135 FE(DSCAPS_PRIMARY16BIT)
136 FE(DSCAPS_CONTINUOUSRATE)
137 FE(DSCAPS_EMULDRIVER)
139 FE(DSCAPS_SECONDARYMONO)
140 FE(DSCAPS_SECONDARYSTEREO)
141 FE(DSCAPS_SECONDARY8BIT)
142 FE(DSCAPS_SECONDARY16BIT)
147 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
148 if ((flags[i].mask & xmask) == flags[i].mask)
149 DPRINTF("%s ",flags[i].name);
152 static void _dump_DSBCAPS(DWORD xmask) {
157 #define FE(x) { x, #x },
158 FE(DSBCAPS_PRIMARYBUFFER)
160 FE(DSBCAPS_LOCHARDWARE)
161 FE(DSBCAPS_LOCSOFTWARE)
163 FE(DSBCAPS_CTRLFREQUENCY)
165 FE(DSBCAPS_CTRLVOLUME)
166 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
167 FE(DSBCAPS_STICKYFOCUS)
168 FE(DSBCAPS_GLOBALFOCUS)
169 FE(DSBCAPS_GETCURRENTPOSITION2)
170 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
175 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
176 if ((flags[i].mask & xmask) == flags[i].mask)
177 DPRINTF("%s ",flags[i].name);
180 /*******************************************************************************
181 * IDirectSoundImpl_DirectSound
183 static HRESULT DSOUND_QueryInterface(
184 LPDIRECTSOUND8 iface,
188 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
189 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
192 WARN("invalid parameter\n");
196 if (IsEqualIID(riid, &IID_IUnknown)) {
197 if (!This->pUnknown) {
198 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
199 if (!This->pUnknown) {
200 WARN("IDirectSound_IUnknown_Create() failed\n");
202 return E_NOINTERFACE;
205 IDirectSound_IUnknown_AddRef(This->pUnknown);
206 *ppobj = This->pUnknown;
208 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
210 IDirectSound_IDirectSound_Create(iface, &This->pDS);
212 WARN("IDirectSound_IDirectSound_Create() failed\n");
214 return E_NOINTERFACE;
217 IDirectSound_IDirectSound_AddRef(This->pDS);
223 WARN("Unknown IID %s\n",debugstr_guid(riid));
224 return E_NOINTERFACE;
227 static HRESULT DSOUND_QueryInterface8(
228 LPDIRECTSOUND8 iface,
232 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
233 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
236 WARN("invalid parameter\n");
240 if (IsEqualIID(riid, &IID_IUnknown)) {
241 if (!This->pUnknown) {
242 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
243 if (!This->pUnknown) {
244 WARN("IDirectSound8_IUnknown_Create() failed\n");
246 return E_NOINTERFACE;
249 IDirectSound8_IUnknown_AddRef(This->pUnknown);
250 *ppobj = This->pUnknown;
252 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
254 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
256 WARN("IDirectSound8_IDirectSound_Create() failed\n");
258 return E_NOINTERFACE;
261 IDirectSound8_IDirectSound_AddRef(This->pDS);
264 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
266 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
268 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
270 return E_NOINTERFACE;
273 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
279 WARN("Unknown IID %s\n",debugstr_guid(riid));
280 return E_NOINTERFACE;
283 static ULONG IDirectSoundImpl_AddRef(
284 LPDIRECTSOUND8 iface)
286 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
287 ULONG ref = InterlockedIncrement(&(This->ref));
288 TRACE("(%p) ref was %d\n", This, ref - 1);
292 static ULONG IDirectSoundImpl_Release(
293 LPDIRECTSOUND8 iface)
295 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
296 ULONG ref = InterlockedDecrement(&(This->ref));
297 TRACE("(%p) ref was %d\n", This, ref + 1);
301 DirectSoundDevice_Release(This->device);
302 HeapFree(GetProcessHeap(),0,This);
303 TRACE("(%p) released\n", This);
308 static HRESULT IDirectSoundImpl_Create(
309 LPDIRECTSOUND8 * ppDS)
311 IDirectSoundImpl* pDS;
312 TRACE("(%p)\n",ppDS);
314 /* Allocate memory */
315 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
317 WARN("out of memory\n");
319 return DSERR_OUTOFMEMORY;
325 *ppDS = (LPDIRECTSOUND8)pDS;
330 /*******************************************************************************
331 * IDirectSound_IUnknown
333 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
338 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
339 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
340 return DSOUND_QueryInterface(This->pds, riid, ppobj);
343 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
346 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
347 ULONG ref = InterlockedIncrement(&(This->ref));
348 TRACE("(%p) ref was %d\n", This, ref - 1);
352 static ULONG WINAPI IDirectSound_IUnknown_Release(
355 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
356 ULONG ref = InterlockedDecrement(&(This->ref));
357 TRACE("(%p) ref was %d\n", This, ref + 1);
359 IDirectSoundImpl_Release(This->pds);
360 HeapFree(GetProcessHeap(), 0, This);
361 TRACE("(%p) released\n", This);
366 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
368 IDirectSound_IUnknown_QueryInterface,
369 IDirectSound_IUnknown_AddRef,
370 IDirectSound_IUnknown_Release
373 static HRESULT IDirectSound_IUnknown_Create(
377 IDirectSound_IUnknown * pdsunk;
378 TRACE("(%p,%p)\n",pds,ppunk);
381 ERR("invalid parameter: ppunk == NULL\n");
382 return DSERR_INVALIDPARAM;
386 ERR("invalid parameter: pds == NULL\n");
388 return DSERR_INVALIDPARAM;
391 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
392 if (pdsunk == NULL) {
393 WARN("out of memory\n");
395 return DSERR_OUTOFMEMORY;
398 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
402 IDirectSoundImpl_AddRef(pds);
403 *ppunk = (LPUNKNOWN)pdsunk;
408 /*******************************************************************************
409 * IDirectSound_IDirectSound
411 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
416 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
417 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
418 return DSOUND_QueryInterface(This->pds, riid, ppobj);
421 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
424 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
425 ULONG ref = InterlockedIncrement(&(This->ref));
426 TRACE("(%p) ref was %d\n", This, ref - 1);
430 static ULONG WINAPI IDirectSound_IDirectSound_Release(
433 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
434 ULONG ref = InterlockedDecrement(&(This->ref));
435 TRACE("(%p) ref was %d\n", This, ref + 1);
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_Release(This->pds);
599 HeapFree(GetProcessHeap(), 0, This);
600 TRACE("(%p) released\n", This);
605 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
607 IDirectSound8_IUnknown_QueryInterface,
608 IDirectSound8_IUnknown_AddRef,
609 IDirectSound8_IUnknown_Release
612 static HRESULT IDirectSound8_IUnknown_Create(
616 IDirectSound8_IUnknown * pdsunk;
617 TRACE("(%p,%p)\n",pds,ppunk);
620 ERR("invalid parameter: ppunk == NULL\n");
621 return DSERR_INVALIDPARAM;
625 ERR("invalid parameter: pds == NULL\n");
627 return DSERR_INVALIDPARAM;
630 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
631 if (pdsunk == NULL) {
632 WARN("out of memory\n");
634 return DSERR_OUTOFMEMORY;
637 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
641 IDirectSoundImpl_AddRef(pds);
642 *ppunk = (LPUNKNOWN)pdsunk;
647 /*******************************************************************************
648 * IDirectSound8_IDirectSound
650 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
655 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
656 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
657 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
660 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
663 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
664 ULONG ref = InterlockedIncrement(&(This->ref));
665 TRACE("(%p) ref was %d\n", This, ref - 1);
669 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
672 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
673 ULONG ref = InterlockedDecrement(&(This->ref));
674 TRACE("(%p) ref was %d\n", This, ref + 1);
676 IDirectSoundImpl_Release(This->pds);
677 HeapFree(GetProcessHeap(), 0, This);
678 TRACE("(%p) released\n", This);
683 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
685 LPCDSBUFFERDESC dsbd,
686 LPLPDIRECTSOUNDBUFFER ppdsb,
689 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
690 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
691 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
694 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
698 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
699 TRACE("(%p,%p)\n",This,lpDSCaps);
700 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
703 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
705 LPDIRECTSOUNDBUFFER psb,
706 LPLPDIRECTSOUNDBUFFER ppdsb)
708 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
709 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
710 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
713 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
718 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
719 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
720 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
723 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
726 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
727 TRACE("(%p)\n", This);
728 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
731 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
733 LPDWORD lpdwSpeakerConfig)
735 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
736 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
737 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
740 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
744 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
745 TRACE("(%p,0x%08x)\n",This,config);
746 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
749 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
753 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
754 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
755 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
758 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
760 IDirectSound8_IDirectSound_QueryInterface,
761 IDirectSound8_IDirectSound_AddRef,
762 IDirectSound8_IDirectSound_Release,
763 IDirectSound8_IDirectSound_CreateSoundBuffer,
764 IDirectSound8_IDirectSound_GetCaps,
765 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
766 IDirectSound8_IDirectSound_SetCooperativeLevel,
767 IDirectSound8_IDirectSound_Compact,
768 IDirectSound8_IDirectSound_GetSpeakerConfig,
769 IDirectSound8_IDirectSound_SetSpeakerConfig,
770 IDirectSound8_IDirectSound_Initialize
773 static HRESULT IDirectSound8_IDirectSound_Create(
775 LPDIRECTSOUND * ppds)
777 IDirectSound8_IDirectSound * pdsds;
778 TRACE("(%p,%p)\n",pds,ppds);
781 ERR("invalid parameter: ppds == NULL\n");
782 return DSERR_INVALIDPARAM;
786 ERR("invalid parameter: pds == NULL\n");
788 return DSERR_INVALIDPARAM;
791 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
793 WARN("out of memory\n");
795 return DSERR_OUTOFMEMORY;
798 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
802 IDirectSoundImpl_AddRef(pds);
803 *ppds = (LPDIRECTSOUND)pdsds;
808 /*******************************************************************************
809 * IDirectSound8_IDirectSound8
811 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
812 LPDIRECTSOUND8 iface,
816 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
817 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
818 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
821 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
822 LPDIRECTSOUND8 iface)
824 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
825 ULONG ref = InterlockedIncrement(&(This->ref));
826 TRACE("(%p) ref was %d\n", This, ref - 1);
830 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
831 LPDIRECTSOUND8 iface)
833 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
834 ULONG ref = InterlockedDecrement(&(This->ref));
835 TRACE("(%p) ref was %d\n", This, ref + 1);
837 IDirectSoundImpl_Release(This->pds);
838 HeapFree(GetProcessHeap(), 0, This);
839 TRACE("(%p) released\n", This);
844 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
845 LPDIRECTSOUND8 iface,
846 LPCDSBUFFERDESC dsbd,
847 LPLPDIRECTSOUNDBUFFER ppdsb,
850 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
851 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
852 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
855 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
856 LPDIRECTSOUND8 iface,
859 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
860 TRACE("(%p,%p)\n",This,lpDSCaps);
861 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
864 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
865 LPDIRECTSOUND8 iface,
866 LPDIRECTSOUNDBUFFER psb,
867 LPLPDIRECTSOUNDBUFFER ppdsb)
869 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
870 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
871 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
874 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
875 LPDIRECTSOUND8 iface,
879 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
880 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
881 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
884 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
885 LPDIRECTSOUND8 iface)
887 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
888 TRACE("(%p)\n", This);
889 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
892 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
893 LPDIRECTSOUND8 iface,
894 LPDWORD lpdwSpeakerConfig)
896 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
897 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
898 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
901 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
902 LPDIRECTSOUND8 iface,
905 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
906 TRACE("(%p,0x%08x)\n",This,config);
907 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
910 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
911 LPDIRECTSOUND8 iface,
914 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
915 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
916 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
919 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
920 LPDIRECTSOUND8 iface,
921 LPDWORD pdwCertified)
923 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
924 TRACE("(%p, %p)\n", This, pdwCertified);
925 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
928 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
930 IDirectSound8_IDirectSound8_QueryInterface,
931 IDirectSound8_IDirectSound8_AddRef,
932 IDirectSound8_IDirectSound8_Release,
933 IDirectSound8_IDirectSound8_CreateSoundBuffer,
934 IDirectSound8_IDirectSound8_GetCaps,
935 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
936 IDirectSound8_IDirectSound8_SetCooperativeLevel,
937 IDirectSound8_IDirectSound8_Compact,
938 IDirectSound8_IDirectSound8_GetSpeakerConfig,
939 IDirectSound8_IDirectSound8_SetSpeakerConfig,
940 IDirectSound8_IDirectSound8_Initialize,
941 IDirectSound8_IDirectSound8_VerifyCertification
944 static HRESULT IDirectSound8_IDirectSound8_Create(
946 LPDIRECTSOUND8 * ppds)
948 IDirectSound8_IDirectSound8 * pdsds;
949 TRACE("(%p,%p)\n",pds,ppds);
952 ERR("invalid parameter: ppds == NULL\n");
953 return DSERR_INVALIDPARAM;
957 ERR("invalid parameter: pds == NULL\n");
959 return DSERR_INVALIDPARAM;
962 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
964 WARN("out of memory\n");
966 return DSERR_OUTOFMEMORY;
969 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
973 IDirectSoundImpl_AddRef(pds);
974 *ppds = (LPDIRECTSOUND8)pdsds;
979 HRESULT DSOUND_Create(
985 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
987 if (!IsEqualIID(riid, &IID_IUnknown) &&
988 !IsEqualIID(riid, &IID_IDirectSound)) {
990 return E_NOINTERFACE;
993 /* Get dsound configuration */
994 setup_dsound_options();
996 hr = IDirectSoundImpl_Create(&pDS);
998 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1000 IDirectSound_IDirectSound_AddRef(*ppDS);
1002 WARN("IDirectSound_IDirectSound_Create failed\n");
1003 IDirectSound8_Release(pDS);
1006 WARN("IDirectSoundImpl_Create failed\n");
1013 /*******************************************************************************
1014 * DirectSoundCreate (DSOUND.1)
1016 * Creates and initializes a DirectSound interface.
1019 * lpcGUID [I] Address of the GUID that identifies the sound device.
1020 * ppDS [O] Address of a variable to receive the interface pointer.
1021 * pUnkOuter [I] Must be NULL.
1025 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1026 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1028 HRESULT WINAPI DirectSoundCreate(
1030 LPDIRECTSOUND *ppDS,
1031 IUnknown *pUnkOuter)
1036 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1039 WARN("invalid parameter: ppDS == NULL\n");
1040 return DSERR_INVALIDPARAM;
1043 if (pUnkOuter != NULL) {
1044 WARN("invalid parameter: pUnkOuter != NULL\n");
1046 return DSERR_INVALIDPARAM;
1049 hr = DSOUND_Create(&IID_IDirectSound, &pDS);
1051 hr = IDirectSound_Initialize(pDS, lpcGUID);
1053 if (hr != DSERR_ALREADYINITIALIZED) {
1054 IDirectSound_Release(pDS);
1066 HRESULT DSOUND_Create8(
1068 LPDIRECTSOUND8 *ppDS)
1072 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
1074 if (!IsEqualIID(riid, &IID_IUnknown) &&
1075 !IsEqualIID(riid, &IID_IDirectSound8)) {
1077 return E_NOINTERFACE;
1080 /* Get dsound configuration */
1081 setup_dsound_options();
1083 hr = IDirectSoundImpl_Create(&pDS);
1085 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1087 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1089 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1090 IDirectSound8_Release(pDS);
1093 WARN("IDirectSoundImpl_Create failed\n");
1100 /*******************************************************************************
1101 * DirectSoundCreate8 (DSOUND.11)
1103 * Creates and initializes a DirectSound8 interface.
1106 * lpcGUID [I] Address of the GUID that identifies the sound device.
1107 * ppDS [O] Address of a variable to receive the interface pointer.
1108 * pUnkOuter [I] Must be NULL.
1112 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1113 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1115 HRESULT WINAPI DirectSoundCreate8(
1117 LPDIRECTSOUND8 *ppDS,
1118 IUnknown *pUnkOuter)
1123 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1126 WARN("invalid parameter: ppDS == NULL\n");
1127 return DSERR_INVALIDPARAM;
1130 if (pUnkOuter != NULL) {
1131 WARN("invalid parameter: pUnkOuter != NULL\n");
1133 return DSERR_INVALIDPARAM;
1136 hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
1138 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1140 if (hr != DSERR_ALREADYINITIALIZED) {
1141 IDirectSound8_Release(pDS);
1153 /*******************************************************************************
1156 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
1158 DirectSoundDevice * device;
1159 TRACE("(%p)\n", ppDevice);
1161 /* Allocate memory */
1162 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
1163 if (device == NULL) {
1164 WARN("out of memory\n");
1165 return DSERR_OUTOFMEMORY;
1169 device->driver = NULL;
1170 device->priolevel = DSSCL_NORMAL;
1171 device->fraglen = 0;
1172 device->hwbuf = NULL;
1173 device->buffer = NULL;
1175 device->writelead = 0;
1176 device->state = STATE_STOPPED;
1177 device->nrofbuffers = 0;
1178 device->buffers = NULL;
1179 device->primary = NULL;
1180 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
1181 device->tmp_buffer = NULL;
1182 device->tmp_buffer_len = 0;
1184 /* 3D listener initial parameters */
1185 device->listener = NULL;
1186 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1187 device->ds3dl.vPosition.x = 0.0;
1188 device->ds3dl.vPosition.y = 0.0;
1189 device->ds3dl.vPosition.z = 0.0;
1190 device->ds3dl.vVelocity.x = 0.0;
1191 device->ds3dl.vVelocity.y = 0.0;
1192 device->ds3dl.vVelocity.z = 0.0;
1193 device->ds3dl.vOrientFront.x = 0.0;
1194 device->ds3dl.vOrientFront.y = 0.0;
1195 device->ds3dl.vOrientFront.z = 1.0;
1196 device->ds3dl.vOrientTop.x = 0.0;
1197 device->ds3dl.vOrientTop.y = 1.0;
1198 device->ds3dl.vOrientTop.z = 0.0;
1199 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1200 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1201 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1203 device->prebuf = ds_snd_queue_max;
1204 device->guid = GUID_NULL;
1206 /* Set default wave format (may need it for waveOutOpen) */
1207 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
1208 if (device->pwfx == NULL) {
1209 WARN("out of memory\n");
1210 HeapFree(GetProcessHeap(),0,device);
1211 return DSERR_OUTOFMEMORY;
1214 /* We rely on the sound driver to return the actual sound format of
1215 * the device if it does not support 22050x8x2 and is given the
1216 * WAVE_DIRECTSOUND flag.
1218 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1219 device->pwfx->nSamplesPerSec = ds_default_sample_rate;
1220 device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
1221 device->pwfx->nChannels = 2;
1222 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
1223 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
1224 device->pwfx->cbSize = 0;
1226 InitializeCriticalSection(&(device->mixlock));
1227 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock";
1229 RtlInitializeResource(&(device->buffer_list_lock));
1236 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
1238 ULONG ref = InterlockedIncrement(&(device->ref));
1239 TRACE("(%p) ref was %d\n", device, ref - 1);
1243 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
1246 ULONG ref = InterlockedDecrement(&(device->ref));
1247 TRACE("(%p) ref was %u\n", device, ref + 1);
1250 timeKillEvent(device->timerID);
1251 timeEndPeriod(DS_TIME_RES);
1252 /* wait for timer to expire */
1253 Sleep(DS_TIME_RES+1);
1255 /* The sleep above should have allowed the timer process to expire
1256 * but try to grab the lock just in case. Can't hold lock because
1257 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1258 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1259 RtlReleaseResource(&(device->buffer_list_lock));
1261 /* It is allowed to release this object even when buffers are playing */
1262 if (device->buffers) {
1263 WARN("%d secondary buffers not released\n", device->nrofbuffers);
1264 for( i=0;i<device->nrofbuffers;i++)
1265 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
1268 if (device->primary) {
1269 WARN("primary buffer not released\n");
1270 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
1273 hr = DSOUND_PrimaryDestroy(device);
1275 WARN("DSOUND_PrimaryDestroy failed\n");
1278 IDsDriver_Close(device->driver);
1280 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
1281 waveOutClose(device->hwo);
1284 IDsDriver_Release(device->driver);
1286 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
1288 HeapFree(GetProcessHeap(),0,device->tmp_buffer);
1289 HeapFree(GetProcessHeap(),0,device->buffer);
1290 RtlDeleteResource(&device->buffer_list_lock);
1291 device->mixlock.DebugInfo->Spare[0] = 0;
1292 DeleteCriticalSection(&device->mixlock);
1293 HeapFree(GetProcessHeap(),0,device);
1294 TRACE("(%p) released\n", device);
1299 HRESULT DirectSoundDevice_GetCaps(
1300 DirectSoundDevice * device,
1303 TRACE("(%p,%p)\n",device,lpDSCaps);
1305 if (device == NULL) {
1306 WARN("not initialized\n");
1307 return DSERR_UNINITIALIZED;
1310 if (lpDSCaps == NULL) {
1311 WARN("invalid parameter: lpDSCaps = NULL\n");
1312 return DSERR_INVALIDPARAM;
1315 /* check if there is enough room */
1316 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
1317 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
1318 return DSERR_INVALIDPARAM;
1321 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
1322 if (TRACE_ON(dsound)) {
1323 TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
1324 _dump_DSCAPS(lpDSCaps->dwFlags);
1327 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
1328 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
1329 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
1330 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
1331 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
1332 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
1333 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
1334 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
1335 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
1336 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
1337 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
1338 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
1339 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
1340 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
1341 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
1342 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
1343 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
1344 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
1346 /* driver doesn't have these */
1347 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
1348 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
1353 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
1357 BOOLEAN found = FALSE;
1359 DirectSoundDevice * device = *ppDevice;
1360 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
1362 if (*ppDevice != NULL) {
1363 WARN("already initialized\n");
1364 return DSERR_ALREADYINITIALIZED;
1367 /* Default device? */
1368 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1369 lpcGUID = &DSDEVID_DefaultPlayback;
1371 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1372 WARN("invalid parameter: lpcGUID\n");
1373 return DSERR_INVALIDPARAM;
1376 /* Enumerate WINMM audio devices and find the one we want */
1377 wodn = waveOutGetNumDevs();
1379 WARN("no driver\n");
1380 return DSERR_NODRIVER;
1383 for (wod=0; wod<wodn; wod++) {
1384 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
1390 if (found == FALSE) {
1391 WARN("No device found matching given ID!\n");
1392 return DSERR_NODRIVER;
1395 if (DSOUND_renderer[wod]) {
1396 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
1397 device = DSOUND_renderer[wod];
1398 DirectSoundDevice_AddRef(device);
1402 ERR("device GUID doesn't match\n");
1407 hr = DirectSoundDevice_Create(&device);
1409 WARN("DirectSoundDevice_Create failed\n");
1415 device->guid = devGUID;
1417 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
1418 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
1420 /* Disable the direct sound driver to force emulation if requested. */
1421 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
1422 device->driver = NULL;
1424 /* Get driver description */
1425 if (device->driver) {
1426 hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
1428 WARN("IDsDriver_GetDriverDesc failed\n");
1432 /* if no DirectSound interface available, use WINMM API instead */
1433 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
1436 device->drvdesc.dnDevNode = wod;
1438 /* If the driver requests being opened through MMSYSTEM
1439 * (which is recommended by the DDK), it is supposed to happen
1440 * before the DirectSound interface is opened */
1441 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
1443 DWORD flags = CALLBACK_FUNCTION;
1445 /* disable direct sound if requested */
1446 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
1447 flags |= WAVE_DIRECTSOUND;
1449 hr = mmErr(waveOutOpen(&(device->hwo),
1450 device->drvdesc.dnDevNode, device->pwfx,
1451 (DWORD_PTR)DSOUND_callback, (DWORD)device,
1454 WARN("waveOutOpen failed\n");
1459 if (device->driver) {
1460 hr = IDsDriver_Open(device->driver);
1462 WARN("IDsDriver_Open failed\n");
1466 /* the driver is now open, so it's now allowed to call GetCaps */
1467 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
1469 WARN("IDsDriver_GetCaps failed\n");
1474 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
1476 WARN("waveOutGetDevCaps failed\n");
1479 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
1480 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
1481 (woc.dwFormats & WAVE_FORMAT_2M08) ||
1482 (woc.dwFormats & WAVE_FORMAT_4M08) ||
1483 (woc.dwFormats & WAVE_FORMAT_48M08) ||
1484 (woc.dwFormats & WAVE_FORMAT_96M08)) {
1485 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1486 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1488 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
1489 (woc.dwFormats & WAVE_FORMAT_2M16) ||
1490 (woc.dwFormats & WAVE_FORMAT_4M16) ||
1491 (woc.dwFormats & WAVE_FORMAT_48M16) ||
1492 (woc.dwFormats & WAVE_FORMAT_96M16)) {
1493 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1494 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1496 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
1497 (woc.dwFormats & WAVE_FORMAT_2S08) ||
1498 (woc.dwFormats & WAVE_FORMAT_4S08) ||
1499 (woc.dwFormats & WAVE_FORMAT_48S08) ||
1500 (woc.dwFormats & WAVE_FORMAT_96S08)) {
1501 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1502 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1504 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
1505 (woc.dwFormats & WAVE_FORMAT_2S16) ||
1506 (woc.dwFormats & WAVE_FORMAT_4S16) ||
1507 (woc.dwFormats & WAVE_FORMAT_48S16) ||
1508 (woc.dwFormats & WAVE_FORMAT_96S16)) {
1509 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1510 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1513 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
1514 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
1515 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
1516 device->drvcaps.dwPrimaryBuffers = 1;
1519 hr = DSOUND_PrimaryCreate(device);
1521 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
1522 timeBeginPeriod(DS_TIME_RES);
1523 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1524 (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1526 WARN("DSOUND_PrimaryCreate failed\n");
1532 HRESULT DirectSoundDevice_CreateSoundBuffer(
1533 DirectSoundDevice * device,
1534 LPCDSBUFFERDESC dsbd,
1535 LPLPDIRECTSOUNDBUFFER ppdsb,
1539 HRESULT hres = DS_OK;
1540 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
1542 if (device == NULL) {
1543 WARN("not initialized\n");
1544 return DSERR_UNINITIALIZED;
1548 WARN("invalid parameter: dsbd == NULL\n");
1549 return DSERR_INVALIDPARAM;
1552 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
1553 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
1554 WARN("invalid parameter: dsbd\n");
1555 return DSERR_INVALIDPARAM;
1558 if (ppdsb == NULL) {
1559 WARN("invalid parameter: ppdsb == NULL\n");
1560 return DSERR_INVALIDPARAM;
1563 if (TRACE_ON(dsound)) {
1564 TRACE("(structsize=%d)\n",dsbd->dwSize);
1565 TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
1566 _dump_DSBCAPS(dsbd->dwFlags);
1568 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
1569 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
1572 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
1573 if (dsbd->lpwfxFormat != NULL) {
1574 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1575 "primary buffer\n");
1576 return DSERR_INVALIDPARAM;
1579 if (device->primary) {
1580 WARN("Primary Buffer already created\n");
1581 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1582 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1584 device->dsbd = *dsbd;
1585 hres = PrimaryBufferImpl_Create(device, (PrimaryBufferImpl**)&(device->primary), &(device->dsbd));
1586 if (device->primary) {
1587 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1588 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1590 WARN("PrimaryBufferImpl_Create failed\n");
1593 IDirectSoundBufferImpl * dsb;
1595 if (dsbd->lpwfxFormat == NULL) {
1596 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1597 "secondary buffer\n");
1598 return DSERR_INVALIDPARAM;
1601 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1602 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1603 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
1604 dsbd->lpwfxFormat->nSamplesPerSec,
1605 dsbd->lpwfxFormat->nAvgBytesPerSec,
1606 dsbd->lpwfxFormat->nBlockAlign,
1607 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
1609 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
1610 WARN("invalid parameter: 3D buffer format must be mono\n");
1611 return DSERR_INVALIDPARAM;
1614 hres = IDirectSoundBufferImpl_Create(device, (IDirectSoundBufferImpl**)&dsb, dsbd);
1616 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
1618 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
1619 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
1621 WARN("SecondaryBufferImpl_Create failed\n");
1623 WARN("IDirectSoundBufferImpl_Create failed\n");
1629 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
1630 DirectSoundDevice * device,
1631 LPDIRECTSOUNDBUFFER psb,
1632 LPLPDIRECTSOUNDBUFFER ppdsb)
1634 HRESULT hres = DS_OK;
1635 IDirectSoundBufferImpl* dsb;
1636 TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
1638 if (device == NULL) {
1639 WARN("not initialized\n");
1640 return DSERR_UNINITIALIZED;
1644 WARN("invalid parameter: psb == NULL\n");
1645 return DSERR_INVALIDPARAM;
1648 if (ppdsb == NULL) {
1649 WARN("invalid parameter: ppdsb == NULL\n");
1650 return DSERR_INVALIDPARAM;
1653 /* make sure we have a secondary buffer */
1654 if ((PrimaryBufferImpl *)psb == device->primary) {
1655 WARN("trying to duplicate primary buffer\n");
1657 return DSERR_INVALIDCALL;
1660 /* duplicate the actual buffer implementation */
1661 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb,
1662 ((SecondaryBufferImpl *)psb)->dsb);
1664 if (hres == DS_OK) {
1665 /* create a new secondary buffer using the new implementation */
1666 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
1668 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
1669 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
1671 WARN("SecondaryBufferImpl_Create failed\n");
1672 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
1673 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb);
1680 HRESULT DirectSoundDevice_SetCooperativeLevel(
1681 DirectSoundDevice * device,
1685 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
1687 if (device == NULL) {
1688 WARN("not initialized\n");
1689 return DSERR_UNINITIALIZED;
1692 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
1693 WARN("level=%s not fully supported\n",
1694 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1697 device->priolevel = level;
1701 HRESULT DirectSoundDevice_Compact(
1702 DirectSoundDevice * device)
1704 TRACE("(%p)\n", device);
1706 if (device == NULL) {
1707 WARN("not initialized\n");
1708 return DSERR_UNINITIALIZED;
1711 if (device->priolevel != DSSCL_PRIORITY) {
1712 WARN("incorrect priority level\n");
1713 return DSERR_PRIOLEVELNEEDED;
1719 HRESULT DirectSoundDevice_GetSpeakerConfig(
1720 DirectSoundDevice * device,
1721 LPDWORD lpdwSpeakerConfig)
1723 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
1725 if (device == NULL) {
1726 WARN("not initialized\n");
1727 return DSERR_UNINITIALIZED;
1730 if (lpdwSpeakerConfig == NULL) {
1731 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1732 return DSERR_INVALIDPARAM;
1735 WARN("not fully functional\n");
1736 *lpdwSpeakerConfig = device->speaker_config;
1740 HRESULT DirectSoundDevice_SetSpeakerConfig(
1741 DirectSoundDevice * device,
1744 TRACE("(%p,0x%08x)\n",device,config);
1746 if (device == NULL) {
1747 WARN("not initialized\n");
1748 return DSERR_UNINITIALIZED;
1751 device->speaker_config = config;
1752 WARN("not fully functional\n");
1756 static HRESULT DirectSoundDevice_VerifyCertification(
1757 DirectSoundDevice * device,
1758 LPDWORD pdwCertified)
1760 TRACE("(%p, %p)\n",device,pdwCertified);
1762 if (device == NULL) {
1763 WARN("not initialized\n");
1764 return DSERR_UNINITIALIZED;
1767 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
1768 *pdwCertified = DS_CERTIFIED;
1770 *pdwCertified = DS_UNCERTIFIED;
1776 * Add secondary buffer to buffer list.
1777 * Gets exclusive access to buffer for writing.
1779 HRESULT DirectSoundDevice_AddBuffer(
1780 DirectSoundDevice * device,
1781 IDirectSoundBufferImpl * pDSB)
1783 IDirectSoundBufferImpl **newbuffers;
1786 TRACE("(%p, %p)\n", device, pDSB);
1788 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1790 if (device->buffers)
1791 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1793 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1796 device->buffers = newbuffers;
1797 device->buffers[device->nrofbuffers] = pDSB;
1798 device->nrofbuffers++;
1799 TRACE("buffer count is now %d\n", device->nrofbuffers);
1801 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
1802 hr = DSERR_OUTOFMEMORY;
1805 RtlReleaseResource(&(device->buffer_list_lock));
1811 * Remove secondary buffer from buffer list.
1812 * Gets exclusive access to buffer for writing.
1814 HRESULT DirectSoundDevice_RemoveBuffer(
1815 DirectSoundDevice * device,
1816 IDirectSoundBufferImpl * pDSB)
1821 TRACE("(%p, %p)\n", device, pDSB);
1823 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1825 for (i = 0; i < device->nrofbuffers; i++)
1826 if (device->buffers[i] == pDSB)
1829 if (i < device->nrofbuffers) {
1830 /* Put the last buffer of the list in the (now empty) position */
1831 device->buffers[i] = device->buffers[device->nrofbuffers - 1];
1832 device->nrofbuffers--;
1833 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
1834 TRACE("buffer count is now %d\n", device->nrofbuffers);
1837 if (device->nrofbuffers == 0) {
1838 HeapFree(GetProcessHeap(),0,device->buffers);
1839 device->buffers = NULL;
1842 RtlReleaseResource(&(device->buffer_list_lock));