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