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
31 #include "wine/debug.h"
33 #include "dsound_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
37 /*****************************************************************************
38 * IDirectSoundFullDuplex implementation structure
40 typedef struct IDirectSoundFullDuplexImpl
42 IUnknown IUnknown_iface
;
43 IDirectSoundFullDuplex IDirectSoundFullDuplex_iface
;
44 LONG ref
, refdsfd
, numIfaces
;
45 IUnknown
*ds8_unk
; /* Aggregated IDirectSound8 */
46 IUnknown
*dsc8_unk
; /* Aggregated IDirectSoundCapture8 */
47 } IDirectSoundFullDuplexImpl
;
49 static void fullduplex_destroy(IDirectSoundFullDuplexImpl
*This
)
52 IDirectSoundCapture8
*dsc8
;
55 IUnknown_QueryInterface(This
->ds8_unk
, &IID_IDirectSound8
, (void**)&ds8
);
56 while(IDirectSound8_Release(ds8
) > 0);
57 IUnknown_Release(This
->ds8_unk
);
60 IUnknown_QueryInterface(This
->dsc8_unk
, &IID_IDirectSoundCapture8
, (void**)&dsc8
);
61 while(IDirectSoundCapture_Release(dsc8
) > 0);
62 IUnknown_Release(This
->dsc8_unk
);
64 TRACE("(%p) released\n", This
);
65 HeapFree(GetProcessHeap(), 0, This
);
68 /*******************************************************************************
69 * IUnknown implementation for DirectSoundFullDuplex
71 static inline IDirectSoundFullDuplexImpl
*impl_from_IUnknown(IUnknown
*iface
)
73 return CONTAINING_RECORD(iface
, IDirectSoundFullDuplexImpl
, IUnknown_iface
);
76 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
78 IDirectSoundFullDuplexImpl
*This
= impl_from_IUnknown(iface
);
80 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
83 WARN("invalid parameter\n");
87 if (IsEqualIID(riid
, &IID_IUnknown
)) {
88 IUnknown_AddRef(&This
->IUnknown_iface
);
89 *ppv
= &This
->IUnknown_iface
;
91 } else if (IsEqualIID(riid
, &IID_IDirectSoundFullDuplex
)) {
92 IDirectSoundFullDuplex_AddRef(&This
->IDirectSoundFullDuplex_iface
);
93 *ppv
= &This
->IDirectSoundFullDuplex_iface
;
95 } else if (This
->ds8_unk
&& (IsEqualIID(riid
, &IID_IDirectSound
) ||
96 IsEqualIID(riid
, &IID_IDirectSound8
)))
97 return IUnknown_QueryInterface(This
->ds8_unk
, riid
, ppv
);
98 else if (This
->dsc8_unk
&& IsEqualIID(riid
, &IID_IDirectSoundCapture
))
99 return IUnknown_QueryInterface(This
->dsc8_unk
, riid
, ppv
);
102 return E_NOINTERFACE
;
105 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
*iface
)
107 IDirectSoundFullDuplexImpl
*This
= impl_from_IUnknown(iface
);
108 ULONG ref
= InterlockedIncrement(&This
->ref
);
110 TRACE("(%p) ref=%ld\n", This
, ref
);
113 InterlockedIncrement(&This
->numIfaces
);
117 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
*iface
)
119 IDirectSoundFullDuplexImpl
*This
= impl_from_IUnknown(iface
);
120 ULONG ref
= InterlockedDecrement(&This
->ref
);
122 TRACE("(%p) ref=%ld\n", This
, ref
);
124 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
125 fullduplex_destroy(This
);
129 static const IUnknownVtbl unk_vtbl
=
131 IUnknownImpl_QueryInterface
,
136 /***************************************************************************
137 * IDirectSoundFullDuplex implementation
139 static inline IDirectSoundFullDuplexImpl
*impl_from_IDirectSoundFullDuplex(IDirectSoundFullDuplex
*iface
)
141 return CONTAINING_RECORD(iface
, IDirectSoundFullDuplexImpl
, IDirectSoundFullDuplex_iface
);
144 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_QueryInterface(IDirectSoundFullDuplex
*iface
,
145 REFIID riid
, void **ppv
)
147 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
148 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
149 return IUnknown_QueryInterface(&This
->IUnknown_iface
, riid
, ppv
);
152 static ULONG WINAPI
IDirectSoundFullDuplexImpl_AddRef(IDirectSoundFullDuplex
*iface
)
154 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
155 ULONG ref
= InterlockedIncrement(&This
->refdsfd
);
157 TRACE("(%p) ref=%ld\n", This
, ref
);
160 InterlockedIncrement(&This
->numIfaces
);
164 static ULONG WINAPI
IDirectSoundFullDuplexImpl_Release(IDirectSoundFullDuplex
*iface
)
166 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
167 ULONG ref
= InterlockedDecrement(&This
->refdsfd
);
169 TRACE("(%p) ref=%ld\n", This
, ref
);
171 if (!ref
&& !InterlockedDecrement(&This
->numIfaces
))
172 fullduplex_destroy(This
);
176 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex
*iface
,
177 const GUID
*capture_dev
, const GUID
*render_dev
, const DSCBUFFERDESC
*cbufdesc
,
178 const DSBUFFERDESC
*bufdesc
, HWND hwnd
, DWORD level
, IDirectSoundCaptureBuffer8
**dscb8
,
179 IDirectSoundBuffer8
**dsb8
)
181 IDirectSoundFullDuplexImpl
*This
= impl_from_IDirectSoundFullDuplex(iface
);
182 IDirectSound8
*ds8
= NULL
;
183 IDirectSoundCapture8
*dsc8
= NULL
;
186 TRACE("(%p,%s,%s,%p,%p,%p,%lx,%p,%p)\n", This
, debugstr_guid(capture_dev
),
187 debugstr_guid(render_dev
), cbufdesc
, bufdesc
, hwnd
, level
, dscb8
, dsb8
);
195 if (This
->ds8_unk
|| This
->dsc8_unk
) {
196 WARN("already initialized\n");
197 return DSERR_ALREADYINITIALIZED
;
200 hr
= IDirectSoundImpl_Create(&This
->IUnknown_iface
, &IID_IUnknown
, (void**)&This
->ds8_unk
,
203 IUnknown_QueryInterface(This
->ds8_unk
, &IID_IDirectSound8
, (void**)&ds8
);
204 hr
= IDirectSound8_Initialize(ds8
, render_dev
);
207 WARN("Creating/initializing IDirectSound8 failed\n");
211 IDirectSound8_SetCooperativeLevel(ds8
, hwnd
, level
);
213 hr
= IDirectSound8_CreateSoundBuffer(ds8
, bufdesc
, (IDirectSoundBuffer
**)dsb8
, NULL
);
215 WARN("IDirectSoundBuffer_Create() failed\n");
219 hr
= IDirectSoundCaptureImpl_Create(&This
->IUnknown_iface
, &IID_IUnknown
,
220 (void**)&This
->dsc8_unk
, TRUE
);
222 IUnknown_QueryInterface(This
->dsc8_unk
, &IID_IDirectSoundCapture8
, (void**)&dsc8
);
223 hr
= IDirectSoundCapture_Initialize(dsc8
, capture_dev
);
226 WARN("Creating/initializing IDirectSoundCapture8 failed\n");
230 hr
= IDirectSoundCapture_CreateCaptureBuffer(dsc8
, cbufdesc
,
231 (IDirectSoundCaptureBuffer
**)dscb8
, NULL
);
233 WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n");
237 IDirectSound8_Release(ds8
);
238 IDirectSoundCapture_Release(dsc8
);
243 IDirectSoundBuffer8_Release(*dsb8
);
247 IDirectSound8_Release(ds8
);
249 IUnknown_Release(This
->ds8_unk
);
250 This
->ds8_unk
= NULL
;
253 IDirectSoundCaptureBuffer8_Release(*dscb8
);
257 IDirectSoundCapture_Release(dsc8
);
258 if (This
->dsc8_unk
) {
259 IUnknown_Release(This
->dsc8_unk
);
260 This
->dsc8_unk
= NULL
;
265 static const IDirectSoundFullDuplexVtbl dsfd_vtbl
=
267 /* IUnknown methods */
268 IDirectSoundFullDuplexImpl_QueryInterface
,
269 IDirectSoundFullDuplexImpl_AddRef
,
270 IDirectSoundFullDuplexImpl_Release
,
272 /* IDirectSoundFullDuplex methods */
273 IDirectSoundFullDuplexImpl_Initialize
276 HRESULT
DSOUND_FullDuplexCreate(REFIID riid
, void **ppv
)
278 IDirectSoundFullDuplexImpl
*obj
;
281 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
284 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*obj
));
286 WARN("out of memory\n");
287 return DSERR_OUTOFMEMORY
;
290 setup_dsound_options();
292 obj
->IDirectSoundFullDuplex_iface
.lpVtbl
= &dsfd_vtbl
;
293 obj
->IUnknown_iface
.lpVtbl
= &unk_vtbl
;
298 hr
= IUnknown_QueryInterface(&obj
->IUnknown_iface
, riid
, ppv
);
299 IUnknown_Release(&obj
->IUnknown_iface
);
304 /***************************************************************************
305 * DirectSoundFullDuplexCreate [DSOUND.10]
307 * Create and initialize a DirectSoundFullDuplex interface.
310 * capture_dev [I] Address of sound capture device GUID.
311 * render_dev [I] Address of sound render device GUID.
312 * cbufdesc [I] Address of capture buffer description.
313 * bufdesc [I] Address of render buffer description.
314 * hwnd [I] Handle to application window.
315 * level [I] Cooperative level.
316 * dsfd [O] Address where full duplex interface returned.
317 * dscb8 [0] Address where capture buffer interface returned.
318 * dsb8 [0] Address where render buffer interface returned.
319 * outer_unk [I] Must be NULL.
323 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
324 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
326 HRESULT WINAPI
DirectSoundFullDuplexCreate(const GUID
*capture_dev
, const GUID
*render_dev
,
327 const DSCBUFFERDESC
*cbufdesc
, const DSBUFFERDESC
*bufdesc
, HWND hwnd
, DWORD level
,
328 IDirectSoundFullDuplex
**dsfd
, IDirectSoundCaptureBuffer8
**dscb8
,
329 IDirectSoundBuffer8
**dsb8
, IUnknown
*outer_unk
)
333 TRACE("(%s,%s,%p,%p,%p,%lx,%p,%p,%p,%p)\n", debugstr_guid(capture_dev
),
334 debugstr_guid(render_dev
), cbufdesc
, bufdesc
, hwnd
, level
, dsfd
, dscb8
, dsb8
,
338 return DSERR_INVALIDPARAM
;
341 return DSERR_NOAGGREGATION
;
344 hr
= DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex
, (void**)dsfd
);
346 hr
= IDirectSoundFullDuplex_Initialize(*dsfd
, capture_dev
, render_dev
, cbufdesc
, bufdesc
,
347 hwnd
, level
, dscb8
, dsb8
);
349 IDirectSoundFullDuplex_Release(*dsfd
);
351 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");