1 /* DirectSoundFullDuplex
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
6 * Copyright 2005 Robert Reif
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include "dsound_private.h"
24
25 /*****************************************************************************
26 * IDirectSoundFullDuplex implementation structure
27 */
28 typedef struct IDirectSoundFullDuplexImpl
29 {
30 /* IUnknown fields */
31 const IDirectSoundFullDuplexVtbl *lpVtbl;
32 LONG ref;
33
34 /* IDirectSoundFullDuplexImpl fields */
35 IDirectSound8 *renderer_device;
36 IDirectSoundCapture *capture_device;
37
38 LPUNKNOWN pUnknown;
39 LPDIRECTSOUND8 pDS8;
40 LPDIRECTSOUNDCAPTURE pDSC;
41 } IDirectSoundFullDuplexImpl;
42
43 typedef struct IDirectSoundFullDuplex_IUnknown {
44 const IUnknownVtbl *lpVtbl;
45 LONG ref;
46 IDirectSoundFullDuplexImpl *pdsfd;
47 } IDirectSoundFullDuplex_IUnknown;
48
49 typedef struct IDirectSoundFullDuplex_IDirectSound8 {
50 const IDirectSound8Vtbl *lpVtbl;
51 LONG ref;
52 IDirectSoundFullDuplexImpl *pdsfd;
53 } IDirectSoundFullDuplex_IDirectSound8;
54
55 typedef struct IDirectSoundFullDuplex_IDirectSoundCapture {
56 const IDirectSoundCaptureVtbl *lpVtbl;
57 LONG ref;
58 IDirectSoundFullDuplexImpl *pdsfd;
59 } IDirectSoundFullDuplex_IDirectSoundCapture;
60
61 /*******************************************************************************
62 * IUnknown
63 */
IDirectSoundFullDuplex_IUnknown_QueryInterface(LPUNKNOWN iface,REFIID riid,LPVOID * ppobj)64 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
65 LPUNKNOWN iface,
66 REFIID riid,
67 LPVOID * ppobj)
68 {
69 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
70 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
71 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
72 }
73
IDirectSoundFullDuplex_IUnknown_AddRef(LPUNKNOWN iface)74 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
75 LPUNKNOWN iface)
76 {
77 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
78 ULONG ref = InterlockedIncrement(&(This->ref));
79 TRACE("(%p) ref was %d\n", This, ref - 1);
80 return ref;
81 }
82
IDirectSoundFullDuplex_IUnknown_Release(LPUNKNOWN iface)83 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
84 LPUNKNOWN iface)
85 {
86 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
87 ULONG ref = InterlockedDecrement(&(This->ref));
88 TRACE("(%p) ref was %d\n", This, ref + 1);
89 if (!ref) {
90 This->pdsfd->pUnknown = NULL;
91 HeapFree(GetProcessHeap(), 0, This);
92 TRACE("(%p) released\n", This);
93 }
94 return ref;
95 }
96
97 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
98 {
99 IDirectSoundFullDuplex_IUnknown_QueryInterface,
100 IDirectSoundFullDuplex_IUnknown_AddRef,
101 IDirectSoundFullDuplex_IUnknown_Release
102 };
103
IDirectSoundFullDuplex_IUnknown_Create(LPDIRECTSOUNDFULLDUPLEX pdsfd,LPUNKNOWN * ppunk)104 static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
105 LPDIRECTSOUNDFULLDUPLEX pdsfd,
106 LPUNKNOWN * ppunk)
107 {
108 IDirectSoundFullDuplex_IUnknown * pdsfdunk;
109 TRACE("(%p,%p)\n",pdsfd,ppunk);
110
111 if (pdsfd == NULL) {
112 ERR("invalid parameter: pdsfd == NULL\n");
113 return DSERR_INVALIDPARAM;
114 }
115
116 if (ppunk == NULL) {
117 ERR("invalid parameter: ppunk == NULL\n");
118 return DSERR_INVALIDPARAM;
119 }
120
121 pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
122 if (pdsfdunk == NULL) {
123 WARN("out of memory\n");
124 *ppunk = NULL;
125 return DSERR_OUTOFMEMORY;
126 }
127
128 pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
129 pdsfdunk->ref = 0;
130 pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
131
132 *ppunk = (LPUNKNOWN)pdsfdunk;
133
134 return DS_OK;
135 }
136
137 /*******************************************************************************
138 * IDirectSoundFullDuplex_IDirectSound8
139 */
IDirectSoundFullDuplex_IDirectSound8_QueryInterface(LPDIRECTSOUND8 iface,REFIID riid,LPVOID * ppobj)140 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
141 LPDIRECTSOUND8 iface,
142 REFIID riid,
143 LPVOID * ppobj)
144 {
145 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
146 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
147 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
148 }
149
IDirectSoundFullDuplex_IDirectSound8_AddRef(LPDIRECTSOUND8 iface)150 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
151 LPDIRECTSOUND8 iface)
152 {
153 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
154 ULONG ref = InterlockedIncrement(&(This->ref));
155 TRACE("(%p) ref was %d\n", This, ref - 1);
156 return ref;
157 }
158
IDirectSoundFullDuplex_IDirectSound8_Release(LPDIRECTSOUND8 iface)159 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
160 LPDIRECTSOUND8 iface)
161 {
162 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
163 ULONG ref = InterlockedDecrement(&(This->ref));
164 TRACE("(%p) ref was %d\n", This, ref + 1);
165 if (!ref) {
166 This->pdsfd->pDS8 = NULL;
167 HeapFree(GetProcessHeap(), 0, This);
168 TRACE("(%p) released\n", This);
169 }
170 return ref;
171 }
172
IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(LPDIRECTSOUND8 iface,LPCDSBUFFERDESC dsbd,LPLPDIRECTSOUNDBUFFER ppdsb,LPUNKNOWN lpunk)173 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
174 LPDIRECTSOUND8 iface,
175 LPCDSBUFFERDESC dsbd,
176 LPLPDIRECTSOUNDBUFFER ppdsb,
177 LPUNKNOWN lpunk)
178 {
179 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
180 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
181 return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk);
182 }
183
IDirectSoundFullDuplex_IDirectSound8_GetCaps(LPDIRECTSOUND8 iface,LPDSCAPS lpDSCaps)184 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
185 LPDIRECTSOUND8 iface,
186 LPDSCAPS lpDSCaps)
187 {
188 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
189 TRACE("(%p,%p)\n",This,lpDSCaps);
190 return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
191 }
192
IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(LPDIRECTSOUND8 iface,LPDIRECTSOUNDBUFFER psb,LPLPDIRECTSOUNDBUFFER ppdsb)193 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
194 LPDIRECTSOUND8 iface,
195 LPDIRECTSOUNDBUFFER psb,
196 LPLPDIRECTSOUNDBUFFER ppdsb)
197 {
198 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
199 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
200 return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
201 }
202
IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(LPDIRECTSOUND8 iface,HWND hwnd,DWORD level)203 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
204 LPDIRECTSOUND8 iface,
205 HWND hwnd,
206 DWORD level)
207 {
208 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
209 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
210 return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
211 }
212
IDirectSoundFullDuplex_IDirectSound8_Compact(LPDIRECTSOUND8 iface)213 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
214 LPDIRECTSOUND8 iface)
215 {
216 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
217 TRACE("(%p)\n", This);
218 return IDirectSound8_Compact(This->pdsfd->renderer_device);
219 }
220
IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(LPDIRECTSOUND8 iface,LPDWORD lpdwSpeakerConfig)221 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
222 LPDIRECTSOUND8 iface,
223 LPDWORD lpdwSpeakerConfig)
224 {
225 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
226 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
227 return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
228 }
229
IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(LPDIRECTSOUND8 iface,DWORD config)230 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
231 LPDIRECTSOUND8 iface,
232 DWORD config)
233 {
234 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
235 TRACE("(%p,0x%08x)\n",This,config);
236 return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config);
237 }
238
IDirectSoundFullDuplex_IDirectSound8_Initialize(LPDIRECTSOUND8 iface,LPCGUID lpcGuid)239 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
240 LPDIRECTSOUND8 iface,
241 LPCGUID lpcGuid)
242 {
243 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
244 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
245 return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid);
246 }
247
IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(LPDIRECTSOUND8 iface,DWORD * cert)248 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
249 LPDIRECTSOUND8 iface,
250 DWORD *cert)
251 {
252 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
253 TRACE("(%p, %p)\n", This, cert);
254 return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert);
255 }
256
257 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
258 {
259 IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
260 IDirectSoundFullDuplex_IDirectSound8_AddRef,
261 IDirectSoundFullDuplex_IDirectSound8_Release,
262 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
263 IDirectSoundFullDuplex_IDirectSound8_GetCaps,
264 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
265 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
266 IDirectSoundFullDuplex_IDirectSound8_Compact,
267 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
268 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
269 IDirectSoundFullDuplex_IDirectSound8_Initialize,
270 IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
271 };
272
IDirectSoundFullDuplex_IDirectSound8_Create(LPDIRECTSOUNDFULLDUPLEX pdsfd,LPDIRECTSOUND8 * ppds8)273 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
274 LPDIRECTSOUNDFULLDUPLEX pdsfd,
275 LPDIRECTSOUND8 * ppds8)
276 {
277 IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
278 TRACE("(%p,%p)\n",pdsfd,ppds8);
279
280 if (pdsfd == NULL) {
281 ERR("invalid parameter: pdsfd == NULL\n");
282 return DSERR_INVALIDPARAM;
283 }
284
285 if (ppds8 == NULL) {
286 ERR("invalid parameter: ppds8 == NULL\n");
287 return DSERR_INVALIDPARAM;
288 }
289
290 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
291 WARN("not initialized\n");
292 *ppds8 = NULL;
293 return DSERR_UNINITIALIZED;
294 }
295
296 pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
297 if (pdsfdds8 == NULL) {
298 WARN("out of memory\n");
299 *ppds8 = NULL;
300 return DSERR_OUTOFMEMORY;
301 }
302
303 pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
304 pdsfdds8->ref = 0;
305 pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
306
307 *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
308
309 return DS_OK;
310 }
311
312 /*******************************************************************************
313 * IDirectSoundFullDuplex_IDirectSoundCapture
314 */
IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(LPDIRECTSOUNDCAPTURE iface,REFIID riid,LPVOID * ppobj)315 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
316 LPDIRECTSOUNDCAPTURE iface,
317 REFIID riid,
318 LPVOID * ppobj)
319 {
320 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
321 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
322 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
323 }
324
IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(LPDIRECTSOUNDCAPTURE iface)325 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
326 LPDIRECTSOUNDCAPTURE iface)
327 {
328 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
329 ULONG ref = InterlockedIncrement(&(This->ref));
330 TRACE("(%p) ref was %d\n", This, ref - 1);
331 return ref;
332 }
333
IDirectSoundFullDuplex_IDirectSoundCapture_Release(LPDIRECTSOUNDCAPTURE iface)334 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
335 LPDIRECTSOUNDCAPTURE iface)
336 {
337 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
338 ULONG ref = InterlockedDecrement(&(This->ref));
339 TRACE("(%p) ref was %d\n", This, ref + 1);
340 if (!ref) {
341 This->pdsfd->pDSC = NULL;
342 HeapFree(GetProcessHeap(), 0, This);
343 TRACE("(%p) released\n", This);
344 }
345 return ref;
346 }
347
IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(LPDIRECTSOUNDCAPTURE iface,LPCDSCBUFFERDESC lpcDSCBufferDesc,LPDIRECTSOUNDCAPTUREBUFFER * lplpDSCaptureBuffer,LPUNKNOWN pUnk)348 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
349 LPDIRECTSOUNDCAPTURE iface,
350 LPCDSCBUFFERDESC lpcDSCBufferDesc,
351 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
352 LPUNKNOWN pUnk)
353 {
354 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
355 TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
356 return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
357 }
358
IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(LPDIRECTSOUNDCAPTURE iface,LPDSCCAPS lpDSCCaps)359 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
360 LPDIRECTSOUNDCAPTURE iface,
361 LPDSCCAPS lpDSCCaps)
362 {
363 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
364 TRACE("(%p,%p)\n",This,lpDSCCaps);
365 return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps);
366 }
367
IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(LPDIRECTSOUNDCAPTURE iface,LPCGUID lpcGUID)368 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
369 LPDIRECTSOUNDCAPTURE iface,
370 LPCGUID lpcGUID)
371 {
372 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
373 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
374 return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID);
375 }
376
377 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
378 {
379 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
380 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
381 IDirectSoundFullDuplex_IDirectSoundCapture_Release,
382 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
383 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
384 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
385 };
386
IDirectSoundFullDuplex_IDirectSoundCapture_Create(LPDIRECTSOUNDFULLDUPLEX pdsfd,LPDIRECTSOUNDCAPTURE8 * ppdsc8)387 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
388 LPDIRECTSOUNDFULLDUPLEX pdsfd,
389 LPDIRECTSOUNDCAPTURE8 * ppdsc8)
390 {
391 IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
392 TRACE("(%p,%p)\n",pdsfd,ppdsc8);
393
394 if (pdsfd == NULL) {
395 ERR("invalid parameter: pdsfd == NULL\n");
396 return DSERR_INVALIDPARAM;
397 }
398
399 if (ppdsc8 == NULL) {
400 ERR("invalid parameter: ppdsc8 == NULL\n");
401 return DSERR_INVALIDPARAM;
402 }
403
404 if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
405 WARN("not initialized\n");
406 *ppdsc8 = NULL;
407 return DSERR_UNINITIALIZED;
408 }
409
410 pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
411 if (pdsfddsc == NULL) {
412 WARN("out of memory\n");
413 *ppdsc8 = NULL;
414 return DSERR_OUTOFMEMORY;
415 }
416
417 pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
418 pdsfddsc->ref = 0;
419 pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
420
421 *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
422
423 return DS_OK;
424 }
425
426 /***************************************************************************
427 * IDirectSoundFullDuplexImpl
428 */
429 static ULONG WINAPI
IDirectSoundFullDuplexImpl_AddRef(LPDIRECTSOUNDFULLDUPLEX iface)430 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
431 {
432 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
433 ULONG ref = InterlockedIncrement(&(This->ref));
434 TRACE("(%p) ref was %d\n", This, ref - 1);
435 return ref;
436 }
437
438 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_QueryInterface(LPDIRECTSOUNDFULLDUPLEX iface,REFIID riid,LPVOID * ppobj)439 IDirectSoundFullDuplexImpl_QueryInterface(
440 LPDIRECTSOUNDFULLDUPLEX iface,
441 REFIID riid,
442 LPVOID* ppobj )
443 {
444 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
445 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
446
447 if (ppobj == NULL) {
448 WARN("invalid parameter\n");
449 return E_INVALIDARG;
450 }
451
452 *ppobj = NULL;
453
454 if (IsEqualIID(riid, &IID_IUnknown)) {
455 if (!This->pUnknown) {
456 IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
457 if (!This->pUnknown) {
458 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
459 *ppobj = NULL;
460 return E_NOINTERFACE;
461 }
462 }
463 IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
464 *ppobj = This->pUnknown;
465 return S_OK;
466 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
467 IDirectSoundFullDuplexImpl_AddRef(iface);
468 *ppobj = This;
469 return S_OK;
470 } else if (IsEqualIID(riid, &IID_IDirectSound)
471 || IsEqualIID(riid, &IID_IDirectSound8)) {
472 if (!This->pDS8) {
473 IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
474 if (!This->pDS8) {
475 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
476 *ppobj = NULL;
477 return E_NOINTERFACE;
478 }
479 }
480 IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
481 *ppobj = This->pDS8;
482 return S_OK;
483 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
484 if (!This->pDSC) {
485 IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
486 if (!This->pDSC) {
487 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
488 *ppobj = NULL;
489 return E_NOINTERFACE;
490 }
491 }
492 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
493 *ppobj = This->pDSC;
494 return S_OK;
495 }
496
497 return E_NOINTERFACE;
498 }
499
500 static ULONG WINAPI
IDirectSoundFullDuplexImpl_Release(LPDIRECTSOUNDFULLDUPLEX iface)501 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
502 {
503 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
504 ULONG ref = InterlockedDecrement(&(This->ref));
505 TRACE("(%p) ref was %d\n", This, ref - 1);
506
507 if (!ref) {
508 if (This->capture_device)
509 IDirectSoundCapture_Release(This->capture_device);
510 if (This->renderer_device)
511 IDirectSound_Release(This->renderer_device);
512 HeapFree( GetProcessHeap(), 0, This );
513 TRACE("(%p) released\n", This);
514 }
515 return ref;
516 }
517
518 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_Initialize(LPDIRECTSOUNDFULLDUPLEX iface,LPCGUID pCaptureGuid,LPCGUID pRendererGuid,LPCDSCBUFFERDESC lpDscBufferDesc,LPCDSBUFFERDESC lpDsBufferDesc,HWND hWnd,DWORD dwLevel,LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8)519 IDirectSoundFullDuplexImpl_Initialize(
520 LPDIRECTSOUNDFULLDUPLEX iface,
521 LPCGUID pCaptureGuid,
522 LPCGUID pRendererGuid,
523 LPCDSCBUFFERDESC lpDscBufferDesc,
524 LPCDSBUFFERDESC lpDsBufferDesc,
525 HWND hWnd,
526 DWORD dwLevel,
527 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
528 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
529 {
530 HRESULT hr;
531 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
532
533 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This,
534 debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
535 lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
536 lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
537
538 if (!lplpDirectSoundCaptureBuffer8 || !lplpDirectSoundBuffer8)
539 return E_INVALIDARG;
540
541 if (This->renderer_device != NULL || This->capture_device != NULL) {
542 WARN("already initialized\n");
543 *lplpDirectSoundCaptureBuffer8 = NULL;
544 *lplpDirectSoundBuffer8 = NULL;
545 return DSERR_ALREADYINITIALIZED;
546 }
547
548 hr = DSOUND_Create8(&IID_IDirectSound8, &This->renderer_device);
549 if (SUCCEEDED(hr))
550 hr = IDirectSound_Initialize(This->renderer_device, pRendererGuid);
551 if (hr != DS_OK) {
552 WARN("DirectSoundDevice_Initialize() failed\n");
553 *lplpDirectSoundCaptureBuffer8 = NULL;
554 *lplpDirectSoundBuffer8 = NULL;
555 return hr;
556 }
557
558 IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel);
559
560 hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc,
561 (IDirectSoundBuffer**)lplpDirectSoundBuffer8, NULL);
562 if (hr != DS_OK) {
563 WARN("IDirectSoundBufferImpl_Create() failed\n");
564 *lplpDirectSoundCaptureBuffer8 = NULL;
565 *lplpDirectSoundBuffer8 = NULL;
566 return hr;
567 }
568
569 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &This->capture_device);
570 if (SUCCEEDED(hr))
571 hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid);
572 if (hr != DS_OK) {
573 WARN("DirectSoundCaptureDevice_Initialize() failed\n");
574 *lplpDirectSoundCaptureBuffer8 = NULL;
575 *lplpDirectSoundBuffer8 = NULL;
576 return hr;
577 }
578
579 hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device,
580 lpDscBufferDesc,
581 (IDirectSoundCaptureBuffer**)lplpDirectSoundCaptureBuffer8,
582 NULL);
583 if (hr != DS_OK) {
584 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
585 *lplpDirectSoundCaptureBuffer8 = NULL;
586 *lplpDirectSoundBuffer8 = NULL;
587 return hr;
588 }
589
590 return hr;
591 }
592
593 static const IDirectSoundFullDuplexVtbl dsfdvt =
594 {
595 /* IUnknown methods */
596 IDirectSoundFullDuplexImpl_QueryInterface,
597 IDirectSoundFullDuplexImpl_AddRef,
598 IDirectSoundFullDuplexImpl_Release,
599
600 /* IDirectSoundFullDuplex methods */
601 IDirectSoundFullDuplexImpl_Initialize
602 };
603
DSOUND_FullDuplexCreate(REFIID riid,LPDIRECTSOUNDFULLDUPLEX * ppDSFD)604 HRESULT DSOUND_FullDuplexCreate(
605 REFIID riid,
606 LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
607 {
608 IDirectSoundFullDuplexImpl *This = NULL;
609 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
610
611 if (ppDSFD == NULL) {
612 WARN("invalid parameter: ppDSFD == NULL\n");
613 return DSERR_INVALIDPARAM;
614 }
615
616 if (!IsEqualIID(riid, &IID_IUnknown) &&
617 !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
618 *ppDSFD = 0;
619 return E_NOINTERFACE;
620 }
621
622 /* Get dsound configuration */
623 setup_dsound_options();
624
625 This = HeapAlloc(GetProcessHeap(),
626 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
627
628 if (This == NULL) {
629 WARN("out of memory\n");
630 *ppDSFD = NULL;
631 return DSERR_OUTOFMEMORY;
632 }
633
634 This->lpVtbl = &dsfdvt;
635 This->ref = 1;
636 This->capture_device = NULL;
637 This->renderer_device = NULL;
638
639 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
640
641 return DS_OK;
642 }
643
644 /***************************************************************************
645 * DirectSoundFullDuplexCreate [DSOUND.10]
646 *
647 * Create and initialize a DirectSoundFullDuplex interface.
648 *
649 * PARAMS
650 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
651 * pcGuidRenderDevice [I] Address of sound render device GUID.
652 * pcDSCBufferDesc [I] Address of capture buffer description.
653 * pcDSBufferDesc [I] Address of render buffer description.
654 * hWnd [I] Handle to application window.
655 * dwLevel [I] Cooperative level.
656 * ppDSFD [O] Address where full duplex interface returned.
657 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
658 * ppDSBuffer8 [0] Address where render buffer interface returned.
659 * pUnkOuter [I] Must be NULL.
660 *
661 * RETURNS
662 * Success: DS_OK
663 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
664 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
665 */
666 HRESULT WINAPI
DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice,LPCGUID pcGuidRenderDevice,LPCDSCBUFFERDESC pcDSCBufferDesc,LPCDSBUFFERDESC pcDSBufferDesc,HWND hWnd,DWORD dwLevel,LPDIRECTSOUNDFULLDUPLEX * ppDSFD,LPDIRECTSOUNDCAPTUREBUFFER8 * ppDSCBuffer8,LPDIRECTSOUNDBUFFER8 * ppDSBuffer8,LPUNKNOWN pUnkOuter)667 DirectSoundFullDuplexCreate(
668 LPCGUID pcGuidCaptureDevice,
669 LPCGUID pcGuidRenderDevice,
670 LPCDSCBUFFERDESC pcDSCBufferDesc,
671 LPCDSBUFFERDESC pcDSBufferDesc,
672 HWND hWnd,
673 DWORD dwLevel,
674 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
675 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
676 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
677 LPUNKNOWN pUnkOuter)
678 {
679 HRESULT hres;
680 IDirectSoundFullDuplexImpl *This = NULL;
681 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
682 debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
683 pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
684 ppDSBuffer8, pUnkOuter);
685
686 if (pUnkOuter) {
687 WARN("pUnkOuter != 0\n");
688 *ppDSFD = NULL;
689 return DSERR_NOAGGREGATION;
690 }
691
692 if (pcDSCBufferDesc == NULL) {
693 WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
694 *ppDSFD = NULL;
695 return DSERR_INVALIDPARAM;
696 }
697
698 if (pcDSBufferDesc == NULL) {
699 WARN("invalid parameter: pcDSBufferDesc == NULL\n");
700 *ppDSFD = NULL;
701 return DSERR_INVALIDPARAM;
702 }
703
704 if (ppDSFD == NULL) {
705 WARN("invalid parameter: ppDSFD == NULL\n");
706 return DSERR_INVALIDPARAM;
707 }
708
709 if (ppDSCBuffer8 == NULL) {
710 WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
711 *ppDSFD = NULL;
712 return DSERR_INVALIDPARAM;
713 }
714
715 if (ppDSBuffer8 == NULL) {
716 WARN("invalid parameter: ppDSBuffer8 == NULL\n");
717 *ppDSFD = NULL;
718 return DSERR_INVALIDPARAM;
719 }
720
721 hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (LPDIRECTSOUNDFULLDUPLEX*)&This);
722 if (FAILED(hres)) return hres;
723
724 hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
725 pcGuidCaptureDevice,
726 pcGuidRenderDevice,
727 pcDSCBufferDesc,
728 pcDSBufferDesc,
729 hWnd, dwLevel, ppDSCBuffer8,
730 ppDSBuffer8);
731 if (hres != DS_OK) {
732 IUnknown_Release((LPDIRECTSOUNDFULLDUPLEX)This);
733 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
734 *ppDSFD = NULL;
735 } else
736 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
737
738 return hres;
739 }
740