dsound: Remove hardware acceleration support.
[wine.git] / dlls / dsound / dsound.c
blobbefa58dc0298fe56859cbb84f7ad6625799300be
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 "dsound_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
44 /*****************************************************************************
45 * IDirectSound COM components
47 struct IDirectSound_IUnknown {
48 const IUnknownVtbl *lpVtbl;
49 LONG ref;
50 LPDIRECTSOUND8 pds;
53 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
55 struct IDirectSound_IDirectSound {
56 const IDirectSoundVtbl *lpVtbl;
57 LONG ref;
58 LPDIRECTSOUND8 pds;
61 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
63 /*****************************************************************************
64 * IDirectSound8 COM components
66 struct IDirectSound8_IUnknown {
67 const IUnknownVtbl *lpVtbl;
68 LONG ref;
69 LPDIRECTSOUND8 pds;
72 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
73 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
75 struct IDirectSound8_IDirectSound {
76 const IDirectSoundVtbl *lpVtbl;
77 LONG ref;
78 LPDIRECTSOUND8 pds;
81 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
82 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
84 struct IDirectSound8_IDirectSound8 {
85 const IDirectSound8Vtbl *lpVtbl;
86 LONG ref;
87 LPDIRECTSOUND8 pds;
90 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
91 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
93 /*****************************************************************************
94 * IDirectSound implementation structure
96 struct IDirectSoundImpl
98 LONG ref;
100 DirectSoundDevice *device;
101 LPUNKNOWN pUnknown;
102 LPDIRECTSOUND pDS;
103 LPDIRECTSOUND8 pDS8;
106 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
108 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
109 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
111 const char * dumpCooperativeLevel(DWORD level)
113 #define LE(x) case x: return #x
114 switch (level) {
115 LE(DSSCL_NORMAL);
116 LE(DSSCL_PRIORITY);
117 LE(DSSCL_EXCLUSIVE);
118 LE(DSSCL_WRITEPRIMARY);
120 #undef LE
121 return wine_dbg_sprintf("Unknown(%08x)", level);
124 static void _dump_DSCAPS(DWORD xmask) {
125 struct {
126 DWORD mask;
127 const char *name;
128 } flags[] = {
129 #define FE(x) { x, #x },
130 FE(DSCAPS_PRIMARYMONO)
131 FE(DSCAPS_PRIMARYSTEREO)
132 FE(DSCAPS_PRIMARY8BIT)
133 FE(DSCAPS_PRIMARY16BIT)
134 FE(DSCAPS_CONTINUOUSRATE)
135 FE(DSCAPS_EMULDRIVER)
136 FE(DSCAPS_CERTIFIED)
137 FE(DSCAPS_SECONDARYMONO)
138 FE(DSCAPS_SECONDARYSTEREO)
139 FE(DSCAPS_SECONDARY8BIT)
140 FE(DSCAPS_SECONDARY16BIT)
141 #undef FE
143 unsigned int i;
145 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
146 if ((flags[i].mask & xmask) == flags[i].mask)
147 TRACE("%s ",flags[i].name);
150 static void _dump_DSBCAPS(DWORD xmask) {
151 struct {
152 DWORD mask;
153 const char *name;
154 } flags[] = {
155 #define FE(x) { x, #x },
156 FE(DSBCAPS_PRIMARYBUFFER)
157 FE(DSBCAPS_STATIC)
158 FE(DSBCAPS_LOCHARDWARE)
159 FE(DSBCAPS_LOCSOFTWARE)
160 FE(DSBCAPS_CTRL3D)
161 FE(DSBCAPS_CTRLFREQUENCY)
162 FE(DSBCAPS_CTRLPAN)
163 FE(DSBCAPS_CTRLVOLUME)
164 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
165 FE(DSBCAPS_STICKYFOCUS)
166 FE(DSBCAPS_GLOBALFOCUS)
167 FE(DSBCAPS_GETCURRENTPOSITION2)
168 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
169 #undef FE
171 unsigned int i;
173 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
174 if ((flags[i].mask & xmask) == flags[i].mask)
175 TRACE("%s ",flags[i].name);
178 /*******************************************************************************
179 * IDirectSoundImpl_DirectSound
181 static HRESULT DSOUND_QueryInterface(
182 LPDIRECTSOUND8 iface,
183 REFIID riid,
184 LPVOID * ppobj)
186 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
187 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
189 if (ppobj == NULL) {
190 WARN("invalid parameter\n");
191 return E_INVALIDARG;
194 if (IsEqualIID(riid, &IID_IUnknown)) {
195 if (!This->pUnknown) {
196 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
197 if (!This->pUnknown) {
198 WARN("IDirectSound_IUnknown_Create() failed\n");
199 *ppobj = NULL;
200 return E_NOINTERFACE;
203 IDirectSound_IUnknown_AddRef(This->pUnknown);
204 *ppobj = This->pUnknown;
205 return S_OK;
206 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
207 if (!This->pDS) {
208 IDirectSound_IDirectSound_Create(iface, &This->pDS);
209 if (!This->pDS) {
210 WARN("IDirectSound_IDirectSound_Create() failed\n");
211 *ppobj = NULL;
212 return E_NOINTERFACE;
215 IDirectSound_IDirectSound_AddRef(This->pDS);
216 *ppobj = This->pDS;
217 return S_OK;
220 *ppobj = NULL;
221 WARN("Unknown IID %s\n",debugstr_guid(riid));
222 return E_NOINTERFACE;
225 static HRESULT DSOUND_QueryInterface8(
226 LPDIRECTSOUND8 iface,
227 REFIID riid,
228 LPVOID * ppobj)
230 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
231 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
233 if (ppobj == NULL) {
234 WARN("invalid parameter\n");
235 return E_INVALIDARG;
238 if (IsEqualIID(riid, &IID_IUnknown)) {
239 if (!This->pUnknown) {
240 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
241 if (!This->pUnknown) {
242 WARN("IDirectSound8_IUnknown_Create() failed\n");
243 *ppobj = NULL;
244 return E_NOINTERFACE;
247 IDirectSound8_IUnknown_AddRef(This->pUnknown);
248 *ppobj = This->pUnknown;
249 return S_OK;
250 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
251 if (!This->pDS) {
252 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
253 if (!This->pDS) {
254 WARN("IDirectSound8_IDirectSound_Create() failed\n");
255 *ppobj = NULL;
256 return E_NOINTERFACE;
259 IDirectSound8_IDirectSound_AddRef(This->pDS);
260 *ppobj = This->pDS;
261 return S_OK;
262 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
263 if (!This->pDS8) {
264 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
265 if (!This->pDS8) {
266 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
267 *ppobj = NULL;
268 return E_NOINTERFACE;
271 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
272 *ppobj = This->pDS8;
273 return S_OK;
276 *ppobj = NULL;
277 WARN("Unknown IID %s\n",debugstr_guid(riid));
278 return E_NOINTERFACE;
281 static ULONG IDirectSoundImpl_AddRef(
282 LPDIRECTSOUND8 iface)
284 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
285 ULONG ref = InterlockedIncrement(&(This->ref));
286 TRACE("(%p) ref was %d\n", This, ref - 1);
287 return ref;
290 static ULONG IDirectSoundImpl_Release(
291 LPDIRECTSOUND8 iface)
293 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
294 ULONG ref = InterlockedDecrement(&(This->ref));
295 TRACE("(%p) ref was %d\n", This, ref + 1);
297 if (!ref) {
298 if (This->device)
299 DirectSoundDevice_Release(This->device);
300 HeapFree(GetProcessHeap(),0,This);
301 TRACE("(%p) released\n", This);
303 return ref;
306 static HRESULT IDirectSoundImpl_Create(
307 LPDIRECTSOUND8 * ppDS)
309 IDirectSoundImpl* pDS;
310 TRACE("(%p)\n",ppDS);
312 /* Allocate memory */
313 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
314 if (pDS == NULL) {
315 WARN("out of memory\n");
316 *ppDS = NULL;
317 return DSERR_OUTOFMEMORY;
320 pDS->ref = 0;
321 pDS->device = NULL;
323 *ppDS = (LPDIRECTSOUND8)pDS;
325 return DS_OK;
328 /*******************************************************************************
329 * IDirectSound_IUnknown
331 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
332 LPUNKNOWN iface,
333 REFIID riid,
334 LPVOID * ppobj)
336 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
337 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
338 return DSOUND_QueryInterface(This->pds, riid, ppobj);
341 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
342 LPUNKNOWN iface)
344 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
345 ULONG ref = InterlockedIncrement(&(This->ref));
346 TRACE("(%p) ref was %d\n", This, ref - 1);
347 return ref;
350 static ULONG WINAPI IDirectSound_IUnknown_Release(
351 LPUNKNOWN iface)
353 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
354 ULONG ref = InterlockedDecrement(&(This->ref));
355 TRACE("(%p) ref was %d\n", This, ref + 1);
356 if (!ref) {
357 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
358 IDirectSoundImpl_Release(This->pds);
359 HeapFree(GetProcessHeap(), 0, This);
360 TRACE("(%p) released\n", This);
362 return ref;
365 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
367 IDirectSound_IUnknown_QueryInterface,
368 IDirectSound_IUnknown_AddRef,
369 IDirectSound_IUnknown_Release
372 static HRESULT IDirectSound_IUnknown_Create(
373 LPDIRECTSOUND8 pds,
374 LPUNKNOWN * ppunk)
376 IDirectSound_IUnknown * pdsunk;
377 TRACE("(%p,%p)\n",pds,ppunk);
379 if (ppunk == NULL) {
380 ERR("invalid parameter: ppunk == NULL\n");
381 return DSERR_INVALIDPARAM;
384 if (pds == NULL) {
385 ERR("invalid parameter: pds == NULL\n");
386 *ppunk = NULL;
387 return DSERR_INVALIDPARAM;
390 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
391 if (pdsunk == NULL) {
392 WARN("out of memory\n");
393 *ppunk = NULL;
394 return DSERR_OUTOFMEMORY;
397 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
398 pdsunk->ref = 0;
399 pdsunk->pds = pds;
401 IDirectSoundImpl_AddRef(pds);
402 *ppunk = (LPUNKNOWN)pdsunk;
404 return DS_OK;
407 /*******************************************************************************
408 * IDirectSound_IDirectSound
410 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
411 LPDIRECTSOUND iface,
412 REFIID riid,
413 LPVOID * ppobj)
415 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
416 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
417 return DSOUND_QueryInterface(This->pds, riid, ppobj);
420 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
421 LPDIRECTSOUND iface)
423 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
424 ULONG ref = InterlockedIncrement(&(This->ref));
425 TRACE("(%p) ref was %d\n", This, ref - 1);
426 return ref;
429 static ULONG WINAPI IDirectSound_IDirectSound_Release(
430 LPDIRECTSOUND iface)
432 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
433 ULONG ref = InterlockedDecrement(&(This->ref));
434 TRACE("(%p) ref was %d\n", This, ref + 1);
435 if (!ref) {
436 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
437 IDirectSoundImpl_Release(This->pds);
438 HeapFree(GetProcessHeap(), 0, This);
439 TRACE("(%p) released\n", This);
441 return ref;
444 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
445 LPDIRECTSOUND iface,
446 LPCDSBUFFERDESC dsbd,
447 LPLPDIRECTSOUNDBUFFER ppdsb,
448 LPUNKNOWN lpunk)
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(
456 LPDIRECTSOUND iface,
457 LPDSCAPS lpDSCaps)
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(
465 LPDIRECTSOUND iface,
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(
475 LPDIRECTSOUND iface,
476 HWND hwnd,
477 DWORD level)
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(
485 LPDIRECTSOUND iface)
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(
493 LPDIRECTSOUND iface,
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(
502 LPDIRECTSOUND iface,
503 DWORD config)
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(
511 LPDIRECTSOUND iface,
512 LPCGUID lpcGuid)
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(
535 LPDIRECTSOUND8 pds,
536 LPDIRECTSOUND * ppds)
538 IDirectSound_IDirectSound * pdsds;
539 TRACE("(%p,%p)\n",pds,ppds);
541 if (ppds == NULL) {
542 ERR("invalid parameter: ppds == NULL\n");
543 return DSERR_INVALIDPARAM;
546 if (pds == NULL) {
547 ERR("invalid parameter: pds == NULL\n");
548 *ppds = NULL;
549 return DSERR_INVALIDPARAM;
552 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
553 if (pdsds == NULL) {
554 WARN("out of memory\n");
555 *ppds = NULL;
556 return DSERR_OUTOFMEMORY;
559 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
560 pdsds->ref = 0;
561 pdsds->pds = pds;
563 IDirectSoundImpl_AddRef(pds);
564 *ppds = (LPDIRECTSOUND)pdsds;
566 return DS_OK;
569 /*******************************************************************************
570 * IDirectSound8_IUnknown
572 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
573 LPUNKNOWN iface,
574 REFIID riid,
575 LPVOID * ppobj)
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(
583 LPUNKNOWN iface)
585 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
586 ULONG ref = InterlockedIncrement(&(This->ref));
587 TRACE("(%p) ref was %d\n", This, ref - 1);
588 return ref;
591 static ULONG WINAPI IDirectSound8_IUnknown_Release(
592 LPUNKNOWN iface)
594 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
595 ULONG ref = InterlockedDecrement(&(This->ref));
596 TRACE("(%p) ref was %d\n", This, ref + 1);
597 if (!ref) {
598 ((IDirectSoundImpl*)This->pds)->pUnknown = NULL;
599 IDirectSoundImpl_Release(This->pds);
600 HeapFree(GetProcessHeap(), 0, This);
601 TRACE("(%p) released\n", This);
603 return ref;
606 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
608 IDirectSound8_IUnknown_QueryInterface,
609 IDirectSound8_IUnknown_AddRef,
610 IDirectSound8_IUnknown_Release
613 static HRESULT IDirectSound8_IUnknown_Create(
614 LPDIRECTSOUND8 pds,
615 LPUNKNOWN * ppunk)
617 IDirectSound8_IUnknown * pdsunk;
618 TRACE("(%p,%p)\n",pds,ppunk);
620 if (ppunk == NULL) {
621 ERR("invalid parameter: ppunk == NULL\n");
622 return DSERR_INVALIDPARAM;
625 if (pds == NULL) {
626 ERR("invalid parameter: pds == NULL\n");
627 *ppunk = NULL;
628 return DSERR_INVALIDPARAM;
631 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
632 if (pdsunk == NULL) {
633 WARN("out of memory\n");
634 *ppunk = NULL;
635 return DSERR_OUTOFMEMORY;
638 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
639 pdsunk->ref = 0;
640 pdsunk->pds = pds;
642 IDirectSoundImpl_AddRef(pds);
643 *ppunk = (LPUNKNOWN)pdsunk;
645 return DS_OK;
648 /*******************************************************************************
649 * IDirectSound8_IDirectSound
651 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
652 LPDIRECTSOUND iface,
653 REFIID riid,
654 LPVOID * ppobj)
656 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
657 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
658 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
661 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
662 LPDIRECTSOUND iface)
664 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
665 ULONG ref = InterlockedIncrement(&(This->ref));
666 TRACE("(%p) ref was %d\n", This, ref - 1);
667 return ref;
670 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
671 LPDIRECTSOUND iface)
673 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
674 ULONG ref = InterlockedDecrement(&(This->ref));
675 TRACE("(%p) ref was %d\n", This, ref + 1);
676 if (!ref) {
677 ((IDirectSoundImpl*)This->pds)->pDS = NULL;
678 IDirectSoundImpl_Release(This->pds);
679 HeapFree(GetProcessHeap(), 0, This);
680 TRACE("(%p) released\n", This);
682 return ref;
685 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
686 LPDIRECTSOUND iface,
687 LPCDSBUFFERDESC dsbd,
688 LPLPDIRECTSOUNDBUFFER ppdsb,
689 LPUNKNOWN lpunk)
691 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
692 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
693 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
696 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
697 LPDIRECTSOUND iface,
698 LPDSCAPS lpDSCaps)
700 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
701 TRACE("(%p,%p)\n",This,lpDSCaps);
702 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
705 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
706 LPDIRECTSOUND iface,
707 LPDIRECTSOUNDBUFFER psb,
708 LPLPDIRECTSOUNDBUFFER ppdsb)
710 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
711 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
712 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
715 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
716 LPDIRECTSOUND iface,
717 HWND hwnd,
718 DWORD level)
720 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
721 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
722 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
725 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
726 LPDIRECTSOUND iface)
728 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
729 TRACE("(%p)\n", This);
730 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
733 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
734 LPDIRECTSOUND iface,
735 LPDWORD lpdwSpeakerConfig)
737 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
738 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
739 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
742 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
743 LPDIRECTSOUND iface,
744 DWORD config)
746 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
747 TRACE("(%p,0x%08x)\n",This,config);
748 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
751 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
752 LPDIRECTSOUND iface,
753 LPCGUID lpcGuid)
755 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
756 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
757 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
760 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
762 IDirectSound8_IDirectSound_QueryInterface,
763 IDirectSound8_IDirectSound_AddRef,
764 IDirectSound8_IDirectSound_Release,
765 IDirectSound8_IDirectSound_CreateSoundBuffer,
766 IDirectSound8_IDirectSound_GetCaps,
767 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
768 IDirectSound8_IDirectSound_SetCooperativeLevel,
769 IDirectSound8_IDirectSound_Compact,
770 IDirectSound8_IDirectSound_GetSpeakerConfig,
771 IDirectSound8_IDirectSound_SetSpeakerConfig,
772 IDirectSound8_IDirectSound_Initialize
775 static HRESULT IDirectSound8_IDirectSound_Create(
776 LPDIRECTSOUND8 pds,
777 LPDIRECTSOUND * ppds)
779 IDirectSound8_IDirectSound * pdsds;
780 TRACE("(%p,%p)\n",pds,ppds);
782 if (ppds == NULL) {
783 ERR("invalid parameter: ppds == NULL\n");
784 return DSERR_INVALIDPARAM;
787 if (pds == NULL) {
788 ERR("invalid parameter: pds == NULL\n");
789 *ppds = NULL;
790 return DSERR_INVALIDPARAM;
793 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
794 if (pdsds == NULL) {
795 WARN("out of memory\n");
796 *ppds = NULL;
797 return DSERR_OUTOFMEMORY;
800 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
801 pdsds->ref = 0;
802 pdsds->pds = pds;
804 IDirectSoundImpl_AddRef(pds);
805 *ppds = (LPDIRECTSOUND)pdsds;
807 return DS_OK;
810 /*******************************************************************************
811 * IDirectSound8_IDirectSound8
813 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
814 LPDIRECTSOUND8 iface,
815 REFIID riid,
816 LPVOID * ppobj)
818 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
819 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
820 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
823 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
824 LPDIRECTSOUND8 iface)
826 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
827 ULONG ref = InterlockedIncrement(&(This->ref));
828 TRACE("(%p) ref was %d\n", This, ref - 1);
829 return ref;
832 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
833 LPDIRECTSOUND8 iface)
835 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
836 ULONG ref = InterlockedDecrement(&(This->ref));
837 TRACE("(%p) ref was %d\n", This, ref + 1);
838 if (!ref) {
839 ((IDirectSoundImpl*)This->pds)->pDS8 = NULL;
840 IDirectSoundImpl_Release(This->pds);
841 HeapFree(GetProcessHeap(), 0, This);
842 TRACE("(%p) released\n", This);
844 return ref;
847 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
848 LPDIRECTSOUND8 iface,
849 LPCDSBUFFERDESC dsbd,
850 LPLPDIRECTSOUNDBUFFER ppdsb,
851 LPUNKNOWN lpunk)
853 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
854 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
855 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
858 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
859 LPDIRECTSOUND8 iface,
860 LPDSCAPS lpDSCaps)
862 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
863 TRACE("(%p,%p)\n",This,lpDSCaps);
864 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
867 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
868 LPDIRECTSOUND8 iface,
869 LPDIRECTSOUNDBUFFER psb,
870 LPLPDIRECTSOUNDBUFFER ppdsb)
872 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
873 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
874 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
877 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
878 LPDIRECTSOUND8 iface,
879 HWND hwnd,
880 DWORD level)
882 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
883 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
884 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
887 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
888 LPDIRECTSOUND8 iface)
890 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
891 TRACE("(%p)\n", This);
892 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
895 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
896 LPDIRECTSOUND8 iface,
897 LPDWORD lpdwSpeakerConfig)
899 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
900 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
901 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
904 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
905 LPDIRECTSOUND8 iface,
906 DWORD config)
908 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
909 TRACE("(%p,0x%08x)\n",This,config);
910 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
913 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
914 LPDIRECTSOUND8 iface,
915 LPCGUID lpcGuid)
917 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
918 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
919 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
922 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
923 LPDIRECTSOUND8 iface,
924 LPDWORD pdwCertified)
926 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
927 TRACE("(%p, %p)\n", This, pdwCertified);
928 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
931 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
933 IDirectSound8_IDirectSound8_QueryInterface,
934 IDirectSound8_IDirectSound8_AddRef,
935 IDirectSound8_IDirectSound8_Release,
936 IDirectSound8_IDirectSound8_CreateSoundBuffer,
937 IDirectSound8_IDirectSound8_GetCaps,
938 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
939 IDirectSound8_IDirectSound8_SetCooperativeLevel,
940 IDirectSound8_IDirectSound8_Compact,
941 IDirectSound8_IDirectSound8_GetSpeakerConfig,
942 IDirectSound8_IDirectSound8_SetSpeakerConfig,
943 IDirectSound8_IDirectSound8_Initialize,
944 IDirectSound8_IDirectSound8_VerifyCertification
947 static HRESULT IDirectSound8_IDirectSound8_Create(
948 LPDIRECTSOUND8 pds,
949 LPDIRECTSOUND8 * ppds)
951 IDirectSound8_IDirectSound8 * pdsds;
952 TRACE("(%p,%p)\n",pds,ppds);
954 if (ppds == NULL) {
955 ERR("invalid parameter: ppds == NULL\n");
956 return DSERR_INVALIDPARAM;
959 if (pds == NULL) {
960 ERR("invalid parameter: pds == NULL\n");
961 *ppds = NULL;
962 return DSERR_INVALIDPARAM;
965 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
966 if (pdsds == NULL) {
967 WARN("out of memory\n");
968 *ppds = NULL;
969 return DSERR_OUTOFMEMORY;
972 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
973 pdsds->ref = 0;
974 pdsds->pds = pds;
976 IDirectSoundImpl_AddRef(pds);
977 *ppds = (LPDIRECTSOUND8)pdsds;
979 return DS_OK;
982 HRESULT DSOUND_Create(
983 REFIID riid,
984 LPDIRECTSOUND *ppDS)
986 LPDIRECTSOUND8 pDS;
987 HRESULT hr;
988 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
990 if (!IsEqualIID(riid, &IID_IUnknown) &&
991 !IsEqualIID(riid, &IID_IDirectSound)) {
992 *ppDS = 0;
993 return E_NOINTERFACE;
996 /* Get dsound configuration */
997 setup_dsound_options();
999 hr = IDirectSoundImpl_Create(&pDS);
1000 if (hr == DS_OK) {
1001 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1002 if (*ppDS)
1003 IDirectSound_IDirectSound_AddRef(*ppDS);
1004 else {
1005 WARN("IDirectSound_IDirectSound_Create failed\n");
1006 IDirectSound8_Release(pDS);
1008 } else {
1009 WARN("IDirectSoundImpl_Create failed\n");
1010 *ppDS = 0;
1013 return hr;
1016 /*******************************************************************************
1017 * DirectSoundCreate (DSOUND.1)
1019 * Creates and initializes a DirectSound interface.
1021 * PARAMS
1022 * lpcGUID [I] Address of the GUID that identifies the sound device.
1023 * ppDS [O] Address of a variable to receive the interface pointer.
1024 * pUnkOuter [I] Must be NULL.
1026 * RETURNS
1027 * Success: DS_OK
1028 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1029 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1031 HRESULT WINAPI DirectSoundCreate(
1032 LPCGUID lpcGUID,
1033 LPDIRECTSOUND *ppDS,
1034 IUnknown *pUnkOuter)
1036 HRESULT hr;
1037 LPDIRECTSOUND pDS;
1039 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1041 if (ppDS == NULL) {
1042 WARN("invalid parameter: ppDS == NULL\n");
1043 return DSERR_INVALIDPARAM;
1046 if (pUnkOuter != NULL) {
1047 WARN("invalid parameter: pUnkOuter != NULL\n");
1048 *ppDS = 0;
1049 return DSERR_INVALIDPARAM;
1052 hr = DSOUND_Create(&IID_IDirectSound, &pDS);
1053 if (hr == DS_OK) {
1054 hr = IDirectSound_Initialize(pDS, lpcGUID);
1055 if (hr != DS_OK) {
1056 if (hr != DSERR_ALREADYINITIALIZED) {
1057 IDirectSound_Release(pDS);
1058 pDS = 0;
1059 } else
1060 hr = DS_OK;
1064 *ppDS = pDS;
1066 return hr;
1069 HRESULT DSOUND_Create8(
1070 REFIID riid,
1071 LPDIRECTSOUND8 *ppDS)
1073 LPDIRECTSOUND8 pDS;
1074 HRESULT hr;
1075 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
1077 if (!IsEqualIID(riid, &IID_IUnknown) &&
1078 !IsEqualIID(riid, &IID_IDirectSound) &&
1079 !IsEqualIID(riid, &IID_IDirectSound8)) {
1080 *ppDS = 0;
1081 return E_NOINTERFACE;
1084 /* Get dsound configuration */
1085 setup_dsound_options();
1087 hr = IDirectSoundImpl_Create(&pDS);
1088 if (hr == DS_OK) {
1089 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1090 if (*ppDS)
1091 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1092 else {
1093 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1094 IDirectSound8_Release(pDS);
1096 } else {
1097 WARN("IDirectSoundImpl_Create failed\n");
1098 *ppDS = 0;
1101 return hr;
1104 /*******************************************************************************
1105 * DirectSoundCreate8 (DSOUND.11)
1107 * Creates and initializes a DirectSound8 interface.
1109 * PARAMS
1110 * lpcGUID [I] Address of the GUID that identifies the sound device.
1111 * ppDS [O] Address of a variable to receive the interface pointer.
1112 * pUnkOuter [I] Must be NULL.
1114 * RETURNS
1115 * Success: DS_OK
1116 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1117 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1119 HRESULT WINAPI DirectSoundCreate8(
1120 LPCGUID lpcGUID,
1121 LPDIRECTSOUND8 *ppDS,
1122 IUnknown *pUnkOuter)
1124 HRESULT hr;
1125 LPDIRECTSOUND8 pDS;
1127 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1129 if (ppDS == NULL) {
1130 WARN("invalid parameter: ppDS == NULL\n");
1131 return DSERR_INVALIDPARAM;
1134 if (pUnkOuter != NULL) {
1135 WARN("invalid parameter: pUnkOuter != NULL\n");
1136 *ppDS = 0;
1137 return DSERR_INVALIDPARAM;
1140 hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
1141 if (hr == DS_OK) {
1142 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1143 if (hr != DS_OK) {
1144 if (hr != DSERR_ALREADYINITIALIZED) {
1145 IDirectSound8_Release(pDS);
1146 pDS = 0;
1147 } else
1148 hr = DS_OK;
1152 *ppDS = pDS;
1154 return hr;
1157 /*******************************************************************************
1158 * DirectSoundDevice
1160 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
1162 DirectSoundDevice * device;
1163 TRACE("(%p)\n", ppDevice);
1165 /* Allocate memory */
1166 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
1167 if (device == NULL) {
1168 WARN("out of memory\n");
1169 return DSERR_OUTOFMEMORY;
1172 device->ref = 1;
1173 device->priolevel = DSSCL_NORMAL;
1174 device->state = STATE_STOPPED;
1175 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
1177 /* 3D listener initial parameters */
1178 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1179 device->ds3dl.vPosition.x = 0.0;
1180 device->ds3dl.vPosition.y = 0.0;
1181 device->ds3dl.vPosition.z = 0.0;
1182 device->ds3dl.vVelocity.x = 0.0;
1183 device->ds3dl.vVelocity.y = 0.0;
1184 device->ds3dl.vVelocity.z = 0.0;
1185 device->ds3dl.vOrientFront.x = 0.0;
1186 device->ds3dl.vOrientFront.y = 0.0;
1187 device->ds3dl.vOrientFront.z = 1.0;
1188 device->ds3dl.vOrientTop.x = 0.0;
1189 device->ds3dl.vOrientTop.y = 1.0;
1190 device->ds3dl.vOrientTop.z = 0.0;
1191 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1192 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1193 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1195 device->prebuf = ds_snd_queue_max;
1196 device->guid = GUID_NULL;
1198 /* Set default wave format (may need it for waveOutOpen) */
1199 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
1200 if (device->pwfx == NULL) {
1201 WARN("out of memory\n");
1202 HeapFree(GetProcessHeap(),0,device);
1203 return DSERR_OUTOFMEMORY;
1206 /* We rely on the sound driver to return the actual sound format of
1207 * the device if it does not support 22050x8x2 and is given the
1208 * WAVE_DIRECTSOUND flag.
1210 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1211 device->pwfx->nSamplesPerSec = ds_default_sample_rate;
1212 device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
1213 device->pwfx->nChannels = 2;
1214 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
1215 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
1216 device->pwfx->cbSize = 0;
1218 InitializeCriticalSection(&(device->mixlock));
1219 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
1221 RtlInitializeResource(&(device->buffer_list_lock));
1223 *ppDevice = device;
1225 return DS_OK;
1228 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
1230 ULONG ref = InterlockedIncrement(&(device->ref));
1231 TRACE("(%p) ref was %d\n", device, ref - 1);
1232 return ref;
1235 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
1237 HRESULT hr;
1238 ULONG ref = InterlockedDecrement(&(device->ref));
1239 TRACE("(%p) ref was %u\n", device, ref + 1);
1240 if (!ref) {
1241 int i;
1242 timeKillEvent(device->timerID);
1243 timeEndPeriod(DS_TIME_RES);
1245 /* The kill event should have allowed the timer process to expire
1246 * but try to grab the lock just in case. Can't hold lock because
1247 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1248 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1249 RtlReleaseResource(&(device->buffer_list_lock));
1251 /* It is allowed to release this object even when buffers are playing */
1252 if (device->buffers) {
1253 WARN("%d secondary buffers not released\n", device->nrofbuffers);
1254 for( i=0;i<device->nrofbuffers;i++)
1255 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
1258 if (device->primary) {
1259 WARN("primary buffer not released\n");
1260 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
1263 hr = DSOUND_PrimaryDestroy(device);
1264 if (hr != DS_OK)
1265 WARN("DSOUND_PrimaryDestroy failed\n");
1267 waveOutClose(device->hwo);
1269 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
1271 HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
1272 HeapFree(GetProcessHeap(), 0, device->mix_buffer);
1273 HeapFree(GetProcessHeap(), 0, device->buffer);
1274 RtlDeleteResource(&device->buffer_list_lock);
1275 device->mixlock.DebugInfo->Spare[0] = 0;
1276 DeleteCriticalSection(&device->mixlock);
1277 HeapFree(GetProcessHeap(),0,device);
1278 TRACE("(%p) released\n", device);
1280 return ref;
1283 HRESULT DirectSoundDevice_GetCaps(
1284 DirectSoundDevice * device,
1285 LPDSCAPS lpDSCaps)
1287 TRACE("(%p,%p)\n",device,lpDSCaps);
1289 if (device == NULL) {
1290 WARN("not initialized\n");
1291 return DSERR_UNINITIALIZED;
1294 if (lpDSCaps == NULL) {
1295 WARN("invalid parameter: lpDSCaps = NULL\n");
1296 return DSERR_INVALIDPARAM;
1299 /* check if there is enough room */
1300 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
1301 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
1302 return DSERR_INVALIDPARAM;
1305 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
1306 if (TRACE_ON(dsound)) {
1307 TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
1308 _dump_DSCAPS(lpDSCaps->dwFlags);
1309 TRACE(")\n");
1311 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
1312 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
1313 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
1314 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
1315 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
1316 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
1317 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
1318 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
1319 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
1320 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
1321 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
1322 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
1323 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
1324 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
1325 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
1326 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
1327 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
1328 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
1330 /* driver doesn't have these */
1331 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
1332 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
1334 return DS_OK;
1337 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
1339 HRESULT hr = DS_OK;
1340 unsigned wod, wodn;
1341 BOOLEAN found = FALSE;
1342 GUID devGUID;
1343 DirectSoundDevice * device = *ppDevice;
1344 WAVEOUTCAPSA woc;
1346 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
1348 if (*ppDevice != NULL) {
1349 WARN("already initialized\n");
1350 return DSERR_ALREADYINITIALIZED;
1353 /* Default device? */
1354 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1355 lpcGUID = &DSDEVID_DefaultPlayback;
1357 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1358 WARN("invalid parameter: lpcGUID\n");
1359 return DSERR_INVALIDPARAM;
1362 /* Enumerate WINMM audio devices and find the one we want */
1363 wodn = waveOutGetNumDevs();
1364 if (!wodn) {
1365 WARN("no driver\n");
1366 return DSERR_NODRIVER;
1369 for (wod=0; wod<wodn; wod++) {
1370 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
1371 found = TRUE;
1372 break;
1376 if (found == FALSE) {
1377 WARN("No device found matching given ID!\n");
1378 return DSERR_NODRIVER;
1381 if (DSOUND_renderer[wod]) {
1382 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
1383 device = DSOUND_renderer[wod];
1384 DirectSoundDevice_AddRef(device);
1385 *ppDevice = device;
1386 return DS_OK;
1387 } else {
1388 ERR("device GUID doesn't match\n");
1389 hr = DSERR_GENERIC;
1390 return hr;
1392 } else {
1393 hr = DirectSoundDevice_Create(&device);
1394 if (hr != DS_OK) {
1395 WARN("DirectSoundDevice_Create failed\n");
1396 return hr;
1400 *ppDevice = device;
1401 device->guid = devGUID;
1403 device->drvdesc.dnDevNode = wod;
1404 hr = DSOUND_ReopenDevice(device, FALSE);
1405 if (FAILED(hr))
1407 WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
1408 return hr;
1411 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
1412 if (hr != DS_OK) {
1413 WARN("waveOutGetDevCaps failed\n");
1414 return hr;
1416 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
1417 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
1418 (woc.dwFormats & WAVE_FORMAT_2M08) ||
1419 (woc.dwFormats & WAVE_FORMAT_4M08) ||
1420 (woc.dwFormats & WAVE_FORMAT_48M08) ||
1421 (woc.dwFormats & WAVE_FORMAT_96M08)) {
1422 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1423 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1425 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
1426 (woc.dwFormats & WAVE_FORMAT_2M16) ||
1427 (woc.dwFormats & WAVE_FORMAT_4M16) ||
1428 (woc.dwFormats & WAVE_FORMAT_48M16) ||
1429 (woc.dwFormats & WAVE_FORMAT_96M16)) {
1430 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1431 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1433 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
1434 (woc.dwFormats & WAVE_FORMAT_2S08) ||
1435 (woc.dwFormats & WAVE_FORMAT_4S08) ||
1436 (woc.dwFormats & WAVE_FORMAT_48S08) ||
1437 (woc.dwFormats & WAVE_FORMAT_96S08)) {
1438 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1439 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1441 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
1442 (woc.dwFormats & WAVE_FORMAT_2S16) ||
1443 (woc.dwFormats & WAVE_FORMAT_4S16) ||
1444 (woc.dwFormats & WAVE_FORMAT_48S16) ||
1445 (woc.dwFormats & WAVE_FORMAT_96S16)) {
1446 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1447 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1450 if(ds_emuldriver)
1451 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
1452 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
1453 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
1454 ZeroMemory(&device->volpan, sizeof(device->volpan));
1456 hr = DSOUND_PrimaryCreate(device);
1457 if (hr == DS_OK) {
1458 UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
1459 TIMECAPS time;
1461 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
1462 timeGetDevCaps(&time, sizeof(TIMECAPS));
1463 TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
1464 if (triggertime < time.wPeriodMin)
1465 triggertime = time.wPeriodMin;
1466 if (res < time.wPeriodMin)
1467 res = time.wPeriodMin;
1468 if (timeBeginPeriod(res) == TIMERR_NOCANDO)
1469 WARN("Could not set minimum resolution, don't expect sound\n");
1470 id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
1471 if (!id)
1473 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1474 id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC);
1475 if (!id) ERR("Could not create timer, sound playback will not occur\n");
1477 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id;
1478 } else {
1479 WARN("DSOUND_PrimaryCreate failed\n");
1482 return hr;
1485 HRESULT DirectSoundDevice_CreateSoundBuffer(
1486 DirectSoundDevice * device,
1487 LPCDSBUFFERDESC dsbd,
1488 LPLPDIRECTSOUNDBUFFER ppdsb,
1489 LPUNKNOWN lpunk,
1490 BOOL from8)
1492 HRESULT hres = DS_OK;
1493 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
1495 if (device == NULL) {
1496 WARN("not initialized\n");
1497 return DSERR_UNINITIALIZED;
1500 if (dsbd == NULL) {
1501 WARN("invalid parameter: dsbd == NULL\n");
1502 return DSERR_INVALIDPARAM;
1505 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
1506 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
1507 WARN("invalid parameter: dsbd\n");
1508 return DSERR_INVALIDPARAM;
1511 if (ppdsb == NULL) {
1512 WARN("invalid parameter: ppdsb == NULL\n");
1513 return DSERR_INVALIDPARAM;
1515 *ppdsb = NULL;
1517 if (TRACE_ON(dsound)) {
1518 TRACE("(structsize=%d)\n",dsbd->dwSize);
1519 TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
1520 _dump_DSBCAPS(dsbd->dwFlags);
1521 TRACE(")\n");
1522 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
1523 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
1526 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
1527 if (dsbd->lpwfxFormat != NULL) {
1528 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1529 "primary buffer\n");
1530 return DSERR_INVALIDPARAM;
1533 if (device->primary) {
1534 WARN("Primary Buffer already created\n");
1535 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1536 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1537 } else {
1538 hres = primarybuffer_create(device, &device->primary, dsbd);
1539 if (device->primary) {
1540 *ppdsb = (IDirectSoundBuffer*)&device->primary->IDirectSoundBuffer8_iface;
1541 device->primary->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
1542 device->primary->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
1543 } else
1544 WARN("primarybuffer_create() failed\n");
1546 } else {
1547 IDirectSoundBufferImpl * dsb;
1548 WAVEFORMATEXTENSIBLE *pwfxe;
1550 if (dsbd->lpwfxFormat == NULL) {
1551 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1552 "secondary buffer\n");
1553 return DSERR_INVALIDPARAM;
1555 pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
1557 if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
1559 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
1560 return DSERR_CONTROLUNAVAIL;
1562 if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
1564 /* check if cbSize is at least 22 bytes */
1565 if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
1567 WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize);
1568 return DSERR_INVALIDPARAM;
1571 /* cbSize should be 22 bytes, with one possible exception */
1572 if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) &&
1573 !((IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) &&
1574 pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
1576 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
1577 return DSERR_CONTROLUNAVAIL;
1580 if ((!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) && (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
1582 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
1583 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
1584 return DSERR_INVALIDPARAM;
1586 if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample)
1588 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample);
1589 return DSERR_INVALIDPARAM;
1591 if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample)
1593 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample);
1594 return DSERR_CONTROLUNAVAIL;
1598 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1599 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1600 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
1601 dsbd->lpwfxFormat->nSamplesPerSec,
1602 dsbd->lpwfxFormat->nAvgBytesPerSec,
1603 dsbd->lpwfxFormat->nBlockAlign,
1604 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
1606 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
1607 WARN("invalid parameter: 3D buffer format must be mono\n");
1608 return DSERR_INVALIDPARAM;
1611 hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd);
1612 if (dsb)
1613 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
1614 else
1615 WARN("IDirectSoundBufferImpl_Create failed\n");
1618 return hres;
1621 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
1622 DirectSoundDevice * device,
1623 LPDIRECTSOUNDBUFFER psb,
1624 LPLPDIRECTSOUNDBUFFER ppdsb)
1626 HRESULT hres = DS_OK;
1627 IDirectSoundBufferImpl* dsb;
1628 TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
1630 if (device == NULL) {
1631 WARN("not initialized\n");
1632 return DSERR_UNINITIALIZED;
1635 if (psb == NULL) {
1636 WARN("invalid parameter: psb == NULL\n");
1637 return DSERR_INVALIDPARAM;
1640 if (ppdsb == NULL) {
1641 WARN("invalid parameter: ppdsb == NULL\n");
1642 return DSERR_INVALIDPARAM;
1645 /* make sure we have a secondary buffer */
1646 if (psb == (IDirectSoundBuffer *)&device->primary->IDirectSoundBuffer8_iface) {
1647 WARN("trying to duplicate primary buffer\n");
1648 *ppdsb = NULL;
1649 return DSERR_INVALIDCALL;
1652 /* duplicate the actual buffer implementation */
1653 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb, (IDirectSoundBufferImpl*)psb);
1654 if (hres == DS_OK)
1655 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
1656 else
1657 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1659 return hres;
1662 HRESULT DirectSoundDevice_SetCooperativeLevel(
1663 DirectSoundDevice * device,
1664 HWND hwnd,
1665 DWORD level)
1667 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
1669 if (device == NULL) {
1670 WARN("not initialized\n");
1671 return DSERR_UNINITIALIZED;
1674 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
1675 WARN("level=%s not fully supported\n",
1676 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1679 device->priolevel = level;
1680 return DS_OK;
1683 HRESULT DirectSoundDevice_Compact(
1684 DirectSoundDevice * device)
1686 TRACE("(%p)\n", device);
1688 if (device == NULL) {
1689 WARN("not initialized\n");
1690 return DSERR_UNINITIALIZED;
1693 if (device->priolevel < DSSCL_PRIORITY) {
1694 WARN("incorrect priority level\n");
1695 return DSERR_PRIOLEVELNEEDED;
1698 return DS_OK;
1701 HRESULT DirectSoundDevice_GetSpeakerConfig(
1702 DirectSoundDevice * device,
1703 LPDWORD lpdwSpeakerConfig)
1705 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
1707 if (device == NULL) {
1708 WARN("not initialized\n");
1709 return DSERR_UNINITIALIZED;
1712 if (lpdwSpeakerConfig == NULL) {
1713 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1714 return DSERR_INVALIDPARAM;
1717 WARN("not fully functional\n");
1718 *lpdwSpeakerConfig = device->speaker_config;
1719 return DS_OK;
1722 HRESULT DirectSoundDevice_SetSpeakerConfig(
1723 DirectSoundDevice * device,
1724 DWORD config)
1726 TRACE("(%p,0x%08x)\n",device,config);
1728 if (device == NULL) {
1729 WARN("not initialized\n");
1730 return DSERR_UNINITIALIZED;
1733 device->speaker_config = config;
1734 WARN("not fully functional\n");
1735 return DS_OK;
1738 HRESULT DirectSoundDevice_VerifyCertification(
1739 DirectSoundDevice * device,
1740 LPDWORD pdwCertified)
1742 TRACE("(%p, %p)\n",device,pdwCertified);
1744 if (device == NULL) {
1745 WARN("not initialized\n");
1746 return DSERR_UNINITIALIZED;
1749 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
1750 *pdwCertified = DS_CERTIFIED;
1751 else
1752 *pdwCertified = DS_UNCERTIFIED;
1754 return DS_OK;
1758 * Add secondary buffer to buffer list.
1759 * Gets exclusive access to buffer for writing.
1761 HRESULT DirectSoundDevice_AddBuffer(
1762 DirectSoundDevice * device,
1763 IDirectSoundBufferImpl * pDSB)
1765 IDirectSoundBufferImpl **newbuffers;
1766 HRESULT hr = DS_OK;
1768 TRACE("(%p, %p)\n", device, pDSB);
1770 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1772 if (device->buffers)
1773 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1774 else
1775 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1777 if (newbuffers) {
1778 device->buffers = newbuffers;
1779 device->buffers[device->nrofbuffers] = pDSB;
1780 device->nrofbuffers++;
1781 TRACE("buffer count is now %d\n", device->nrofbuffers);
1782 } else {
1783 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
1784 hr = DSERR_OUTOFMEMORY;
1787 RtlReleaseResource(&(device->buffer_list_lock));
1789 return hr;
1793 * Remove secondary buffer from buffer list.
1794 * Gets exclusive access to buffer for writing.
1796 HRESULT DirectSoundDevice_RemoveBuffer(
1797 DirectSoundDevice * device,
1798 IDirectSoundBufferImpl * pDSB)
1800 int i;
1801 HRESULT hr = DS_OK;
1803 TRACE("(%p, %p)\n", device, pDSB);
1805 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1807 for (i = 0; i < device->nrofbuffers; i++)
1808 if (device->buffers[i] == pDSB)
1809 break;
1811 if (i < device->nrofbuffers) {
1812 /* Put the last buffer of the list in the (now empty) position */
1813 device->buffers[i] = device->buffers[device->nrofbuffers - 1];
1814 device->nrofbuffers--;
1815 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
1816 TRACE("buffer count is now %d\n", device->nrofbuffers);
1819 if (device->nrofbuffers == 0) {
1820 HeapFree(GetProcessHeap(),0,device->buffers);
1821 device->buffers = NULL;
1824 RtlReleaseResource(&(device->buffer_list_lock));
1826 return hr;