Added error checking to IDirectSound_Compact.
[wine/gsoc_dplay.git] / dlls / dsound / dsound.c
blob124f8fc1e8755c5f27fbb54e3596d00622dd3551
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 ICOM_THIS(IDirectSoundImpl,iface);
472 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
474 if (This == NULL) {
475 WARN("invalid parameter: This == NULL\n");
476 return DSERR_INVALIDPARAM;
479 if (This->initialized == FALSE) {
480 WARN("not initialized\n");
481 return DSERR_UNINITIALIZED;
484 if (psb == NULL) {
485 WARN("invalid parameter: psb == NULL\n");
486 return DSERR_INVALIDPARAM;
489 if (ppdsb == NULL) {
490 WARN("invalid parameter: ppdsb == NULL\n");
491 return DSERR_INVALIDPARAM;
494 /* FIXME: hack to make sure we have a secondary buffer */
495 if ((DWORD)((SecondaryBufferImpl *)psb)->dsb == (DWORD)This) {
496 WARN("trying to duplicate primary buffer\n");
497 *ppdsb = NULL;
498 return DSERR_INVALIDCALL;
501 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
503 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
505 if (dsb == NULL) {
506 WARN("out of memory\n");
507 *ppdsb = NULL;
508 return DSERR_OUTOFMEMORY;
511 memcpy(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
513 if (pdsb->hwbuf) {
514 TRACE("duplicating hardware buffer\n");
516 hres = IDsDriver_DuplicateSoundBuffer(This->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
517 if (hres != DS_OK) {
518 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
519 dsb->hwbuf = NULL;
520 /* allocate buffer */
521 if (This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
522 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
523 if (dsb->buffer == NULL) {
524 WARN("out of memory\n");
525 HeapFree(GetProcessHeap(),0,dsb);
526 *ppdsb = NULL;
527 return DSERR_OUTOFMEMORY;
530 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
531 if (dsb->buffer->memory == NULL) {
532 WARN("out of memory\n");
533 HeapFree(GetProcessHeap(),0,dsb->buffer);
534 HeapFree(GetProcessHeap(),0,dsb);
535 *ppdsb = NULL;
536 return DSERR_OUTOFMEMORY;
538 dsb->buffer->ref = 1;
540 /* FIXME: copy buffer ? */
543 } else {
544 dsb->hwbuf = NULL;
545 dsb->buffer->ref++;
548 dsb->ref = 0;
549 dsb->state = STATE_STOPPED;
550 dsb->playpos = 0;
551 dsb->buf_mixpos = 0;
552 dsb->dsound = This;
553 dsb->ds3db = NULL;
554 dsb->iks = NULL; /* FIXME? */
555 dsb->dsb = NULL;
556 memcpy(&(dsb->wfx), &(pdsb->wfx), sizeof(dsb->wfx));
557 InitializeCriticalSection(&(dsb->lock));
558 /* register buffer */
559 RtlAcquireResourceExclusive(&(This->lock), TRUE);
561 IDirectSoundBufferImpl **newbuffers;
562 if (This->buffers)
563 newbuffers = HeapReAlloc(GetProcessHeap(),0,This->buffers,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
564 else
565 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl**)*(This->nrofbuffers+1));
567 if (newbuffers) {
568 This->buffers = newbuffers;
569 This->buffers[This->nrofbuffers] = dsb;
570 This->nrofbuffers++;
571 TRACE("buffer count is now %d\n", This->nrofbuffers);
572 } else {
573 ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
574 IDirectSoundBuffer8_Release(psb);
575 DeleteCriticalSection(&(dsb->lock));
576 RtlReleaseResource(&(This->lock));
577 HeapFree(GetProcessHeap(),0,dsb);
578 *ppdsb = 0;
579 return DSERR_OUTOFMEMORY;
582 RtlReleaseResource(&(This->lock));
583 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
584 if (*ppdsb) {
585 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
586 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
587 } else
588 WARN("SecondaryBufferImpl_Create failed\n");
590 return hres;
593 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
594 LPDIRECTSOUND8 iface,
595 HWND hwnd,
596 DWORD level)
598 ICOM_THIS(IDirectSoundImpl,iface);
599 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
601 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
602 FIXME("level=%s not fully supported\n",
603 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
605 This->priolevel = level;
606 return DS_OK;
609 static HRESULT WINAPI IDirectSoundImpl_Compact(
610 LPDIRECTSOUND8 iface)
612 ICOM_THIS(IDirectSoundImpl,iface);
613 TRACE("(%p)\n",This);
615 if (This->initialized == FALSE) {
616 WARN("not initialized\n");
617 return DSERR_UNINITIALIZED;
620 if (This->priolevel != DSSCL_PRIORITY) {
621 WARN("incorrect priority level\n");
622 return DSERR_PRIOLEVELNEEDED;
625 return DS_OK;
628 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
629 LPDIRECTSOUND8 iface,
630 LPDWORD lpdwSpeakerConfig)
632 ICOM_THIS(IDirectSoundImpl,iface);
633 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
635 if (This->initialized == FALSE) {
636 WARN("not initialized\n");
637 return DSERR_UNINITIALIZED;
640 if (lpdwSpeakerConfig == NULL) {
641 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
642 return DSERR_INVALIDPARAM;
645 WARN("not fully functional\n");
646 *lpdwSpeakerConfig = This->speaker_config;
647 return DS_OK;
650 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
651 LPDIRECTSOUND8 iface,
652 DWORD config)
654 ICOM_THIS(IDirectSoundImpl,iface);
655 TRACE("(%p,0x%08lx)\n",This,config);
657 if (This->initialized == FALSE) {
658 WARN("not initialized\n");
659 return DSERR_UNINITIALIZED;
662 This->speaker_config = config;
663 WARN("not fully functional\n");
664 return DS_OK;
667 static HRESULT WINAPI IDirectSoundImpl_Initialize(
668 LPDIRECTSOUND8 iface,
669 LPCGUID lpcGuid)
671 ICOM_THIS(IDirectSoundImpl,iface);
672 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGuid));
674 This->initialized = TRUE;
676 return DS_OK;
679 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
680 LPDIRECTSOUND8 iface,
681 LPDWORD pdwCertified)
683 ICOM_THIS(IDirectSoundImpl,iface);
684 TRACE("(%p, %p)\n",This,pdwCertified);
686 if (This->initialized == FALSE) {
687 WARN("not initialized\n");
688 return DSERR_UNINITIALIZED;
691 if (This->drvcaps.dwFlags & DSCAPS_CERTIFIED)
692 *pdwCertified = DS_CERTIFIED;
693 else
694 *pdwCertified = DS_UNCERTIFIED;
695 return DS_OK;
698 static ICOM_VTABLE(IDirectSound8) IDirectSoundImpl_Vtbl =
700 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
701 IDirectSoundImpl_QueryInterface,
702 IDirectSoundImpl_AddRef,
703 IDirectSoundImpl_Release,
704 IDirectSoundImpl_CreateSoundBuffer,
705 IDirectSoundImpl_GetCaps,
706 IDirectSoundImpl_DuplicateSoundBuffer,
707 IDirectSoundImpl_SetCooperativeLevel,
708 IDirectSoundImpl_Compact,
709 IDirectSoundImpl_GetSpeakerConfig,
710 IDirectSoundImpl_SetSpeakerConfig,
711 IDirectSoundImpl_Initialize,
712 IDirectSoundImpl_VerifyCertification
715 HRESULT WINAPI IDirectSoundImpl_Create(
716 LPCGUID lpcGUID,
717 LPDIRECTSOUND8 * ppDS)
719 HRESULT err = DSERR_INVALIDPARAM;
720 PIDSDRIVER drv = NULL;
721 IDirectSoundImpl* pDS;
722 unsigned wod, wodn;
723 BOOLEAN found = FALSE;
724 TRACE("(%s,%p)\n",debugstr_guid(lpcGUID),ppDS);
726 /* Enumerate WINMM audio devices and find the one we want */
727 wodn = waveOutGetNumDevs();
728 if (!wodn) {
729 WARN("no driver\n");
730 *ppDS = NULL;
731 return DSERR_NODRIVER;
734 TRACE(" expecting GUID %s.\n", debugstr_guid(lpcGUID));
736 for (wod=0; wod<wodn; wod++) {
737 GUID guid;
738 err = mmErr(waveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
739 if (err != DS_OK) {
740 WARN("waveOutMessage failed; err=%lx\n",err);
741 *ppDS = NULL;
742 return err;
744 TRACE("got GUID %s for wod %d.\n", debugstr_guid(&guid), wod);
745 if (IsEqualGUID( lpcGUID, &guid)) {
746 err = DS_OK;
747 found = TRUE;
748 break;
752 if (err != DS_OK) {
753 WARN("invalid parameter\n");
754 *ppDS = NULL;
755 return DSERR_INVALIDPARAM;
758 if (found == FALSE) {
759 WARN("No device found matching given ID!\n");
760 return DSERR_NODRIVER;
763 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
764 waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD)&drv, 0);
766 /* Disable the direct sound driver to force emulation if requested. */
767 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
768 drv = NULL;
770 /* Allocate memory */
771 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
772 if (ppDS == NULL) {
773 WARN("out of memory\n");
774 *ppDS = NULL;
775 return DSERR_OUTOFMEMORY;
778 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
779 pDS->ref = 0;
781 pDS->driver = drv;
782 pDS->priolevel = DSSCL_NORMAL;
783 pDS->fraglen = 0;
784 pDS->hwbuf = NULL;
785 pDS->buffer = NULL;
786 pDS->buflen = 0;
787 pDS->writelead = 0;
788 pDS->state = STATE_STOPPED;
789 pDS->nrofbuffers = 0;
790 pDS->buffers = NULL;
791 pDS->primary = NULL;
792 pDS->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
793 pDS->initialized = FALSE;
795 /* 3D listener initial parameters */
796 pDS->listener = NULL;
797 pDS->ds3dl.dwSize = sizeof(DS3DLISTENER);
798 pDS->ds3dl.vPosition.x = 0.0;
799 pDS->ds3dl.vPosition.y = 0.0;
800 pDS->ds3dl.vPosition.z = 0.0;
801 pDS->ds3dl.vVelocity.x = 0.0;
802 pDS->ds3dl.vVelocity.y = 0.0;
803 pDS->ds3dl.vVelocity.z = 0.0;
804 pDS->ds3dl.vOrientFront.x = 0.0;
805 pDS->ds3dl.vOrientFront.y = 0.0;
806 pDS->ds3dl.vOrientFront.z = 1.0;
807 pDS->ds3dl.vOrientTop.x = 0.0;
808 pDS->ds3dl.vOrientTop.y = 1.0;
809 pDS->ds3dl.vOrientTop.z = 0.0;
810 pDS->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
811 pDS->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
812 pDS->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
814 pDS->prebuf = ds_snd_queue_max;
815 pDS->guid = *lpcGUID;
817 /* Get driver description */
818 if (drv) {
819 err = IDsDriver_GetDriverDesc(drv,&(pDS->drvdesc));
820 if (err != DS_OK) {
821 WARN("IDsDriver_GetDriverDesc failed\n");
822 HeapFree(GetProcessHeap(),0,pDS);
823 *ppDS = NULL;
824 return err;
826 } else {
827 /* if no DirectSound interface available, use WINMM API instead */
828 pDS->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
831 pDS->drvdesc.dnDevNode = wod;
833 /* Set default wave format (may need it for waveOutOpen) */
834 pDS->wfx.wFormatTag = WAVE_FORMAT_PCM;
835 /* We rely on the sound driver to return the actual sound format of
836 * the device if it does not support 22050x8x2 and is given the
837 * WAVE_DIRECTSOUND flag.
839 pDS->wfx.nSamplesPerSec = 22050;
840 pDS->wfx.wBitsPerSample = 8;
841 pDS->wfx.nChannels = 2;
842 pDS->wfx.nBlockAlign = pDS->wfx.wBitsPerSample * pDS->wfx.nChannels / 8;
843 pDS->wfx.nAvgBytesPerSec = pDS->wfx.nSamplesPerSec * pDS->wfx.nBlockAlign;
844 pDS->wfx.cbSize = 0;
846 /* If the driver requests being opened through MMSYSTEM
847 * (which is recommended by the DDK), it is supposed to happen
848 * before the DirectSound interface is opened */
849 if (pDS->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
851 DWORD flags = CALLBACK_FUNCTION;
853 /* disable direct sound if requested */
854 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
855 flags |= WAVE_DIRECTSOUND;
857 err = mmErr(waveOutOpen(&(pDS->hwo),
858 pDS->drvdesc.dnDevNode, &(pDS->wfx),
859 (DWORD)DSOUND_callback, (DWORD)pDS,
860 flags));
861 if (err != DS_OK) {
862 WARN("waveOutOpen failed\n");
863 HeapFree(GetProcessHeap(),0,pDS);
864 *ppDS = NULL;
865 return err;
869 if (drv) {
870 err = IDsDriver_Open(drv);
871 if (err != DS_OK) {
872 WARN("IDsDriver_Open failed\n");
873 HeapFree(GetProcessHeap(),0,pDS);
874 *ppDS = NULL;
875 return err;
878 /* the driver is now open, so it's now allowed to call GetCaps */
879 err = IDsDriver_GetCaps(drv,&(pDS->drvcaps));
880 if (err != DS_OK) {
881 WARN("IDsDriver_GetCaps failed\n");
882 HeapFree(GetProcessHeap(),0,pDS);
883 *ppDS = NULL;
884 return err;
886 } else {
887 WAVEOUTCAPSA woc;
888 err = mmErr(waveOutGetDevCapsA(pDS->drvdesc.dnDevNode, &woc, sizeof(woc)));
889 if (err != DS_OK) {
890 WARN("waveOutGetDevCaps failed\n");
891 HeapFree(GetProcessHeap(),0,pDS);
892 *ppDS = NULL;
893 return err;
895 ZeroMemory(&pDS->drvcaps, sizeof(pDS->drvcaps));
896 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
897 (woc.dwFormats & WAVE_FORMAT_2M08) ||
898 (woc.dwFormats & WAVE_FORMAT_4M08) ||
899 (woc.dwFormats & WAVE_FORMAT_48M08) ||
900 (woc.dwFormats & WAVE_FORMAT_96M08)) {
901 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
902 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
904 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
905 (woc.dwFormats & WAVE_FORMAT_2M16) ||
906 (woc.dwFormats & WAVE_FORMAT_4M16) ||
907 (woc.dwFormats & WAVE_FORMAT_48M16) ||
908 (woc.dwFormats & WAVE_FORMAT_96M16)) {
909 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
910 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
912 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
913 (woc.dwFormats & WAVE_FORMAT_2S08) ||
914 (woc.dwFormats & WAVE_FORMAT_4S08) ||
915 (woc.dwFormats & WAVE_FORMAT_48S08) ||
916 (woc.dwFormats & WAVE_FORMAT_96S08)) {
917 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
918 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
920 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
921 (woc.dwFormats & WAVE_FORMAT_2S16) ||
922 (woc.dwFormats & WAVE_FORMAT_4S16) ||
923 (woc.dwFormats & WAVE_FORMAT_48S16) ||
924 (woc.dwFormats & WAVE_FORMAT_96S16)) {
925 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
926 pDS->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
928 if (ds_emuldriver)
929 pDS->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
930 pDS->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
931 pDS->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
932 pDS->drvcaps.dwPrimaryBuffers = 1;
935 InitializeCriticalSection(&(pDS->mixlock));
936 RtlInitializeResource(&(pDS->lock));
938 *ppDS = (LPDIRECTSOUND8)pDS;
940 return DS_OK;
942 /*******************************************************************************
943 * IDirectSound_IUnknown
945 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
946 LPUNKNOWN iface,
947 REFIID riid,
948 LPVOID * ppobj)
950 ICOM_THIS(IDirectSound_IUnknown,iface);
951 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
952 return DSOUND_QueryInterface(This->pds, riid, ppobj);
955 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
956 LPUNKNOWN iface)
958 ICOM_THIS(IDirectSound_IUnknown,iface);
959 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
960 return InterlockedIncrement(&This->ref);
963 static ULONG WINAPI IDirectSound_IUnknown_Release(
964 LPUNKNOWN iface)
966 ICOM_THIS(IDirectSound_IUnknown,iface);
967 ULONG ulReturn;
968 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
969 ulReturn = InterlockedDecrement(&This->ref);
970 if (ulReturn == 0) {
971 IDirectSoundImpl_Release(This->pds);
972 HeapFree(GetProcessHeap(),0,This);
973 TRACE("(%p) released\n",This);
975 return ulReturn;
978 static ICOM_VTABLE(IUnknown) DirectSound_Unknown_Vtbl =
980 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
981 IDirectSound_IUnknown_QueryInterface,
982 IDirectSound_IUnknown_AddRef,
983 IDirectSound_IUnknown_Release
986 HRESULT WINAPI IDirectSound_IUnknown_Create(
987 LPDIRECTSOUND8 pds,
988 LPUNKNOWN * ppunk)
990 IDirectSound_IUnknown * pdsunk;
991 TRACE("(%p,%p)\n",pds,ppunk);
993 if (ppunk == NULL) {
994 ERR("invalid parameter: ppunk == NULL\n");
995 return DSERR_INVALIDPARAM;
998 if (pds == NULL) {
999 ERR("invalid parameter: pds == NULL\n");
1000 *ppunk = NULL;
1001 return DSERR_INVALIDPARAM;
1004 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1005 if (pdsunk == NULL) {
1006 WARN("out of memory\n");
1007 *ppunk = NULL;
1008 return DSERR_OUTOFMEMORY;
1011 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1012 pdsunk->ref = 0;
1013 pdsunk->pds = pds;
1015 IDirectSoundImpl_AddRef(pds);
1016 *ppunk = (LPUNKNOWN)pdsunk;
1018 return DS_OK;
1021 /*******************************************************************************
1022 * IDirectSound_IDirectSound
1024 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1025 LPDIRECTSOUND iface,
1026 REFIID riid,
1027 LPVOID * ppobj)
1029 ICOM_THIS(IDirectSound_IDirectSound,iface);
1030 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1031 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1034 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1035 LPDIRECTSOUND iface)
1037 ICOM_THIS(IDirectSound_IDirectSound,iface);
1038 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1039 return InterlockedIncrement(&This->ref);
1042 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1043 LPDIRECTSOUND iface)
1045 ICOM_THIS(IDirectSound_IDirectSound,iface);
1046 ULONG ulReturn;
1047 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1048 ulReturn = InterlockedDecrement(&This->ref);
1049 if (ulReturn == 0) {
1050 IDirectSoundImpl_Release(This->pds);
1051 HeapFree(GetProcessHeap(),0,This);
1052 TRACE("(%p) released\n",This);
1054 return ulReturn;
1057 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1058 LPDIRECTSOUND iface,
1059 LPCDSBUFFERDESC dsbd,
1060 LPLPDIRECTSOUNDBUFFER ppdsb,
1061 LPUNKNOWN lpunk)
1063 ICOM_THIS(IDirectSound_IDirectSound,iface);
1064 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1065 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1068 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1069 LPDIRECTSOUND iface,
1070 LPDSCAPS lpDSCaps)
1072 ICOM_THIS(IDirectSound_IDirectSound,iface);
1073 TRACE("(%p,%p)\n",This,lpDSCaps);
1074 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1077 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1078 LPDIRECTSOUND iface,
1079 LPDIRECTSOUNDBUFFER psb,
1080 LPLPDIRECTSOUNDBUFFER ppdsb)
1082 ICOM_THIS(IDirectSound_IDirectSound,iface);
1083 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1084 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1087 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1088 LPDIRECTSOUND iface,
1089 HWND hwnd,
1090 DWORD level)
1092 ICOM_THIS(IDirectSound_IDirectSound,iface);
1093 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1094 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1097 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1098 LPDIRECTSOUND iface)
1100 ICOM_THIS(IDirectSound_IDirectSound,iface);
1101 TRACE("(%p)\n", This);
1102 return IDirectSoundImpl_Compact(This->pds);
1105 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1106 LPDIRECTSOUND iface,
1107 LPDWORD lpdwSpeakerConfig)
1109 ICOM_THIS(IDirectSound_IDirectSound,iface);
1110 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1111 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1114 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1115 LPDIRECTSOUND iface,
1116 DWORD config)
1118 ICOM_THIS(IDirectSound_IDirectSound,iface);
1119 TRACE("(%p,0x%08lx)\n",This,config);
1120 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1123 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1124 LPDIRECTSOUND iface,
1125 LPCGUID lpcGuid)
1127 ICOM_THIS(IDirectSound_IDirectSound,iface);
1128 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1129 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1132 static ICOM_VTABLE(IDirectSound) DirectSound_DirectSound_Vtbl =
1134 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1135 IDirectSound_IDirectSound_QueryInterface,
1136 IDirectSound_IDirectSound_AddRef,
1137 IDirectSound_IDirectSound_Release,
1138 IDirectSound_IDirectSound_CreateSoundBuffer,
1139 IDirectSound_IDirectSound_GetCaps,
1140 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1141 IDirectSound_IDirectSound_SetCooperativeLevel,
1142 IDirectSound_IDirectSound_Compact,
1143 IDirectSound_IDirectSound_GetSpeakerConfig,
1144 IDirectSound_IDirectSound_SetSpeakerConfig,
1145 IDirectSound_IDirectSound_Initialize
1148 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1149 LPDIRECTSOUND8 pds,
1150 LPDIRECTSOUND * ppds)
1152 IDirectSound_IDirectSound * pdsds;
1153 TRACE("(%p,%p)\n",pds,ppds);
1155 if (ppds == NULL) {
1156 ERR("invalid parameter: ppds == NULL\n");
1157 return DSERR_INVALIDPARAM;
1160 if (pds == NULL) {
1161 ERR("invalid parameter: pds == NULL\n");
1162 *ppds = NULL;
1163 return DSERR_INVALIDPARAM;
1166 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1167 if (pdsds == NULL) {
1168 WARN("out of memory\n");
1169 *ppds = NULL;
1170 return DSERR_OUTOFMEMORY;
1173 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1174 pdsds->ref = 0;
1175 pdsds->pds = pds;
1177 IDirectSoundImpl_AddRef(pds);
1178 *ppds = (LPDIRECTSOUND)pdsds;
1180 return DS_OK;
1183 /*******************************************************************************
1184 * IDirectSound8_IUnknown
1186 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1187 LPUNKNOWN iface,
1188 REFIID riid,
1189 LPVOID * ppobj)
1191 ICOM_THIS(IDirectSound_IUnknown,iface);
1192 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1193 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1196 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1197 LPUNKNOWN iface)
1199 ICOM_THIS(IDirectSound_IUnknown,iface);
1200 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1201 return InterlockedIncrement(&This->ref);
1204 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1205 LPUNKNOWN iface)
1207 ICOM_THIS(IDirectSound_IUnknown,iface);
1208 ULONG ulReturn;
1209 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1210 ulReturn = InterlockedDecrement(&This->ref);
1211 if (ulReturn == 0) {
1212 IDirectSoundImpl_Release(This->pds);
1213 HeapFree(GetProcessHeap(),0,This);
1214 TRACE("(%p) released\n",This);
1216 return ulReturn;
1219 static ICOM_VTABLE(IUnknown) DirectSound8_Unknown_Vtbl =
1221 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1222 IDirectSound8_IUnknown_QueryInterface,
1223 IDirectSound8_IUnknown_AddRef,
1224 IDirectSound8_IUnknown_Release
1227 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1228 LPDIRECTSOUND8 pds,
1229 LPUNKNOWN * ppunk)
1231 IDirectSound8_IUnknown * pdsunk;
1232 TRACE("(%p,%p)\n",pds,ppunk);
1234 if (ppunk == NULL) {
1235 ERR("invalid parameter: ppunk == NULL\n");
1236 return DSERR_INVALIDPARAM;
1239 if (pds == NULL) {
1240 ERR("invalid parameter: pds == NULL\n");
1241 *ppunk = NULL;
1242 return DSERR_INVALIDPARAM;
1245 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1246 if (pdsunk == NULL) {
1247 WARN("out of memory\n");
1248 *ppunk = NULL;
1249 return DSERR_OUTOFMEMORY;
1252 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1253 pdsunk->ref = 0;
1254 pdsunk->pds = pds;
1256 IDirectSoundImpl_AddRef(pds);
1257 *ppunk = (LPUNKNOWN)pdsunk;
1259 return DS_OK;
1262 /*******************************************************************************
1263 * IDirectSound8_IDirectSound
1265 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1266 LPDIRECTSOUND iface,
1267 REFIID riid,
1268 LPVOID * ppobj)
1270 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1271 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1272 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1275 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1276 LPDIRECTSOUND iface)
1278 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1279 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1280 return InterlockedIncrement(&This->ref);
1283 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1284 LPDIRECTSOUND iface)
1286 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1287 ULONG ulReturn;
1288 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1289 ulReturn = InterlockedDecrement(&This->ref);
1290 if (ulReturn == 0) {
1291 IDirectSoundImpl_Release(This->pds);
1292 HeapFree(GetProcessHeap(),0,This);
1293 TRACE("(%p) released\n",This);
1295 return ulReturn;
1298 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1299 LPDIRECTSOUND iface,
1300 LPCDSBUFFERDESC dsbd,
1301 LPLPDIRECTSOUNDBUFFER ppdsb,
1302 LPUNKNOWN lpunk)
1304 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1305 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1306 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1309 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1310 LPDIRECTSOUND iface,
1311 LPDSCAPS lpDSCaps)
1313 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1314 TRACE("(%p,%p)\n",This,lpDSCaps);
1315 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1318 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1319 LPDIRECTSOUND iface,
1320 LPDIRECTSOUNDBUFFER psb,
1321 LPLPDIRECTSOUNDBUFFER ppdsb)
1323 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1324 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1325 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1328 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1329 LPDIRECTSOUND iface,
1330 HWND hwnd,
1331 DWORD level)
1333 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1334 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1335 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1338 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1339 LPDIRECTSOUND iface)
1341 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1342 TRACE("(%p)\n", This);
1343 return IDirectSoundImpl_Compact(This->pds);
1346 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1347 LPDIRECTSOUND iface,
1348 LPDWORD lpdwSpeakerConfig)
1350 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1351 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1352 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1355 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1356 LPDIRECTSOUND iface,
1357 DWORD config)
1359 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1360 TRACE("(%p,0x%08lx)\n",This,config);
1361 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1364 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1365 LPDIRECTSOUND iface,
1366 LPCGUID lpcGuid)
1368 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1369 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1370 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1373 static ICOM_VTABLE(IDirectSound) DirectSound8_DirectSound_Vtbl =
1375 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1376 IDirectSound8_IDirectSound_QueryInterface,
1377 IDirectSound8_IDirectSound_AddRef,
1378 IDirectSound8_IDirectSound_Release,
1379 IDirectSound8_IDirectSound_CreateSoundBuffer,
1380 IDirectSound8_IDirectSound_GetCaps,
1381 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1382 IDirectSound8_IDirectSound_SetCooperativeLevel,
1383 IDirectSound8_IDirectSound_Compact,
1384 IDirectSound8_IDirectSound_GetSpeakerConfig,
1385 IDirectSound8_IDirectSound_SetSpeakerConfig,
1386 IDirectSound8_IDirectSound_Initialize
1389 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1390 LPDIRECTSOUND8 pds,
1391 LPDIRECTSOUND * ppds)
1393 IDirectSound8_IDirectSound * pdsds;
1394 TRACE("(%p,%p)\n",pds,ppds);
1396 if (ppds == NULL) {
1397 ERR("invalid parameter: ppds == NULL\n");
1398 return DSERR_INVALIDPARAM;
1401 if (pds == NULL) {
1402 ERR("invalid parameter: pds == NULL\n");
1403 *ppds = NULL;
1404 return DSERR_INVALIDPARAM;
1407 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1408 if (pdsds == NULL) {
1409 WARN("out of memory\n");
1410 *ppds = NULL;
1411 return DSERR_OUTOFMEMORY;
1414 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1415 pdsds->ref = 0;
1416 pdsds->pds = pds;
1418 IDirectSoundImpl_AddRef(pds);
1419 *ppds = (LPDIRECTSOUND)pdsds;
1421 return DS_OK;
1424 /*******************************************************************************
1425 * IDirectSound8_IDirectSound8
1427 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1428 LPDIRECTSOUND8 iface,
1429 REFIID riid,
1430 LPVOID * ppobj)
1432 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1433 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1434 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1437 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1438 LPDIRECTSOUND8 iface)
1440 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1441 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1442 return InterlockedIncrement(&This->ref);
1445 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1446 LPDIRECTSOUND8 iface)
1448 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1449 ULONG ulReturn;
1450 TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
1451 ulReturn = InterlockedDecrement(&This->ref);
1452 if (ulReturn == 0) {
1453 IDirectSoundImpl_Release(This->pds);
1454 HeapFree(GetProcessHeap(),0,This);
1455 TRACE("(%p) released\n",This);
1457 return ulReturn;
1460 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1461 LPDIRECTSOUND8 iface,
1462 LPCDSBUFFERDESC dsbd,
1463 LPLPDIRECTSOUNDBUFFER ppdsb,
1464 LPUNKNOWN lpunk)
1466 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1467 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1468 return IDirectSoundImpl_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk);
1471 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1472 LPDIRECTSOUND8 iface,
1473 LPDSCAPS lpDSCaps)
1475 ICOM_THIS(IDirectSound8_IDirectSound,iface);
1476 TRACE("(%p,%p)\n",This,lpDSCaps);
1477 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1480 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1481 LPDIRECTSOUND8 iface,
1482 LPDIRECTSOUNDBUFFER psb,
1483 LPLPDIRECTSOUNDBUFFER ppdsb)
1485 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1486 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1487 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1490 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1491 LPDIRECTSOUND8 iface,
1492 HWND hwnd,
1493 DWORD level)
1495 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1496 TRACE("(%p,%08lx,%s)\n",This,(DWORD)hwnd,dumpCooperativeLevel(level));
1497 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1500 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1501 LPDIRECTSOUND8 iface)
1503 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1504 TRACE("(%p)\n", This);
1505 return IDirectSoundImpl_Compact(This->pds);
1508 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1509 LPDIRECTSOUND8 iface,
1510 LPDWORD lpdwSpeakerConfig)
1512 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1513 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1514 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1517 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1518 LPDIRECTSOUND8 iface,
1519 DWORD config)
1521 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1522 TRACE("(%p,0x%08lx)\n",This,config);
1523 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1526 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1527 LPDIRECTSOUND8 iface,
1528 LPCGUID lpcGuid)
1530 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1531 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1532 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1535 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1536 LPDIRECTSOUND8 iface,
1537 LPDWORD pdwCertified)
1539 ICOM_THIS(IDirectSound8_IDirectSound8,iface);
1540 TRACE("(%p, %p)\n", This, pdwCertified);
1541 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1544 static ICOM_VTABLE(IDirectSound8) DirectSound8_DirectSound8_Vtbl =
1546 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1547 IDirectSound8_IDirectSound8_QueryInterface,
1548 IDirectSound8_IDirectSound8_AddRef,
1549 IDirectSound8_IDirectSound8_Release,
1550 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1551 IDirectSound8_IDirectSound8_GetCaps,
1552 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1553 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1554 IDirectSound8_IDirectSound8_Compact,
1555 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1556 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1557 IDirectSound8_IDirectSound8_Initialize,
1558 IDirectSound8_IDirectSound8_VerifyCertification
1561 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1562 LPDIRECTSOUND8 pds,
1563 LPDIRECTSOUND8 * ppds)
1565 IDirectSound8_IDirectSound8 * pdsds;
1566 TRACE("(%p,%p)\n",pds,ppds);
1568 if (ppds == NULL) {
1569 ERR("invalid parameter: ppds == NULL\n");
1570 return DSERR_INVALIDPARAM;
1573 if (pds == NULL) {
1574 ERR("invalid parameter: pds == NULL\n");
1575 *ppds = NULL;
1576 return DSERR_INVALIDPARAM;
1579 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1580 if (pdsds == NULL) {
1581 WARN("out of memory\n");
1582 *ppds = NULL;
1583 return DSERR_OUTOFMEMORY;
1586 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1587 pdsds->ref = 0;
1588 pdsds->pds = pds;
1590 IDirectSoundImpl_AddRef(pds);
1591 *ppds = (LPDIRECTSOUND8)pdsds;
1593 return DS_OK;
1596 HRESULT WINAPI DSOUND_Create(
1597 LPCGUID lpcGUID,
1598 LPDIRECTSOUND *ppDS,
1599 IUnknown *pUnkOuter)
1601 HRESULT hr;
1602 GUID devGuid;
1604 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1606 if (pUnkOuter != NULL) {
1607 WARN("invalid parameter: pUnkOuter != NULL\n");
1608 return DSERR_INVALIDPARAM;
1611 if (ppDS == NULL) {
1612 WARN("invalid parameter: ppDS == NULL\n");
1613 return DSERR_INVALIDPARAM;
1616 /* Get dsound configuration */
1617 setup_dsound_options();
1619 /* Default device? */
1620 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1621 lpcGUID = &DSDEVID_DefaultPlayback;
1623 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1624 WARN("invalid parameter: lpcGUID\n");
1625 *ppDS = NULL;
1626 return DSERR_INVALIDPARAM;
1629 if (dsound) {
1630 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1631 hr = IDirectSound_IDirectSound_Create((LPDIRECTSOUND8)dsound, ppDS);
1632 if (*ppDS)
1633 IDirectSound_IDirectSound_AddRef(*ppDS);
1634 else
1635 WARN("IDirectSound_IDirectSound_Create failed\n");
1636 } else {
1637 ERR("different dsound already opened (only support one sound card at a time now)\n");
1638 *ppDS = NULL;
1639 hr = DSERR_ALLOCATED;
1641 } else {
1642 LPDIRECTSOUND8 pDS;
1643 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1644 if (pDS) {
1645 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1646 if (hr == DS_OK) {
1647 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1648 if (*ppDS) {
1649 IDirectSound_IDirectSound_AddRef(*ppDS);
1651 dsound = (IDirectSoundImpl*)pDS;
1652 timeBeginPeriod(DS_TIME_RES);
1653 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1654 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1655 } else {
1656 WARN("IDirectSound_IDirectSound_Create failed\n");
1657 IDirectSound8_Release(pDS);
1659 } else {
1660 WARN("DSOUND_PrimaryCreate failed\n");
1661 IDirectSound8_Release(pDS);
1663 } else
1664 WARN("IDirectSoundImpl_Create failed\n");
1667 return hr;
1670 /*******************************************************************************
1671 * DirectSoundCreate (DSOUND.1)
1673 * Creates and initializes a DirectSound interface.
1675 * PARAMS
1676 * lpcGUID [I] Address of the GUID that identifies the sound device.
1677 * ppDS [O] Address of a variable to receive the interface pointer.
1678 * pUnkOuter [I] Must be NULL.
1680 * RETURNS
1681 * Success: DS_OK
1682 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1683 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1685 HRESULT WINAPI DirectSoundCreate(
1686 LPCGUID lpcGUID,
1687 LPDIRECTSOUND *ppDS,
1688 IUnknown *pUnkOuter)
1690 HRESULT hr;
1692 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1694 hr = DSOUND_Create(lpcGUID, ppDS, pUnkOuter);
1695 if (hr == DS_OK)
1696 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1698 return hr;
1701 HRESULT WINAPI DSOUND_Create8(
1702 LPCGUID lpcGUID,
1703 LPDIRECTSOUND8 *ppDS,
1704 IUnknown *pUnkOuter)
1706 HRESULT hr;
1707 GUID devGuid;
1709 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1711 if (pUnkOuter != NULL) {
1712 WARN("invalid parameter: pUnkOuter != NULL\n");
1713 return DSERR_INVALIDPARAM;
1716 if (ppDS == NULL) {
1717 WARN("invalid parameter: ppDS == NULL\n");
1718 return DSERR_INVALIDPARAM;
1721 /* Get dsound configuration */
1722 setup_dsound_options();
1724 /* Default device? */
1725 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
1726 lpcGUID = &DSDEVID_DefaultPlayback;
1728 if (GetDeviceID(lpcGUID, &devGuid) != DS_OK) {
1729 WARN("invalid parameter: lpcGUID\n");
1730 *ppDS = NULL;
1731 return DSERR_INVALIDPARAM;
1734 if (dsound) {
1735 if (IsEqualGUID(&devGuid, &dsound->guid)) {
1736 hr = IDirectSound8_IDirectSound8_Create((LPDIRECTSOUND8)dsound, ppDS);
1737 if (*ppDS)
1738 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1739 else
1740 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1741 } else {
1742 ERR("different dsound already opened (only support one sound card at a time now)\n");
1743 *ppDS = NULL;
1744 hr = DSERR_ALLOCATED;
1746 } else {
1747 LPDIRECTSOUND8 pDS;
1748 hr = IDirectSoundImpl_Create(&devGuid, &pDS);
1749 if (pDS) {
1750 hr = DSOUND_PrimaryCreate((IDirectSoundImpl*)pDS);
1751 if (hr == DS_OK) {
1752 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1753 if (*ppDS) {
1754 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1756 dsound = (IDirectSoundImpl*)pDS;
1757 timeBeginPeriod(DS_TIME_RES);
1758 dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
1759 (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
1760 } else {
1761 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1762 IDirectSound8_Release(pDS);
1764 } else {
1765 WARN("DSOUND_PrimaryCreate failed\n");
1766 IDirectSound8_Release(pDS);
1768 } else
1769 WARN("IDirectSoundImpl_Create failed\n");
1772 return hr;
1775 /*******************************************************************************
1776 * DirectSoundCreate8 (DSOUND.11)
1778 * Creates and initializes a DirectSound8 interface.
1780 * PARAMS
1781 * lpcGUID [I] Address of the GUID that identifies the sound device.
1782 * ppDS [O] Address of a variable to receive the interface pointer.
1783 * pUnkOuter [I] Must be NULL.
1785 * RETURNS
1786 * Success: DS_OK
1787 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1788 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1790 HRESULT WINAPI DirectSoundCreate8(
1791 LPCGUID lpcGUID,
1792 LPDIRECTSOUND8 *ppDS,
1793 IUnknown *pUnkOuter)
1795 HRESULT hr;
1797 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1799 hr = DSOUND_Create8(lpcGUID, ppDS, pUnkOuter);
1800 if (hr == DS_OK)
1801 IDirectSoundImpl_Initialize((LPDIRECTSOUND8)dsound, lpcGUID);
1803 return hr;