Sync with trunk (r48144)
[reactos.git] / dll / directx / dsound / duplex.c
1 /* DirectSoundFullDuplex
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
6 * Copyright 2005 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
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "mmsystem.h"
31 #include "mmddk.h"
32 #include "winternl.h"
33 #include "wine/debug.h"
34 #include "dsound.h"
35 #include "dsdriver.h"
36 #include "dsound_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
39
40 /*******************************************************************************
41 * IUnknown
42 */
43 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
44 LPUNKNOWN iface,
45 REFIID riid,
46 LPVOID * ppobj)
47 {
48 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
49 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
50 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
51 }
52
53 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
54 LPUNKNOWN iface)
55 {
56 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
57 ULONG ref = InterlockedIncrement(&(This->ref));
58 TRACE("(%p) ref was %d\n", This, ref - 1);
59 return ref;
60 }
61
62 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
63 LPUNKNOWN iface)
64 {
65 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
66 ULONG ref = InterlockedDecrement(&(This->ref));
67 TRACE("(%p) ref was %d\n", This, ref + 1);
68 if (!ref) {
69 IDirectSound_Release(This->pdsfd->pUnknown);
70 HeapFree(GetProcessHeap(), 0, This);
71 TRACE("(%p) released\n", This);
72 }
73 return ref;
74 }
75
76 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
77 {
78 IDirectSoundFullDuplex_IUnknown_QueryInterface,
79 IDirectSoundFullDuplex_IUnknown_AddRef,
80 IDirectSoundFullDuplex_IUnknown_Release
81 };
82
83 static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
84 LPDIRECTSOUNDFULLDUPLEX pdsfd,
85 LPUNKNOWN * ppunk)
86 {
87 IDirectSoundFullDuplex_IUnknown * pdsfdunk;
88 TRACE("(%p,%p)\n",pdsfd,ppunk);
89
90 if (pdsfd == NULL) {
91 ERR("invalid parameter: pdsfd == NULL\n");
92 return DSERR_INVALIDPARAM;
93 }
94
95 if (ppunk == NULL) {
96 ERR("invalid parameter: ppunk == NULL\n");
97 return DSERR_INVALIDPARAM;
98 }
99
100 pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
101 if (pdsfdunk == NULL) {
102 WARN("out of memory\n");
103 *ppunk = NULL;
104 return DSERR_OUTOFMEMORY;
105 }
106
107 pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
108 pdsfdunk->ref = 0;
109 pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
110
111 *ppunk = (LPUNKNOWN)pdsfdunk;
112
113 return DS_OK;
114 }
115
116 /*******************************************************************************
117 * IDirectSoundFullDuplex_IDirectSound
118 */
119 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_QueryInterface(
120 LPDIRECTSOUND iface,
121 REFIID riid,
122 LPVOID * ppobj)
123 {
124 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
125 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
126 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
127 }
128
129 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_AddRef(
130 LPDIRECTSOUND iface)
131 {
132 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
133 ULONG ref = InterlockedIncrement(&(This->ref));
134 TRACE("(%p) ref was %d\n", This, ref - 1);
135 return ref;
136 }
137
138 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_Release(
139 LPDIRECTSOUND iface)
140 {
141 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
142 ULONG ref = InterlockedDecrement(&(This->ref));
143 TRACE("(%p) ref was %d\n", This, ref + 1);
144 if (!ref) {
145 IDirectSound_Release(This->pdsfd->pDS);
146 HeapFree(GetProcessHeap(), 0, This);
147 TRACE("(%p) released\n", This);
148 }
149 return ref;
150 }
151
152 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer(
153 LPDIRECTSOUND iface,
154 LPCDSBUFFERDESC dsbd,
155 LPLPDIRECTSOUNDBUFFER ppdsb,
156 LPUNKNOWN lpunk)
157 {
158 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
159 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
160 return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,FALSE);
161 }
162
163 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetCaps(
164 LPDIRECTSOUND iface,
165 LPDSCAPS lpDSCaps)
166 {
167 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
168 TRACE("(%p,%p)\n",This,lpDSCaps);
169 return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
170 }
171
172 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer(
173 LPDIRECTSOUND iface,
174 LPDIRECTSOUNDBUFFER psb,
175 LPLPDIRECTSOUNDBUFFER ppdsb)
176 {
177 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
178 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
179 return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
180 }
181
182 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel(
183 LPDIRECTSOUND iface,
184 HWND hwnd,
185 DWORD level)
186 {
187 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
188 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
189 return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
190 }
191
192 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Compact(
193 LPDIRECTSOUND iface)
194 {
195 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
196 TRACE("(%p)\n", This);
197 return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
198 }
199
200 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig(
201 LPDIRECTSOUND iface,
202 LPDWORD lpdwSpeakerConfig)
203 {
204 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
205 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
206 return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
207 }
208
209 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig(
210 LPDIRECTSOUND iface,
211 DWORD config)
212 {
213 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
214 TRACE("(%p,0x%08x)\n",This,config);
215 return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
216 }
217
218 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Initialize(
219 LPDIRECTSOUND iface,
220 LPCGUID lpcGuid)
221 {
222 IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface;
223 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
224 return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
225 }
226
227 static const IDirectSoundVtbl DirectSoundFullDuplex_DirectSound_Vtbl =
228 {
229 IDirectSoundFullDuplex_IDirectSound_QueryInterface,
230 IDirectSoundFullDuplex_IDirectSound_AddRef,
231 IDirectSoundFullDuplex_IDirectSound_Release,
232 IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer,
233 IDirectSoundFullDuplex_IDirectSound_GetCaps,
234 IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer,
235 IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel,
236 IDirectSoundFullDuplex_IDirectSound_Compact,
237 IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig,
238 IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig,
239 IDirectSoundFullDuplex_IDirectSound_Initialize
240 };
241
242 static HRESULT IDirectSoundFullDuplex_IDirectSound_Create(
243 LPDIRECTSOUNDFULLDUPLEX pdsfd,
244 LPDIRECTSOUND * ppds)
245 {
246 IDirectSoundFullDuplex_IDirectSound * pdsfdds;
247 TRACE("(%p,%p)\n",pdsfd,ppds);
248
249 if (pdsfd == NULL) {
250 ERR("invalid parameter: pdsfd == NULL\n");
251 return DSERR_INVALIDPARAM;
252 }
253
254 if (ppds == NULL) {
255 ERR("invalid parameter: ppds == NULL\n");
256 return DSERR_INVALIDPARAM;
257 }
258
259 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
260 WARN("not initialized\n");
261 *ppds = NULL;
262 return DSERR_UNINITIALIZED;
263 }
264
265 pdsfdds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds));
266 if (pdsfdds == NULL) {
267 WARN("out of memory\n");
268 *ppds = NULL;
269 return DSERR_OUTOFMEMORY;
270 }
271
272 pdsfdds->lpVtbl = &DirectSoundFullDuplex_DirectSound_Vtbl;
273 pdsfdds->ref = 0;
274 pdsfdds->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
275
276 *ppds = (LPDIRECTSOUND)pdsfdds;
277
278 return DS_OK;
279 }
280
281 /*******************************************************************************
282 * IDirectSoundFullDuplex_IDirectSound8
283 */
284 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
285 LPDIRECTSOUND8 iface,
286 REFIID riid,
287 LPVOID * ppobj)
288 {
289 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
290 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
291 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
292 }
293
294 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
295 LPDIRECTSOUND8 iface)
296 {
297 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
298 ULONG ref = InterlockedIncrement(&(This->ref));
299 TRACE("(%p) ref was %d\n", This, ref - 1);
300 return ref;
301 }
302
303 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
304 LPDIRECTSOUND8 iface)
305 {
306 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
307 ULONG ref = InterlockedDecrement(&(This->ref));
308 TRACE("(%p) ref was %d\n", This, ref + 1);
309 if (!ref) {
310 IDirectSound_Release(This->pdsfd->pDS8);
311 HeapFree(GetProcessHeap(), 0, This);
312 TRACE("(%p) released\n", This);
313 }
314 return ref;
315 }
316
317 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
318 LPDIRECTSOUND8 iface,
319 LPCDSBUFFERDESC dsbd,
320 LPLPDIRECTSOUNDBUFFER ppdsb,
321 LPUNKNOWN lpunk)
322 {
323 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
324 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
325 return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,TRUE);
326 }
327
328 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
329 LPDIRECTSOUND8 iface,
330 LPDSCAPS lpDSCaps)
331 {
332 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
333 TRACE("(%p,%p)\n",This,lpDSCaps);
334 return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
335 }
336
337 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
338 LPDIRECTSOUND8 iface,
339 LPDIRECTSOUNDBUFFER psb,
340 LPLPDIRECTSOUNDBUFFER ppdsb)
341 {
342 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
343 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
344 return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
345 }
346
347 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
348 LPDIRECTSOUND8 iface,
349 HWND hwnd,
350 DWORD level)
351 {
352 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
353 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
354 return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
355 }
356
357 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
358 LPDIRECTSOUND8 iface)
359 {
360 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
361 TRACE("(%p)\n", This);
362 return DirectSoundDevice_Compact(This->pdsfd->renderer_device);
363 }
364
365 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
366 LPDIRECTSOUND8 iface,
367 LPDWORD lpdwSpeakerConfig)
368 {
369 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
370 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
371 return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
372 }
373
374 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
375 LPDIRECTSOUND8 iface,
376 DWORD config)
377 {
378 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
379 TRACE("(%p,0x%08x)\n",This,config);
380 return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config);
381 }
382
383 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
384 LPDIRECTSOUND8 iface,
385 LPCGUID lpcGuid)
386 {
387 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
388 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
389 return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid);
390 }
391
392 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
393 {
394 IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
395 IDirectSoundFullDuplex_IDirectSound8_AddRef,
396 IDirectSoundFullDuplex_IDirectSound8_Release,
397 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
398 IDirectSoundFullDuplex_IDirectSound8_GetCaps,
399 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
400 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
401 IDirectSoundFullDuplex_IDirectSound8_Compact,
402 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
403 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
404 IDirectSoundFullDuplex_IDirectSound8_Initialize
405 };
406
407 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
408 LPDIRECTSOUNDFULLDUPLEX pdsfd,
409 LPDIRECTSOUND8 * ppds8)
410 {
411 IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
412 TRACE("(%p,%p)\n",pdsfd,ppds8);
413
414 if (pdsfd == NULL) {
415 ERR("invalid parameter: pdsfd == NULL\n");
416 return DSERR_INVALIDPARAM;
417 }
418
419 if (ppds8 == NULL) {
420 ERR("invalid parameter: ppds8 == NULL\n");
421 return DSERR_INVALIDPARAM;
422 }
423
424 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
425 WARN("not initialized\n");
426 *ppds8 = NULL;
427 return DSERR_UNINITIALIZED;
428 }
429
430 pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
431 if (pdsfdds8 == NULL) {
432 WARN("out of memory\n");
433 *ppds8 = NULL;
434 return DSERR_OUTOFMEMORY;
435 }
436
437 pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
438 pdsfdds8->ref = 0;
439 pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
440
441 *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
442
443 return DS_OK;
444 }
445
446 /*******************************************************************************
447 * IDirectSoundFullDuplex_IDirectSoundCapture
448 */
449 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
450 LPDIRECTSOUNDCAPTURE iface,
451 REFIID riid,
452 LPVOID * ppobj)
453 {
454 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
455 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
456 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
457 }
458
459 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
460 LPDIRECTSOUNDCAPTURE iface)
461 {
462 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
463 ULONG ref = InterlockedIncrement(&(This->ref));
464 TRACE("(%p) ref was %d\n", This, ref - 1);
465 return ref;
466 }
467
468 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
469 LPDIRECTSOUNDCAPTURE iface)
470 {
471 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
472 ULONG ref = InterlockedDecrement(&(This->ref));
473 TRACE("(%p) ref was %d\n", This, ref + 1);
474 if (!ref) {
475 IDirectSoundCapture_Release(This->pdsfd->pDSC);
476 HeapFree(GetProcessHeap(), 0, This);
477 TRACE("(%p) released\n", This);
478 }
479 return ref;
480 }
481
482 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
483 LPDIRECTSOUNDCAPTURE iface,
484 LPCDSCBUFFERDESC lpcDSCBufferDesc,
485 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
486 LPUNKNOWN pUnk)
487 {
488 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
489 TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
490 return IDirectSoundCaptureImpl_CreateCaptureBuffer(This->pdsfd->pDSC,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
491 }
492
493 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
494 LPDIRECTSOUNDCAPTURE iface,
495 LPDSCCAPS lpDSCCaps)
496 {
497 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
498 TRACE("(%p,%p)\n",This,lpDSCCaps);
499 return IDirectSoundCaptureImpl_GetCaps(This->pdsfd->pDSC, lpDSCCaps);
500 }
501
502 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
503 LPDIRECTSOUNDCAPTURE iface,
504 LPCGUID lpcGUID)
505 {
506 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
507 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
508 return IDirectSoundCaptureImpl_Initialize(This->pdsfd->pDSC,lpcGUID);
509 }
510
511 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
512 {
513 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
514 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
515 IDirectSoundFullDuplex_IDirectSoundCapture_Release,
516 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
517 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
518 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
519 };
520
521 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
522 LPDIRECTSOUNDFULLDUPLEX pdsfd,
523 LPDIRECTSOUNDCAPTURE8 * ppdsc8)
524 {
525 IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
526 TRACE("(%p,%p)\n",pdsfd,ppdsc8);
527
528 if (pdsfd == NULL) {
529 ERR("invalid parameter: pdsfd == NULL\n");
530 return DSERR_INVALIDPARAM;
531 }
532
533 if (ppdsc8 == NULL) {
534 ERR("invalid parameter: ppdsc8 == NULL\n");
535 return DSERR_INVALIDPARAM;
536 }
537
538 if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
539 WARN("not initialized\n");
540 *ppdsc8 = NULL;
541 return DSERR_UNINITIALIZED;
542 }
543
544 pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
545 if (pdsfddsc == NULL) {
546 WARN("out of memory\n");
547 *ppdsc8 = NULL;
548 return DSERR_OUTOFMEMORY;
549 }
550
551 pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
552 pdsfddsc->ref = 0;
553 pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
554
555 *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
556
557 return DS_OK;
558 }
559
560 /***************************************************************************
561 * IDirectSoundFullDuplexImpl
562 */
563 static ULONG WINAPI
564 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
565 {
566 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
567 ULONG ref = InterlockedIncrement(&(This->ref));
568 TRACE("(%p) ref was %d\n", This, ref - 1);
569 return ref;
570 }
571
572 static HRESULT WINAPI
573 IDirectSoundFullDuplexImpl_QueryInterface(
574 LPDIRECTSOUNDFULLDUPLEX iface,
575 REFIID riid,
576 LPVOID* ppobj )
577 {
578 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
579 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
580
581 if (ppobj == NULL) {
582 WARN("invalid parameter\n");
583 return E_INVALIDARG;
584 }
585
586 *ppobj = NULL;
587
588 if (IsEqualIID(riid, &IID_IUnknown)) {
589 if (!This->pUnknown) {
590 IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
591 if (!This->pUnknown) {
592 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
593 *ppobj = NULL;
594 return E_NOINTERFACE;
595 }
596 }
597 IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
598 *ppobj = This->pUnknown;
599 return S_OK;
600 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
601 IDirectSoundFullDuplexImpl_AddRef(iface);
602 *ppobj = This;
603 return S_OK;
604 } else if (IsEqualIID(riid, &IID_IDirectSound)) {
605 if (!This->pDS) {
606 IDirectSoundFullDuplex_IDirectSound_Create(iface, &This->pDS);
607 if (!This->pDS) {
608 WARN("IDirectSoundFullDuplex_IDirectSound_Create() failed\n");
609 *ppobj = NULL;
610 return E_NOINTERFACE;
611 }
612 }
613 IDirectSoundFullDuplex_IDirectSound_AddRef(This->pDS);
614 *ppobj = This->pDS;
615 return S_OK;
616 } else if (IsEqualIID(riid, &IID_IDirectSound8)) {
617 if (!This->pDS8) {
618 IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
619 if (!This->pDS8) {
620 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
621 *ppobj = NULL;
622 return E_NOINTERFACE;
623 }
624 }
625 IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
626 *ppobj = This->pDS8;
627 return S_OK;
628 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
629 if (!This->pDSC) {
630 IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
631 if (!This->pDSC) {
632 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
633 *ppobj = NULL;
634 return E_NOINTERFACE;
635 }
636 }
637 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
638 *ppobj = This->pDSC;
639 return S_OK;
640 }
641
642 return E_NOINTERFACE;
643 }
644
645 static ULONG WINAPI
646 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
647 {
648 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
649 ULONG ref = InterlockedDecrement(&(This->ref));
650 TRACE("(%p) ref was %d\n", This, ref - 1);
651
652 if (!ref) {
653 if (This->capture_device)
654 DirectSoundCaptureDevice_Release(This->capture_device);
655 if (This->renderer_device)
656 DirectSoundDevice_Release(This->renderer_device);
657 HeapFree( GetProcessHeap(), 0, This );
658 TRACE("(%p) released\n", This);
659 }
660 return ref;
661 }
662
663 static HRESULT WINAPI
664 IDirectSoundFullDuplexImpl_Initialize(
665 LPDIRECTSOUNDFULLDUPLEX iface,
666 LPCGUID pCaptureGuid,
667 LPCGUID pRendererGuid,
668 LPCDSCBUFFERDESC lpDscBufferDesc,
669 LPCDSBUFFERDESC lpDsBufferDesc,
670 HWND hWnd,
671 DWORD dwLevel,
672 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
673 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
674 {
675 HRESULT hr;
676 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
677 IDirectSoundBufferImpl * dsb;
678
679 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This,
680 debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
681 lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
682 lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
683
684 if (This->renderer_device != NULL || This->capture_device != NULL) {
685 WARN("already initialized\n");
686 *lplpDirectSoundCaptureBuffer8 = NULL;
687 *lplpDirectSoundBuffer8 = NULL;
688 return DSERR_ALREADYINITIALIZED;
689 }
690
691 hr = DirectSoundDevice_Initialize(&This->renderer_device, pRendererGuid);
692 if (hr != DS_OK) {
693 WARN("DirectSoundDevice_Initialize() failed\n");
694 *lplpDirectSoundCaptureBuffer8 = NULL;
695 *lplpDirectSoundBuffer8 = NULL;
696 return hr;
697 }
698
699 if (dwLevel==DSSCL_PRIORITY || dwLevel==DSSCL_EXCLUSIVE) {
700 WARN("level=%s not fully supported\n",
701 dwLevel==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
702 }
703 This->renderer_device->priolevel = dwLevel;
704
705 hr = DSOUND_PrimarySetFormat(This->renderer_device, lpDsBufferDesc->lpwfxFormat, dwLevel == DSSCL_EXCLUSIVE);
706 if (hr != DS_OK) {
707 WARN("DSOUND_PrimarySetFormat() failed\n");
708 *lplpDirectSoundCaptureBuffer8 = NULL;
709 *lplpDirectSoundBuffer8 = NULL;
710 return hr;
711 }
712 hr = IDirectSoundBufferImpl_Create(This->renderer_device, &dsb, lpDsBufferDesc);
713 if (hr != DS_OK) {
714 WARN("IDirectSoundBufferImpl_Create() failed\n");
715 *lplpDirectSoundCaptureBuffer8 = NULL;
716 *lplpDirectSoundBuffer8 = NULL;
717 return hr;
718 }
719
720 hr = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl **)lplpDirectSoundBuffer8);
721 if (hr != DS_OK) {
722 WARN("SecondaryBufferImpl_Create() failed\n");
723 *lplpDirectSoundCaptureBuffer8 = NULL;
724 *lplpDirectSoundBuffer8 = NULL;
725 return hr;
726 }
727 IDirectSoundBuffer8_AddRef(*lplpDirectSoundBuffer8);
728
729 hr = DirectSoundCaptureDevice_Initialize(&This->capture_device, pCaptureGuid);
730 if (hr != DS_OK) {
731 WARN("DirectSoundCaptureDevice_Initialize() failed\n");
732 *lplpDirectSoundCaptureBuffer8 = NULL;
733 *lplpDirectSoundBuffer8 = NULL;
734 return hr;
735 }
736
737 hr = IDirectSoundCaptureBufferImpl_Create(This->capture_device,
738 (IDirectSoundCaptureBufferImpl **)lplpDirectSoundCaptureBuffer8,
739 lpDscBufferDesc);
740 if (hr != DS_OK) {
741 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
742 *lplpDirectSoundCaptureBuffer8 = NULL;
743 *lplpDirectSoundBuffer8 = NULL;
744 return hr;
745 }
746
747 return hr;
748 }
749
750 static const IDirectSoundFullDuplexVtbl dsfdvt =
751 {
752 /* IUnknown methods */
753 IDirectSoundFullDuplexImpl_QueryInterface,
754 IDirectSoundFullDuplexImpl_AddRef,
755 IDirectSoundFullDuplexImpl_Release,
756
757 /* IDirectSoundFullDuplex methods */
758 IDirectSoundFullDuplexImpl_Initialize
759 };
760
761 HRESULT DSOUND_FullDuplexCreate(
762 REFIID riid,
763 LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
764 {
765 IDirectSoundFullDuplexImpl *This = NULL;
766 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
767
768 if (ppDSFD == NULL) {
769 WARN("invalid parameter: ppDSFD == NULL\n");
770 return DSERR_INVALIDPARAM;
771 }
772
773 if (!IsEqualIID(riid, &IID_IUnknown) &&
774 !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
775 *ppDSFD = 0;
776 return E_NOINTERFACE;
777 }
778
779 /* Get dsound configuration */
780 setup_dsound_options();
781
782 This = HeapAlloc(GetProcessHeap(),
783 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
784
785 if (This == NULL) {
786 WARN("out of memory\n");
787 *ppDSFD = NULL;
788 return DSERR_OUTOFMEMORY;
789 }
790
791 This->lpVtbl = &dsfdvt;
792 This->ref = 1;
793 This->capture_device = NULL;
794 This->renderer_device = NULL;
795
796 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
797
798 return DS_OK;
799 }
800
801 /***************************************************************************
802 * DirectSoundFullDuplexCreate [DSOUND.10]
803 *
804 * Create and initialize a DirectSoundFullDuplex interface.
805 *
806 * PARAMS
807 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
808 * pcGuidRenderDevice [I] Address of sound render device GUID.
809 * pcDSCBufferDesc [I] Address of capture buffer description.
810 * pcDSBufferDesc [I] Address of render buffer description.
811 * hWnd [I] Handle to application window.
812 * dwLevel [I] Cooperative level.
813 * ppDSFD [O] Address where full duplex interface returned.
814 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
815 * ppDSBuffer8 [0] Address where render buffer interface returned.
816 * pUnkOuter [I] Must be NULL.
817 *
818 * RETURNS
819 * Success: DS_OK
820 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
821 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
822 */
823 HRESULT WINAPI
824 DirectSoundFullDuplexCreate(
825 LPCGUID pcGuidCaptureDevice,
826 LPCGUID pcGuidRenderDevice,
827 LPCDSCBUFFERDESC pcDSCBufferDesc,
828 LPCDSBUFFERDESC pcDSBufferDesc,
829 HWND hWnd,
830 DWORD dwLevel,
831 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
832 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
833 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
834 LPUNKNOWN pUnkOuter)
835 {
836 HRESULT hres;
837 IDirectSoundFullDuplexImpl *This = NULL;
838 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
839 debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
840 pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
841 ppDSBuffer8, pUnkOuter);
842
843 if (pUnkOuter) {
844 WARN("pUnkOuter != 0\n");
845 *ppDSFD = NULL;
846 return DSERR_NOAGGREGATION;
847 }
848
849 if (pcDSCBufferDesc == NULL) {
850 WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
851 *ppDSFD = NULL;
852 return DSERR_INVALIDPARAM;
853 }
854
855 if (pcDSBufferDesc == NULL) {
856 WARN("invalid parameter: pcDSBufferDesc == NULL\n");
857 *ppDSFD = NULL;
858 return DSERR_INVALIDPARAM;
859 }
860
861 if (ppDSFD == NULL) {
862 WARN("invalid parameter: ppDSFD == NULL\n");
863 return DSERR_INVALIDPARAM;
864 }
865
866 if (ppDSCBuffer8 == NULL) {
867 WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
868 *ppDSFD = NULL;
869 return DSERR_INVALIDPARAM;
870 }
871
872 if (ppDSBuffer8 == NULL) {
873 WARN("invalid parameter: ppDSBuffer8 == NULL\n");
874 *ppDSFD = NULL;
875 return DSERR_INVALIDPARAM;
876 }
877
878 /* Get dsound configuration */
879 setup_dsound_options();
880
881 This = HeapAlloc(GetProcessHeap(),
882 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
883
884 if (This == NULL) {
885 WARN("out of memory\n");
886 *ppDSFD = NULL;
887 return DSERR_OUTOFMEMORY;
888 }
889
890 This->lpVtbl = &dsfdvt;
891 This->ref = 1;
892 This->capture_device = NULL;
893 This->renderer_device = NULL;
894
895 hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
896 pcGuidCaptureDevice,
897 pcGuidRenderDevice,
898 pcDSCBufferDesc,
899 pcDSBufferDesc,
900 hWnd, dwLevel, ppDSCBuffer8,
901 ppDSBuffer8);
902 if (hres != DS_OK) {
903 HeapFree(GetProcessHeap(), 0, This);
904 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
905 *ppDSFD = NULL;
906 } else
907 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
908
909 return hres;
910 }