1 /* DirectSoundFullDuplex
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
6 * Copyright 2005 Robert Reif
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
34 #include "dsound_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
38 /*****************************************************************************
39 * IDirectSoundFullDuplex implementation structure
41 typedef struct IDirectSoundFullDuplexImpl
43 IUnknown IUnknown_iface
;
44 IDirectSoundFullDuplex IDirectSoundFullDuplex_iface
;
45 LONG ref
, refdsfd
, numIfaces
;
46 IUnknown
*ds8_unk
; /* Aggregated IDirectSound8 */
47 IUnknown
*dsc8_unk
; /* Aggregated IDirectSoundCapture8 */
48 } IDirectSoundFullDuplexImpl
;
50 static void fullduplex_destroy(IDirectSoundFullDuplexImpl
*This
)
53 IDirectSoundCapture8
*dsc8
;
56 IUnknown_QueryInterface(This
->ds8_unk
, &IID_IDirectSound8
, (void**)&ds8
);
57 while(IDirectSound8_Release(ds8
) > 0);
58 IUnknown_Release(This
->ds8_unk
);
61 IUnknown_QueryInterface(This
->dsc8_unk
, &IID_IDirectSoundCapture8
, (void**)&dsc8
);
62 while(IDirectSoundCapture_Release(dsc8
) > 0);
63 IUnknown_Release(This
->dsc8_unk
);
65 HeapFree(GetProcessHeap(), 0, This
);
66 TRACE("(%p) released\n", This
);
69 /*******************************************************************************
70 * IUnknown implementation for DirectSoundFullDuplex
72 static inline IDirectSoundFullDuplexImpl
*impl_from_IUnknown(IUnknown
*iface
)
74 return CONTAINING_RECORD(iface
, IDirectSoundFullDuplexImpl
, IUnknown_iface
);
77 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
79 IDirectSoundFullDuplexImpl
*This
= impl_from_IUnknown(iface
);
81 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
84 WARN("invalid parameter\n");
88 if (IsEqualIID(riid
, &IID_IUnknown
)) {
89 IUnknown_AddRef(&This
->IUnknown_iface
);
90 *ppv
= &This
->IUnknown_iface
;
92 } else if (IsEqualIID(riid
, &IID_IDirectSoundFullDuplex
)) {
93 IDirectSoundFullDuplex_AddRef(&This
->IDirectSoundFullDuplex_iface
);
94 *ppv
= &This
->IDirectSoundFullDuplex_iface
;
96 } else if (This
->ds8_unk
&& (IsEqualIID(riid
, &IID_IDirectSound
) ||
97 IsEqualIID(riid
, &IID_IDirectSound8
)))
98 return IUnknown_QueryInterface(This
->ds8_unk
, riid
, ppv
);
99 else if (This
->dsc8_unk
&& IsEqualIID(riid
, &IID_IDirectSoundCapture
))
100 return IUnknown_QueryInterface(This
->dsc8_unk
, riid
, ppv
);
103 return E_NOINTERFACE
;
106 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
*iface
)
108 IDirectSoundFullDuplexImpl
*This
= impl_from_IUnknown(iface
);
109 ULONG ref
= InterlockedIncrement(&This
->ref
);
111 TRACE("(%p) ref=%d\n", This
, ref
);
114 InterlockedIncrement(&This
->numIfaces
);
118 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
*iface
)
120 IDirectSoundFullDuplexImpl
*This
= impl_from_IUnknown(iface
);
121 ULONG ref
= InterlockedDecrement(&This
->ref
);
123 TRACE("(%p) ref=%d\n", This
, ref
);
125 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
126 fullduplex_destroy(This
);
130 static const IUnknownVtbl unk_vtbl
=
132 IUnknownImpl_QueryInterface
,
137 /***************************************************************************
138 * IDirectSoundFullDuplex implementation
140 static inline IDirectSoundFullDuplexImpl
*impl_from_IDirectSoundFullDuplex(IDirectSoundFullDuplex
*iface
)
142 return CONTAINING_RECORD(iface
, IDirectSoundFullDuplexImpl
, IDirectSoundFullDuplex_iface
);
145 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_QueryInterface(IDirectSoundFullDuplex
*iface
,
146 REFIID riid
, void **ppv
)
148 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
149 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
150 return IUnknown_QueryInterface(&This
->IUnknown_iface
, riid
, ppv
);
153 static ULONG WINAPI
IDirectSoundFullDuplexImpl_AddRef(IDirectSoundFullDuplex
*iface
)
155 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
156 ULONG ref
= InterlockedIncrement(&This
->refdsfd
);
158 TRACE("(%p) ref=%d\n", This
, ref
);
161 InterlockedIncrement(&This
->numIfaces
);
165 static ULONG WINAPI
IDirectSoundFullDuplexImpl_Release(IDirectSoundFullDuplex
*iface
)
167 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
168 ULONG ref
= InterlockedDecrement(&This
->refdsfd
);
170 TRACE("(%p) ref=%d\n", This
, ref
);
172 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
173 fullduplex_destroy(This
);
177 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex
*iface
,
178 const GUID
*capture_dev
, const GUID
*render_dev
, const DSCBUFFERDESC
*cbufdesc
,
179 const DSBUFFERDESC
*bufdesc
, HWND hwnd
, DWORD level
, IDirectSoundCaptureBuffer8
**dscb8
,
180 IDirectSoundBuffer8
**dsb8
)
182 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
183 IDirectSound8
*ds8
= NULL
;
184 IDirectSoundCapture8
*dsc8
= NULL
;
187 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This
, debugstr_guid(capture_dev
),
188 debugstr_guid(render_dev
), cbufdesc
, bufdesc
, hwnd
, level
, dscb8
, dsb8
);
196 if (This
->ds8_unk
|| This
->dsc8_unk
) {
197 WARN("already initialized\n");
198 return DSERR_ALREADYINITIALIZED
;
201 hr
= IDirectSoundImpl_Create(&This
->IUnknown_iface
, &IID_IUnknown
, (void**)&This
->ds8_unk
,
204 IUnknown_QueryInterface(This
->ds8_unk
, &IID_IDirectSound8
, (void**)&ds8
);
205 hr
= IDirectSound_Initialize(ds8
, render_dev
);
208 WARN("Creating/initializing IDirectSound8 failed\n");
212 IDirectSound8_SetCooperativeLevel(ds8
, hwnd
, level
);
214 hr
= IDirectSound8_CreateSoundBuffer(ds8
, bufdesc
, (IDirectSoundBuffer
**)dsb8
, NULL
);
216 WARN("IDirectSoundBuffer_Create() failed\n");
220 hr
= IDirectSoundCaptureImpl_Create(&This
->IUnknown_iface
, &IID_IUnknown
,
221 (void**)&This
->dsc8_unk
, TRUE
);
223 IUnknown_QueryInterface(This
->dsc8_unk
, &IID_IDirectSoundCapture8
, (void**)&dsc8
);
224 hr
= IDirectSoundCapture_Initialize(dsc8
, capture_dev
);
227 WARN("Creating/initializing IDirectSoundCapture8 failed\n");
231 hr
= IDirectSoundCapture_CreateCaptureBuffer(dsc8
, cbufdesc
,
232 (IDirectSoundCaptureBuffer
**)dscb8
, NULL
);
234 WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n");
238 IDirectSound8_Release(ds8
);
239 IDirectSoundCapture_Release(dsc8
);
244 IDirectSoundBuffer8_Release(*dsb8
);
248 IDirectSound8_Release(ds8
);
250 IUnknown_Release(This
->ds8_unk
);
251 This
->ds8_unk
= NULL
;
254 IDirectSoundCaptureBuffer8_Release(*dscb8
);
258 IDirectSoundCapture_Release(dsc8
);
259 if (This
->dsc8_unk
) {
260 IUnknown_Release(This
->dsc8_unk
);
261 This
->dsc8_unk
= NULL
;
266 static const IDirectSoundFullDuplexVtbl dsfd_vtbl
=
268 /* IUnknown methods */
269 IDirectSoundFullDuplexImpl_QueryInterface
,
270 IDirectSoundFullDuplexImpl_AddRef
,
271 IDirectSoundFullDuplexImpl_Release
,
273 /* IDirectSoundFullDuplex methods */
274 IDirectSoundFullDuplexImpl_Initialize
277 HRESULT
DSOUND_FullDuplexCreate(REFIID riid
, void **ppv
)
279 IDirectSoundFullDuplexImpl
*obj
;
282 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
285 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
287 WARN("out of memory\n");
288 return DSERR_OUTOFMEMORY
;
291 setup_dsound_options();
293 obj
->IDirectSoundFullDuplex_iface
.lpVtbl
= &dsfd_vtbl
;
294 obj
->IUnknown_iface
.lpVtbl
= &unk_vtbl
;
299 hr
= IUnknown_QueryInterface(&obj
->IUnknown_iface
, riid
, ppv
);
300 IUnknown_Release(&obj
->IUnknown_iface
);
305 /***************************************************************************
306 * DirectSoundFullDuplexCreate [DSOUND.10]
308 * Create and initialize a DirectSoundFullDuplex interface.
311 * capture_dev [I] Address of sound capture device GUID.
312 * render_dev [I] Address of sound render device GUID.
313 * cbufdesc [I] Address of capture buffer description.
314 * bufdesc [I] Address of render buffer description.
315 * hwnd [I] Handle to application window.
316 * level [I] Cooperative level.
317 * dsfd [O] Address where full duplex interface returned.
318 * dscb8 [0] Address where capture buffer interface returned.
319 * dsb8 [0] Address where render buffer interface returned.
320 * outer_unk [I] Must be NULL.
324 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
325 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
327 HRESULT WINAPI
DirectSoundFullDuplexCreate(const GUID
*capture_dev
, const GUID
*render_dev
,
328 const DSCBUFFERDESC
*cbufdesc
, const DSBUFFERDESC
*bufdesc
, HWND hwnd
, DWORD level
,
329 IDirectSoundFullDuplex
**dsfd
, IDirectSoundCaptureBuffer8
**dscb8
,
330 IDirectSoundBuffer8
**dsb8
, IUnknown
*outer_unk
)
334 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", debugstr_guid(capture_dev
),
335 debugstr_guid(render_dev
), cbufdesc
, bufdesc
, hwnd
, level
, dsfd
, dscb8
, dsb8
,
339 return DSERR_INVALIDPARAM
;
342 return DSERR_NOAGGREGATION
;
345 hr
= DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex
, (void**)dsfd
);
347 hr
= IDirectSoundFullDuplex_Initialize(*dsfd
, capture_dev
, render_dev
, cbufdesc
, bufdesc
,
348 hwnd
, level
, dscb8
, dsb8
);
350 IDirectSoundFullDuplex_Release(*dsfd
);
352 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");