Consolidate secondary buffer list processing and locking.
[wine/dcerpc.git] / dlls / dsound / dsound.c
bloba119a7ab261be439e9f61db7263fce7364efe00d
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 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 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 ICOM_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 ICOM_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 ICOM_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 ICOM_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 UINT 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 DeleteCriticalSection(&This->mixlock);
306 HeapFree(GetProcessHeap(),0,This);
307 dsound = NULL;
308 TRACE("(%p) released\n",This);
311 return ref;
314 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
315 LPDIRECTSOUND8 iface,
316 LPCDSBUFFERDESC dsbd,
317 LPLPDIRECTSOUNDBUFFER ppdsb,
318 LPUNKNOWN lpunk)
320 ICOM_THIS(IDirectSoundImpl,iface);
321 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
322 FIXME("shouldn't be called directly\n");
323 return DSERR_GENERIC;
326 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
327 LPDIRECTSOUND8 iface,
328 LPCDSBUFFERDESC dsbd,
329 LPLPDIRECTSOUNDBUFFER ppdsb,
330 LPUNKNOWN lpunk,
331 BOOL from8)
333 ICOM_THIS(IDirectSoundImpl,iface);
334 HRESULT hres = DS_OK;
335 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
337 if (This == NULL) {
338 WARN("invalid parameter: This == NULL\n");
339 return DSERR_INVALIDPARAM;
342 if (This->initialized == FALSE) {
343 WARN("not initialized\n");
344 return DSERR_UNINITIALIZED;
347 if (dsbd == NULL) {
348 WARN("invalid parameter: dsbd == NULL\n");
349 return DSERR_INVALIDPARAM;
352 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
353 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
354 WARN("invalid parameter: dsbd\n");
355 return DSERR_INVALIDPARAM;
358 if (ppdsb == NULL) {
359 WARN("invalid parameter: ppdsb == NULL\n");
360 return DSERR_INVALIDPARAM;
363 if (TRACE_ON(dsound)) {
364 TRACE("(structsize=%ld)\n",dsbd->dwSize);
365 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
366 _dump_DSBCAPS(dsbd->dwFlags);
367 DPRINTF(")\n");
368 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
369 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
372 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
373 if (dsbd->lpwfxFormat != NULL) {
374 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
375 "primary buffer\n");
376 return DSERR_INVALIDPARAM;
379 if (This->primary) {
380 WARN("Primary Buffer already created\n");
381 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
382 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
383 } else {
384 This->dsbd = *dsbd;
385 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
386 if (This->primary) {
387 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
388 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
389 } else
390 WARN("PrimaryBufferImpl_Create failed\n");
392 } else {
393 IDirectSoundBufferImpl * dsb;
395 if (dsbd->lpwfxFormat == NULL) {
396 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
397 "secondary buffer\n");
398 return DSERR_INVALIDPARAM;
401 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
402 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
403 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
404 dsbd->lpwfxFormat->nSamplesPerSec,
405 dsbd->lpwfxFormat->nAvgBytesPerSec,
406 dsbd->lpwfxFormat->nBlockAlign,
407 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
409 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
410 WARN("invalid parameter: 3D buffer format must be mono\n");
411 return DSERR_INVALIDPARAM;
414 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
415 if (dsb) {
416 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
417 if (*ppdsb) {
418 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
419 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
420 } else
421 WARN("SecondaryBufferImpl_Create failed\n");
422 } else
423 WARN("IDirectSoundBufferImpl_Create failed\n");
426 return hres;
429 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
430 LPDIRECTSOUND8 iface,
431 LPDSCAPS lpDSCaps)
433 ICOM_THIS(IDirectSoundImpl,iface);
434 TRACE("(%p,%p)\n",This,lpDSCaps);
436 if (This == NULL) {
437 WARN("invalid parameter: This == NULL\n");
438 return DSERR_INVALIDPARAM;
441 if (This->initialized == FALSE) {
442 WARN("not initialized\n");
443 return DSERR_UNINITIALIZED;
446 if (lpDSCaps == NULL) {
447 WARN("invalid parameter: lpDSCaps = NULL\n");
448 return DSERR_INVALIDPARAM;
451 /* check if there is enough room */
452 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
453 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
454 lpDSCaps->dwSize, sizeof(*lpDSCaps));
455 return DSERR_INVALIDPARAM;
458 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
459 if (TRACE_ON(dsound)) {
460 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
461 _dump_DSCAPS(lpDSCaps->dwFlags);
462 DPRINTF(")\n");
464 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
465 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
466 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
467 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
468 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
469 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
470 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
471 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
472 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
473 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
474 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
475 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
476 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
477 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
478 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
479 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
480 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
481 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
483 /* driver doesn't have these */
484 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
485 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
487 return DS_OK;
490 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
491 LPDIRECTSOUND8 iface,
492 LPDIRECTSOUNDBUFFER psb,
493 LPLPDIRECTSOUNDBUFFER ppdsb)
495 IDirectSoundBufferImpl* pdsb;
496 IDirectSoundBufferImpl* dsb;
497 HRESULT hres = DS_OK;
498 int size;
499 ICOM_THIS(IDirectSoundImpl,iface);
501 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
503 if (This == NULL) {
504 WARN("invalid parameter: This == NULL\n");
505 return DSERR_INVALIDPARAM;
508 if (This->initialized == FALSE) {
509 WARN("not initialized\n");
510 return DSERR_UNINITIALIZED;
513 if (psb == NULL) {
514 WARN("invalid parameter: psb == NULL\n");
515 return DSERR_INVALIDPARAM;
518 if (ppdsb == NULL) {
519 WARN("invalid parameter: ppdsb == NULL\n");
520 return DSERR_INVALIDPARAM;
523 /* FIXME: hack to make sure we have a secondary buffer */
524 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
525 WARN("trying to duplicate primary buffer\n");
526 *ppdsb = NULL;
527 return DSERR_INVALIDCALL;
530 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
532 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
534 if (dsb == NULL) {
535 WARN("out of memory\n");
536 *ppdsb = NULL;
537 return DSERR_OUTOFMEMORY;
540 memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
542 if (pdsb->hwbuf) {
543 TRACE("duplicating hardware buffer\n");
545 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
546 if (hres != DS_OK) {
547 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
548 dsb->hwbuf = NULL;
549 /* allocate buffer */
550 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
551 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
552 if (dsb->buffer == NULL) {
553 WARN("out of memory\n");
554 HeapFree(GetProcessHeap(),0,dsb);
555 *ppdsb = NULL;
556 return DSERR_OUTOFMEMORY;
559 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
560 if (dsb->buffer->memory == NULL) {
561 WARN("out of memory\n");
562 HeapFree(GetProcessHeap(),0,dsb->buffer);
563 HeapFree(GetProcessHeap(),0,dsb);
564 *ppdsb = NULL;
565 return DSERR_OUTOFMEMORY;
567 dsb->buffer->ref = 1;
569 /* FIXME: copy buffer ? */
572 } else {
573 dsb->hwbuf = NULL;
574 dsb->buffer->ref++;
577 dsb->ref = 0;
578 dsb->state = STATE_STOPPED;
579 dsb->playpos = 0;
580 dsb->buf_mixpos = 0;
581 dsb->dsound = This;
582 dsb->ds3db = NULL;
583 dsb->iks = NULL; /* FIXME? */
584 dsb->dsb = NULL;
586 /* variable sized struct so calculate size based on format */
587 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
589 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
590 if (dsb->pwfx == NULL) {
591 WARN("out of memory\n");
592 HeapFree(GetProcessHeap(),0,dsb->buffer);
593 HeapFree(GetProcessHeap(),0,dsb);
594 *ppdsb = NULL;
595 return DSERR_OUTOFMEMORY;
598 memcpy(dsb->pwfx, pdsb->pwfx, size);
600 InitializeCriticalSection(&(dsb->lock));
601 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
603 /* register buffer */
604 hres = DSOUND_AddBuffer(This, dsb);
605 if (hres != DS_OK) {
606 IDirectSoundBuffer8_Release(psb);
607 DeleteCriticalSection(&(dsb->lock));
608 HeapFree(GetProcessHeap(),0,dsb->buffer);
609 HeapFree(GetProcessHeap(),0,dsb->pwfx);
610 HeapFree(GetProcessHeap(),0,dsb);
611 *ppdsb = 0;
612 } else {
613 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
614 if (*ppdsb) {
615 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
616 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
617 } else
618 WARN("SecondaryBufferImpl_Create failed\n");
621 return hres;
624 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
625 LPDIRECTSOUND8 iface,
626 HWND hwnd,
627 DWORD level)
629 ICOM_THIS(IDirectSoundImpl,iface);
630 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
632 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
633 FIXME("level=%s not fully supported\n",
634 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
636 This->priolevel = level;
637 return DS_OK;
640 static HRESULT WINAPI IDirectSoundImpl_Compact(
641 LPDIRECTSOUND8 iface)
643 ICOM_THIS(IDirectSoundImpl,iface);
644 TRACE("(%p)\n",This);
646 if (This->initialized == FALSE) {
647 WARN("not initialized\n");
648 return DSERR_UNINITIALIZED;
651 if (This->priolevel != DSSCL_PRIORITY) {
652 WARN("incorrect priority level\n");
653 return DSERR_PRIOLEVELNEEDED;
656 return DS_OK;
659 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
660 LPDIRECTSOUND8 iface,
661 LPDWORD lpdwSpeakerConfig)
663 ICOM_THIS(IDirectSoundImpl,iface);
664 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
666 if (This->initialized == FALSE) {
667 WARN("not initialized\n");
668 return DSERR_UNINITIALIZED;
671 if (lpdwSpeakerConfig == NULL) {
672 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
673 return DSERR_INVALIDPARAM;
676 WARN("not fully functional\n");
677 *lpdwSpeakerConfig = This->speaker_config;
678 return DS_OK;
681 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
682 LPDIRECTSOUND8 iface,
683 DWORD config)
685 ICOM_THIS(IDirectSoundImpl,iface);
686 TRACE("(%p,0x%08lx)\n",This,config);
688 if (This->initialized == FALSE) {
689 WARN("not initialized\n");
690 return DSERR_UNINITIALIZED;
693 This->speaker_config = config;
694 WARN("not fully functional\n");
695 return DS_OK;
698 static HRESULT WINAPI IDirectSoundImpl_Initialize(
699 LPDIRECTSOUND8 iface,
700 LPCGUID lpcGuid)
702 ICOM_THIS(IDirectSoundImpl,iface);
703 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
705 This->initialized = TRUE;
707 return DS_OK;
710 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
711 LPDIRECTSOUND8 iface,
712 LPDWORD pdwCertified)
714 ICOM_THIS(IDirectSoundImpl,iface);
715 TRACE("(%p, %p)\n",This,pdwCertified);
717 if (This->initialized == FALSE) {
718 WARN("not initialized\n");
719 return DSERR_UNINITIALIZED;
722 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
723 *pdwCertified = DS_CERTIFIED;
724 else
725 *pdwCertified = DS_UNCERTIFIED;
726 return DS_OK;
729 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
731 IDirectSoundImpl_QueryInterface,
732 IDirectSoundImpl_AddRef,
733 IDirectSoundImpl_Release,
734 IDirectSoundImpl_CreateSoundBuffer,
735 IDirectSoundImpl_GetCaps,
736 IDirectSoundImpl_DuplicateSoundBuffer,
737 IDirectSoundImpl_SetCooperativeLevel,
738 IDirectSoundImpl_Compact,
739 IDirectSoundImpl_GetSpeakerConfig,
740 IDirectSoundImpl_SetSpeakerConfig,
741 IDirectSoundImpl_Initialize,
742 IDirectSoundImpl_VerifyCertification
745 HRESULT WINAPI IDirectSoundImpl_Create(
746 LPCGUID lpcGUID,
747 LPDIRECTSOUND8 * ppDS)
749 HRESULT err;
750 PIDSDRIVER drv = NULL;
751 IDirectSoundImpl* pDS;
752 unsigned wod, wodn;
753 BOOLEAN found = FALSE;
754 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
756 /* Enumerate WINMM audio devices and find the one we want */
757 wodn = waveOutGetNumDevs();
758 if (!wodn) {
759 WARN("no driver\n");
760 *ppDS = NULL;
761 return DSERR_NODRIVER;
764 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
766 for (wod=0; wod<wodn; wod++) {
767 if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
768 found = TRUE;
769 break;
773 if (found == FALSE) {
774 WARN("No device found matching given ID!\n");
775 *ppDS = NULL;
776 return DSERR_NODRIVER;
779 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
780 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
782 /* Disable the direct sound driver to force emulation if requested. */
783 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
784 drv = NULL;
786 /* Allocate memory */
787 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
788 if (ppDS == NULL) {
789 WARN("out of memory\n");
790 *ppDS = NULL;
791 return DSERR_OUTOFMEMORY;
794 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
795 pDS->ref = 0;
797 pDS->driver = drv;
798 pDS->priolevel = DSSCL_NORMAL;
799 pDS->fraglen = 0;
800 pDS->hwbuf = NULL;
801 pDS->buffer = NULL;
802 pDS->buflen = 0;
803 pDS->writelead = 0;
804 pDS->state = STATE_STOPPED;
805 pDS->nrofbuffers = 0;
806 pDS->buffers = NULL;
807 pDS->primary = NULL;
808 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
809 pDS->initialized = FALSE;
811 /* 3D listener initial parameters */
812 pDS->listener = NULL;
813 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
814 pDS->ds3dl.vPosition.x = 0.0;
815 pDS->ds3dl.vPosition.y = 0.0;
816 pDS->ds3dl.vPosition.z = 0.0;
817 pDS->ds3dl.vVelocity.x = 0.0;
818 pDS->ds3dl.vVelocity.y = 0.0;
819 pDS->ds3dl.vVelocity.z = 0.0;
820 pDS->ds3dl.vOrientFront.x = 0.0;
821 pDS->ds3dl.vOrientFront.y = 0.0;
822 pDS->ds3dl.vOrientFront.z = 1.0;
823 pDS->ds3dl.vOrientTop.x = 0.0;
824 pDS->ds3dl.vOrientTop.y = 1.0;
825 pDS->ds3dl.vOrientTop.z = 0.0;
826 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
827 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
828 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
830 pDS->prebuf = ds_snd_queue_max;
831 pDS->guid = *lpcGUID;
833 /* Get driver description */
834 if (drv) {
835 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
836 if (err != DS_OK) {
837 WARN("IDsDriver_GetDriverDesc failed\n");
838 HeapFree(GetProcessHeap(),0,pDS);
839 *ppDS = NULL;
840 return err;
842 } else {
843 /* if no DirectSound interface available, use WINMM API instead */
844 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
847 pDS->drvdesc.dnDevNode = wod;
849 /* Set default wave format (may need it for waveOutOpen) */
850 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
851 if (pDS->pwfx == NULL) {
852 WARN("out of memory\n");
853 HeapFree(GetProcessHeap(),0,pDS);
854 *ppDS = NULL;
855 return DSERR_OUTOFMEMORY;
858 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
859 /* We rely on the sound driver to return the actual sound format of
860 * the device if it does not support 22050x8x2 and is given the
861 * WAVE_DIRECTSOUND flag.
863 pDS->pwfx->nSamplesPerSec = 22050;
864 pDS->pwfx->wBitsPerSample = 8;
865 pDS->pwfx->nChannels = 2;
866 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
867 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
868 pDS->pwfx->cbSize = 0;
870 /* If the driver requests being opened through MMSYSTEM
871 * (which is recommended by the DDK), it is supposed to happen
872 * before the DirectSound interface is opened */
873 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
875 DWORD flags = CALLBACK_FUNCTION;
877 /* disable direct sound if requested */
878 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
879 flags |= WAVE_DIRECTSOUND;
881 err = mmErr(waveOutOpen(&(pDS->hwo),
882 pDS->drvdesc.dnDevNode, pDS->pwfx,
883 (DWORD)DSOUND_callback, (DWORD)pDS,
884 flags));
885 if (err != DS_OK) {
886 WARN("waveOutOpen failed\n");
887 HeapFree(GetProcessHeap(),0,pDS);
888 *ppDS = NULL;
889 return err;
893 if (drv) {
894 err = IDsDriver_Open(drv);
895 if (err != DS_OK) {
896 WARN("IDsDriver_Open failed\n");
897 HeapFree(GetProcessHeap(),0,pDS);
898 *ppDS = NULL;
899 return err;
902 /* the driver is now open, so it's now allowed to call GetCaps */
903 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
904 if (err != DS_OK) {
905 WARN("IDsDriver_GetCaps failed\n");
906 HeapFree(GetProcessHeap(),0,pDS);
907 *ppDS = NULL;
908 return err;
910 } else {
911 WAVEOUTCAPSA woc;
912 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
913 if (err != DS_OK) {
914 WARN("waveOutGetDevCaps failed\n");
915 HeapFree(GetProcessHeap(),0,pDS);
916 *ppDS = NULL;
917 return err;
919 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
920 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
921 (woc.dwFormats & WAVE_FORMAT_2M08) ||
922 (woc.dwFormats & WAVE_FORMAT_4M08) ||
923 (woc.dwFormats & WAVE_FORMAT_48M08) ||
924 (woc.dwFormats & WAVE_FORMAT_96M08)) {
925 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
926 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
928 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
929 (woc.dwFormats & WAVE_FORMAT_2M16) ||
930 (woc.dwFormats & WAVE_FORMAT_4M16) ||
931 (woc.dwFormats & WAVE_FORMAT_48M16) ||
932 (woc.dwFormats & WAVE_FORMAT_96M16)) {
933 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
934 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
936 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
937 (woc.dwFormats & WAVE_FORMAT_2S08) ||
938 (woc.dwFormats & WAVE_FORMAT_4S08) ||
939 (woc.dwFormats & WAVE_FORMAT_48S08) ||
940 (woc.dwFormats & WAVE_FORMAT_96S08)) {
941 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
942 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
944 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
945 (woc.dwFormats & WAVE_FORMAT_2S16) ||
946 (woc.dwFormats & WAVE_FORMAT_4S16) ||
947 (woc.dwFormats & WAVE_FORMAT_48S16) ||
948 (woc.dwFormats & WAVE_FORMAT_96S16)) {
949 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
950 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
952 if (ds_emuldriver)
953 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
954 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
955 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
956 pDS->drvcaps.dwPrimaryBuffers = 1;
959 InitializeCriticalSection(&(pDS->mixlock));
960 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
962 RtlInitializeResource(&(pDS->buffer_list_lock));
964 *ppDS = (LPDIRECTSOUND8)pDS;
966 return DS_OK;
968 /*******************************************************************************
969 * IDirectSound_IUnknown
971 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
972 LPUNKNOWN iface,
973 REFIID riid,
974 LPVOID * ppobj)
976 ICOM_THIS(IDirectSound_IUnknown,iface);
977 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
978 return DSOUND_QueryInterface(This->pds, riid, ppobj);
981 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
982 LPUNKNOWN iface)
984 ICOM_THIS(IDirectSound_IUnknown,iface);
985 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
986 return InterlockedIncrement(&This->ref);
989 static ULONG WINAPI IDirectSound_IUnknown_Release(
990 LPUNKNOWN iface)
992 ICOM_THIS(IDirectSound_IUnknown,iface);
993 ULONG ulReturn;
994 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
995 ulReturn = InterlockedDecrement(&This->ref);
996 if (ulReturn == 0) {
997 IDirectSoundImpl_Release(This->pds);
998 HeapFree(GetProcessHeap(),0,This);
999 TRACE("(%p) released\n",This);
1001 return ulReturn;
1004 static IUnknownVtbl DirectSound_Unknown_Vtbl =
1006 IDirectSound_IUnknown_QueryInterface,
1007 IDirectSound_IUnknown_AddRef,
1008 IDirectSound_IUnknown_Release
1011 HRESULT WINAPI IDirectSound_IUnknown_Create(
1012 LPDIRECTSOUND8 pds,
1013 LPUNKNOWN * ppunk)
1015 IDirectSound_IUnknown * pdsunk;
1016 TRACE("(%p,%p)\n",pds,ppunk);
1018 if (ppunk == NULL) {
1019 ERR("invalid parameter: ppunk == NULL\n");
1020 return DSERR_INVALIDPARAM;
1023 if (pds == NULL) {
1024 ERR("invalid parameter: pds == NULL\n");
1025 *ppunk = NULL;
1026 return DSERR_INVALIDPARAM;
1029 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1030 if (pdsunk == NULL) {
1031 WARN("out of memory\n");
1032 *ppunk = NULL;
1033 return DSERR_OUTOFMEMORY;
1036 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1037 pdsunk->ref = 0;
1038 pdsunk->pds = pds;
1040 IDirectSoundImpl_AddRef(pds);
1041 *ppunk = (LPUNKNOWN)pdsunk;
1043 return DS_OK;
1046 /*******************************************************************************
1047 * IDirectSound_IDirectSound
1049 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1050 LPDIRECTSOUND iface,
1051 REFIID riid,
1052 LPVOID * ppobj)
1054 ICOM_THIS(IDirectSound_IDirectSound,iface);
1055 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1056 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1059 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1060 LPDIRECTSOUND iface)
1062 ICOM_THIS(IDirectSound_IDirectSound,iface);
1063 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1064 return InterlockedIncrement(&This->ref);
1067 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1068 LPDIRECTSOUND iface)
1070 ICOM_THIS(IDirectSound_IDirectSound,iface);
1071 ULONG ulReturn;
1072 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1073 ulReturn = InterlockedDecrement(&This->ref);
1074 if (ulReturn == 0) {
1075 IDirectSoundImpl_Release(This->pds);
1076 HeapFree(GetProcessHeap(),0,This);
1077 TRACE("(%p) released\n",This);
1079 return ulReturn;
1082 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1083 LPDIRECTSOUND iface,
1084 LPCDSBUFFERDESC dsbd,
1085 LPLPDIRECTSOUNDBUFFER ppdsb,
1086 LPUNKNOWN lpunk)
1088 ICOM_THIS(IDirectSound_IDirectSound,iface);
1089 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1090 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1093 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1094 LPDIRECTSOUND iface,
1095 LPDSCAPS lpDSCaps)
1097 ICOM_THIS(IDirectSound_IDirectSound,iface);
1098 TRACE("(%p,%p)\n",This,lpDSCaps);
1099 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1102 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1103 LPDIRECTSOUND iface,
1104 LPDIRECTSOUNDBUFFER psb,
1105 LPLPDIRECTSOUNDBUFFER ppdsb)
1107 ICOM_THIS(IDirectSound_IDirectSound,iface);
1108 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1109 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1112 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1113 LPDIRECTSOUND iface,
1114 HWND hwnd,
1115 DWORD level)
1117 ICOM_THIS(IDirectSound_IDirectSound,iface);
1118 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1119 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1122 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1123 LPDIRECTSOUND iface)
1125 ICOM_THIS(IDirectSound_IDirectSound,iface);
1126 TRACE("(%p)\n", This);
1127 return IDirectSoundImpl_Compact(This->pds);
1130 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1131 LPDIRECTSOUND iface,
1132 LPDWORD lpdwSpeakerConfig)
1134 ICOM_THIS(IDirectSound_IDirectSound,iface);
1135 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1136 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1139 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1140 LPDIRECTSOUND iface,
1141 DWORD config)
1143 ICOM_THIS(IDirectSound_IDirectSound,iface);
1144 TRACE("(%p,0x%08lx)\n",This,config);
1145 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1148 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1149 LPDIRECTSOUND iface,
1150 LPCGUID lpcGuid)
1152 ICOM_THIS(IDirectSound_IDirectSound,iface);
1153 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1154 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1157 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1159 IDirectSound_IDirectSound_QueryInterface,
1160 IDirectSound_IDirectSound_AddRef,
1161 IDirectSound_IDirectSound_Release,
1162 IDirectSound_IDirectSound_CreateSoundBuffer,
1163 IDirectSound_IDirectSound_GetCaps,
1164 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1165 IDirectSound_IDirectSound_SetCooperativeLevel,
1166 IDirectSound_IDirectSound_Compact,
1167 IDirectSound_IDirectSound_GetSpeakerConfig,
1168 IDirectSound_IDirectSound_SetSpeakerConfig,
1169 IDirectSound_IDirectSound_Initialize
1172 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1173 LPDIRECTSOUND8 pds,
1174 LPDIRECTSOUND * ppds)
1176 IDirectSound_IDirectSound * pdsds;
1177 TRACE("(%p,%p)\n",pds,ppds);
1179 if (ppds == NULL) {
1180 ERR("invalid parameter: ppds == NULL\n");
1181 return DSERR_INVALIDPARAM;
1184 if (pds == NULL) {
1185 ERR("invalid parameter: pds == NULL\n");
1186 *ppds = NULL;
1187 return DSERR_INVALIDPARAM;
1190 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1191 if (pdsds == NULL) {
1192 WARN("out of memory\n");
1193 *ppds = NULL;
1194 return DSERR_OUTOFMEMORY;
1197 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1198 pdsds->ref = 0;
1199 pdsds->pds = pds;
1201 IDirectSoundImpl_AddRef(pds);
1202 *ppds = (LPDIRECTSOUND)pdsds;
1204 return DS_OK;
1207 /*******************************************************************************
1208 * IDirectSound8_IUnknown
1210 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1211 LPUNKNOWN iface,
1212 REFIID riid,
1213 LPVOID * ppobj)
1215 ICOM_THIS(IDirectSound_IUnknown,iface);
1216 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1217 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1220 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1221 LPUNKNOWN iface)
1223 ICOM_THIS(IDirectSound_IUnknown,iface);
1224 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1225 return InterlockedIncrement(&This->ref);
1228 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1229 LPUNKNOWN iface)
1231 ICOM_THIS(IDirectSound_IUnknown,iface);
1232 ULONG ulReturn;
1233 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1234 ulReturn = InterlockedDecrement(&This->ref);
1235 if (ulReturn == 0) {
1236 IDirectSoundImpl_Release(This->pds);
1237 HeapFree(GetProcessHeap(),0,This);
1238 TRACE("(%p) released\n",This);
1240 return ulReturn;
1243 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1245 IDirectSound8_IUnknown_QueryInterface,
1246 IDirectSound8_IUnknown_AddRef,
1247 IDirectSound8_IUnknown_Release
1250 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1251 LPDIRECTSOUND8 pds,
1252 LPUNKNOWN * ppunk)
1254 IDirectSound8_IUnknown * pdsunk;
1255 TRACE("(%p,%p)\n",pds,ppunk);
1257 if (ppunk == NULL) {
1258 ERR("invalid parameter: ppunk == NULL\n");
1259 return DSERR_INVALIDPARAM;
1262 if (pds == NULL) {
1263 ERR("invalid parameter: pds == NULL\n");
1264 *ppunk = NULL;
1265 return DSERR_INVALIDPARAM;
1268 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1269 if (pdsunk == NULL) {
1270 WARN("out of memory\n");
1271 *ppunk = NULL;
1272 return DSERR_OUTOFMEMORY;
1275 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1276 pdsunk->ref = 0;
1277 pdsunk->pds = pds;
1279 IDirectSoundImpl_AddRef(pds);
1280 *ppunk = (LPUNKNOWN)pdsunk;
1282 return DS_OK;
1285 /*******************************************************************************
1286 * IDirectSound8_IDirectSound
1288 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1289 LPDIRECTSOUND iface,
1290 REFIID riid,
1291 LPVOID * ppobj)
1293 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1294 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1295 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1298 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1299 LPDIRECTSOUND iface)
1301 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1302 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1303 return InterlockedIncrement(&This->ref);
1306 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1307 LPDIRECTSOUND iface)
1309 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1310 ULONG ulReturn;
1311 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1312 ulReturn = InterlockedDecrement(&This->ref);
1313 if (ulReturn == 0) {
1314 IDirectSoundImpl_Release(This->pds);
1315 HeapFree(GetProcessHeap(),0,This);
1316 TRACE("(%p) released\n",This);
1318 return ulReturn;
1321 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1322 LPDIRECTSOUND iface,
1323 LPCDSBUFFERDESC dsbd,
1324 LPLPDIRECTSOUNDBUFFER ppdsb,
1325 LPUNKNOWN lpunk)
1327 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1328 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1329 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1332 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1333 LPDIRECTSOUND iface,
1334 LPDSCAPS lpDSCaps)
1336 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1337 TRACE("(%p,%p)\n",This,lpDSCaps);
1338 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1341 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1342 LPDIRECTSOUND iface,
1343 LPDIRECTSOUNDBUFFER psb,
1344 LPLPDIRECTSOUNDBUFFER ppdsb)
1346 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1347 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1348 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1351 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1352 LPDIRECTSOUND iface,
1353 HWND hwnd,
1354 DWORD level)
1356 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1357 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1358 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1361 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1362 LPDIRECTSOUND iface)
1364 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1365 TRACE("(%p)\n", This);
1366 return IDirectSoundImpl_Compact(This->pds);
1369 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1370 LPDIRECTSOUND iface,
1371 LPDWORD lpdwSpeakerConfig)
1373 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1374 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1375 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1378 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1379 LPDIRECTSOUND iface,
1380 DWORD config)
1382 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1383 TRACE("(%p,0x%08lx)\n",This,config);
1384 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1387 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1388 LPDIRECTSOUND iface,
1389 LPCGUID lpcGuid)
1391 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1392 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1393 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1396 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1398 IDirectSound8_IDirectSound_QueryInterface,
1399 IDirectSound8_IDirectSound_AddRef,
1400 IDirectSound8_IDirectSound_Release,
1401 IDirectSound8_IDirectSound_CreateSoundBuffer,
1402 IDirectSound8_IDirectSound_GetCaps,
1403 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1404 IDirectSound8_IDirectSound_SetCooperativeLevel,
1405 IDirectSound8_IDirectSound_Compact,
1406 IDirectSound8_IDirectSound_GetSpeakerConfig,
1407 IDirectSound8_IDirectSound_SetSpeakerConfig,
1408 IDirectSound8_IDirectSound_Initialize
1411 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1412 LPDIRECTSOUND8 pds,
1413 LPDIRECTSOUND * ppds)
1415 IDirectSound8_IDirectSound * pdsds;
1416 TRACE("(%p,%p)\n",pds,ppds);
1418 if (ppds == NULL) {
1419 ERR("invalid parameter: ppds == NULL\n");
1420 return DSERR_INVALIDPARAM;
1423 if (pds == NULL) {
1424 ERR("invalid parameter: pds == NULL\n");
1425 *ppds = NULL;
1426 return DSERR_INVALIDPARAM;
1429 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1430 if (pdsds == NULL) {
1431 WARN("out of memory\n");
1432 *ppds = NULL;
1433 return DSERR_OUTOFMEMORY;
1436 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1437 pdsds->ref = 0;
1438 pdsds->pds = pds;
1440 IDirectSoundImpl_AddRef(pds);
1441 *ppds = (LPDIRECTSOUND)pdsds;
1443 return DS_OK;
1446 /*******************************************************************************
1447 * IDirectSound8_IDirectSound8
1449 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1450 LPDIRECTSOUND8 iface,
1451 REFIID riid,
1452 LPVOID * ppobj)
1454 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1455 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1456 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1459 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1460 LPDIRECTSOUND8 iface)
1462 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1463 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1464 return InterlockedIncrement(&This->ref);
1467 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1468 LPDIRECTSOUND8 iface)
1470 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1471 ULONG ulReturn;
1472 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1473 ulReturn = InterlockedDecrement(&This->ref);
1474 if (ulReturn == 0) {
1475 IDirectSoundImpl_Release(This->pds);
1476 HeapFree(GetProcessHeap(),0,This);
1477 TRACE("(%p) released\n",This);
1479 return ulReturn;
1482 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1483 LPDIRECTSOUND8 iface,
1484 LPCDSBUFFERDESC dsbd,
1485 LPLPDIRECTSOUNDBUFFER ppdsb,
1486 LPUNKNOWN lpunk)
1488 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1489 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1490 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1493 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1494 LPDIRECTSOUND8 iface,
1495 LPDSCAPS lpDSCaps)
1497 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1498 TRACE("(%p,%p)\n",This,lpDSCaps);
1499 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1502 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1503 LPDIRECTSOUND8 iface,
1504 LPDIRECTSOUNDBUFFER psb,
1505 LPLPDIRECTSOUNDBUFFER ppdsb)
1507 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1508 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1509 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1512 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1513 LPDIRECTSOUND8 iface,
1514 HWND hwnd,
1515 DWORD level)
1517 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1518 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1519 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1522 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1523 LPDIRECTSOUND8 iface)
1525 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1526 TRACE("(%p)\n", This);
1527 return IDirectSoundImpl_Compact(This->pds);
1530 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1531 LPDIRECTSOUND8 iface,
1532 LPDWORD lpdwSpeakerConfig)
1534 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1535 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1536 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1539 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1540 LPDIRECTSOUND8 iface,
1541 DWORD config)
1543 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1544 TRACE("(%p,0x%08lx)\n",This,config);
1545 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1548 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1549 LPDIRECTSOUND8 iface,
1550 LPCGUID lpcGuid)
1552 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1553 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1554 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1557 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1558 LPDIRECTSOUND8 iface,
1559 LPDWORD pdwCertified)
1561 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1562 TRACE("(%p, %p)\n", This, pdwCertified);
1563 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1566 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1568 IDirectSound8_IDirectSound8_QueryInterface,
1569 IDirectSound8_IDirectSound8_AddRef,
1570 IDirectSound8_IDirectSound8_Release,
1571 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1572 IDirectSound8_IDirectSound8_GetCaps,
1573 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1574 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1575 IDirectSound8_IDirectSound8_Compact,
1576 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1577 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1578 IDirectSound8_IDirectSound8_Initialize,
1579 IDirectSound8_IDirectSound8_VerifyCertification
1582 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1583 LPDIRECTSOUND8 pds,
1584 LPDIRECTSOUND8 * ppds)
1586 IDirectSound8_IDirectSound8 * pdsds;
1587 TRACE("(%p,%p)\n",pds,ppds);
1589 if (ppds == NULL) {
1590 ERR("invalid parameter: ppds == NULL\n");
1591 return DSERR_INVALIDPARAM;
1594 if (pds == NULL) {
1595 ERR("invalid parameter: pds == NULL\n");
1596 *ppds = NULL;
1597 return DSERR_INVALIDPARAM;
1600 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1601 if (pdsds == NULL) {
1602 WARN("out of memory\n");
1603 *ppds = NULL;
1604 return DSERR_OUTOFMEMORY;
1607 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1608 pdsds->ref = 0;
1609 pdsds->pds = pds;
1611 IDirectSoundImpl_AddRef(pds);
1612 *ppds = (LPDIRECTSOUND8)pdsds;
1614 return DS_OK;
1617 HRESULT WINAPI DSOUND_Create(
1618 LPCGUID lpcGUID,
1619 LPDIRECTSOUND *ppDS,
1620 IUnknown *pUnkOuter)
1622 HRESULT hr;
1623 GUID devGuid;
1625 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1627 if (pUnkOuter != NULL) {
1628 WARN("invalid parameter: pUnkOuter != NULL\n");
1629 return DSERR_INVALIDPARAM;
1632 if (ppDS == NULL) {
1633 WARN("invalid parameter: ppDS == NULL\n");
1634 return DSERR_INVALIDPARAM;
1637 /* Get dsound configuration */
1638 setup_dsound_options();
1640 /* Default device? */
1641 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1642 lpcGUID = &DSDEVID_DefaultPlayback;
1644 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1645 WARN("invalid parameter: lpcGUID\n");
1646 *ppDS = NULL;
1647 return DSERR_INVALIDPARAM;
1650 if (dsound) {
1651 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1652 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1653 if (*ppDS)
1654 IDirectSound_IDirectSound_AddRef(*ppDS);
1655 else
1656 WARN("IDirectSound_IDirectSound_Create failed\n");
1657 } else {
1658 ERR("different dsound already opened (only support one sound card at a time now)\n");
1659 *ppDS = NULL;
1660 hr = DSERR_ALLOCATED;
1662 } else {
1663 LPDIRECTSOUND8 pDS;
1664 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1665 if (hr == DS_OK) {
1666 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1667 if (hr == DS_OK) {
1668 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1669 if (*ppDS) {
1670 IDirectSound_IDirectSound_AddRef(*ppDS);
1672 dsound = (IDirectSoundImpl*)pDS;
1673 timeBeginPeriod(DS_TIME_RES);
1674 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1675 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1676 } else {
1677 WARN("IDirectSound_IDirectSound_Create failed\n");
1678 IDirectSound8_Release(pDS);
1680 } else {
1681 WARN("DSOUND_PrimaryCreate failed\n");
1682 IDirectSound8_Release(pDS);
1684 } else
1685 WARN("IDirectSoundImpl_Create failed\n");
1688 return hr;
1691 /*******************************************************************************
1692 * DirectSoundCreate (DSOUND.1)
1694 * Creates and initializes a DirectSound interface.
1696 * PARAMS
1697 * lpcGUID [I] Address of the GUID that identifies the sound device.
1698 * ppDS [O] Address of a variable to receive the interface pointer.
1699 * pUnkOuter [I] Must be NULL.
1701 * RETURNS
1702 * Success: DS_OK
1703 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1704 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1706 HRESULT WINAPI DirectSoundCreate(
1707 LPCGUID lpcGUID,
1708 LPDIRECTSOUND *ppDS,
1709 IUnknown *pUnkOuter)
1711 HRESULT hr;
1713 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1715 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1716 if (hr == DS_OK)
1717 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1719 return hr;
1722 HRESULT WINAPI DSOUND_Create8(
1723 LPCGUID lpcGUID,
1724 LPDIRECTSOUND8 *ppDS,
1725 IUnknown *pUnkOuter)
1727 HRESULT hr;
1728 GUID devGuid;
1730 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1732 if (pUnkOuter != NULL) {
1733 WARN("invalid parameter: pUnkOuter != NULL\n");
1734 return DSERR_INVALIDPARAM;
1737 if (ppDS == NULL) {
1738 WARN("invalid parameter: ppDS == NULL\n");
1739 return DSERR_INVALIDPARAM;
1742 /* Get dsound configuration */
1743 setup_dsound_options();
1745 /* Default device? */
1746 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1747 lpcGUID = &DSDEVID_DefaultPlayback;
1749 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1750 WARN("invalid parameter: lpcGUID\n");
1751 *ppDS = NULL;
1752 return DSERR_INVALIDPARAM;
1755 if (dsound) {
1756 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1757 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1758 if (*ppDS)
1759 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1760 else
1761 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1762 } else {
1763 ERR("different dsound already opened (only support one sound card at a time now)\n");
1764 *ppDS = NULL;
1765 hr = DSERR_ALLOCATED;
1767 } else {
1768 LPDIRECTSOUND8 pDS;
1769 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1770 if (hr == DS_OK) {
1771 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1772 if (hr == DS_OK) {
1773 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1774 if (*ppDS) {
1775 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1777 dsound = (IDirectSoundImpl*)pDS;
1778 timeBeginPeriod(DS_TIME_RES);
1779 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1780 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1781 } else {
1782 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1783 IDirectSound8_Release(pDS);
1785 } else {
1786 WARN("DSOUND_PrimaryCreate failed\n");
1787 IDirectSound8_Release(pDS);
1789 } else
1790 WARN("IDirectSoundImpl_Create failed\n");
1793 return hr;
1796 /*******************************************************************************
1797 * DirectSoundCreate8 (DSOUND.11)
1799 * Creates and initializes a DirectSound8 interface.
1801 * PARAMS
1802 * lpcGUID [I] Address of the GUID that identifies the sound device.
1803 * ppDS [O] Address of a variable to receive the interface pointer.
1804 * pUnkOuter [I] Must be NULL.
1806 * RETURNS
1807 * Success: DS_OK
1808 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1809 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1811 HRESULT WINAPI DirectSoundCreate8(
1812 LPCGUID lpcGUID,
1813 LPDIRECTSOUND8 *ppDS,
1814 IUnknown *pUnkOuter)
1816 HRESULT hr;
1818 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1820 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1821 if (hr == DS_OK)
1822 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1824 return hr;
1828 * Add secondary buffer to buffer list.
1829 * Gets exclusive access to buffer for writing.
1831 HRESULT DSOUND_AddBuffer(
1832 IDirectSoundImpl * pDS,
1833 IDirectSoundBufferImpl * pDSB)
1835 IDirectSoundBufferImpl **newbuffers;
1836 HRESULT hr = DS_OK;
1838 TRACE("(%p, %p)\n", pDS, pDSB);
1840 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1842 if (pDS->buffers)
1843 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1844 else
1845 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->nrofbuffers+1));
1847 if (newbuffers) {
1848 pDS->buffers = newbuffers;
1849 pDS->buffers[pDS->nrofbuffers] = pDSB;
1850 pDS->nrofbuffers++;
1851 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1852 } else {
1853 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->nrofbuffers);
1854 hr = DSERR_OUTOFMEMORY;
1857 RtlReleaseResource(&(pDS->buffer_list_lock));
1859 return hr;
1863 * Remove secondary buffer from buffer list.
1864 * Gets exclusive access to buffer for writing.
1866 HRESULT DSOUND_RemoveBuffer(
1867 IDirectSoundImpl * pDS,
1868 IDirectSoundBufferImpl * pDSB)
1870 int i;
1871 HRESULT hr = DS_OK;
1873 TRACE("(%p, %p)\n", pDS, pDSB);
1875 RtlAcquireResourceExclusive(&(pDS->buffer_list_lock), TRUE);
1877 for (i = 0; i < pDS->nrofbuffers; i++)
1878 if (pDS->buffers[i] == pDSB)
1879 break;
1881 if (i < pDS->nrofbuffers) {
1882 /* Put the last buffer of the list in the (now empty) position */
1883 pDS->buffers[i] = pDS->buffers[pDS->nrofbuffers - 1];
1884 pDS->nrofbuffers--;
1885 pDS->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->nrofbuffers);
1886 TRACE("buffer count is now %d\n", pDS->nrofbuffers);
1889 if (pDS->nrofbuffers == 0) {
1890 HeapFree(GetProcessHeap(),0,pDS->buffers);
1891 pDS->buffers = NULL;
1894 RtlReleaseResource(&(pDS->buffer_list_lock));
1896 return hr;