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");