363 lines
10 KiB
C++
363 lines
10 KiB
C++
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: dvclient.c
|
|
* Content: Implements functions for the DirectXVoiceClient interface
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 07/02/99 rodtoll Created It
|
|
* 07/26/99 rodtoll Updated QueryInterface to support IDirectXVoiceNotify
|
|
* 08/25/99 rodtoll General Cleanup/Modifications to support new
|
|
* compression sub-system.
|
|
* Added new parameter to GetCompressionTypes
|
|
* 09/03/99 rodtoll Updated parameters for DeleteUserBuffer
|
|
* 09/07/99 rodtoll Updated EnumCompressionTypes so that object doesn't
|
|
* need to be Initialized.
|
|
* 09/10/99 rodtoll Object validity checking
|
|
* 09/14/99 rodtoll Added DVC_SetNotifyMask
|
|
* 10/05/99 rodtoll Reversed destruction order to destroy object before
|
|
* transport. Fixes crash in some situations
|
|
* 10/18/99 rodtoll Fix: Passing NULL in QueryInterface casues crash
|
|
* rodtoll Fix: Calling Initialize twice passes
|
|
* 10/19/99 rodtoll Fix: Bug #113904 - Shutdown issues
|
|
* - Added reference count for notify interface, allows
|
|
* determination if disconnect should be called from release
|
|
* 10/25/99 rodtoll Fix: Bug #114098 - Release/Addref failure from multiple threads
|
|
* 11/17/99 rodtoll Fix: Bug #117447 - Removed checks for initialization because
|
|
* DirectVoiceCLientEngine members already do this.
|
|
* 12/16/99 rodtoll Bug #117405 - 3D Sound APIs misleading - 3d sound apis renamed
|
|
* The Delete3DSoundBuffer was re-worked to match the create
|
|
* 01/14/2000 rodtoll Updated parameters to Get/SetTransmitTargets
|
|
* rodtoll Added new API call GetSoundDeviceConfig
|
|
* 01/27/2000 rodtoll Bug #129934 - Update Create3DSoundBuffer to take DSBUFFERDESC
|
|
* 03/28/2000 rodtoll Removed reference to removed header file.
|
|
* 06/21/2000 rodtoll Bug #35767 - Update Create3DSoundBuffer to take DIRECTSOUNDBUFFERs
|
|
* 08/23/2000 rodtoll DllCanUnloadNow always returning TRUE!
|
|
* 10/05/2000 rodtoll Bug #46541 - DPVOICE: A/V linking to dpvoice.lib could cause application to fail init and crash
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dxvoicepch.h"
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_Release"
|
|
STDAPI DVC_Release(LPDIRECTVOICECLIENTOBJECT lpDV )
|
|
{
|
|
HRESULT hr=S_OK;
|
|
LONG rc;
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( lpDV ) )
|
|
return DVERR_INVALIDOBJECT;
|
|
|
|
DNEnterCriticalSection( &lpDV->csCountLock );
|
|
|
|
if (lpDV->lIntRefCnt == 0)
|
|
{
|
|
DNLeaveCriticalSection( &lpDV->csCountLock );
|
|
return 0;
|
|
}
|
|
|
|
// dec the interface count
|
|
lpDV->lIntRefCnt--;
|
|
|
|
// Special case: Releasing object without stopping session
|
|
// May be more then one transport thread indicating in us
|
|
if( (lpDV->lIntRefCnt == 0) && lpDV->lpDVClientEngine->GetCurrentState() != DVCSTATE_IDLE )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing interface without calling Disconnect" );
|
|
|
|
lpDV->lIntRefCnt = 0;
|
|
|
|
// We must release the lock because stopsession may call back into this function
|
|
DNLeaveCriticalSection( &lpDV->csCountLock );
|
|
|
|
hr = lpDV->lpDVClientEngine->Disconnect( DVFLAGS_SYNC );
|
|
|
|
DNEnterCriticalSection( &lpDV->csCountLock );
|
|
|
|
if( hr != DV_OK && hr != DVERR_SESSIONLOST )
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Disconnect Failed hr=0x%x", hr );
|
|
}
|
|
|
|
}
|
|
|
|
rc = lpDV->lIntRefCnt;
|
|
|
|
if ( lpDV->lIntRefCnt == 0 )
|
|
{
|
|
// Leave the critical section, we may call back into this func.
|
|
// (Shouldn't though).
|
|
DNLeaveCriticalSection( &lpDV->csCountLock );
|
|
|
|
delete lpDV->lpDVClientEngine;
|
|
lpDV->lpDVClientEngine = NULL;
|
|
|
|
if( lpDV->lpDVTransport != 0 )
|
|
{
|
|
DNASSERT( lpDV->lpDVTransport->m_lRefCount == 0 );
|
|
delete lpDV->lpDVTransport;
|
|
lpDV->lpDVTransport = NULL;
|
|
}
|
|
|
|
DNDeleteCriticalSection( &lpDV->csCountLock );
|
|
|
|
DNFree(lpDV);
|
|
|
|
DecrementObjectCount();
|
|
}
|
|
else
|
|
{
|
|
DNLeaveCriticalSection( &lpDV->csCountLock );
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_QueryInterface"
|
|
STDMETHODIMP DVC_QueryInterface(LPDIRECTVOICECLIENTOBJECT lpDVC, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if( ppvObj == NULL ||
|
|
!DNVALID_WRITEPTR( ppvObj, sizeof(LPVOID) ) )
|
|
{
|
|
DPFX(DPFPREP, DVF_ERRORLEVEL, "Invalid pointer passed for object" );
|
|
return DVERR_INVALIDPOINTER;
|
|
}
|
|
|
|
*ppvObj=NULL;
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( lpDVC ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
// hmmm, switch would be cleaner...
|
|
if( IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_IDirectPlayVoiceClient ) )
|
|
{
|
|
*ppvObj = lpDVC;
|
|
DV_AddRef(lpDVC);
|
|
}
|
|
else if( IsEqualIID(riid, IID_IDirectPlayVoiceNotify ) )
|
|
{
|
|
*ppvObj = &lpDVC->dvNotify;
|
|
DV_Notify_AddRef(&lpDVC->dvNotify);
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}//DVC_QueryInterface
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_Connect"
|
|
STDMETHODIMP DVC_Connect(LPDIRECTVOICECLIENTOBJECT This, LPDVSOUNDDEVICECONFIG lpSoundDeviceConfig, LPDVCLIENTCONFIG lpClientConfig, DWORD dwFlags )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
return This->lpDVClientEngine->Connect( lpSoundDeviceConfig, lpClientConfig, dwFlags );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_Disconnect"
|
|
STDMETHODIMP DVC_Disconnect(LPDIRECTVOICECLIENTOBJECT This, DWORD dwFlags)
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
return This->lpDVClientEngine->Disconnect( dwFlags );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_GetSessionDesc"
|
|
STDMETHODIMP DVC_GetSessionDesc(LPDIRECTVOICECLIENTOBJECT This, LPDVSESSIONDESC lpSessionDesc )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
|
|
return This->lpDVClientEngine->GetSessionDesc( lpSessionDesc );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_GetSoundDeviceConfig"
|
|
STDAPI DVC_GetSoundDeviceConfig( LPDIRECTVOICECLIENTOBJECT This, PDVSOUNDDEVICECONFIG pSoundDeviceConfig, PDWORD pdwBufferSize )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
|
|
return This->lpDVClientEngine->GetSoundDeviceConfig( pSoundDeviceConfig, pdwBufferSize );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_GetClientConfig"
|
|
STDMETHODIMP DVC_GetClientConfig(LPDIRECTVOICECLIENTOBJECT This, LPDVCLIENTCONFIG lpClientConfig )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
|
|
return This->lpDVClientEngine->GetClientConfig( lpClientConfig );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_SetClientConfig"
|
|
STDMETHODIMP DVC_SetClientConfig(LPDIRECTVOICECLIENTOBJECT This, LPDVCLIENTCONFIG lpClientConfig )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
|
|
return This->lpDVClientEngine->SetClientConfig( lpClientConfig );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_GetCaps"
|
|
STDMETHODIMP DVC_GetCaps(LPDIRECTVOICECLIENTOBJECT This, LPDVCAPS lpdvCaps )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
|
|
return This->lpDVClientEngine->GetCaps( lpdvCaps );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_GetCompressionTypes"
|
|
STDMETHODIMP DVC_GetCompressionTypes( LPDIRECTVOICECLIENTOBJECT This, LPVOID lpDataBuffer, LPDWORD lpdwSize, LPDWORD lpdwNumElements, DWORD dwFlags)
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
|
|
return This->lpDVClientEngine->GetCompressionTypes( lpDataBuffer, lpdwSize, lpdwNumElements, dwFlags );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_SetTransmitTarget"
|
|
STDMETHODIMP DVC_SetTransmitTarget( LPDIRECTVOICECLIENTOBJECT This, PDVID pdvidTargets, DWORD dwNumTargets, DWORD dwFlags )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
return This->lpDVClientEngine->SetTransmitTarget( pdvidTargets, dwNumTargets, dwFlags );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_GetTransmitTarget"
|
|
STDMETHODIMP DVC_GetTransmitTarget( LPDIRECTVOICECLIENTOBJECT This, LPDVID lpdvidTargets, PDWORD pdwNumElements, DWORD dwFlags )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
return This->lpDVClientEngine->GetTransmitTarget( lpdvidTargets, pdwNumElements, dwFlags );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_Create3DSoundBuffer"
|
|
STDMETHODIMP DVC_Create3DSoundBuffer( LPDIRECTVOICECLIENTOBJECT This, DVID dvidEntity, LPDIRECTSOUNDBUFFER lpdsBuffer, DWORD dwPriority, DWORD dwFlags, LPDIRECTSOUND3DBUFFER *lpSoundBuffer )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
return This->lpDVClientEngine->Create3DSoundBuffer( dvidEntity, lpdsBuffer, dwPriority, dwFlags, lpSoundBuffer );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_Delete3DSoundBuffer"
|
|
STDMETHODIMP DVC_Delete3DSoundBuffer( LPDIRECTVOICECLIENTOBJECT This, DVID dvidBuffer, LPDIRECTSOUND3DBUFFER *lpSoundBuffer )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
{
|
|
return DVERR_INVALIDOBJECT;
|
|
}
|
|
|
|
return This->lpDVClientEngine->Delete3DSoundBuffer( dvidBuffer, lpSoundBuffer );
|
|
}
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DVC_SetNotifyMask"
|
|
STDMETHODIMP DVC_SetNotifyMask( LPDIRECTVOICECLIENTOBJECT This, LPDWORD lpdwMessages, DWORD dwNumElements )
|
|
{
|
|
DNASSERT( This != NULL );
|
|
DNASSERT( This->lpDVEngine != NULL );
|
|
|
|
if( !DV_ValidDirectXVoiceClientObject( This ) )
|
|
return DVERR_INVALIDOBJECT;
|
|
|
|
return This->lpDVClientEngine->SetNotifyMask( lpdwMessages, dwNumElements );
|
|
}
|
|
|