wine/dlls/dsound/duplex.c
2009-11-30 16:25:11 +01:00

754 lines
25 KiB
C

/* DirectSoundFullDuplex
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Rob Riggs
* Copyright 2000-2001 TransGaming Technologies, Inc.
* Copyright 2005 Robert Reif
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#define CINTERFACE
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "mmsystem.h"
#include "mmddk.h"
#include "winternl.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
#include "dsound_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
/*****************************************************************************
* IDirectSoundFullDuplex implementation structure
*/
typedef struct IDirectSoundFullDuplexImpl
{
/* IUnknown fields */
const IDirectSoundFullDuplexVtbl *lpVtbl;
LONG ref;
/* IDirectSoundFullDuplexImpl fields */
IDirectSound8 *renderer_device;
IDirectSoundCapture *capture_device;
LPUNKNOWN pUnknown;
LPDIRECTSOUND8 pDS8;
LPDIRECTSOUNDCAPTURE pDSC;
} IDirectSoundFullDuplexImpl;
typedef struct IDirectSoundFullDuplex_IUnknown {
const IUnknownVtbl *lpVtbl;
LONG ref;
IDirectSoundFullDuplexImpl *pdsfd;
} IDirectSoundFullDuplex_IUnknown;
typedef struct IDirectSoundFullDuplex_IDirectSound8 {
const IDirectSound8Vtbl *lpVtbl;
LONG ref;
IDirectSoundFullDuplexImpl *pdsfd;
} IDirectSoundFullDuplex_IDirectSound8;
typedef struct IDirectSoundFullDuplex_IDirectSoundCapture {
const IDirectSoundCaptureVtbl *lpVtbl;
LONG ref;
IDirectSoundFullDuplexImpl *pdsfd;
} IDirectSoundFullDuplex_IDirectSoundCapture;
/*******************************************************************************
* IUnknown
*/
static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface(
LPUNKNOWN iface,
REFIID riid,
LPVOID * ppobj)
{
IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
}
static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef(
LPUNKNOWN iface)
{
IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
return ref;
}
static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release(
LPUNKNOWN iface)
{
IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface;
ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
if (!ref) {
This->pdsfd->pUnknown = NULL;
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
}
return ref;
}
static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl =
{
IDirectSoundFullDuplex_IUnknown_QueryInterface,
IDirectSoundFullDuplex_IUnknown_AddRef,
IDirectSoundFullDuplex_IUnknown_Release
};
static HRESULT IDirectSoundFullDuplex_IUnknown_Create(
LPDIRECTSOUNDFULLDUPLEX pdsfd,
LPUNKNOWN * ppunk)
{
IDirectSoundFullDuplex_IUnknown * pdsfdunk;
TRACE("(%p,%p)\n",pdsfd,ppunk);
if (pdsfd == NULL) {
ERR("invalid parameter: pdsfd == NULL\n");
return DSERR_INVALIDPARAM;
}
if (ppunk == NULL) {
ERR("invalid parameter: ppunk == NULL\n");
return DSERR_INVALIDPARAM;
}
pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk));
if (pdsfdunk == NULL) {
WARN("out of memory\n");
*ppunk = NULL;
return DSERR_OUTOFMEMORY;
}
pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl;
pdsfdunk->ref = 0;
pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
*ppunk = (LPUNKNOWN)pdsfdunk;
return DS_OK;
}
/*******************************************************************************
* IDirectSoundFullDuplex_IDirectSound8
*/
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface(
LPDIRECTSOUND8 iface,
REFIID riid,
LPVOID * ppobj)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
}
static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef(
LPDIRECTSOUND8 iface)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
return ref;
}
static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release(
LPDIRECTSOUND8 iface)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
if (!ref) {
This->pdsfd->pDS8 = NULL;
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
}
return ref;
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer(
LPDIRECTSOUND8 iface,
LPCDSBUFFERDESC dsbd,
LPLPDIRECTSOUNDBUFFER ppdsb,
LPUNKNOWN lpunk)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
return IDirectSound8_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps(
LPDIRECTSOUND8 iface,
LPDSCAPS lpDSCaps)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p,%p)\n",This,lpDSCaps);
return IDirectSound8_GetCaps(This->pdsfd->renderer_device, lpDSCaps);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer(
LPDIRECTSOUND8 iface,
LPDIRECTSOUNDBUFFER psb,
LPLPDIRECTSOUNDBUFFER ppdsb)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
return IDirectSound8_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel(
LPDIRECTSOUND8 iface,
HWND hwnd,
DWORD level)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
return IDirectSound8_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact(
LPDIRECTSOUND8 iface)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p)\n", This);
return IDirectSound8_Compact(This->pdsfd->renderer_device);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig(
LPDIRECTSOUND8 iface,
LPDWORD lpdwSpeakerConfig)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
return IDirectSound8_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig(
LPDIRECTSOUND8 iface,
DWORD config)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p,0x%08x)\n",This,config);
return IDirectSound8_SetSpeakerConfig(This->pdsfd->renderer_device,config);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize(
LPDIRECTSOUND8 iface,
LPCGUID lpcGuid)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
return IDirectSound8_Initialize(This->pdsfd->renderer_device,lpcGuid);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_VerifyCertification(
LPDIRECTSOUND8 iface,
DWORD *cert)
{
IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface;
TRACE("(%p, %p)\n", This, cert);
return IDirectSound8_VerifyCertification(This->pdsfd->renderer_device,cert);
}
static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl =
{
IDirectSoundFullDuplex_IDirectSound8_QueryInterface,
IDirectSoundFullDuplex_IDirectSound8_AddRef,
IDirectSoundFullDuplex_IDirectSound8_Release,
IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer,
IDirectSoundFullDuplex_IDirectSound8_GetCaps,
IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer,
IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel,
IDirectSoundFullDuplex_IDirectSound8_Compact,
IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig,
IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig,
IDirectSoundFullDuplex_IDirectSound8_Initialize,
IDirectSoundFullDuplex_IDirectSound8_VerifyCertification
};
static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create(
LPDIRECTSOUNDFULLDUPLEX pdsfd,
LPDIRECTSOUND8 * ppds8)
{
IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8;
TRACE("(%p,%p)\n",pdsfd,ppds8);
if (pdsfd == NULL) {
ERR("invalid parameter: pdsfd == NULL\n");
return DSERR_INVALIDPARAM;
}
if (ppds8 == NULL) {
ERR("invalid parameter: ppds8 == NULL\n");
return DSERR_INVALIDPARAM;
}
if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) {
WARN("not initialized\n");
*ppds8 = NULL;
return DSERR_UNINITIALIZED;
}
pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8));
if (pdsfdds8 == NULL) {
WARN("out of memory\n");
*ppds8 = NULL;
return DSERR_OUTOFMEMORY;
}
pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl;
pdsfdds8->ref = 0;
pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
*ppds8 = (LPDIRECTSOUND8)pdsfdds8;
return DS_OK;
}
/*******************************************************************************
* IDirectSoundFullDuplex_IDirectSoundCapture
*/
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface(
LPDIRECTSOUNDCAPTURE iface,
REFIID riid,
LPVOID * ppobj)
{
IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj);
}
static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(
LPDIRECTSOUNDCAPTURE iface)
{
IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
return ref;
}
static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release(
LPDIRECTSOUNDCAPTURE iface)
{
IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref + 1);
if (!ref) {
This->pdsfd->pDSC = NULL;
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
}
return ref;
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer(
LPDIRECTSOUNDCAPTURE iface,
LPCDSCBUFFERDESC lpcDSCBufferDesc,
LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
LPUNKNOWN pUnk)
{
IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
return IDirectSoundCapture_CreateCaptureBuffer(This->pdsfd->capture_device,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps(
LPDIRECTSOUNDCAPTURE iface,
LPDSCCAPS lpDSCCaps)
{
IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
TRACE("(%p,%p)\n",This,lpDSCCaps);
return IDirectSoundCapture_GetCaps(This->pdsfd->capture_device, lpDSCCaps);
}
static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize(
LPDIRECTSOUNDCAPTURE iface,
LPCGUID lpcGUID)
{
IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface;
TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID));
return IDirectSoundCapture_Initialize(This->pdsfd->capture_device,lpcGUID);
}
static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl =
{
IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface,
IDirectSoundFullDuplex_IDirectSoundCapture_AddRef,
IDirectSoundFullDuplex_IDirectSoundCapture_Release,
IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer,
IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps,
IDirectSoundFullDuplex_IDirectSoundCapture_Initialize
};
static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create(
LPDIRECTSOUNDFULLDUPLEX pdsfd,
LPDIRECTSOUNDCAPTURE8 * ppdsc8)
{
IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc;
TRACE("(%p,%p)\n",pdsfd,ppdsc8);
if (pdsfd == NULL) {
ERR("invalid parameter: pdsfd == NULL\n");
return DSERR_INVALIDPARAM;
}
if (ppdsc8 == NULL) {
ERR("invalid parameter: ppdsc8 == NULL\n");
return DSERR_INVALIDPARAM;
}
if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) {
WARN("not initialized\n");
*ppdsc8 = NULL;
return DSERR_UNINITIALIZED;
}
pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc));
if (pdsfddsc == NULL) {
WARN("out of memory\n");
*ppdsc8 = NULL;
return DSERR_OUTOFMEMORY;
}
pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl;
pdsfddsc->ref = 0;
pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd;
*ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc;
return DS_OK;
}
/***************************************************************************
* IDirectSoundFullDuplexImpl
*/
static ULONG WINAPI
IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
{
IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
ULONG ref = InterlockedIncrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
return ref;
}
static HRESULT WINAPI
IDirectSoundFullDuplexImpl_QueryInterface(
LPDIRECTSOUNDFULLDUPLEX iface,
REFIID riid,
LPVOID* ppobj )
{
IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
if (ppobj == NULL) {
WARN("invalid parameter\n");
return E_INVALIDARG;
}
*ppobj = NULL;
if (IsEqualIID(riid, &IID_IUnknown)) {
if (!This->pUnknown) {
IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown);
if (!This->pUnknown) {
WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n");
*ppobj = NULL;
return E_NOINTERFACE;
}
}
IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown);
*ppobj = This->pUnknown;
return S_OK;
} else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
IDirectSoundFullDuplexImpl_AddRef(iface);
*ppobj = This;
return S_OK;
} else if (IsEqualIID(riid, &IID_IDirectSound)
|| IsEqualIID(riid, &IID_IDirectSound8)) {
if (!This->pDS8) {
IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8);
if (!This->pDS8) {
WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n");
*ppobj = NULL;
return E_NOINTERFACE;
}
}
IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8);
*ppobj = This->pDS8;
return S_OK;
} else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
if (!This->pDSC) {
IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC);
if (!This->pDSC) {
WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n");
*ppobj = NULL;
return E_NOINTERFACE;
}
}
IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC);
*ppobj = This->pDSC;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI
IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
{
IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
ULONG ref = InterlockedDecrement(&(This->ref));
TRACE("(%p) ref was %d\n", This, ref - 1);
if (!ref) {
if (This->capture_device)
IDirectSoundCapture_Release(This->capture_device);
if (This->renderer_device)
IDirectSound_Release(This->renderer_device);
HeapFree( GetProcessHeap(), 0, This );
TRACE("(%p) released\n", This);
}
return ref;
}
static HRESULT WINAPI
IDirectSoundFullDuplexImpl_Initialize(
LPDIRECTSOUNDFULLDUPLEX iface,
LPCGUID pCaptureGuid,
LPCGUID pRendererGuid,
LPCDSCBUFFERDESC lpDscBufferDesc,
LPCDSBUFFERDESC lpDsBufferDesc,
HWND hWnd,
DWORD dwLevel,
LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
{
HRESULT hr;
IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This,
debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid),
lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8);
if (This->renderer_device != NULL || This->capture_device != NULL) {
WARN("already initialized\n");
*lplpDirectSoundCaptureBuffer8 = NULL;
*lplpDirectSoundBuffer8 = NULL;
return DSERR_ALREADYINITIALIZED;
}
hr = DSOUND_Create8(&IID_IDirectSound8, &This->renderer_device);
if (SUCCEEDED(hr))
hr = IDirectSound_Initialize(This->renderer_device, pRendererGuid);
if (hr != DS_OK) {
WARN("DirectSoundDevice_Initialize() failed\n");
*lplpDirectSoundCaptureBuffer8 = NULL;
*lplpDirectSoundBuffer8 = NULL;
return hr;
}
IDirectSound8_SetCooperativeLevel(This->renderer_device, hWnd, dwLevel);
hr = IDirectSound8_CreateSoundBuffer(This->renderer_device, lpDsBufferDesc,
(IDirectSoundBuffer**)lplpDirectSoundBuffer8, NULL);
if (hr != DS_OK) {
WARN("IDirectSoundBufferImpl_Create() failed\n");
*lplpDirectSoundCaptureBuffer8 = NULL;
*lplpDirectSoundBuffer8 = NULL;
return hr;
}
hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &This->capture_device);
if (SUCCEEDED(hr))
hr = IDirectSoundCapture_Initialize(This->capture_device, pCaptureGuid);
if (hr != DS_OK) {
WARN("DirectSoundCaptureDevice_Initialize() failed\n");
*lplpDirectSoundCaptureBuffer8 = NULL;
*lplpDirectSoundBuffer8 = NULL;
return hr;
}
hr = IDirectSoundCapture_CreateCaptureBuffer(This->capture_device,
lpDscBufferDesc,
(IDirectSoundCaptureBuffer**)lplpDirectSoundCaptureBuffer8,
NULL);
if (hr != DS_OK) {
WARN("IDirectSoundCaptureBufferImpl_Create() failed\n");
*lplpDirectSoundCaptureBuffer8 = NULL;
*lplpDirectSoundBuffer8 = NULL;
return hr;
}
return hr;
}
static const IDirectSoundFullDuplexVtbl dsfdvt =
{
/* IUnknown methods */
IDirectSoundFullDuplexImpl_QueryInterface,
IDirectSoundFullDuplexImpl_AddRef,
IDirectSoundFullDuplexImpl_Release,
/* IDirectSoundFullDuplex methods */
IDirectSoundFullDuplexImpl_Initialize
};
HRESULT DSOUND_FullDuplexCreate(
REFIID riid,
LPDIRECTSOUNDFULLDUPLEX* ppDSFD)
{
IDirectSoundFullDuplexImpl *This = NULL;
TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD);
if (ppDSFD == NULL) {
WARN("invalid parameter: ppDSFD == NULL\n");
return DSERR_INVALIDPARAM;
}
if (!IsEqualIID(riid, &IID_IUnknown) &&
!IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) {
*ppDSFD = 0;
return E_NOINTERFACE;
}
/* Get dsound configuration */
setup_dsound_options();
This = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
if (This == NULL) {
WARN("out of memory\n");
*ppDSFD = NULL;
return DSERR_OUTOFMEMORY;
}
This->lpVtbl = &dsfdvt;
This->ref = 1;
This->capture_device = NULL;
This->renderer_device = NULL;
*ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
return DS_OK;
}
/***************************************************************************
* DirectSoundFullDuplexCreate [DSOUND.10]
*
* Create and initialize a DirectSoundFullDuplex interface.
*
* PARAMS
* pcGuidCaptureDevice [I] Address of sound capture device GUID.
* pcGuidRenderDevice [I] Address of sound render device GUID.
* pcDSCBufferDesc [I] Address of capture buffer description.
* pcDSBufferDesc [I] Address of render buffer description.
* hWnd [I] Handle to application window.
* dwLevel [I] Cooperative level.
* ppDSFD [O] Address where full duplex interface returned.
* ppDSCBuffer8 [0] Address where capture buffer interface returned.
* ppDSBuffer8 [0] Address where render buffer interface returned.
* pUnkOuter [I] Must be NULL.
*
* RETURNS
* Success: DS_OK
* Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
* DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
*/
HRESULT WINAPI
DirectSoundFullDuplexCreate(
LPCGUID pcGuidCaptureDevice,
LPCGUID pcGuidRenderDevice,
LPCDSCBUFFERDESC pcDSCBufferDesc,
LPCDSBUFFERDESC pcDSBufferDesc,
HWND hWnd,
DWORD dwLevel,
LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
LPUNKNOWN pUnkOuter)
{
HRESULT hres;
IDirectSoundFullDuplexImpl *This = NULL;
TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n",
debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice),
pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8,
ppDSBuffer8, pUnkOuter);
if (pUnkOuter) {
WARN("pUnkOuter != 0\n");
*ppDSFD = NULL;
return DSERR_NOAGGREGATION;
}
if (pcDSCBufferDesc == NULL) {
WARN("invalid parameter: pcDSCBufferDesc == NULL\n");
*ppDSFD = NULL;
return DSERR_INVALIDPARAM;
}
if (pcDSBufferDesc == NULL) {
WARN("invalid parameter: pcDSBufferDesc == NULL\n");
*ppDSFD = NULL;
return DSERR_INVALIDPARAM;
}
if (ppDSFD == NULL) {
WARN("invalid parameter: ppDSFD == NULL\n");
return DSERR_INVALIDPARAM;
}
if (ppDSCBuffer8 == NULL) {
WARN("invalid parameter: ppDSCBuffer8 == NULL\n");
*ppDSFD = NULL;
return DSERR_INVALIDPARAM;
}
if (ppDSBuffer8 == NULL) {
WARN("invalid parameter: ppDSBuffer8 == NULL\n");
*ppDSFD = NULL;
return DSERR_INVALIDPARAM;
}
hres = DSOUND_FullDuplexCreate(&IID_IDirectSoundFullDuplex, (LPDIRECTSOUNDFULLDUPLEX*)&This);
if (FAILED(hres)) return hres;
hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This,
pcGuidCaptureDevice,
pcGuidRenderDevice,
pcDSCBufferDesc,
pcDSBufferDesc,
hWnd, dwLevel, ppDSCBuffer8,
ppDSBuffer8);
if (hres != DS_OK) {
IUnknown_Release((LPDIRECTSOUNDFULLDUPLEX)This);
WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
*ppDSFD = NULL;
} else
*ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This;
return hres;
}