Added YUV routines needed for v4l driver, and in the future possibly
[wine/gsoc-2012-control.git] / dlls / dsound / dsound.c
blob698de37246ce8b6454534be4b5896b50716ed1bd
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 "winreg.h"
31 #include "mmsystem.h"
32 #include "winternl.h"
33 #include "mmddk.h"
34 #include "wine/debug.h"
35 #include "dsound.h"
36 #include "dsdriver.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
41 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
42 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
43 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
44 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
45 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
47 static const char * dumpCooperativeLevel(DWORD level)
49 static char unknown[32];
50 #define LE(x) case x: return #x
51 switch (level) {
52 LE(DSSCL_NORMAL);
53 LE(DSSCL_PRIORITY);
54 LE(DSSCL_EXCLUSIVE);
55 LE(DSSCL_WRITEPRIMARY);
57 #undef LE
58 sprintf(unknown, "Unknown(%08lx)", level);
59 return unknown;
62 static void _dump_DSCAPS(DWORD xmask) {
63 struct {
64 DWORD mask;
65 char *name;
66 } flags[] = {
67 #define FE(x) { x, #x },
68 FE(DSCAPS_PRIMARYMONO)
69 FE(DSCAPS_PRIMARYSTEREO)
70 FE(DSCAPS_PRIMARY8BIT)
71 FE(DSCAPS_PRIMARY16BIT)
72 FE(DSCAPS_CONTINUOUSRATE)
73 FE(DSCAPS_EMULDRIVER)
74 FE(DSCAPS_CERTIFIED)
75 FE(DSCAPS_SECONDARYMONO)
76 FE(DSCAPS_SECONDARYSTEREO)
77 FE(DSCAPS_SECONDARY8BIT)
78 FE(DSCAPS_SECONDARY16BIT)
79 #undef FE
81 unsigned int i;
83 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
84 if ((flags[i].mask & xmask) == flags[i].mask)
85 DPRINTF("%s ",flags[i].name);
88 static void _dump_DSBCAPS(DWORD xmask) {
89 struct {
90 DWORD mask;
91 char *name;
92 } flags[] = {
93 #define FE(x) { x, #x },
94 FE(DSBCAPS_PRIMARYBUFFER)
95 FE(DSBCAPS_STATIC)
96 FE(DSBCAPS_LOCHARDWARE)
97 FE(DSBCAPS_LOCSOFTWARE)
98 FE(DSBCAPS_CTRL3D)
99 FE(DSBCAPS_CTRLFREQUENCY)
100 FE(DSBCAPS_CTRLPAN)
101 FE(DSBCAPS_CTRLVOLUME)
102 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
103 FE(DSBCAPS_STICKYFOCUS)
104 FE(DSBCAPS_GLOBALFOCUS)
105 FE(DSBCAPS_GETCURRENTPOSITION2)
106 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
107 #undef FE
109 unsigned int i;
111 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
112 if ((flags[i].mask & xmask) == flags[i].mask)
113 DPRINTF("%s ",flags[i].name);
116 /*******************************************************************************
117 * IDirectSoundImpl_DirectSound
119 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
120 LPDIRECTSOUND8 iface,
121 REFIID riid,
122 LPVOID * ppobj)
124 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
125 FIXME("shouldn't be called directly\n");
126 return E_NOINTERFACE;
129 static HRESULT WINAPI DSOUND_QueryInterface(
130 LPDIRECTSOUND8 iface,
131 REFIID riid,
132 LPVOID * ppobj)
134 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
135 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
137 if (ppobj == NULL) {
138 WARN("invalid parameter\n");
139 return E_INVALIDARG;
142 if (IsEqualIID(riid, &IID_IUnknown)) {
143 if (!This->pUnknown) {
144 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
145 if (!This->pUnknown) {
146 WARN("IDirectSound_IUnknown_Create() failed\n");
147 *ppobj = NULL;
148 return E_NOINTERFACE;
151 IDirectSound_IUnknown_AddRef(This->pUnknown);
152 *ppobj = This->pUnknown;
153 return S_OK;
154 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
155 if (!This->pDS) {
156 IDirectSound_IDirectSound_Create(iface, &This->pDS);
157 if (!This->pDS) {
158 WARN("IDirectSound_IDirectSound_Create() failed\n");
159 *ppobj = NULL;
160 return E_NOINTERFACE;
163 IDirectSound_IDirectSound_AddRef(This->pDS);
164 *ppobj = This->pDS;
165 return S_OK;
168 *ppobj = NULL;
169 WARN("Unknown IID %s\n",debugstr_guid(riid));
170 return E_NOINTERFACE;
173 static HRESULT WINAPI DSOUND_QueryInterface8(
174 LPDIRECTSOUND8 iface,
175 REFIID riid,
176 LPVOID * ppobj)
178 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
179 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
181 if (ppobj == NULL) {
182 WARN("invalid parameter\n");
183 return E_INVALIDARG;
186 if (IsEqualIID(riid, &IID_IUnknown)) {
187 if (!This->pUnknown) {
188 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
189 if (!This->pUnknown) {
190 WARN("IDirectSound8_IUnknown_Create() failed\n");
191 *ppobj = NULL;
192 return E_NOINTERFACE;
195 IDirectSound8_IUnknown_AddRef(This->pUnknown);
196 *ppobj = This->pUnknown;
197 return S_OK;
198 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
199 if (!This->pDS) {
200 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
201 if (!This->pDS) {
202 WARN("IDirectSound8_IDirectSound_Create() failed\n");
203 *ppobj = NULL;
204 return E_NOINTERFACE;
207 IDirectSound8_IDirectSound_AddRef(This->pDS);
208 *ppobj = This->pDS;
209 return S_OK;
210 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
211 if (!This->pDS8) {
212 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
213 if (!This->pDS8) {
214 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
215 *ppobj = NULL;
216 return E_NOINTERFACE;
219 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
220 *ppobj = This->pDS8;
221 return S_OK;
224 *ppobj = NULL;
225 WARN("Unknown IID %s\n",debugstr_guid(riid));
226 return E_NOINTERFACE;
229 static ULONG WINAPI IDirectSoundImpl_AddRef(
230 LPDIRECTSOUND8 iface)
232 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
233 ULONG ref = InterlockedIncrement(&(This->ref));
234 TRACE("(%p) ref was %ld\n", This, ref - 1);
235 return ref;
238 static ULONG WINAPI IDirectSoundImpl_Release(
239 LPDIRECTSOUND8 iface)
241 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
242 ULONG ref = InterlockedDecrement(&(This->ref));
243 TRACE("(%p) ref was %ld\n", This, ref + 1);
245 if (!ref) {
246 HRESULT hres;
247 INT i;
249 timeKillEvent(This->timerID);
250 timeEndPeriod(DS_TIME_RES);
251 /* wait for timer to expire */
252 Sleep(DS_TIME_RES+1);
254 /* The sleep above should have allowed the timer process to expire
255 * but try to grab the lock just in case. Can't hold lock because
256 * IDirectSoundBufferImpl_Destroy also grabs the lock */
257 RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
258 RtlReleaseResource(&(This->buffer_list_lock));
260 /* It is allowed to release this object even when buffers are playing */
261 if (This->buffers) {
262 WARN("%d secondary buffers not released\n", This->nrofbuffers);
263 for( i=0;i<This->nrofbuffers;i++)
264 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
267 if (This->primary) {
268 WARN("primary buffer not released\n");
269 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
272 hres = DSOUND_PrimaryDestroy(This);
273 if (hres != DS_OK)
274 WARN("DSOUND_PrimaryDestroy failed\n");
276 if (This->driver)
277 IDsDriver_Close(This->driver);
279 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
280 waveOutClose(This->hwo);
282 if (This->driver)
283 IDsDriver_Release(This->driver);
285 HeapFree(GetProcessHeap(),0,This->tmp_buffer);
286 HeapFree(GetProcessHeap(),0,This->buffer);
287 RtlDeleteResource(&This->buffer_list_lock);
288 This->mixlock.DebugInfo->Spare[1] = 0;
289 DeleteCriticalSection(&This->mixlock);
290 HeapFree(GetProcessHeap(),0,This);
291 DSOUND_renderer = NULL;
292 TRACE("(%p) released\n", This);
294 return ref;
297 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
298 LPDIRECTSOUND8 iface,
299 LPCDSBUFFERDESC dsbd,
300 LPLPDIRECTSOUNDBUFFER ppdsb,
301 LPUNKNOWN lpunk)
303 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
304 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
305 FIXME("shouldn't be called directly\n");
306 return DSERR_GENERIC;
309 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
310 LPDIRECTSOUND8 iface,
311 LPCDSBUFFERDESC dsbd,
312 LPLPDIRECTSOUNDBUFFER ppdsb,
313 LPUNKNOWN lpunk,
314 BOOL from8)
316 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
317 HRESULT hres = DS_OK;
318 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
320 if (This == NULL) {
321 WARN("invalid parameter: This == NULL\n");
322 return DSERR_INVALIDPARAM;
325 if (This->initialized == FALSE) {
326 WARN("not initialized\n");
327 return DSERR_UNINITIALIZED;
330 if (dsbd == NULL) {
331 WARN("invalid parameter: dsbd == NULL\n");
332 return DSERR_INVALIDPARAM;
335 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
336 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
337 WARN("invalid parameter: dsbd\n");
338 return DSERR_INVALIDPARAM;
341 if (ppdsb == NULL) {
342 WARN("invalid parameter: ppdsb == NULL\n");
343 return DSERR_INVALIDPARAM;
346 if (TRACE_ON(dsound)) {
347 TRACE("(structsize=%ld)\n",dsbd->dwSize);
348 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
349 _dump_DSBCAPS(dsbd->dwFlags);
350 DPRINTF(")\n");
351 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
352 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
355 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
356 if (dsbd->lpwfxFormat != NULL) {
357 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
358 "primary buffer\n");
359 return DSERR_INVALIDPARAM;
362 if (This->primary) {
363 WARN("Primary Buffer already created\n");
364 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
365 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
366 } else {
367 This->dsbd = *dsbd;
368 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
369 if (This->primary) {
370 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
371 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
372 } else
373 WARN("PrimaryBufferImpl_Create failed\n");
375 } else {
376 IDirectSoundBufferImpl * dsb;
378 if (dsbd->lpwfxFormat == NULL) {
379 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
380 "secondary buffer\n");
381 return DSERR_INVALIDPARAM;
384 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
385 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
386 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
387 dsbd->lpwfxFormat->nSamplesPerSec,
388 dsbd->lpwfxFormat->nAvgBytesPerSec,
389 dsbd->lpwfxFormat->nBlockAlign,
390 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
392 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
393 WARN("invalid parameter: 3D buffer format must be mono\n");
394 return DSERR_INVALIDPARAM;
397 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
398 if (dsb) {
399 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
400 if (*ppdsb) {
401 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
402 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
403 } else
404 WARN("SecondaryBufferImpl_Create failed\n");
405 } else
406 WARN("IDirectSoundBufferImpl_Create failed\n");
409 return hres;
412 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
413 LPDIRECTSOUND8 iface,
414 LPDSCAPS lpDSCaps)
416 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
417 TRACE("(%p,%p)\n",This,lpDSCaps);
419 if (This == NULL) {
420 WARN("invalid parameter: This == NULL\n");
421 return DSERR_INVALIDPARAM;
424 if (This->initialized == FALSE) {
425 WARN("not initialized\n");
426 return DSERR_UNINITIALIZED;
429 if (lpDSCaps == NULL) {
430 WARN("invalid parameter: lpDSCaps = NULL\n");
431 return DSERR_INVALIDPARAM;
434 /* check if there is enough room */
435 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
436 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
437 lpDSCaps->dwSize, sizeof(*lpDSCaps));
438 return DSERR_INVALIDPARAM;
441 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
442 if (TRACE_ON(dsound)) {
443 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
444 _dump_DSCAPS(lpDSCaps->dwFlags);
445 DPRINTF(")\n");
447 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
448 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
449 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
450 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
451 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
452 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
453 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
454 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
455 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
456 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
457 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
458 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
459 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
460 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
461 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
462 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
463 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
464 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
466 /* driver doesn't have these */
467 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
468 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
470 return DS_OK;
473 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
474 LPDIRECTSOUND8 iface,
475 LPDIRECTSOUNDBUFFER psb,
476 LPLPDIRECTSOUNDBUFFER ppdsb)
478 IDirectSoundBufferImpl* pdsb;
479 IDirectSoundBufferImpl* dsb;
480 HRESULT hres = DS_OK;
481 int size;
482 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
484 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
486 if (This == NULL) {
487 WARN("invalid parameter: This == NULL\n");
488 return DSERR_INVALIDPARAM;
491 if (This->initialized == FALSE) {
492 WARN("not initialized\n");
493 return DSERR_UNINITIALIZED;
496 if (psb == NULL) {
497 WARN("invalid parameter: psb == NULL\n");
498 return DSERR_INVALIDPARAM;
501 if (ppdsb == NULL) {
502 WARN("invalid parameter: ppdsb == NULL\n");
503 return DSERR_INVALIDPARAM;
506 /* FIXME: hack to make sure we have a secondary buffer */
507 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
508 WARN("trying to duplicate primary buffer\n");
509 *ppdsb = NULL;
510 return DSERR_INVALIDCALL;
513 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
515 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
517 if (dsb == NULL) {
518 WARN("out of memory\n");
519 *ppdsb = NULL;
520 return DSERR_OUTOFMEMORY;
523 CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
525 if (pdsb->hwbuf) {
526 TRACE("duplicating hardware buffer\n");
528 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
529 if (hres != DS_OK) {
530 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
531 dsb->hwbuf = NULL;
532 /* allocate buffer */
533 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
534 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
535 if (dsb->buffer == NULL) {
536 WARN("out of memory\n");
537 HeapFree(GetProcessHeap(),0,dsb);
538 *ppdsb = NULL;
539 return DSERR_OUTOFMEMORY;
542 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
543 if (dsb->buffer->memory == NULL) {
544 WARN("out of memory\n");
545 HeapFree(GetProcessHeap(),0,dsb->buffer);
546 HeapFree(GetProcessHeap(),0,dsb);
547 *ppdsb = NULL;
548 return DSERR_OUTOFMEMORY;
550 dsb->buffer->ref = 1;
552 /* FIXME: copy buffer ? */
555 } else {
556 dsb->hwbuf = NULL;
557 dsb->buffer->ref++;
560 dsb->ref = 0;
561 dsb->state = STATE_STOPPED;
562 dsb->playpos = 0;
563 dsb->buf_mixpos = 0;
564 dsb->dsound = This;
565 dsb->ds3db = NULL;
566 dsb->iks = NULL; /* FIXME? */
567 dsb->dsb = NULL;
569 /* variable sized struct so calculate size based on format */
570 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
572 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
573 if (dsb->pwfx == NULL) {
574 WARN("out of memory\n");
575 HeapFree(GetProcessHeap(),0,dsb->buffer);
576 HeapFree(GetProcessHeap(),0,dsb);
577 *ppdsb = NULL;
578 return DSERR_OUTOFMEMORY;
581 CopyMemory(dsb->pwfx, pdsb->pwfx, size);
583 InitializeCriticalSection(&(dsb->lock));
584 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
586 /* register buffer */
587 hres = DSOUND_AddBuffer(This, dsb);
588 if (hres != DS_OK) {
589 IDirectSoundBuffer8_Release(psb);
590 dsb->lock.DebugInfo->Spare[1] = 0;
591 DeleteCriticalSection(&(dsb->lock));
592 HeapFree(GetProcessHeap(),0,dsb->buffer);
593 HeapFree(GetProcessHeap(),0,dsb->pwfx);
594 HeapFree(GetProcessHeap(),0,dsb);
595 *ppdsb = 0;
596 } else {
597 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
598 if (*ppdsb) {
599 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
600 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
601 } else
602 WARN("SecondaryBufferImpl_Create failed\n");
605 return hres;
608 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
609 LPDIRECTSOUND8 iface,
610 HWND hwnd,
611 DWORD level)
613 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
614 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
616 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
617 WARN("level=%s not fully supported\n",
618 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
620 This->priolevel = level;
621 return DS_OK;
624 static HRESULT WINAPI IDirectSoundImpl_Compact(
625 LPDIRECTSOUND8 iface)
627 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
628 TRACE("(%p)\n",This);
630 if (This->initialized == FALSE) {
631 WARN("not initialized\n");
632 return DSERR_UNINITIALIZED;
635 if (This->priolevel != DSSCL_PRIORITY) {
636 WARN("incorrect priority level\n");
637 return DSERR_PRIOLEVELNEEDED;
640 return DS_OK;
643 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
644 LPDIRECTSOUND8 iface,
645 LPDWORD lpdwSpeakerConfig)
647 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
648 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
650 if (This->initialized == FALSE) {
651 WARN("not initialized\n");
652 return DSERR_UNINITIALIZED;
655 if (lpdwSpeakerConfig == NULL) {
656 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
657 return DSERR_INVALIDPARAM;
660 WARN("not fully functional\n");
661 *lpdwSpeakerConfig = This->speaker_config;
662 return DS_OK;
665 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
666 LPDIRECTSOUND8 iface,
667 DWORD config)
669 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
670 TRACE("(%p,0x%08lx)\n",This,config);
672 if (This->initialized == FALSE) {
673 WARN("not initialized\n");
674 return DSERR_UNINITIALIZED;
677 This->speaker_config = config;
678 WARN("not fully functional\n");
679 return DS_OK;
682 static HRESULT WINAPI IDirectSoundImpl_Initialize(
683 LPDIRECTSOUND8 iface,
684 LPCGUID lpcGuid)
686 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
687 HRESULT hr = DS_OK;
688 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
690 if (This->initialized == TRUE) {
691 WARN("already initialized\n");
692 return DSERR_ALREADYINITIALIZED;
695 /* If the driver requests being opened through MMSYSTEM
696 * (which is recommended by the DDK), it is supposed to happen
697 * before the DirectSound interface is opened */
698 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
700 DWORD flags = CALLBACK_FUNCTION;
702 /* disable direct sound if requested */
703 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
704 flags |= WAVE_DIRECTSOUND;
706 hr = mmErr(waveOutOpen(&(This->hwo),
707 This->drvdesc.dnDevNode, This->pwfx,
708 (DWORD)DSOUND_callback, (DWORD)This,
709 flags));
710 if (hr != DS_OK) {
711 WARN("waveOutOpen failed\n");
712 return hr;
716 if (This->driver) {
717 hr = IDsDriver_Open(This->driver);
718 if (hr != DS_OK) {
719 WARN("IDsDriver_Open failed\n");
720 return hr;
723 /* the driver is now open, so it's now allowed to call GetCaps */
724 hr = IDsDriver_GetCaps(This->driver,&(This->drvcaps));
725 if (hr != DS_OK) {
726 WARN("IDsDriver_GetCaps failed\n");
727 return hr;
729 } else {
730 WAVEOUTCAPSA woc;
731 hr = mmErr(waveOutGetDevCapsA(This->drvdesc.dnDevNode, &woc, sizeof(woc)));
732 if (hr != DS_OK) {
733 WARN("waveOutGetDevCaps failed\n");
734 return hr;
736 ZeroMemory(&This->drvcaps, sizeof(This->drvcaps));
737 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
738 (woc.dwFormats & WAVE_FORMAT_2M08) ||
739 (woc.dwFormats & WAVE_FORMAT_4M08) ||
740 (woc.dwFormats & WAVE_FORMAT_48M08) ||
741 (woc.dwFormats & WAVE_FORMAT_96M08)) {
742 This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
743 This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
745 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
746 (woc.dwFormats & WAVE_FORMAT_2M16) ||
747 (woc.dwFormats & WAVE_FORMAT_4M16) ||
748 (woc.dwFormats & WAVE_FORMAT_48M16) ||
749 (woc.dwFormats & WAVE_FORMAT_96M16)) {
750 This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
751 This->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
753 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
754 (woc.dwFormats & WAVE_FORMAT_2S08) ||
755 (woc.dwFormats & WAVE_FORMAT_4S08) ||
756 (woc.dwFormats & WAVE_FORMAT_48S08) ||
757 (woc.dwFormats & WAVE_FORMAT_96S08)) {
758 This->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
759 This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
761 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
762 (woc.dwFormats & WAVE_FORMAT_2S16) ||
763 (woc.dwFormats & WAVE_FORMAT_4S16) ||
764 (woc.dwFormats & WAVE_FORMAT_48S16) ||
765 (woc.dwFormats & WAVE_FORMAT_96S16)) {
766 This->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
767 This->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
769 if (ds_emuldriver)
770 This->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
771 This->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
772 This->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
773 This->drvcaps.dwPrimaryBuffers = 1;
776 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)This);
777 if (hr == DS_OK) {
778 This->initialized = TRUE;
779 DSOUND_renderer = (IDirectSoundImpl*)This;
780 timeBeginPeriod(DS_TIME_RES);
781 DSOUND_renderer->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
782 (DWORD)DSOUND_renderer, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
783 } else {
784 WARN("DSOUND_PrimaryCreate failed\n");
787 return hr;
790 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
791 LPDIRECTSOUND8 iface,
792 LPDWORD pdwCertified)
794 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
795 TRACE("(%p, %p)\n",This,pdwCertified);
797 if (This->initialized == FALSE) {
798 WARN("not initialized\n");
799 return DSERR_UNINITIALIZED;
802 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
803 *pdwCertified = DS_CERTIFIED;
804 else
805 *pdwCertified = DS_UNCERTIFIED;
806 return DS_OK;
809 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
811 IDirectSoundImpl_QueryInterface,
812 IDirectSoundImpl_AddRef,
813 IDirectSoundImpl_Release,
814 IDirectSoundImpl_CreateSoundBuffer,
815 IDirectSoundImpl_GetCaps,
816 IDirectSoundImpl_DuplicateSoundBuffer,
817 IDirectSoundImpl_SetCooperativeLevel,
818 IDirectSoundImpl_Compact,
819 IDirectSoundImpl_GetSpeakerConfig,
820 IDirectSoundImpl_SetSpeakerConfig,
821 IDirectSoundImpl_Initialize,
822 IDirectSoundImpl_VerifyCertification
825 HRESULT WINAPI IDirectSoundImpl_Create(
826 LPCGUID lpcGUID,
827 LPDIRECTSOUND8 * ppDS)
829 HRESULT err;
830 PIDSDRIVER drv = NULL;
831 IDirectSoundImpl* pDS;
832 unsigned wod, wodn;
833 BOOLEAN found = FALSE;
834 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
836 /* Enumerate WINMM audio devices and find the one we want */
837 wodn = waveOutGetNumDevs();
838 if (!wodn) {
839 WARN("no driver\n");
840 *ppDS = NULL;
841 return DSERR_NODRIVER;
844 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
846 for (wod=0; wod<wodn; wod++) {
847 if (IsEqualGUID( lpcGUID, &DSOUND_renderer_guids[wod])) {
848 found = TRUE;
849 break;
853 if (found == FALSE) {
854 WARN("No device found matching given ID!\n");
855 *ppDS = NULL;
856 return DSERR_NODRIVER;
859 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
860 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
862 /* Disable the direct sound driver to force emulation if requested. */
863 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
864 drv = NULL;
866 /* Allocate memory */
867 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
868 if (pDS == NULL) {
869 WARN("out of memory\n");
870 *ppDS = NULL;
871 return DSERR_OUTOFMEMORY;
874 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
875 pDS->ref = 0;
877 pDS->driver = drv;
878 pDS->priolevel = DSSCL_NORMAL;
879 pDS->fraglen = 0;
880 pDS->hwbuf = NULL;
881 pDS->buffer = NULL;
882 pDS->buflen = 0;
883 pDS->writelead = 0;
884 pDS->state = STATE_STOPPED;
885 pDS->nrofbuffers = 0;
886 pDS->buffers = NULL;
887 pDS->primary = NULL;
888 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
889 pDS->initialized = FALSE;
890 pDS->tmp_buffer = NULL;
891 pDS->tmp_buffer_len = 0;
893 /* 3D listener initial parameters */
894 pDS->listener = NULL;
895 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
896 pDS->ds3dl.vPosition.x = 0.0;
897 pDS->ds3dl.vPosition.y = 0.0;
898 pDS->ds3dl.vPosition.z = 0.0;
899 pDS->ds3dl.vVelocity.x = 0.0;
900 pDS->ds3dl.vVelocity.y = 0.0;
901 pDS->ds3dl.vVelocity.z = 0.0;
902 pDS->ds3dl.vOrientFront.x = 0.0;
903 pDS->ds3dl.vOrientFront.y = 0.0;
904 pDS->ds3dl.vOrientFront.z = 1.0;
905 pDS->ds3dl.vOrientTop.x = 0.0;
906 pDS->ds3dl.vOrientTop.y = 1.0;
907 pDS->ds3dl.vOrientTop.z = 0.0;
908 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
909 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
910 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
912 pDS->prebuf = ds_snd_queue_max;
913 pDS->guid = *lpcGUID;
915 /* Get driver description */
916 if (drv) {
917 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
918 if (err != DS_OK) {
919 WARN("IDsDriver_GetDriverDesc failed\n");
920 HeapFree(GetProcessHeap(),0,pDS);
921 *ppDS = NULL;
922 return err;
924 } else {
925 /* if no DirectSound interface available, use WINMM API instead */
926 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
929 pDS->drvdesc.dnDevNode = wod;
931 /* Set default wave format (may need it for waveOutOpen) */
932 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
933 if (pDS->pwfx == NULL) {
934 WARN("out of memory\n");
935 HeapFree(GetProcessHeap(),0,pDS);
936 *ppDS = NULL;
937 return DSERR_OUTOFMEMORY;
940 /* We rely on the sound driver to return the actual sound format of
941 * the device if it does not support 22050x8x2 and is given the
942 * WAVE_DIRECTSOUND flag.
944 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
945 pDS->pwfx->nSamplesPerSec = 22050;
946 pDS->pwfx->wBitsPerSample = 8;
947 pDS->pwfx->nChannels = 2;
948 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
949 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
950 pDS->pwfx->cbSize = 0;
952 InitializeCriticalSection(&(pDS->mixlock));
953 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
955 RtlInitializeResource(&(pDS->buffer_list_lock));
957 *ppDS = (LPDIRECTSOUND8)pDS;
959 return DS_OK;
961 /*******************************************************************************
962 * IDirectSound_IUnknown
964 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
965 LPUNKNOWN iface,
966 REFIID riid,
967 LPVOID * ppobj)
969 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
970 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
971 return DSOUND_QueryInterface(This->pds, riid, ppobj);
974 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
975 LPUNKNOWN iface)
977 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
978 ULONG ref = InterlockedIncrement(&(This->ref));
979 TRACE("(%p) ref was %ld\n", This, ref - 1);
980 return ref;
983 static ULONG WINAPI IDirectSound_IUnknown_Release(
984 LPUNKNOWN iface)
986 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
987 ULONG ref = InterlockedDecrement(&(This->ref));
988 TRACE("(%p) ref was %ld\n", This, ref + 1);
989 if (!ref) {
990 IDirectSoundImpl_Release(This->pds);
991 HeapFree(GetProcessHeap(), 0, This);
992 TRACE("(%p) released\n", This);
994 return ref;
997 static IUnknownVtbl DirectSound_Unknown_Vtbl =
999 IDirectSound_IUnknown_QueryInterface,
1000 IDirectSound_IUnknown_AddRef,
1001 IDirectSound_IUnknown_Release
1004 HRESULT WINAPI IDirectSound_IUnknown_Create(
1005 LPDIRECTSOUND8 pds,
1006 LPUNKNOWN * ppunk)
1008 IDirectSound_IUnknown * pdsunk;
1009 TRACE("(%p,%p)\n",pds,ppunk);
1011 if (ppunk == NULL) {
1012 ERR("invalid parameter: ppunk == NULL\n");
1013 return DSERR_INVALIDPARAM;
1016 if (pds == NULL) {
1017 ERR("invalid parameter: pds == NULL\n");
1018 *ppunk = NULL;
1019 return DSERR_INVALIDPARAM;
1022 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1023 if (pdsunk == NULL) {
1024 WARN("out of memory\n");
1025 *ppunk = NULL;
1026 return DSERR_OUTOFMEMORY;
1029 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1030 pdsunk->ref = 0;
1031 pdsunk->pds = pds;
1033 IDirectSoundImpl_AddRef(pds);
1034 *ppunk = (LPUNKNOWN)pdsunk;
1036 return DS_OK;
1039 /*******************************************************************************
1040 * IDirectSound_IDirectSound
1042 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1043 LPDIRECTSOUND iface,
1044 REFIID riid,
1045 LPVOID * ppobj)
1047 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1048 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1049 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1052 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1053 LPDIRECTSOUND iface)
1055 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1056 ULONG ref = InterlockedIncrement(&(This->ref));
1057 TRACE("(%p) ref was %ld\n", This, ref - 1);
1058 return ref;
1061 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1062 LPDIRECTSOUND iface)
1064 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1065 ULONG ref = InterlockedDecrement(&(This->ref));
1066 TRACE("(%p) ref was %ld\n", This, ref + 1);
1067 if (!ref) {
1068 IDirectSoundImpl_Release(This->pds);
1069 HeapFree(GetProcessHeap(), 0, This);
1070 TRACE("(%p) released\n", This);
1072 return ref;
1075 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1076 LPDIRECTSOUND iface,
1077 LPCDSBUFFERDESC dsbd,
1078 LPLPDIRECTSOUNDBUFFER ppdsb,
1079 LPUNKNOWN lpunk)
1081 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1082 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1083 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1086 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1087 LPDIRECTSOUND iface,
1088 LPDSCAPS lpDSCaps)
1090 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1091 TRACE("(%p,%p)\n",This,lpDSCaps);
1092 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1095 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1096 LPDIRECTSOUND iface,
1097 LPDIRECTSOUNDBUFFER psb,
1098 LPLPDIRECTSOUNDBUFFER ppdsb)
1100 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1101 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1102 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1105 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1106 LPDIRECTSOUND iface,
1107 HWND hwnd,
1108 DWORD level)
1110 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1111 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1112 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1115 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1116 LPDIRECTSOUND iface)
1118 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1119 TRACE("(%p)\n", This);
1120 return IDirectSoundImpl_Compact(This->pds);
1123 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1124 LPDIRECTSOUND iface,
1125 LPDWORD lpdwSpeakerConfig)
1127 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1128 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1129 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1132 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1133 LPDIRECTSOUND iface,
1134 DWORD config)
1136 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1137 TRACE("(%p,0x%08lx)\n",This,config);
1138 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1141 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1142 LPDIRECTSOUND iface,
1143 LPCGUID lpcGuid)
1145 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1146 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1147 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1150 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1152 IDirectSound_IDirectSound_QueryInterface,
1153 IDirectSound_IDirectSound_AddRef,
1154 IDirectSound_IDirectSound_Release,
1155 IDirectSound_IDirectSound_CreateSoundBuffer,
1156 IDirectSound_IDirectSound_GetCaps,
1157 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1158 IDirectSound_IDirectSound_SetCooperativeLevel,
1159 IDirectSound_IDirectSound_Compact,
1160 IDirectSound_IDirectSound_GetSpeakerConfig,
1161 IDirectSound_IDirectSound_SetSpeakerConfig,
1162 IDirectSound_IDirectSound_Initialize
1165 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1166 LPDIRECTSOUND8 pds,
1167 LPDIRECTSOUND * ppds)
1169 IDirectSound_IDirectSound * pdsds;
1170 TRACE("(%p,%p)\n",pds,ppds);
1172 if (ppds == NULL) {
1173 ERR("invalid parameter: ppds == NULL\n");
1174 return DSERR_INVALIDPARAM;
1177 if (pds == NULL) {
1178 ERR("invalid parameter: pds == NULL\n");
1179 *ppds = NULL;
1180 return DSERR_INVALIDPARAM;
1183 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1184 if (pdsds == NULL) {
1185 WARN("out of memory\n");
1186 *ppds = NULL;
1187 return DSERR_OUTOFMEMORY;
1190 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1191 pdsds->ref = 0;
1192 pdsds->pds = pds;
1194 IDirectSoundImpl_AddRef(pds);
1195 *ppds = (LPDIRECTSOUND)pdsds;
1197 return DS_OK;
1200 /*******************************************************************************
1201 * IDirectSound8_IUnknown
1203 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1204 LPUNKNOWN iface,
1205 REFIID riid,
1206 LPVOID * ppobj)
1208 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1209 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1210 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1213 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1214 LPUNKNOWN iface)
1216 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1217 ULONG ref = InterlockedIncrement(&(This->ref));
1218 TRACE("(%p) ref was %ld\n", This, ref - 1);
1219 return ref;
1222 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1223 LPUNKNOWN iface)
1225 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1226 ULONG ref = InterlockedDecrement(&(This->ref));
1227 TRACE("(%p) ref was %ld\n", This, ref + 1);
1228 if (!ref) {
1229 IDirectSoundImpl_Release(This->pds);
1230 HeapFree(GetProcessHeap(), 0, This);
1231 TRACE("(%p) released\n", This);
1233 return ref;
1236 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1238 IDirectSound8_IUnknown_QueryInterface,
1239 IDirectSound8_IUnknown_AddRef,
1240 IDirectSound8_IUnknown_Release
1243 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1244 LPDIRECTSOUND8 pds,
1245 LPUNKNOWN * ppunk)
1247 IDirectSound8_IUnknown * pdsunk;
1248 TRACE("(%p,%p)\n",pds,ppunk);
1250 if (ppunk == NULL) {
1251 ERR("invalid parameter: ppunk == NULL\n");
1252 return DSERR_INVALIDPARAM;
1255 if (pds == NULL) {
1256 ERR("invalid parameter: pds == NULL\n");
1257 *ppunk = NULL;
1258 return DSERR_INVALIDPARAM;
1261 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1262 if (pdsunk == NULL) {
1263 WARN("out of memory\n");
1264 *ppunk = NULL;
1265 return DSERR_OUTOFMEMORY;
1268 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1269 pdsunk->ref = 0;
1270 pdsunk->pds = pds;
1272 IDirectSoundImpl_AddRef(pds);
1273 *ppunk = (LPUNKNOWN)pdsunk;
1275 return DS_OK;
1278 /*******************************************************************************
1279 * IDirectSound8_IDirectSound
1281 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1282 LPDIRECTSOUND iface,
1283 REFIID riid,
1284 LPVOID * ppobj)
1286 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1287 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1288 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1291 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1292 LPDIRECTSOUND iface)
1294 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1295 ULONG ref = InterlockedIncrement(&(This->ref));
1296 TRACE("(%p) ref was %ld\n", This, ref - 1);
1297 return ref;
1300 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1301 LPDIRECTSOUND iface)
1303 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1304 ULONG ref = InterlockedDecrement(&(This->ref));
1305 TRACE("(%p) ref was %ld\n", This, ref + 1);
1306 if (!ref) {
1307 IDirectSoundImpl_Release(This->pds);
1308 HeapFree(GetProcessHeap(), 0, This);
1309 TRACE("(%p) released\n", This);
1311 return ref;
1314 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1315 LPDIRECTSOUND iface,
1316 LPCDSBUFFERDESC dsbd,
1317 LPLPDIRECTSOUNDBUFFER ppdsb,
1318 LPUNKNOWN lpunk)
1320 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1321 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1322 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1325 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1326 LPDIRECTSOUND iface,
1327 LPDSCAPS lpDSCaps)
1329 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1330 TRACE("(%p,%p)\n",This,lpDSCaps);
1331 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1334 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1335 LPDIRECTSOUND iface,
1336 LPDIRECTSOUNDBUFFER psb,
1337 LPLPDIRECTSOUNDBUFFER ppdsb)
1339 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1340 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1341 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1344 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1345 LPDIRECTSOUND iface,
1346 HWND hwnd,
1347 DWORD level)
1349 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1350 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1351 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1354 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1355 LPDIRECTSOUND iface)
1357 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1358 TRACE("(%p)\n", This);
1359 return IDirectSoundImpl_Compact(This->pds);
1362 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1363 LPDIRECTSOUND iface,
1364 LPDWORD lpdwSpeakerConfig)
1366 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1367 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1368 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1371 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1372 LPDIRECTSOUND iface,
1373 DWORD config)
1375 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1376 TRACE("(%p,0x%08lx)\n",This,config);
1377 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1380 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1381 LPDIRECTSOUND iface,
1382 LPCGUID lpcGuid)
1384 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1385 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1386 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1389 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1391 IDirectSound8_IDirectSound_QueryInterface,
1392 IDirectSound8_IDirectSound_AddRef,
1393 IDirectSound8_IDirectSound_Release,
1394 IDirectSound8_IDirectSound_CreateSoundBuffer,
1395 IDirectSound8_IDirectSound_GetCaps,
1396 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1397 IDirectSound8_IDirectSound_SetCooperativeLevel,
1398 IDirectSound8_IDirectSound_Compact,
1399 IDirectSound8_IDirectSound_GetSpeakerConfig,
1400 IDirectSound8_IDirectSound_SetSpeakerConfig,
1401 IDirectSound8_IDirectSound_Initialize
1404 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1405 LPDIRECTSOUND8 pds,
1406 LPDIRECTSOUND * ppds)
1408 IDirectSound8_IDirectSound * pdsds;
1409 TRACE("(%p,%p)\n",pds,ppds);
1411 if (ppds == NULL) {
1412 ERR("invalid parameter: ppds == NULL\n");
1413 return DSERR_INVALIDPARAM;
1416 if (pds == NULL) {
1417 ERR("invalid parameter: pds == NULL\n");
1418 *ppds = NULL;
1419 return DSERR_INVALIDPARAM;
1422 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1423 if (pdsds == NULL) {
1424 WARN("out of memory\n");
1425 *ppds = NULL;
1426 return DSERR_OUTOFMEMORY;
1429 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1430 pdsds->ref = 0;
1431 pdsds->pds = pds;
1433 IDirectSoundImpl_AddRef(pds);
1434 *ppds = (LPDIRECTSOUND)pdsds;
1436 return DS_OK;
1439 /*******************************************************************************
1440 * IDirectSound8_IDirectSound8
1442 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1443 LPDIRECTSOUND8 iface,
1444 REFIID riid,
1445 LPVOID * ppobj)
1447 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1448 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1449 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1452 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1453 LPDIRECTSOUND8 iface)
1455 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1456 ULONG ref = InterlockedIncrement(&(This->ref));
1457 TRACE("(%p) ref was %ld\n", This, ref - 1);
1458 return ref;
1461 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1462 LPDIRECTSOUND8 iface)
1464 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1465 ULONG ref = InterlockedDecrement(&(This->ref));
1466 TRACE("(%p) ref was %ld\n", This, ref + 1);
1467 if (!ref) {
1468 IDirectSoundImpl_Release(This->pds);
1469 HeapFree(GetProcessHeap(), 0, This);
1470 TRACE("(%p) released\n", This);
1472 return ref;
1475 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1476 LPDIRECTSOUND8 iface,
1477 LPCDSBUFFERDESC dsbd,
1478 LPLPDIRECTSOUNDBUFFER ppdsb,
1479 LPUNKNOWN lpunk)
1481 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1482 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1483 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1486 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1487 LPDIRECTSOUND8 iface,
1488 LPDSCAPS lpDSCaps)
1490 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1491 TRACE("(%p,%p)\n",This,lpDSCaps);
1492 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1495 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1496 LPDIRECTSOUND8 iface,
1497 LPDIRECTSOUNDBUFFER psb,
1498 LPLPDIRECTSOUNDBUFFER ppdsb)
1500 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1501 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1502 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1505 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1506 LPDIRECTSOUND8 iface,
1507 HWND hwnd,
1508 DWORD level)
1510 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1511 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1512 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1515 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1516 LPDIRECTSOUND8 iface)
1518 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1519 TRACE("(%p)\n", This);
1520 return IDirectSoundImpl_Compact(This->pds);
1523 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1524 LPDIRECTSOUND8 iface,
1525 LPDWORD lpdwSpeakerConfig)
1527 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1528 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1529 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1532 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1533 LPDIRECTSOUND8 iface,
1534 DWORD config)
1536 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1537 TRACE("(%p,0x%08lx)\n",This,config);
1538 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1541 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1542 LPDIRECTSOUND8 iface,
1543 LPCGUID lpcGuid)
1545 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1546 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1547 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1550 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1551 LPDIRECTSOUND8 iface,
1552 LPDWORD pdwCertified)
1554 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1555 TRACE("(%p, %p)\n", This, pdwCertified);
1556 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1559 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1561 IDirectSound8_IDirectSound8_QueryInterface,
1562 IDirectSound8_IDirectSound8_AddRef,
1563 IDirectSound8_IDirectSound8_Release,
1564 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1565 IDirectSound8_IDirectSound8_GetCaps,
1566 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1567 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1568 IDirectSound8_IDirectSound8_Compact,
1569 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1570 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1571 IDirectSound8_IDirectSound8_Initialize,
1572 IDirectSound8_IDirectSound8_VerifyCertification
1575 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1576 LPDIRECTSOUND8 pds,
1577 LPDIRECTSOUND8 * ppds)
1579 IDirectSound8_IDirectSound8 * pdsds;
1580 TRACE("(%p,%p)\n",pds,ppds);
1582 if (ppds == NULL) {
1583 ERR("invalid parameter: ppds == NULL\n");
1584 return DSERR_INVALIDPARAM;
1587 if (pds == NULL) {
1588 ERR("invalid parameter: pds == NULL\n");
1589 *ppds = NULL;
1590 return DSERR_INVALIDPARAM;
1593 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1594 if (pdsds == NULL) {
1595 WARN("out of memory\n");
1596 *ppds = NULL;
1597 return DSERR_OUTOFMEMORY;
1600 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1601 pdsds->ref = 0;
1602 pdsds->pds = pds;
1604 IDirectSoundImpl_AddRef(pds);
1605 *ppds = (LPDIRECTSOUND8)pdsds;
1607 return DS_OK;
1610 HRESULT WINAPI DSOUND_Create(
1611 LPCGUID lpcGUID,
1612 LPDIRECTSOUND *ppDS,
1613 IUnknown *pUnkOuter)
1615 HRESULT hr;
1616 GUID devGuid;
1618 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1620 /* Get dsound configuration */
1621 setup_dsound_options();
1623 /* Default device? */
1624 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1625 lpcGUID = &DSDEVID_DefaultPlayback;
1627 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1628 WARN("invalid parameter: lpcGUID\n");
1629 *ppDS = NULL;
1630 return DSERR_INVALIDPARAM;
1633 if (DSOUND_renderer) {
1634 if (IsEqualGUID(&devGuid, &DSOUND_renderer->guid)) {
1635 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)DSOUND_renderer, ppDS);
1636 if (*ppDS)
1637 IDirectSound_IDirectSound_AddRef(*ppDS);
1638 else
1639 WARN("IDirectSound_IDirectSound_Create failed\n");
1640 } else {
1641 ERR("different dsound already opened (only support one sound card at a time now)\n");
1642 *ppDS = NULL;
1643 hr = DSERR_ALLOCATED;
1645 } else {
1646 LPDIRECTSOUND8 pDS;
1647 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1648 if (hr == DS_OK) {
1649 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1650 if (*ppDS)
1651 IDirectSound_IDirectSound_AddRef(*ppDS);
1652 else {
1653 WARN("IDirectSound_IDirectSound_Create failed\n");
1654 IDirectSound8_Release(pDS);
1656 } else
1657 WARN("IDirectSoundImpl_Create failed\n");
1660 return hr;
1663 /*******************************************************************************
1664 * DirectSoundCreate (DSOUND.1)
1666 * Creates and initializes a DirectSound interface.
1668 * PARAMS
1669 * lpcGUID [I] Address of the GUID that identifies the sound device.
1670 * ppDS [O] Address of a variable to receive the interface pointer.
1671 * pUnkOuter [I] Must be NULL.
1673 * RETURNS
1674 * Success: DS_OK
1675 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1676 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1678 HRESULT WINAPI DirectSoundCreate(
1679 LPCGUID lpcGUID,
1680 LPDIRECTSOUND *ppDS,
1681 IUnknown *pUnkOuter)
1683 HRESULT hr;
1684 LPDIRECTSOUND pDS;
1686 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1688 if (ppDS == NULL) {
1689 WARN("invalid parameter: ppDS == NULL\n");
1690 return DSERR_INVALIDPARAM;
1693 if (pUnkOuter != NULL) {
1694 WARN("invalid parameter: pUnkOuter != NULL\n");
1695 *ppDS = 0;
1696 return DSERR_INVALIDPARAM;
1699 hr = DSOUND_Create(lpcGUID, &pDS, pUnkOuter);
1700 if (hr == DS_OK) {
1701 IDirectSound_IDirectSound * pp = (IDirectSound_IDirectSound *)pDS;
1702 IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds);
1703 if (!(p->initialized)) {
1704 hr = IDirectSound_Initialize(pDS, lpcGUID);
1705 if (hr != DS_OK)
1706 IDirectSound_Release(pDS);
1710 *ppDS = pDS;
1712 return hr;
1715 HRESULT WINAPI DSOUND_Create8(
1716 LPCGUID lpcGUID,
1717 LPDIRECTSOUND8 *ppDS,
1718 IUnknown *pUnkOuter)
1720 HRESULT hr;
1721 GUID devGuid;
1723 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1725 /* Get dsound configuration */
1726 setup_dsound_options();
1728 /* Default device? */
1729 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1730 lpcGUID = &DSDEVID_DefaultPlayback;
1732 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1733 WARN("invalid parameter: lpcGUID\n");
1734 *ppDS = NULL;
1735 return DSERR_INVALIDPARAM;
1738 if (DSOUND_renderer) {
1739 if (IsEqualGUID(&devGuid, &DSOUND_renderer->guid)) {
1740 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)DSOUND_renderer, ppDS);
1741 if (*ppDS)
1742 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1743 else
1744 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1745 } else {
1746 ERR("different dsound already opened (only support one sound card at a time now)\n");
1747 *ppDS = NULL;
1748 hr = DSERR_ALLOCATED;
1750 } else {
1751 LPDIRECTSOUND8 pDS;
1752 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1753 if (hr == DS_OK) {
1754 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1755 if (*ppDS)
1756 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1757 else {
1758 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1759 IDirectSound8_Release(pDS);
1761 } else
1762 WARN("IDirectSoundImpl_Create failed\n");
1765 return hr;
1768 /*******************************************************************************
1769 * DirectSoundCreate8 (DSOUND.11)
1771 * Creates and initializes a DirectSound8 interface.
1773 * PARAMS
1774 * lpcGUID [I] Address of the GUID that identifies the sound device.
1775 * ppDS [O] Address of a variable to receive the interface pointer.
1776 * pUnkOuter [I] Must be NULL.
1778 * RETURNS
1779 * Success: DS_OK
1780 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1781 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1783 HRESULT WINAPI DirectSoundCreate8(
1784 LPCGUID lpcGUID,
1785 LPDIRECTSOUND8 *ppDS,
1786 IUnknown *pUnkOuter)
1788 HRESULT hr;
1789 LPDIRECTSOUND8 pDS;
1791 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1793 if (ppDS == NULL) {
1794 WARN("invalid parameter: ppDS == NULL\n");
1795 return DSERR_INVALIDPARAM;
1798 if (pUnkOuter != NULL) {
1799 WARN("invalid parameter: pUnkOuter != NULL\n");
1800 *ppDS = 0;
1801 return DSERR_INVALIDPARAM;
1804 hr = DSOUND_Create8(lpcGUID, &pDS, pUnkOuter);
1805 if (hr == DS_OK) {
1806 IDirectSound8_IDirectSound8 * pp = (IDirectSound8_IDirectSound8 *)pDS;
1807 IDirectSoundImpl * p = (IDirectSoundImpl *)(pp->pds);
1808 if (!(p->initialized)) {
1809 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1810 if (hr != DS_OK)
1811 IDirectSound8_Release(pDS);
1815 *ppDS = pDS;
1817 return hr;
1821 * Add secondary buffer to buffer list.
1822 * Gets exclusive access to buffer for writing.
1824 HRESULT DSOUND_AddBuffer(
1825 IDirectSoundImpl * pDS,
1826 IDirectSoundBufferImpl * pDSB)
1828 IDirectSoundBufferImpl **newbuffers;
1829 HRESULT hr = DS_OK;
1831 TRACE("(%p, %p)\n", pDS, pDSB);
1833 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1835 if (pDS->buffers)
1836 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1837 else
1838 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1840 if (newbuffers) {
1841 pDS->buffers = newbuffers;
1842 pDS->buffers[pDS->nrofbuffers] = pDSB;
1843 pDS->nrofbuffers++;
1844 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1845 } else {
1846 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
1847 hr = DSERR_OUTOFMEMORY;
1850 RtlReleaseResource(&(pDS->buffer_list_lock));
1852 return hr;
1856 * Remove secondary buffer from buffer list.
1857 * Gets exclusive access to buffer for writing.
1859 HRESULT DSOUND_RemoveBuffer(
1860 IDirectSoundImpl * pDS,
1861 IDirectSoundBufferImpl * pDSB)
1863 int i;
1864 HRESULT hr = DS_OK;
1866 TRACE("(%p, %p)\n", pDS, pDSB);
1868 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1870 for (i = 0; i < pDS->nrofbuffers; i++)
1871 if (pDS->buffers[i] == pDSB)
1872 break;
1874 if (i < pDS->nrofbuffers) {
1875 /* Put the last buffer of the list in the (now empty) position */
1876 pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
1877 pDS->nrofbuffers--;
1878 pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
1879 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1882 if (pDS->nrofbuffers == 0) {
1883 HeapFree(GetProcessHeap(),0,pDS->buffers);
1884 pDS->buffers = NULL;
1887 RtlReleaseResource(&(pDS->buffer_list_lock));
1889 return hr;