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
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
34 #include "wine/debug.h"
36 #include "dsound_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
40 /*****************************************************************************
41 * IDirectSoundFullDuplex implementation structure
43 typedef struct IDirectSoundFullDuplexImpl
45 IUnknown IUnknown_iface;
46 IDirectSoundFullDuplex IDirectSoundFullDuplex_iface;
47 LONG ref, refdsfd, numIfaces;
48 IUnknown *ds8_unk; /* Aggregated IDirectSound8 */
49 IUnknown *dsc8_unk; /* Aggregated IDirectSoundCapture8 */
50 } IDirectSoundFullDuplexImpl;
52 static void fullduplex_destroy(IDirectSoundFullDuplexImpl *This)
55 IDirectSoundCapture8 *dsc8;
58 IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
59 while(IDirectSound8_Release(ds8) > 0);
60 IUnknown_Release(This->ds8_unk);
63 IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8);
64 while(IDirectSoundCapture_Release(dsc8) > 0);
65 IUnknown_Release(This->dsc8_unk);
67 HeapFree(GetProcessHeap(), 0, This);
68 TRACE("(%p) released\n", This);
71 /*******************************************************************************
72 * IUnknown implemetation for DirectSoundFullDuplex
74 static inline IDirectSoundFullDuplexImpl *impl_from_IUnknown(IUnknown *iface)
76 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IUnknown_iface);
79 static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
81 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
82 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
83 return IDirectSoundFullDuplex_QueryInterface(&This->IDirectSoundFullDuplex_iface, riid, ppv);
86 static ULONG WINAPI IUnknownImpl_AddRef(IUnknown *iface)
88 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
89 ULONG ref = InterlockedIncrement(&This->ref);
91 TRACE("(%p) ref=%d\n", This, ref);
94 InterlockedIncrement(&This->numIfaces);
98 static ULONG WINAPI IUnknownImpl_Release(IUnknown *iface)
100 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
101 ULONG ref = InterlockedDecrement(&This->ref);
103 TRACE("(%p) ref=%d\n", This, ref);
105 if (!ref && !InterlockedDecrement(&This->numIfaces))
106 fullduplex_destroy(This);
110 static const IUnknownVtbl unk_vtbl =
112 IUnknownImpl_QueryInterface,
117 /***************************************************************************
118 * IDirectSoundFullDuplex implementation
120 static inline IDirectSoundFullDuplexImpl *impl_from_IDirectSoundFullDuplex(IDirectSoundFullDuplex *iface)
122 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IDirectSoundFullDuplex_iface);
125 static ULONG WINAPI IDirectSoundFullDuplexImpl_AddRef(IDirectSoundFullDuplex *iface)
127 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
128 ULONG ref = InterlockedIncrement(&This->refdsfd);
130 TRACE("(%p) ref=%d\n", This, ref);
133 InterlockedIncrement(&This->numIfaces);
137 static HRESULT WINAPI IDirectSoundFullDuplexImpl_QueryInterface(IDirectSoundFullDuplex *iface,
138 REFIID riid, void **ppv)
140 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
141 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
144 WARN("invalid parameter\n");
150 if (IsEqualIID(riid, &IID_IUnknown)) {
151 IUnknown_AddRef(&This->IUnknown_iface);
152 *ppv = &This->IUnknown_iface;
154 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
155 IDirectSoundFullDuplexImpl_AddRef(iface);
156 *ppv = &This->IDirectSoundFullDuplex_iface;
158 } else if (This->ds8_unk && (IsEqualIID(riid, &IID_IDirectSound) ||
159 IsEqualIID(riid, &IID_IDirectSound8))) {
160 return IUnknown_QueryInterface(This->ds8_unk, riid, ppv);
161 } else if (This->dsc8_unk && IsEqualIID(riid, &IID_IDirectSoundCapture)) {
162 return IUnknown_QueryInterface(This->dsc8_unk, riid, ppv);
165 return E_NOINTERFACE;
168 static ULONG WINAPI IDirectSoundFullDuplexImpl_Release(IDirectSoundFullDuplex *iface)
170 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
171 ULONG ref = InterlockedDecrement(&This->refdsfd);
173 TRACE("(%p) ref=%d\n", This, ref);
175 if (!ref && !InterlockedDecrement(&This->numIfaces))
176 fullduplex_destroy(This);
180 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex *iface,
181 const GUID *capture_dev, const GUID *render_dev, const DSCBUFFERDESC *cbufdesc,
182 const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level, IDirectSoundCaptureBuffer8 **dscb8,
183 IDirectSoundBuffer8 **dsb8)
185 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
186 IDirectSound8 *ds8 = NULL;
187 IDirectSoundCapture8 *dsc8 = NULL;
190 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, debugstr_guid(capture_dev),
191 debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dscb8, dsb8);
199 if (This->ds8_unk || This->dsc8_unk) {
200 WARN("already initialized\n");
201 return DSERR_ALREADYINITIALIZED;
204 hr = IDirectSoundImpl_Create(&This->IUnknown_iface, &IID_IUnknown, (void**)&This->ds8_unk,
207 IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
208 hr = IDirectSound_Initialize(ds8, render_dev);
211 WARN("Creating/initializing IDirectSound8 failed\n");
215 IDirectSound8_SetCooperativeLevel(ds8, hwnd, level);
217 hr = IDirectSound8_CreateSoundBuffer(ds8, bufdesc, (IDirectSoundBuffer**)dsb8, NULL);
219 WARN("IDirectSoundBuffer_Create() failed\n");
223 hr = IDirectSoundCaptureImpl_Create(&This->IUnknown_iface, &IID_IUnknown,
224 (void**)&This->dsc8_unk, TRUE);
226 IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8);
227 hr = IDirectSoundCapture_Initialize(dsc8, capture_dev);
230 WARN("Creating/initializing IDirectSoundCapture8 failed\n");
234 hr = IDirectSoundCapture_CreateCaptureBuffer(dsc8, cbufdesc,
235 (IDirectSoundCaptureBuffer**)dscb8, NULL);
237 WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n");
241 IDirectSound8_Release(ds8);
242 IDirectSoundCapture_Release(dsc8);
247 IDirectSoundBuffer8_Release(*dsb8);
251 IDirectSound8_Release(ds8);
253 IUnknown_Release(This->ds8_unk);
254 This->ds8_unk = NULL;
257 IDirectSoundCaptureBuffer8_Release(*dscb8);
261 IDirectSoundCapture_Release(dsc8);
262 if (This->dsc8_unk) {
263 IUnknown_Release(This->dsc8_unk);
264 This->dsc8_unk = NULL;
269 static const IDirectSoundFullDuplexVtbl dsfd_vtbl =
271 /* IUnknown methods */
272 IDirectSoundFullDuplexImpl_QueryInterface,
273 IDirectSoundFullDuplexImpl_AddRef,
274 IDirectSoundFullDuplexImpl_Release,
276 /* IDirectSoundFullDuplex methods */
277 IDirectSoundFullDuplexImpl_Initialize
280 HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv)
282 IDirectSoundFullDuplexImpl *obj;
285 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
288 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
290 WARN("out of memory\n");
291 return DSERR_OUTOFMEMORY;
294 setup_dsound_options();
296 obj->IDirectSoundFullDuplex_iface.lpVtbl = &dsfd_vtbl;
297 obj->IUnknown_iface.lpVtbl = &unk_vtbl;
302 hr = IUnknown_QueryInterface(&obj->IUnknown_iface, riid, ppv);
303 IUnknown_Release(&obj->IUnknown_iface);
308 /***************************************************************************
309 * DirectSoundFullDuplexCreate [DSOUND.10]
311 * Create and initialize a DirectSoundFullDuplex interface.
314 * capture_dev [I] Address of sound capture device GUID.
315 * render_dev [I] Address of sound render device GUID.
316 * cbufdesc [I] Address of capture buffer description.
317 * bufdesc [I] Address of render buffer description.
318 * hwnd [I] Handle to application window.
319 * level [I] Cooperative level.
320 * dsfd [O] Address where full duplex interface returned.
321 * dscb8 [0] Address where capture buffer interface returned.
322 * dsb8 [0] Address where render buffer interface returned.
323 * outer_unk [I] Must be NULL.
327 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
328 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
330 HRESULT WINAPI DirectSoundFullDuplexCreate(const GUID *capture_dev, const GUID *render_dev,
331 const DSCBUFFERDESC *cbufdesc, const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level,
332 IDirectSoundFullDuplex **dsfd, IDirectSoundCaptureBuffer8 **dscb8,
333 IDirectSoundBuffer8 **dsb8, IUnknown *outer_unk)
337 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", debugstr_guid(capture_dev),
338 debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dsfd, dscb8, dsb8,
342 return DSERR_INVALIDPARAM;
345 return DSERR_NOAGGREGATION;
348 hr = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (void**)dsfd);
350 hr = IDirectSoundFullDuplex_Initialize(*dsfd, capture_dev, render_dev, cbufdesc, bufdesc,
351 hwnd, level, dscb8, dsb8);
353 IDirectSoundFullDuplex_Release(*dsfd);
355 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");