wined3d: Disable the SWAPEFFECT_DISCARD clear.
[wine] / dlls / 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,%x,%x,%p,%p)\n", This,
680         debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
681         lpDscBufferDesc, lpDsBufferDesc, (DWORD)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 }