gdiplus: Add support for JPEG encoding.
[wine/multimedia.git] / dlls / dsound / dsound.c
blob91184c9c8065ef3a2f127c214aaf31f3d0fb3e07
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 COBJMACROS
27 #define NONAMELESSSTRUCT
28 #define NONAMELESSUNION
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.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_COMBINED(DSSPEAKER_STEREO, DSSPEAKER_GEOMETRY_WIDE);
1177 /* 3D listener initial parameters */
1178 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1179 device->ds3dl.vPosition.x = 0.0;
1180 device->ds3dl.vPosition.y = 0.0;
1181 device->ds3dl.vPosition.z = 0.0;
1182 device->ds3dl.vVelocity.x = 0.0;
1183 device->ds3dl.vVelocity.y = 0.0;
1184 device->ds3dl.vVelocity.z = 0.0;
1185 device->ds3dl.vOrientFront.x = 0.0;
1186 device->ds3dl.vOrientFront.y = 0.0;
1187 device->ds3dl.vOrientFront.z = 1.0;
1188 device->ds3dl.vOrientTop.x = 0.0;
1189 device->ds3dl.vOrientTop.y = 1.0;
1190 device->ds3dl.vOrientTop.z = 0.0;
1191 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1192 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1193 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1195 device->prebuf = ds_snd_queue_max;
1196 device->guid = GUID_NULL;
1198 /* Set default wave format (may need it for waveOutOpen) */
1199 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
1200 if (device->pwfx == NULL) {
1201 WARN("out of memory\n");
1202 HeapFree(GetProcessHeap(),0,device);
1203 return DSERR_OUTOFMEMORY;
1206 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
1207 device->pwfx->nSamplesPerSec = ds_default_sample_rate;
1208 device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
1209 device->pwfx->nChannels = 2;
1210 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
1211 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
1212 device->pwfx->cbSize = 0;
1214 InitializeCriticalSection(&(device->mixlock));
1215 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
1217 RtlInitializeResource(&(device->buffer_list_lock));
1219 *ppDevice = device;
1221 return DS_OK;
1224 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
1226 ULONG ref = InterlockedIncrement(&(device->ref));
1227 TRACE("(%p) ref was %d\n", device, ref - 1);
1228 return ref;
1231 ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
1233 HRESULT hr;
1234 ULONG ref = InterlockedDecrement(&(device->ref));
1235 TRACE("(%p) ref was %u\n", device, ref + 1);
1236 if (!ref) {
1237 int i;
1238 timeKillEvent(device->timerID);
1239 timeEndPeriod(DS_TIME_RES);
1241 /* The kill event should have allowed the timer process to expire
1242 * but try to grab the lock just in case. Can't hold lock because
1243 * secondarybuffer_destroy also grabs the lock */
1244 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
1245 RtlReleaseResource(&(device->buffer_list_lock));
1247 EnterCriticalSection(&DSOUND_renderers_lock);
1248 list_remove(&device->entry);
1249 LeaveCriticalSection(&DSOUND_renderers_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 secondarybuffer_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 if(device->client)
1268 IAudioClient_Release(device->client);
1269 if(device->render)
1270 IAudioRenderClient_Release(device->render);
1271 if(device->clock)
1272 IAudioClock_Release(device->clock);
1273 if(device->volume)
1274 IAudioStreamVolume_Release(device->volume);
1276 HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
1277 HeapFree(GetProcessHeap(), 0, device->mix_buffer);
1278 HeapFree(GetProcessHeap(), 0, device->buffer);
1279 RtlDeleteResource(&device->buffer_list_lock);
1280 device->mixlock.DebugInfo->Spare[0] = 0;
1281 DeleteCriticalSection(&device->mixlock);
1282 HeapFree(GetProcessHeap(),0,device);
1283 TRACE("(%p) released\n", device);
1285 return ref;
1288 HRESULT DirectSoundDevice_GetCaps(
1289 DirectSoundDevice * device,
1290 LPDSCAPS lpDSCaps)
1292 TRACE("(%p,%p)\n",device,lpDSCaps);
1294 if (device == NULL) {
1295 WARN("not initialized\n");
1296 return DSERR_UNINITIALIZED;
1299 if (lpDSCaps == NULL) {
1300 WARN("invalid parameter: lpDSCaps = NULL\n");
1301 return DSERR_INVALIDPARAM;
1304 /* check if there is enough room */
1305 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
1306 WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize);
1307 return DSERR_INVALIDPARAM;
1310 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
1311 if (TRACE_ON(dsound)) {
1312 TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags);
1313 _dump_DSCAPS(lpDSCaps->dwFlags);
1314 TRACE(")\n");
1316 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
1317 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
1318 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
1319 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
1320 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
1321 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
1322 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
1323 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
1324 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
1325 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
1326 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
1327 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
1328 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
1329 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
1330 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
1331 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
1332 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
1333 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
1334 lpDSCaps->dwUnlockTransferRateHwBuffers = device->drvcaps.dwUnlockTransferRateHwBuffers;
1335 lpDSCaps->dwPlayCpuOverheadSwBuffers = device->drvcaps.dwPlayCpuOverheadSwBuffers;
1337 return DS_OK;
1340 BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate,
1341 DWORD depth, WORD channels)
1343 WAVEFORMATEX fmt, *junk;
1344 HRESULT hr;
1346 fmt.wFormatTag = WAVE_FORMAT_PCM;
1347 fmt.nChannels = channels;
1348 fmt.nSamplesPerSec = rate;
1349 fmt.wBitsPerSample = depth;
1350 fmt.nBlockAlign = (channels * depth) / 8;
1351 fmt.nAvgBytesPerSec = rate * fmt.nBlockAlign;
1352 fmt.cbSize = 0;
1354 hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &fmt, &junk);
1355 if(SUCCEEDED(hr))
1356 CoTaskMemFree(junk);
1358 return hr == S_OK;
1361 UINT DSOUND_create_timer(LPTIMECALLBACK cb, DWORD_PTR user)
1363 UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id;
1364 TIMECAPS time;
1366 timeGetDevCaps(&time, sizeof(TIMECAPS));
1367 TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax);
1368 if (triggertime < time.wPeriodMin)
1369 triggertime = time.wPeriodMin;
1370 if (res < time.wPeriodMin)
1371 res = time.wPeriodMin;
1372 if (timeBeginPeriod(res) == TIMERR_NOCANDO)
1373 WARN("Could not set minimum resolution, don't expect sound\n");
1374 id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
1375 if (!id)
1377 WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n");
1378 id = timeSetEvent(triggertime, res, cb, user, TIME_PERIODIC);
1379 if (!id)
1380 ERR("Could not create timer, sound playback will not occur\n");
1382 return id;
1385 HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
1387 HRESULT hr = DS_OK;
1388 GUID devGUID;
1389 DirectSoundDevice *device;
1390 IMMDevice *mmdevice;
1392 TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
1394 if (*ppDevice != NULL) {
1395 WARN("already initialized\n");
1396 return DSERR_ALREADYINITIALIZED;
1399 /* Default device? */
1400 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1401 lpcGUID = &DSDEVID_DefaultPlayback;
1403 if(IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) ||
1404 IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture))
1405 return DSERR_NODRIVER;
1407 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1408 WARN("invalid parameter: lpcGUID\n");
1409 return DSERR_INVALIDPARAM;
1412 hr = get_mmdevice(eRender, &devGUID, &mmdevice);
1413 if(FAILED(hr))
1414 return hr;
1416 EnterCriticalSection(&DSOUND_renderers_lock);
1418 LIST_FOR_EACH_ENTRY(device, &DSOUND_renderers, DirectSoundDevice, entry){
1419 if(IsEqualGUID(&device->guid, &devGUID)){
1420 IMMDevice_Release(mmdevice);
1421 DirectSoundDevice_AddRef(device);
1422 *ppDevice = device;
1423 LeaveCriticalSection(&DSOUND_renderers_lock);
1424 return DS_OK;
1428 hr = DirectSoundDevice_Create(&device);
1429 if(FAILED(hr)){
1430 WARN("DirectSoundDevice_Create failed\n");
1431 IMMDevice_Release(mmdevice);
1432 LeaveCriticalSection(&DSOUND_renderers_lock);
1433 return hr;
1436 device->mmdevice = mmdevice;
1437 device->guid = devGUID;
1439 hr = DSOUND_ReopenDevice(device, FALSE);
1440 if (FAILED(hr))
1442 HeapFree(GetProcessHeap(), 0, device);
1443 LeaveCriticalSection(&DSOUND_renderers_lock);
1444 IMMDevice_Release(mmdevice);
1445 WARN("DSOUND_ReopenDevice failed: %08x\n", hr);
1446 return hr;
1449 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
1451 if(DSOUND_check_supported(device->client, 11025, 8, 1) ||
1452 DSOUND_check_supported(device->client, 22050, 8, 1) ||
1453 DSOUND_check_supported(device->client, 44100, 8, 1) ||
1454 DSOUND_check_supported(device->client, 48000, 8, 1) ||
1455 DSOUND_check_supported(device->client, 96000, 8, 1))
1456 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYMONO;
1458 if(DSOUND_check_supported(device->client, 11025, 16, 1) ||
1459 DSOUND_check_supported(device->client, 22050, 16, 1) ||
1460 DSOUND_check_supported(device->client, 44100, 16, 1) ||
1461 DSOUND_check_supported(device->client, 48000, 16, 1) ||
1462 DSOUND_check_supported(device->client, 96000, 16, 1))
1463 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYMONO;
1465 if(DSOUND_check_supported(device->client, 11025, 8, 2) ||
1466 DSOUND_check_supported(device->client, 22050, 8, 2) ||
1467 DSOUND_check_supported(device->client, 44100, 8, 2) ||
1468 DSOUND_check_supported(device->client, 48000, 8, 2) ||
1469 DSOUND_check_supported(device->client, 96000, 8, 2))
1470 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYSTEREO;
1472 if(DSOUND_check_supported(device->client, 11025, 16, 2) ||
1473 DSOUND_check_supported(device->client, 22050, 16, 2) ||
1474 DSOUND_check_supported(device->client, 44100, 16, 2) ||
1475 DSOUND_check_supported(device->client, 48000, 16, 2) ||
1476 DSOUND_check_supported(device->client, 96000, 16, 2))
1477 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO;
1479 /* the dsound mixer supports all of the following */
1480 device->drvcaps.dwFlags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;
1481 device->drvcaps.dwFlags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
1482 device->drvcaps.dwFlags |= DSCAPS_CONTINUOUSRATE;
1484 device->drvcaps.dwPrimaryBuffers = 1;
1485 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
1486 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
1487 device->drvcaps.dwMaxHwMixingAllBuffers = 1;
1488 device->drvcaps.dwMaxHwMixingStaticBuffers = 1;
1489 device->drvcaps.dwMaxHwMixingStreamingBuffers = 1;
1491 ZeroMemory(&device->volpan, sizeof(device->volpan));
1493 hr = DSOUND_PrimaryCreate(device);
1494 if (hr == DS_OK)
1495 device->timerID = DSOUND_create_timer(DSOUND_timer, (DWORD_PTR)device);
1496 else
1497 WARN("DSOUND_PrimaryCreate failed: %08x\n", hr);
1499 *ppDevice = device;
1500 list_add_tail(&DSOUND_renderers, &device->entry);
1502 LeaveCriticalSection(&DSOUND_renderers_lock);
1504 return hr;
1507 HRESULT DirectSoundDevice_CreateSoundBuffer(
1508 DirectSoundDevice * device,
1509 LPCDSBUFFERDESC dsbd,
1510 LPLPDIRECTSOUNDBUFFER ppdsb,
1511 LPUNKNOWN lpunk,
1512 BOOL from8)
1514 HRESULT hres = DS_OK;
1515 TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
1517 if (device == NULL) {
1518 WARN("not initialized\n");
1519 return DSERR_UNINITIALIZED;
1522 if (dsbd == NULL) {
1523 WARN("invalid parameter: dsbd == NULL\n");
1524 return DSERR_INVALIDPARAM;
1527 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
1528 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
1529 WARN("invalid parameter: dsbd\n");
1530 return DSERR_INVALIDPARAM;
1533 if (ppdsb == NULL) {
1534 WARN("invalid parameter: ppdsb == NULL\n");
1535 return DSERR_INVALIDPARAM;
1537 *ppdsb = NULL;
1539 if (TRACE_ON(dsound)) {
1540 TRACE("(structsize=%d)\n",dsbd->dwSize);
1541 TRACE("(flags=0x%08x:\n",dsbd->dwFlags);
1542 _dump_DSBCAPS(dsbd->dwFlags);
1543 TRACE(")\n");
1544 TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes);
1545 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
1548 if (dsbd->dwFlags & DSBCAPS_LOCHARDWARE &&
1549 !(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
1550 TRACE("LOCHARDWARE is not supported, returning E_NOTIMPL\n");
1551 return E_NOTIMPL;
1554 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
1555 if (dsbd->lpwfxFormat != NULL) {
1556 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
1557 "primary buffer\n");
1558 return DSERR_INVALIDPARAM;
1561 if (device->primary) {
1562 WARN("Primary Buffer already created\n");
1563 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
1564 *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
1565 } else {
1566 hres = primarybuffer_create(device, &device->primary, dsbd);
1567 if (device->primary) {
1568 *ppdsb = (IDirectSoundBuffer*)&device->primary->IDirectSoundBuffer8_iface;
1569 device->primary->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE);
1570 device->primary->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE;
1571 } else
1572 WARN("primarybuffer_create() failed\n");
1574 } else {
1575 IDirectSoundBufferImpl * dsb;
1576 WAVEFORMATEXTENSIBLE *pwfxe;
1578 if (dsbd->lpwfxFormat == NULL) {
1579 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
1580 "secondary buffer\n");
1581 return DSERR_INVALIDPARAM;
1583 pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat;
1585 if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE)
1587 WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample);
1588 return DSERR_CONTROLUNAVAIL;
1590 if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
1592 /* check if cbSize is at least 22 bytes */
1593 if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)))
1595 WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize);
1596 return DSERR_INVALIDPARAM;
1599 /* cbSize should be 22 bytes, with one possible exception */
1600 if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) &&
1601 !((IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) &&
1602 pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
1604 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
1605 return DSERR_CONTROLUNAVAIL;
1608 if ((!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) && (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
1610 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
1611 FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
1612 return DSERR_INVALIDPARAM;
1614 if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample)
1616 WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample);
1617 return DSERR_INVALIDPARAM;
1619 if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample)
1621 FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample);
1622 return DSERR_CONTROLUNAVAIL;
1626 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1627 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1628 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
1629 dsbd->lpwfxFormat->nSamplesPerSec,
1630 dsbd->lpwfxFormat->nAvgBytesPerSec,
1631 dsbd->lpwfxFormat->nBlockAlign,
1632 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
1634 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
1635 WARN("invalid parameter: 3D buffer format must be mono\n");
1636 return DSERR_INVALIDPARAM;
1639 hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd);
1640 if (dsb)
1641 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
1642 else
1643 WARN("IDirectSoundBufferImpl_Create failed\n");
1646 return hres;
1649 HRESULT DirectSoundDevice_DuplicateSoundBuffer(
1650 DirectSoundDevice * device,
1651 LPDIRECTSOUNDBUFFER psb,
1652 LPLPDIRECTSOUNDBUFFER ppdsb)
1654 HRESULT hres = DS_OK;
1655 IDirectSoundBufferImpl* dsb;
1656 TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
1658 if (device == NULL) {
1659 WARN("not initialized\n");
1660 return DSERR_UNINITIALIZED;
1663 if (psb == NULL) {
1664 WARN("invalid parameter: psb == NULL\n");
1665 return DSERR_INVALIDPARAM;
1668 if (ppdsb == NULL) {
1669 WARN("invalid parameter: ppdsb == NULL\n");
1670 return DSERR_INVALIDPARAM;
1673 /* make sure we have a secondary buffer */
1674 if (psb == (IDirectSoundBuffer *)&device->primary->IDirectSoundBuffer8_iface) {
1675 WARN("trying to duplicate primary buffer\n");
1676 *ppdsb = NULL;
1677 return DSERR_INVALIDCALL;
1680 /* duplicate the actual buffer implementation */
1681 hres = IDirectSoundBufferImpl_Duplicate(device, &dsb, (IDirectSoundBufferImpl*)psb);
1682 if (hres == DS_OK)
1683 *ppdsb = (IDirectSoundBuffer*)&dsb->IDirectSoundBuffer8_iface;
1684 else
1685 WARN("IDirectSoundBufferImpl_Duplicate failed\n");
1687 return hres;
1690 HRESULT DirectSoundDevice_SetCooperativeLevel(
1691 DirectSoundDevice * device,
1692 HWND hwnd,
1693 DWORD level)
1695 TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
1697 if (device == NULL) {
1698 WARN("not initialized\n");
1699 return DSERR_UNINITIALIZED;
1702 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
1703 WARN("level=%s not fully supported\n",
1704 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
1707 device->priolevel = level;
1708 return DS_OK;
1711 HRESULT DirectSoundDevice_Compact(
1712 DirectSoundDevice * device)
1714 TRACE("(%p)\n", device);
1716 if (device == NULL) {
1717 WARN("not initialized\n");
1718 return DSERR_UNINITIALIZED;
1721 if (device->priolevel < DSSCL_PRIORITY) {
1722 WARN("incorrect priority level\n");
1723 return DSERR_PRIOLEVELNEEDED;
1726 return DS_OK;
1729 HRESULT DirectSoundDevice_GetSpeakerConfig(
1730 DirectSoundDevice * device,
1731 LPDWORD lpdwSpeakerConfig)
1733 TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
1735 if (device == NULL) {
1736 WARN("not initialized\n");
1737 return DSERR_UNINITIALIZED;
1740 if (lpdwSpeakerConfig == NULL) {
1741 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
1742 return DSERR_INVALIDPARAM;
1745 WARN("not fully functional\n");
1746 *lpdwSpeakerConfig = device->speaker_config;
1747 return DS_OK;
1750 HRESULT DirectSoundDevice_SetSpeakerConfig(
1751 DirectSoundDevice * device,
1752 DWORD config)
1754 TRACE("(%p,0x%08x)\n",device,config);
1756 if (device == NULL) {
1757 WARN("not initialized\n");
1758 return DSERR_UNINITIALIZED;
1761 device->speaker_config = config;
1762 WARN("not fully functional\n");
1763 return DS_OK;
1766 HRESULT DirectSoundDevice_VerifyCertification(
1767 DirectSoundDevice * device,
1768 LPDWORD pdwCertified)
1770 TRACE("(%p, %p)\n",device,pdwCertified);
1772 if (device == NULL) {
1773 WARN("not initialized\n");
1774 return DSERR_UNINITIALIZED;
1777 if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
1778 *pdwCertified = DS_CERTIFIED;
1779 else
1780 *pdwCertified = DS_UNCERTIFIED;
1782 return DS_OK;
1786 * Add secondary buffer to buffer list.
1787 * Gets exclusive access to buffer for writing.
1789 HRESULT DirectSoundDevice_AddBuffer(
1790 DirectSoundDevice * device,
1791 IDirectSoundBufferImpl * pDSB)
1793 IDirectSoundBufferImpl **newbuffers;
1794 HRESULT hr = DS_OK;
1796 TRACE("(%p, %p)\n", device, pDSB);
1798 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1800 if (device->buffers)
1801 newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1802 else
1803 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1));
1805 if (newbuffers) {
1806 device->buffers = newbuffers;
1807 device->buffers[device->nrofbuffers] = pDSB;
1808 device->nrofbuffers++;
1809 TRACE("buffer count is now %d\n", device->nrofbuffers);
1810 } else {
1811 ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers);
1812 hr = DSERR_OUTOFMEMORY;
1815 RtlReleaseResource(&(device->buffer_list_lock));
1817 return hr;
1821 * Remove secondary buffer from buffer list.
1822 * Gets exclusive access to buffer for writing.
1824 HRESULT DirectSoundDevice_RemoveBuffer(
1825 DirectSoundDevice * device,
1826 IDirectSoundBufferImpl * pDSB)
1828 int i;
1829 HRESULT hr = DS_OK;
1831 TRACE("(%p, %p)\n", device, pDSB);
1833 RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
1835 for (i = 0; i < device->nrofbuffers; i++)
1836 if (device->buffers[i] == pDSB)
1837 break;
1839 if (i < device->nrofbuffers) {
1840 /* Put the last buffer of the list in the (now empty) position */
1841 device->buffers[i] = device->buffers[device->nrofbuffers - 1];
1842 device->nrofbuffers--;
1843 device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers);
1844 TRACE("buffer count is now %d\n", device->nrofbuffers);
1847 if (device->nrofbuffers == 0) {
1848 HeapFree(GetProcessHeap(),0,device->buffers);
1849 device->buffers = NULL;
1852 RtlReleaseResource(&(device->buffer_list_lock));
1854 return hr;