gdi32: Simplify dibdrv_PutImage a little.
[wine.git] / dlls / dsound / duplex.c
blob4a1fbd20db984770a3a3ee2b7d6b002ee7f78f50
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 "dsdriver.h"
37 #include "dsound_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
41 /*****************************************************************************
42 * IDirectSoundFullDuplex implementation structure
44 typedef struct IDirectSoundFullDuplexImpl
46 /* IUnknown fields */
47 const IDirectSoundFullDuplexVtbl *lpVtbl;
48 LONG ref;
50 /* IDirectSoundFullDuplexImpl fields */
51 IDirectSound8 *renderer_device;
52 IDirectSoundCapture *capture_device;
54 LPUNKNOWN pUnknown;
55 LPDIRECTSOUND8 pDS8;
56 LPDIRECTSOUNDCAPTURE pDSC;
57 } IDirectSoundFullDuplexImpl;
59 typedef struct IDirectSoundFullDuplex_IUnknown {
60 const IUnknownVtbl *lpVtbl;
61 LONG ref;
62 IDirectSoundFullDuplexImpl *pdsfd;
63 } IDirectSoundFullDuplex_IUnknown;
65 typedef struct IDirectSoundFullDuplex_IDirectSound8 {
66 const IDirectSound8Vtbl *lpVtbl;
67 LONG ref;
68 IDirectSoundFullDuplexImpl *pdsfd;
69 } IDirectSoundFullDuplex_IDirectSound8;
71 typedef struct IDirectSoundFullDuplex_IDirectSoundCapture {
72 const IDirectSoundCaptureVtbl *lpVtbl;
73 LONG ref;
74 IDirectSoundFullDuplexImpl *pdsfd;
75 } IDirectSoundFullDuplex_IDirectSoundCapture;
77 /*******************************************************************************
78 * IUnknown
80 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
81 LPUNKNOWN iface,
82 REFIID riid,
83 LPVOID * ppobj)
85 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
86 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
87 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
90 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
91 LPUNKNOWN iface)
93 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
94 ULONG ref = InterlockedIncrement(&(This->ref));
95 TRACE("(%p) ref was %d\n", This, ref - 1);
96 return ref;
99 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
100 LPUNKNOWN iface)
102 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
103 ULONG ref = InterlockedDecrement(&(This->ref));
104 TRACE("(%p) ref was %d\n", This, ref + 1);
105 if (!ref) {
106 This->pdsfd->pUnknown = NULL;
107 HeapFree(GetProcessHeap(), 0, This);
108 TRACE("(%p) released\n", This);
110 return ref;
113 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
115 IDirectSoundFullDuplex_IUnknown_QueryInterface,
116 IDirectSoundFullDuplex_IUnknown_AddRef,
117 IDirectSoundFullDuplex_IUnknown_Release
120 static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
121 LPDIRECTSOUNDFULLDUPLEX pdsfd,
122 LPUNKNOWN * ppunk)
124 IDirectSoundFullDuplex_IUnknown * pdsfdunk;
125 TRACE("(%p,%p)\n",pdsfd,ppunk);
127 if (pdsfd == NULL) {
128 ERR("invalid parameter: pdsfd == NULL\n");
129 return DSERR_INVALIDPARAM;
132 if (ppunk == NULL) {
133 ERR("invalid parameter: ppunk == NULL\n");
134 return DSERR_INVALIDPARAM;
137 pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
138 if (pdsfdunk == NULL) {
139 WARN("out of memory\n");
140 *ppunk = NULL;
141 return DSERR_OUTOFMEMORY;
144 pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
145 pdsfdunk->ref = 0;
146 pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
148 *ppunk = (LPUNKNOWN)pdsfdunk;
150 return DS_OK;
153 /*******************************************************************************
154 * IDirectSoundFullDuplex_IDirectSound8
156 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
157 LPDIRECTSOUND8 iface,
158 REFIID riid,
159 LPVOID * ppobj)
161 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
162 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
163 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
166 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
167 LPDIRECTSOUND8 iface)
169 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
170 ULONG ref = InterlockedIncrement(&(This->ref));
171 TRACE("(%p) ref was %d\n", This, ref - 1);
172 return ref;
175 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
176 LPDIRECTSOUND8 iface)
178 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
179 ULONG ref = InterlockedDecrement(&(This->ref));
180 TRACE("(%p) ref was %d\n", This, ref + 1);
181 if (!ref) {
182 This->pdsfd->pDS8 = NULL;
183 HeapFree(GetProcessHeap(), 0, This);
184 TRACE("(%p) released\n", This);
186 return ref;
189 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
190 LPDIRECTSOUND8 iface,
191 LPCDSBUFFERDESC dsbd,
192 LPLPDIRECTSOUNDBUFFER ppdsb,
193 LPUNKNOWN lpunk)
195 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
196 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
197 return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk);
200 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
201 LPDIRECTSOUND8 iface,
202 LPDSCAPS lpDSCaps)
204 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
205 TRACE("(%p,%p)\n",This,lpDSCaps);
206 return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
209 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
210 LPDIRECTSOUND8 iface,
211 LPDIRECTSOUNDBUFFER psb,
212 LPLPDIRECTSOUNDBUFFER ppdsb)
214 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
215 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
216 return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
219 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
220 LPDIRECTSOUND8 iface,
221 HWND hwnd,
222 DWORD level)
224 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
225 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
226 return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
229 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
230 LPDIRECTSOUND8 iface)
232 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
233 TRACE("(%p)\n", This);
234 return IDirectSound8_Compact(This->pdsfd->renderer_device);
237 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
238 LPDIRECTSOUND8 iface,
239 LPDWORD lpdwSpeakerConfig)
241 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
242 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
243 return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
246 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
247 LPDIRECTSOUND8 iface,
248 DWORD config)
250 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
251 TRACE("(%p,0x%08x)\n",This,config);
252 return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config);
255 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
256 LPDIRECTSOUND8 iface,
257 LPCGUID lpcGuid)
259 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
260 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
261 return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid);
264 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
265 LPDIRECTSOUND8 iface,
266 DWORD *cert)
268 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
269 TRACE("(%p, %p)\n", This, cert);
270 return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert);
273 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
275 IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
276 IDirectSoundFullDuplex_IDirectSound8_AddRef,
277 IDirectSoundFullDuplex_IDirectSound8_Release,
278 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
279 IDirectSoundFullDuplex_IDirectSound8_GetCaps,
280 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
281 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
282 IDirectSoundFullDuplex_IDirectSound8_Compact,
283 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
284 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
285 IDirectSoundFullDuplex_IDirectSound8_Initialize,
286 IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
289 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
290 LPDIRECTSOUNDFULLDUPLEX pdsfd,
291 LPDIRECTSOUND8 * ppds8)
293 IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
294 TRACE("(%p,%p)\n",pdsfd,ppds8);
296 if (pdsfd == NULL) {
297 ERR("invalid parameter: pdsfd == NULL\n");
298 return DSERR_INVALIDPARAM;
301 if (ppds8 == NULL) {
302 ERR("invalid parameter: ppds8 == NULL\n");
303 return DSERR_INVALIDPARAM;
306 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
307 WARN("not initialized\n");
308 *ppds8 = NULL;
309 return DSERR_UNINITIALIZED;
312 pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
313 if (pdsfdds8 == NULL) {
314 WARN("out of memory\n");
315 *ppds8 = NULL;
316 return DSERR_OUTOFMEMORY;
319 pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
320 pdsfdds8->ref = 0;
321 pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
323 *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
325 return DS_OK;
328 /*******************************************************************************
329 * IDirectSoundFullDuplex_IDirectSoundCapture
331 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
332 LPDIRECTSOUNDCAPTURE iface,
333 REFIID riid,
334 LPVOID * ppobj)
336 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
337 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
338 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
341 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
342 LPDIRECTSOUNDCAPTURE iface)
344 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
345 ULONG ref = InterlockedIncrement(&(This->ref));
346 TRACE("(%p) ref was %d\n", This, ref - 1);
347 return ref;
350 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
351 LPDIRECTSOUNDCAPTURE iface)
353 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
354 ULONG ref = InterlockedDecrement(&(This->ref));
355 TRACE("(%p) ref was %d\n", This, ref + 1);
356 if (!ref) {
357 This->pdsfd->pDSC = NULL;
358 HeapFree(GetProcessHeap(), 0, This);
359 TRACE("(%p) released\n", This);
361 return ref;
364 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
365 LPDIRECTSOUNDCAPTURE iface,
366 LPCDSCBUFFERDESC lpcDSCBufferDesc,
367 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
368 LPUNKNOWN pUnk)
370 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
371 TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
372 return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
375 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
376 LPDIRECTSOUNDCAPTURE iface,
377 LPDSCCAPS lpDSCCaps)
379 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
380 TRACE("(%p,%p)\n",This,lpDSCCaps);
381 return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps);
384 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
385 LPDIRECTSOUNDCAPTURE iface,
386 LPCGUID lpcGUID)
388 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
389 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
390 return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID);
393 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
395 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
396 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
397 IDirectSoundFullDuplex_IDirectSoundCapture_Release,
398 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
399 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
400 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
403 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
404 LPDIRECTSOUNDFULLDUPLEX pdsfd,
405 LPDIRECTSOUNDCAPTURE8 * ppdsc8)
407 IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
408 TRACE("(%p,%p)\n",pdsfd,ppdsc8);
410 if (pdsfd == NULL) {
411 ERR("invalid parameter: pdsfd == NULL\n");
412 return DSERR_INVALIDPARAM;
415 if (ppdsc8 == NULL) {
416 ERR("invalid parameter: ppdsc8 == NULL\n");
417 return DSERR_INVALIDPARAM;
420 if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
421 WARN("not initialized\n");
422 *ppdsc8 = NULL;
423 return DSERR_UNINITIALIZED;
426 pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
427 if (pdsfddsc == NULL) {
428 WARN("out of memory\n");
429 *ppdsc8 = NULL;
430 return DSERR_OUTOFMEMORY;
433 pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
434 pdsfddsc->ref = 0;
435 pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
437 *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
439 return DS_OK;
442 /***************************************************************************
443 * IDirectSoundFullDuplexImpl
445 static ULONG WINAPI
446 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
448 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
449 ULONG ref = InterlockedIncrement(&(This->ref));
450 TRACE("(%p) ref was %d\n", This, ref - 1);
451 return ref;
454 static HRESULT WINAPI
455 IDirectSoundFullDuplexImpl_QueryInterface(
456 LPDIRECTSOUNDFULLDUPLEX iface,
457 REFIID riid,
458 LPVOID* ppobj )
460 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
461 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
463 if (ppobj == NULL) {
464 WARN("invalid parameter\n");
465 return E_INVALIDARG;
468 *ppobj = NULL;
470 if (IsEqualIID(riid, &IID_IUnknown)) {
471 if (!This->pUnknown) {
472 IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
473 if (!This->pUnknown) {
474 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
475 *ppobj = NULL;
476 return E_NOINTERFACE;
479 IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
480 *ppobj = This->pUnknown;
481 return S_OK;
482 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
483 IDirectSoundFullDuplexImpl_AddRef(iface);
484 *ppobj = This;
485 return S_OK;
486 } else if (IsEqualIID(riid, &IID_IDirectSound)
487 || IsEqualIID(riid, &IID_IDirectSound8)) {
488 if (!This->pDS8) {
489 IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
490 if (!This->pDS8) {
491 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
492 *ppobj = NULL;
493 return E_NOINTERFACE;
496 IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
497 *ppobj = This->pDS8;
498 return S_OK;
499 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
500 if (!This->pDSC) {
501 IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
502 if (!This->pDSC) {
503 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
504 *ppobj = NULL;
505 return E_NOINTERFACE;
508 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
509 *ppobj = This->pDSC;
510 return S_OK;
513 return E_NOINTERFACE;
516 static ULONG WINAPI
517 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
519 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
520 ULONG ref = InterlockedDecrement(&(This->ref));
521 TRACE("(%p) ref was %d\n", This, ref - 1);
523 if (!ref) {
524 if (This->capture_device)
525 IDirectSoundCapture_Release(This->capture_device);
526 if (This->renderer_device)
527 IDirectSound_Release(This->renderer_device);
528 HeapFree( GetProcessHeap(), 0, This );
529 TRACE("(%p) released\n", This);
531 return ref;
534 static HRESULT WINAPI
535 IDirectSoundFullDuplexImpl_Initialize(
536 LPDIRECTSOUNDFULLDUPLEX iface,
537 LPCGUID pCaptureGuid,
538 LPCGUID pRendererGuid,
539 LPCDSCBUFFERDESC lpDscBufferDesc,
540 LPCDSBUFFERDESC lpDsBufferDesc,
541 HWND hWnd,
542 DWORD dwLevel,
543 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
544 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
546 HRESULT hr;
547 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
549 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This,
550 debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
551 lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
552 lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
554 if (This->renderer_device != NULL || This->capture_device != NULL) {
555 WARN("already initialized\n");
556 *lplpDirectSoundCaptureBuffer8 = NULL;
557 *lplpDirectSoundBuffer8 = NULL;
558 return DSERR_ALREADYINITIALIZED;
561 hr = DSOUND_Create8(&IID_IDirectSound8, &This->renderer_device);
562 if (SUCCEEDED(hr))
563 hr = IDirectSound_Initialize(This->renderer_device, pRendererGuid);
564 if (hr != DS_OK) {
565 WARN("DirectSoundDevice_Initialize() failed\n");
566 *lplpDirectSoundCaptureBuffer8 = NULL;
567 *lplpDirectSoundBuffer8 = NULL;
568 return hr;
571 IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel);
573 hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc,
574 (IDirectSoundBuffer**)lplpDirectSoundBuffer8, NULL);
575 if (hr != DS_OK) {
576 WARN("IDirectSoundBufferImpl_Create() failed\n");
577 *lplpDirectSoundCaptureBuffer8 = NULL;
578 *lplpDirectSoundBuffer8 = NULL;
579 return hr;
582 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &This->capture_device);
583 if (SUCCEEDED(hr))
584 hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid);
585 if (hr != DS_OK) {
586 WARN("DirectSoundCaptureDevice_Initialize() failed\n");
587 *lplpDirectSoundCaptureBuffer8 = NULL;
588 *lplpDirectSoundBuffer8 = NULL;
589 return hr;
592 hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device,
593 lpDscBufferDesc,
594 (IDirectSoundCaptureBuffer**)lplpDirectSoundCaptureBuffer8,
595 NULL);
596 if (hr != DS_OK) {
597 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
598 *lplpDirectSoundCaptureBuffer8 = NULL;
599 *lplpDirectSoundBuffer8 = NULL;
600 return hr;
603 return hr;
606 static const IDirectSoundFullDuplexVtbl dsfdvt =
608 /* IUnknown methods */
609 IDirectSoundFullDuplexImpl_QueryInterface,
610 IDirectSoundFullDuplexImpl_AddRef,
611 IDirectSoundFullDuplexImpl_Release,
613 /* IDirectSoundFullDuplex methods */
614 IDirectSoundFullDuplexImpl_Initialize
617 HRESULT DSOUND_FullDuplexCreate(
618 REFIID riid,
619 LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
621 IDirectSoundFullDuplexImpl *This = NULL;
622 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
624 if (ppDSFD == NULL) {
625 WARN("invalid parameter: ppDSFD == NULL\n");
626 return DSERR_INVALIDPARAM;
629 if (!IsEqualIID(riid, &IID_IUnknown) &&
630 !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
631 *ppDSFD = 0;
632 return E_NOINTERFACE;
635 /* Get dsound configuration */
636 setup_dsound_options();
638 This = HeapAlloc(GetProcessHeap(),
639 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
641 if (This == NULL) {
642 WARN("out of memory\n");
643 *ppDSFD = NULL;
644 return DSERR_OUTOFMEMORY;
647 This->lpVtbl = &dsfdvt;
648 This->ref = 1;
649 This->capture_device = NULL;
650 This->renderer_device = NULL;
652 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
654 return DS_OK;
657 /***************************************************************************
658 * DirectSoundFullDuplexCreate [DSOUND.10]
660 * Create and initialize a DirectSoundFullDuplex interface.
662 * PARAMS
663 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
664 * pcGuidRenderDevice [I] Address of sound render device GUID.
665 * pcDSCBufferDesc [I] Address of capture buffer description.
666 * pcDSBufferDesc [I] Address of render buffer description.
667 * hWnd [I] Handle to application window.
668 * dwLevel [I] Cooperative level.
669 * ppDSFD [O] Address where full duplex interface returned.
670 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
671 * ppDSBuffer8 [0] Address where render buffer interface returned.
672 * pUnkOuter [I] Must be NULL.
674 * RETURNS
675 * Success: DS_OK
676 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
677 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
679 HRESULT WINAPI
680 DirectSoundFullDuplexCreate(
681 LPCGUID pcGuidCaptureDevice,
682 LPCGUID pcGuidRenderDevice,
683 LPCDSCBUFFERDESC pcDSCBufferDesc,
684 LPCDSBUFFERDESC pcDSBufferDesc,
685 HWND hWnd,
686 DWORD dwLevel,
687 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
688 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
689 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
690 LPUNKNOWN pUnkOuter)
692 HRESULT hres;
693 IDirectSoundFullDuplexImpl *This = NULL;
694 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
695 debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
696 pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
697 ppDSBuffer8, pUnkOuter);
699 if (pUnkOuter) {
700 WARN("pUnkOuter != 0\n");
701 *ppDSFD = NULL;
702 return DSERR_NOAGGREGATION;
705 if (pcDSCBufferDesc == NULL) {
706 WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
707 *ppDSFD = NULL;
708 return DSERR_INVALIDPARAM;
711 if (pcDSBufferDesc == NULL) {
712 WARN("invalid parameter: pcDSBufferDesc == NULL\n");
713 *ppDSFD = NULL;
714 return DSERR_INVALIDPARAM;
717 if (ppDSFD == NULL) {
718 WARN("invalid parameter: ppDSFD == NULL\n");
719 return DSERR_INVALIDPARAM;
722 if (ppDSCBuffer8 == NULL) {
723 WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
724 *ppDSFD = NULL;
725 return DSERR_INVALIDPARAM;
728 if (ppDSBuffer8 == NULL) {
729 WARN("invalid parameter: ppDSBuffer8 == NULL\n");
730 *ppDSFD = NULL;
731 return DSERR_INVALIDPARAM;
734 hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (LPDIRECTSOUNDFULLDUPLEX*)&This);
735 if (FAILED(hres)) return hres;
737 hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
738 pcGuidCaptureDevice,
739 pcGuidRenderDevice,
740 pcDSCBufferDesc,
741 pcDSBufferDesc,
742 hWnd, dwLevel, ppDSCBuffer8,
743 ppDSBuffer8);
744 if (hres != DS_OK) {
745 IUnknown_Release((LPDIRECTSOUNDFULLDUPLEX)This);
746 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
747 *ppDSFD = NULL;
748 } else
749 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
751 return hres;