dmusic: Midi message takes 4 bytes space but only 3 are relevant.
[wine/multimedia.git] / dlls / dsound / duplex.c
blobe3477ea016b71320f2ab82404bdc3a36c38258c0
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 fields */
46 const IDirectSoundFullDuplexVtbl *lpVtbl;
47 LONG ref;
49 /* IDirectSoundFullDuplexImpl fields */
50 IDirectSound8 *renderer_device;
51 IDirectSoundCapture *capture_device;
53 LPUNKNOWN pUnknown;
54 LPDIRECTSOUND8 pDS8;
55 LPDIRECTSOUNDCAPTURE pDSC;
56 } IDirectSoundFullDuplexImpl;
58 typedef struct IDirectSoundFullDuplex_IUnknown {
59 const IUnknownVtbl *lpVtbl;
60 LONG ref;
61 IDirectSoundFullDuplexImpl *pdsfd;
62 } IDirectSoundFullDuplex_IUnknown;
64 typedef struct IDirectSoundFullDuplex_IDirectSound8 {
65 const IDirectSound8Vtbl *lpVtbl;
66 LONG ref;
67 IDirectSoundFullDuplexImpl *pdsfd;
68 } IDirectSoundFullDuplex_IDirectSound8;
70 typedef struct IDirectSoundFullDuplex_IDirectSoundCapture {
71 const IDirectSoundCaptureVtbl *lpVtbl;
72 LONG ref;
73 IDirectSoundFullDuplexImpl *pdsfd;
74 } IDirectSoundFullDuplex_IDirectSoundCapture;
76 /*******************************************************************************
77 * IUnknown
79 static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
80 LPUNKNOWN iface,
81 REFIID riid,
82 LPVOID * ppobj)
84 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
85 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
86 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
89 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
90 LPUNKNOWN iface)
92 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
93 ULONG ref = InterlockedIncrement(&(This->ref));
94 TRACE("(%p) ref was %d\n", This, ref - 1);
95 return ref;
98 static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
99 LPUNKNOWN iface)
101 IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
102 ULONG ref = InterlockedDecrement(&(This->ref));
103 TRACE("(%p) ref was %d\n", This, ref + 1);
104 if (!ref) {
105 This->pdsfd->pUnknown = NULL;
106 HeapFree(GetProcessHeap(), 0, This);
107 TRACE("(%p) released\n", This);
109 return ref;
112 static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
114 IDirectSoundFullDuplex_IUnknown_QueryInterface,
115 IDirectSoundFullDuplex_IUnknown_AddRef,
116 IDirectSoundFullDuplex_IUnknown_Release
119 static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
120 LPDIRECTSOUNDFULLDUPLEX pdsfd,
121 LPUNKNOWN * ppunk)
123 IDirectSoundFullDuplex_IUnknown * pdsfdunk;
124 TRACE("(%p,%p)\n",pdsfd,ppunk);
126 if (pdsfd == NULL) {
127 ERR("invalid parameter: pdsfd == NULL\n");
128 return DSERR_INVALIDPARAM;
131 if (ppunk == NULL) {
132 ERR("invalid parameter: ppunk == NULL\n");
133 return DSERR_INVALIDPARAM;
136 pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
137 if (pdsfdunk == NULL) {
138 WARN("out of memory\n");
139 *ppunk = NULL;
140 return DSERR_OUTOFMEMORY;
143 pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
144 pdsfdunk->ref = 0;
145 pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
147 *ppunk = (LPUNKNOWN)pdsfdunk;
149 return DS_OK;
152 /*******************************************************************************
153 * IDirectSoundFullDuplex_IDirectSound8
155 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
156 LPDIRECTSOUND8 iface,
157 REFIID riid,
158 LPVOID * ppobj)
160 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
161 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
162 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
165 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
166 LPDIRECTSOUND8 iface)
168 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
169 ULONG ref = InterlockedIncrement(&(This->ref));
170 TRACE("(%p) ref was %d\n", This, ref - 1);
171 return ref;
174 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
175 LPDIRECTSOUND8 iface)
177 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
178 ULONG ref = InterlockedDecrement(&(This->ref));
179 TRACE("(%p) ref was %d\n", This, ref + 1);
180 if (!ref) {
181 This->pdsfd->pDS8 = NULL;
182 HeapFree(GetProcessHeap(), 0, This);
183 TRACE("(%p) released\n", This);
185 return ref;
188 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
189 LPDIRECTSOUND8 iface,
190 LPCDSBUFFERDESC dsbd,
191 LPLPDIRECTSOUNDBUFFER ppdsb,
192 LPUNKNOWN lpunk)
194 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
195 TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
196 return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk);
199 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
200 LPDIRECTSOUND8 iface,
201 LPDSCAPS lpDSCaps)
203 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
204 TRACE("(%p,%p)\n",This,lpDSCaps);
205 return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
208 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
209 LPDIRECTSOUND8 iface,
210 LPDIRECTSOUNDBUFFER psb,
211 LPLPDIRECTSOUNDBUFFER ppdsb)
213 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
214 TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
215 return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
218 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
219 LPDIRECTSOUND8 iface,
220 HWND hwnd,
221 DWORD level)
223 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
224 TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
225 return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
228 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
229 LPDIRECTSOUND8 iface)
231 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
232 TRACE("(%p)\n", This);
233 return IDirectSound8_Compact(This->pdsfd->renderer_device);
236 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
237 LPDIRECTSOUND8 iface,
238 LPDWORD lpdwSpeakerConfig)
240 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
241 TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
242 return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
245 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
246 LPDIRECTSOUND8 iface,
247 DWORD config)
249 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
250 TRACE("(%p,0x%08x)\n",This,config);
251 return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config);
254 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
255 LPDIRECTSOUND8 iface,
256 LPCGUID lpcGuid)
258 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
259 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
260 return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid);
263 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
264 LPDIRECTSOUND8 iface,
265 DWORD *cert)
267 IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
268 TRACE("(%p, %p)\n", This, cert);
269 return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert);
272 static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
274 IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
275 IDirectSoundFullDuplex_IDirectSound8_AddRef,
276 IDirectSoundFullDuplex_IDirectSound8_Release,
277 IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
278 IDirectSoundFullDuplex_IDirectSound8_GetCaps,
279 IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
280 IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
281 IDirectSoundFullDuplex_IDirectSound8_Compact,
282 IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
283 IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
284 IDirectSoundFullDuplex_IDirectSound8_Initialize,
285 IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
288 static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
289 LPDIRECTSOUNDFULLDUPLEX pdsfd,
290 LPDIRECTSOUND8 * ppds8)
292 IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
293 TRACE("(%p,%p)\n",pdsfd,ppds8);
295 if (pdsfd == NULL) {
296 ERR("invalid parameter: pdsfd == NULL\n");
297 return DSERR_INVALIDPARAM;
300 if (ppds8 == NULL) {
301 ERR("invalid parameter: ppds8 == NULL\n");
302 return DSERR_INVALIDPARAM;
305 if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
306 WARN("not initialized\n");
307 *ppds8 = NULL;
308 return DSERR_UNINITIALIZED;
311 pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
312 if (pdsfdds8 == NULL) {
313 WARN("out of memory\n");
314 *ppds8 = NULL;
315 return DSERR_OUTOFMEMORY;
318 pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
319 pdsfdds8->ref = 0;
320 pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
322 *ppds8 = (LPDIRECTSOUND8)pdsfdds8;
324 return DS_OK;
327 /*******************************************************************************
328 * IDirectSoundFullDuplex_IDirectSoundCapture
330 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
331 LPDIRECTSOUNDCAPTURE iface,
332 REFIID riid,
333 LPVOID * ppobj)
335 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
336 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
337 return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
340 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
341 LPDIRECTSOUNDCAPTURE iface)
343 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
344 ULONG ref = InterlockedIncrement(&(This->ref));
345 TRACE("(%p) ref was %d\n", This, ref - 1);
346 return ref;
349 static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
350 LPDIRECTSOUNDCAPTURE iface)
352 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
353 ULONG ref = InterlockedDecrement(&(This->ref));
354 TRACE("(%p) ref was %d\n", This, ref + 1);
355 if (!ref) {
356 This->pdsfd->pDSC = NULL;
357 HeapFree(GetProcessHeap(), 0, This);
358 TRACE("(%p) released\n", This);
360 return ref;
363 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
364 LPDIRECTSOUNDCAPTURE iface,
365 LPCDSCBUFFERDESC lpcDSCBufferDesc,
366 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
367 LPUNKNOWN pUnk)
369 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
370 TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
371 return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
374 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
375 LPDIRECTSOUNDCAPTURE iface,
376 LPDSCCAPS lpDSCCaps)
378 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
379 TRACE("(%p,%p)\n",This,lpDSCCaps);
380 return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps);
383 static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
384 LPDIRECTSOUNDCAPTURE iface,
385 LPCGUID lpcGUID)
387 IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
388 TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
389 return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID);
392 static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
394 IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
395 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
396 IDirectSoundFullDuplex_IDirectSoundCapture_Release,
397 IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
398 IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
399 IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
402 static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
403 LPDIRECTSOUNDFULLDUPLEX pdsfd,
404 LPDIRECTSOUNDCAPTURE8 * ppdsc8)
406 IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
407 TRACE("(%p,%p)\n",pdsfd,ppdsc8);
409 if (pdsfd == NULL) {
410 ERR("invalid parameter: pdsfd == NULL\n");
411 return DSERR_INVALIDPARAM;
414 if (ppdsc8 == NULL) {
415 ERR("invalid parameter: ppdsc8 == NULL\n");
416 return DSERR_INVALIDPARAM;
419 if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
420 WARN("not initialized\n");
421 *ppdsc8 = NULL;
422 return DSERR_UNINITIALIZED;
425 pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
426 if (pdsfddsc == NULL) {
427 WARN("out of memory\n");
428 *ppdsc8 = NULL;
429 return DSERR_OUTOFMEMORY;
432 pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
433 pdsfddsc->ref = 0;
434 pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
436 *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
438 return DS_OK;
441 /***************************************************************************
442 * IDirectSoundFullDuplexImpl
444 static ULONG WINAPI
445 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
447 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
448 ULONG ref = InterlockedIncrement(&(This->ref));
449 TRACE("(%p) ref was %d\n", This, ref - 1);
450 return ref;
453 static HRESULT WINAPI
454 IDirectSoundFullDuplexImpl_QueryInterface(
455 LPDIRECTSOUNDFULLDUPLEX iface,
456 REFIID riid,
457 LPVOID* ppobj )
459 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
460 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
462 if (ppobj == NULL) {
463 WARN("invalid parameter\n");
464 return E_INVALIDARG;
467 *ppobj = NULL;
469 if (IsEqualIID(riid, &IID_IUnknown)) {
470 if (!This->pUnknown) {
471 IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
472 if (!This->pUnknown) {
473 WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
474 *ppobj = NULL;
475 return E_NOINTERFACE;
478 IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
479 *ppobj = This->pUnknown;
480 return S_OK;
481 } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
482 IDirectSoundFullDuplexImpl_AddRef(iface);
483 *ppobj = This;
484 return S_OK;
485 } else if (IsEqualIID(riid, &IID_IDirectSound)
486 || IsEqualIID(riid, &IID_IDirectSound8)) {
487 if (!This->pDS8) {
488 IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
489 if (!This->pDS8) {
490 WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
491 *ppobj = NULL;
492 return E_NOINTERFACE;
495 IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
496 *ppobj = This->pDS8;
497 return S_OK;
498 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
499 if (!This->pDSC) {
500 IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
501 if (!This->pDSC) {
502 WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
503 *ppobj = NULL;
504 return E_NOINTERFACE;
507 IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
508 *ppobj = This->pDSC;
509 return S_OK;
512 return E_NOINTERFACE;
515 static ULONG WINAPI
516 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
518 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
519 ULONG ref = InterlockedDecrement(&(This->ref));
520 TRACE("(%p) ref was %d\n", This, ref - 1);
522 if (!ref) {
523 if (This->capture_device)
524 IDirectSoundCapture_Release(This->capture_device);
525 if (This->renderer_device)
526 IDirectSound_Release(This->renderer_device);
527 HeapFree( GetProcessHeap(), 0, This );
528 TRACE("(%p) released\n", This);
530 return ref;
533 static HRESULT WINAPI
534 IDirectSoundFullDuplexImpl_Initialize(
535 LPDIRECTSOUNDFULLDUPLEX iface,
536 LPCGUID pCaptureGuid,
537 LPCGUID pRendererGuid,
538 LPCDSCBUFFERDESC lpDscBufferDesc,
539 LPCDSBUFFERDESC lpDsBufferDesc,
540 HWND hWnd,
541 DWORD dwLevel,
542 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
543 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
545 HRESULT hr;
546 IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
548 TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This,
549 debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
550 lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
551 lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
553 if (This->renderer_device != NULL || This->capture_device != NULL) {
554 WARN("already initialized\n");
555 *lplpDirectSoundCaptureBuffer8 = NULL;
556 *lplpDirectSoundBuffer8 = NULL;
557 return DSERR_ALREADYINITIALIZED;
560 hr = DSOUND_Create8(&IID_IDirectSound8, &This->renderer_device);
561 if (SUCCEEDED(hr))
562 hr = IDirectSound_Initialize(This->renderer_device, pRendererGuid);
563 if (hr != DS_OK) {
564 WARN("DirectSoundDevice_Initialize() failed\n");
565 *lplpDirectSoundCaptureBuffer8 = NULL;
566 *lplpDirectSoundBuffer8 = NULL;
567 return hr;
570 IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel);
572 hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc,
573 (IDirectSoundBuffer**)lplpDirectSoundBuffer8, NULL);
574 if (hr != DS_OK) {
575 WARN("IDirectSoundBufferImpl_Create() failed\n");
576 *lplpDirectSoundCaptureBuffer8 = NULL;
577 *lplpDirectSoundBuffer8 = NULL;
578 return hr;
581 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &This->capture_device);
582 if (SUCCEEDED(hr))
583 hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid);
584 if (hr != DS_OK) {
585 WARN("DirectSoundCaptureDevice_Initialize() failed\n");
586 *lplpDirectSoundCaptureBuffer8 = NULL;
587 *lplpDirectSoundBuffer8 = NULL;
588 return hr;
591 hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device,
592 lpDscBufferDesc,
593 (IDirectSoundCaptureBuffer**)lplpDirectSoundCaptureBuffer8,
594 NULL);
595 if (hr != DS_OK) {
596 WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
597 *lplpDirectSoundCaptureBuffer8 = NULL;
598 *lplpDirectSoundBuffer8 = NULL;
599 return hr;
602 return hr;
605 static const IDirectSoundFullDuplexVtbl dsfdvt =
607 /* IUnknown methods */
608 IDirectSoundFullDuplexImpl_QueryInterface,
609 IDirectSoundFullDuplexImpl_AddRef,
610 IDirectSoundFullDuplexImpl_Release,
612 /* IDirectSoundFullDuplex methods */
613 IDirectSoundFullDuplexImpl_Initialize
616 HRESULT DSOUND_FullDuplexCreate(
617 REFIID riid,
618 LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
620 IDirectSoundFullDuplexImpl *This = NULL;
621 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
623 if (ppDSFD == NULL) {
624 WARN("invalid parameter: ppDSFD == NULL\n");
625 return DSERR_INVALIDPARAM;
628 if (!IsEqualIID(riid, &IID_IUnknown) &&
629 !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
630 *ppDSFD = 0;
631 return E_NOINTERFACE;
634 /* Get dsound configuration */
635 setup_dsound_options();
637 This = HeapAlloc(GetProcessHeap(),
638 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
640 if (This == NULL) {
641 WARN("out of memory\n");
642 *ppDSFD = NULL;
643 return DSERR_OUTOFMEMORY;
646 This->lpVtbl = &dsfdvt;
647 This->ref = 1;
648 This->capture_device = NULL;
649 This->renderer_device = NULL;
651 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
653 return DS_OK;
656 /***************************************************************************
657 * DirectSoundFullDuplexCreate [DSOUND.10]
659 * Create and initialize a DirectSoundFullDuplex interface.
661 * PARAMS
662 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
663 * pcGuidRenderDevice [I] Address of sound render device GUID.
664 * pcDSCBufferDesc [I] Address of capture buffer description.
665 * pcDSBufferDesc [I] Address of render buffer description.
666 * hWnd [I] Handle to application window.
667 * dwLevel [I] Cooperative level.
668 * ppDSFD [O] Address where full duplex interface returned.
669 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
670 * ppDSBuffer8 [0] Address where render buffer interface returned.
671 * pUnkOuter [I] Must be NULL.
673 * RETURNS
674 * Success: DS_OK
675 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
676 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
678 HRESULT WINAPI
679 DirectSoundFullDuplexCreate(
680 LPCGUID pcGuidCaptureDevice,
681 LPCGUID pcGuidRenderDevice,
682 LPCDSCBUFFERDESC pcDSCBufferDesc,
683 LPCDSBUFFERDESC pcDSBufferDesc,
684 HWND hWnd,
685 DWORD dwLevel,
686 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
687 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
688 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
689 LPUNKNOWN pUnkOuter)
691 HRESULT hres;
692 IDirectSoundFullDuplexImpl *This = NULL;
693 TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
694 debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
695 pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
696 ppDSBuffer8, pUnkOuter);
698 if (pUnkOuter) {
699 WARN("pUnkOuter != 0\n");
700 *ppDSFD = NULL;
701 return DSERR_NOAGGREGATION;
704 if (pcDSCBufferDesc == NULL) {
705 WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
706 *ppDSFD = NULL;
707 return DSERR_INVALIDPARAM;
710 if (pcDSBufferDesc == NULL) {
711 WARN("invalid parameter: pcDSBufferDesc == NULL\n");
712 *ppDSFD = NULL;
713 return DSERR_INVALIDPARAM;
716 if (ppDSFD == NULL) {
717 WARN("invalid parameter: ppDSFD == NULL\n");
718 return DSERR_INVALIDPARAM;
721 if (ppDSCBuffer8 == NULL) {
722 WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
723 *ppDSFD = NULL;
724 return DSERR_INVALIDPARAM;
727 if (ppDSBuffer8 == NULL) {
728 WARN("invalid parameter: ppDSBuffer8 == NULL\n");
729 *ppDSFD = NULL;
730 return DSERR_INVALIDPARAM;
733 hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (LPDIRECTSOUNDFULLDUPLEX*)&This);
734 if (FAILED(hres)) return hres;
736 hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
737 pcGuidCaptureDevice,
738 pcGuidRenderDevice,
739 pcDSCBufferDesc,
740 pcDSBufferDesc,
741 hWnd, dwLevel, ppDSCBuffer8,
742 ppDSBuffer8);
743 if (hres != DS_OK) {
744 IUnknown_Release((LPDIRECTSOUNDFULLDUPLEX)This);
745 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
746 *ppDSFD = NULL;
747 } else
748 *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
750 return hres;