| /* 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; |
| } |