wined3d: Add a registry key to disable rendering swapchains onscreen.
[wine.git] / dlls / dsound / dsound.c
blob8c1b81240b5036d81d3ab1352f2018dea3328669
1 /* DirectSound
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
23 #include <stdarg.h>
24 #include <stdio.h>
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "winternl.h"
33 #include "mmddk.h"
34 #include "wingdi.h"
35 #include "mmreg.h"
36 #include "ks.h"
37 #include "ksmedia.h"
38 #include "wine/debug.h"
39 #include "dsound.h"
40 #include "dsdriver.h"
41 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
45 /*****************************************************************************
46 * IDirectSound COM components
48 struct IDirectSound_IUnknown {
49 const IUnknownVtbl *lpVtbl;
50 LONG ref;
51 LPDIRECTSOUND8 pds;
54 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
56 struct IDirectSound_IDirectSound {
57 const IDirectSoundVtbl *lpVtbl;
58 LONG ref;
59 LPDIRECTSOUND8 pds;
62 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
64 /*****************************************************************************
65 * IDirectSound8 COM components
67 struct IDirectSound8_IUnknown {
68 const IUnknownVtbl *lpVtbl;
69 LONG ref;
70 LPDIRECTSOUND8 pds;
73 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
74 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
76 struct IDirectSound8_IDirectSound {
77 const IDirectSoundVtbl *lpVtbl;
78 LONG ref;
79 LPDIRECTSOUND8 pds;
82 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
83 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
85 struct IDirectSound8_IDirectSound8 {
86 const IDirectSound8Vtbl *lpVtbl;
87 LONG ref;
88 LPDIRECTSOUND8 pds;
91 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
92 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
94 /*****************************************************************************
95 * IDirectSound implementation structure
97 struct IDirectSoundImpl
99 LONG ref;
101 DirectSoundDevice *device;
102 LPUNKNOWN pUnknown;
103 LPDIRECTSOUND pDS;
104 LPDIRECTSOUND8 pDS8;
107 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
109 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
110 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
112 const char * dumpCooperativeLevel(DWORD level)
114 #define LE(x) case x: return #x
115 switch (level) {
116 LE(DSSCL_NORMAL);
117 LE(DSSCL_PRIORITY);
118 LE(DSSCL_EXCLUSIVE);
119 LE(DSSCL_WRITEPRIMARY);
121 #undef LE
122 return wine_dbg_sprintf("Unknown(%08x)", level);
125 static void _dump_DSCAPS(DWORD xmask) {
126 struct {
127 DWORD mask;
128 const char *name;
129 } flags[] = {
130 #define FE(x) { x, #x },
131 FE(DSCAPS_PRIMARYMONO)
132 FE(DSCAPS_PRIMARYSTEREO)
133 FE(DSCAPS_PRIMARY8BIT)
134 FE(DSCAPS_PRIMARY16BIT)
135 FE(DSCAPS_CONTINUOUSRATE)
136 FE(DSCAPS_EMULDRIVER)
137 FE(DSCAPS_CERTIFIED)
138 FE(DSCAPS_SECONDARYMONO)
139 FE(DSCAPS_SECONDARYSTEREO)
140 FE(DSCAPS_SECONDARY8BIT)
141 FE(DSCAPS_SECONDARY16BIT)
142 #undef FE
144 unsigned int i;
146 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
147 if ((flags[i].mask & xmask) == flags[i].mask)
148 TRACE("%s ",flags[i].name);
151 static void _dump_DSBCAPS(DWORD xmask) {
152 struct {
153 DWORD mask;
154 const char *name;
155 } flags[] = {
156 #define FE(x) { x, #x },
157 FE(DSBCAPS_PRIMARYBUFFER)
158 FE(DSBCAPS_STATIC)
159 FE(DSBCAPS_LOCHARDWARE)
160 FE(DSBCAPS_LOCSOFTWARE)
161 FE(DSBCAPS_CTRL3D)
162 FE(DSBCAPS_CTRLFREQUENCY)
163 FE(DSBCAPS_CTRLPAN)
164 FE(DSBCAPS_CTRLVOLUME)
165 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
166 FE(DSBCAPS_STICKYFOCUS)
167 FE(DSBCAPS_GLOBALFOCUS)
168 FE(DSBCAPS_GETCURRENTPOSITION2)
169 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
170 #undef FE
172 unsigned int i;
174 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
175 if ((flags[i].mask & xmask) == flags[i].mask)
176 TRACE("%s ",flags[i].name);
179 /*******************************************************************************
180 * IDirectSoundImpl_DirectSound
182 static HRESULT DSOUND_QueryInterface(
183 LPDIRECTSOUND8 iface,
184 REFIID riid,
185 LPVOID * ppobj)
187 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
188 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
190 if (ppobj == NULL) {
191 WARN("invalid parameter\n");
192 return E_INVALIDARG;
195 if (IsEqualIID(riid, &IID_IUnknown)) {
196 if (!This->pUnknown) {
197 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
198 if (!This->pUnknown) {
199 WARN("IDirectSound_IUnknown_Create() failed\n");
200 *ppobj = NULL;
201 return E_NOINTERFACE;
204 IDirectSound_IUnknown_AddRef(This->pUnknown);
205 *ppobj = This->pUnknown;
206 return S_OK;
207 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
208 if (!This->pDS) {
209 IDirectSound_IDirectSound_Create(iface, &This->pDS);
210 if (!This->pDS) {
211 WARN("IDirectSound_IDirectSound_Create() failed\n");
212 *ppobj = NULL;
213 return E_NOINTERFACE;
216 IDirectSound_IDirectSound_AddRef(This->pDS);
217 *ppobj = This->pDS;
218 return S_OK;
221 *ppobj = NULL;
222 WARN("Unknown IID %s\n",debugstr_guid(riid));
223 return E_NOINTERFACE;
226 static HRESULT DSOUND_QueryInterface8(
227 LPDIRECTSOUND8 iface,
228 REFIID riid,
229 LPVOID * ppobj)
231 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
232 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
234 if (ppobj == NULL) {
235 WARN("invalid parameter\n");
236 return E_INVALIDARG;
239 if (IsEqualIID(riid, &IID_IUnknown)) {
240 if (!This->pUnknown) {
241 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
242 if (!This->pUnknown) {
243 WARN("IDirectSound8_IUnknown_Create() failed\n");
244 *ppobj = NULL;
245 return E_NOINTERFACE;
248 IDirectSound8_IUnknown_AddRef(This->pUnknown);
249 *ppobj = This->pUnknown;
250 return S_OK;
251 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
252 if (!This->pDS) {
253 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
254 if (!This->pDS) {
255 WARN("IDirectSound8_IDirectSound_Create() failed\n");
256 *ppobj = NULL;
257 return E_NOINTERFACE;
260 IDirectSound8_IDirectSound_AddRef(This->pDS);
261 *ppobj = This->pDS;
262 return S_OK;
263 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
264 if (!This->pDS8) {
265 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
266 if (!This->pDS8) {
267 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
268 *ppobj = NULL;
269 return E_NOINTERFACE;
272 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
273 *ppobj = This->pDS8;
274 return S_OK;
277 *ppobj = NULL;
278 WARN("Unknown IID %s\n",debugstr_guid(riid));
279 return E_NOINTERFACE;
282 static ULONG IDirectSoundImpl_AddRef(
283 LPDIRECTSOUND8 iface)
285 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
286 ULONG ref = InterlockedIncrement(&(This->ref));
287 TRACE("(%p) ref was %d\n", This, ref - 1);
288 return ref;
291 static ULONG IDirectSoundImpl_Release(
292 LPDIRECTSOUND8 iface)
294 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
295 ULONG ref = InterlockedDecrement(&(This->ref));
296 TRACE("(%p) ref was %d\n", This, ref + 1);
298 if (!ref) {
299 if (This->device)
300 DirectSoundDevice_Release(This->device);
301 HeapFree(GetProcessHeap(),0,This);
302 TRACE("(%p) released\n", This);
304 return ref;
307 static HRESULT IDirectSoundImpl_Create(
308 LPDIRECTSOUND8 * ppDS)
310 IDirectSoundImpl* pDS;
311 TRACE("(%p)\n",ppDS);
313 /* Allocate memory */
314 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
315 if (pDS == NULL) {
316 WARN("out of memory\n");
317 *ppDS = NULL;
318 return DSERR_OUTOFMEMORY;
321 pDS->ref = 0;
322 pDS->device = NULL;
324 *ppDS = (LPDIRECTSOUND8)pDS;
326 return DS_OK;
329 /*******************************************************************************
330 * IDirectSound_IUnknown
332 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
333 LPUNKNOWN iface,
334 REFIID riid,
335 LPVOID * ppobj)
337 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
338 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
339 return DSOUND_QueryInterface(This->pds, riid, ppobj);
342 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
343 LPUNKNOWN iface)
345 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
346 ULONG ref = InterlockedIncrement(&(This->ref));
347 TRACE("(%p) ref was %d\n", This, ref - 1);
348 return ref;
351 static ULONG WINAPI IDirectSound_IUnknown_Release(
352 LPUNKNOWN iface)
354 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
355 ULONG ref = InterlockedDecrement(&(This->ref));
356 TRACE("(%p) ref was %d\n", This, ref + 1);
357 if (!ref) {
358 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
359 IDirectSoundImpl_Release(This->pds);
360 HeapFree(GetProcessHeap(), 0, This);
361 TRACE("(%p) released\n", This);
363 return ref;
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(
374 LPDIRECTSOUND8 pds,
375 LPUNKNOWN * ppunk)
377 IDirectSound_IUnknown * pdsunk;
378 TRACE("(%p,%p)\n",pds,ppunk);
380 if (ppunk == NULL) {
381 ERR("invalid parameter: ppunk == NULL\n");
382 return DSERR_INVALIDPARAM;
385 if (pds == NULL) {
386 ERR("invalid parameter: pds == NULL\n");
387 *ppunk = NULL;
388 return DSERR_INVALIDPARAM;
391 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
392 if (pdsunk == NULL) {
393 WARN("out of memory\n");
394 *ppunk = NULL;
395 return DSERR_OUTOFMEMORY;
398 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
399 pdsunk->ref = 0;
400 pdsunk->pds = pds;
402 IDirectSoundImpl_AddRef(pds);
403 *ppunk = (LPUNKNOWN)pdsunk;
405 return DS_OK;
408 /*******************************************************************************
409 * IDirectSound_IDirectSound
411 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
412 LPDIRECTSOUND iface,
413 REFIID riid,
414 LPVOID * ppobj)
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(
422 LPDIRECTSOUND iface)
424 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
425 ULONG ref = InterlockedIncrement(&(This->ref));
426 TRACE("(%p) ref was %d\n", This, ref - 1);
427 return ref;
430 static ULONG WINAPI IDirectSound_IDirectSound_Release(
431 LPDIRECTSOUND iface)
433 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
434 ULONG ref = InterlockedDecrement(&(This->ref));
435 TRACE("(%p) ref was %d\n", This, ref + 1);
436 if (!ref) {
437 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
438 IDirectSoundImpl_Release(This->pds);
439 HeapFree(GetProcessHeap(), 0, This);
440 TRACE("(%p) released\n", This);
442 return ref;
445 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
446 LPDIRECTSOUND iface,
447 LPCDSBUFFERDESC dsbd,
448 LPLPDIRECTSOUNDBUFFER ppdsb,
449 LPUNKNOWN lpunk)
451 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
452 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
453 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
456 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
457 LPDIRECTSOUND iface,
458 LPDSCAPS lpDSCaps)
460 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
461 TRACE("(%p,%p)\n",This,lpDSCaps);
462 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
465 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
466 LPDIRECTSOUND iface,
467 LPDIRECTSOUNDBUFFER psb,
468 LPLPDIRECTSOUNDBUFFER ppdsb)
470 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
471 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
472 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
475 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
476 LPDIRECTSOUND iface,
477 HWND hwnd,
478 DWORD level)
480 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
481 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
482 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
485 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
486 LPDIRECTSOUND iface)
488 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
489 TRACE("(%p)\n", This);
490 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
493 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
494 LPDIRECTSOUND iface,
495 LPDWORD lpdwSpeakerConfig)
497 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
498 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
499 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
502 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
503 LPDIRECTSOUND iface,
504 DWORD config)
506 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
507 TRACE("(%p,0x%08x)\n",This,config);
508 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
511 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
512 LPDIRECTSOUND iface,
513 LPCGUID lpcGuid)
515 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
516 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
517 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
520 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
522 IDirectSound_IDirectSound_QueryInterface,
523 IDirectSound_IDirectSound_AddRef,
524 IDirectSound_IDirectSound_Release,
525 IDirectSound_IDirectSound_CreateSoundBuffer,
526 IDirectSound_IDirectSound_GetCaps,
527 IDirectSound_IDirectSound_DuplicateSoundBuffer,
528 IDirectSound_IDirectSound_SetCooperativeLevel,
529 IDirectSound_IDirectSound_Compact,
530 IDirectSound_IDirectSound_GetSpeakerConfig,
531 IDirectSound_IDirectSound_SetSpeakerConfig,
532 IDirectSound_IDirectSound_Initialize
535 static HRESULT IDirectSound_IDirectSound_Create(
536 LPDIRECTSOUND8 pds,
537 LPDIRECTSOUND * ppds)
539 IDirectSound_IDirectSound * pdsds;
540 TRACE("(%p,%p)\n",pds,ppds);
542 if (ppds == NULL) {
543 ERR("invalid parameter: ppds == NULL\n");
544 return DSERR_INVALIDPARAM;
547 if (pds == NULL) {
548 ERR("invalid parameter: pds == NULL\n");
549 *ppds = NULL;
550 return DSERR_INVALIDPARAM;
553 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
554 if (pdsds == NULL) {
555 WARN("out of memory\n");
556 *ppds = NULL;
557 return DSERR_OUTOFMEMORY;
560 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
561 pdsds->ref = 0;
562 pdsds->pds = pds;
564 IDirectSoundImpl_AddRef(pds);
565 *ppds = (LPDIRECTSOUND)pdsds;
567 return DS_OK;
570 /*******************************************************************************
571 * IDirectSound8_IUnknown
573 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
574 LPUNKNOWN iface,
575 REFIID riid,
576 LPVOID * ppobj)
578 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
579 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
580 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
583 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
584 LPUNKNOWN iface)
586 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
587 ULONG ref = InterlockedIncrement(&(This->ref));
588 TRACE("(%p) ref was %d\n", This, ref - 1);
589 return ref;
592 static ULONG WINAPI IDirectSound8_IUnknown_Release(
593 LPUNKNOWN iface)
595 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
596 ULONG ref = InterlockedDecrement(&(This->ref));
597 TRACE("(%p) ref was %d\n", This, ref + 1);
598 if (!ref) {
599 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
600 IDirectSoundImpl_Release(This->pds);
601 HeapFree(GetProcessHeap(), 0, This);
602 TRACE("(%p) released\n", This);
604 return ref;
607 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
609 IDirectSound8_IUnknown_QueryInterface,
610 IDirectSound8_IUnknown_AddRef,
611 IDirectSound8_IUnknown_Release
614 static HRESULT IDirectSound8_IUnknown_Create(
615 LPDIRECTSOUND8 pds,
616 LPUNKNOWN * ppunk)
618 IDirectSound8_IUnknown * pdsunk;
619 TRACE("(%p,%p)\n",pds,ppunk);
621 if (ppunk == NULL) {
622 ERR("invalid parameter: ppunk == NULL\n");
623 return DSERR_INVALIDPARAM;
626 if (pds == NULL) {
627 ERR("invalid parameter: pds == NULL\n");
628 *ppunk = NULL;
629 return DSERR_INVALIDPARAM;
632 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
633 if (pdsunk == NULL) {
634 WARN("out of memory\n");
635 *ppunk = NULL;
636 return DSERR_OUTOFMEMORY;
639 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
640 pdsunk->ref = 0;
641 pdsunk->pds = pds;
643 IDirectSoundImpl_AddRef(pds);
644 *ppunk = (LPUNKNOWN)pdsunk;
646 return DS_OK;
649 /*******************************************************************************
650 * IDirectSound8_IDirectSound
652 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
653 LPDIRECTSOUND iface,
654 REFIID riid,
655 LPVOID * ppobj)
657 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
658 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
659 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
662 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
663 LPDIRECTSOUND iface)
665 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
666 ULONG ref = InterlockedIncrement(&(This->ref));
667 TRACE("(%p) ref was %d\n", This, ref - 1);
668 return ref;
671 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
672 LPDIRECTSOUND iface)
674 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
675 ULONG ref = InterlockedDecrement(&(This->ref));
676 TRACE("(%p) ref was %d\n", This, ref + 1);
677 if (!ref) {
678 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
679 IDirectSoundImpl_Release(This->pds);
680 HeapFree(GetProcessHeap(), 0, This);
681 TRACE("(%p) released\n", This);
683 return ref;
686 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
687 LPDIRECTSOUND iface,
688 LPCDSBUFFERDESC dsbd,
689 LPLPDIRECTSOUNDBUFFER ppdsb,
690 LPUNKNOWN lpunk)
692 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
693 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
694 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
697 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
698 LPDIRECTSOUND iface,
699 LPDSCAPS lpDSCaps)
701 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
702 TRACE("(%p,%p)\n",This,lpDSCaps);
703 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
706 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
707 LPDIRECTSOUND iface,
708 LPDIRECTSOUNDBUFFER psb,
709 LPLPDIRECTSOUNDBUFFER ppdsb)
711 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
712 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
713 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
716 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
717 LPDIRECTSOUND iface,
718 HWND hwnd,
719 DWORD level)
721 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
722 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
723 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
726 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
727 LPDIRECTSOUND iface)
729 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
730 TRACE("(%p)\n", This);
731 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
734 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
735 LPDIRECTSOUND iface,
736 LPDWORD lpdwSpeakerConfig)
738 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
739 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
740 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
743 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
744 LPDIRECTSOUND iface,
745 DWORD config)
747 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
748 TRACE("(%p,0x%08x)\n",This,config);
749 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
752 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
753 LPDIRECTSOUND iface,
754 LPCGUID lpcGuid)
756 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
757 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
758 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
761 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
763 IDirectSound8_IDirectSound_QueryInterface,
764 IDirectSound8_IDirectSound_AddRef,
765 IDirectSound8_IDirectSound_Release,
766 IDirectSound8_IDirectSound_CreateSoundBuffer,
767 IDirectSound8_IDirectSound_GetCaps,
768 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
769 IDirectSound8_IDirectSound_SetCooperativeLevel,
770 IDirectSound8_IDirectSound_Compact,
771 IDirectSound8_IDirectSound_GetSpeakerConfig,
772 IDirectSound8_IDirectSound_SetSpeakerConfig,
773 IDirectSound8_IDirectSound_Initialize
776 static HRESULT IDirectSound8_IDirectSound_Create(
777 LPDIRECTSOUND8 pds,
778 LPDIRECTSOUND * ppds)
780 IDirectSound8_IDirectSound * pdsds;
781 TRACE("(%p,%p)\n",pds,ppds);
783 if (ppds == NULL) {
784 ERR("invalid parameter: ppds == NULL\n");
785 return DSERR_INVALIDPARAM;
788 if (pds == NULL) {
789 ERR("invalid parameter: pds == NULL\n");
790 *ppds = NULL;
791 return DSERR_INVALIDPARAM;
794 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
795 if (pdsds == NULL) {
796 WARN("out of memory\n");
797 *ppds = NULL;
798 return DSERR_OUTOFMEMORY;
801 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
802 pdsds->ref = 0;
803 pdsds->pds = pds;
805 IDirectSoundImpl_AddRef(pds);
806 *ppds = (LPDIRECTSOUND)pdsds;
808 return DS_OK;
811 /*******************************************************************************
812 * IDirectSound8_IDirectSound8
814 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
815 LPDIRECTSOUND8 iface,
816 REFIID riid,
817 LPVOID * ppobj)
819 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
820 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
821 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
824 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
825 LPDIRECTSOUND8 iface)
827 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
828 ULONG ref = InterlockedIncrement(&(This->ref));
829 TRACE("(%p) ref was %d\n", This, ref - 1);
830 return ref;
833 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
834 LPDIRECTSOUND8 iface)
836 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
837 ULONG ref = InterlockedDecrement(&(This->ref));
838 TRACE("(%p) ref was %d\n", This, ref + 1);
839 if (!ref) {
840 ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
841 IDirectSoundImpl_Release(This->pds);
842 HeapFree(GetProcessHeap(), 0, This);
843 TRACE("(%p) released\n", This);
845 return ref;
848 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
849 LPDIRECTSOUND8 iface,
850 LPCDSBUFFERDESC dsbd,
851 LPLPDIRECTSOUNDBUFFER ppdsb,
852 LPUNKNOWN lpunk)
854 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
855 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
856 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
859 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
860 LPDIRECTSOUND8 iface,
861 LPDSCAPS lpDSCaps)
863 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
864 TRACE("(%p,%p)\n",This,lpDSCaps);
865 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
868 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
869 LPDIRECTSOUND8 iface,
870 LPDIRECTSOUNDBUFFER psb,
871 LPLPDIRECTSOUNDBUFFER ppdsb)
873 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
874 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
875 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
878 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
879 LPDIRECTSOUND8 iface,
880 HWND hwnd,
881 DWORD level)
883 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
884 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
885 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
888 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
889 LPDIRECTSOUND8 iface)
891 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
892 TRACE("(%p)\n", This);
893 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
896 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
897 LPDIRECTSOUND8 iface,
898 LPDWORD lpdwSpeakerConfig)
900 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
901 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
902 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
905 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
906 LPDIRECTSOUND8 iface,
907 DWORD config)
909 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
910 TRACE("(%p,0x%08x)\n",This,config);
911 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
914 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
915 LPDIRECTSOUND8 iface,
916 LPCGUID lpcGuid)
918 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
919 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
920 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
923 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
924 LPDIRECTSOUND8 iface,
925 LPDWORD pdwCertified)
927 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
928 TRACE("(%p, %p)\n", This, pdwCertified);
929 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
932 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
934 IDirectSound8_IDirectSound8_QueryInterface,
935 IDirectSound8_IDirectSound8_AddRef,
936 IDirectSound8_IDirectSound8_Release,
937 IDirectSound8_IDirectSound8_CreateSoundBuffer,
938 IDirectSound8_IDirectSound8_GetCaps,
939 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
940 IDirectSound8_IDirectSound8_SetCooperativeLevel,
941 IDirectSound8_IDirectSound8_Compact,
942 IDirectSound8_IDirectSound8_GetSpeakerConfig,
943 IDirectSound8_IDirectSound8_SetSpeakerConfig,
944 IDirectSound8_IDirectSound8_Initialize,
945 IDirectSound8_IDirectSound8_VerifyCertification
948 static HRESULT IDirectSound8_IDirectSound8_Create(
949 LPDIRECTSOUND8 pds,
950 LPDIRECTSOUND8 * ppds)
952 IDirectSound8_IDirectSound8 * pdsds;
953 TRACE("(%p,%p)\n",pds,ppds);
955 if (ppds == NULL) {
956 ERR("invalid parameter: ppds == NULL\n");
957 return DSERR_INVALIDPARAM;
960 if (pds == NULL) {
961 ERR("invalid parameter: pds == NULL\n");
962 *ppds = NULL;
963 return DSERR_INVALIDPARAM;
966 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
967 if (pdsds == NULL) {
968 WARN("out of memory\n");
969 *ppds = NULL;
970 return DSERR_OUTOFMEMORY;
973 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
974 pdsds->ref = 0;
975 pdsds->pds = pds;
977 IDirectSoundImpl_AddRef(pds);
978 *ppds = (LPDIRECTSOUND8)pdsds;
980 return DS_OK;
983 HRESULT DSOUND_Create(
984 REFIID riid,
985 LPDIRECTSOUND *ppDS)
987 LPDIRECTSOUND8 pDS;
988 HRESULT hr;
989 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
991 if (!IsEqualIID(riid, &IID_IUnknown) &&
992 !IsEqualIID(riid, &IID_IDirectSound)) {
993 *ppDS = 0;
994 return E_NOINTERFACE;
997 /* Get dsound configuration */
998 setup_dsound_options();
1000 hr = IDirectSoundImpl_Create(&pDS);
1001 if (hr == DS_OK) {
1002 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1003 if (*ppDS)
1004 IDirectSound_IDirectSound_AddRef(*ppDS);
1005 else {
1006 WARN("IDirectSound_IDirectSound_Create failed\n");
1007 IDirectSound8_Release(pDS);
1009 } else {
1010 WARN("IDirectSoundImpl_Create failed\n");
1011 *ppDS = 0;
1014 return hr;
1017 /*******************************************************************************
1018 * DirectSoundCreate (DSOUND.1)
1020 * Creates and initializes a DirectSound interface.
1022 * PARAMS
1023 * lpcGUID [I] Address of the GUID that identifies the sound device.
1024 * ppDS [O] Address of a variable to receive the interface pointer.
1025 * pUnkOuter [I] Must be NULL.
1027 * RETURNS
1028 * Success: DS_OK
1029 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1030 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1032 HRESULT WINAPI DirectSoundCreate(
1033 LPCGUID lpcGUID,
1034 LPDIRECTSOUND *ppDS,
1035 IUnknown *pUnkOuter)
1037 HRESULT hr;
1038 LPDIRECTSOUND pDS;
1040 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1042 if (ppDS == NULL) {
1043 WARN("invalid parameter: ppDS == NULL\n");
1044 return DSERR_INVALIDPARAM;
1047 if (pUnkOuter != NULL) {
1048 WARN("invalid parameter: pUnkOuter != NULL\n");
1049 *ppDS = 0;
1050 return DSERR_INVALIDPARAM;
1053 hr = DSOUND_Create(&IID_IDirectSound, &pDS);
1054 if (hr == DS_OK) {
1055 hr = IDirectSound_Initialize(pDS, lpcGUID);
1056 if (hr != DS_OK) {
1057 if (hr != DSERR_ALREADYINITIALIZED) {
1058 IDirectSound_Release(pDS);
1059 pDS = 0;
1060 } else
1061 hr = DS_OK;
1065 *ppDS = pDS;
1067 return hr;
1070 HRESULT DSOUND_Create8(
1071 REFIID riid,
1072 LPDIRECTSOUND8 *ppDS)
1074 LPDIRECTSOUND8 pDS;
1075 HRESULT hr;
1076 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
1078 if (!IsEqualIID(riid, &IID_IUnknown) &&
1079 !IsEqualIID(riid, &IID_IDirectSound) &&
1080 !IsEqualIID(riid, &IID_IDirectSound8)) {
1081 *ppDS = 0;
1082 return E_NOINTERFACE;
1085 /* Get dsound configuration */
1086 setup_dsound_options();
1088 hr = IDirectSoundImpl_Create(&pDS);
1089 if (hr == DS_OK) {
1090 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1091 if (*ppDS)
1092 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1093 else {
1094 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1095 IDirectSound8_Release(pDS);
1097 } else {
1098 WARN("IDirectSoundImpl_Create failed\n");
1099 *ppDS = 0;
1102 return hr;
1105 /*******************************************************************************
1106 * DirectSoundCreate8 (DSOUND.11)
1108 * Creates and initializes a DirectSound8 interface.
1110 * PARAMS
1111 * lpcGUID [I] Address of the GUID that identifies the sound device.
1112 * ppDS [O] Address of a variable to receive the interface pointer.
1113 * pUnkOuter [I] Must be NULL.
1115 * RETURNS
1116 * Success: DS_OK
1117 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1118 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1120 HRESULT WINAPI DirectSoundCreate8(
1121 LPCGUID lpcGUID,
1122 LPDIRECTSOUND8 *ppDS,
1123 IUnknown *pUnkOuter)
1125 HRESULT hr;
1126 LPDIRECTSOUND8 pDS;
1128 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1130 if (ppDS == NULL) {
1131 WARN("invalid parameter: ppDS == NULL\n");
1132 return DSERR_INVALIDPARAM;
1135 if (pUnkOuter != NULL) {
1136 WARN("invalid parameter: pUnkOuter != NULL\n");
1137 *ppDS = 0;
1138 return DSERR_INVALIDPARAM;
1141 hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
1142 if (hr == DS_OK) {
1143 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1144 if (hr != DS_OK) {
1145 if (hr != DSERR_ALREADYINITIALIZED) {
1146 IDirectSound8_Release(pDS);
1147 pDS = 0;
1148 } else
1149 hr = DS_OK;
1153 *ppDS = pDS;
1155 return hr;
1158 /*******************************************************************************
1159 * DirectSoundDevice
1161 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
1163 DirectSoundDevice * device;
1164 TRACE("(%p)\n", ppDevice);
1166 /* Allocate memory */
1167 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
1168 if (device == NULL) {
1169 WARN("out of memory\n");
1170 return DSERR_OUTOFMEMORY;
1173 device->ref = 1;
1174 device->priolevel = DSSCL_NORMAL;
1175 device->state = STATE_STOPPED;
1176 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
1178 /* 3D listener initial parameters */
1179 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1180 device->ds3dl.vPosition.x = 0.0;
1181 device->ds3dl.vPosition.y = 0.0;
1182 device->ds3dl.vPosition.z = 0.0;
1183 device->ds3dl.vVelocity.x = 0.0;
1184 device->ds3dl.vVelocity.y = 0.0;
1185 device->ds3dl.vVelocity.z = 0.0;
1186 device->ds3dl.vOrientFront.x = 0.0;
1187 device->ds3dl.vOrientFront.y = 0.0;
1188 device->ds3dl.vOrientFront.z = 1.0;
1189 device->ds3dl.vOrientTop.x = 0.0;
1190 device->ds3dl.vOrientTop.y = 1.0;
1191 device->ds3dl.vOrientTop.z = 0.0;
1192 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1193 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1194 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1196 device->prebuf = ds_snd_queue_max;
1197 device->guid = GUID_NULL;
1199 /* Set default wave format (may need it for waveOutOpen) */
1200 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
1201 if (device->pwfx == NULL) {
1202 WARN("out of memory\n");
1203 HeapFree(GetProcessHeap(),0,device);
1204 return DSERR_OUTOFMEMORY;
1207 /* We rely on the sound driver to return the actual sound format of
1208 * the device if it does not support 22050x8x2 and is given the
1209 * WAVE_DIRECTSOUND flag.
1211 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1212 device->pwfx->nSamplesPerSec = ds_default_sample_rate;
1213 device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
1214 device->pwfx->nChannels = 2;
1215 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
1216 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
1217 device->pwfx->cbSize = 0;
1219 InitializeCriticalSection(&(device->mixlock));
1220 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
1222 RtlInitializeResource(&(device->buffer_list_lock));
1224 *ppDevice = device;
1226 return DS_OK;
1229 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
1231 ULONG ref = InterlockedIncrement(&(device->ref));
1232 TRACE("(%p) ref was %d\n", device, ref - 1);
1233 return ref;
1236 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
1238 HRESULT hr;
1239 ULONG ref = InterlockedDecrement(&(device->ref));
1240 TRACE("(%p) ref was %u\n", device, ref + 1);
1241 if (!ref) {
1242 int i;
1243 timeKillEvent(device->timerID);
1244 timeEndPeriod(DS_TIME_RES);
1246 /* The kill event should have allowed the timer process to expire
1247 * but try to grab the lock just in case. Can't hold lock because
1248 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1249 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1250 RtlReleaseResource(&(device->buffer_list_lock));
1252 /* It is allowed to release this object even when buffers are playing */
1253 if (device->buffers) {
1254 WARN("%d secondary buffers not released\n", device->nrofbuffers);
1255 for( i=0;i<device->nrofbuffers;i++)
1256 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
1259 if (device->primary) {
1260 WARN("primary buffer not released\n");
1261 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
1264 hr = DSOUND_PrimaryDestroy(device);
1265 if (hr != DS_OK)
1266 WARN("DSOUND_PrimaryDestroy failed\n");
1268 if (device->driver)
1269 IDsDriver_Close(device->driver);
1271 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
1272 waveOutClose(device->hwo);
1274 if (device->driver)
1275 IDsDriver_Release(device->driver);
1277 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
1279 HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
1280 HeapFree(GetProcessHeap(), 0, device->mix_buffer);
1281 if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
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);
1289 return ref;
1292 HRESULT DirectSoundDevice_GetCaps(
1293 DirectSoundDevice * device,
1294 LPDSCAPS lpDSCaps)
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);
1318 TRACE(")\n");
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;
1339 /* driver doesn't have these */
1340 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
1341 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
1343 return DS_OK;
1346 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
1348 HRESULT hr = DS_OK;
1349 unsigned wod, wodn;
1350 BOOLEAN found = FALSE;
1351 GUID devGUID;
1352 DirectSoundDevice * device = *ppDevice;
1353 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
1355 if (*ppDevice != NULL) {
1356 WARN("already initialized\n");
1357 return DSERR_ALREADYINITIALIZED;
1360 /* Default device? */
1361 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1362 lpcGUID = &DSDEVID_DefaultPlayback;
1364 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1365 WARN("invalid parameter: lpcGUID\n");
1366 return DSERR_INVALIDPARAM;
1369 /* Enumerate WINMM audio devices and find the one we want */
1370 wodn = waveOutGetNumDevs();
1371 if (!wodn) {
1372 WARN("no driver\n");
1373 return DSERR_NODRIVER;
1376 for (wod=0; wod<wodn; wod++) {
1377 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
1378 found = TRUE;
1379 break;
1383 if (found == FALSE) {
1384 WARN("No device found matching given ID!\n");
1385 return DSERR_NODRIVER;
1388 if (DSOUND_renderer[wod]) {
1389 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
1390 device = DSOUND_renderer[wod];
1391 DirectSoundDevice_AddRef(device);
1392 *ppDevice = device;
1393 return DS_OK;
1394 } else {
1395 ERR("device GUID doesn't match\n");
1396 hr = DSERR_GENERIC;
1397 return hr;
1399 } else {
1400 hr = DirectSoundDevice_Create(&device);
1401 if (hr != DS_OK) {
1402 WARN("DirectSoundDevice_Create failed\n");
1403 return hr;
1407 *ppDevice = device;
1408 device->guid = devGUID;
1409 device->driver = NULL;
1411 device->drvdesc.dnDevNode = wod;
1412 hr = DSOUND_ReopenDevice(device, FALSE);
1413 if (FAILED(hr))
1415 WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
1416 return hr;
1419 if (device->driver) {
1420 /* the driver is now open, so it's now allowed to call GetCaps */
1421 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
1422 if (hr != DS_OK) {
1423 WARN("IDsDriver_GetCaps failed\n");
1424 return hr;
1426 } else {
1427 WAVEOUTCAPSA woc;
1428 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
1429 if (hr != DS_OK) {
1430 WARN("waveOutGetDevCaps failed\n");
1431 return hr;
1433 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
1434 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
1435 (woc.dwFormats & WAVE_FORMAT_2M08) ||
1436 (woc.dwFormats & WAVE_FORMAT_4M08) ||
1437 (woc.dwFormats & WAVE_FORMAT_48M08) ||
1438 (woc.dwFormats & WAVE_FORMAT_96M08)) {
1439 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1440 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1442 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
1443 (woc.dwFormats & WAVE_FORMAT_2M16) ||
1444 (woc.dwFormats & WAVE_FORMAT_4M16) ||
1445 (woc.dwFormats & WAVE_FORMAT_48M16) ||
1446 (woc.dwFormats & WAVE_FORMAT_96M16)) {
1447 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1448 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1450 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
1451 (woc.dwFormats & WAVE_FORMAT_2S08) ||
1452 (woc.dwFormats & WAVE_FORMAT_4S08) ||
1453 (woc.dwFormats & WAVE_FORMAT_48S08) ||
1454 (woc.dwFormats & WAVE_FORMAT_96S08)) {
1455 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1456 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1458 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
1459 (woc.dwFormats & WAVE_FORMAT_2S16) ||
1460 (woc.dwFormats & WAVE_FORMAT_4S16) ||
1461 (woc.dwFormats & WAVE_FORMAT_48S16) ||
1462 (woc.dwFormats & WAVE_FORMAT_96S16)) {
1463 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1464 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1466 if (ds_emuldriver)
1467 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
1468 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
1469 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
1470 ZeroMemory(&device->volpan, sizeof(device->volpan));
1473 hr = DSOUND_PrimaryCreate(device);
1474 if (hr == DS_OK) {
1475 UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
1476 TIMECAPS time;
1478 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
1479 timeGetDevCaps(&time, sizeof(TIMECAPS));
1480 TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
1481 if (triggertime < time.wPeriodMin)
1482 triggertime = time.wPeriodMin;
1483 if (res < time.wPeriodMin)
1484 res = time.wPeriodMin;
1485 if (timeBeginPeriod(res) == TIMERR_NOCANDO)
1486 WARN("Could not set minimum resolution, don't expect sound\n");
1487 id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
1488 if (!id)
1490 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1491 id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC);
1492 if (!id) ERR("Could not create timer, sound playback will not occur\n");
1494 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id;
1495 } else {
1496 WARN("DSOUND_PrimaryCreate failed\n");
1499 return hr;
1502 HRESULT DirectSoundDevice_CreateSoundBuffer(
1503 DirectSoundDevice * device,
1504 LPCDSBUFFERDESC dsbd,
1505 LPLPDIRECTSOUNDBUFFER ppdsb,
1506 LPUNKNOWN lpunk,
1507 BOOL from8)
1509 HRESULT hres = DS_OK;
1510 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
1512 if (device == NULL) {
1513 WARN("not initialized\n");
1514 return DSERR_UNINITIALIZED;
1517 if (dsbd == NULL) {
1518 WARN("invalid parameter: dsbd == NULL\n");
1519 return DSERR_INVALIDPARAM;
1522 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
1523 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
1524 WARN("invalid parameter: dsbd\n");
1525 return DSERR_INVALIDPARAM;
1528 if (ppdsb == NULL) {
1529 WARN("invalid parameter: ppdsb == NULL\n");
1530 return DSERR_INVALIDPARAM;
1532 *ppdsb = NULL;
1534 if (TRACE_ON(dsound)) {
1535 TRACE("(structsize=%d)\n",dsbd->dwSize);
1536 TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
1537 _dump_DSBCAPS(dsbd->dwFlags);
1538 TRACE(")\n");
1539 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
1540 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
1543 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
1544 if (dsbd->lpwfxFormat != NULL) {
1545 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1546 "primary buffer\n");
1547 return DSERR_INVALIDPARAM;
1550 if (device->primary) {
1551 WARN("Primary Buffer already created\n");
1552 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1553 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1554 } else {
1555 device->dsbd = *dsbd;
1556 device->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
1557 if (device->hwbuf)
1558 device->dsbd.dwFlags |= DSBCAPS_LOCHARDWARE;
1559 else device->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
1560 hres = PrimaryBufferImpl_Create(device, &(device->primary), &(device->dsbd));
1561 if (device->primary) {
1562 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1563 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1564 } else
1565 WARN("PrimaryBufferImpl_Create failed\n");
1567 } else {
1568 IDirectSoundBufferImpl * dsb;
1569 WAVEFORMATEXTENSIBLE *pwfxe;
1571 if (dsbd->lpwfxFormat == NULL) {
1572 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1573 "secondary buffer\n");
1574 return DSERR_INVALIDPARAM;
1576 pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
1578 if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
1580 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
1581 return DSERR_CONTROLUNAVAIL;
1583 if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
1585 /* check if cbSize is at least 22 bytes */
1586 if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
1588 WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize);
1589 return DSERR_INVALIDPARAM;
1592 /* cbSize should be 22 bytes, with one possible exception */
1593 if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) &&
1594 !((IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) &&
1595 pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
1597 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
1598 return DSERR_CONTROLUNAVAIL;
1601 if ((!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) && (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
1603 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
1604 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
1605 return DSERR_INVALIDPARAM;
1607 if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample)
1609 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample);
1610 return DSERR_INVALIDPARAM;
1612 if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample)
1614 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample);
1615 return DSERR_CONTROLUNAVAIL;
1619 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1620 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1621 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
1622 dsbd->lpwfxFormat->nSamplesPerSec,
1623 dsbd->lpwfxFormat->nAvgBytesPerSec,
1624 dsbd->lpwfxFormat->nBlockAlign,
1625 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
1627 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
1628 WARN("invalid parameter: 3D buffer format must be mono\n");
1629 return DSERR_INVALIDPARAM;
1632 hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd);
1633 if (dsb) {
1634 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
1635 if (*ppdsb) {
1636 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
1637 IDirectSoundBuffer_AddRef(*ppdsb);
1638 } else
1639 WARN("SecondaryBufferImpl_Create failed\n");
1640 } else
1641 WARN("IDirectSoundBufferImpl_Create failed\n");
1644 return hres;
1647 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
1648 DirectSoundDevice * device,
1649 LPDIRECTSOUNDBUFFER psb,
1650 LPLPDIRECTSOUNDBUFFER ppdsb)
1652 HRESULT hres = DS_OK;
1653 IDirectSoundBufferImpl* dsb;
1654 TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
1656 if (device == NULL) {
1657 WARN("not initialized\n");
1658 return DSERR_UNINITIALIZED;
1661 if (psb == NULL) {
1662 WARN("invalid parameter: psb == NULL\n");
1663 return DSERR_INVALIDPARAM;
1666 if (ppdsb == NULL) {
1667 WARN("invalid parameter: ppdsb == NULL\n");
1668 return DSERR_INVALIDPARAM;
1671 /* make sure we have a secondary buffer */
1672 if ((PrimaryBufferImpl *)psb == device->primary) {
1673 WARN("trying to duplicate primary buffer\n");
1674 *ppdsb = NULL;
1675 return DSERR_INVALIDCALL;
1678 /* duplicate the actual buffer implementation */
1679 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb,
1680 ((SecondaryBufferImpl *)psb)->dsb);
1682 if (hres == DS_OK) {
1683 /* create a new secondary buffer using the new implementation */
1684 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
1685 if (*ppdsb) {
1686 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
1687 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
1688 } else {
1689 WARN("SecondaryBufferImpl_Create failed\n");
1690 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
1691 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb);
1695 return hres;
1698 HRESULT DirectSoundDevice_SetCooperativeLevel(
1699 DirectSoundDevice * device,
1700 HWND hwnd,
1701 DWORD level)
1703 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
1705 if (device == NULL) {
1706 WARN("not initialized\n");
1707 return DSERR_UNINITIALIZED;
1710 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
1711 WARN("level=%s not fully supported\n",
1712 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1715 device->priolevel = level;
1716 return DS_OK;
1719 HRESULT DirectSoundDevice_Compact(
1720 DirectSoundDevice * device)
1722 TRACE("(%p)\n", device);
1724 if (device == NULL) {
1725 WARN("not initialized\n");
1726 return DSERR_UNINITIALIZED;
1729 if (device->priolevel < DSSCL_PRIORITY) {
1730 WARN("incorrect priority level\n");
1731 return DSERR_PRIOLEVELNEEDED;
1734 return DS_OK;
1737 HRESULT DirectSoundDevice_GetSpeakerConfig(
1738 DirectSoundDevice * device,
1739 LPDWORD lpdwSpeakerConfig)
1741 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
1743 if (device == NULL) {
1744 WARN("not initialized\n");
1745 return DSERR_UNINITIALIZED;
1748 if (lpdwSpeakerConfig == NULL) {
1749 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1750 return DSERR_INVALIDPARAM;
1753 WARN("not fully functional\n");
1754 *lpdwSpeakerConfig = device->speaker_config;
1755 return DS_OK;
1758 HRESULT DirectSoundDevice_SetSpeakerConfig(
1759 DirectSoundDevice * device,
1760 DWORD config)
1762 TRACE("(%p,0x%08x)\n",device,config);
1764 if (device == NULL) {
1765 WARN("not initialized\n");
1766 return DSERR_UNINITIALIZED;
1769 device->speaker_config = config;
1770 WARN("not fully functional\n");
1771 return DS_OK;
1774 HRESULT DirectSoundDevice_VerifyCertification(
1775 DirectSoundDevice * device,
1776 LPDWORD pdwCertified)
1778 TRACE("(%p, %p)\n",device,pdwCertified);
1780 if (device == NULL) {
1781 WARN("not initialized\n");
1782 return DSERR_UNINITIALIZED;
1785 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
1786 *pdwCertified = DS_CERTIFIED;
1787 else
1788 *pdwCertified = DS_UNCERTIFIED;
1790 return DS_OK;
1794 * Add secondary buffer to buffer list.
1795 * Gets exclusive access to buffer for writing.
1797 HRESULT DirectSoundDevice_AddBuffer(
1798 DirectSoundDevice * device,
1799 IDirectSoundBufferImpl * pDSB)
1801 IDirectSoundBufferImpl **newbuffers;
1802 HRESULT hr = DS_OK;
1804 TRACE("(%p, %p)\n", device, pDSB);
1806 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1808 if (device->buffers)
1809 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1810 else
1811 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1813 if (newbuffers) {
1814 device->buffers = newbuffers;
1815 device->buffers[device->nrofbuffers] = pDSB;
1816 device->nrofbuffers++;
1817 TRACE("buffer count is now %d\n", device->nrofbuffers);
1818 } else {
1819 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
1820 hr = DSERR_OUTOFMEMORY;
1823 RtlReleaseResource(&(device->buffer_list_lock));
1825 return hr;
1829 * Remove secondary buffer from buffer list.
1830 * Gets exclusive access to buffer for writing.
1832 HRESULT DirectSoundDevice_RemoveBuffer(
1833 DirectSoundDevice * device,
1834 IDirectSoundBufferImpl * pDSB)
1836 int i;
1837 HRESULT hr = DS_OK;
1839 TRACE("(%p, %p)\n", device, pDSB);
1841 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1843 for (i = 0; i < device->nrofbuffers; i++)
1844 if (device->buffers[i] == pDSB)
1845 break;
1847 if (i < device->nrofbuffers) {
1848 /* Put the last buffer of the list in the (now empty) position */
1849 device->buffers[i] = device->buffers[device->nrofbuffers - 1];
1850 device->nrofbuffers--;
1851 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
1852 TRACE("buffer count is now %d\n", device->nrofbuffers);
1855 if (device->nrofbuffers == 0) {
1856 HeapFree(GetProcessHeap(),0,device->buffers);
1857 device->buffers = NULL;
1860 RtlReleaseResource(&(device->buffer_list_lock));
1862 return hr;