Include winuser.h so the code compiles cleanly on windows using
[wine.git] / dlls / dsound / dsound.c
bloba654ede5c379c7c58aee2cb6728915d1813ce4d3
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "winreg.h"
32 #include "mmsystem.h"
33 #include "winternl.h"
34 #include "mmddk.h"
35 #include "wine/debug.h"
36 #include "dsound.h"
37 #include "dsdriver.h"
38 #include "dsound_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
42 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
43 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
44 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
45 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
46 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
48 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice);
49 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device);
50 static ULONG DirectSoundDevice_Release(DirectSoundDevice * device);
52 static const char * dumpCooperativeLevel(DWORD level)
54 static char unknown[32];
55 #define LE(x) case x: return #x
56 switch (level) {
57 LE(DSSCL_NORMAL);
58 LE(DSSCL_PRIORITY);
59 LE(DSSCL_EXCLUSIVE);
60 LE(DSSCL_WRITEPRIMARY);
62 #undef LE
63 sprintf(unknown, "Unknown(%08lx)", level);
64 return unknown;
67 static void _dump_DSCAPS(DWORD xmask) {
68 struct {
69 DWORD mask;
70 const char *name;
71 } flags[] = {
72 #define FE(x) { x, #x },
73 FE(DSCAPS_PRIMARYMONO)
74 FE(DSCAPS_PRIMARYSTEREO)
75 FE(DSCAPS_PRIMARY8BIT)
76 FE(DSCAPS_PRIMARY16BIT)
77 FE(DSCAPS_CONTINUOUSRATE)
78 FE(DSCAPS_EMULDRIVER)
79 FE(DSCAPS_CERTIFIED)
80 FE(DSCAPS_SECONDARYMONO)
81 FE(DSCAPS_SECONDARYSTEREO)
82 FE(DSCAPS_SECONDARY8BIT)
83 FE(DSCAPS_SECONDARY16BIT)
84 #undef FE
86 unsigned int i;
88 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
89 if ((flags[i].mask & xmask) == flags[i].mask)
90 DPRINTF("%s ",flags[i].name);
93 static void _dump_DSBCAPS(DWORD xmask) {
94 struct {
95 DWORD mask;
96 const char *name;
97 } flags[] = {
98 #define FE(x) { x, #x },
99 FE(DSBCAPS_PRIMARYBUFFER)
100 FE(DSBCAPS_STATIC)
101 FE(DSBCAPS_LOCHARDWARE)
102 FE(DSBCAPS_LOCSOFTWARE)
103 FE(DSBCAPS_CTRL3D)
104 FE(DSBCAPS_CTRLFREQUENCY)
105 FE(DSBCAPS_CTRLPAN)
106 FE(DSBCAPS_CTRLVOLUME)
107 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
108 FE(DSBCAPS_STICKYFOCUS)
109 FE(DSBCAPS_GLOBALFOCUS)
110 FE(DSBCAPS_GETCURRENTPOSITION2)
111 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
112 #undef FE
114 unsigned int i;
116 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
117 if ((flags[i].mask & xmask) == flags[i].mask)
118 DPRINTF("%s ",flags[i].name);
121 /*******************************************************************************
122 * IDirectSoundImpl_DirectSound
124 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
125 LPDIRECTSOUND8 iface,
126 REFIID riid,
127 LPVOID * ppobj)
129 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
130 FIXME("shouldn't be called directly\n");
131 return E_NOINTERFACE;
134 static HRESULT WINAPI DSOUND_QueryInterface(
135 LPDIRECTSOUND8 iface,
136 REFIID riid,
137 LPVOID * ppobj)
139 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
140 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
142 if (ppobj == NULL) {
143 WARN("invalid parameter\n");
144 return E_INVALIDARG;
147 if (IsEqualIID(riid, &IID_IUnknown)) {
148 if (!This->pUnknown) {
149 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
150 if (!This->pUnknown) {
151 WARN("IDirectSound_IUnknown_Create() failed\n");
152 *ppobj = NULL;
153 return E_NOINTERFACE;
156 IDirectSound_IUnknown_AddRef(This->pUnknown);
157 *ppobj = This->pUnknown;
158 return S_OK;
159 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
160 if (!This->pDS) {
161 IDirectSound_IDirectSound_Create(iface, &This->pDS);
162 if (!This->pDS) {
163 WARN("IDirectSound_IDirectSound_Create() failed\n");
164 *ppobj = NULL;
165 return E_NOINTERFACE;
168 IDirectSound_IDirectSound_AddRef(This->pDS);
169 *ppobj = This->pDS;
170 return S_OK;
173 *ppobj = NULL;
174 WARN("Unknown IID %s\n",debugstr_guid(riid));
175 return E_NOINTERFACE;
178 static HRESULT WINAPI DSOUND_QueryInterface8(
179 LPDIRECTSOUND8 iface,
180 REFIID riid,
181 LPVOID * ppobj)
183 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
184 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
186 if (ppobj == NULL) {
187 WARN("invalid parameter\n");
188 return E_INVALIDARG;
191 if (IsEqualIID(riid, &IID_IUnknown)) {
192 if (!This->pUnknown) {
193 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
194 if (!This->pUnknown) {
195 WARN("IDirectSound8_IUnknown_Create() failed\n");
196 *ppobj = NULL;
197 return E_NOINTERFACE;
200 IDirectSound8_IUnknown_AddRef(This->pUnknown);
201 *ppobj = This->pUnknown;
202 return S_OK;
203 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
204 if (!This->pDS) {
205 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
206 if (!This->pDS) {
207 WARN("IDirectSound8_IDirectSound_Create() failed\n");
208 *ppobj = NULL;
209 return E_NOINTERFACE;
212 IDirectSound8_IDirectSound_AddRef(This->pDS);
213 *ppobj = This->pDS;
214 return S_OK;
215 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
216 if (!This->pDS8) {
217 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
218 if (!This->pDS8) {
219 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
220 *ppobj = NULL;
221 return E_NOINTERFACE;
224 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
225 *ppobj = This->pDS8;
226 return S_OK;
229 *ppobj = NULL;
230 WARN("Unknown IID %s\n",debugstr_guid(riid));
231 return E_NOINTERFACE;
234 static ULONG WINAPI IDirectSoundImpl_AddRef(
235 LPDIRECTSOUND8 iface)
237 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
238 ULONG ref = InterlockedIncrement(&(This->ref));
239 TRACE("(%p) ref was %ld\n", This, ref - 1);
240 return ref;
243 static ULONG WINAPI IDirectSoundImpl_Release(
244 LPDIRECTSOUND8 iface)
246 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
247 ULONG ref = InterlockedDecrement(&(This->ref));
248 TRACE("(%p) ref was %ld\n", This, ref + 1);
250 if (!ref) {
251 if (This->device) {
252 if (DirectSoundDevice_Release(This->device) != 0) {
253 /* device not released so make sure primary reference to This removed */
254 if (This->device->primary)
255 This->device->primary->dsound = NULL;
258 HeapFree(GetProcessHeap(),0,This);
259 TRACE("(%p) released\n", This);
261 return ref;
264 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
265 LPDIRECTSOUND8 iface,
266 LPCDSBUFFERDESC dsbd,
267 LPLPDIRECTSOUNDBUFFER ppdsb,
268 LPUNKNOWN lpunk)
270 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
271 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
272 FIXME("shouldn't be called directly\n");
273 return DSERR_GENERIC;
276 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
277 LPDIRECTSOUND8 iface,
278 LPCDSBUFFERDESC dsbd,
279 LPLPDIRECTSOUNDBUFFER ppdsb,
280 LPUNKNOWN lpunk,
281 BOOL from8)
283 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
284 HRESULT hres = DS_OK;
285 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
287 if (This == NULL) {
288 WARN("invalid parameter: This == NULL\n");
289 return DSERR_INVALIDPARAM;
292 if (This->device == NULL) {
293 WARN("not initialized\n");
294 return DSERR_UNINITIALIZED;
297 if (dsbd == NULL) {
298 WARN("invalid parameter: dsbd == NULL\n");
299 return DSERR_INVALIDPARAM;
302 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
303 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
304 WARN("invalid parameter: dsbd\n");
305 return DSERR_INVALIDPARAM;
308 if (ppdsb == NULL) {
309 WARN("invalid parameter: ppdsb == NULL\n");
310 return DSERR_INVALIDPARAM;
313 if (TRACE_ON(dsound)) {
314 TRACE("(structsize=%ld)\n",dsbd->dwSize);
315 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
316 _dump_DSBCAPS(dsbd->dwFlags);
317 DPRINTF(")\n");
318 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
319 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
322 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
323 if (dsbd->lpwfxFormat != NULL) {
324 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
325 "primary buffer\n");
326 return DSERR_INVALIDPARAM;
329 if (This->device->primary) {
330 WARN("Primary Buffer already created\n");
331 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
332 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
333 This->device->primary->dsound = This;
334 } else {
335 This->device->dsbd = *dsbd;
336 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd));
337 if (This->device->primary) {
338 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
339 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
340 } else
341 WARN("PrimaryBufferImpl_Create failed\n");
343 } else {
344 IDirectSoundBufferImpl * dsb;
346 if (dsbd->lpwfxFormat == NULL) {
347 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
348 "secondary buffer\n");
349 return DSERR_INVALIDPARAM;
352 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
353 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
354 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
355 dsbd->lpwfxFormat->nSamplesPerSec,
356 dsbd->lpwfxFormat->nAvgBytesPerSec,
357 dsbd->lpwfxFormat->nBlockAlign,
358 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
360 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
361 WARN("invalid parameter: 3D buffer format must be mono\n");
362 return DSERR_INVALIDPARAM;
365 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
366 if (dsb) {
367 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
368 if (*ppdsb) {
369 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
370 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
371 } else
372 WARN("SecondaryBufferImpl_Create failed\n");
373 } else
374 WARN("IDirectSoundBufferImpl_Create failed\n");
377 return hres;
380 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
381 LPDIRECTSOUND8 iface,
382 LPDSCAPS lpDSCaps)
384 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
385 DirectSoundDevice *device;
386 TRACE("(%p,%p)\n",This,lpDSCaps);
388 if (This == NULL) {
389 WARN("invalid parameter: This == NULL\n");
390 return DSERR_INVALIDPARAM;
393 device = This->device;
395 if (device == NULL) {
396 WARN("not initialized\n");
397 return DSERR_UNINITIALIZED;
400 if (lpDSCaps == NULL) {
401 WARN("invalid parameter: lpDSCaps = NULL\n");
402 return DSERR_INVALIDPARAM;
405 /* check if there is enough room */
406 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
407 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
408 lpDSCaps->dwSize, sizeof(*lpDSCaps));
409 return DSERR_INVALIDPARAM;
412 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
413 if (TRACE_ON(dsound)) {
414 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
415 _dump_DSCAPS(lpDSCaps->dwFlags);
416 DPRINTF(")\n");
418 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
419 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
420 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
421 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
422 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
423 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
424 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
425 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
426 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
427 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
428 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
429 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
430 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
431 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
432 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
433 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
434 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
435 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
437 /* driver doesn't have these */
438 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
439 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
441 return DS_OK;
444 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
445 LPDIRECTSOUND8 iface,
446 LPDIRECTSOUNDBUFFER psb,
447 LPLPDIRECTSOUNDBUFFER ppdsb)
449 IDirectSoundBufferImpl* pdsb;
450 IDirectSoundBufferImpl* dsb;
451 HRESULT hres = DS_OK;
452 int size;
453 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
455 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
457 if (This == NULL) {
458 WARN("invalid parameter: This == NULL\n");
459 return DSERR_INVALIDPARAM;
462 if (This->device == NULL) {
463 WARN("not initialized\n");
464 return DSERR_UNINITIALIZED;
467 if (psb == NULL) {
468 WARN("invalid parameter: psb == NULL\n");
469 return DSERR_INVALIDPARAM;
472 if (ppdsb == NULL) {
473 WARN("invalid parameter: ppdsb == NULL\n");
474 return DSERR_INVALIDPARAM;
477 /* FIXME: hack to make sure we have a secondary buffer */
478 if ((IDirectSoundImpl *)((SecondaryBufferImpl *)psb)->dsb == This) {
479 WARN("trying to duplicate primary buffer\n");
480 *ppdsb = NULL;
481 return DSERR_INVALIDCALL;
484 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
486 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
488 if (dsb == NULL) {
489 WARN("out of memory\n");
490 *ppdsb = NULL;
491 return DSERR_OUTOFMEMORY;
494 CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
496 if (pdsb->hwbuf) {
497 TRACE("duplicating hardware buffer\n");
499 hres = IDsDriver_DuplicateSoundBuffer(This->device->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
500 if (hres != DS_OK) {
501 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
502 dsb->hwbuf = NULL;
503 /* allocate buffer */
504 if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
505 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
506 if (dsb->buffer == NULL) {
507 WARN("out of memory\n");
508 HeapFree(GetProcessHeap(),0,dsb);
509 *ppdsb = NULL;
510 return DSERR_OUTOFMEMORY;
513 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
514 if (dsb->buffer->memory == NULL) {
515 WARN("out of memory\n");
516 HeapFree(GetProcessHeap(),0,dsb->buffer);
517 HeapFree(GetProcessHeap(),0,dsb);
518 *ppdsb = NULL;
519 return DSERR_OUTOFMEMORY;
521 dsb->buffer->ref = 1;
523 /* FIXME: copy buffer ? */
526 } else {
527 dsb->hwbuf = NULL;
528 dsb->buffer->ref++;
531 dsb->ref = 0;
532 dsb->state = STATE_STOPPED;
533 dsb->playpos = 0;
534 dsb->buf_mixpos = 0;
535 dsb->dsound = This;
536 dsb->ds3db = NULL;
537 dsb->iks = NULL; /* FIXME? */
538 dsb->dsb = NULL;
540 /* variable sized struct so calculate size based on format */
541 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
543 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
544 if (dsb->pwfx == NULL) {
545 WARN("out of memory\n");
546 HeapFree(GetProcessHeap(),0,dsb->buffer);
547 HeapFree(GetProcessHeap(),0,dsb);
548 *ppdsb = NULL;
549 return DSERR_OUTOFMEMORY;
552 CopyMemory(dsb->pwfx, pdsb->pwfx, size);
554 InitializeCriticalSection(&(dsb->lock));
555 dsb->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUNDBUFFER_lock";
557 /* register buffer */
558 hres = DSOUND_AddBuffer(This, dsb);
559 if (hres != DS_OK) {
560 IDirectSoundBuffer8_Release(psb);
561 dsb->lock.DebugInfo->Spare[0] = 0;
562 DeleteCriticalSection(&(dsb->lock));
563 HeapFree(GetProcessHeap(),0,dsb->buffer);
564 HeapFree(GetProcessHeap(),0,dsb->pwfx);
565 HeapFree(GetProcessHeap(),0,dsb);
566 *ppdsb = 0;
567 } else {
568 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
569 if (*ppdsb) {
570 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
571 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
572 } else
573 WARN("SecondaryBufferImpl_Create failed\n");
576 return hres;
579 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
580 LPDIRECTSOUND8 iface,
581 HWND hwnd,
582 DWORD level)
584 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
585 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
587 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
588 WARN("level=%s not fully supported\n",
589 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
591 This->device->priolevel = level;
592 return DS_OK;
595 static HRESULT WINAPI IDirectSoundImpl_Compact(
596 LPDIRECTSOUND8 iface)
598 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
599 TRACE("(%p)\n",This);
601 if (This->device == NULL) {
602 WARN("not initialized\n");
603 return DSERR_UNINITIALIZED;
606 if (This->device->priolevel != DSSCL_PRIORITY) {
607 WARN("incorrect priority level\n");
608 return DSERR_PRIOLEVELNEEDED;
611 return DS_OK;
614 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
615 LPDIRECTSOUND8 iface,
616 LPDWORD lpdwSpeakerConfig)
618 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
619 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
621 if (This->device == NULL) {
622 WARN("not initialized\n");
623 return DSERR_UNINITIALIZED;
626 if (lpdwSpeakerConfig == NULL) {
627 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
628 return DSERR_INVALIDPARAM;
631 WARN("not fully functional\n");
632 *lpdwSpeakerConfig = This->device->speaker_config;
633 return DS_OK;
636 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
637 LPDIRECTSOUND8 iface,
638 DWORD config)
640 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
641 TRACE("(%p,0x%08lx)\n",This,config);
643 if (This->device == NULL) {
644 WARN("not initialized\n");
645 return DSERR_UNINITIALIZED;
648 This->device->speaker_config = config;
649 WARN("not fully functional\n");
650 return DS_OK;
653 static HRESULT WINAPI IDirectSoundImpl_Initialize(
654 LPDIRECTSOUND8 iface,
655 LPCGUID lpcGUID)
657 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
658 DirectSoundDevice *device = This->device;
659 HRESULT hr = DS_OK;
660 unsigned wod, wodn;
661 BOOLEAN found = FALSE;
662 GUID devGUID;
663 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID));
665 if (device != NULL) {
666 WARN("already initialized\n");
667 return DSERR_ALREADYINITIALIZED;
670 /* Default device? */
671 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
672 lpcGUID = &DSDEVID_DefaultPlayback;
674 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
675 WARN("invalid parameter: lpcGUID\n");
676 return DSERR_INVALIDPARAM;
679 /* Enumerate WINMM audio devices and find the one we want */
680 wodn = waveOutGetNumDevs();
681 if (!wodn) {
682 WARN("no driver\n");
683 return DSERR_NODRIVER;
686 for (wod=0; wod<wodn; wod++) {
687 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
688 found = TRUE;
689 break;
693 if (found == FALSE) {
694 WARN("No device found matching given ID!\n");
695 return DSERR_NODRIVER;
698 if (DSOUND_renderer[wod]) {
699 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
700 device = DSOUND_renderer[wod];
701 DirectSoundDevice_AddRef(device);
702 This->device = device;
703 return DS_OK;
704 } else {
705 ERR("device GUID doesn't match\n");
706 hr = DSERR_GENERIC;
707 return hr;
709 } else {
710 hr = DirectSoundDevice_Create(&(device));
711 if (hr != DS_OK) {
712 WARN("DirectSoundDevice_Create failed\n");
713 return hr;
717 This->device = device;
718 device->guid = devGUID;
720 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
721 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
723 /* Disable the direct sound driver to force emulation if requested. */
724 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
725 device->driver = NULL;
727 /* Get driver description */
728 if (device->driver) {
729 hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
730 if (hr != DS_OK) {
731 WARN("IDsDriver_GetDriverDesc failed\n");
732 return hr;
734 } else {
735 /* if no DirectSound interface available, use WINMM API instead */
736 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
739 device->drvdesc.dnDevNode = wod;
741 /* If the driver requests being opened through MMSYSTEM
742 * (which is recommended by the DDK), it is supposed to happen
743 * before the DirectSound interface is opened */
744 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
746 DWORD flags = CALLBACK_FUNCTION;
748 /* disable direct sound if requested */
749 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
750 flags |= WAVE_DIRECTSOUND;
752 hr = mmErr(waveOutOpen(&(device->hwo),
753 device->drvdesc.dnDevNode, device->pwfx,
754 (DWORD_PTR)DSOUND_callback, (DWORD)device,
755 flags));
756 if (hr != DS_OK) {
757 WARN("waveOutOpen failed\n");
758 return hr;
762 if (device->driver) {
763 hr = IDsDriver_Open(device->driver);
764 if (hr != DS_OK) {
765 WARN("IDsDriver_Open failed\n");
766 return hr;
769 /* the driver is now open, so it's now allowed to call GetCaps */
770 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
771 if (hr != DS_OK) {
772 WARN("IDsDriver_GetCaps failed\n");
773 return hr;
775 } else {
776 WAVEOUTCAPSA woc;
777 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
778 if (hr != DS_OK) {
779 WARN("waveOutGetDevCaps failed\n");
780 return hr;
782 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
783 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
784 (woc.dwFormats & WAVE_FORMAT_2M08) ||
785 (woc.dwFormats & WAVE_FORMAT_4M08) ||
786 (woc.dwFormats & WAVE_FORMAT_48M08) ||
787 (woc.dwFormats & WAVE_FORMAT_96M08)) {
788 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
789 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
791 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
792 (woc.dwFormats & WAVE_FORMAT_2M16) ||
793 (woc.dwFormats & WAVE_FORMAT_4M16) ||
794 (woc.dwFormats & WAVE_FORMAT_48M16) ||
795 (woc.dwFormats & WAVE_FORMAT_96M16)) {
796 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
797 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
799 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
800 (woc.dwFormats & WAVE_FORMAT_2S08) ||
801 (woc.dwFormats & WAVE_FORMAT_4S08) ||
802 (woc.dwFormats & WAVE_FORMAT_48S08) ||
803 (woc.dwFormats & WAVE_FORMAT_96S08)) {
804 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
805 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
807 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
808 (woc.dwFormats & WAVE_FORMAT_2S16) ||
809 (woc.dwFormats & WAVE_FORMAT_4S16) ||
810 (woc.dwFormats & WAVE_FORMAT_48S16) ||
811 (woc.dwFormats & WAVE_FORMAT_96S16)) {
812 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
813 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
815 if (ds_emuldriver)
816 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
817 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
818 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
819 device->drvcaps.dwPrimaryBuffers = 1;
822 hr = DSOUND_PrimaryCreate(device);
823 if (hr == DS_OK) {
824 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
825 timeBeginPeriod(DS_TIME_RES);
826 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
827 (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
828 } else {
829 WARN("DSOUND_PrimaryCreate failed\n");
832 return hr;
835 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
836 LPDIRECTSOUND8 iface,
837 LPDWORD pdwCertified)
839 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
840 TRACE("(%p, %p)\n",This,pdwCertified);
842 if (This->device == NULL) {
843 WARN("not initialized\n");
844 return DSERR_UNINITIALIZED;
847 if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
848 *pdwCertified = DS_CERTIFIED;
849 else
850 *pdwCertified = DS_UNCERTIFIED;
851 return DS_OK;
854 static const IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
856 IDirectSoundImpl_QueryInterface,
857 IDirectSoundImpl_AddRef,
858 IDirectSoundImpl_Release,
859 IDirectSoundImpl_CreateSoundBuffer,
860 IDirectSoundImpl_GetCaps,
861 IDirectSoundImpl_DuplicateSoundBuffer,
862 IDirectSoundImpl_SetCooperativeLevel,
863 IDirectSoundImpl_Compact,
864 IDirectSoundImpl_GetSpeakerConfig,
865 IDirectSoundImpl_SetSpeakerConfig,
866 IDirectSoundImpl_Initialize,
867 IDirectSoundImpl_VerifyCertification
870 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
872 DirectSoundDevice * device;
873 TRACE("(%p)\n", ppDevice);
875 /* Allocate memory */
876 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
877 if (device == NULL) {
878 WARN("out of memory\n");
879 return DSERR_OUTOFMEMORY;
882 device->ref = 1;
883 device->driver = NULL;
884 device->priolevel = DSSCL_NORMAL;
885 device->fraglen = 0;
886 device->hwbuf = NULL;
887 device->buffer = NULL;
888 device->buflen = 0;
889 device->writelead = 0;
890 device->state = STATE_STOPPED;
891 device->nrofbuffers = 0;
892 device->buffers = NULL;
893 device->primary = NULL;
894 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
895 device->tmp_buffer = NULL;
896 device->tmp_buffer_len = 0;
898 /* 3D listener initial parameters */
899 device->listener = NULL;
900 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
901 device->ds3dl.vPosition.x = 0.0;
902 device->ds3dl.vPosition.y = 0.0;
903 device->ds3dl.vPosition.z = 0.0;
904 device->ds3dl.vVelocity.x = 0.0;
905 device->ds3dl.vVelocity.y = 0.0;
906 device->ds3dl.vVelocity.z = 0.0;
907 device->ds3dl.vOrientFront.x = 0.0;
908 device->ds3dl.vOrientFront.y = 0.0;
909 device->ds3dl.vOrientFront.z = 1.0;
910 device->ds3dl.vOrientTop.x = 0.0;
911 device->ds3dl.vOrientTop.y = 1.0;
912 device->ds3dl.vOrientTop.z = 0.0;
913 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
914 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
915 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
917 device->prebuf = ds_snd_queue_max;
918 device->guid = GUID_NULL;
920 /* Set default wave format (may need it for waveOutOpen) */
921 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
922 if (device->pwfx == NULL) {
923 WARN("out of memory\n");
924 HeapFree(GetProcessHeap(),0,device);
925 return DSERR_OUTOFMEMORY;
928 /* We rely on the sound driver to return the actual sound format of
929 * the device if it does not support 22050x8x2 and is given the
930 * WAVE_DIRECTSOUND flag.
932 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
933 device->pwfx->nSamplesPerSec = 22050;
934 device->pwfx->wBitsPerSample = 8;
935 device->pwfx->nChannels = 2;
936 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
937 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
938 device->pwfx->cbSize = 0;
940 InitializeCriticalSection(&(device->mixlock));
941 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock";
943 RtlInitializeResource(&(device->buffer_list_lock));
945 *ppDevice = device;
947 return DS_OK;
950 static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
952 ULONG ref = InterlockedIncrement(&(device->ref));
953 TRACE("(%p) ref was %ld\n", device, ref - 1);
954 return ref;
957 static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
959 HRESULT hr;
960 ULONG ref = InterlockedDecrement(&(device->ref));
961 TRACE("(%p) ref was %lu\n", device, ref + 1);
962 if (!ref) {
963 int i;
964 timeKillEvent(device->timerID);
965 timeEndPeriod(DS_TIME_RES);
966 /* wait for timer to expire */
967 Sleep(DS_TIME_RES+1);
969 /* The sleep above should have allowed the timer process to expire
970 * but try to grab the lock just in case. Can't hold lock because
971 * IDirectSoundBufferImpl_Destroy also grabs the lock */
972 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
973 RtlReleaseResource(&(device->buffer_list_lock));
975 /* It is allowed to release this object even when buffers are playing */
976 if (device->buffers) {
977 WARN("%d secondary buffers not released\n", device->nrofbuffers);
978 for( i=0;i<device->nrofbuffers;i++)
979 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
982 if (device->primary) {
983 WARN("primary buffer not released\n");
984 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
987 hr = DSOUND_PrimaryDestroy(device);
988 if (hr != DS_OK)
989 WARN("DSOUND_PrimaryDestroy failed\n");
991 if (device->driver)
992 IDsDriver_Close(device->driver);
994 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
995 waveOutClose(device->hwo);
997 if (device->driver)
998 IDsDriver_Release(device->driver);
1000 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
1002 HeapFree(GetProcessHeap(),0,device->tmp_buffer);
1003 HeapFree(GetProcessHeap(),0,device->buffer);
1004 RtlDeleteResource(&device->buffer_list_lock);
1005 device->mixlock.DebugInfo->Spare[0] = 0;
1006 DeleteCriticalSection(&device->mixlock);
1007 HeapFree(GetProcessHeap(),0,device);
1008 TRACE("(%p) released\n", device);
1010 return ref;
1013 HRESULT WINAPI IDirectSoundImpl_Create(
1014 LPDIRECTSOUND8 * ppDS)
1016 IDirectSoundImpl* pDS;
1017 TRACE("(%p)\n",ppDS);
1019 /* Allocate memory */
1020 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
1021 if (pDS == NULL) {
1022 WARN("out of memory\n");
1023 *ppDS = NULL;
1024 return DSERR_OUTOFMEMORY;
1027 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
1028 pDS->ref = 0;
1029 pDS->device = NULL;
1031 *ppDS = (LPDIRECTSOUND8)pDS;
1033 return DS_OK;
1036 /*******************************************************************************
1037 * IDirectSound_IUnknown
1039 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
1040 LPUNKNOWN iface,
1041 REFIID riid,
1042 LPVOID * ppobj)
1044 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1045 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1046 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1049 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
1050 LPUNKNOWN iface)
1052 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1053 ULONG ref = InterlockedIncrement(&(This->ref));
1054 TRACE("(%p) ref was %ld\n", This, ref - 1);
1055 return ref;
1058 static ULONG WINAPI IDirectSound_IUnknown_Release(
1059 LPUNKNOWN iface)
1061 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1062 ULONG ref = InterlockedDecrement(&(This->ref));
1063 TRACE("(%p) ref was %ld\n", This, ref + 1);
1064 if (!ref) {
1065 IDirectSoundImpl_Release(This->pds);
1066 HeapFree(GetProcessHeap(), 0, This);
1067 TRACE("(%p) released\n", This);
1069 return ref;
1072 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
1074 IDirectSound_IUnknown_QueryInterface,
1075 IDirectSound_IUnknown_AddRef,
1076 IDirectSound_IUnknown_Release
1079 HRESULT WINAPI IDirectSound_IUnknown_Create(
1080 LPDIRECTSOUND8 pds,
1081 LPUNKNOWN * ppunk)
1083 IDirectSound_IUnknown * pdsunk;
1084 TRACE("(%p,%p)\n",pds,ppunk);
1086 if (ppunk == NULL) {
1087 ERR("invalid parameter: ppunk == NULL\n");
1088 return DSERR_INVALIDPARAM;
1091 if (pds == NULL) {
1092 ERR("invalid parameter: pds == NULL\n");
1093 *ppunk = NULL;
1094 return DSERR_INVALIDPARAM;
1097 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1098 if (pdsunk == NULL) {
1099 WARN("out of memory\n");
1100 *ppunk = NULL;
1101 return DSERR_OUTOFMEMORY;
1104 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1105 pdsunk->ref = 0;
1106 pdsunk->pds = pds;
1108 IDirectSoundImpl_AddRef(pds);
1109 *ppunk = (LPUNKNOWN)pdsunk;
1111 return DS_OK;
1114 /*******************************************************************************
1115 * IDirectSound_IDirectSound
1117 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1118 LPDIRECTSOUND iface,
1119 REFIID riid,
1120 LPVOID * ppobj)
1122 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1123 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1124 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1127 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1128 LPDIRECTSOUND iface)
1130 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1131 ULONG ref = InterlockedIncrement(&(This->ref));
1132 TRACE("(%p) ref was %ld\n", This, ref - 1);
1133 return ref;
1136 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1137 LPDIRECTSOUND iface)
1139 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1140 ULONG ref = InterlockedDecrement(&(This->ref));
1141 TRACE("(%p) ref was %ld\n", This, ref + 1);
1142 if (!ref) {
1143 IDirectSoundImpl_Release(This->pds);
1144 HeapFree(GetProcessHeap(), 0, This);
1145 TRACE("(%p) released\n", This);
1147 return ref;
1150 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1151 LPDIRECTSOUND iface,
1152 LPCDSBUFFERDESC dsbd,
1153 LPLPDIRECTSOUNDBUFFER ppdsb,
1154 LPUNKNOWN lpunk)
1156 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1157 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1158 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1161 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1162 LPDIRECTSOUND iface,
1163 LPDSCAPS lpDSCaps)
1165 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1166 TRACE("(%p,%p)\n",This,lpDSCaps);
1167 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1170 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1171 LPDIRECTSOUND iface,
1172 LPDIRECTSOUNDBUFFER psb,
1173 LPLPDIRECTSOUNDBUFFER ppdsb)
1175 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1176 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1177 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1180 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1181 LPDIRECTSOUND iface,
1182 HWND hwnd,
1183 DWORD level)
1185 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1186 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1187 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1190 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1191 LPDIRECTSOUND iface)
1193 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1194 TRACE("(%p)\n", This);
1195 return IDirectSoundImpl_Compact(This->pds);
1198 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1199 LPDIRECTSOUND iface,
1200 LPDWORD lpdwSpeakerConfig)
1202 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1203 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1204 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1207 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1208 LPDIRECTSOUND iface,
1209 DWORD config)
1211 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1212 TRACE("(%p,0x%08lx)\n",This,config);
1213 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1216 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1217 LPDIRECTSOUND iface,
1218 LPCGUID lpcGuid)
1220 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1221 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1222 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1225 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1227 IDirectSound_IDirectSound_QueryInterface,
1228 IDirectSound_IDirectSound_AddRef,
1229 IDirectSound_IDirectSound_Release,
1230 IDirectSound_IDirectSound_CreateSoundBuffer,
1231 IDirectSound_IDirectSound_GetCaps,
1232 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1233 IDirectSound_IDirectSound_SetCooperativeLevel,
1234 IDirectSound_IDirectSound_Compact,
1235 IDirectSound_IDirectSound_GetSpeakerConfig,
1236 IDirectSound_IDirectSound_SetSpeakerConfig,
1237 IDirectSound_IDirectSound_Initialize
1240 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1241 LPDIRECTSOUND8 pds,
1242 LPDIRECTSOUND * ppds)
1244 IDirectSound_IDirectSound * pdsds;
1245 TRACE("(%p,%p)\n",pds,ppds);
1247 if (ppds == NULL) {
1248 ERR("invalid parameter: ppds == NULL\n");
1249 return DSERR_INVALIDPARAM;
1252 if (pds == NULL) {
1253 ERR("invalid parameter: pds == NULL\n");
1254 *ppds = NULL;
1255 return DSERR_INVALIDPARAM;
1258 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1259 if (pdsds == NULL) {
1260 WARN("out of memory\n");
1261 *ppds = NULL;
1262 return DSERR_OUTOFMEMORY;
1265 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1266 pdsds->ref = 0;
1267 pdsds->pds = pds;
1269 IDirectSoundImpl_AddRef(pds);
1270 *ppds = (LPDIRECTSOUND)pdsds;
1272 return DS_OK;
1275 /*******************************************************************************
1276 * IDirectSound8_IUnknown
1278 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1279 LPUNKNOWN iface,
1280 REFIID riid,
1281 LPVOID * ppobj)
1283 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1284 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1285 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1288 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1289 LPUNKNOWN iface)
1291 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1292 ULONG ref = InterlockedIncrement(&(This->ref));
1293 TRACE("(%p) ref was %ld\n", This, ref - 1);
1294 return ref;
1297 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1298 LPUNKNOWN iface)
1300 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1301 ULONG ref = InterlockedDecrement(&(This->ref));
1302 TRACE("(%p) ref was %ld\n", This, ref + 1);
1303 if (!ref) {
1304 IDirectSoundImpl_Release(This->pds);
1305 HeapFree(GetProcessHeap(), 0, This);
1306 TRACE("(%p) released\n", This);
1308 return ref;
1311 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
1313 IDirectSound8_IUnknown_QueryInterface,
1314 IDirectSound8_IUnknown_AddRef,
1315 IDirectSound8_IUnknown_Release
1318 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1319 LPDIRECTSOUND8 pds,
1320 LPUNKNOWN * ppunk)
1322 IDirectSound8_IUnknown * pdsunk;
1323 TRACE("(%p,%p)\n",pds,ppunk);
1325 if (ppunk == NULL) {
1326 ERR("invalid parameter: ppunk == NULL\n");
1327 return DSERR_INVALIDPARAM;
1330 if (pds == NULL) {
1331 ERR("invalid parameter: pds == NULL\n");
1332 *ppunk = NULL;
1333 return DSERR_INVALIDPARAM;
1336 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1337 if (pdsunk == NULL) {
1338 WARN("out of memory\n");
1339 *ppunk = NULL;
1340 return DSERR_OUTOFMEMORY;
1343 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1344 pdsunk->ref = 0;
1345 pdsunk->pds = pds;
1347 IDirectSoundImpl_AddRef(pds);
1348 *ppunk = (LPUNKNOWN)pdsunk;
1350 return DS_OK;
1353 /*******************************************************************************
1354 * IDirectSound8_IDirectSound
1356 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1357 LPDIRECTSOUND iface,
1358 REFIID riid,
1359 LPVOID * ppobj)
1361 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1362 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1363 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1366 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1367 LPDIRECTSOUND iface)
1369 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1370 ULONG ref = InterlockedIncrement(&(This->ref));
1371 TRACE("(%p) ref was %ld\n", This, ref - 1);
1372 return ref;
1375 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1376 LPDIRECTSOUND iface)
1378 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1379 ULONG ref = InterlockedDecrement(&(This->ref));
1380 TRACE("(%p) ref was %ld\n", This, ref + 1);
1381 if (!ref) {
1382 IDirectSoundImpl_Release(This->pds);
1383 HeapFree(GetProcessHeap(), 0, This);
1384 TRACE("(%p) released\n", This);
1386 return ref;
1389 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1390 LPDIRECTSOUND iface,
1391 LPCDSBUFFERDESC dsbd,
1392 LPLPDIRECTSOUNDBUFFER ppdsb,
1393 LPUNKNOWN lpunk)
1395 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1396 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1397 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1400 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1401 LPDIRECTSOUND iface,
1402 LPDSCAPS lpDSCaps)
1404 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1405 TRACE("(%p,%p)\n",This,lpDSCaps);
1406 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1409 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1410 LPDIRECTSOUND iface,
1411 LPDIRECTSOUNDBUFFER psb,
1412 LPLPDIRECTSOUNDBUFFER ppdsb)
1414 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1415 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1416 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1419 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1420 LPDIRECTSOUND iface,
1421 HWND hwnd,
1422 DWORD level)
1424 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1425 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1426 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1429 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1430 LPDIRECTSOUND iface)
1432 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1433 TRACE("(%p)\n", This);
1434 return IDirectSoundImpl_Compact(This->pds);
1437 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1438 LPDIRECTSOUND iface,
1439 LPDWORD lpdwSpeakerConfig)
1441 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1442 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1443 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1446 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1447 LPDIRECTSOUND iface,
1448 DWORD config)
1450 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1451 TRACE("(%p,0x%08lx)\n",This,config);
1452 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1455 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1456 LPDIRECTSOUND iface,
1457 LPCGUID lpcGuid)
1459 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1460 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1461 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1464 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1466 IDirectSound8_IDirectSound_QueryInterface,
1467 IDirectSound8_IDirectSound_AddRef,
1468 IDirectSound8_IDirectSound_Release,
1469 IDirectSound8_IDirectSound_CreateSoundBuffer,
1470 IDirectSound8_IDirectSound_GetCaps,
1471 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1472 IDirectSound8_IDirectSound_SetCooperativeLevel,
1473 IDirectSound8_IDirectSound_Compact,
1474 IDirectSound8_IDirectSound_GetSpeakerConfig,
1475 IDirectSound8_IDirectSound_SetSpeakerConfig,
1476 IDirectSound8_IDirectSound_Initialize
1479 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1480 LPDIRECTSOUND8 pds,
1481 LPDIRECTSOUND * ppds)
1483 IDirectSound8_IDirectSound * pdsds;
1484 TRACE("(%p,%p)\n",pds,ppds);
1486 if (ppds == NULL) {
1487 ERR("invalid parameter: ppds == NULL\n");
1488 return DSERR_INVALIDPARAM;
1491 if (pds == NULL) {
1492 ERR("invalid parameter: pds == NULL\n");
1493 *ppds = NULL;
1494 return DSERR_INVALIDPARAM;
1497 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1498 if (pdsds == NULL) {
1499 WARN("out of memory\n");
1500 *ppds = NULL;
1501 return DSERR_OUTOFMEMORY;
1504 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1505 pdsds->ref = 0;
1506 pdsds->pds = pds;
1508 IDirectSoundImpl_AddRef(pds);
1509 *ppds = (LPDIRECTSOUND)pdsds;
1511 return DS_OK;
1514 /*******************************************************************************
1515 * IDirectSound8_IDirectSound8
1517 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1518 LPDIRECTSOUND8 iface,
1519 REFIID riid,
1520 LPVOID * ppobj)
1522 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1523 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1524 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1527 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1528 LPDIRECTSOUND8 iface)
1530 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1531 ULONG ref = InterlockedIncrement(&(This->ref));
1532 TRACE("(%p) ref was %ld\n", This, ref - 1);
1533 return ref;
1536 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1537 LPDIRECTSOUND8 iface)
1539 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1540 ULONG ref = InterlockedDecrement(&(This->ref));
1541 TRACE("(%p) ref was %ld\n", This, ref + 1);
1542 if (!ref) {
1543 IDirectSoundImpl_Release(This->pds);
1544 HeapFree(GetProcessHeap(), 0, This);
1545 TRACE("(%p) released\n", This);
1547 return ref;
1550 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1551 LPDIRECTSOUND8 iface,
1552 LPCDSBUFFERDESC dsbd,
1553 LPLPDIRECTSOUNDBUFFER ppdsb,
1554 LPUNKNOWN lpunk)
1556 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1557 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1558 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1561 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1562 LPDIRECTSOUND8 iface,
1563 LPDSCAPS lpDSCaps)
1565 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1566 TRACE("(%p,%p)\n",This,lpDSCaps);
1567 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1570 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1571 LPDIRECTSOUND8 iface,
1572 LPDIRECTSOUNDBUFFER psb,
1573 LPLPDIRECTSOUNDBUFFER ppdsb)
1575 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1576 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1577 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1580 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1581 LPDIRECTSOUND8 iface,
1582 HWND hwnd,
1583 DWORD level)
1585 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1586 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1587 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1590 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1591 LPDIRECTSOUND8 iface)
1593 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1594 TRACE("(%p)\n", This);
1595 return IDirectSoundImpl_Compact(This->pds);
1598 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1599 LPDIRECTSOUND8 iface,
1600 LPDWORD lpdwSpeakerConfig)
1602 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1603 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1604 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1607 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1608 LPDIRECTSOUND8 iface,
1609 DWORD config)
1611 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1612 TRACE("(%p,0x%08lx)\n",This,config);
1613 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1616 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1617 LPDIRECTSOUND8 iface,
1618 LPCGUID lpcGuid)
1620 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1621 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1622 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1625 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1626 LPDIRECTSOUND8 iface,
1627 LPDWORD pdwCertified)
1629 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1630 TRACE("(%p, %p)\n", This, pdwCertified);
1631 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1634 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1636 IDirectSound8_IDirectSound8_QueryInterface,
1637 IDirectSound8_IDirectSound8_AddRef,
1638 IDirectSound8_IDirectSound8_Release,
1639 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1640 IDirectSound8_IDirectSound8_GetCaps,
1641 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1642 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1643 IDirectSound8_IDirectSound8_Compact,
1644 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1645 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1646 IDirectSound8_IDirectSound8_Initialize,
1647 IDirectSound8_IDirectSound8_VerifyCertification
1650 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1651 LPDIRECTSOUND8 pds,
1652 LPDIRECTSOUND8 * ppds)
1654 IDirectSound8_IDirectSound8 * pdsds;
1655 TRACE("(%p,%p)\n",pds,ppds);
1657 if (ppds == NULL) {
1658 ERR("invalid parameter: ppds == NULL\n");
1659 return DSERR_INVALIDPARAM;
1662 if (pds == NULL) {
1663 ERR("invalid parameter: pds == NULL\n");
1664 *ppds = NULL;
1665 return DSERR_INVALIDPARAM;
1668 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1669 if (pdsds == NULL) {
1670 WARN("out of memory\n");
1671 *ppds = NULL;
1672 return DSERR_OUTOFMEMORY;
1675 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1676 pdsds->ref = 0;
1677 pdsds->pds = pds;
1679 IDirectSoundImpl_AddRef(pds);
1680 *ppds = (LPDIRECTSOUND8)pdsds;
1682 return DS_OK;
1685 HRESULT WINAPI DSOUND_Create(
1686 LPDIRECTSOUND *ppDS,
1687 IUnknown *pUnkOuter)
1689 LPDIRECTSOUND8 pDS;
1690 HRESULT hr;
1691 TRACE("(%p,%p)\n",ppDS,pUnkOuter);
1693 /* Get dsound configuration */
1694 setup_dsound_options();
1696 hr = IDirectSoundImpl_Create(&pDS);
1697 if (hr == DS_OK) {
1698 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1699 if (*ppDS)
1700 IDirectSound_IDirectSound_AddRef(*ppDS);
1701 else {
1702 WARN("IDirectSound_IDirectSound_Create failed\n");
1703 IDirectSound8_Release(pDS);
1705 } else {
1706 WARN("IDirectSoundImpl_Create failed\n");
1707 *ppDS = 0;
1710 return hr;
1713 /*******************************************************************************
1714 * DirectSoundCreate (DSOUND.1)
1716 * Creates and initializes a DirectSound interface.
1718 * PARAMS
1719 * lpcGUID [I] Address of the GUID that identifies the sound device.
1720 * ppDS [O] Address of a variable to receive the interface pointer.
1721 * pUnkOuter [I] Must be NULL.
1723 * RETURNS
1724 * Success: DS_OK
1725 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1726 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1728 HRESULT WINAPI DirectSoundCreate(
1729 LPCGUID lpcGUID,
1730 LPDIRECTSOUND *ppDS,
1731 IUnknown *pUnkOuter)
1733 HRESULT hr;
1734 LPDIRECTSOUND pDS;
1736 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1738 if (ppDS == NULL) {
1739 WARN("invalid parameter: ppDS == NULL\n");
1740 return DSERR_INVALIDPARAM;
1743 if (pUnkOuter != NULL) {
1744 WARN("invalid parameter: pUnkOuter != NULL\n");
1745 *ppDS = 0;
1746 return DSERR_INVALIDPARAM;
1749 hr = DSOUND_Create(&pDS, pUnkOuter);
1750 if (hr == DS_OK) {
1751 hr = IDirectSound_Initialize(pDS, lpcGUID);
1752 if (hr != DS_OK) {
1753 if (hr != DSERR_ALREADYINITIALIZED) {
1754 IDirectSound_Release(pDS);
1755 pDS = 0;
1756 } else
1757 hr = DS_OK;
1761 *ppDS = pDS;
1763 return hr;
1766 HRESULT WINAPI DSOUND_Create8(
1767 LPDIRECTSOUND8 *ppDS,
1768 IUnknown *pUnkOuter)
1770 LPDIRECTSOUND8 pDS;
1771 HRESULT hr;
1772 TRACE("(%p,%p)\n",ppDS,pUnkOuter);
1774 /* Get dsound configuration */
1775 setup_dsound_options();
1777 hr = IDirectSoundImpl_Create(&pDS);
1778 if (hr == DS_OK) {
1779 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1780 if (*ppDS)
1781 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1782 else {
1783 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1784 IDirectSound8_Release(pDS);
1786 } else {
1787 WARN("IDirectSoundImpl_Create failed\n");
1788 *ppDS = 0;
1791 return hr;
1794 /*******************************************************************************
1795 * DirectSoundCreate8 (DSOUND.11)
1797 * Creates and initializes a DirectSound8 interface.
1799 * PARAMS
1800 * lpcGUID [I] Address of the GUID that identifies the sound device.
1801 * ppDS [O] Address of a variable to receive the interface pointer.
1802 * pUnkOuter [I] Must be NULL.
1804 * RETURNS
1805 * Success: DS_OK
1806 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1807 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1809 HRESULT WINAPI DirectSoundCreate8(
1810 LPCGUID lpcGUID,
1811 LPDIRECTSOUND8 *ppDS,
1812 IUnknown *pUnkOuter)
1814 HRESULT hr;
1815 LPDIRECTSOUND8 pDS;
1817 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1819 if (ppDS == NULL) {
1820 WARN("invalid parameter: ppDS == NULL\n");
1821 return DSERR_INVALIDPARAM;
1824 if (pUnkOuter != NULL) {
1825 WARN("invalid parameter: pUnkOuter != NULL\n");
1826 *ppDS = 0;
1827 return DSERR_INVALIDPARAM;
1830 hr = DSOUND_Create8(&pDS, pUnkOuter);
1831 if (hr == DS_OK) {
1832 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1833 if (hr != DS_OK) {
1834 if (hr != DSERR_ALREADYINITIALIZED) {
1835 IDirectSound8_Release(pDS);
1836 pDS = 0;
1837 } else
1838 hr = DS_OK;
1842 *ppDS = pDS;
1844 return hr;
1848 * Add secondary buffer to buffer list.
1849 * Gets exclusive access to buffer for writing.
1851 HRESULT DSOUND_AddBuffer(
1852 IDirectSoundImpl * pDS,
1853 IDirectSoundBufferImpl * pDSB)
1855 IDirectSoundBufferImpl **newbuffers;
1856 HRESULT hr = DS_OK;
1858 TRACE("(%p, %p)\n", pDS, pDSB);
1860 RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
1862 if (pDS->device->buffers)
1863 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
1864 else
1865 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
1867 if (newbuffers) {
1868 pDS->device->buffers = newbuffers;
1869 pDS->device->buffers[pDS->device->nrofbuffers] = pDSB;
1870 pDS->device->nrofbuffers++;
1871 TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
1872 } else {
1873 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->device->nrofbuffers);
1874 hr = DSERR_OUTOFMEMORY;
1877 RtlReleaseResource(&(pDS->device->buffer_list_lock));
1879 return hr;
1883 * Remove secondary buffer from buffer list.
1884 * Gets exclusive access to buffer for writing.
1886 HRESULT DSOUND_RemoveBuffer(
1887 IDirectSoundImpl * pDS,
1888 IDirectSoundBufferImpl * pDSB)
1890 int i;
1891 HRESULT hr = DS_OK;
1893 TRACE("(%p, %p)\n", pDS, pDSB);
1895 RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
1897 for (i = 0; i < pDS->device->nrofbuffers; i++)
1898 if (pDS->device->buffers[i] == pDSB)
1899 break;
1901 if (i < pDS->device->nrofbuffers) {
1902 /* Put the last buffer of the list in the (now empty) position */
1903 pDS->device->buffers[i] = pDS->device->buffers[pDS->device->nrofbuffers - 1];
1904 pDS->device->nrofbuffers--;
1905 pDS->device->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->device->nrofbuffers);
1906 TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
1909 if (pDS->device->nrofbuffers == 0) {
1910 HeapFree(GetProcessHeap(),0,pDS->device->buffers);
1911 pDS->device->buffers = NULL;
1914 RtlReleaseResource(&(pDS->device->buffer_list_lock));
1916 return hr;