Merge from branch ReactX to Trunk,
[reactos.git] / reactos / dll / directx / dsound / dsound.c
1 /* DirectSound
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
6 * Copyright 2004 Robert Reif
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "mmsystem.h"
32 #include "winternl.h"
33 #include "mmddk.h"
34 #include "wine/debug.h"
35 #include "dsound.h"
36 #include "dsdriver.h"
37 #include "dsound_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
40
41 static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface);
42 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface);
43 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface);
44 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface);
45 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface);
46
47 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice);
48 static ULONG DirectSoundDevice_Release(DirectSoundDevice * device);
49
50 static const char * dumpCooperativeLevel(DWORD level)
51 {
52 static char unknown[32];
53 #define LE(x) case x: return #x
54 switch (level) {
55 LE(DSSCL_NORMAL);
56 LE(DSSCL_PRIORITY);
57 LE(DSSCL_EXCLUSIVE);
58 LE(DSSCL_WRITEPRIMARY);
59 }
60 #undef LE
61 sprintf(unknown, "Unknown(%08lx)", level);
62 return unknown;
63 }
64
65 static void _dump_DSCAPS(DWORD xmask) {
66 struct {
67 DWORD mask;
68 const char *name;
69 } flags[] = {
70 #define FE(x) { x, #x },
71 FE(DSCAPS_PRIMARYMONO)
72 FE(DSCAPS_PRIMARYSTEREO)
73 FE(DSCAPS_PRIMARY8BIT)
74 FE(DSCAPS_PRIMARY16BIT)
75 FE(DSCAPS_CONTINUOUSRATE)
76 FE(DSCAPS_EMULDRIVER)
77 FE(DSCAPS_CERTIFIED)
78 FE(DSCAPS_SECONDARYMONO)
79 FE(DSCAPS_SECONDARYSTEREO)
80 FE(DSCAPS_SECONDARY8BIT)
81 FE(DSCAPS_SECONDARY16BIT)
82 #undef FE
83 };
84 unsigned int i;
85
86 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
87 if ((flags[i].mask & xmask) == flags[i].mask)
88 DPRINTF("%s ",flags[i].name);
89 }
90
91 static void _dump_DSBCAPS(DWORD xmask) {
92 struct {
93 DWORD mask;
94 const char *name;
95 } flags[] = {
96 #define FE(x) { x, #x },
97 FE(DSBCAPS_PRIMARYBUFFER)
98 FE(DSBCAPS_STATIC)
99 FE(DSBCAPS_LOCHARDWARE)
100 FE(DSBCAPS_LOCSOFTWARE)
101 FE(DSBCAPS_CTRL3D)
102 FE(DSBCAPS_CTRLFREQUENCY)
103 FE(DSBCAPS_CTRLPAN)
104 FE(DSBCAPS_CTRLVOLUME)
105 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
106 FE(DSBCAPS_STICKYFOCUS)
107 FE(DSBCAPS_GLOBALFOCUS)
108 FE(DSBCAPS_GETCURRENTPOSITION2)
109 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
110 #undef FE
111 };
112 unsigned int i;
113
114 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
115 if ((flags[i].mask & xmask) == flags[i].mask)
116 DPRINTF("%s ",flags[i].name);
117 }
118
119 /*******************************************************************************
120 * IDirectSoundImpl_DirectSound
121 */
122 static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
123 LPDIRECTSOUND8 iface,
124 REFIID riid,
125 LPVOID * ppobj)
126 {
127 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
128 FIXME("shouldn't be called directly\n");
129 return E_NOINTERFACE;
130 }
131
132 static HRESULT WINAPI DSOUND_QueryInterface(
133 LPDIRECTSOUND8 iface,
134 REFIID riid,
135 LPVOID * ppobj)
136 {
137 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
138 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
139
140 if (ppobj == NULL) {
141 WARN("invalid parameter\n");
142 return E_INVALIDARG;
143 }
144
145 if (IsEqualIID(riid, &IID_IUnknown)) {
146 if (!This->pUnknown) {
147 IDirectSound_IUnknown_Create(iface, &This->pUnknown);
148 if (!This->pUnknown) {
149 WARN("IDirectSound_IUnknown_Create() failed\n");
150 *ppobj = NULL;
151 return E_NOINTERFACE;
152 }
153 }
154 IDirectSound_IUnknown_AddRef(This->pUnknown);
155 *ppobj = This->pUnknown;
156 return S_OK;
157 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
158 if (!This->pDS) {
159 IDirectSound_IDirectSound_Create(iface, &This->pDS);
160 if (!This->pDS) {
161 WARN("IDirectSound_IDirectSound_Create() failed\n");
162 *ppobj = NULL;
163 return E_NOINTERFACE;
164 }
165 }
166 IDirectSound_IDirectSound_AddRef(This->pDS);
167 *ppobj = This->pDS;
168 return S_OK;
169 }
170
171 *ppobj = NULL;
172 WARN("Unknown IID %s\n",debugstr_guid(riid));
173 return E_NOINTERFACE;
174 }
175
176 static HRESULT WINAPI DSOUND_QueryInterface8(
177 LPDIRECTSOUND8 iface,
178 REFIID riid,
179 LPVOID * ppobj)
180 {
181 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
182 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
183
184 if (ppobj == NULL) {
185 WARN("invalid parameter\n");
186 return E_INVALIDARG;
187 }
188
189 if (IsEqualIID(riid, &IID_IUnknown)) {
190 if (!This->pUnknown) {
191 IDirectSound8_IUnknown_Create(iface, &This->pUnknown);
192 if (!This->pUnknown) {
193 WARN("IDirectSound8_IUnknown_Create() failed\n");
194 *ppobj = NULL;
195 return E_NOINTERFACE;
196 }
197 }
198 IDirectSound8_IUnknown_AddRef(This->pUnknown);
199 *ppobj = This->pUnknown;
200 return S_OK;
201 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
202 if (!This->pDS) {
203 IDirectSound8_IDirectSound_Create(iface, &This->pDS);
204 if (!This->pDS) {
205 WARN("IDirectSound8_IDirectSound_Create() failed\n");
206 *ppobj = NULL;
207 return E_NOINTERFACE;
208 }
209 }
210 IDirectSound8_IDirectSound_AddRef(This->pDS);
211 *ppobj = This->pDS;
212 return S_OK;
213 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
214 if (!This->pDS8) {
215 IDirectSound8_IDirectSound8_Create(iface, &This->pDS8);
216 if (!This->pDS8) {
217 WARN("IDirectSound8_IDirectSound8_Create() failed\n");
218 *ppobj = NULL;
219 return E_NOINTERFACE;
220 }
221 }
222 IDirectSound8_IDirectSound8_AddRef(This->pDS8);
223 *ppobj = This->pDS8;
224 return S_OK;
225 }
226
227 *ppobj = NULL;
228 WARN("Unknown IID %s\n",debugstr_guid(riid));
229 return E_NOINTERFACE;
230 }
231
232 static ULONG WINAPI IDirectSoundImpl_AddRef(
233 LPDIRECTSOUND8 iface)
234 {
235 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
236 ULONG ref = InterlockedIncrement(&(This->ref));
237 TRACE("(%p) ref was %ld\n", This, ref - 1);
238 return ref;
239 }
240
241 static ULONG WINAPI IDirectSoundImpl_Release(
242 LPDIRECTSOUND8 iface)
243 {
244 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
245 ULONG ref = InterlockedDecrement(&(This->ref));
246 TRACE("(%p) ref was %ld\n", This, ref + 1);
247
248 if (!ref) {
249 if (This->device)
250 DirectSoundDevice_Release(This->device);
251
252 HeapFree(GetProcessHeap(),0,This);
253 TRACE("(%p) released\n", This);
254 }
255 return ref;
256 }
257
258 static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
259 LPDIRECTSOUND8 iface,
260 LPCDSBUFFERDESC dsbd,
261 LPLPDIRECTSOUNDBUFFER ppdsb,
262 LPUNKNOWN lpunk)
263 {
264 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
265 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
266 FIXME("shouldn't be called directly\n");
267 return DSERR_GENERIC;
268 }
269
270 static HRESULT WINAPI DSOUND_CreateSoundBuffer(
271 LPDIRECTSOUND8 iface,
272 LPCDSBUFFERDESC dsbd,
273 LPLPDIRECTSOUNDBUFFER ppdsb,
274 LPUNKNOWN lpunk,
275 BOOL from8)
276 {
277 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
278 HRESULT hres = DS_OK;
279 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
280
281 if (This == NULL) {
282 WARN("invalid parameter: This == NULL\n");
283 return DSERR_INVALIDPARAM;
284 }
285
286 if (This->device == NULL) {
287 WARN("not initialized\n");
288 return DSERR_UNINITIALIZED;
289 }
290
291 if (dsbd == NULL) {
292 WARN("invalid parameter: dsbd == NULL\n");
293 return DSERR_INVALIDPARAM;
294 }
295
296 if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
297 dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
298 WARN("invalid parameter: dsbd\n");
299 return DSERR_INVALIDPARAM;
300 }
301
302 if (ppdsb == NULL) {
303 WARN("invalid parameter: ppdsb == NULL\n");
304 return DSERR_INVALIDPARAM;
305 }
306
307 if (TRACE_ON(dsound)) {
308 TRACE("(structsize=%ld)\n",dsbd->dwSize);
309 TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
310 _dump_DSBCAPS(dsbd->dwFlags);
311 DPRINTF(")\n");
312 TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
313 TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
314 }
315
316 if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
317 if (dsbd->lpwfxFormat != NULL) {
318 WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
319 "primary buffer\n");
320 return DSERR_INVALIDPARAM;
321 }
322
323 if (This->device->primary) {
324 WARN("Primary Buffer already created\n");
325 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
326 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
327 } else {
328 This->device->dsbd = *dsbd;
329 hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd));
330 if (This->device->primary) {
331 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
332 *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
333 } else
334 WARN("PrimaryBufferImpl_Create failed\n");
335 }
336 } else {
337 IDirectSoundBufferImpl * dsb;
338
339 if (dsbd->lpwfxFormat == NULL) {
340 WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
341 "secondary buffer\n");
342 return DSERR_INVALIDPARAM;
343 }
344
345 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
346 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
347 dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
348 dsbd->lpwfxFormat->nSamplesPerSec,
349 dsbd->lpwfxFormat->nAvgBytesPerSec,
350 dsbd->lpwfxFormat->nBlockAlign,
351 dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
352
353 if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
354 WARN("invalid parameter: 3D buffer format must be mono\n");
355 return DSERR_INVALIDPARAM;
356 }
357
358 hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd);
359 if (dsb) {
360 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
361 if (*ppdsb) {
362 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
363 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
364 } else
365 WARN("SecondaryBufferImpl_Create failed\n");
366 } else
367 WARN("IDirectSoundBufferImpl_Create failed\n");
368 }
369
370 return hres;
371 }
372
373 static HRESULT WINAPI IDirectSoundImpl_GetCaps(
374 LPDIRECTSOUND8 iface,
375 LPDSCAPS lpDSCaps)
376 {
377 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
378 DirectSoundDevice *device;
379 TRACE("(%p,%p)\n",This,lpDSCaps);
380
381 if (This == NULL) {
382 WARN("invalid parameter: This == NULL\n");
383 return DSERR_INVALIDPARAM;
384 }
385
386 device = This->device;
387
388 if (device == NULL) {
389 WARN("not initialized\n");
390 return DSERR_UNINITIALIZED;
391 }
392
393 if (lpDSCaps == NULL) {
394 WARN("invalid parameter: lpDSCaps = NULL\n");
395 return DSERR_INVALIDPARAM;
396 }
397
398 /* check if there is enough room */
399 if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
400 WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
401 lpDSCaps->dwSize, sizeof(*lpDSCaps));
402 return DSERR_INVALIDPARAM;
403 }
404
405 lpDSCaps->dwFlags = device->drvcaps.dwFlags;
406 if (TRACE_ON(dsound)) {
407 TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
408 _dump_DSCAPS(lpDSCaps->dwFlags);
409 DPRINTF(")\n");
410 }
411 lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate;
412 lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate;
413 lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers;
414 lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers;
415 lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers;
416 lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers;
417 lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers;
418 lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers;
419 lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers;
420 lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers;
421 lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers;
422 lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers;
423 lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers;
424 lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers;
425 lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers;
426 lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes;
427 lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes;
428 lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
429
430 /* driver doesn't have these */
431 lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */
432 lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
433
434 return DS_OK;
435 }
436
437 static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
438 LPDIRECTSOUND8 iface,
439 LPDIRECTSOUNDBUFFER psb,
440 LPLPDIRECTSOUNDBUFFER ppdsb)
441 {
442 IDirectSoundBufferImpl* pdsb;
443 IDirectSoundBufferImpl* dsb;
444 HRESULT hres = DS_OK;
445 int size;
446 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
447
448 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
449
450 if (This == NULL) {
451 WARN("invalid parameter: This == NULL\n");
452 return DSERR_INVALIDPARAM;
453 }
454
455 if (This->device == NULL) {
456 WARN("not initialized\n");
457 return DSERR_UNINITIALIZED;
458 }
459
460 if (psb == NULL) {
461 WARN("invalid parameter: psb == NULL\n");
462 return DSERR_INVALIDPARAM;
463 }
464
465 if (ppdsb == NULL) {
466 WARN("invalid parameter: ppdsb == NULL\n");
467 return DSERR_INVALIDPARAM;
468 }
469
470 /* FIXME: hack to make sure we have a secondary buffer */
471 if ((IDirectSoundImpl *)((SecondaryBufferImpl *)psb)->dsb == This) {
472 WARN("trying to duplicate primary buffer\n");
473 *ppdsb = NULL;
474 return DSERR_INVALIDCALL;
475 }
476
477 pdsb = ((SecondaryBufferImpl *)psb)->dsb;
478
479 dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
480
481 if (dsb == NULL) {
482 WARN("out of memory\n");
483 *ppdsb = NULL;
484 return DSERR_OUTOFMEMORY;
485 }
486
487 CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl));
488
489 if (pdsb->hwbuf) {
490 TRACE("duplicating hardware buffer\n");
491
492 hres = IDsDriver_DuplicateSoundBuffer(This->device->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf);
493 if (hres != DS_OK) {
494 TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n");
495 dsb->hwbuf = NULL;
496 /* allocate buffer */
497 if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
498 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
499 if (dsb->buffer == NULL) {
500 WARN("out of memory\n");
501 HeapFree(GetProcessHeap(),0,dsb);
502 *ppdsb = NULL;
503 return DSERR_OUTOFMEMORY;
504 }
505
506 dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
507 if (dsb->buffer->memory == NULL) {
508 WARN("out of memory\n");
509 HeapFree(GetProcessHeap(),0,dsb->buffer);
510 HeapFree(GetProcessHeap(),0,dsb);
511 *ppdsb = NULL;
512 return DSERR_OUTOFMEMORY;
513 }
514 dsb->buffer->ref = 1;
515
516 /* FIXME: copy buffer ? */
517 }
518 }
519 } else {
520 dsb->hwbuf = NULL;
521 dsb->buffer->ref++;
522 }
523
524 dsb->ref = 0;
525 dsb->state = STATE_STOPPED;
526 dsb->playpos = 0;
527 dsb->buf_mixpos = 0;
528 dsb->dsound = This;
529 dsb->ds3db = NULL;
530 dsb->iks = NULL; /* FIXME? */
531 dsb->dsb = NULL;
532
533 /* variable sized struct so calculate size based on format */
534 size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize;
535
536 dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size);
537 if (dsb->pwfx == NULL) {
538 WARN("out of memory\n");
539 HeapFree(GetProcessHeap(),0,dsb->buffer);
540 HeapFree(GetProcessHeap(),0,dsb);
541 *ppdsb = NULL;
542 return DSERR_OUTOFMEMORY;
543 }
544
545 CopyMemory(dsb->pwfx, pdsb->pwfx, size);
546
547 InitializeCriticalSection(&(dsb->lock));
548 dsb->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUNDBUFFER_lock";
549
550 /* register buffer */
551 hres = DSOUND_AddBuffer(This, dsb);
552 if (hres != DS_OK) {
553 IDirectSoundBuffer8_Release(psb);
554 dsb->lock.DebugInfo->Spare[0] = 0;
555 DeleteCriticalSection(&(dsb->lock));
556 HeapFree(GetProcessHeap(),0,dsb->buffer);
557 HeapFree(GetProcessHeap(),0,dsb->pwfx);
558 HeapFree(GetProcessHeap(),0,dsb);
559 *ppdsb = 0;
560 } else {
561 hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
562 if (*ppdsb) {
563 dsb->dsb = (SecondaryBufferImpl*)*ppdsb;
564 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
565 } else
566 WARN("SecondaryBufferImpl_Create failed\n");
567 }
568
569 return hres;
570 }
571
572 static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
573 LPDIRECTSOUND8 iface,
574 HWND hwnd,
575 DWORD level)
576 {
577 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
578 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
579
580 if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
581 WARN("level=%s not fully supported\n",
582 level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
583 }
584 This->device->priolevel = level;
585 return DS_OK;
586 }
587
588 static HRESULT WINAPI IDirectSoundImpl_Compact(
589 LPDIRECTSOUND8 iface)
590 {
591 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
592 TRACE("(%p)\n",This);
593
594 if (This->device == NULL) {
595 WARN("not initialized\n");
596 return DSERR_UNINITIALIZED;
597 }
598
599 if (This->device->priolevel != DSSCL_PRIORITY) {
600 WARN("incorrect priority level\n");
601 return DSERR_PRIOLEVELNEEDED;
602 }
603
604 return DS_OK;
605 }
606
607 static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
608 LPDIRECTSOUND8 iface,
609 LPDWORD lpdwSpeakerConfig)
610 {
611 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
612 TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
613
614 if (This->device == NULL) {
615 WARN("not initialized\n");
616 return DSERR_UNINITIALIZED;
617 }
618
619 if (lpdwSpeakerConfig == NULL) {
620 WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
621 return DSERR_INVALIDPARAM;
622 }
623
624 WARN("not fully functional\n");
625 *lpdwSpeakerConfig = This->device->speaker_config;
626 return DS_OK;
627 }
628
629 static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
630 LPDIRECTSOUND8 iface,
631 DWORD config)
632 {
633 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
634 TRACE("(%p,0x%08lx)\n",This,config);
635
636 if (This->device == NULL) {
637 WARN("not initialized\n");
638 return DSERR_UNINITIALIZED;
639 }
640
641 This->device->speaker_config = config;
642 WARN("not fully functional\n");
643 return DS_OK;
644 }
645
646 static HRESULT WINAPI IDirectSoundImpl_Initialize(
647 LPDIRECTSOUND8 iface,
648 LPCGUID lpcGUID)
649 {
650 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
651 DirectSoundDevice *device = This->device;
652 HRESULT hr = DS_OK;
653 unsigned wod, wodn;
654 BOOLEAN found = FALSE;
655 GUID devGUID;
656 TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID));
657
658 if (device != NULL) {
659 WARN("already initialized\n");
660 return DSERR_ALREADYINITIALIZED;
661 }
662
663 /* Default device? */
664 if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
665 lpcGUID = &DSDEVID_DefaultPlayback;
666
667 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
668 WARN("invalid parameter: lpcGUID\n");
669 return DSERR_INVALIDPARAM;
670 }
671
672 /* Enumerate WINMM audio devices and find the one we want */
673 wodn = waveOutGetNumDevs();
674 if (!wodn) {
675 WARN("no driver\n");
676 return DSERR_NODRIVER;
677 }
678
679 for (wod=0; wod<wodn; wod++) {
680 if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
681 found = TRUE;
682 break;
683 }
684 }
685
686 if (found == FALSE) {
687 WARN("No device found matching given ID!\n");
688 return DSERR_NODRIVER;
689 }
690
691 if (DSOUND_renderer[wod]) {
692 if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
693 device = DSOUND_renderer[wod];
694 device->ref++;
695 This->device = device;
696 return DS_OK;
697 } else {
698 ERR("device GUID doesn't match\n");
699 hr = DSERR_GENERIC;
700 return hr;
701 }
702 } else {
703 hr = DirectSoundDevice_Create(&(device));
704 if (hr != DS_OK) {
705 WARN("DirectSoundDevice_Create failed\n");
706 return hr;
707 }
708 }
709
710 This->device = device;
711 device->guid = devGUID;
712
713 /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
714 WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
715
716 /* Disable the direct sound driver to force emulation if requested. */
717 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
718 device->driver = NULL;
719
720 /* Get driver description */
721 if (device->driver) {
722 hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
723 if (hr != DS_OK) {
724 WARN("IDsDriver_GetDriverDesc failed\n");
725 return hr;
726 }
727 } else {
728 /* if no DirectSound interface available, use WINMM API instead */
729 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
730 }
731
732 device->drvdesc.dnDevNode = wod;
733
734 /* If the driver requests being opened through MMSYSTEM
735 * (which is recommended by the DDK), it is supposed to happen
736 * before the DirectSound interface is opened */
737 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
738 {
739 DWORD flags = CALLBACK_FUNCTION;
740
741 /* disable direct sound if requested */
742 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
743 flags |= WAVE_DIRECTSOUND;
744
745 hr = mmErr(waveOutOpen(&(device->hwo),
746 device->drvdesc.dnDevNode, device->pwfx,
747 (DWORD_PTR)DSOUND_callback, (DWORD)device,
748 flags));
749 if (hr != DS_OK) {
750 WARN("waveOutOpen failed\n");
751 return hr;
752 }
753 }
754
755 if (device->driver) {
756 hr = IDsDriver_Open(device->driver);
757 if (hr != DS_OK) {
758 WARN("IDsDriver_Open failed\n");
759 return hr;
760 }
761
762 /* the driver is now open, so it's now allowed to call GetCaps */
763 hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
764 if (hr != DS_OK) {
765 WARN("IDsDriver_GetCaps failed\n");
766 return hr;
767 }
768 } else {
769 WAVEOUTCAPSA woc;
770 hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
771 if (hr != DS_OK) {
772 WARN("waveOutGetDevCaps failed\n");
773 return hr;
774 }
775 ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
776 if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
777 (woc.dwFormats & WAVE_FORMAT_2M08) ||
778 (woc.dwFormats & WAVE_FORMAT_4M08) ||
779 (woc.dwFormats & WAVE_FORMAT_48M08) ||
780 (woc.dwFormats & WAVE_FORMAT_96M08)) {
781 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
782 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
783 }
784 if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
785 (woc.dwFormats & WAVE_FORMAT_2M16) ||
786 (woc.dwFormats & WAVE_FORMAT_4M16) ||
787 (woc.dwFormats & WAVE_FORMAT_48M16) ||
788 (woc.dwFormats & WAVE_FORMAT_96M16)) {
789 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
790 device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
791 }
792 if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
793 (woc.dwFormats & WAVE_FORMAT_2S08) ||
794 (woc.dwFormats & WAVE_FORMAT_4S08) ||
795 (woc.dwFormats & WAVE_FORMAT_48S08) ||
796 (woc.dwFormats & WAVE_FORMAT_96S08)) {
797 device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
798 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
799 }
800 if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
801 (woc.dwFormats & WAVE_FORMAT_2S16) ||
802 (woc.dwFormats & WAVE_FORMAT_4S16) ||
803 (woc.dwFormats & WAVE_FORMAT_48S16) ||
804 (woc.dwFormats & WAVE_FORMAT_96S16)) {
805 device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
806 device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
807 }
808 if (ds_emuldriver)
809 device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
810 device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
811 device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
812 device->drvcaps.dwPrimaryBuffers = 1;
813 }
814
815 hr = DSOUND_PrimaryCreate(device);
816 if (hr == DS_OK) {
817 DSOUND_renderer[device->drvdesc.dnDevNode] = device;
818 timeBeginPeriod(DS_TIME_RES);
819 DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
820 (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
821 } else {
822 WARN("DSOUND_PrimaryCreate failed\n");
823 }
824
825 return hr;
826 }
827
828 static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
829 LPDIRECTSOUND8 iface,
830 LPDWORD pdwCertified)
831 {
832 IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
833 TRACE("(%p, %p)\n",This,pdwCertified);
834
835 if (This->device == NULL) {
836 WARN("not initialized\n");
837 return DSERR_UNINITIALIZED;
838 }
839
840 if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
841 *pdwCertified = DS_CERTIFIED;
842 else
843 *pdwCertified = DS_UNCERTIFIED;
844 return DS_OK;
845 }
846
847 static const IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
848 {
849 IDirectSoundImpl_QueryInterface,
850 IDirectSoundImpl_AddRef,
851 IDirectSoundImpl_Release,
852 IDirectSoundImpl_CreateSoundBuffer,
853 IDirectSoundImpl_GetCaps,
854 IDirectSoundImpl_DuplicateSoundBuffer,
855 IDirectSoundImpl_SetCooperativeLevel,
856 IDirectSoundImpl_Compact,
857 IDirectSoundImpl_GetSpeakerConfig,
858 IDirectSoundImpl_SetSpeakerConfig,
859 IDirectSoundImpl_Initialize,
860 IDirectSoundImpl_VerifyCertification
861 };
862
863 static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
864 {
865 DirectSoundDevice * device;
866 TRACE("(%p)\n", ppDevice);
867
868 /* Allocate memory */
869 device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
870 if (device == NULL) {
871 WARN("out of memory\n");
872 return DSERR_OUTOFMEMORY;
873 }
874
875 device->ref = 1;
876 device->driver = NULL;
877 device->priolevel = DSSCL_NORMAL;
878 device->fraglen = 0;
879 device->hwbuf = NULL;
880 device->buffer = NULL;
881 device->buflen = 0;
882 device->writelead = 0;
883 device->state = STATE_STOPPED;
884 device->nrofbuffers = 0;
885 device->buffers = NULL;
886 device->primary = NULL;
887 device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
888 device->tmp_buffer = NULL;
889 device->tmp_buffer_len = 0;
890
891 /* 3D listener initial parameters */
892 device->listener = NULL;
893 device->ds3dl.dwSize = sizeof(DS3DLISTENER);
894 device->ds3dl.vPosition.x = 0.0;
895 device->ds3dl.vPosition.y = 0.0;
896 device->ds3dl.vPosition.z = 0.0;
897 device->ds3dl.vVelocity.x = 0.0;
898 device->ds3dl.vVelocity.y = 0.0;
899 device->ds3dl.vVelocity.z = 0.0;
900 device->ds3dl.vOrientFront.x = 0.0;
901 device->ds3dl.vOrientFront.y = 0.0;
902 device->ds3dl.vOrientFront.z = 1.0;
903 device->ds3dl.vOrientTop.x = 0.0;
904 device->ds3dl.vOrientTop.y = 1.0;
905 device->ds3dl.vOrientTop.z = 0.0;
906 device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
907 device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
908 device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
909
910 device->prebuf = ds_snd_queue_max;
911 device->guid = GUID_NULL;
912
913 /* Set default wave format (may need it for waveOutOpen) */
914 device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
915 if (device->pwfx == NULL) {
916 WARN("out of memory\n");
917 HeapFree(GetProcessHeap(),0,device);
918 return DSERR_OUTOFMEMORY;
919 }
920
921 /* We rely on the sound driver to return the actual sound format of
922 * the device if it does not support 22050x8x2 and is given the
923 * WAVE_DIRECTSOUND flag.
924 */
925 device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
926 device->pwfx->nSamplesPerSec = 22050;
927 device->pwfx->wBitsPerSample = 8;
928 device->pwfx->nChannels = 2;
929 device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
930 device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
931 device->pwfx->cbSize = 0;
932
933 InitializeCriticalSection(&(device->mixlock));
934 device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock";
935
936 RtlInitializeResource(&(device->buffer_list_lock));
937
938 *ppDevice = device;
939
940 return DS_OK;
941 }
942
943 static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
944 {
945 int i;
946 HRESULT hr;
947 TRACE("(%p) ref was %lu\n", device, device->ref);
948
949 device->ref--;
950 if (device->ref == 0) {
951 timeKillEvent(device->timerID);
952 timeEndPeriod(DS_TIME_RES);
953 /* wait for timer to expire */
954 Sleep(DS_TIME_RES+1);
955
956 /* The sleep above should have allowed the timer process to expire
957 * but try to grab the lock just in case. Can't hold lock because
958 * IDirectSoundBufferImpl_Destroy also grabs the lock */
959 RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
960 RtlReleaseResource(&(device->buffer_list_lock));
961
962 /* It is allowed to release this object even when buffers are playing */
963 if (device->buffers) {
964 WARN("%d secondary buffers not released\n", device->nrofbuffers);
965 for( i=0;i<device->nrofbuffers;i++)
966 IDirectSoundBufferImpl_Destroy(device->buffers[i]);
967 }
968
969 if (device->primary) {
970 WARN("primary buffer not released\n");
971 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
972 }
973
974 hr = DSOUND_PrimaryDestroy(device);
975 if (hr != DS_OK)
976 WARN("DSOUND_PrimaryDestroy failed\n");
977
978 if (device->driver)
979 IDsDriver_Close(device->driver);
980
981 if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
982 waveOutClose(device->hwo);
983
984 if (device->driver)
985 IDsDriver_Release(device->driver);
986
987 DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
988
989 HeapFree(GetProcessHeap(),0,device->tmp_buffer);
990 HeapFree(GetProcessHeap(),0,device->buffer);
991 RtlDeleteResource(&device->buffer_list_lock);
992 device->mixlock.DebugInfo->Spare[0] = 0;
993 DeleteCriticalSection(&device->mixlock);
994 HeapFree(GetProcessHeap(),0,device);
995 TRACE("(%p) released\n", device);
996 }
997 return device->ref;
998 }
999
1000 HRESULT WINAPI IDirectSoundImpl_Create(
1001 LPDIRECTSOUND8 * ppDS)
1002 {
1003 IDirectSoundImpl* pDS;
1004 TRACE("(%p)\n",ppDS);
1005
1006 /* Allocate memory */
1007 pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
1008 if (pDS == NULL) {
1009 WARN("out of memory\n");
1010 *ppDS = NULL;
1011 return DSERR_OUTOFMEMORY;
1012 }
1013
1014 pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
1015 pDS->ref = 0;
1016 pDS->device = NULL;
1017
1018 *ppDS = (LPDIRECTSOUND8)pDS;
1019
1020 return DS_OK;
1021 }
1022
1023 /*******************************************************************************
1024 * IDirectSound_IUnknown
1025 */
1026 static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
1027 LPUNKNOWN iface,
1028 REFIID riid,
1029 LPVOID * ppobj)
1030 {
1031 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1032 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1033 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1034 }
1035
1036 static ULONG WINAPI IDirectSound_IUnknown_AddRef(
1037 LPUNKNOWN iface)
1038 {
1039 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1040 ULONG ref = InterlockedIncrement(&(This->ref));
1041 TRACE("(%p) ref was %ld\n", This, ref - 1);
1042 return ref;
1043 }
1044
1045 static ULONG WINAPI IDirectSound_IUnknown_Release(
1046 LPUNKNOWN iface)
1047 {
1048 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1049 ULONG ref = InterlockedDecrement(&(This->ref));
1050 TRACE("(%p) ref was %ld\n", This, ref + 1);
1051 if (!ref) {
1052 IDirectSoundImpl_Release(This->pds);
1053 HeapFree(GetProcessHeap(), 0, This);
1054 TRACE("(%p) released\n", This);
1055 }
1056 return ref;
1057 }
1058
1059 static const IUnknownVtbl DirectSound_Unknown_Vtbl =
1060 {
1061 IDirectSound_IUnknown_QueryInterface,
1062 IDirectSound_IUnknown_AddRef,
1063 IDirectSound_IUnknown_Release
1064 };
1065
1066 HRESULT WINAPI IDirectSound_IUnknown_Create(
1067 LPDIRECTSOUND8 pds,
1068 LPUNKNOWN * ppunk)
1069 {
1070 IDirectSound_IUnknown * pdsunk;
1071 TRACE("(%p,%p)\n",pds,ppunk);
1072
1073 if (ppunk == NULL) {
1074 ERR("invalid parameter: ppunk == NULL\n");
1075 return DSERR_INVALIDPARAM;
1076 }
1077
1078 if (pds == NULL) {
1079 ERR("invalid parameter: pds == NULL\n");
1080 *ppunk = NULL;
1081 return DSERR_INVALIDPARAM;
1082 }
1083
1084 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1085 if (pdsunk == NULL) {
1086 WARN("out of memory\n");
1087 *ppunk = NULL;
1088 return DSERR_OUTOFMEMORY;
1089 }
1090
1091 pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
1092 pdsunk->ref = 0;
1093 pdsunk->pds = pds;
1094
1095 IDirectSoundImpl_AddRef(pds);
1096 *ppunk = (LPUNKNOWN)pdsunk;
1097
1098 return DS_OK;
1099 }
1100
1101 /*******************************************************************************
1102 * IDirectSound_IDirectSound
1103 */
1104 static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
1105 LPDIRECTSOUND iface,
1106 REFIID riid,
1107 LPVOID * ppobj)
1108 {
1109 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1110 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1111 return DSOUND_QueryInterface(This->pds, riid, ppobj);
1112 }
1113
1114 static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
1115 LPDIRECTSOUND iface)
1116 {
1117 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1118 ULONG ref = InterlockedIncrement(&(This->ref));
1119 TRACE("(%p) ref was %ld\n", This, ref - 1);
1120 return ref;
1121 }
1122
1123 static ULONG WINAPI IDirectSound_IDirectSound_Release(
1124 LPDIRECTSOUND iface)
1125 {
1126 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1127 ULONG ref = InterlockedDecrement(&(This->ref));
1128 TRACE("(%p) ref was %ld\n", This, ref + 1);
1129 if (!ref) {
1130 IDirectSoundImpl_Release(This->pds);
1131 HeapFree(GetProcessHeap(), 0, This);
1132 TRACE("(%p) released\n", This);
1133 }
1134 return ref;
1135 }
1136
1137 static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
1138 LPDIRECTSOUND iface,
1139 LPCDSBUFFERDESC dsbd,
1140 LPLPDIRECTSOUNDBUFFER ppdsb,
1141 LPUNKNOWN lpunk)
1142 {
1143 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1144 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1145 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
1146 }
1147
1148 static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
1149 LPDIRECTSOUND iface,
1150 LPDSCAPS lpDSCaps)
1151 {
1152 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1153 TRACE("(%p,%p)\n",This,lpDSCaps);
1154 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1155 }
1156
1157 static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
1158 LPDIRECTSOUND iface,
1159 LPDIRECTSOUNDBUFFER psb,
1160 LPLPDIRECTSOUNDBUFFER ppdsb)
1161 {
1162 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1163 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1164 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1165 }
1166
1167 static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
1168 LPDIRECTSOUND iface,
1169 HWND hwnd,
1170 DWORD level)
1171 {
1172 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1173 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1174 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1175 }
1176
1177 static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
1178 LPDIRECTSOUND iface)
1179 {
1180 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1181 TRACE("(%p)\n", This);
1182 return IDirectSoundImpl_Compact(This->pds);
1183 }
1184
1185 static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
1186 LPDIRECTSOUND iface,
1187 LPDWORD lpdwSpeakerConfig)
1188 {
1189 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1190 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1191 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1192 }
1193
1194 static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
1195 LPDIRECTSOUND iface,
1196 DWORD config)
1197 {
1198 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1199 TRACE("(%p,0x%08lx)\n",This,config);
1200 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1201 }
1202
1203 static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
1204 LPDIRECTSOUND iface,
1205 LPCGUID lpcGuid)
1206 {
1207 IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
1208 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1209 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1210 }
1211
1212 static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
1213 {
1214 IDirectSound_IDirectSound_QueryInterface,
1215 IDirectSound_IDirectSound_AddRef,
1216 IDirectSound_IDirectSound_Release,
1217 IDirectSound_IDirectSound_CreateSoundBuffer,
1218 IDirectSound_IDirectSound_GetCaps,
1219 IDirectSound_IDirectSound_DuplicateSoundBuffer,
1220 IDirectSound_IDirectSound_SetCooperativeLevel,
1221 IDirectSound_IDirectSound_Compact,
1222 IDirectSound_IDirectSound_GetSpeakerConfig,
1223 IDirectSound_IDirectSound_SetSpeakerConfig,
1224 IDirectSound_IDirectSound_Initialize
1225 };
1226
1227 HRESULT WINAPI IDirectSound_IDirectSound_Create(
1228 LPDIRECTSOUND8 pds,
1229 LPDIRECTSOUND * ppds)
1230 {
1231 IDirectSound_IDirectSound * pdsds;
1232 TRACE("(%p,%p)\n",pds,ppds);
1233
1234 if (ppds == NULL) {
1235 ERR("invalid parameter: ppds == NULL\n");
1236 return DSERR_INVALIDPARAM;
1237 }
1238
1239 if (pds == NULL) {
1240 ERR("invalid parameter: pds == NULL\n");
1241 *ppds = NULL;
1242 return DSERR_INVALIDPARAM;
1243 }
1244
1245 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1246 if (pdsds == NULL) {
1247 WARN("out of memory\n");
1248 *ppds = NULL;
1249 return DSERR_OUTOFMEMORY;
1250 }
1251
1252 pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
1253 pdsds->ref = 0;
1254 pdsds->pds = pds;
1255
1256 IDirectSoundImpl_AddRef(pds);
1257 *ppds = (LPDIRECTSOUND)pdsds;
1258
1259 return DS_OK;
1260 }
1261
1262 /*******************************************************************************
1263 * IDirectSound8_IUnknown
1264 */
1265 static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
1266 LPUNKNOWN iface,
1267 REFIID riid,
1268 LPVOID * ppobj)
1269 {
1270 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1271 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1272 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1273 }
1274
1275 static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
1276 LPUNKNOWN iface)
1277 {
1278 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1279 ULONG ref = InterlockedIncrement(&(This->ref));
1280 TRACE("(%p) ref was %ld\n", This, ref - 1);
1281 return ref;
1282 }
1283
1284 static ULONG WINAPI IDirectSound8_IUnknown_Release(
1285 LPUNKNOWN iface)
1286 {
1287 IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
1288 ULONG ref = InterlockedDecrement(&(This->ref));
1289 TRACE("(%p) ref was %ld\n", This, ref + 1);
1290 if (!ref) {
1291 IDirectSoundImpl_Release(This->pds);
1292 HeapFree(GetProcessHeap(), 0, This);
1293 TRACE("(%p) released\n", This);
1294 }
1295 return ref;
1296 }
1297
1298 static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
1299 {
1300 IDirectSound8_IUnknown_QueryInterface,
1301 IDirectSound8_IUnknown_AddRef,
1302 IDirectSound8_IUnknown_Release
1303 };
1304
1305 HRESULT WINAPI IDirectSound8_IUnknown_Create(
1306 LPDIRECTSOUND8 pds,
1307 LPUNKNOWN * ppunk)
1308 {
1309 IDirectSound8_IUnknown * pdsunk;
1310 TRACE("(%p,%p)\n",pds,ppunk);
1311
1312 if (ppunk == NULL) {
1313 ERR("invalid parameter: ppunk == NULL\n");
1314 return DSERR_INVALIDPARAM;
1315 }
1316
1317 if (pds == NULL) {
1318 ERR("invalid parameter: pds == NULL\n");
1319 *ppunk = NULL;
1320 return DSERR_INVALIDPARAM;
1321 }
1322
1323 pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
1324 if (pdsunk == NULL) {
1325 WARN("out of memory\n");
1326 *ppunk = NULL;
1327 return DSERR_OUTOFMEMORY;
1328 }
1329
1330 pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
1331 pdsunk->ref = 0;
1332 pdsunk->pds = pds;
1333
1334 IDirectSoundImpl_AddRef(pds);
1335 *ppunk = (LPUNKNOWN)pdsunk;
1336
1337 return DS_OK;
1338 }
1339
1340 /*******************************************************************************
1341 * IDirectSound8_IDirectSound
1342 */
1343 static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
1344 LPDIRECTSOUND iface,
1345 REFIID riid,
1346 LPVOID * ppobj)
1347 {
1348 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1349 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1350 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1351 }
1352
1353 static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
1354 LPDIRECTSOUND iface)
1355 {
1356 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1357 ULONG ref = InterlockedIncrement(&(This->ref));
1358 TRACE("(%p) ref was %ld\n", This, ref - 1);
1359 return ref;
1360 }
1361
1362 static ULONG WINAPI IDirectSound8_IDirectSound_Release(
1363 LPDIRECTSOUND iface)
1364 {
1365 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1366 ULONG ref = InterlockedDecrement(&(This->ref));
1367 TRACE("(%p) ref was %ld\n", This, ref + 1);
1368 if (!ref) {
1369 IDirectSoundImpl_Release(This->pds);
1370 HeapFree(GetProcessHeap(), 0, This);
1371 TRACE("(%p) released\n", This);
1372 }
1373 return ref;
1374 }
1375
1376 static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
1377 LPDIRECTSOUND iface,
1378 LPCDSBUFFERDESC dsbd,
1379 LPLPDIRECTSOUNDBUFFER ppdsb,
1380 LPUNKNOWN lpunk)
1381 {
1382 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1383 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1384 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1385 }
1386
1387 static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
1388 LPDIRECTSOUND iface,
1389 LPDSCAPS lpDSCaps)
1390 {
1391 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1392 TRACE("(%p,%p)\n",This,lpDSCaps);
1393 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1394 }
1395
1396 static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
1397 LPDIRECTSOUND iface,
1398 LPDIRECTSOUNDBUFFER psb,
1399 LPLPDIRECTSOUNDBUFFER ppdsb)
1400 {
1401 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1402 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1403 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1404 }
1405
1406 static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
1407 LPDIRECTSOUND iface,
1408 HWND hwnd,
1409 DWORD level)
1410 {
1411 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1412 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1413 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1414 }
1415
1416 static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
1417 LPDIRECTSOUND iface)
1418 {
1419 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1420 TRACE("(%p)\n", This);
1421 return IDirectSoundImpl_Compact(This->pds);
1422 }
1423
1424 static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
1425 LPDIRECTSOUND iface,
1426 LPDWORD lpdwSpeakerConfig)
1427 {
1428 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1429 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1430 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1431 }
1432
1433 static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
1434 LPDIRECTSOUND iface,
1435 DWORD config)
1436 {
1437 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1438 TRACE("(%p,0x%08lx)\n",This,config);
1439 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1440 }
1441
1442 static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
1443 LPDIRECTSOUND iface,
1444 LPCGUID lpcGuid)
1445 {
1446 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1447 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1448 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1449 }
1450
1451 static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
1452 {
1453 IDirectSound8_IDirectSound_QueryInterface,
1454 IDirectSound8_IDirectSound_AddRef,
1455 IDirectSound8_IDirectSound_Release,
1456 IDirectSound8_IDirectSound_CreateSoundBuffer,
1457 IDirectSound8_IDirectSound_GetCaps,
1458 IDirectSound8_IDirectSound_DuplicateSoundBuffer,
1459 IDirectSound8_IDirectSound_SetCooperativeLevel,
1460 IDirectSound8_IDirectSound_Compact,
1461 IDirectSound8_IDirectSound_GetSpeakerConfig,
1462 IDirectSound8_IDirectSound_SetSpeakerConfig,
1463 IDirectSound8_IDirectSound_Initialize
1464 };
1465
1466 HRESULT WINAPI IDirectSound8_IDirectSound_Create(
1467 LPDIRECTSOUND8 pds,
1468 LPDIRECTSOUND * ppds)
1469 {
1470 IDirectSound8_IDirectSound * pdsds;
1471 TRACE("(%p,%p)\n",pds,ppds);
1472
1473 if (ppds == NULL) {
1474 ERR("invalid parameter: ppds == NULL\n");
1475 return DSERR_INVALIDPARAM;
1476 }
1477
1478 if (pds == NULL) {
1479 ERR("invalid parameter: pds == NULL\n");
1480 *ppds = NULL;
1481 return DSERR_INVALIDPARAM;
1482 }
1483
1484 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1485 if (pdsds == NULL) {
1486 WARN("out of memory\n");
1487 *ppds = NULL;
1488 return DSERR_OUTOFMEMORY;
1489 }
1490
1491 pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
1492 pdsds->ref = 0;
1493 pdsds->pds = pds;
1494
1495 IDirectSoundImpl_AddRef(pds);
1496 *ppds = (LPDIRECTSOUND)pdsds;
1497
1498 return DS_OK;
1499 }
1500
1501 /*******************************************************************************
1502 * IDirectSound8_IDirectSound8
1503 */
1504 static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
1505 LPDIRECTSOUND8 iface,
1506 REFIID riid,
1507 LPVOID * ppobj)
1508 {
1509 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1510 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1511 return DSOUND_QueryInterface8(This->pds, riid, ppobj);
1512 }
1513
1514 static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
1515 LPDIRECTSOUND8 iface)
1516 {
1517 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1518 ULONG ref = InterlockedIncrement(&(This->ref));
1519 TRACE("(%p) ref was %ld\n", This, ref - 1);
1520 return ref;
1521 }
1522
1523 static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
1524 LPDIRECTSOUND8 iface)
1525 {
1526 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1527 ULONG ref = InterlockedDecrement(&(This->ref));
1528 TRACE("(%p) ref was %ld\n", This, ref + 1);
1529 if (!ref) {
1530 IDirectSoundImpl_Release(This->pds);
1531 HeapFree(GetProcessHeap(), 0, This);
1532 TRACE("(%p) released\n", This);
1533 }
1534 return ref;
1535 }
1536
1537 static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
1538 LPDIRECTSOUND8 iface,
1539 LPCDSBUFFERDESC dsbd,
1540 LPLPDIRECTSOUNDBUFFER ppdsb,
1541 LPUNKNOWN lpunk)
1542 {
1543 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1544 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
1545 return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
1546 }
1547
1548 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
1549 LPDIRECTSOUND8 iface,
1550 LPDSCAPS lpDSCaps)
1551 {
1552 IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
1553 TRACE("(%p,%p)\n",This,lpDSCaps);
1554 return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
1555 }
1556
1557 static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
1558 LPDIRECTSOUND8 iface,
1559 LPDIRECTSOUNDBUFFER psb,
1560 LPLPDIRECTSOUNDBUFFER ppdsb)
1561 {
1562 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1563 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
1564 return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
1565 }
1566
1567 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
1568 LPDIRECTSOUND8 iface,
1569 HWND hwnd,
1570 DWORD level)
1571 {
1572 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1573 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
1574 return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
1575 }
1576
1577 static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
1578 LPDIRECTSOUND8 iface)
1579 {
1580 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1581 TRACE("(%p)\n", This);
1582 return IDirectSoundImpl_Compact(This->pds);
1583 }
1584
1585 static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
1586 LPDIRECTSOUND8 iface,
1587 LPDWORD lpdwSpeakerConfig)
1588 {
1589 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1590 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
1591 return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
1592 }
1593
1594 static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
1595 LPDIRECTSOUND8 iface,
1596 DWORD config)
1597 {
1598 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1599 TRACE("(%p,0x%08lx)\n",This,config);
1600 return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
1601 }
1602
1603 static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
1604 LPDIRECTSOUND8 iface,
1605 LPCGUID lpcGuid)
1606 {
1607 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1608 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
1609 return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
1610 }
1611
1612 static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
1613 LPDIRECTSOUND8 iface,
1614 LPDWORD pdwCertified)
1615 {
1616 IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
1617 TRACE("(%p, %p)\n", This, pdwCertified);
1618 return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
1619 }
1620
1621 static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
1622 {
1623 IDirectSound8_IDirectSound8_QueryInterface,
1624 IDirectSound8_IDirectSound8_AddRef,
1625 IDirectSound8_IDirectSound8_Release,
1626 IDirectSound8_IDirectSound8_CreateSoundBuffer,
1627 IDirectSound8_IDirectSound8_GetCaps,
1628 IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
1629 IDirectSound8_IDirectSound8_SetCooperativeLevel,
1630 IDirectSound8_IDirectSound8_Compact,
1631 IDirectSound8_IDirectSound8_GetSpeakerConfig,
1632 IDirectSound8_IDirectSound8_SetSpeakerConfig,
1633 IDirectSound8_IDirectSound8_Initialize,
1634 IDirectSound8_IDirectSound8_VerifyCertification
1635 };
1636
1637 HRESULT WINAPI IDirectSound8_IDirectSound8_Create(
1638 LPDIRECTSOUND8 pds,
1639 LPDIRECTSOUND8 * ppds)
1640 {
1641 IDirectSound8_IDirectSound8 * pdsds;
1642 TRACE("(%p,%p)\n",pds,ppds);
1643
1644 if (ppds == NULL) {
1645 ERR("invalid parameter: ppds == NULL\n");
1646 return DSERR_INVALIDPARAM;
1647 }
1648
1649 if (pds == NULL) {
1650 ERR("invalid parameter: pds == NULL\n");
1651 *ppds = NULL;
1652 return DSERR_INVALIDPARAM;
1653 }
1654
1655 pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
1656 if (pdsds == NULL) {
1657 WARN("out of memory\n");
1658 *ppds = NULL;
1659 return DSERR_OUTOFMEMORY;
1660 }
1661
1662 pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
1663 pdsds->ref = 0;
1664 pdsds->pds = pds;
1665
1666 IDirectSoundImpl_AddRef(pds);
1667 *ppds = (LPDIRECTSOUND8)pdsds;
1668
1669 return DS_OK;
1670 }
1671
1672 HRESULT WINAPI DSOUND_Create(
1673 LPDIRECTSOUND *ppDS,
1674 IUnknown *pUnkOuter)
1675 {
1676 LPDIRECTSOUND8 pDS;
1677 HRESULT hr;
1678 TRACE("(%p,%p)\n",ppDS,pUnkOuter);
1679
1680 /* Get dsound configuration */
1681 setup_dsound_options();
1682
1683 hr = IDirectSoundImpl_Create(&pDS);
1684 if (hr == DS_OK) {
1685 hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
1686 if (*ppDS)
1687 IDirectSound_IDirectSound_AddRef(*ppDS);
1688 else {
1689 WARN("IDirectSound_IDirectSound_Create failed\n");
1690 IDirectSound8_Release(pDS);
1691 }
1692 } else {
1693 WARN("IDirectSoundImpl_Create failed\n");
1694 *ppDS = 0;
1695 }
1696
1697 return hr;
1698 }
1699
1700 /*******************************************************************************
1701 * DirectSoundCreate (DSOUND.1)
1702 *
1703 * Creates and initializes a DirectSound interface.
1704 *
1705 * PARAMS
1706 * lpcGUID [I] Address of the GUID that identifies the sound device.
1707 * ppDS [O] Address of a variable to receive the interface pointer.
1708 * pUnkOuter [I] Must be NULL.
1709 *
1710 * RETURNS
1711 * Success: DS_OK
1712 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1713 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1714 */
1715 HRESULT WINAPI DirectSoundCreate(
1716 LPCGUID lpcGUID,
1717 LPDIRECTSOUND *ppDS,
1718 IUnknown *pUnkOuter)
1719 {
1720 HRESULT hr;
1721 LPDIRECTSOUND pDS;
1722
1723 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1724
1725 if (ppDS == NULL) {
1726 WARN("invalid parameter: ppDS == NULL\n");
1727 return DSERR_INVALIDPARAM;
1728 }
1729
1730 if (pUnkOuter != NULL) {
1731 WARN("invalid parameter: pUnkOuter != NULL\n");
1732 *ppDS = 0;
1733 return DSERR_INVALIDPARAM;
1734 }
1735
1736 hr = DSOUND_Create(&pDS, pUnkOuter);
1737 if (hr == DS_OK) {
1738 hr = IDirectSound_Initialize(pDS, lpcGUID);
1739 if (hr != DS_OK) {
1740 if (hr != DSERR_ALREADYINITIALIZED) {
1741 IDirectSound_Release(pDS);
1742 pDS = 0;
1743 } else
1744 hr = DS_OK;
1745 }
1746 }
1747
1748 *ppDS = pDS;
1749
1750 return hr;
1751 }
1752
1753 HRESULT WINAPI DSOUND_Create8(
1754 LPDIRECTSOUND8 *ppDS,
1755 IUnknown *pUnkOuter)
1756 {
1757 LPDIRECTSOUND8 pDS;
1758 HRESULT hr;
1759 TRACE("(%p,%p)\n",ppDS,pUnkOuter);
1760
1761 /* Get dsound configuration */
1762 setup_dsound_options();
1763
1764 hr = IDirectSoundImpl_Create(&pDS);
1765 if (hr == DS_OK) {
1766 hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
1767 if (*ppDS)
1768 IDirectSound8_IDirectSound8_AddRef(*ppDS);
1769 else {
1770 WARN("IDirectSound8_IDirectSound8_Create failed\n");
1771 IDirectSound8_Release(pDS);
1772 }
1773 } else {
1774 WARN("IDirectSoundImpl_Create failed\n");
1775 *ppDS = 0;
1776 }
1777
1778 return hr;
1779 }
1780
1781 /*******************************************************************************
1782 * DirectSoundCreate8 (DSOUND.11)
1783 *
1784 * Creates and initializes a DirectSound8 interface.
1785 *
1786 * PARAMS
1787 * lpcGUID [I] Address of the GUID that identifies the sound device.
1788 * ppDS [O] Address of a variable to receive the interface pointer.
1789 * pUnkOuter [I] Must be NULL.
1790 *
1791 * RETURNS
1792 * Success: DS_OK
1793 * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
1794 * DSERR_NODRIVER, DSERR_OUTOFMEMORY
1795 */
1796 HRESULT WINAPI DirectSoundCreate8(
1797 LPCGUID lpcGUID,
1798 LPDIRECTSOUND8 *ppDS,
1799 IUnknown *pUnkOuter)
1800 {
1801 HRESULT hr;
1802 LPDIRECTSOUND8 pDS;
1803
1804 TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
1805
1806 if (ppDS == NULL) {
1807 WARN("invalid parameter: ppDS == NULL\n");
1808 return DSERR_INVALIDPARAM;
1809 }
1810
1811 if (pUnkOuter != NULL) {
1812 WARN("invalid parameter: pUnkOuter != NULL\n");
1813 *ppDS = 0;
1814 return DSERR_INVALIDPARAM;
1815 }
1816
1817 hr = DSOUND_Create8(&pDS, pUnkOuter);
1818 if (hr == DS_OK) {
1819 hr = IDirectSound8_Initialize(pDS, lpcGUID);
1820 if (hr != DS_OK) {
1821 if (hr != DSERR_ALREADYINITIALIZED) {
1822 IDirectSound8_Release(pDS);
1823 pDS = 0;
1824 } else
1825 hr = DS_OK;
1826 }
1827 }
1828
1829 *ppDS = pDS;
1830
1831 return hr;
1832 }
1833
1834 /*
1835 * Add secondary buffer to buffer list.
1836 * Gets exclusive access to buffer for writing.
1837 */
1838 HRESULT DSOUND_AddBuffer(
1839 IDirectSoundImpl * pDS,
1840 IDirectSoundBufferImpl * pDSB)
1841 {
1842 IDirectSoundBufferImpl **newbuffers;
1843 HRESULT hr = DS_OK;
1844
1845 TRACE("(%p, %p)\n", pDS, pDSB);
1846
1847 RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
1848
1849 if (pDS->device->buffers)
1850 newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
1851 else
1852 newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1));
1853
1854 if (newbuffers) {
1855 pDS->device->buffers = newbuffers;
1856 pDS->device->buffers[pDS->device->nrofbuffers] = pDSB;
1857 pDS->device->nrofbuffers++;
1858 TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
1859 } else {
1860 ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->device->nrofbuffers);
1861 hr = DSERR_OUTOFMEMORY;
1862 }
1863
1864 RtlReleaseResource(&(pDS->device->buffer_list_lock));
1865
1866 return hr;
1867 }
1868
1869 /*
1870 * Remove secondary buffer from buffer list.
1871 * Gets exclusive access to buffer for writing.
1872 */
1873 HRESULT DSOUND_RemoveBuffer(
1874 IDirectSoundImpl * pDS,
1875 IDirectSoundBufferImpl * pDSB)
1876 {
1877 int i;
1878 HRESULT hr = DS_OK;
1879
1880 TRACE("(%p, %p)\n", pDS, pDSB);
1881
1882 RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE);
1883
1884 for (i = 0; i < pDS->device->nrofbuffers; i++)
1885 if (pDS->device->buffers[i] == pDSB)
1886 break;
1887
1888 if (i < pDS->device->nrofbuffers) {
1889 /* Put the last buffer of the list in the (now empty) position */
1890 pDS->device->buffers[i] = pDS->device->buffers[pDS->device->nrofbuffers - 1];
1891 pDS->device->nrofbuffers--;
1892 pDS->device->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->device->nrofbuffers);
1893 TRACE("buffer count is now %d\n", pDS->device->nrofbuffers);
1894 }
1895
1896 if (pDS->device->nrofbuffers == 0) {
1897 HeapFree(GetProcessHeap(),0,pDS->device->buffers);
1898 pDS->device->buffers = NULL;
1899 }
1900
1901 RtlReleaseResource(&(pDS->device->buffer_list_lock));
1902
1903 return hr;
1904 }