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);
83 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
86 WARN("invalid parameter\n");
90 if (IsEqualIID(riid, &IID_IUnknown)) {
91 IUnknown_AddRef(&This->IUnknown_iface);
92 *ppv = &This->IUnknown_iface;
94 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
95 IDirectSoundFullDuplex_AddRef(&This->IDirectSoundFullDuplex_iface);
96 *ppv = &This->IDirectSoundFullDuplex_iface;
98 } else if (This->ds8_unk && (IsEqualIID(riid, &IID_IDirectSound) ||
99 IsEqualIID(riid, &IID_IDirectSound8)))
100 return IUnknown_QueryInterface(This->ds8_unk, riid, ppv);
101 else if (This->dsc8_unk && IsEqualIID(riid, &IID_IDirectSoundCapture))
102 return IUnknown_QueryInterface(This->dsc8_unk, riid, ppv);
105 return E_NOINTERFACE;
108 static ULONG WINAPI IUnknownImpl_AddRef(IUnknown *iface)
110 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
111 ULONG ref = InterlockedIncrement(&This->ref);
113 TRACE("(%p) ref=%d\n", This, ref);
116 InterlockedIncrement(&This->numIfaces);
120 static ULONG WINAPI IUnknownImpl_Release(IUnknown *iface)
122 IDirectSoundFullDuplexImpl *This = impl_from_IUnknown(iface);
123 ULONG ref = InterlockedDecrement(&This->ref);
125 TRACE("(%p) ref=%d\n", This, ref);
127 if (!ref && !InterlockedDecrement(&This->numIfaces))
128 fullduplex_destroy(This);
132 static const IUnknownVtbl unk_vtbl =
134 IUnknownImpl_QueryInterface,
139 /***************************************************************************
140 * IDirectSoundFullDuplex implementation
142 static inline IDirectSoundFullDuplexImpl *impl_from_IDirectSoundFullDuplex(IDirectSoundFullDuplex *iface)
144 return CONTAINING_RECORD(iface, IDirectSoundFullDuplexImpl, IDirectSoundFullDuplex_iface);
147 static HRESULT WINAPI IDirectSoundFullDuplexImpl_QueryInterface(IDirectSoundFullDuplex *iface,
148 REFIID riid, void **ppv)
150 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
151 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
152 return IUnknown_QueryInterface(&This->IUnknown_iface, riid, ppv);
155 static ULONG WINAPI IDirectSoundFullDuplexImpl_AddRef(IDirectSoundFullDuplex *iface)
157 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
158 ULONG ref = InterlockedIncrement(&This->refdsfd);
160 TRACE("(%p) ref=%d\n", This, ref);
163 InterlockedIncrement(&This->numIfaces);
167 static ULONG WINAPI IDirectSoundFullDuplexImpl_Release(IDirectSoundFullDuplex *iface)
169 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
170 ULONG ref = InterlockedDecrement(&This->refdsfd);
172 TRACE("(%p) ref=%d\n", This, ref);
174 if (!ref && !InterlockedDecrement(&This->numIfaces))
175 fullduplex_destroy(This);
179 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex *iface,
180 const GUID *capture_dev, const GUID *render_dev, const DSCBUFFERDESC *cbufdesc,
181 const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level, IDirectSoundCaptureBuffer8 **dscb8,
182 IDirectSoundBuffer8 **dsb8)
184 IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface);
185 IDirectSound8 *ds8 = NULL;
186 IDirectSoundCapture8 *dsc8 = NULL;
189 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, debugstr_guid(capture_dev),
190 debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dscb8, dsb8);
198 if (This->ds8_unk || This->dsc8_unk) {
199 WARN("already initialized\n");
200 return DSERR_ALREADYINITIALIZED;
203 hr = IDirectSoundImpl_Create(&This->IUnknown_iface, &IID_IUnknown, (void**)&This->ds8_unk,
206 IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
207 hr = IDirectSound_Initialize(ds8, render_dev);
210 WARN("Creating/initializing IDirectSound8 failed\n");
214 IDirectSound8_SetCooperativeLevel(ds8, hwnd, level);
216 hr = IDirectSound8_CreateSoundBuffer(ds8, bufdesc, (IDirectSoundBuffer**)dsb8, NULL);
218 WARN("IDirectSoundBuffer_Create() failed\n");
222 hr = IDirectSoundCaptureImpl_Create(&This->IUnknown_iface, &IID_IUnknown,
223 (void**)&This->dsc8_unk, TRUE);
225 IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8);
226 hr = IDirectSoundCapture_Initialize(dsc8, capture_dev);
229 WARN("Creating/initializing IDirectSoundCapture8 failed\n");
233 hr = IDirectSoundCapture_CreateCaptureBuffer(dsc8, cbufdesc,
234 (IDirectSoundCaptureBuffer**)dscb8, NULL);
236 WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n");
240 IDirectSound8_Release(ds8);
241 IDirectSoundCapture_Release(dsc8);
246 IDirectSoundBuffer8_Release(*dsb8);
250 IDirectSound8_Release(ds8);
252 IUnknown_Release(This->ds8_unk);
253 This->ds8_unk = NULL;
256 IDirectSoundCaptureBuffer8_Release(*dscb8);
260 IDirectSoundCapture_Release(dsc8);
261 if (This->dsc8_unk) {
262 IUnknown_Release(This->dsc8_unk);
263 This->dsc8_unk = NULL;
268 static const IDirectSoundFullDuplexVtbl dsfd_vtbl =
270 /* IUnknown methods */
271 IDirectSoundFullDuplexImpl_QueryInterface,
272 IDirectSoundFullDuplexImpl_AddRef,
273 IDirectSoundFullDuplexImpl_Release,
275 /* IDirectSoundFullDuplex methods */
276 IDirectSoundFullDuplexImpl_Initialize
279 HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv)
281 IDirectSoundFullDuplexImpl *obj;
284 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
287 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
289 WARN("out of memory\n");
290 return DSERR_OUTOFMEMORY;
293 setup_dsound_options();
295 obj->IDirectSoundFullDuplex_iface.lpVtbl = &dsfd_vtbl;
296 obj->IUnknown_iface.lpVtbl = &unk_vtbl;
301 hr = IUnknown_QueryInterface(&obj->IUnknown_iface, riid, ppv);
302 IUnknown_Release(&obj->IUnknown_iface);
307 /***************************************************************************
308 * DirectSoundFullDuplexCreate [DSOUND.10]
310 * Create and initialize a DirectSoundFullDuplex interface.
313 * capture_dev [I] Address of sound capture device GUID.
314 * render_dev [I] Address of sound render device GUID.
315 * cbufdesc [I] Address of capture buffer description.
316 * bufdesc [I] Address of render buffer description.
317 * hwnd [I] Handle to application window.
318 * level [I] Cooperative level.
319 * dsfd [O] Address where full duplex interface returned.
320 * dscb8 [0] Address where capture buffer interface returned.
321 * dsb8 [0] Address where render buffer interface returned.
322 * outer_unk [I] Must be NULL.
326 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
327 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
329 HRESULT WINAPI DirectSoundFullDuplexCreate(const GUID *capture_dev, const GUID *render_dev,
330 const DSCBUFFERDESC *cbufdesc, const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level,
331 IDirectSoundFullDuplex **dsfd, IDirectSoundCaptureBuffer8 **dscb8,
332 IDirectSoundBuffer8 **dsb8, IUnknown *outer_unk)
336 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", debugstr_guid(capture_dev),
337 debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dsfd, dscb8, dsb8,
341 return DSERR_INVALIDPARAM;
344 return DSERR_NOAGGREGATION;
347 hr = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (void**)dsfd);
349 hr = IDirectSoundFullDuplex_Initialize(*dsfd, capture_dev, render_dev, cbufdesc, bufdesc,
350 hwnd, level, dscb8, dsb8);
352 IDirectSoundFullDuplex_Release(*dsfd);
354 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");