shell32: DragQueryFile doesn't count the null terminator.
[wine/multimedia.git] / dlls / dsound / dsound.c
blob96809307849da9474a31df1fa338bdfadac905a0
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 "wine/debug.h"
35 #include "dsound.h"
36 #include "dsdriver.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
41 /*****************************************************************************
42 * IDirectSound COM components
44 struct IDirectSound_IUnknown {
45 const IUnknownVtbl *lpVtbl;
46 LONG ref;
47 LPDIRECTSOUND8 pds;
50 static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
52 struct IDirectSound_IDirectSound {
53 const IDirectSoundVtbl *lpVtbl;
54 LONG ref;
55 LPDIRECTSOUND8 pds;
58 static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
60 /*****************************************************************************
61 * IDirectSound8 COM components
63 struct IDirectSound8_IUnknown {
64 const IUnknownVtbl *lpVtbl;
65 LONG ref;
66 LPDIRECTSOUND8 pds;
69 static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk);
70 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
72 struct IDirectSound8_IDirectSound {
73 const IDirectSoundVtbl *lpVtbl;
74 LONG ref;
75 LPDIRECTSOUND8 pds;
78 static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds);
79 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
81 struct IDirectSound8_IDirectSound8 {
82 const IDirectSound8Vtbl *lpVtbl;
83 LONG ref;
84 LPDIRECTSOUND8 pds;
87 static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds);
88 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
90 /*****************************************************************************
91 * IDirectSound implementation structure
93 struct IDirectSoundImpl
95 LONG ref;
97 DirectSoundDevice *device;
98 LPUNKNOWN pUnknown;
99 LPDIRECTSOUND pDS;
100 LPDIRECTSOUND8 pDS8;
103 static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds);
105 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
106 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
108 static HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device, LPDWORD pdwCertified);
110 const char * dumpCooperativeLevel(DWORD level)
112 static char unknown[32];
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 sprintf(unknown, "Unknown(%08x)", level);
122 return unknown;
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_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_Release(This->pds);
437 HeapFree(GetProcessHeap(), 0, This);
438 TRACE("(%p) released\n", This);
440 return ref;
443 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
444 LPDIRECTSOUND iface,
445 LPCDSBUFFERDESC dsbd,
446 LPLPDIRECTSOUNDBUFFER ppdsb,
447 LPUNKNOWN lpunk)
449 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
450 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
451 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
454 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
455 LPDIRECTSOUND iface,
456 LPDSCAPS lpDSCaps)
458 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
459 TRACE("(%p,%p)\n",This,lpDSCaps);
460 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
463 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
464 LPDIRECTSOUND iface,
465 LPDIRECTSOUNDBUFFER psb,
466 LPLPDIRECTSOUNDBUFFER ppdsb)
468 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
469 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
470 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
473 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
474 LPDIRECTSOUND iface,
475 HWND hwnd,
476 DWORD level)
478 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
479 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
480 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
483 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
484 LPDIRECTSOUND iface)
486 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
487 TRACE("(%p)\n", This);
488 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
491 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
492 LPDIRECTSOUND iface,
493 LPDWORD lpdwSpeakerConfig)
495 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
496 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
497 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
500 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
501 LPDIRECTSOUND iface,
502 DWORD config)
504 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
505 TRACE("(%p,0x%08x)\n",This,config);
506 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
509 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
510 LPDIRECTSOUND iface,
511 LPCGUID lpcGuid)
513 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
514 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
515 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
518 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
520 IDirectSound_IDirectSound_QueryInterface,
521 IDirectSound_IDirectSound_AddRef,
522 IDirectSound_IDirectSound_Release,
523 IDirectSound_IDirectSound_CreateSoundBuffer,
524 IDirectSound_IDirectSound_GetCaps,
525 IDirectSound_IDirectSound_DuplicateSoundBuffer,
526 IDirectSound_IDirectSound_SetCooperativeLevel,
527 IDirectSound_IDirectSound_Compact,
528 IDirectSound_IDirectSound_GetSpeakerConfig,
529 IDirectSound_IDirectSound_SetSpeakerConfig,
530 IDirectSound_IDirectSound_Initialize
533 static HRESULT IDirectSound_IDirectSound_Create(
534 LPDIRECTSOUND8 pds,
535 LPDIRECTSOUND * ppds)
537 IDirectSound_IDirectSound * pdsds;
538 TRACE("(%p,%p)\n",pds,ppds);
540 if (ppds == NULL) {
541 ERR("invalid parameter: ppds == NULL\n");
542 return DSERR_INVALIDPARAM;
545 if (pds == NULL) {
546 ERR("invalid parameter: pds == NULL\n");
547 *ppds = NULL;
548 return DSERR_INVALIDPARAM;
551 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
552 if (pdsds == NULL) {
553 WARN("out of memory\n");
554 *ppds = NULL;
555 return DSERR_OUTOFMEMORY;
558 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
559 pdsds->ref = 0;
560 pdsds->pds = pds;
562 IDirectSoundImpl_AddRef(pds);
563 *ppds = (LPDIRECTSOUND)pdsds;
565 return DS_OK;
568 /*******************************************************************************
569 * IDirectSound8_IUnknown
571 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
572 LPUNKNOWN iface,
573 REFIID riid,
574 LPVOID * ppobj)
576 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
577 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
578 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
581 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
582 LPUNKNOWN iface)
584 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
585 ULONG ref = InterlockedIncrement(&(This->ref));
586 TRACE("(%p) ref was %d\n", This, ref - 1);
587 return ref;
590 static ULONG WINAPI IDirectSound8_IUnknown_Release(
591 LPUNKNOWN iface)
593 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
594 ULONG ref = InterlockedDecrement(&(This->ref));
595 TRACE("(%p) ref was %d\n", This, ref + 1);
596 if (!ref) {
597 IDirectSoundImpl_Release(This->pds);
598 HeapFree(GetProcessHeap(), 0, This);
599 TRACE("(%p) released\n", This);
601 return ref;
604 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
606 IDirectSound8_IUnknown_QueryInterface,
607 IDirectSound8_IUnknown_AddRef,
608 IDirectSound8_IUnknown_Release
611 static HRESULT IDirectSound8_IUnknown_Create(
612 LPDIRECTSOUND8 pds,
613 LPUNKNOWN * ppunk)
615 IDirectSound8_IUnknown * pdsunk;
616 TRACE("(%p,%p)\n",pds,ppunk);
618 if (ppunk == NULL) {
619 ERR("invalid parameter: ppunk == NULL\n");
620 return DSERR_INVALIDPARAM;
623 if (pds == NULL) {
624 ERR("invalid parameter: pds == NULL\n");
625 *ppunk = NULL;
626 return DSERR_INVALIDPARAM;
629 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
630 if (pdsunk == NULL) {
631 WARN("out of memory\n");
632 *ppunk = NULL;
633 return DSERR_OUTOFMEMORY;
636 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
637 pdsunk->ref = 0;
638 pdsunk->pds = pds;
640 IDirectSoundImpl_AddRef(pds);
641 *ppunk = (LPUNKNOWN)pdsunk;
643 return DS_OK;
646 /*******************************************************************************
647 * IDirectSound8_IDirectSound
649 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
650 LPDIRECTSOUND iface,
651 REFIID riid,
652 LPVOID * ppobj)
654 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
655 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
656 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
659 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
660 LPDIRECTSOUND iface)
662 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
663 ULONG ref = InterlockedIncrement(&(This->ref));
664 TRACE("(%p) ref was %d\n", This, ref - 1);
665 return ref;
668 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
669 LPDIRECTSOUND iface)
671 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
672 ULONG ref = InterlockedDecrement(&(This->ref));
673 TRACE("(%p) ref was %d\n", This, ref + 1);
674 if (!ref) {
675 IDirectSoundImpl_Release(This->pds);
676 HeapFree(GetProcessHeap(), 0, This);
677 TRACE("(%p) released\n", This);
679 return ref;
682 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
683 LPDIRECTSOUND iface,
684 LPCDSBUFFERDESC dsbd,
685 LPLPDIRECTSOUNDBUFFER ppdsb,
686 LPUNKNOWN lpunk)
688 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
689 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
690 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
693 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
694 LPDIRECTSOUND iface,
695 LPDSCAPS lpDSCaps)
697 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
698 TRACE("(%p,%p)\n",This,lpDSCaps);
699 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
702 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
703 LPDIRECTSOUND iface,
704 LPDIRECTSOUNDBUFFER psb,
705 LPLPDIRECTSOUNDBUFFER ppdsb)
707 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
708 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
709 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
712 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
713 LPDIRECTSOUND iface,
714 HWND hwnd,
715 DWORD level)
717 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
718 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
719 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
722 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
723 LPDIRECTSOUND iface)
725 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
726 TRACE("(%p)\n", This);
727 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
730 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
731 LPDIRECTSOUND iface,
732 LPDWORD lpdwSpeakerConfig)
734 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
735 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
736 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
739 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
740 LPDIRECTSOUND iface,
741 DWORD config)
743 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
744 TRACE("(%p,0x%08x)\n",This,config);
745 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
748 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
749 LPDIRECTSOUND iface,
750 LPCGUID lpcGuid)
752 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
753 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
754 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
757 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
759 IDirectSound8_IDirectSound_QueryInterface,
760 IDirectSound8_IDirectSound_AddRef,
761 IDirectSound8_IDirectSound_Release,
762 IDirectSound8_IDirectSound_CreateSoundBuffer,
763 IDirectSound8_IDirectSound_GetCaps,
764 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
765 IDirectSound8_IDirectSound_SetCooperativeLevel,
766 IDirectSound8_IDirectSound_Compact,
767 IDirectSound8_IDirectSound_GetSpeakerConfig,
768 IDirectSound8_IDirectSound_SetSpeakerConfig,
769 IDirectSound8_IDirectSound_Initialize
772 static HRESULT IDirectSound8_IDirectSound_Create(
773 LPDIRECTSOUND8 pds,
774 LPDIRECTSOUND * ppds)
776 IDirectSound8_IDirectSound * pdsds;
777 TRACE("(%p,%p)\n",pds,ppds);
779 if (ppds == NULL) {
780 ERR("invalid parameter: ppds == NULL\n");
781 return DSERR_INVALIDPARAM;
784 if (pds == NULL) {
785 ERR("invalid parameter: pds == NULL\n");
786 *ppds = NULL;
787 return DSERR_INVALIDPARAM;
790 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
791 if (pdsds == NULL) {
792 WARN("out of memory\n");
793 *ppds = NULL;
794 return DSERR_OUTOFMEMORY;
797 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
798 pdsds->ref = 0;
799 pdsds->pds = pds;
801 IDirectSoundImpl_AddRef(pds);
802 *ppds = (LPDIRECTSOUND)pdsds;
804 return DS_OK;
807 /*******************************************************************************
808 * IDirectSound8_IDirectSound8
810 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
811 LPDIRECTSOUND8 iface,
812 REFIID riid,
813 LPVOID * ppobj)
815 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
816 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
817 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
820 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
821 LPDIRECTSOUND8 iface)
823 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
824 ULONG ref = InterlockedIncrement(&(This->ref));
825 TRACE("(%p) ref was %d\n", This, ref - 1);
826 return ref;
829 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
830 LPDIRECTSOUND8 iface)
832 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
833 ULONG ref = InterlockedDecrement(&(This->ref));
834 TRACE("(%p) ref was %d\n", This, ref + 1);
835 if (!ref) {
836 IDirectSoundImpl_Release(This->pds);
837 HeapFree(GetProcessHeap(), 0, This);
838 TRACE("(%p) released\n", This);
840 return ref;
843 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
844 LPDIRECTSOUND8 iface,
845 LPCDSBUFFERDESC dsbd,
846 LPLPDIRECTSOUNDBUFFER ppdsb,
847 LPUNKNOWN lpunk)
849 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
850 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
851 return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
854 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
855 LPDIRECTSOUND8 iface,
856 LPDSCAPS lpDSCaps)
858 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
859 TRACE("(%p,%p)\n",This,lpDSCaps);
860 return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
863 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
864 LPDIRECTSOUND8 iface,
865 LPDIRECTSOUNDBUFFER psb,
866 LPLPDIRECTSOUNDBUFFER ppdsb)
868 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
869 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
870 return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
873 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
874 LPDIRECTSOUND8 iface,
875 HWND hwnd,
876 DWORD level)
878 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
879 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
880 return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
883 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
884 LPDIRECTSOUND8 iface)
886 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
887 TRACE("(%p)\n", This);
888 return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
891 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
892 LPDIRECTSOUND8 iface,
893 LPDWORD lpdwSpeakerConfig)
895 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
896 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
897 return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
900 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
901 LPDIRECTSOUND8 iface,
902 DWORD config)
904 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
905 TRACE("(%p,0x%08x)\n",This,config);
906 return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
909 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
910 LPDIRECTSOUND8 iface,
911 LPCGUID lpcGuid)
913 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
914 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
915 return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
918 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
919 LPDIRECTSOUND8 iface,
920 LPDWORD pdwCertified)
922 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
923 TRACE("(%p, %p)\n", This, pdwCertified);
924 return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
927 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
929 IDirectSound8_IDirectSound8_QueryInterface,
930 IDirectSound8_IDirectSound8_AddRef,
931 IDirectSound8_IDirectSound8_Release,
932 IDirectSound8_IDirectSound8_CreateSoundBuffer,
933 IDirectSound8_IDirectSound8_GetCaps,
934 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
935 IDirectSound8_IDirectSound8_SetCooperativeLevel,
936 IDirectSound8_IDirectSound8_Compact,
937 IDirectSound8_IDirectSound8_GetSpeakerConfig,
938 IDirectSound8_IDirectSound8_SetSpeakerConfig,
939 IDirectSound8_IDirectSound8_Initialize,
940 IDirectSound8_IDirectSound8_VerifyCertification
943 static HRESULT IDirectSound8_IDirectSound8_Create(
944 LPDIRECTSOUND8 pds,
945 LPDIRECTSOUND8 * ppds)
947 IDirectSound8_IDirectSound8 * pdsds;
948 TRACE("(%p,%p)\n",pds,ppds);
950 if (ppds == NULL) {
951 ERR("invalid parameter: ppds == NULL\n");
952 return DSERR_INVALIDPARAM;
955 if (pds == NULL) {
956 ERR("invalid parameter: pds == NULL\n");
957 *ppds = NULL;
958 return DSERR_INVALIDPARAM;
961 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
962 if (pdsds == NULL) {
963 WARN("out of memory\n");
964 *ppds = NULL;
965 return DSERR_OUTOFMEMORY;
968 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
969 pdsds->ref = 0;
970 pdsds->pds = pds;
972 IDirectSoundImpl_AddRef(pds);
973 *ppds = (LPDIRECTSOUND8)pdsds;
975 return DS_OK;
978 HRESULT DSOUND_Create(
979 REFIID riid,
980 LPDIRECTSOUND *ppDS)
982 LPDIRECTSOUND8 pDS;
983 HRESULT hr;
984 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
986 if (!IsEqualIID(riid, &IID_IUnknown) &&
987 !IsEqualIID(riid, &IID_IDirectSound)) {
988 *ppDS = 0;
989 return E_NOINTERFACE;
992 /* Get dsound configuration */
993 setup_dsound_options();
995 hr = IDirectSoundImpl_Create(&pDS);
996 if (hr == DS_OK) {
997 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
998 if (*ppDS)
999 IDirectSound_IDirectSound_AddRef(*ppDS);
1000 else {
1001 WARN("IDirectSound_IDirectSound_Create failed\n");
1002 IDirectSound8_Release(pDS);
1004 } else {
1005 WARN("IDirectSoundImpl_Create failed\n");
1006 *ppDS = 0;
1009 return hr;
1012 /*******************************************************************************
1013 * DirectSoundCreate (DSOUND.1)
1015 * Creates and initializes a DirectSound interface.
1017 * PARAMS
1018 * lpcGUID [I] Address of the GUID that identifies the sound device.
1019 * ppDS [O] Address of a variable to receive the interface pointer.
1020 * pUnkOuter [I] Must be NULL.
1022 * RETURNS
1023 * Success: DS_OK
1024 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1025 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1027 HRESULT WINAPI DirectSoundCreate(
1028 LPCGUID lpcGUID,
1029 LPDIRECTSOUND *ppDS,
1030 IUnknown *pUnkOuter)
1032 HRESULT hr;
1033 LPDIRECTSOUND pDS;
1035 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1037 if (ppDS == NULL) {
1038 WARN("invalid parameter: ppDS == NULL\n");
1039 return DSERR_INVALIDPARAM;
1042 if (pUnkOuter != NULL) {
1043 WARN("invalid parameter: pUnkOuter != NULL\n");
1044 *ppDS = 0;
1045 return DSERR_INVALIDPARAM;
1048 hr = DSOUND_Create(&IID_IDirectSound, &pDS);
1049 if (hr == DS_OK) {
1050 hr = IDirectSound_Initialize(pDS, lpcGUID);
1051 if (hr != DS_OK) {
1052 if (hr != DSERR_ALREADYINITIALIZED) {
1053 IDirectSound_Release(pDS);
1054 pDS = 0;
1055 } else
1056 hr = DS_OK;
1060 *ppDS = pDS;
1062 return hr;
1065 HRESULT DSOUND_Create8(
1066 REFIID riid,
1067 LPDIRECTSOUND8 *ppDS)
1069 LPDIRECTSOUND8 pDS;
1070 HRESULT hr;
1071 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS);
1073 if (!IsEqualIID(riid, &IID_IUnknown) &&
1074 !IsEqualIID(riid, &IID_IDirectSound) &&
1075 !IsEqualIID(riid, &IID_IDirectSound8)) {
1076 *ppDS = 0;
1077 return E_NOINTERFACE;
1080 /* Get dsound configuration */
1081 setup_dsound_options();
1083 hr = IDirectSoundImpl_Create(&pDS);
1084 if (hr == DS_OK) {
1085 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1086 if (*ppDS)
1087 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1088 else {
1089 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1090 IDirectSound8_Release(pDS);
1092 } else {
1093 WARN("IDirectSoundImpl_Create failed\n");
1094 *ppDS = 0;
1097 return hr;
1100 /*******************************************************************************
1101 * DirectSoundCreate8 (DSOUND.11)
1103 * Creates and initializes a DirectSound8 interface.
1105 * PARAMS
1106 * lpcGUID [I] Address of the GUID that identifies the sound device.
1107 * ppDS [O] Address of a variable to receive the interface pointer.
1108 * pUnkOuter [I] Must be NULL.
1110 * RETURNS
1111 * Success: DS_OK
1112 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1113 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1115 HRESULT WINAPI DirectSoundCreate8(
1116 LPCGUID lpcGUID,
1117 LPDIRECTSOUND8 *ppDS,
1118 IUnknown *pUnkOuter)
1120 HRESULT hr;
1121 LPDIRECTSOUND8 pDS;
1123 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1125 if (ppDS == NULL) {
1126 WARN("invalid parameter: ppDS == NULL\n");
1127 return DSERR_INVALIDPARAM;
1130 if (pUnkOuter != NULL) {
1131 WARN("invalid parameter: pUnkOuter != NULL\n");
1132 *ppDS = 0;
1133 return DSERR_INVALIDPARAM;
1136 hr = DSOUND_Create8(&IID_IDirectSound8, &pDS);
1137 if (hr == DS_OK) {
1138 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1139 if (hr != DS_OK) {
1140 if (hr != DSERR_ALREADYINITIALIZED) {
1141 IDirectSound8_Release(pDS);
1142 pDS = 0;
1143 } else
1144 hr = DS_OK;
1148 *ppDS = pDS;
1150 return hr;
1153 /*******************************************************************************
1154 * DirectSoundDevice
1156 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
1158 DirectSoundDevice * device;
1159 TRACE("(%p)\n", ppDevice);
1161 /* Allocate memory */
1162 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
1163 if (device == NULL) {
1164 WARN("out of memory\n");
1165 return DSERR_OUTOFMEMORY;
1168 device->ref = 1;
1169 device->driver = NULL;
1170 device->priolevel = DSSCL_NORMAL;
1171 device->fraglen = 0;
1172 device->hwbuf = NULL;
1173 device->buffer = NULL;
1174 device->buflen = 0;
1175 device->writelead = 0;
1176 device->state = STATE_STOPPED;
1177 device->nrofbuffers = 0;
1178 device->buffers = NULL;
1179 device->primary = NULL;
1180 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
1181 device->tmp_buffer = NULL;
1182 device->tmp_buffer_len = 0;
1184 /* 3D listener initial parameters */
1185 device->listener = NULL;
1186 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1187 device->ds3dl.vPosition.x = 0.0;
1188 device->ds3dl.vPosition.y = 0.0;
1189 device->ds3dl.vPosition.z = 0.0;
1190 device->ds3dl.vVelocity.x = 0.0;
1191 device->ds3dl.vVelocity.y = 0.0;
1192 device->ds3dl.vVelocity.z = 0.0;
1193 device->ds3dl.vOrientFront.x = 0.0;
1194 device->ds3dl.vOrientFront.y = 0.0;
1195 device->ds3dl.vOrientFront.z = 1.0;
1196 device->ds3dl.vOrientTop.x = 0.0;
1197 device->ds3dl.vOrientTop.y = 1.0;
1198 device->ds3dl.vOrientTop.z = 0.0;
1199 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1200 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1201 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1203 device->prebuf = ds_snd_queue_max;
1204 device->guid = GUID_NULL;
1206 /* Set default wave format (may need it for waveOutOpen) */
1207 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
1208 if (device->pwfx == NULL) {
1209 WARN("out of memory\n");
1210 HeapFree(GetProcessHeap(),0,device);
1211 return DSERR_OUTOFMEMORY;
1214 /* We rely on the sound driver to return the actual sound format of
1215 * the device if it does not support 22050x8x2 and is given the
1216 * WAVE_DIRECTSOUND flag.
1218 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1219 device->pwfx->nSamplesPerSec = ds_default_sample_rate;
1220 device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
1221 device->pwfx->nChannels = 2;
1222 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
1223 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
1224 device->pwfx->cbSize = 0;
1226 InitializeCriticalSection(&(device->mixlock));
1227 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
1229 RtlInitializeResource(&(device->buffer_list_lock));
1231 *ppDevice = device;
1233 return DS_OK;
1236 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
1238 ULONG ref = InterlockedIncrement(&(device->ref));
1239 TRACE("(%p) ref was %d\n", device, ref - 1);
1240 return ref;
1243 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
1245 HRESULT hr;
1246 ULONG ref = InterlockedDecrement(&(device->ref));
1247 TRACE("(%p) ref was %u\n", device, ref + 1);
1248 if (!ref) {
1249 int i;
1250 timeKillEvent(device->timerID);
1251 timeEndPeriod(DS_TIME_RES);
1253 /* The kill event should have allowed the timer process to expire
1254 * but try to grab the lock just in case. Can't hold lock because
1255 * IDirectSoundBufferImpl_Destroy also grabs the lock */
1256 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1257 RtlReleaseResource(&(device->buffer_list_lock));
1259 /* It is allowed to release this object even when buffers are playing */
1260 if (device->buffers) {
1261 WARN("%d secondary buffers not released\n", device->nrofbuffers);
1262 for( i=0;i<device->nrofbuffers;i++)
1263 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
1266 if (device->primary) {
1267 WARN("primary buffer not released\n");
1268 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
1271 hr = DSOUND_PrimaryDestroy(device);
1272 if (hr != DS_OK)
1273 WARN("DSOUND_PrimaryDestroy failed\n");
1275 if (device->driver)
1276 IDsDriver_Close(device->driver);
1278 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
1279 waveOutClose(device->hwo);
1281 if (device->driver)
1282 IDsDriver_Release(device->driver);
1284 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
1286 HeapFree(GetProcessHeap(),0,device->tmp_buffer);
1287 HeapFree(GetProcessHeap(),0,device->buffer);
1288 RtlDeleteResource(&device->buffer_list_lock);
1289 device->mixlock.DebugInfo->Spare[0] = 0;
1290 DeleteCriticalSection(&device->mixlock);
1291 HeapFree(GetProcessHeap(),0,device);
1292 TRACE("(%p) released\n", device);
1294 return ref;
1297 HRESULT DirectSoundDevice_GetCaps(
1298 DirectSoundDevice * device,
1299 LPDSCAPS lpDSCaps)
1301 TRACE("(%p,%p)\n",device,lpDSCaps);
1303 if (device == NULL) {
1304 WARN("not initialized\n");
1305 return DSERR_UNINITIALIZED;
1308 if (lpDSCaps == NULL) {
1309 WARN("invalid parameter: lpDSCaps = NULL\n");
1310 return DSERR_INVALIDPARAM;
1313 /* check if there is enough room */
1314 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
1315 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
1316 return DSERR_INVALIDPARAM;
1319 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
1320 if (TRACE_ON(dsound)) {
1321 TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
1322 _dump_DSCAPS(lpDSCaps->dwFlags);
1323 DPRINTF(")\n");
1325 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
1326 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
1327 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
1328 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
1329 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
1330 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
1331 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
1332 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
1333 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
1334 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
1335 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
1336 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
1337 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
1338 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
1339 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
1340 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
1341 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
1342 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
1344 /* driver doesn't have these */
1345 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
1346 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
1348 return DS_OK;
1351 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
1353 HRESULT hr = DS_OK;
1354 unsigned wod, wodn;
1355 BOOLEAN found = FALSE;
1356 GUID devGUID;
1357 DirectSoundDevice * device = *ppDevice;
1358 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
1360 if (*ppDevice != NULL) {
1361 WARN("already initialized\n");
1362 return DSERR_ALREADYINITIALIZED;
1365 /* Default device? */
1366 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1367 lpcGUID = &DSDEVID_DefaultPlayback;
1369 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1370 WARN("invalid parameter: lpcGUID\n");
1371 return DSERR_INVALIDPARAM;
1374 /* Enumerate WINMM audio devices and find the one we want */
1375 wodn = waveOutGetNumDevs();
1376 if (!wodn) {
1377 WARN("no driver\n");
1378 return DSERR_NODRIVER;
1381 for (wod=0; wod<wodn; wod++) {
1382 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
1383 found = TRUE;
1384 break;
1388 if (found == FALSE) {
1389 WARN("No device found matching given ID!\n");
1390 return DSERR_NODRIVER;
1393 if (DSOUND_renderer[wod]) {
1394 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
1395 device = DSOUND_renderer[wod];
1396 DirectSoundDevice_AddRef(device);
1397 *ppDevice = device;
1398 return DS_OK;
1399 } else {
1400 ERR("device GUID doesn't match\n");
1401 hr = DSERR_GENERIC;
1402 return hr;
1404 } else {
1405 hr = DirectSoundDevice_Create(&device);
1406 if (hr != DS_OK) {
1407 WARN("DirectSoundDevice_Create failed\n");
1408 return hr;
1412 *ppDevice = device;
1413 device->guid = devGUID;
1415 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
1416 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
1418 /* Disable the direct sound driver to force emulation if requested. */
1419 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
1420 device->driver = NULL;
1422 /* Get driver description */
1423 if (device->driver) {
1424 hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
1425 if (hr != DS_OK) {
1426 WARN("IDsDriver_GetDriverDesc failed\n");
1427 return hr;
1429 } else {
1430 /* if no DirectSound interface available, use WINMM API instead */
1431 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
1434 device->drvdesc.dnDevNode = wod;
1436 /* If the driver requests being opened through MMSYSTEM
1437 * (which is recommended by the DDK), it is supposed to happen
1438 * before the DirectSound interface is opened */
1439 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
1441 DWORD flags = CALLBACK_FUNCTION;
1443 /* disable direct sound if requested */
1444 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
1445 flags |= WAVE_DIRECTSOUND;
1447 hr = mmErr(waveOutOpen(&(device->hwo),
1448 device->drvdesc.dnDevNode, device->pwfx,
1449 (DWORD_PTR)DSOUND_callback, (DWORD)device,
1450 flags));
1451 if (hr != DS_OK) {
1452 WARN("waveOutOpen failed\n");
1453 return hr;
1457 if (device->driver) {
1458 hr = IDsDriver_Open(device->driver);
1459 if (hr != DS_OK) {
1460 WARN("IDsDriver_Open failed\n");
1461 return hr;
1464 /* the driver is now open, so it's now allowed to call GetCaps */
1465 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
1466 if (hr != DS_OK) {
1467 WARN("IDsDriver_GetCaps failed\n");
1468 return hr;
1470 } else {
1471 WAVEOUTCAPSA woc;
1472 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
1473 if (hr != DS_OK) {
1474 WARN("waveOutGetDevCaps failed\n");
1475 return hr;
1477 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
1478 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
1479 (woc.dwFormats & WAVE_FORMAT_2M08) ||
1480 (woc.dwFormats & WAVE_FORMAT_4M08) ||
1481 (woc.dwFormats & WAVE_FORMAT_48M08) ||
1482 (woc.dwFormats & WAVE_FORMAT_96M08)) {
1483 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1484 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1486 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
1487 (woc.dwFormats & WAVE_FORMAT_2M16) ||
1488 (woc.dwFormats & WAVE_FORMAT_4M16) ||
1489 (woc.dwFormats & WAVE_FORMAT_48M16) ||
1490 (woc.dwFormats & WAVE_FORMAT_96M16)) {
1491 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1492 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
1494 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
1495 (woc.dwFormats & WAVE_FORMAT_2S08) ||
1496 (woc.dwFormats & WAVE_FORMAT_4S08) ||
1497 (woc.dwFormats & WAVE_FORMAT_48S08) ||
1498 (woc.dwFormats & WAVE_FORMAT_96S08)) {
1499 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
1500 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1502 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
1503 (woc.dwFormats & WAVE_FORMAT_2S16) ||
1504 (woc.dwFormats & WAVE_FORMAT_4S16) ||
1505 (woc.dwFormats & WAVE_FORMAT_48S16) ||
1506 (woc.dwFormats & WAVE_FORMAT_96S16)) {
1507 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
1508 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
1510 if (ds_emuldriver)
1511 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
1512 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
1513 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
1514 device->drvcaps.dwPrimaryBuffers = 1;
1517 hr = DSOUND_PrimaryCreate(device);
1518 if (hr == DS_OK) {
1519 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
1520 timeBeginPeriod(DS_TIME_RES);
1521 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1522 (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
1523 } else {
1524 WARN("DSOUND_PrimaryCreate failed\n");
1527 return hr;
1530 HRESULT DirectSoundDevice_CreateSoundBuffer(
1531 DirectSoundDevice * device,
1532 LPCDSBUFFERDESC dsbd,
1533 LPLPDIRECTSOUNDBUFFER ppdsb,
1534 LPUNKNOWN lpunk,
1535 BOOL from8)
1537 HRESULT hres = DS_OK;
1538 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
1540 if (device == NULL) {
1541 WARN("not initialized\n");
1542 return DSERR_UNINITIALIZED;
1545 if (dsbd == NULL) {
1546 WARN("invalid parameter: dsbd == NULL\n");
1547 return DSERR_INVALIDPARAM;
1550 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
1551 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
1552 WARN("invalid parameter: dsbd\n");
1553 return DSERR_INVALIDPARAM;
1556 if (ppdsb == NULL) {
1557 WARN("invalid parameter: ppdsb == NULL\n");
1558 return DSERR_INVALIDPARAM;
1561 if (TRACE_ON(dsound)) {
1562 TRACE("(structsize=%d)\n",dsbd->dwSize);
1563 TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
1564 _dump_DSBCAPS(dsbd->dwFlags);
1565 DPRINTF(")\n");
1566 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
1567 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
1570 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
1571 if (dsbd->lpwfxFormat != NULL) {
1572 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1573 "primary buffer\n");
1574 return DSERR_INVALIDPARAM;
1577 if (device->primary) {
1578 WARN("Primary Buffer already created\n");
1579 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1580 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1581 } else {
1582 device->dsbd = *dsbd;
1583 hres = PrimaryBufferImpl_Create(device, (PrimaryBufferImpl**)&(device->primary), &(device->dsbd));
1584 if (device->primary) {
1585 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1586 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1587 } else
1588 WARN("PrimaryBufferImpl_Create failed\n");
1590 } else {
1591 IDirectSoundBufferImpl * dsb;
1593 if (dsbd->lpwfxFormat == NULL) {
1594 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1595 "secondary buffer\n");
1596 return DSERR_INVALIDPARAM;
1599 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1600 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1601 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
1602 dsbd->lpwfxFormat->nSamplesPerSec,
1603 dsbd->lpwfxFormat->nAvgBytesPerSec,
1604 dsbd->lpwfxFormat->nBlockAlign,
1605 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
1607 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
1608 WARN("invalid parameter: 3D buffer format must be mono\n");
1609 return DSERR_INVALIDPARAM;
1612 hres = IDirectSoundBufferImpl_Create(device, (IDirectSoundBufferImpl**)&dsb, dsbd);
1613 if (dsb) {
1614 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
1615 if (*ppdsb) {
1616 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
1617 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
1618 } else
1619 WARN("SecondaryBufferImpl_Create failed\n");
1620 } else
1621 WARN("IDirectSoundBufferImpl_Create failed\n");
1624 return hres;
1627 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
1628 DirectSoundDevice * device,
1629 LPDIRECTSOUNDBUFFER psb,
1630 LPLPDIRECTSOUNDBUFFER ppdsb)
1632 HRESULT hres = DS_OK;
1633 IDirectSoundBufferImpl* dsb;
1634 TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
1636 if (device == NULL) {
1637 WARN("not initialized\n");
1638 return DSERR_UNINITIALIZED;
1641 if (psb == NULL) {
1642 WARN("invalid parameter: psb == NULL\n");
1643 return DSERR_INVALIDPARAM;
1646 if (ppdsb == NULL) {
1647 WARN("invalid parameter: ppdsb == NULL\n");
1648 return DSERR_INVALIDPARAM;
1651 /* make sure we have a secondary buffer */
1652 if ((PrimaryBufferImpl *)psb == device->primary) {
1653 WARN("trying to duplicate primary buffer\n");
1654 *ppdsb = NULL;
1655 return DSERR_INVALIDCALL;
1658 /* duplicate the actual buffer implementation */
1659 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb,
1660 ((SecondaryBufferImpl *)psb)->dsb);
1662 if (hres == DS_OK) {
1663 /* create a new secondary buffer using the new implementation */
1664 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
1665 if (*ppdsb) {
1666 dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
1667 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
1668 } else {
1669 WARN("SecondaryBufferImpl_Create failed\n");
1670 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
1671 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb);
1675 return hres;
1678 HRESULT DirectSoundDevice_SetCooperativeLevel(
1679 DirectSoundDevice * device,
1680 HWND hwnd,
1681 DWORD level)
1683 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
1685 if (device == NULL) {
1686 WARN("not initialized\n");
1687 return DSERR_UNINITIALIZED;
1690 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
1691 WARN("level=%s not fully supported\n",
1692 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1695 device->priolevel = level;
1696 return DS_OK;
1699 HRESULT DirectSoundDevice_Compact(
1700 DirectSoundDevice * device)
1702 TRACE("(%p)\n", device);
1704 if (device == NULL) {
1705 WARN("not initialized\n");
1706 return DSERR_UNINITIALIZED;
1709 if (device->priolevel < DSSCL_PRIORITY) {
1710 WARN("incorrect priority level\n");
1711 return DSERR_PRIOLEVELNEEDED;
1714 return DS_OK;
1717 HRESULT DirectSoundDevice_GetSpeakerConfig(
1718 DirectSoundDevice * device,
1719 LPDWORD lpdwSpeakerConfig)
1721 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
1723 if (device == NULL) {
1724 WARN("not initialized\n");
1725 return DSERR_UNINITIALIZED;
1728 if (lpdwSpeakerConfig == NULL) {
1729 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1730 return DSERR_INVALIDPARAM;
1733 WARN("not fully functional\n");
1734 *lpdwSpeakerConfig = device->speaker_config;
1735 return DS_OK;
1738 HRESULT DirectSoundDevice_SetSpeakerConfig(
1739 DirectSoundDevice * device,
1740 DWORD config)
1742 TRACE("(%p,0x%08x)\n",device,config);
1744 if (device == NULL) {
1745 WARN("not initialized\n");
1746 return DSERR_UNINITIALIZED;
1749 device->speaker_config = config;
1750 WARN("not fully functional\n");
1751 return DS_OK;
1754 static HRESULT DirectSoundDevice_VerifyCertification(
1755 DirectSoundDevice * device,
1756 LPDWORD pdwCertified)
1758 TRACE("(%p, %p)\n",device,pdwCertified);
1760 if (device == NULL) {
1761 WARN("not initialized\n");
1762 return DSERR_UNINITIALIZED;
1765 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
1766 *pdwCertified = DS_CERTIFIED;
1767 else
1768 *pdwCertified = DS_UNCERTIFIED;
1770 return DS_OK;
1774 * Add secondary buffer to buffer list.
1775 * Gets exclusive access to buffer for writing.
1777 HRESULT DirectSoundDevice_AddBuffer(
1778 DirectSoundDevice * device,
1779 IDirectSoundBufferImpl * pDSB)
1781 IDirectSoundBufferImpl **newbuffers;
1782 HRESULT hr = DS_OK;
1784 TRACE("(%p, %p)\n", device, pDSB);
1786 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1788 if (device->buffers)
1789 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1790 else
1791 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1793 if (newbuffers) {
1794 device->buffers = newbuffers;
1795 device->buffers[device->nrofbuffers] = pDSB;
1796 device->nrofbuffers++;
1797 TRACE("buffer count is now %d\n", device->nrofbuffers);
1798 } else {
1799 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
1800 hr = DSERR_OUTOFMEMORY;
1803 RtlReleaseResource(&(device->buffer_list_lock));
1805 return hr;
1809 * Remove secondary buffer from buffer list.
1810 * Gets exclusive access to buffer for writing.
1812 HRESULT DirectSoundDevice_RemoveBuffer(
1813 DirectSoundDevice * device,
1814 IDirectSoundBufferImpl * pDSB)
1816 int i;
1817 HRESULT hr = DS_OK;
1819 TRACE("(%p, %p)\n", device, pDSB);
1821 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1823 for (i = 0; i < device->nrofbuffers; i++)
1824 if (device->buffers[i] == pDSB)
1825 break;
1827 if (i < device->nrofbuffers) {
1828 /* Put the last buffer of the list in the (now empty) position */
1829 device->buffers[i] = device->buffers[device->nrofbuffers - 1];
1830 device->nrofbuffers--;
1831 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
1832 TRACE("buffer count is now %d\n", device->nrofbuffers);
1835 if (device->nrofbuffers == 0) {
1836 HeapFree(GetProcessHeap(),0,device->buffers);
1837 device->buffers = NULL;
1840 RtlReleaseResource(&(device->buffer_list_lock));
1842 return hr;