Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine.git] / dlls / dsound / dsound.c
blob403af8ae5b86755f289b0a8c3b1ab21606cf1a90
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_CTRLDEFAULT)
121 FE(DSBCAPS_CTRLALL)
122 FE(DSBCAPS_STICKYFOCUS)
123 FE(DSBCAPS_GLOBALFOCUS)
124 FE(DSBCAPS_GETCURRENTPOSITION2)
125 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
126 #undef FE
128 int i;
130 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
131 if ((flags[i].mask & xmask) == flags[i].mask)
132 DPRINTF("%s ",flags[i].name);
135 /*******************************************************************************
136 * IDirectSoundImpl_DirectSound
138 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
139 LPDIRECTSOUND8 iface,
140 REFIID riid,
141 LPVOID * ppobj)
143 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
144 FIXME("shouldn't be called directly\n");
145 return E_NOINTERFACE;
148 static HRESULT WINAPI DSOUND_QueryInterface(
149 LPDIRECTSOUND8 iface,
150 REFIID riid,
151 LPVOID * ppobj)
153 ICOM_THIS(IDirectSoundImpl,iface);
154 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
156 if (ppobj == NULL) {
157 WARN("invalid parameter\n");
158 return E_INVALIDARG;
161 if (IsEqualIID(riid, &IID_IUnknown)) {
162 if (!This->pUnknown) {
163 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
164 if (!This->pUnknown) {
165 WARN("IDirectSound_IUnknown_Create() failed\n");
166 *ppobj = NULL;
167 return E_NOINTERFACE;
170 IDirectSound_IUnknown_AddRef(This->pUnknown);
171 *ppobj = This->pUnknown;
172 return S_OK;
173 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
174 if (!This->pDS) {
175 IDirectSound_IDirectSound_Create(iface, &This->pDS);
176 if (!This->pDS) {
177 WARN("IDirectSound_IDirectSound_Create() failed\n");
178 *ppobj = NULL;
179 return E_NOINTERFACE;
182 IDirectSound_IDirectSound_AddRef(This->pDS);
183 *ppobj = This->pDS;
184 return S_OK;
187 *ppobj = NULL;
188 WARN("Unknown IID %s\n",debugstr_guid(riid));
189 return E_NOINTERFACE;
192 static HRESULT WINAPI DSOUND_QueryInterface8(
193 LPDIRECTSOUND8 iface,
194 REFIID riid,
195 LPVOID * ppobj)
197 ICOM_THIS(IDirectSoundImpl,iface);
198 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
200 if (ppobj == NULL) {
201 WARN("invalid parameter\n");
202 return E_INVALIDARG;
205 if (IsEqualIID(riid, &IID_IUnknown)) {
206 if (!This->pUnknown) {
207 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
208 if (!This->pUnknown) {
209 WARN("IDirectSound8_IUnknown_Create() failed\n");
210 *ppobj = NULL;
211 return E_NOINTERFACE;
214 IDirectSound8_IUnknown_AddRef(This->pUnknown);
215 *ppobj = This->pUnknown;
216 return S_OK;
217 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
218 if (!This->pDS) {
219 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
220 if (!This->pDS) {
221 WARN("IDirectSound8_IDirectSound_Create() failed\n");
222 *ppobj = NULL;
223 return E_NOINTERFACE;
226 IDirectSound8_IDirectSound_AddRef(This->pDS);
227 *ppobj = This->pDS;
228 return S_OK;
229 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
230 if (!This->pDS8) {
231 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
232 if (!This->pDS8) {
233 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
234 *ppobj = NULL;
235 return E_NOINTERFACE;
238 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
239 *ppobj = This->pDS8;
240 return S_OK;
243 *ppobj = NULL;
244 WARN("Unknown IID %s\n",debugstr_guid(riid));
245 return E_NOINTERFACE;
248 static ULONG WINAPI IDirectSoundImpl_AddRef(
249 LPDIRECTSOUND8 iface)
251 ICOM_THIS(IDirectSoundImpl,iface);
252 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
254 return InterlockedIncrement(&This->ref);
257 static ULONG WINAPI IDirectSoundImpl_Release(
258 LPDIRECTSOUND8 iface)
260 ICOM_THIS(IDirectSoundImpl,iface);
261 ULONG ref;
262 TRACE("(%p) ref was %ld, thread is %04lx\n",
263 This, This->ref, GetCurrentThreadId());
265 ref = InterlockedDecrement(&This->ref);
266 if (ref == 0) {
267 HRESULT hres;
268 UINT i;
270 timeKillEvent(This->timerID);
271 timeEndPeriod(DS_TIME_RES);
272 /* wait for timer to expire */
273 Sleep(DS_TIME_RES+1);
275 /* The sleep above should have allowed the timer process to expire
276 * but try to grab the lock just in case. Can't hold lock because
277 * IDirectSoundBufferImpl_Destroy also grabs the lock */
278 RtlAcquireResourceShared(&(This->lock), TRUE);
279 RtlReleaseResource(&(This->lock));
281 /* It is allowed to release this object even when buffers are playing */
282 if (This->buffers) {
283 WARN("%d secondary buffers not released\n", This->nrofbuffers);
284 for( i=0;i<This->nrofbuffers;i++)
285 IDirectSoundBufferImpl_Destroy(This->buffers[i]);
288 if (This->primary) {
289 WARN("primary buffer not released\n");
290 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
293 hres = DSOUND_PrimaryDestroy(This);
294 if (hres != DS_OK)
295 WARN("DSOUND_PrimaryDestroy failed\n");
297 if (This->driver)
298 IDsDriver_Close(This->driver);
300 if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
301 waveOutClose(This->hwo);
303 if (This->driver)
304 IDsDriver_Release(This->driver);
306 RtlDeleteResource(&This->lock);
307 DeleteCriticalSection(&This->mixlock);
308 HeapFree(GetProcessHeap(),0,This);
309 dsound = NULL;
310 TRACE("(%p) released\n",This);
313 return ref;
316 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
317 LPDIRECTSOUND8 iface,
318 LPCDSBUFFERDESC dsbd,
319 LPLPDIRECTSOUNDBUFFER ppdsb,
320 LPUNKNOWN lpunk)
322 ICOM_THIS(IDirectSoundImpl,iface);
323 LPWAVEFORMATEX wfex;
324 HRESULT hres = DS_OK;
325 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
327 if (This == NULL) {
328 WARN("invalid parameter: This == NULL\n");
329 return DSERR_INVALIDPARAM;
332 if (This->initialized == FALSE) {
333 WARN("not initialized\n");
334 return DSERR_UNINITIALIZED;
337 if (dsbd == NULL) {
338 WARN("invalid parameter: dsbd == NULL\n");
339 return DSERR_INVALIDPARAM;
342 if (dsbd->dwSize != sizeof(DSBUFFERDESC) && dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
343 WARN("invalid parameter: dsbd\n");
344 return DSERR_INVALIDPARAM;
347 if (ppdsb == NULL) {
348 WARN("invalid parameter: ppdsb == NULL\n");
349 return DSERR_INVALIDPARAM;
352 if (TRACE_ON(dsound)) {
353 TRACE("(structsize=%ld)\n",dsbd->dwSize);
354 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
355 _dump_DSBCAPS(dsbd->dwFlags);
356 DPRINTF(")\n");
357 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
358 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
361 wfex = dsbd->lpwfxFormat;
363 if (wfex)
364 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
365 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
366 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
367 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
368 wfex->wBitsPerSample, wfex->cbSize);
370 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
371 if (This->primary) {
372 WARN("Primary Buffer already created\n");
373 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
374 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
375 } else {
376 This->dsbd = *dsbd;
377 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->primary), &(This->dsbd));
378 if (This->primary) {
379 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->primary));
380 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->primary);
381 } else
382 WARN("PrimaryBufferImpl_Create failed\n");
384 } else {
385 IDirectSoundBufferImpl * dsb;
386 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
387 if (dsb) {
388 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
389 if (*ppdsb) {
390 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
391 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
392 } else
393 WARN("SecondaryBufferImpl_Create failed\n");
394 } else
395 WARN("IDirectSoundBufferImpl_Create failed\n");
398 return hres;
401 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
402 LPDIRECTSOUND8 iface,
403 LPDSCAPS lpDSCaps)
405 ICOM_THIS(IDirectSoundImpl,iface);
406 TRACE("(%p,%p)\n",This,lpDSCaps);
408 if (This == NULL) {
409 WARN("invalid parameter: This == NULL\n");
410 return DSERR_INVALIDPARAM;
413 if (This->initialized == FALSE) {
414 WARN("not initialized\n");
415 return DSERR_UNINITIALIZED;
418 if (lpDSCaps == NULL) {
419 WARN("invalid parameter: lpDSCaps = NULL\n");
420 return DSERR_INVALIDPARAM;
423 /* check if there is enough room */
424 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
425 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
426 lpDSCaps->dwSize, sizeof(*lpDSCaps));
427 return DSERR_INVALIDPARAM;
430 lpDSCaps->dwFlags = This->drvcaps.dwFlags;
431 if (TRACE_ON(dsound)) {
432 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
433 _dump_DSCAPS(lpDSCaps->dwFlags);
434 DPRINTF(")\n");
436 lpDSCaps->dwMinSecondarySampleRate = This->drvcaps.dwMinSecondarySampleRate;
437 lpDSCaps->dwMaxSecondarySampleRate = This->drvcaps.dwMaxSecondarySampleRate;
438 lpDSCaps->dwPrimaryBuffers = This->drvcaps.dwPrimaryBuffers;
439 lpDSCaps->dwMaxHwMixingAllBuffers = This->drvcaps.dwMaxHwMixingAllBuffers;
440 lpDSCaps->dwMaxHwMixingStaticBuffers = This->drvcaps.dwMaxHwMixingStaticBuffers;
441 lpDSCaps->dwMaxHwMixingStreamingBuffers = This->drvcaps.dwMaxHwMixingStreamingBuffers;
442 lpDSCaps->dwFreeHwMixingAllBuffers = This->drvcaps.dwFreeHwMixingAllBuffers;
443 lpDSCaps->dwFreeHwMixingStaticBuffers = This->drvcaps.dwFreeHwMixingStaticBuffers;
444 lpDSCaps->dwFreeHwMixingStreamingBuffers = This->drvcaps.dwFreeHwMixingStreamingBuffers;
445 lpDSCaps->dwMaxHw3DAllBuffers = This->drvcaps.dwMaxHw3DAllBuffers;
446 lpDSCaps->dwMaxHw3DStaticBuffers = This->drvcaps.dwMaxHw3DStaticBuffers;
447 lpDSCaps->dwMaxHw3DStreamingBuffers = This->drvcaps.dwMaxHw3DStreamingBuffers;
448 lpDSCaps->dwFreeHw3DAllBuffers = This->drvcaps.dwFreeHw3DAllBuffers;
449 lpDSCaps->dwFreeHw3DStaticBuffers = This->drvcaps.dwFreeHw3DStaticBuffers;
450 lpDSCaps->dwFreeHw3DStreamingBuffers = This->drvcaps.dwFreeHw3DStreamingBuffers;
451 lpDSCaps->dwTotalHwMemBytes = This->drvcaps.dwTotalHwMemBytes;
452 lpDSCaps->dwFreeHwMemBytes = This->drvcaps.dwFreeHwMemBytes;
453 lpDSCaps->dwMaxContigFreeHwMemBytes = This->drvcaps.dwMaxContigFreeHwMemBytes;
455 /* driver doesn't have these */
456 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
457 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
459 return DS_OK;
462 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
463 LPDIRECTSOUND8 iface,
464 LPDIRECTSOUNDBUFFER psb,
465 LPLPDIRECTSOUNDBUFFER ppdsb)
467 IDirectSoundBufferImpl* pdsb;
468 IDirectSoundBufferImpl* dsb;
469 HRESULT hres = DS_OK;
470 int size;
471 ICOM_THIS(IDirectSoundImpl,iface);
473 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
475 if (This == NULL) {
476 WARN("invalid parameter: This == NULL\n");
477 return DSERR_INVALIDPARAM;
480 if (This->initialized == FALSE) {
481 WARN("not initialized\n");
482 return DSERR_UNINITIALIZED;
485 if (psb == NULL) {
486 WARN("invalid parameter: psb == NULL\n");
487 return DSERR_INVALIDPARAM;
490 if (ppdsb == NULL) {
491 WARN("invalid parameter: ppdsb == NULL\n");
492 return DSERR_INVALIDPARAM;
495 /* FIXME: hack to make sure we have a secondary buffer */
496 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
497 WARN("trying to duplicate primary buffer\n");
498 *ppdsb = NULL;
499 return DSERR_INVALIDCALL;
502 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
504 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
506 if (dsb == NULL) {
507 WARN("out of memory\n");
508 *ppdsb = NULL;
509 return DSERR_OUTOFMEMORY;
512 memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
514 if (pdsb->hwbuf) {
515 TRACE("duplicating hardware buffer\n");
517 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
518 if (hres != DS_OK) {
519 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
520 dsb->hwbuf = NULL;
521 /* allocate buffer */
522 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
523 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
524 if (dsb->buffer == NULL) {
525 WARN("out of memory\n");
526 HeapFree(GetProcessHeap(),0,dsb);
527 *ppdsb = NULL;
528 return DSERR_OUTOFMEMORY;
531 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
532 if (dsb->buffer->memory == NULL) {
533 WARN("out of memory\n");
534 HeapFree(GetProcessHeap(),0,dsb->buffer);
535 HeapFree(GetProcessHeap(),0,dsb);
536 *ppdsb = NULL;
537 return DSERR_OUTOFMEMORY;
539 dsb->buffer->ref = 1;
541 /* FIXME: copy buffer ? */
544 } else {
545 dsb->hwbuf = NULL;
546 dsb->buffer->ref++;
549 dsb->ref = 0;
550 dsb->state = STATE_STOPPED;
551 dsb->playpos = 0;
552 dsb->buf_mixpos = 0;
553 dsb->dsound = This;
554 dsb->ds3db = NULL;
555 dsb->iks = NULL; /* FIXME? */
556 dsb->dsb = NULL;
558 /* variable sized struct so calculate size based on format */
559 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
561 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
562 if (dsb->pwfx == NULL) {
563 WARN("out of memory\n");
564 HeapFree(GetProcessHeap(),0,dsb->buffer);
565 HeapFree(GetProcessHeap(),0,dsb);
566 *ppdsb = NULL;
567 return DSERR_OUTOFMEMORY;
570 memcpy(dsb->pwfx, pdsb->pwfx, size);
572 InitializeCriticalSection(&(dsb->lock));
573 dsb->lock.DebugInfo->Spare[1] = (DWORD)"DSOUNDBUFFER_lock";
574 /* register buffer */
575 RtlAcquireResourceExclusive(&(This->lock), TRUE);
577 IDirectSoundBufferImpl **newbuffers;
578 if (This->buffers)
579 newbuffers = HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
580 else
581 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
583 if (newbuffers) {
584 This->buffers = newbuffers;
585 This->buffers[This->nrofbuffers] = dsb;
586 This->nrofbuffers++;
587 TRACE("buffer count is now %d\n", This->nrofbuffers);
588 } else {
589 ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
590 IDirectSoundBuffer8_Release(psb);
591 DeleteCriticalSection(&(dsb->lock));
592 RtlReleaseResource(&(This->lock));
593 HeapFree(GetProcessHeap(),0,dsb->buffer);
594 HeapFree(GetProcessHeap(),0,dsb->pwfx);
595 HeapFree(GetProcessHeap(),0,dsb);
596 *ppdsb = 0;
597 return DSERR_OUTOFMEMORY;
600 RtlReleaseResource(&(This->lock));
601 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
602 if (*ppdsb) {
603 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
604 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
605 } else
606 WARN("SecondaryBufferImpl_Create failed\n");
608 return hres;
611 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
612 LPDIRECTSOUND8 iface,
613 HWND hwnd,
614 DWORD level)
616 ICOM_THIS(IDirectSoundImpl,iface);
617 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
619 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
620 FIXME("level=%s not fully supported\n",
621 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
623 This->priolevel = level;
624 return DS_OK;
627 static HRESULT WINAPI IDirectSoundImpl_Compact(
628 LPDIRECTSOUND8 iface)
630 ICOM_THIS(IDirectSoundImpl,iface);
631 TRACE("(%p)\n",This);
633 if (This->initialized == FALSE) {
634 WARN("not initialized\n");
635 return DSERR_UNINITIALIZED;
638 if (This->priolevel != DSSCL_PRIORITY) {
639 WARN("incorrect priority level\n");
640 return DSERR_PRIOLEVELNEEDED;
643 return DS_OK;
646 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
647 LPDIRECTSOUND8 iface,
648 LPDWORD lpdwSpeakerConfig)
650 ICOM_THIS(IDirectSoundImpl,iface);
651 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
653 if (This->initialized == FALSE) {
654 WARN("not initialized\n");
655 return DSERR_UNINITIALIZED;
658 if (lpdwSpeakerConfig == NULL) {
659 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
660 return DSERR_INVALIDPARAM;
663 WARN("not fully functional\n");
664 *lpdwSpeakerConfig = This->speaker_config;
665 return DS_OK;
668 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
669 LPDIRECTSOUND8 iface,
670 DWORD config)
672 ICOM_THIS(IDirectSoundImpl,iface);
673 TRACE("(%p,0x%08lx)\n",This,config);
675 if (This->initialized == FALSE) {
676 WARN("not initialized\n");
677 return DSERR_UNINITIALIZED;
680 This->speaker_config = config;
681 WARN("not fully functional\n");
682 return DS_OK;
685 static HRESULT WINAPI IDirectSoundImpl_Initialize(
686 LPDIRECTSOUND8 iface,
687 LPCGUID lpcGuid)
689 ICOM_THIS(IDirectSoundImpl,iface);
690 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
692 This->initialized = TRUE;
694 return DS_OK;
697 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
698 LPDIRECTSOUND8 iface,
699 LPDWORD pdwCertified)
701 ICOM_THIS(IDirectSoundImpl,iface);
702 TRACE("(%p, %p)\n",This,pdwCertified);
704 if (This->initialized == FALSE) {
705 WARN("not initialized\n");
706 return DSERR_UNINITIALIZED;
709 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
710 *pdwCertified = DS_CERTIFIED;
711 else
712 *pdwCertified = DS_UNCERTIFIED;
713 return DS_OK;
716 static IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
718 IDirectSoundImpl_QueryInterface,
719 IDirectSoundImpl_AddRef,
720 IDirectSoundImpl_Release,
721 IDirectSoundImpl_CreateSoundBuffer,
722 IDirectSoundImpl_GetCaps,
723 IDirectSoundImpl_DuplicateSoundBuffer,
724 IDirectSoundImpl_SetCooperativeLevel,
725 IDirectSoundImpl_Compact,
726 IDirectSoundImpl_GetSpeakerConfig,
727 IDirectSoundImpl_SetSpeakerConfig,
728 IDirectSoundImpl_Initialize,
729 IDirectSoundImpl_VerifyCertification
732 HRESULT WINAPI IDirectSoundImpl_Create(
733 LPCGUID lpcGUID,
734 LPDIRECTSOUND8 * ppDS)
736 HRESULT err;
737 PIDSDRIVER drv = NULL;
738 IDirectSoundImpl* pDS;
739 unsigned wod, wodn;
740 BOOLEAN found = FALSE;
741 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
743 /* Enumerate WINMM audio devices and find the one we want */
744 wodn = waveOutGetNumDevs();
745 if (!wodn) {
746 WARN("no driver\n");
747 *ppDS = NULL;
748 return DSERR_NODRIVER;
751 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
753 for (wod=0; wod<wodn; wod++) {
754 if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
755 found = TRUE;
756 break;
760 if (found == FALSE) {
761 WARN("No device found matching given ID!\n");
762 *ppDS = NULL;
763 return DSERR_NODRIVER;
766 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
767 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
769 /* Disable the direct sound driver to force emulation if requested. */
770 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
771 drv = NULL;
773 /* Allocate memory */
774 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
775 if (ppDS == NULL) {
776 WARN("out of memory\n");
777 *ppDS = NULL;
778 return DSERR_OUTOFMEMORY;
781 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
782 pDS->ref = 0;
784 pDS->driver = drv;
785 pDS->priolevel = DSSCL_NORMAL;
786 pDS->fraglen = 0;
787 pDS->hwbuf = NULL;
788 pDS->buffer = NULL;
789 pDS->buflen = 0;
790 pDS->writelead = 0;
791 pDS->state = STATE_STOPPED;
792 pDS->nrofbuffers = 0;
793 pDS->buffers = NULL;
794 pDS->primary = NULL;
795 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
796 pDS->initialized = FALSE;
798 /* 3D listener initial parameters */
799 pDS->listener = NULL;
800 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
801 pDS->ds3dl.vPosition.x = 0.0;
802 pDS->ds3dl.vPosition.y = 0.0;
803 pDS->ds3dl.vPosition.z = 0.0;
804 pDS->ds3dl.vVelocity.x = 0.0;
805 pDS->ds3dl.vVelocity.y = 0.0;
806 pDS->ds3dl.vVelocity.z = 0.0;
807 pDS->ds3dl.vOrientFront.x = 0.0;
808 pDS->ds3dl.vOrientFront.y = 0.0;
809 pDS->ds3dl.vOrientFront.z = 1.0;
810 pDS->ds3dl.vOrientTop.x = 0.0;
811 pDS->ds3dl.vOrientTop.y = 1.0;
812 pDS->ds3dl.vOrientTop.z = 0.0;
813 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
814 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
815 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
817 pDS->prebuf = ds_snd_queue_max;
818 pDS->guid = *lpcGUID;
820 /* Get driver description */
821 if (drv) {
822 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
823 if (err != DS_OK) {
824 WARN("IDsDriver_GetDriverDesc failed\n");
825 HeapFree(GetProcessHeap(),0,pDS);
826 *ppDS = NULL;
827 return err;
829 } else {
830 /* if no DirectSound interface available, use WINMM API instead */
831 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
834 pDS->drvdesc.dnDevNode = wod;
836 /* Set default wave format (may need it for waveOutOpen) */
837 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
838 if (pDS->pwfx == NULL) {
839 WARN("out of memory\n");
840 HeapFree(GetProcessHeap(),0,pDS);
841 *ppDS = NULL;
842 return DSERR_OUTOFMEMORY;
845 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
846 /* We rely on the sound driver to return the actual sound format of
847 * the device if it does not support 22050x8x2 and is given the
848 * WAVE_DIRECTSOUND flag.
850 pDS->pwfx->nSamplesPerSec = 22050;
851 pDS->pwfx->wBitsPerSample = 8;
852 pDS->pwfx->nChannels = 2;
853 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
854 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
855 pDS->pwfx->cbSize = 0;
857 /* If the driver requests being opened through MMSYSTEM
858 * (which is recommended by the DDK), it is supposed to happen
859 * before the DirectSound interface is opened */
860 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
862 DWORD flags = CALLBACK_FUNCTION;
864 /* disable direct sound if requested */
865 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
866 flags |= WAVE_DIRECTSOUND;
868 err = mmErr(waveOutOpen(&(pDS->hwo),
869 pDS->drvdesc.dnDevNode, pDS->pwfx,
870 (DWORD)DSOUND_callback, (DWORD)pDS,
871 flags));
872 if (err != DS_OK) {
873 WARN("waveOutOpen failed\n");
874 HeapFree(GetProcessHeap(),0,pDS);
875 *ppDS = NULL;
876 return err;
880 if (drv) {
881 err = IDsDriver_Open(drv);
882 if (err != DS_OK) {
883 WARN("IDsDriver_Open failed\n");
884 HeapFree(GetProcessHeap(),0,pDS);
885 *ppDS = NULL;
886 return err;
889 /* the driver is now open, so it's now allowed to call GetCaps */
890 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
891 if (err != DS_OK) {
892 WARN("IDsDriver_GetCaps failed\n");
893 HeapFree(GetProcessHeap(),0,pDS);
894 *ppDS = NULL;
895 return err;
897 } else {
898 WAVEOUTCAPSA woc;
899 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
900 if (err != DS_OK) {
901 WARN("waveOutGetDevCaps failed\n");
902 HeapFree(GetProcessHeap(),0,pDS);
903 *ppDS = NULL;
904 return err;
906 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
907 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
908 (woc.dwFormats & WAVE_FORMAT_2M08) ||
909 (woc.dwFormats & WAVE_FORMAT_4M08) ||
910 (woc.dwFormats & WAVE_FORMAT_48M08) ||
911 (woc.dwFormats & WAVE_FORMAT_96M08)) {
912 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
913 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
915 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
916 (woc.dwFormats & WAVE_FORMAT_2M16) ||
917 (woc.dwFormats & WAVE_FORMAT_4M16) ||
918 (woc.dwFormats & WAVE_FORMAT_48M16) ||
919 (woc.dwFormats & WAVE_FORMAT_96M16)) {
920 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
921 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
923 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
924 (woc.dwFormats & WAVE_FORMAT_2S08) ||
925 (woc.dwFormats & WAVE_FORMAT_4S08) ||
926 (woc.dwFormats & WAVE_FORMAT_48S08) ||
927 (woc.dwFormats & WAVE_FORMAT_96S08)) {
928 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
929 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
931 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
932 (woc.dwFormats & WAVE_FORMAT_2S16) ||
933 (woc.dwFormats & WAVE_FORMAT_4S16) ||
934 (woc.dwFormats & WAVE_FORMAT_48S16) ||
935 (woc.dwFormats & WAVE_FORMAT_96S16)) {
936 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
937 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
939 if (ds_emuldriver)
940 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
941 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
942 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
943 pDS->drvcaps.dwPrimaryBuffers = 1;
946 InitializeCriticalSection(&(pDS->mixlock));
947 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
948 RtlInitializeResource(&(pDS->lock));
950 *ppDS = (LPDIRECTSOUND8)pDS;
952 return DS_OK;
954 /*******************************************************************************
955 * IDirectSound_IUnknown
957 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
958 LPUNKNOWN iface,
959 REFIID riid,
960 LPVOID * ppobj)
962 ICOM_THIS(IDirectSound_IUnknown,iface);
963 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
964 return DSOUND_QueryInterface(This->pds, riid, ppobj);
967 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
968 LPUNKNOWN iface)
970 ICOM_THIS(IDirectSound_IUnknown,iface);
971 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
972 return InterlockedIncrement(&This->ref);
975 static ULONG WINAPI IDirectSound_IUnknown_Release(
976 LPUNKNOWN iface)
978 ICOM_THIS(IDirectSound_IUnknown,iface);
979 ULONG ulReturn;
980 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
981 ulReturn = InterlockedDecrement(&This->ref);
982 if (ulReturn == 0) {
983 IDirectSoundImpl_Release(This->pds);
984 HeapFree(GetProcessHeap(),0,This);
985 TRACE("(%p) released\n",This);
987 return ulReturn;
990 static IUnknownVtbl DirectSound_Unknown_Vtbl =
992 IDirectSound_IUnknown_QueryInterface,
993 IDirectSound_IUnknown_AddRef,
994 IDirectSound_IUnknown_Release
997 HRESULT WINAPI IDirectSound_IUnknown_Create(
998 LPDIRECTSOUND8 pds,
999 LPUNKNOWN * ppunk)
1001 IDirectSound_IUnknown * pdsunk;
1002 TRACE("(%p,%p)\n",pds,ppunk);
1004 if (ppunk == NULL) {
1005 ERR("invalid parameter: ppunk == NULL\n");
1006 return DSERR_INVALIDPARAM;
1009 if (pds == NULL) {
1010 ERR("invalid parameter: pds == NULL\n");
1011 *ppunk = NULL;
1012 return DSERR_INVALIDPARAM;
1015 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1016 if (pdsunk == NULL) {
1017 WARN("out of memory\n");
1018 *ppunk = NULL;
1019 return DSERR_OUTOFMEMORY;
1022 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1023 pdsunk->ref = 0;
1024 pdsunk->pds = pds;
1026 IDirectSoundImpl_AddRef(pds);
1027 *ppunk = (LPUNKNOWN)pdsunk;
1029 return DS_OK;
1032 /*******************************************************************************
1033 * IDirectSound_IDirectSound
1035 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1036 LPDIRECTSOUND iface,
1037 REFIID riid,
1038 LPVOID * ppobj)
1040 ICOM_THIS(IDirectSound_IDirectSound,iface);
1041 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1042 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1045 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1046 LPDIRECTSOUND iface)
1048 ICOM_THIS(IDirectSound_IDirectSound,iface);
1049 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1050 return InterlockedIncrement(&This->ref);
1053 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1054 LPDIRECTSOUND iface)
1056 ICOM_THIS(IDirectSound_IDirectSound,iface);
1057 ULONG ulReturn;
1058 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1059 ulReturn = InterlockedDecrement(&This->ref);
1060 if (ulReturn == 0) {
1061 IDirectSoundImpl_Release(This->pds);
1062 HeapFree(GetProcessHeap(),0,This);
1063 TRACE("(%p) released\n",This);
1065 return ulReturn;
1068 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1069 LPDIRECTSOUND iface,
1070 LPCDSBUFFERDESC dsbd,
1071 LPLPDIRECTSOUNDBUFFER ppdsb,
1072 LPUNKNOWN lpunk)
1074 ICOM_THIS(IDirectSound_IDirectSound,iface);
1075 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1076 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1079 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1080 LPDIRECTSOUND iface,
1081 LPDSCAPS lpDSCaps)
1083 ICOM_THIS(IDirectSound_IDirectSound,iface);
1084 TRACE("(%p,%p)\n",This,lpDSCaps);
1085 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1088 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1089 LPDIRECTSOUND iface,
1090 LPDIRECTSOUNDBUFFER psb,
1091 LPLPDIRECTSOUNDBUFFER ppdsb)
1093 ICOM_THIS(IDirectSound_IDirectSound,iface);
1094 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1095 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1098 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1099 LPDIRECTSOUND iface,
1100 HWND hwnd,
1101 DWORD level)
1103 ICOM_THIS(IDirectSound_IDirectSound,iface);
1104 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1105 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1108 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1109 LPDIRECTSOUND iface)
1111 ICOM_THIS(IDirectSound_IDirectSound,iface);
1112 TRACE("(%p)\n", This);
1113 return IDirectSoundImpl_Compact(This->pds);
1116 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1117 LPDIRECTSOUND iface,
1118 LPDWORD lpdwSpeakerConfig)
1120 ICOM_THIS(IDirectSound_IDirectSound,iface);
1121 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1122 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1125 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1126 LPDIRECTSOUND iface,
1127 DWORD config)
1129 ICOM_THIS(IDirectSound_IDirectSound,iface);
1130 TRACE("(%p,0x%08lx)\n",This,config);
1131 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1134 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1135 LPDIRECTSOUND iface,
1136 LPCGUID lpcGuid)
1138 ICOM_THIS(IDirectSound_IDirectSound,iface);
1139 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1140 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1143 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1145 IDirectSound_IDirectSound_QueryInterface,
1146 IDirectSound_IDirectSound_AddRef,
1147 IDirectSound_IDirectSound_Release,
1148 IDirectSound_IDirectSound_CreateSoundBuffer,
1149 IDirectSound_IDirectSound_GetCaps,
1150 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1151 IDirectSound_IDirectSound_SetCooperativeLevel,
1152 IDirectSound_IDirectSound_Compact,
1153 IDirectSound_IDirectSound_GetSpeakerConfig,
1154 IDirectSound_IDirectSound_SetSpeakerConfig,
1155 IDirectSound_IDirectSound_Initialize
1158 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1159 LPDIRECTSOUND8 pds,
1160 LPDIRECTSOUND * ppds)
1162 IDirectSound_IDirectSound * pdsds;
1163 TRACE("(%p,%p)\n",pds,ppds);
1165 if (ppds == NULL) {
1166 ERR("invalid parameter: ppds == NULL\n");
1167 return DSERR_INVALIDPARAM;
1170 if (pds == NULL) {
1171 ERR("invalid parameter: pds == NULL\n");
1172 *ppds = NULL;
1173 return DSERR_INVALIDPARAM;
1176 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1177 if (pdsds == NULL) {
1178 WARN("out of memory\n");
1179 *ppds = NULL;
1180 return DSERR_OUTOFMEMORY;
1183 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1184 pdsds->ref = 0;
1185 pdsds->pds = pds;
1187 IDirectSoundImpl_AddRef(pds);
1188 *ppds = (LPDIRECTSOUND)pdsds;
1190 return DS_OK;
1193 /*******************************************************************************
1194 * IDirectSound8_IUnknown
1196 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1197 LPUNKNOWN iface,
1198 REFIID riid,
1199 LPVOID * ppobj)
1201 ICOM_THIS(IDirectSound_IUnknown,iface);
1202 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1203 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1206 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1207 LPUNKNOWN iface)
1209 ICOM_THIS(IDirectSound_IUnknown,iface);
1210 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1211 return InterlockedIncrement(&This->ref);
1214 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1215 LPUNKNOWN iface)
1217 ICOM_THIS(IDirectSound_IUnknown,iface);
1218 ULONG ulReturn;
1219 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1220 ulReturn = InterlockedDecrement(&This->ref);
1221 if (ulReturn == 0) {
1222 IDirectSoundImpl_Release(This->pds);
1223 HeapFree(GetProcessHeap(),0,This);
1224 TRACE("(%p) released\n",This);
1226 return ulReturn;
1229 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1231 IDirectSound8_IUnknown_QueryInterface,
1232 IDirectSound8_IUnknown_AddRef,
1233 IDirectSound8_IUnknown_Release
1236 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1237 LPDIRECTSOUND8 pds,
1238 LPUNKNOWN * ppunk)
1240 IDirectSound8_IUnknown * pdsunk;
1241 TRACE("(%p,%p)\n",pds,ppunk);
1243 if (ppunk == NULL) {
1244 ERR("invalid parameter: ppunk == NULL\n");
1245 return DSERR_INVALIDPARAM;
1248 if (pds == NULL) {
1249 ERR("invalid parameter: pds == NULL\n");
1250 *ppunk = NULL;
1251 return DSERR_INVALIDPARAM;
1254 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1255 if (pdsunk == NULL) {
1256 WARN("out of memory\n");
1257 *ppunk = NULL;
1258 return DSERR_OUTOFMEMORY;
1261 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1262 pdsunk->ref = 0;
1263 pdsunk->pds = pds;
1265 IDirectSoundImpl_AddRef(pds);
1266 *ppunk = (LPUNKNOWN)pdsunk;
1268 return DS_OK;
1271 /*******************************************************************************
1272 * IDirectSound8_IDirectSound
1274 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1275 LPDIRECTSOUND iface,
1276 REFIID riid,
1277 LPVOID * ppobj)
1279 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1280 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1281 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1284 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1285 LPDIRECTSOUND iface)
1287 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1288 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1289 return InterlockedIncrement(&This->ref);
1292 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1293 LPDIRECTSOUND iface)
1295 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1296 ULONG ulReturn;
1297 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1298 ulReturn = InterlockedDecrement(&This->ref);
1299 if (ulReturn == 0) {
1300 IDirectSoundImpl_Release(This->pds);
1301 HeapFree(GetProcessHeap(),0,This);
1302 TRACE("(%p) released\n",This);
1304 return ulReturn;
1307 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1308 LPDIRECTSOUND iface,
1309 LPCDSBUFFERDESC dsbd,
1310 LPLPDIRECTSOUNDBUFFER ppdsb,
1311 LPUNKNOWN lpunk)
1313 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1314 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1315 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1318 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1319 LPDIRECTSOUND iface,
1320 LPDSCAPS lpDSCaps)
1322 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1323 TRACE("(%p,%p)\n",This,lpDSCaps);
1324 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1327 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1328 LPDIRECTSOUND iface,
1329 LPDIRECTSOUNDBUFFER psb,
1330 LPLPDIRECTSOUNDBUFFER ppdsb)
1332 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1333 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1334 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1337 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1338 LPDIRECTSOUND iface,
1339 HWND hwnd,
1340 DWORD level)
1342 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1343 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1344 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1347 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1348 LPDIRECTSOUND iface)
1350 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1351 TRACE("(%p)\n", This);
1352 return IDirectSoundImpl_Compact(This->pds);
1355 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1356 LPDIRECTSOUND iface,
1357 LPDWORD lpdwSpeakerConfig)
1359 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1360 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1361 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1364 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1365 LPDIRECTSOUND iface,
1366 DWORD config)
1368 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1369 TRACE("(%p,0x%08lx)\n",This,config);
1370 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1373 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1374 LPDIRECTSOUND iface,
1375 LPCGUID lpcGuid)
1377 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1378 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1379 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1382 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1384 IDirectSound8_IDirectSound_QueryInterface,
1385 IDirectSound8_IDirectSound_AddRef,
1386 IDirectSound8_IDirectSound_Release,
1387 IDirectSound8_IDirectSound_CreateSoundBuffer,
1388 IDirectSound8_IDirectSound_GetCaps,
1389 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1390 IDirectSound8_IDirectSound_SetCooperativeLevel,
1391 IDirectSound8_IDirectSound_Compact,
1392 IDirectSound8_IDirectSound_GetSpeakerConfig,
1393 IDirectSound8_IDirectSound_SetSpeakerConfig,
1394 IDirectSound8_IDirectSound_Initialize
1397 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1398 LPDIRECTSOUND8 pds,
1399 LPDIRECTSOUND * ppds)
1401 IDirectSound8_IDirectSound * pdsds;
1402 TRACE("(%p,%p)\n",pds,ppds);
1404 if (ppds == NULL) {
1405 ERR("invalid parameter: ppds == NULL\n");
1406 return DSERR_INVALIDPARAM;
1409 if (pds == NULL) {
1410 ERR("invalid parameter: pds == NULL\n");
1411 *ppds = NULL;
1412 return DSERR_INVALIDPARAM;
1415 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1416 if (pdsds == NULL) {
1417 WARN("out of memory\n");
1418 *ppds = NULL;
1419 return DSERR_OUTOFMEMORY;
1422 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1423 pdsds->ref = 0;
1424 pdsds->pds = pds;
1426 IDirectSoundImpl_AddRef(pds);
1427 *ppds = (LPDIRECTSOUND)pdsds;
1429 return DS_OK;
1432 /*******************************************************************************
1433 * IDirectSound8_IDirectSound8
1435 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1436 LPDIRECTSOUND8 iface,
1437 REFIID riid,
1438 LPVOID * ppobj)
1440 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1441 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1442 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1445 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1446 LPDIRECTSOUND8 iface)
1448 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1449 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1450 return InterlockedIncrement(&This->ref);
1453 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1454 LPDIRECTSOUND8 iface)
1456 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1457 ULONG ulReturn;
1458 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1459 ulReturn = InterlockedDecrement(&This->ref);
1460 if (ulReturn == 0) {
1461 IDirectSoundImpl_Release(This->pds);
1462 HeapFree(GetProcessHeap(),0,This);
1463 TRACE("(%p) released\n",This);
1465 return ulReturn;
1468 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1469 LPDIRECTSOUND8 iface,
1470 LPCDSBUFFERDESC dsbd,
1471 LPLPDIRECTSOUNDBUFFER ppdsb,
1472 LPUNKNOWN lpunk)
1474 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1475 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1476 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1479 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1480 LPDIRECTSOUND8 iface,
1481 LPDSCAPS lpDSCaps)
1483 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1484 TRACE("(%p,%p)\n",This,lpDSCaps);
1485 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1488 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1489 LPDIRECTSOUND8 iface,
1490 LPDIRECTSOUNDBUFFER psb,
1491 LPLPDIRECTSOUNDBUFFER ppdsb)
1493 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1494 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1495 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1498 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1499 LPDIRECTSOUND8 iface,
1500 HWND hwnd,
1501 DWORD level)
1503 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1504 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1505 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1508 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1509 LPDIRECTSOUND8 iface)
1511 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1512 TRACE("(%p)\n", This);
1513 return IDirectSoundImpl_Compact(This->pds);
1516 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1517 LPDIRECTSOUND8 iface,
1518 LPDWORD lpdwSpeakerConfig)
1520 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1521 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1522 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1525 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1526 LPDIRECTSOUND8 iface,
1527 DWORD config)
1529 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1530 TRACE("(%p,0x%08lx)\n",This,config);
1531 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1534 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1535 LPDIRECTSOUND8 iface,
1536 LPCGUID lpcGuid)
1538 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1539 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1540 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1543 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1544 LPDIRECTSOUND8 iface,
1545 LPDWORD pdwCertified)
1547 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1548 TRACE("(%p, %p)\n", This, pdwCertified);
1549 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1552 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1554 IDirectSound8_IDirectSound8_QueryInterface,
1555 IDirectSound8_IDirectSound8_AddRef,
1556 IDirectSound8_IDirectSound8_Release,
1557 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1558 IDirectSound8_IDirectSound8_GetCaps,
1559 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1560 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1561 IDirectSound8_IDirectSound8_Compact,
1562 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1563 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1564 IDirectSound8_IDirectSound8_Initialize,
1565 IDirectSound8_IDirectSound8_VerifyCertification
1568 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1569 LPDIRECTSOUND8 pds,
1570 LPDIRECTSOUND8 * ppds)
1572 IDirectSound8_IDirectSound8 * pdsds;
1573 TRACE("(%p,%p)\n",pds,ppds);
1575 if (ppds == NULL) {
1576 ERR("invalid parameter: ppds == NULL\n");
1577 return DSERR_INVALIDPARAM;
1580 if (pds == NULL) {
1581 ERR("invalid parameter: pds == NULL\n");
1582 *ppds = NULL;
1583 return DSERR_INVALIDPARAM;
1586 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1587 if (pdsds == NULL) {
1588 WARN("out of memory\n");
1589 *ppds = NULL;
1590 return DSERR_OUTOFMEMORY;
1593 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1594 pdsds->ref = 0;
1595 pdsds->pds = pds;
1597 IDirectSoundImpl_AddRef(pds);
1598 *ppds = (LPDIRECTSOUND8)pdsds;
1600 return DS_OK;
1603 HRESULT WINAPI DSOUND_Create(
1604 LPCGUID lpcGUID,
1605 LPDIRECTSOUND *ppDS,
1606 IUnknown *pUnkOuter)
1608 HRESULT hr;
1609 GUID devGuid;
1611 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1613 if (pUnkOuter != NULL) {
1614 WARN("invalid parameter: pUnkOuter != NULL\n");
1615 return DSERR_INVALIDPARAM;
1618 if (ppDS == NULL) {
1619 WARN("invalid parameter: ppDS == NULL\n");
1620 return DSERR_INVALIDPARAM;
1623 /* Get dsound configuration */
1624 setup_dsound_options();
1626 /* Default device? */
1627 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1628 lpcGUID = &DSDEVID_DefaultPlayback;
1630 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1631 WARN("invalid parameter: lpcGUID\n");
1632 *ppDS = NULL;
1633 return DSERR_INVALIDPARAM;
1636 if (dsound) {
1637 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1638 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1639 if (*ppDS)
1640 IDirectSound_IDirectSound_AddRef(*ppDS);
1641 else
1642 WARN("IDirectSound_IDirectSound_Create failed\n");
1643 } else {
1644 ERR("different dsound already opened (only support one sound card at a time now)\n");
1645 *ppDS = NULL;
1646 hr = DSERR_ALLOCATED;
1648 } else {
1649 LPDIRECTSOUND8 pDS;
1650 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1651 if (hr == DS_OK) {
1652 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1653 if (hr == DS_OK) {
1654 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1655 if (*ppDS) {
1656 IDirectSound_IDirectSound_AddRef(*ppDS);
1658 dsound = (IDirectSoundImpl*)pDS;
1659 timeBeginPeriod(DS_TIME_RES);
1660 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1661 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1662 } else {
1663 WARN("IDirectSound_IDirectSound_Create failed\n");
1664 IDirectSound8_Release(pDS);
1666 } else {
1667 WARN("DSOUND_PrimaryCreate failed\n");
1668 IDirectSound8_Release(pDS);
1670 } else
1671 WARN("IDirectSoundImpl_Create failed\n");
1674 return hr;
1677 /*******************************************************************************
1678 * DirectSoundCreate (DSOUND.1)
1680 * Creates and initializes a DirectSound interface.
1682 * PARAMS
1683 * lpcGUID [I] Address of the GUID that identifies the sound device.
1684 * ppDS [O] Address of a variable to receive the interface pointer.
1685 * pUnkOuter [I] Must be NULL.
1687 * RETURNS
1688 * Success: DS_OK
1689 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1690 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1692 HRESULT WINAPI DirectSoundCreate(
1693 LPCGUID lpcGUID,
1694 LPDIRECTSOUND *ppDS,
1695 IUnknown *pUnkOuter)
1697 HRESULT hr;
1699 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1701 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1702 if (hr == DS_OK)
1703 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1705 return hr;
1708 HRESULT WINAPI DSOUND_Create8(
1709 LPCGUID lpcGUID,
1710 LPDIRECTSOUND8 *ppDS,
1711 IUnknown *pUnkOuter)
1713 HRESULT hr;
1714 GUID devGuid;
1716 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1718 if (pUnkOuter != NULL) {
1719 WARN("invalid parameter: pUnkOuter != NULL\n");
1720 return DSERR_INVALIDPARAM;
1723 if (ppDS == NULL) {
1724 WARN("invalid parameter: ppDS == NULL\n");
1725 return DSERR_INVALIDPARAM;
1728 /* Get dsound configuration */
1729 setup_dsound_options();
1731 /* Default device? */
1732 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1733 lpcGUID = &DSDEVID_DefaultPlayback;
1735 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1736 WARN("invalid parameter: lpcGUID\n");
1737 *ppDS = NULL;
1738 return DSERR_INVALIDPARAM;
1741 if (dsound) {
1742 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1743 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1744 if (*ppDS)
1745 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1746 else
1747 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1748 } else {
1749 ERR("different dsound already opened (only support one sound card at a time now)\n");
1750 *ppDS = NULL;
1751 hr = DSERR_ALLOCATED;
1753 } else {
1754 LPDIRECTSOUND8 pDS;
1755 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1756 if (hr == DS_OK) {
1757 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1758 if (hr == DS_OK) {
1759 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1760 if (*ppDS) {
1761 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1763 dsound = (IDirectSoundImpl*)pDS;
1764 timeBeginPeriod(DS_TIME_RES);
1765 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1766 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1767 } else {
1768 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1769 IDirectSound8_Release(pDS);
1771 } else {
1772 WARN("DSOUND_PrimaryCreate failed\n");
1773 IDirectSound8_Release(pDS);
1775 } else
1776 WARN("IDirectSoundImpl_Create failed\n");
1779 return hr;
1782 /*******************************************************************************
1783 * DirectSoundCreate8 (DSOUND.11)
1785 * Creates and initializes a DirectSound8 interface.
1787 * PARAMS
1788 * lpcGUID [I] Address of the GUID that identifies the sound device.
1789 * ppDS [O] Address of a variable to receive the interface pointer.
1790 * pUnkOuter [I] Must be NULL.
1792 * RETURNS
1793 * Success: DS_OK
1794 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1795 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1797 HRESULT WINAPI DirectSoundCreate8(
1798 LPCGUID lpcGUID,
1799 LPDIRECTSOUND8 *ppDS,
1800 IUnknown *pUnkOuter)
1802 HRESULT hr;
1804 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1806 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1807 if (hr == DS_OK)
1808 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1810 return hr;