Remove lock name from lock debug structure before deletion so it gets
[wine/multimedia.git] / dlls / dsound / dsound.c
blobf1cba5e5de49624ad7ca4c81ced2ec55f0b9e961
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 "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/fcntl.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #include <stdlib.h>
34 #include <string.h>
36 #define NONAMELESSSTRUCT
37 #define NONAMELESSUNION
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winreg.h"
41 #include "winuser.h"
42 #include "wingdi.h"
43 #include "winuser.h"
44 #include "winerror.h"
45 #include "mmsystem.h"
46 #include "winternl.h"
47 #include "mmddk.h"
48 #include "wine/windef16.h"
49 #include "wine/winbase16.h"
50 #include "wine/debug.h"
51 #include "dsound.h"
52 #include "dsdriver.h"
53 #include "dsound_private.h"
54 #include "dsconf.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
58 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
59 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
60 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
61 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
62 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
64 static const char * dumpCooperativeLevel(DWORD level)
66 static char unknown[32];
67 #define LE(x) case x: return #x
68 switch (level) {
69 LE(DSSCL_NORMAL);
70 LE(DSSCL_PRIORITY);
71 LE(DSSCL_EXCLUSIVE);
72 LE(DSSCL_WRITEPRIMARY);
74 #undef LE
75 sprintf(unknown, "Unknown(%08lx)", level);
76 return unknown;
79 static void _dump_DSCAPS(DWORD xmask) {
80 struct {
81 DWORD mask;
82 char *name;
83 } flags[] = {
84 #define FE(x) { x, #x },
85 FE(DSCAPS_PRIMARYMONO)
86 FE(DSCAPS_PRIMARYSTEREO)
87 FE(DSCAPS_PRIMARY8BIT)
88 FE(DSCAPS_PRIMARY16BIT)
89 FE(DSCAPS_CONTINUOUSRATE)
90 FE(DSCAPS_EMULDRIVER)
91 FE(DSCAPS_CERTIFIED)
92 FE(DSCAPS_SECONDARYMONO)
93 FE(DSCAPS_SECONDARYSTEREO)
94 FE(DSCAPS_SECONDARY8BIT)
95 FE(DSCAPS_SECONDARY16BIT)
96 #undef FE
98 unsigned int i;
100 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
101 if ((flags[i].mask & xmask) == flags[i].mask)
102 DPRINTF("%s ",flags[i].name);
105 static void _dump_DSBCAPS(DWORD xmask) {
106 struct {
107 DWORD mask;
108 char *name;
109 } flags[] = {
110 #define FE(x) { x, #x },
111 FE(DSBCAPS_PRIMARYBUFFER)
112 FE(DSBCAPS_STATIC)
113 FE(DSBCAPS_LOCHARDWARE)
114 FE(DSBCAPS_LOCSOFTWARE)
115 FE(DSBCAPS_CTRL3D)
116 FE(DSBCAPS_CTRLFREQUENCY)
117 FE(DSBCAPS_CTRLPAN)
118 FE(DSBCAPS_CTRLVOLUME)
119 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
120 FE(DSBCAPS_STICKYFOCUS)
121 FE(DSBCAPS_GLOBALFOCUS)
122 FE(DSBCAPS_GETCURRENTPOSITION2)
123 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
124 #undef FE
126 unsigned int i;
128 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
129 if ((flags[i].mask & xmask) == flags[i].mask)
130 DPRINTF("%s ",flags[i].name);
133 /*******************************************************************************
134 * IDirectSoundImpl_DirectSound
136 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
137 LPDIRECTSOUND8 iface,
138 REFIID riid,
139 LPVOID * ppobj)
141 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
142 FIXME("shouldn't be called directly\n");
143 return E_NOINTERFACE;
146 static HRESULT WINAPI DSOUND_QueryInterface(
147 LPDIRECTSOUND8 iface,
148 REFIID riid,
149 LPVOID * ppobj)
151 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
152 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
154 if (ppobj == NULL) {
155 WARN("invalid parameter\n");
156 return E_INVALIDARG;
159 if (IsEqualIID(riid, &IID_IUnknown)) {
160 if (!This->pUnknown) {
161 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
162 if (!This->pUnknown) {
163 WARN("IDirectSound_IUnknown_Create() failed\n");
164 *ppobj = NULL;
165 return E_NOINTERFACE;
168 IDirectSound_IUnknown_AddRef(This->pUnknown);
169 *ppobj = This->pUnknown;
170 return S_OK;
171 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
172 if (!This->pDS) {
173 IDirectSound_IDirectSound_Create(iface, &This->pDS);
174 if (!This->pDS) {
175 WARN("IDirectSound_IDirectSound_Create() failed\n");
176 *ppobj = NULL;
177 return E_NOINTERFACE;
180 IDirectSound_IDirectSound_AddRef(This->pDS);
181 *ppobj = This->pDS;
182 return S_OK;
185 *ppobj = NULL;
186 WARN("Unknown IID %s\n",debugstr_guid(riid));
187 return E_NOINTERFACE;
190 static HRESULT WINAPI DSOUND_QueryInterface8(
191 LPDIRECTSOUND8 iface,
192 REFIID riid,
193 LPVOID * ppobj)
195 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
196 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
198 if (ppobj == NULL) {
199 WARN("invalid parameter\n");
200 return E_INVALIDARG;
203 if (IsEqualIID(riid, &IID_IUnknown)) {
204 if (!This->pUnknown) {
205 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
206 if (!This->pUnknown) {
207 WARN("IDirectSound8_IUnknown_Create() failed\n");
208 *ppobj = NULL;
209 return E_NOINTERFACE;
212 IDirectSound8_IUnknown_AddRef(This->pUnknown);
213 *ppobj = This->pUnknown;
214 return S_OK;
215 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
216 if (!This->pDS) {
217 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
218 if (!This->pDS) {
219 WARN("IDirectSound8_IDirectSound_Create() failed\n");
220 *ppobj = NULL;
221 return E_NOINTERFACE;
224 IDirectSound8_IDirectSound_AddRef(This->pDS);
225 *ppobj = This->pDS;
226 return S_OK;
227 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
228 if (!This->pDS8) {
229 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
230 if (!This->pDS8) {
231 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
232 *ppobj = NULL;
233 return E_NOINTERFACE;
236 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
237 *ppobj = This->pDS8;
238 return S_OK;
241 *ppobj = NULL;
242 WARN("Unknown IID %s\n",debugstr_guid(riid));
243 return E_NOINTERFACE;
246 static ULONG WINAPI IDirectSoundImpl_AddRef(
247 LPDIRECTSOUND8 iface)
249 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
250 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
252 return InterlockedIncrement(&This->ref);
255 static ULONG WINAPI IDirectSoundImpl_Release(
256 LPDIRECTSOUND8 iface)
258 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
259 ULONG ref;
260 TRACE("(%p) ref was %ld, thread is %04lx\n",
261 This, This->ref, GetCurrentThreadId());
263 ref = InterlockedDecrement(&This->ref);
264 if (ref == 0) {
265 HRESULT hres;
266 INT i;
268 timeKillEvent(This->timerID);
269 timeEndPeriod(DS_TIME_RES);
270 /* wait for timer to expire */
271 Sleep(DS_TIME_RES+1);
273 /* The sleep above should have allowed the timer process to expire
274 * but try to grab the lock just in case. Can't hold lock because
275 * IDirectSoundBufferImpl_Destroy also grabs the lock */
276 RtlAcquireResourceShared(&(This->buffer_list_lock), TRUE);
277 RtlReleaseResource(&(This->buffer_list_lock));
279 /* It is allowed to release this object even when buffers are playing */
280 if (This->buffers) {
281 WARN("%d secondary buffers not released\n", This->nrofbuffers);
282 for( i=0;i<This->nrofbuffers;i++)
283 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
286 if (This->primary) {
287 WARN("primary buffer not released\n");
288 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
291 hres = DSOUND_PrimaryDestroy(This);
292 if (hres != DS_OK)
293 WARN("DSOUND_PrimaryDestroy failed\n");
295 if (This->driver)
296 IDsDriver_Close(This->driver);
298 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
299 waveOutClose(This->hwo);
301 if (This->driver)
302 IDsDriver_Release(This->driver);
304 RtlDeleteResource(&This->buffer_list_lock);
305 This->mixlock.DebugInfo->Spare[1] = 0;
306 DeleteCriticalSection(&This->mixlock);
307 HeapFree(GetProcessHeap(),0,This);
308 dsound = NULL;
309 TRACE("(%p) released\n",This);
312 return ref;
315 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
316 LPDIRECTSOUND8 iface,
317 LPCDSBUFFERDESC dsbd,
318 LPLPDIRECTSOUNDBUFFER ppdsb,
319 LPUNKNOWN lpunk)
321 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
322 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
323 FIXME("shouldn't be called directly\n");
324 return DSERR_GENERIC;
327 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
328 LPDIRECTSOUND8 iface,
329 LPCDSBUFFERDESC dsbd,
330 LPLPDIRECTSOUNDBUFFER ppdsb,
331 LPUNKNOWN lpunk,
332 BOOL from8)
334 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
335 HRESULT hres = DS_OK;
336 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
338 if (This == NULL) {
339 WARN("invalid parameter: This == NULL\n");
340 return DSERR_INVALIDPARAM;
343 if (This->initialized == FALSE) {
344 WARN("not initialized\n");
345 return DSERR_UNINITIALIZED;
348 if (dsbd == NULL) {
349 WARN("invalid parameter: dsbd == NULL\n");
350 return DSERR_INVALIDPARAM;
353 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
354 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
355 WARN("invalid parameter: dsbd\n");
356 return DSERR_INVALIDPARAM;
359 if (ppdsb == NULL) {
360 WARN("invalid parameter: ppdsb == NULL\n");
361 return DSERR_INVALIDPARAM;
364 if (TRACE_ON(dsound)) {
365 TRACE("(structsize=%ld)\n",dsbd->dwSize);
366 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
367 _dump_DSBCAPS(dsbd->dwFlags);
368 DPRINTF(")\n");
369 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
370 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
373 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
374 if (dsbd->lpwfxFormat != NULL) {
375 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
376 "primary buffer\n");
377 return DSERR_INVALIDPARAM;
380 if (This->primary) {
381 WARN("Primary Buffer already created\n");
382 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
383 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
384 } else {
385 This->dsbd = *dsbd;
386 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
387 if (This->primary) {
388 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
389 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
390 } else
391 WARN("PrimaryBufferImpl_Create failed\n");
393 } else {
394 IDirectSoundBufferImpl * dsb;
396 if (dsbd->lpwfxFormat == NULL) {
397 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
398 "secondary buffer\n");
399 return DSERR_INVALIDPARAM;
402 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
403 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
404 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
405 dsbd->lpwfxFormat->nSamplesPerSec,
406 dsbd->lpwfxFormat->nAvgBytesPerSec,
407 dsbd->lpwfxFormat->nBlockAlign,
408 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
410 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
411 WARN("invalid parameter: 3D buffer format must be mono\n");
412 return DSERR_INVALIDPARAM;
415 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
416 if (dsb) {
417 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
418 if (*ppdsb) {
419 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
420 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
421 } else
422 WARN("SecondaryBufferImpl_Create failed\n");
423 } else
424 WARN("IDirectSoundBufferImpl_Create failed\n");
427 return hres;
430 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
431 LPDIRECTSOUND8 iface,
432 LPDSCAPS lpDSCaps)
434 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
435 TRACE("(%p,%p)\n",This,lpDSCaps);
437 if (This == NULL) {
438 WARN("invalid parameter: This == NULL\n");
439 return DSERR_INVALIDPARAM;
442 if (This->initialized == FALSE) {
443 WARN("not initialized\n");
444 return DSERR_UNINITIALIZED;
447 if (lpDSCaps == NULL) {
448 WARN("invalid parameter: lpDSCaps = NULL\n");
449 return DSERR_INVALIDPARAM;
452 /* check if there is enough room */
453 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
454 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
455 lpDSCaps->dwSize, sizeof(*lpDSCaps));
456 return DSERR_INVALIDPARAM;
459 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
460 if (TRACE_ON(dsound)) {
461 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
462 _dump_DSCAPS(lpDSCaps->dwFlags);
463 DPRINTF(")\n");
465 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
466 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
467 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
468 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
469 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
470 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
471 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
472 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
473 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
474 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
475 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
476 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
477 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
478 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
479 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
480 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
481 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
482 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
484 /* driver doesn't have these */
485 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
486 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
488 return DS_OK;
491 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
492 LPDIRECTSOUND8 iface,
493 LPDIRECTSOUNDBUFFER psb,
494 LPLPDIRECTSOUNDBUFFER ppdsb)
496 IDirectSoundBufferImpl* pdsb;
497 IDirectSoundBufferImpl* dsb;
498 HRESULT hres = DS_OK;
499 int size;
500 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
502 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
504 if (This == NULL) {
505 WARN("invalid parameter: This == NULL\n");
506 return DSERR_INVALIDPARAM;
509 if (This->initialized == FALSE) {
510 WARN("not initialized\n");
511 return DSERR_UNINITIALIZED;
514 if (psb == NULL) {
515 WARN("invalid parameter: psb == NULL\n");
516 return DSERR_INVALIDPARAM;
519 if (ppdsb == NULL) {
520 WARN("invalid parameter: ppdsb == NULL\n");
521 return DSERR_INVALIDPARAM;
524 /* FIXME: hack to make sure we have a secondary buffer */
525 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
526 WARN("trying to duplicate primary buffer\n");
527 *ppdsb = NULL;
528 return DSERR_INVALIDCALL;
531 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
533 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
535 if (dsb == NULL) {
536 WARN("out of memory\n");
537 *ppdsb = NULL;
538 return DSERR_OUTOFMEMORY;
541 memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
543 if (pdsb->hwbuf) {
544 TRACE("duplicating hardware buffer\n");
546 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
547 if (hres != DS_OK) {
548 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
549 dsb->hwbuf = NULL;
550 /* allocate buffer */
551 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
552 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
553 if (dsb->buffer == NULL) {
554 WARN("out of memory\n");
555 HeapFree(GetProcessHeap(),0,dsb);
556 *ppdsb = NULL;
557 return DSERR_OUTOFMEMORY;
560 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
561 if (dsb->buffer->memory == NULL) {
562 WARN("out of memory\n");
563 HeapFree(GetProcessHeap(),0,dsb->buffer);
564 HeapFree(GetProcessHeap(),0,dsb);
565 *ppdsb = NULL;
566 return DSERR_OUTOFMEMORY;
568 dsb->buffer->ref = 1;
570 /* FIXME: copy buffer ? */
573 } else {
574 dsb->hwbuf = NULL;
575 dsb->buffer->ref++;
578 dsb->ref = 0;
579 dsb->state = STATE_STOPPED;
580 dsb->playpos = 0;
581 dsb->buf_mixpos = 0;
582 dsb->dsound = This;
583 dsb->ds3db = NULL;
584 dsb->iks = NULL; /* FIXME? */
585 dsb->dsb = NULL;
587 /* variable sized struct so calculate size based on format */
588 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
590 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
591 if (dsb->pwfx == NULL) {
592 WARN("out of memory\n");
593 HeapFree(GetProcessHeap(),0,dsb->buffer);
594 HeapFree(GetProcessHeap(),0,dsb);
595 *ppdsb = NULL;
596 return DSERR_OUTOFMEMORY;
599 memcpy(dsb->pwfx, pdsb->pwfx, size);
601 InitializeCriticalSection(&(dsb->lock));
602 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
604 /* register buffer */
605 hres = DSOUND_AddBuffer(This, dsb);
606 if (hres != DS_OK) {
607 IDirectSoundBuffer8_Release(psb);
608 dsb->lock.DebugInfo->Spare[1] = 0;
609 DeleteCriticalSection(&(dsb->lock));
610 HeapFree(GetProcessHeap(),0,dsb->buffer);
611 HeapFree(GetProcessHeap(),0,dsb->pwfx);
612 HeapFree(GetProcessHeap(),0,dsb);
613 *ppdsb = 0;
614 } else {
615 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
616 if (*ppdsb) {
617 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
618 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
619 } else
620 WARN("SecondaryBufferImpl_Create failed\n");
623 return hres;
626 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
627 LPDIRECTSOUND8 iface,
628 HWND hwnd,
629 DWORD level)
631 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
632 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
634 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
635 FIXME("level=%s not fully supported\n",
636 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
638 This->priolevel = level;
639 return DS_OK;
642 static HRESULT WINAPI IDirectSoundImpl_Compact(
643 LPDIRECTSOUND8 iface)
645 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
646 TRACE("(%p)\n",This);
648 if (This->initialized == FALSE) {
649 WARN("not initialized\n");
650 return DSERR_UNINITIALIZED;
653 if (This->priolevel != DSSCL_PRIORITY) {
654 WARN("incorrect priority level\n");
655 return DSERR_PRIOLEVELNEEDED;
658 return DS_OK;
661 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
662 LPDIRECTSOUND8 iface,
663 LPDWORD lpdwSpeakerConfig)
665 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
666 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
668 if (This->initialized == FALSE) {
669 WARN("not initialized\n");
670 return DSERR_UNINITIALIZED;
673 if (lpdwSpeakerConfig == NULL) {
674 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
675 return DSERR_INVALIDPARAM;
678 WARN("not fully functional\n");
679 *lpdwSpeakerConfig = This->speaker_config;
680 return DS_OK;
683 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
684 LPDIRECTSOUND8 iface,
685 DWORD config)
687 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
688 TRACE("(%p,0x%08lx)\n",This,config);
690 if (This->initialized == FALSE) {
691 WARN("not initialized\n");
692 return DSERR_UNINITIALIZED;
695 This->speaker_config = config;
696 WARN("not fully functional\n");
697 return DS_OK;
700 static HRESULT WINAPI IDirectSoundImpl_Initialize(
701 LPDIRECTSOUND8 iface,
702 LPCGUID lpcGuid)
704 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
705 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
707 This->initialized = TRUE;
709 return DS_OK;
712 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
713 LPDIRECTSOUND8 iface,
714 LPDWORD pdwCertified)
716 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
717 TRACE("(%p, %p)\n",This,pdwCertified);
719 if (This->initialized == FALSE) {
720 WARN("not initialized\n");
721 return DSERR_UNINITIALIZED;
724 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
725 *pdwCertified = DS_CERTIFIED;
726 else
727 *pdwCertified = DS_UNCERTIFIED;
728 return DS_OK;
731 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
733 IDirectSoundImpl_QueryInterface,
734 IDirectSoundImpl_AddRef,
735 IDirectSoundImpl_Release,
736 IDirectSoundImpl_CreateSoundBuffer,
737 IDirectSoundImpl_GetCaps,
738 IDirectSoundImpl_DuplicateSoundBuffer,
739 IDirectSoundImpl_SetCooperativeLevel,
740 IDirectSoundImpl_Compact,
741 IDirectSoundImpl_GetSpeakerConfig,
742 IDirectSoundImpl_SetSpeakerConfig,
743 IDirectSoundImpl_Initialize,
744 IDirectSoundImpl_VerifyCertification
747 HRESULT WINAPI IDirectSoundImpl_Create(
748 LPCGUID lpcGUID,
749 LPDIRECTSOUND8 * ppDS)
751 HRESULT err;
752 PIDSDRIVER drv = NULL;
753 IDirectSoundImpl* pDS;
754 unsigned wod, wodn;
755 BOOLEAN found = FALSE;
756 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
758 /* Enumerate WINMM audio devices and find the one we want */
759 wodn = waveOutGetNumDevs();
760 if (!wodn) {
761 WARN("no driver\n");
762 *ppDS = NULL;
763 return DSERR_NODRIVER;
766 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
768 for (wod=0; wod<wodn; wod++) {
769 if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
770 found = TRUE;
771 break;
775 if (found == FALSE) {
776 WARN("No device found matching given ID!\n");
777 *ppDS = NULL;
778 return DSERR_NODRIVER;
781 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
782 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
784 /* Disable the direct sound driver to force emulation if requested. */
785 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
786 drv = NULL;
788 /* Allocate memory */
789 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
790 if (ppDS == NULL) {
791 WARN("out of memory\n");
792 *ppDS = NULL;
793 return DSERR_OUTOFMEMORY;
796 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
797 pDS->ref = 0;
799 pDS->driver = drv;
800 pDS->priolevel = DSSCL_NORMAL;
801 pDS->fraglen = 0;
802 pDS->hwbuf = NULL;
803 pDS->buffer = NULL;
804 pDS->buflen = 0;
805 pDS->writelead = 0;
806 pDS->state = STATE_STOPPED;
807 pDS->nrofbuffers = 0;
808 pDS->buffers = NULL;
809 pDS->primary = NULL;
810 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
811 pDS->initialized = FALSE;
813 /* 3D listener initial parameters */
814 pDS->listener = NULL;
815 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
816 pDS->ds3dl.vPosition.x = 0.0;
817 pDS->ds3dl.vPosition.y = 0.0;
818 pDS->ds3dl.vPosition.z = 0.0;
819 pDS->ds3dl.vVelocity.x = 0.0;
820 pDS->ds3dl.vVelocity.y = 0.0;
821 pDS->ds3dl.vVelocity.z = 0.0;
822 pDS->ds3dl.vOrientFront.x = 0.0;
823 pDS->ds3dl.vOrientFront.y = 0.0;
824 pDS->ds3dl.vOrientFront.z = 1.0;
825 pDS->ds3dl.vOrientTop.x = 0.0;
826 pDS->ds3dl.vOrientTop.y = 1.0;
827 pDS->ds3dl.vOrientTop.z = 0.0;
828 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
829 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
830 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
832 pDS->prebuf = ds_snd_queue_max;
833 pDS->guid = *lpcGUID;
835 /* Get driver description */
836 if (drv) {
837 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
838 if (err != DS_OK) {
839 WARN("IDsDriver_GetDriverDesc failed\n");
840 HeapFree(GetProcessHeap(),0,pDS);
841 *ppDS = NULL;
842 return err;
844 } else {
845 /* if no DirectSound interface available, use WINMM API instead */
846 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
849 pDS->drvdesc.dnDevNode = wod;
851 /* Set default wave format (may need it for waveOutOpen) */
852 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
853 if (pDS->pwfx == NULL) {
854 WARN("out of memory\n");
855 HeapFree(GetProcessHeap(),0,pDS);
856 *ppDS = NULL;
857 return DSERR_OUTOFMEMORY;
860 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
861 /* We rely on the sound driver to return the actual sound format of
862 * the device if it does not support 22050x8x2 and is given the
863 * WAVE_DIRECTSOUND flag.
865 pDS->pwfx->nSamplesPerSec = 22050;
866 pDS->pwfx->wBitsPerSample = 8;
867 pDS->pwfx->nChannels = 2;
868 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
869 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
870 pDS->pwfx->cbSize = 0;
872 /* If the driver requests being opened through MMSYSTEM
873 * (which is recommended by the DDK), it is supposed to happen
874 * before the DirectSound interface is opened */
875 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
877 DWORD flags = CALLBACK_FUNCTION;
879 /* disable direct sound if requested */
880 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
881 flags |= WAVE_DIRECTSOUND;
883 err = mmErr(waveOutOpen(&(pDS->hwo),
884 pDS->drvdesc.dnDevNode, pDS->pwfx,
885 (DWORD)DSOUND_callback, (DWORD)pDS,
886 flags));
887 if (err != DS_OK) {
888 WARN("waveOutOpen failed\n");
889 HeapFree(GetProcessHeap(),0,pDS);
890 *ppDS = NULL;
891 return err;
895 if (drv) {
896 err = IDsDriver_Open(drv);
897 if (err != DS_OK) {
898 WARN("IDsDriver_Open failed\n");
899 HeapFree(GetProcessHeap(),0,pDS);
900 *ppDS = NULL;
901 return err;
904 /* the driver is now open, so it's now allowed to call GetCaps */
905 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
906 if (err != DS_OK) {
907 WARN("IDsDriver_GetCaps failed\n");
908 HeapFree(GetProcessHeap(),0,pDS);
909 *ppDS = NULL;
910 return err;
912 } else {
913 WAVEOUTCAPSA woc;
914 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
915 if (err != DS_OK) {
916 WARN("waveOutGetDevCaps failed\n");
917 HeapFree(GetProcessHeap(),0,pDS);
918 *ppDS = NULL;
919 return err;
921 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
922 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
923 (woc.dwFormats & WAVE_FORMAT_2M08) ||
924 (woc.dwFormats & WAVE_FORMAT_4M08) ||
925 (woc.dwFormats & WAVE_FORMAT_48M08) ||
926 (woc.dwFormats & WAVE_FORMAT_96M08)) {
927 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
928 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
930 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
931 (woc.dwFormats & WAVE_FORMAT_2M16) ||
932 (woc.dwFormats & WAVE_FORMAT_4M16) ||
933 (woc.dwFormats & WAVE_FORMAT_48M16) ||
934 (woc.dwFormats & WAVE_FORMAT_96M16)) {
935 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
936 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
938 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
939 (woc.dwFormats & WAVE_FORMAT_2S08) ||
940 (woc.dwFormats & WAVE_FORMAT_4S08) ||
941 (woc.dwFormats & WAVE_FORMAT_48S08) ||
942 (woc.dwFormats & WAVE_FORMAT_96S08)) {
943 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
944 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
946 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
947 (woc.dwFormats & WAVE_FORMAT_2S16) ||
948 (woc.dwFormats & WAVE_FORMAT_4S16) ||
949 (woc.dwFormats & WAVE_FORMAT_48S16) ||
950 (woc.dwFormats & WAVE_FORMAT_96S16)) {
951 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
952 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
954 if (ds_emuldriver)
955 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
956 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
957 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
958 pDS->drvcaps.dwPrimaryBuffers = 1;
961 InitializeCriticalSection(&(pDS->mixlock));
962 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
964 RtlInitializeResource(&(pDS->buffer_list_lock));
966 *ppDS = (LPDIRECTSOUND8)pDS;
968 return DS_OK;
970 /*******************************************************************************
971 * IDirectSound_IUnknown
973 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
974 LPUNKNOWN iface,
975 REFIID riid,
976 LPVOID * ppobj)
978 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
979 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
980 return DSOUND_QueryInterface(This->pds, riid, ppobj);
983 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
984 LPUNKNOWN iface)
986 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
987 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
988 return InterlockedIncrement(&This->ref);
991 static ULONG WINAPI IDirectSound_IUnknown_Release(
992 LPUNKNOWN iface)
994 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
995 ULONG ulReturn;
996 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
997 ulReturn = InterlockedDecrement(&This->ref);
998 if (ulReturn == 0) {
999 IDirectSoundImpl_Release(This->pds);
1000 HeapFree(GetProcessHeap(),0,This);
1001 TRACE("(%p) released\n",This);
1003 return ulReturn;
1006 static IUnknownVtbl DirectSound_Unknown_Vtbl =
1008 IDirectSound_IUnknown_QueryInterface,
1009 IDirectSound_IUnknown_AddRef,
1010 IDirectSound_IUnknown_Release
1013 HRESULT WINAPI IDirectSound_IUnknown_Create(
1014 LPDIRECTSOUND8 pds,
1015 LPUNKNOWN * ppunk)
1017 IDirectSound_IUnknown * pdsunk;
1018 TRACE("(%p,%p)\n",pds,ppunk);
1020 if (ppunk == NULL) {
1021 ERR("invalid parameter: ppunk == NULL\n");
1022 return DSERR_INVALIDPARAM;
1025 if (pds == NULL) {
1026 ERR("invalid parameter: pds == NULL\n");
1027 *ppunk = NULL;
1028 return DSERR_INVALIDPARAM;
1031 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1032 if (pdsunk == NULL) {
1033 WARN("out of memory\n");
1034 *ppunk = NULL;
1035 return DSERR_OUTOFMEMORY;
1038 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1039 pdsunk->ref = 0;
1040 pdsunk->pds = pds;
1042 IDirectSoundImpl_AddRef(pds);
1043 *ppunk = (LPUNKNOWN)pdsunk;
1045 return DS_OK;
1048 /*******************************************************************************
1049 * IDirectSound_IDirectSound
1051 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1052 LPDIRECTSOUND iface,
1053 REFIID riid,
1054 LPVOID * ppobj)
1056 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1057 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1058 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1061 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1062 LPDIRECTSOUND iface)
1064 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1065 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1066 return InterlockedIncrement(&This->ref);
1069 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1070 LPDIRECTSOUND iface)
1072 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1073 ULONG ulReturn;
1074 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1075 ulReturn = InterlockedDecrement(&This->ref);
1076 if (ulReturn == 0) {
1077 IDirectSoundImpl_Release(This->pds);
1078 HeapFree(GetProcessHeap(),0,This);
1079 TRACE("(%p) released\n",This);
1081 return ulReturn;
1084 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1085 LPDIRECTSOUND iface,
1086 LPCDSBUFFERDESC dsbd,
1087 LPLPDIRECTSOUNDBUFFER ppdsb,
1088 LPUNKNOWN lpunk)
1090 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1091 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1092 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1095 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1096 LPDIRECTSOUND iface,
1097 LPDSCAPS lpDSCaps)
1099 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1100 TRACE("(%p,%p)\n",This,lpDSCaps);
1101 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1104 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1105 LPDIRECTSOUND iface,
1106 LPDIRECTSOUNDBUFFER psb,
1107 LPLPDIRECTSOUNDBUFFER ppdsb)
1109 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1110 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1111 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1114 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1115 LPDIRECTSOUND iface,
1116 HWND hwnd,
1117 DWORD level)
1119 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1120 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1121 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1124 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1125 LPDIRECTSOUND iface)
1127 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1128 TRACE("(%p)\n", This);
1129 return IDirectSoundImpl_Compact(This->pds);
1132 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1133 LPDIRECTSOUND iface,
1134 LPDWORD lpdwSpeakerConfig)
1136 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1137 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1138 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1141 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1142 LPDIRECTSOUND iface,
1143 DWORD config)
1145 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1146 TRACE("(%p,0x%08lx)\n",This,config);
1147 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1150 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1151 LPDIRECTSOUND iface,
1152 LPCGUID lpcGuid)
1154 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1155 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1156 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1159 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1161 IDirectSound_IDirectSound_QueryInterface,
1162 IDirectSound_IDirectSound_AddRef,
1163 IDirectSound_IDirectSound_Release,
1164 IDirectSound_IDirectSound_CreateSoundBuffer,
1165 IDirectSound_IDirectSound_GetCaps,
1166 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1167 IDirectSound_IDirectSound_SetCooperativeLevel,
1168 IDirectSound_IDirectSound_Compact,
1169 IDirectSound_IDirectSound_GetSpeakerConfig,
1170 IDirectSound_IDirectSound_SetSpeakerConfig,
1171 IDirectSound_IDirectSound_Initialize
1174 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1175 LPDIRECTSOUND8 pds,
1176 LPDIRECTSOUND * ppds)
1178 IDirectSound_IDirectSound * pdsds;
1179 TRACE("(%p,%p)\n",pds,ppds);
1181 if (ppds == NULL) {
1182 ERR("invalid parameter: ppds == NULL\n");
1183 return DSERR_INVALIDPARAM;
1186 if (pds == NULL) {
1187 ERR("invalid parameter: pds == NULL\n");
1188 *ppds = NULL;
1189 return DSERR_INVALIDPARAM;
1192 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1193 if (pdsds == NULL) {
1194 WARN("out of memory\n");
1195 *ppds = NULL;
1196 return DSERR_OUTOFMEMORY;
1199 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1200 pdsds->ref = 0;
1201 pdsds->pds = pds;
1203 IDirectSoundImpl_AddRef(pds);
1204 *ppds = (LPDIRECTSOUND)pdsds;
1206 return DS_OK;
1209 /*******************************************************************************
1210 * IDirectSound8_IUnknown
1212 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1213 LPUNKNOWN iface,
1214 REFIID riid,
1215 LPVOID * ppobj)
1217 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1218 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1219 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1222 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1223 LPUNKNOWN iface)
1225 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1226 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1227 return InterlockedIncrement(&This->ref);
1230 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1231 LPUNKNOWN iface)
1233 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1234 ULONG ulReturn;
1235 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1236 ulReturn = InterlockedDecrement(&This->ref);
1237 if (ulReturn == 0) {
1238 IDirectSoundImpl_Release(This->pds);
1239 HeapFree(GetProcessHeap(),0,This);
1240 TRACE("(%p) released\n",This);
1242 return ulReturn;
1245 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1247 IDirectSound8_IUnknown_QueryInterface,
1248 IDirectSound8_IUnknown_AddRef,
1249 IDirectSound8_IUnknown_Release
1252 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1253 LPDIRECTSOUND8 pds,
1254 LPUNKNOWN * ppunk)
1256 IDirectSound8_IUnknown * pdsunk;
1257 TRACE("(%p,%p)\n",pds,ppunk);
1259 if (ppunk == NULL) {
1260 ERR("invalid parameter: ppunk == NULL\n");
1261 return DSERR_INVALIDPARAM;
1264 if (pds == NULL) {
1265 ERR("invalid parameter: pds == NULL\n");
1266 *ppunk = NULL;
1267 return DSERR_INVALIDPARAM;
1270 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1271 if (pdsunk == NULL) {
1272 WARN("out of memory\n");
1273 *ppunk = NULL;
1274 return DSERR_OUTOFMEMORY;
1277 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1278 pdsunk->ref = 0;
1279 pdsunk->pds = pds;
1281 IDirectSoundImpl_AddRef(pds);
1282 *ppunk = (LPUNKNOWN)pdsunk;
1284 return DS_OK;
1287 /*******************************************************************************
1288 * IDirectSound8_IDirectSound
1290 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1291 LPDIRECTSOUND iface,
1292 REFIID riid,
1293 LPVOID * ppobj)
1295 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1296 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1297 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1300 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1301 LPDIRECTSOUND iface)
1303 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1304 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1305 return InterlockedIncrement(&This->ref);
1308 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1309 LPDIRECTSOUND iface)
1311 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1312 ULONG ulReturn;
1313 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1314 ulReturn = InterlockedDecrement(&This->ref);
1315 if (ulReturn == 0) {
1316 IDirectSoundImpl_Release(This->pds);
1317 HeapFree(GetProcessHeap(),0,This);
1318 TRACE("(%p) released\n",This);
1320 return ulReturn;
1323 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1324 LPDIRECTSOUND iface,
1325 LPCDSBUFFERDESC dsbd,
1326 LPLPDIRECTSOUNDBUFFER ppdsb,
1327 LPUNKNOWN lpunk)
1329 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1330 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1331 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1334 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1335 LPDIRECTSOUND iface,
1336 LPDSCAPS lpDSCaps)
1338 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1339 TRACE("(%p,%p)\n",This,lpDSCaps);
1340 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1343 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1344 LPDIRECTSOUND iface,
1345 LPDIRECTSOUNDBUFFER psb,
1346 LPLPDIRECTSOUNDBUFFER ppdsb)
1348 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1349 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1350 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1353 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1354 LPDIRECTSOUND iface,
1355 HWND hwnd,
1356 DWORD level)
1358 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1359 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1360 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1363 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1364 LPDIRECTSOUND iface)
1366 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1367 TRACE("(%p)\n", This);
1368 return IDirectSoundImpl_Compact(This->pds);
1371 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1372 LPDIRECTSOUND iface,
1373 LPDWORD lpdwSpeakerConfig)
1375 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1376 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1377 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1380 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1381 LPDIRECTSOUND iface,
1382 DWORD config)
1384 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1385 TRACE("(%p,0x%08lx)\n",This,config);
1386 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1389 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1390 LPDIRECTSOUND iface,
1391 LPCGUID lpcGuid)
1393 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1394 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1395 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1398 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1400 IDirectSound8_IDirectSound_QueryInterface,
1401 IDirectSound8_IDirectSound_AddRef,
1402 IDirectSound8_IDirectSound_Release,
1403 IDirectSound8_IDirectSound_CreateSoundBuffer,
1404 IDirectSound8_IDirectSound_GetCaps,
1405 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1406 IDirectSound8_IDirectSound_SetCooperativeLevel,
1407 IDirectSound8_IDirectSound_Compact,
1408 IDirectSound8_IDirectSound_GetSpeakerConfig,
1409 IDirectSound8_IDirectSound_SetSpeakerConfig,
1410 IDirectSound8_IDirectSound_Initialize
1413 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1414 LPDIRECTSOUND8 pds,
1415 LPDIRECTSOUND * ppds)
1417 IDirectSound8_IDirectSound * pdsds;
1418 TRACE("(%p,%p)\n",pds,ppds);
1420 if (ppds == NULL) {
1421 ERR("invalid parameter: ppds == NULL\n");
1422 return DSERR_INVALIDPARAM;
1425 if (pds == NULL) {
1426 ERR("invalid parameter: pds == NULL\n");
1427 *ppds = NULL;
1428 return DSERR_INVALIDPARAM;
1431 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1432 if (pdsds == NULL) {
1433 WARN("out of memory\n");
1434 *ppds = NULL;
1435 return DSERR_OUTOFMEMORY;
1438 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1439 pdsds->ref = 0;
1440 pdsds->pds = pds;
1442 IDirectSoundImpl_AddRef(pds);
1443 *ppds = (LPDIRECTSOUND)pdsds;
1445 return DS_OK;
1448 /*******************************************************************************
1449 * IDirectSound8_IDirectSound8
1451 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1452 LPDIRECTSOUND8 iface,
1453 REFIID riid,
1454 LPVOID * ppobj)
1456 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1457 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1458 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1461 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1462 LPDIRECTSOUND8 iface)
1464 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1465 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1466 return InterlockedIncrement(&This->ref);
1469 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1470 LPDIRECTSOUND8 iface)
1472 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1473 ULONG ulReturn;
1474 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1475 ulReturn = InterlockedDecrement(&This->ref);
1476 if (ulReturn == 0) {
1477 IDirectSoundImpl_Release(This->pds);
1478 HeapFree(GetProcessHeap(),0,This);
1479 TRACE("(%p) released\n",This);
1481 return ulReturn;
1484 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1485 LPDIRECTSOUND8 iface,
1486 LPCDSBUFFERDESC dsbd,
1487 LPLPDIRECTSOUNDBUFFER ppdsb,
1488 LPUNKNOWN lpunk)
1490 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1491 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1492 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1495 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1496 LPDIRECTSOUND8 iface,
1497 LPDSCAPS lpDSCaps)
1499 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1500 TRACE("(%p,%p)\n",This,lpDSCaps);
1501 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1504 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1505 LPDIRECTSOUND8 iface,
1506 LPDIRECTSOUNDBUFFER psb,
1507 LPLPDIRECTSOUNDBUFFER ppdsb)
1509 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1510 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1511 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1514 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1515 LPDIRECTSOUND8 iface,
1516 HWND hwnd,
1517 DWORD level)
1519 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1520 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1521 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1524 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1525 LPDIRECTSOUND8 iface)
1527 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1528 TRACE("(%p)\n", This);
1529 return IDirectSoundImpl_Compact(This->pds);
1532 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1533 LPDIRECTSOUND8 iface,
1534 LPDWORD lpdwSpeakerConfig)
1536 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1537 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1538 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1541 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1542 LPDIRECTSOUND8 iface,
1543 DWORD config)
1545 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1546 TRACE("(%p,0x%08lx)\n",This,config);
1547 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1550 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1551 LPDIRECTSOUND8 iface,
1552 LPCGUID lpcGuid)
1554 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1555 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1556 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1559 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1560 LPDIRECTSOUND8 iface,
1561 LPDWORD pdwCertified)
1563 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1564 TRACE("(%p, %p)\n", This, pdwCertified);
1565 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1568 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1570 IDirectSound8_IDirectSound8_QueryInterface,
1571 IDirectSound8_IDirectSound8_AddRef,
1572 IDirectSound8_IDirectSound8_Release,
1573 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1574 IDirectSound8_IDirectSound8_GetCaps,
1575 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1576 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1577 IDirectSound8_IDirectSound8_Compact,
1578 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1579 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1580 IDirectSound8_IDirectSound8_Initialize,
1581 IDirectSound8_IDirectSound8_VerifyCertification
1584 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1585 LPDIRECTSOUND8 pds,
1586 LPDIRECTSOUND8 * ppds)
1588 IDirectSound8_IDirectSound8 * pdsds;
1589 TRACE("(%p,%p)\n",pds,ppds);
1591 if (ppds == NULL) {
1592 ERR("invalid parameter: ppds == NULL\n");
1593 return DSERR_INVALIDPARAM;
1596 if (pds == NULL) {
1597 ERR("invalid parameter: pds == NULL\n");
1598 *ppds = NULL;
1599 return DSERR_INVALIDPARAM;
1602 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1603 if (pdsds == NULL) {
1604 WARN("out of memory\n");
1605 *ppds = NULL;
1606 return DSERR_OUTOFMEMORY;
1609 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1610 pdsds->ref = 0;
1611 pdsds->pds = pds;
1613 IDirectSoundImpl_AddRef(pds);
1614 *ppds = (LPDIRECTSOUND8)pdsds;
1616 return DS_OK;
1619 HRESULT WINAPI DSOUND_Create(
1620 LPCGUID lpcGUID,
1621 LPDIRECTSOUND *ppDS,
1622 IUnknown *pUnkOuter)
1624 HRESULT hr;
1625 GUID devGuid;
1627 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1629 if (pUnkOuter != NULL) {
1630 WARN("invalid parameter: pUnkOuter != NULL\n");
1631 return DSERR_INVALIDPARAM;
1634 if (ppDS == NULL) {
1635 WARN("invalid parameter: ppDS == NULL\n");
1636 return DSERR_INVALIDPARAM;
1639 /* Get dsound configuration */
1640 setup_dsound_options();
1642 /* Default device? */
1643 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1644 lpcGUID = &DSDEVID_DefaultPlayback;
1646 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1647 WARN("invalid parameter: lpcGUID\n");
1648 *ppDS = NULL;
1649 return DSERR_INVALIDPARAM;
1652 if (dsound) {
1653 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1654 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1655 if (*ppDS)
1656 IDirectSound_IDirectSound_AddRef(*ppDS);
1657 else
1658 WARN("IDirectSound_IDirectSound_Create failed\n");
1659 } else {
1660 ERR("different dsound already opened (only support one sound card at a time now)\n");
1661 *ppDS = NULL;
1662 hr = DSERR_ALLOCATED;
1664 } else {
1665 LPDIRECTSOUND8 pDS;
1666 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1667 if (hr == DS_OK) {
1668 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1669 if (hr == DS_OK) {
1670 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1671 if (*ppDS) {
1672 IDirectSound_IDirectSound_AddRef(*ppDS);
1674 dsound = (IDirectSoundImpl*)pDS;
1675 timeBeginPeriod(DS_TIME_RES);
1676 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1677 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1678 } else {
1679 WARN("IDirectSound_IDirectSound_Create failed\n");
1680 IDirectSound8_Release(pDS);
1682 } else {
1683 WARN("DSOUND_PrimaryCreate failed\n");
1684 IDirectSound8_Release(pDS);
1686 } else
1687 WARN("IDirectSoundImpl_Create failed\n");
1690 return hr;
1693 /*******************************************************************************
1694 * DirectSoundCreate (DSOUND.1)
1696 * Creates and initializes a DirectSound interface.
1698 * PARAMS
1699 * lpcGUID [I] Address of the GUID that identifies the sound device.
1700 * ppDS [O] Address of a variable to receive the interface pointer.
1701 * pUnkOuter [I] Must be NULL.
1703 * RETURNS
1704 * Success: DS_OK
1705 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1706 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1708 HRESULT WINAPI DirectSoundCreate(
1709 LPCGUID lpcGUID,
1710 LPDIRECTSOUND *ppDS,
1711 IUnknown *pUnkOuter)
1713 HRESULT hr;
1715 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1717 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1718 if (hr == DS_OK)
1719 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1721 return hr;
1724 HRESULT WINAPI DSOUND_Create8(
1725 LPCGUID lpcGUID,
1726 LPDIRECTSOUND8 *ppDS,
1727 IUnknown *pUnkOuter)
1729 HRESULT hr;
1730 GUID devGuid;
1732 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1734 if (pUnkOuter != NULL) {
1735 WARN("invalid parameter: pUnkOuter != NULL\n");
1736 return DSERR_INVALIDPARAM;
1739 if (ppDS == NULL) {
1740 WARN("invalid parameter: ppDS == NULL\n");
1741 return DSERR_INVALIDPARAM;
1744 /* Get dsound configuration */
1745 setup_dsound_options();
1747 /* Default device? */
1748 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1749 lpcGUID = &DSDEVID_DefaultPlayback;
1751 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1752 WARN("invalid parameter: lpcGUID\n");
1753 *ppDS = NULL;
1754 return DSERR_INVALIDPARAM;
1757 if (dsound) {
1758 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1759 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1760 if (*ppDS)
1761 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1762 else
1763 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1764 } else {
1765 ERR("different dsound already opened (only support one sound card at a time now)\n");
1766 *ppDS = NULL;
1767 hr = DSERR_ALLOCATED;
1769 } else {
1770 LPDIRECTSOUND8 pDS;
1771 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1772 if (hr == DS_OK) {
1773 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1774 if (hr == DS_OK) {
1775 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1776 if (*ppDS) {
1777 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1779 dsound = (IDirectSoundImpl*)pDS;
1780 timeBeginPeriod(DS_TIME_RES);
1781 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1782 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1783 } else {
1784 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1785 IDirectSound8_Release(pDS);
1787 } else {
1788 WARN("DSOUND_PrimaryCreate failed\n");
1789 IDirectSound8_Release(pDS);
1791 } else
1792 WARN("IDirectSoundImpl_Create failed\n");
1795 return hr;
1798 /*******************************************************************************
1799 * DirectSoundCreate8 (DSOUND.11)
1801 * Creates and initializes a DirectSound8 interface.
1803 * PARAMS
1804 * lpcGUID [I] Address of the GUID that identifies the sound device.
1805 * ppDS [O] Address of a variable to receive the interface pointer.
1806 * pUnkOuter [I] Must be NULL.
1808 * RETURNS
1809 * Success: DS_OK
1810 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1811 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1813 HRESULT WINAPI DirectSoundCreate8(
1814 LPCGUID lpcGUID,
1815 LPDIRECTSOUND8 *ppDS,
1816 IUnknown *pUnkOuter)
1818 HRESULT hr;
1820 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1822 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1823 if (hr == DS_OK)
1824 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1826 return hr;
1830 * Add secondary buffer to buffer list.
1831 * Gets exclusive access to buffer for writing.
1833 HRESULT DSOUND_AddBuffer(
1834 IDirectSoundImpl * pDS,
1835 IDirectSoundBufferImpl * pDSB)
1837 IDirectSoundBufferImpl **newbuffers;
1838 HRESULT hr = DS_OK;
1840 TRACE("(%p, %p)\n", pDS, pDSB);
1842 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1844 if (pDS->buffers)
1845 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1846 else
1847 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1849 if (newbuffers) {
1850 pDS->buffers = newbuffers;
1851 pDS->buffers[pDS->nrofbuffers] = pDSB;
1852 pDS->nrofbuffers++;
1853 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1854 } else {
1855 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
1856 hr = DSERR_OUTOFMEMORY;
1859 RtlReleaseResource(&(pDS->buffer_list_lock));
1861 return hr;
1865 * Remove secondary buffer from buffer list.
1866 * Gets exclusive access to buffer for writing.
1868 HRESULT DSOUND_RemoveBuffer(
1869 IDirectSoundImpl * pDS,
1870 IDirectSoundBufferImpl * pDSB)
1872 int i;
1873 HRESULT hr = DS_OK;
1875 TRACE("(%p, %p)\n", pDS, pDSB);
1877 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1879 for (i = 0; i < pDS->nrofbuffers; i++)
1880 if (pDS->buffers[i] == pDSB)
1881 break;
1883 if (i < pDS->nrofbuffers) {
1884 /* Put the last buffer of the list in the (now empty) position */
1885 pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
1886 pDS->nrofbuffers--;
1887 pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
1888 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1891 if (pDS->nrofbuffers == 0) {
1892 HeapFree(GetProcessHeap(),0,pDS->buffers);
1893 pDS->buffers = NULL;
1896 RtlReleaseResource(&(pDS->buffer_list_lock));
1898 return hr;