Remove wine specific DRV_QUERYDSOUNDGUID message and calculate it in
[wine/wine-kai.git] / dlls / dsound / dsound.c
blobf142c640140fdadc7f2ef4c8678f1646c58fe1b1
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 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
719 IDirectSoundImpl_QueryInterface,
720 IDirectSoundImpl_AddRef,
721 IDirectSoundImpl_Release,
722 IDirectSoundImpl_CreateSoundBuffer,
723 IDirectSoundImpl_GetCaps,
724 IDirectSoundImpl_DuplicateSoundBuffer,
725 IDirectSoundImpl_SetCooperativeLevel,
726 IDirectSoundImpl_Compact,
727 IDirectSoundImpl_GetSpeakerConfig,
728 IDirectSoundImpl_SetSpeakerConfig,
729 IDirectSoundImpl_Initialize,
730 IDirectSoundImpl_VerifyCertification
733 HRESULT WINAPI IDirectSoundImpl_Create(
734 LPCGUID lpcGUID,
735 LPDIRECTSOUND8 * ppDS)
737 HRESULT err;
738 PIDSDRIVER drv = NULL;
739 IDirectSoundImpl* pDS;
740 unsigned wod, wodn;
741 BOOLEAN found = FALSE;
742 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
744 /* Enumerate WINMM audio devices and find the one we want */
745 wodn = waveOutGetNumDevs();
746 if (!wodn) {
747 WARN("no driver\n");
748 *ppDS = NULL;
749 return DSERR_NODRIVER;
752 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
754 for (wod=0; wod<wodn; wod++) {
755 if (IsEqualGUID( lpcGUID, &renderer_guids[wod])) {
756 found = TRUE;
757 break;
761 if (found == FALSE) {
762 WARN("No device found matching given ID!\n");
763 *ppDS = NULL;
764 return DSERR_NODRIVER;
767 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
768 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
770 /* Disable the direct sound driver to force emulation if requested. */
771 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
772 drv = NULL;
774 /* Allocate memory */
775 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
776 if (ppDS == NULL) {
777 WARN("out of memory\n");
778 *ppDS = NULL;
779 return DSERR_OUTOFMEMORY;
782 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
783 pDS->ref = 0;
785 pDS->driver = drv;
786 pDS->priolevel = DSSCL_NORMAL;
787 pDS->fraglen = 0;
788 pDS->hwbuf = NULL;
789 pDS->buffer = NULL;
790 pDS->buflen = 0;
791 pDS->writelead = 0;
792 pDS->state = STATE_STOPPED;
793 pDS->nrofbuffers = 0;
794 pDS->buffers = NULL;
795 pDS->primary = NULL;
796 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
797 pDS->initialized = FALSE;
799 /* 3D listener initial parameters */
800 pDS->listener = NULL;
801 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
802 pDS->ds3dl.vPosition.x = 0.0;
803 pDS->ds3dl.vPosition.y = 0.0;
804 pDS->ds3dl.vPosition.z = 0.0;
805 pDS->ds3dl.vVelocity.x = 0.0;
806 pDS->ds3dl.vVelocity.y = 0.0;
807 pDS->ds3dl.vVelocity.z = 0.0;
808 pDS->ds3dl.vOrientFront.x = 0.0;
809 pDS->ds3dl.vOrientFront.y = 0.0;
810 pDS->ds3dl.vOrientFront.z = 1.0;
811 pDS->ds3dl.vOrientTop.x = 0.0;
812 pDS->ds3dl.vOrientTop.y = 1.0;
813 pDS->ds3dl.vOrientTop.z = 0.0;
814 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
815 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
816 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
818 pDS->prebuf = ds_snd_queue_max;
819 pDS->guid = *lpcGUID;
821 /* Get driver description */
822 if (drv) {
823 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
824 if (err != DS_OK) {
825 WARN("IDsDriver_GetDriverDesc failed\n");
826 HeapFree(GetProcessHeap(),0,pDS);
827 *ppDS = NULL;
828 return err;
830 } else {
831 /* if no DirectSound interface available, use WINMM API instead */
832 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
835 pDS->drvdesc.dnDevNode = wod;
837 /* Set default wave format (may need it for waveOutOpen) */
838 pDS->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
839 if (pDS->pwfx == NULL) {
840 WARN("out of memory\n");
841 HeapFree(GetProcessHeap(),0,pDS);
842 *ppDS = NULL;
843 return DSERR_OUTOFMEMORY;
846 pDS->pwfx->wFormatTag = WAVE_FORMAT_PCM;
847 /* We rely on the sound driver to return the actual sound format of
848 * the device if it does not support 22050x8x2 and is given the
849 * WAVE_DIRECTSOUND flag.
851 pDS->pwfx->nSamplesPerSec = 22050;
852 pDS->pwfx->wBitsPerSample = 8;
853 pDS->pwfx->nChannels = 2;
854 pDS->pwfx->nBlockAlign = pDS->pwfx->wBitsPerSample * pDS->pwfx->nChannels / 8;
855 pDS->pwfx->nAvgBytesPerSec = pDS->pwfx->nSamplesPerSec * pDS->pwfx->nBlockAlign;
856 pDS->pwfx->cbSize = 0;
858 /* If the driver requests being opened through MMSYSTEM
859 * (which is recommended by the DDK), it is supposed to happen
860 * before the DirectSound interface is opened */
861 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
863 DWORD flags = CALLBACK_FUNCTION;
865 /* disable direct sound if requested */
866 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
867 flags |= WAVE_DIRECTSOUND;
869 err = mmErr(waveOutOpen(&(pDS->hwo),
870 pDS->drvdesc.dnDevNode, pDS->pwfx,
871 (DWORD)DSOUND_callback, (DWORD)pDS,
872 flags));
873 if (err != DS_OK) {
874 WARN("waveOutOpen failed\n");
875 HeapFree(GetProcessHeap(),0,pDS);
876 *ppDS = NULL;
877 return err;
881 if (drv) {
882 err = IDsDriver_Open(drv);
883 if (err != DS_OK) {
884 WARN("IDsDriver_Open failed\n");
885 HeapFree(GetProcessHeap(),0,pDS);
886 *ppDS = NULL;
887 return err;
890 /* the driver is now open, so it's now allowed to call GetCaps */
891 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
892 if (err != DS_OK) {
893 WARN("IDsDriver_GetCaps failed\n");
894 HeapFree(GetProcessHeap(),0,pDS);
895 *ppDS = NULL;
896 return err;
898 } else {
899 WAVEOUTCAPSA woc;
900 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
901 if (err != DS_OK) {
902 WARN("waveOutGetDevCaps failed\n");
903 HeapFree(GetProcessHeap(),0,pDS);
904 *ppDS = NULL;
905 return err;
907 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
908 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
909 (woc.dwFormats & WAVE_FORMAT_2M08) ||
910 (woc.dwFormats & WAVE_FORMAT_4M08) ||
911 (woc.dwFormats & WAVE_FORMAT_48M08) ||
912 (woc.dwFormats & WAVE_FORMAT_96M08)) {
913 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
914 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
916 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
917 (woc.dwFormats & WAVE_FORMAT_2M16) ||
918 (woc.dwFormats & WAVE_FORMAT_4M16) ||
919 (woc.dwFormats & WAVE_FORMAT_48M16) ||
920 (woc.dwFormats & WAVE_FORMAT_96M16)) {
921 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
922 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
924 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
925 (woc.dwFormats & WAVE_FORMAT_2S08) ||
926 (woc.dwFormats & WAVE_FORMAT_4S08) ||
927 (woc.dwFormats & WAVE_FORMAT_48S08) ||
928 (woc.dwFormats & WAVE_FORMAT_96S08)) {
929 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
930 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
932 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
933 (woc.dwFormats & WAVE_FORMAT_2S16) ||
934 (woc.dwFormats & WAVE_FORMAT_4S16) ||
935 (woc.dwFormats & WAVE_FORMAT_48S16) ||
936 (woc.dwFormats & WAVE_FORMAT_96S16)) {
937 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
938 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
940 if (ds_emuldriver)
941 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
942 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
943 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
944 pDS->drvcaps.dwPrimaryBuffers = 1;
947 InitializeCriticalSection(&(pDS->mixlock));
948 pDS->mixlock.DebugInfo->Spare[1] = (DWORD)"DSOUND_mixlock";
949 RtlInitializeResource(&(pDS->lock));
951 *ppDS = (LPDIRECTSOUND8)pDS;
953 return DS_OK;
955 /*******************************************************************************
956 * IDirectSound_IUnknown
958 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
959 LPUNKNOWN iface,
960 REFIID riid,
961 LPVOID * ppobj)
963 ICOM_THIS(IDirectSound_IUnknown,iface);
964 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
965 return DSOUND_QueryInterface(This->pds, riid, ppobj);
968 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
969 LPUNKNOWN iface)
971 ICOM_THIS(IDirectSound_IUnknown,iface);
972 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
973 return InterlockedIncrement(&This->ref);
976 static ULONG WINAPI IDirectSound_IUnknown_Release(
977 LPUNKNOWN iface)
979 ICOM_THIS(IDirectSound_IUnknown,iface);
980 ULONG ulReturn;
981 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
982 ulReturn = InterlockedDecrement(&This->ref);
983 if (ulReturn == 0) {
984 IDirectSoundImpl_Release(This->pds);
985 HeapFree(GetProcessHeap(),0,This);
986 TRACE("(%p) released\n",This);
988 return ulReturn;
991 static IUnknownVtbl DirectSound_Unknown_Vtbl =
993 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
994 IDirectSound_IUnknown_QueryInterface,
995 IDirectSound_IUnknown_AddRef,
996 IDirectSound_IUnknown_Release
999 HRESULT WINAPI IDirectSound_IUnknown_Create(
1000 LPDIRECTSOUND8 pds,
1001 LPUNKNOWN * ppunk)
1003 IDirectSound_IUnknown * pdsunk;
1004 TRACE("(%p,%p)\n",pds,ppunk);
1006 if (ppunk == NULL) {
1007 ERR("invalid parameter: ppunk == NULL\n");
1008 return DSERR_INVALIDPARAM;
1011 if (pds == NULL) {
1012 ERR("invalid parameter: pds == NULL\n");
1013 *ppunk = NULL;
1014 return DSERR_INVALIDPARAM;
1017 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1018 if (pdsunk == NULL) {
1019 WARN("out of memory\n");
1020 *ppunk = NULL;
1021 return DSERR_OUTOFMEMORY;
1024 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1025 pdsunk->ref = 0;
1026 pdsunk->pds = pds;
1028 IDirectSoundImpl_AddRef(pds);
1029 *ppunk = (LPUNKNOWN)pdsunk;
1031 return DS_OK;
1034 /*******************************************************************************
1035 * IDirectSound_IDirectSound
1037 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1038 LPDIRECTSOUND iface,
1039 REFIID riid,
1040 LPVOID * ppobj)
1042 ICOM_THIS(IDirectSound_IDirectSound,iface);
1043 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1044 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1047 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1048 LPDIRECTSOUND iface)
1050 ICOM_THIS(IDirectSound_IDirectSound,iface);
1051 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1052 return InterlockedIncrement(&This->ref);
1055 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1056 LPDIRECTSOUND iface)
1058 ICOM_THIS(IDirectSound_IDirectSound,iface);
1059 ULONG ulReturn;
1060 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1061 ulReturn = InterlockedDecrement(&This->ref);
1062 if (ulReturn == 0) {
1063 IDirectSoundImpl_Release(This->pds);
1064 HeapFree(GetProcessHeap(),0,This);
1065 TRACE("(%p) released\n",This);
1067 return ulReturn;
1070 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1071 LPDIRECTSOUND iface,
1072 LPCDSBUFFERDESC dsbd,
1073 LPLPDIRECTSOUNDBUFFER ppdsb,
1074 LPUNKNOWN lpunk)
1076 ICOM_THIS(IDirectSound_IDirectSound,iface);
1077 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1078 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1081 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1082 LPDIRECTSOUND iface,
1083 LPDSCAPS lpDSCaps)
1085 ICOM_THIS(IDirectSound_IDirectSound,iface);
1086 TRACE("(%p,%p)\n",This,lpDSCaps);
1087 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1090 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1091 LPDIRECTSOUND iface,
1092 LPDIRECTSOUNDBUFFER psb,
1093 LPLPDIRECTSOUNDBUFFER ppdsb)
1095 ICOM_THIS(IDirectSound_IDirectSound,iface);
1096 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1097 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1100 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1101 LPDIRECTSOUND iface,
1102 HWND hwnd,
1103 DWORD level)
1105 ICOM_THIS(IDirectSound_IDirectSound,iface);
1106 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1107 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1110 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1111 LPDIRECTSOUND iface)
1113 ICOM_THIS(IDirectSound_IDirectSound,iface);
1114 TRACE("(%p)\n", This);
1115 return IDirectSoundImpl_Compact(This->pds);
1118 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1119 LPDIRECTSOUND iface,
1120 LPDWORD lpdwSpeakerConfig)
1122 ICOM_THIS(IDirectSound_IDirectSound,iface);
1123 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1124 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1127 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1128 LPDIRECTSOUND iface,
1129 DWORD config)
1131 ICOM_THIS(IDirectSound_IDirectSound,iface);
1132 TRACE("(%p,0x%08lx)\n",This,config);
1133 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1136 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1137 LPDIRECTSOUND iface,
1138 LPCGUID lpcGuid)
1140 ICOM_THIS(IDirectSound_IDirectSound,iface);
1141 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1142 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1145 static IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1147 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1148 IDirectSound_IDirectSound_QueryInterface,
1149 IDirectSound_IDirectSound_AddRef,
1150 IDirectSound_IDirectSound_Release,
1151 IDirectSound_IDirectSound_CreateSoundBuffer,
1152 IDirectSound_IDirectSound_GetCaps,
1153 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1154 IDirectSound_IDirectSound_SetCooperativeLevel,
1155 IDirectSound_IDirectSound_Compact,
1156 IDirectSound_IDirectSound_GetSpeakerConfig,
1157 IDirectSound_IDirectSound_SetSpeakerConfig,
1158 IDirectSound_IDirectSound_Initialize
1161 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1162 LPDIRECTSOUND8 pds,
1163 LPDIRECTSOUND * ppds)
1165 IDirectSound_IDirectSound * pdsds;
1166 TRACE("(%p,%p)\n",pds,ppds);
1168 if (ppds == NULL) {
1169 ERR("invalid parameter: ppds == NULL\n");
1170 return DSERR_INVALIDPARAM;
1173 if (pds == NULL) {
1174 ERR("invalid parameter: pds == NULL\n");
1175 *ppds = NULL;
1176 return DSERR_INVALIDPARAM;
1179 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1180 if (pdsds == NULL) {
1181 WARN("out of memory\n");
1182 *ppds = NULL;
1183 return DSERR_OUTOFMEMORY;
1186 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1187 pdsds->ref = 0;
1188 pdsds->pds = pds;
1190 IDirectSoundImpl_AddRef(pds);
1191 *ppds = (LPDIRECTSOUND)pdsds;
1193 return DS_OK;
1196 /*******************************************************************************
1197 * IDirectSound8_IUnknown
1199 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1200 LPUNKNOWN iface,
1201 REFIID riid,
1202 LPVOID * ppobj)
1204 ICOM_THIS(IDirectSound_IUnknown,iface);
1205 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1206 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1209 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1210 LPUNKNOWN iface)
1212 ICOM_THIS(IDirectSound_IUnknown,iface);
1213 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1214 return InterlockedIncrement(&This->ref);
1217 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1218 LPUNKNOWN iface)
1220 ICOM_THIS(IDirectSound_IUnknown,iface);
1221 ULONG ulReturn;
1222 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1223 ulReturn = InterlockedDecrement(&This->ref);
1224 if (ulReturn == 0) {
1225 IDirectSoundImpl_Release(This->pds);
1226 HeapFree(GetProcessHeap(),0,This);
1227 TRACE("(%p) released\n",This);
1229 return ulReturn;
1232 static IUnknownVtbl DirectSound8_Unknown_Vtbl =
1234 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1235 IDirectSound8_IUnknown_QueryInterface,
1236 IDirectSound8_IUnknown_AddRef,
1237 IDirectSound8_IUnknown_Release
1240 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1241 LPDIRECTSOUND8 pds,
1242 LPUNKNOWN * ppunk)
1244 IDirectSound8_IUnknown * pdsunk;
1245 TRACE("(%p,%p)\n",pds,ppunk);
1247 if (ppunk == NULL) {
1248 ERR("invalid parameter: ppunk == NULL\n");
1249 return DSERR_INVALIDPARAM;
1252 if (pds == NULL) {
1253 ERR("invalid parameter: pds == NULL\n");
1254 *ppunk = NULL;
1255 return DSERR_INVALIDPARAM;
1258 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1259 if (pdsunk == NULL) {
1260 WARN("out of memory\n");
1261 *ppunk = NULL;
1262 return DSERR_OUTOFMEMORY;
1265 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1266 pdsunk->ref = 0;
1267 pdsunk->pds = pds;
1269 IDirectSoundImpl_AddRef(pds);
1270 *ppunk = (LPUNKNOWN)pdsunk;
1272 return DS_OK;
1275 /*******************************************************************************
1276 * IDirectSound8_IDirectSound
1278 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1279 LPDIRECTSOUND iface,
1280 REFIID riid,
1281 LPVOID * ppobj)
1283 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1284 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1285 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1288 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1289 LPDIRECTSOUND iface)
1291 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1292 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1293 return InterlockedIncrement(&This->ref);
1296 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1297 LPDIRECTSOUND iface)
1299 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1300 ULONG ulReturn;
1301 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1302 ulReturn = InterlockedDecrement(&This->ref);
1303 if (ulReturn == 0) {
1304 IDirectSoundImpl_Release(This->pds);
1305 HeapFree(GetProcessHeap(),0,This);
1306 TRACE("(%p) released\n",This);
1308 return ulReturn;
1311 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1312 LPDIRECTSOUND iface,
1313 LPCDSBUFFERDESC dsbd,
1314 LPLPDIRECTSOUNDBUFFER ppdsb,
1315 LPUNKNOWN lpunk)
1317 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1318 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1319 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1322 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1323 LPDIRECTSOUND iface,
1324 LPDSCAPS lpDSCaps)
1326 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1327 TRACE("(%p,%p)\n",This,lpDSCaps);
1328 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1331 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1332 LPDIRECTSOUND iface,
1333 LPDIRECTSOUNDBUFFER psb,
1334 LPLPDIRECTSOUNDBUFFER ppdsb)
1336 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1337 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1338 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1341 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1342 LPDIRECTSOUND iface,
1343 HWND hwnd,
1344 DWORD level)
1346 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1347 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1348 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1351 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1352 LPDIRECTSOUND iface)
1354 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1355 TRACE("(%p)\n", This);
1356 return IDirectSoundImpl_Compact(This->pds);
1359 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1360 LPDIRECTSOUND iface,
1361 LPDWORD lpdwSpeakerConfig)
1363 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1364 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1365 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1368 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1369 LPDIRECTSOUND iface,
1370 DWORD config)
1372 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1373 TRACE("(%p,0x%08lx)\n",This,config);
1374 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1377 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1378 LPDIRECTSOUND iface,
1379 LPCGUID lpcGuid)
1381 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1382 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1383 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1386 static IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1388 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1389 IDirectSound8_IDirectSound_QueryInterface,
1390 IDirectSound8_IDirectSound_AddRef,
1391 IDirectSound8_IDirectSound_Release,
1392 IDirectSound8_IDirectSound_CreateSoundBuffer,
1393 IDirectSound8_IDirectSound_GetCaps,
1394 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1395 IDirectSound8_IDirectSound_SetCooperativeLevel,
1396 IDirectSound8_IDirectSound_Compact,
1397 IDirectSound8_IDirectSound_GetSpeakerConfig,
1398 IDirectSound8_IDirectSound_SetSpeakerConfig,
1399 IDirectSound8_IDirectSound_Initialize
1402 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1403 LPDIRECTSOUND8 pds,
1404 LPDIRECTSOUND * ppds)
1406 IDirectSound8_IDirectSound * pdsds;
1407 TRACE("(%p,%p)\n",pds,ppds);
1409 if (ppds == NULL) {
1410 ERR("invalid parameter: ppds == NULL\n");
1411 return DSERR_INVALIDPARAM;
1414 if (pds == NULL) {
1415 ERR("invalid parameter: pds == NULL\n");
1416 *ppds = NULL;
1417 return DSERR_INVALIDPARAM;
1420 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1421 if (pdsds == NULL) {
1422 WARN("out of memory\n");
1423 *ppds = NULL;
1424 return DSERR_OUTOFMEMORY;
1427 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1428 pdsds->ref = 0;
1429 pdsds->pds = pds;
1431 IDirectSoundImpl_AddRef(pds);
1432 *ppds = (LPDIRECTSOUND)pdsds;
1434 return DS_OK;
1437 /*******************************************************************************
1438 * IDirectSound8_IDirectSound8
1440 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1441 LPDIRECTSOUND8 iface,
1442 REFIID riid,
1443 LPVOID * ppobj)
1445 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1446 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1447 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1450 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1451 LPDIRECTSOUND8 iface)
1453 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1454 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1455 return InterlockedIncrement(&This->ref);
1458 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1459 LPDIRECTSOUND8 iface)
1461 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1462 ULONG ulReturn;
1463 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1464 ulReturn = InterlockedDecrement(&This->ref);
1465 if (ulReturn == 0) {
1466 IDirectSoundImpl_Release(This->pds);
1467 HeapFree(GetProcessHeap(),0,This);
1468 TRACE("(%p) released\n",This);
1470 return ulReturn;
1473 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1474 LPDIRECTSOUND8 iface,
1475 LPCDSBUFFERDESC dsbd,
1476 LPLPDIRECTSOUNDBUFFER ppdsb,
1477 LPUNKNOWN lpunk)
1479 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1480 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1481 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1484 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1485 LPDIRECTSOUND8 iface,
1486 LPDSCAPS lpDSCaps)
1488 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1489 TRACE("(%p,%p)\n",This,lpDSCaps);
1490 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1493 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1494 LPDIRECTSOUND8 iface,
1495 LPDIRECTSOUNDBUFFER psb,
1496 LPLPDIRECTSOUNDBUFFER ppdsb)
1498 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1499 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1500 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1503 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1504 LPDIRECTSOUND8 iface,
1505 HWND hwnd,
1506 DWORD level)
1508 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1509 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1510 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1513 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1514 LPDIRECTSOUND8 iface)
1516 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1517 TRACE("(%p)\n", This);
1518 return IDirectSoundImpl_Compact(This->pds);
1521 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1522 LPDIRECTSOUND8 iface,
1523 LPDWORD lpdwSpeakerConfig)
1525 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1526 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1527 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1530 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1531 LPDIRECTSOUND8 iface,
1532 DWORD config)
1534 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1535 TRACE("(%p,0x%08lx)\n",This,config);
1536 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1539 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1540 LPDIRECTSOUND8 iface,
1541 LPCGUID lpcGuid)
1543 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1544 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1545 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1548 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1549 LPDIRECTSOUND8 iface,
1550 LPDWORD pdwCertified)
1552 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1553 TRACE("(%p, %p)\n", This, pdwCertified);
1554 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1557 static IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1559 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1560 IDirectSound8_IDirectSound8_QueryInterface,
1561 IDirectSound8_IDirectSound8_AddRef,
1562 IDirectSound8_IDirectSound8_Release,
1563 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1564 IDirectSound8_IDirectSound8_GetCaps,
1565 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1566 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1567 IDirectSound8_IDirectSound8_Compact,
1568 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1569 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1570 IDirectSound8_IDirectSound8_Initialize,
1571 IDirectSound8_IDirectSound8_VerifyCertification
1574 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1575 LPDIRECTSOUND8 pds,
1576 LPDIRECTSOUND8 * ppds)
1578 IDirectSound8_IDirectSound8 * pdsds;
1579 TRACE("(%p,%p)\n",pds,ppds);
1581 if (ppds == NULL) {
1582 ERR("invalid parameter: ppds == NULL\n");
1583 return DSERR_INVALIDPARAM;
1586 if (pds == NULL) {
1587 ERR("invalid parameter: pds == NULL\n");
1588 *ppds = NULL;
1589 return DSERR_INVALIDPARAM;
1592 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1593 if (pdsds == NULL) {
1594 WARN("out of memory\n");
1595 *ppds = NULL;
1596 return DSERR_OUTOFMEMORY;
1599 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1600 pdsds->ref = 0;
1601 pdsds->pds = pds;
1603 IDirectSoundImpl_AddRef(pds);
1604 *ppds = (LPDIRECTSOUND8)pdsds;
1606 return DS_OK;
1609 HRESULT WINAPI DSOUND_Create(
1610 LPCGUID lpcGUID,
1611 LPDIRECTSOUND *ppDS,
1612 IUnknown *pUnkOuter)
1614 HRESULT hr;
1615 GUID devGuid;
1617 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1619 if (pUnkOuter != NULL) {
1620 WARN("invalid parameter: pUnkOuter != NULL\n");
1621 return DSERR_INVALIDPARAM;
1624 if (ppDS == NULL) {
1625 WARN("invalid parameter: ppDS == NULL\n");
1626 return DSERR_INVALIDPARAM;
1629 /* Get dsound configuration */
1630 setup_dsound_options();
1632 /* Default device? */
1633 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1634 lpcGUID = &DSDEVID_DefaultPlayback;
1636 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1637 WARN("invalid parameter: lpcGUID\n");
1638 *ppDS = NULL;
1639 return DSERR_INVALIDPARAM;
1642 if (dsound) {
1643 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1644 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1645 if (*ppDS)
1646 IDirectSound_IDirectSound_AddRef(*ppDS);
1647 else
1648 WARN("IDirectSound_IDirectSound_Create failed\n");
1649 } else {
1650 ERR("different dsound already opened (only support one sound card at a time now)\n");
1651 *ppDS = NULL;
1652 hr = DSERR_ALLOCATED;
1654 } else {
1655 LPDIRECTSOUND8 pDS;
1656 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1657 if (hr == DS_OK) {
1658 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1659 if (hr == DS_OK) {
1660 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1661 if (*ppDS) {
1662 IDirectSound_IDirectSound_AddRef(*ppDS);
1664 dsound = (IDirectSoundImpl*)pDS;
1665 timeBeginPeriod(DS_TIME_RES);
1666 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1667 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1668 } else {
1669 WARN("IDirectSound_IDirectSound_Create failed\n");
1670 IDirectSound8_Release(pDS);
1672 } else {
1673 WARN("DSOUND_PrimaryCreate failed\n");
1674 IDirectSound8_Release(pDS);
1676 } else
1677 WARN("IDirectSoundImpl_Create failed\n");
1680 return hr;
1683 /*******************************************************************************
1684 * DirectSoundCreate (DSOUND.1)
1686 * Creates and initializes a DirectSound interface.
1688 * PARAMS
1689 * lpcGUID [I] Address of the GUID that identifies the sound device.
1690 * ppDS [O] Address of a variable to receive the interface pointer.
1691 * pUnkOuter [I] Must be NULL.
1693 * RETURNS
1694 * Success: DS_OK
1695 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1696 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1698 HRESULT WINAPI DirectSoundCreate(
1699 LPCGUID lpcGUID,
1700 LPDIRECTSOUND *ppDS,
1701 IUnknown *pUnkOuter)
1703 HRESULT hr;
1705 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1707 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1708 if (hr == DS_OK)
1709 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1711 return hr;
1714 HRESULT WINAPI DSOUND_Create8(
1715 LPCGUID lpcGUID,
1716 LPDIRECTSOUND8 *ppDS,
1717 IUnknown *pUnkOuter)
1719 HRESULT hr;
1720 GUID devGuid;
1722 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1724 if (pUnkOuter != NULL) {
1725 WARN("invalid parameter: pUnkOuter != NULL\n");
1726 return DSERR_INVALIDPARAM;
1729 if (ppDS == NULL) {
1730 WARN("invalid parameter: ppDS == NULL\n");
1731 return DSERR_INVALIDPARAM;
1734 /* Get dsound configuration */
1735 setup_dsound_options();
1737 /* Default device? */
1738 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1739 lpcGUID = &DSDEVID_DefaultPlayback;
1741 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1742 WARN("invalid parameter: lpcGUID\n");
1743 *ppDS = NULL;
1744 return DSERR_INVALIDPARAM;
1747 if (dsound) {
1748 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1749 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1750 if (*ppDS)
1751 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1752 else
1753 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1754 } else {
1755 ERR("different dsound already opened (only support one sound card at a time now)\n");
1756 *ppDS = NULL;
1757 hr = DSERR_ALLOCATED;
1759 } else {
1760 LPDIRECTSOUND8 pDS;
1761 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1762 if (hr == DS_OK) {
1763 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1764 if (hr == DS_OK) {
1765 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1766 if (*ppDS) {
1767 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1769 dsound = (IDirectSoundImpl*)pDS;
1770 timeBeginPeriod(DS_TIME_RES);
1771 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1772 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1773 } else {
1774 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1775 IDirectSound8_Release(pDS);
1777 } else {
1778 WARN("DSOUND_PrimaryCreate failed\n");
1779 IDirectSound8_Release(pDS);
1781 } else
1782 WARN("IDirectSoundImpl_Create failed\n");
1785 return hr;
1788 /*******************************************************************************
1789 * DirectSoundCreate8 (DSOUND.11)
1791 * Creates and initializes a DirectSound8 interface.
1793 * PARAMS
1794 * lpcGUID [I] Address of the GUID that identifies the sound device.
1795 * ppDS [O] Address of a variable to receive the interface pointer.
1796 * pUnkOuter [I] Must be NULL.
1798 * RETURNS
1799 * Success: DS_OK
1800 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1801 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1803 HRESULT WINAPI DirectSoundCreate8(
1804 LPCGUID lpcGUID,
1805 LPDIRECTSOUND8 *ppDS,
1806 IUnknown *pUnkOuter)
1808 HRESULT hr;
1810 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1812 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1813 if (hr == DS_OK)
1814 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1816 return hr;