msdmo: Actually copy output string in IEnumDMO_fnNext.
[wine.git] / dlls / dsound / duplex.c
bloba2bc72672219988c5e28df62be29bc1735294831
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
23 #include <stdarg.h>
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
27 #define COBJMACROS
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "mmddk.h"
33 #include "winternl.h"
34 #include "wine/debug.h"
35 #include "dsound.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)
54 IDirectSound8 *ds8;
55 IDirectSoundCapture8 *dsc8;
57 if (This->ds8_unk) {
58 IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
59 while(IDirectSound8_Release(ds8) > 0);
60 IUnknown_Release(This->ds8_unk);
62 if (This->dsc8_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);
85 if (!ppv) {
86 WARN("invalid parameter\n");
87 return E_INVALIDARG;
90 if (IsEqualIID(riid, &IID_IUnknown)) {
91 IUnknown_AddRef(&This->IUnknown_iface);
92 *ppv = &This->IUnknown_iface;
93 return S_OK;
94 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
95 IDirectSoundFullDuplex_AddRef(&This->IDirectSoundFullDuplex_iface);
96 *ppv = &This->IDirectSoundFullDuplex_iface;
97 return S_OK;
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);
104 *ppv = NULL;
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);
115 if(ref == 1)
116 InterlockedIncrement(&This->numIfaces);
117 return ref;
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);
129 return ref;
132 static const IUnknownVtbl unk_vtbl =
134 IUnknownImpl_QueryInterface,
135 IUnknownImpl_AddRef,
136 IUnknownImpl_Release
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);
162 if(ref == 1)
163 InterlockedIncrement(&This->numIfaces);
164 return ref;
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);
176 return ref;
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;
187 HRESULT hr;
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);
192 if (!dscb8 || !dsb8)
193 return E_INVALIDARG;
195 *dscb8 = NULL;
196 *dsb8 = NULL;
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,
204 TRUE);
205 if (SUCCEEDED(hr)) {
206 IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8);
207 hr = IDirectSound_Initialize(ds8, render_dev);
209 if (hr != DS_OK) {
210 WARN("Creating/initializing IDirectSound8 failed\n");
211 goto error;
214 IDirectSound8_SetCooperativeLevel(ds8, hwnd, level);
216 hr = IDirectSound8_CreateSoundBuffer(ds8, bufdesc, (IDirectSoundBuffer**)dsb8, NULL);
217 if (hr != DS_OK) {
218 WARN("IDirectSoundBuffer_Create() failed\n");
219 goto error;
222 hr = IDirectSoundCaptureImpl_Create(&This->IUnknown_iface, &IID_IUnknown,
223 (void**)&This->dsc8_unk, TRUE);
224 if (SUCCEEDED(hr)) {
225 IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8);
226 hr = IDirectSoundCapture_Initialize(dsc8, capture_dev);
228 if (hr != DS_OK) {
229 WARN("Creating/initializing IDirectSoundCapture8 failed\n");
230 goto error;
233 hr = IDirectSoundCapture_CreateCaptureBuffer(dsc8, cbufdesc,
234 (IDirectSoundCaptureBuffer**)dscb8, NULL);
235 if (hr != DS_OK) {
236 WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n");
237 goto error;
240 IDirectSound8_Release(ds8);
241 IDirectSoundCapture_Release(dsc8);
242 return DS_OK;
244 error:
245 if (*dsb8) {
246 IDirectSoundBuffer8_Release(*dsb8);
247 *dsb8 = NULL;
249 if (ds8)
250 IDirectSound8_Release(ds8);
251 if (This->ds8_unk) {
252 IUnknown_Release(This->ds8_unk);
253 This->ds8_unk = NULL;
255 if (*dscb8) {
256 IDirectSoundCaptureBuffer8_Release(*dscb8);
257 *dscb8 = NULL;
259 if (dsc8)
260 IDirectSoundCapture_Release(dsc8);
261 if (This->dsc8_unk) {
262 IUnknown_Release(This->dsc8_unk);
263 This->dsc8_unk = NULL;
265 return hr;
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;
282 HRESULT hr;
284 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
286 *ppv = NULL;
287 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj));
288 if (!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;
297 obj->ref = 1;
298 obj->refdsfd = 0;
299 obj->numIfaces = 1;
301 hr = IUnknown_QueryInterface(&obj->IUnknown_iface, riid, ppv);
302 IUnknown_Release(&obj->IUnknown_iface);
304 return hr;
307 /***************************************************************************
308 * DirectSoundFullDuplexCreate [DSOUND.10]
310 * Create and initialize a DirectSoundFullDuplex interface.
312 * PARAMS
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.
324 * RETURNS
325 * Success: DS_OK
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)
334 HRESULT hr;
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,
338 outer_unk);
340 if (!dsfd)
341 return DSERR_INVALIDPARAM;
342 if (outer_unk) {
343 *dsfd = NULL;
344 return DSERR_NOAGGREGATION;
347 hr = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (void**)dsfd);
348 if (hr == DS_OK) {
349 hr = IDirectSoundFullDuplex_Initialize(*dsfd, capture_dev, render_dev, cbufdesc, bufdesc,
350 hwnd, level, dscb8, dsb8);
351 if (hr != DS_OK) {
352 IDirectSoundFullDuplex_Release(*dsfd);
353 *dsfd = NULL;
354 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
358 return hr;