www.pudn.com > Win32DirectX9.rar > netvoice.cpp
//----------------------------------------------------------------------------- // File: NetVoice.cpp // // Desc: DirectPlay Voice framework class. Feel free to use // this class as a starting point for adding extra functionality. // // // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #ifndef UNDER_CE #ifndef STRICT #define STRICT #endif // !STRICT #include#include #include #include "NetVoice.h" #include "DXUtil.h" //----------------------------------------------------------------------------- // Name: CNetVoice // Desc: //----------------------------------------------------------------------------- CNetVoice::CNetVoice( LPDVMESSAGEHANDLER pfnDirectPlayClientVoiceMessageHandler, LPDVMESSAGEHANDLER pfnDirectPlayServerVoiceMessageHandler ) { m_bHalfDuplex = FALSE; m_pVoiceClient = NULL; m_pVoiceServer = NULL; m_pfnDirectPlayClientVoiceMessageHandler = pfnDirectPlayClientVoiceMessageHandler; m_pfnDirectPlayServerVoiceMessageHandler = pfnDirectPlayServerVoiceMessageHandler; } //----------------------------------------------------------------------------- // Name: ~CNetVoice // Desc: //----------------------------------------------------------------------------- CNetVoice::~CNetVoice() { Free(); } //----------------------------------------------------------------------------- // Name: Init() // Desc: Initializes DirectPlay Voice. // Params: hDlg: the HWND of the parent window for use by the voice setup wizard // bCreateSession: if TRUE then it creates the DirectPlay Voice sesson. // bConnectToSession: if TRUE then it connects to the DirectPlay Voice // session. // pDirectPlay: inteface to the IDirectPlay8Client or // IDirectPlay8Peer interface // pGuidCT: guid of the voice compression codec // pdvClientConfig: client config. Can be NULL if bConnectToSession is FALSE. // lpds: pointer to an existing DirectSound object, or NULL // if none exists yet. //----------------------------------------------------------------------------- HRESULT CNetVoice::Init( HWND hDlg, BOOL bCreateSession, BOOL bConnectToSession, LPUNKNOWN pDirectPlay, DWORD dwSessionType, GUID* pGuidCT, DVCLIENTCONFIG* pdvClientConfig, LPDIRECTSOUND lpds ) { HRESULT hr; // Validate required parameters if( NULL == pDirectPlay ) return E_INVALIDARG; // Typically the host player creates the voice session if( bCreateSession ) { if( FAILED( hr = VoiceSessionCreate( pDirectPlay, dwSessionType, pGuidCT ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionCreate"), hr ); } if( bConnectToSession ) { // Test the voice setup to make sure the voice setup wizard has been run if( FAILED( hr = VoiceSessionTestAudioSetup( hDlg ) ) ) { if( hr == DVERR_USERCANCEL || hr == DVERR_ALREADYPENDING ) return hr; return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionTestAudioSetup"), hr ); } // Typically all of the clients connect to the voice session if( FAILED( hr = VoiceSessionConnect( hDlg, pDirectPlay, pdvClientConfig, lpds ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionConnect"), hr ); } return S_OK; } //----------------------------------------------------------------------------- // Name: Free() // Desc: Frees DirectPlayVoice //----------------------------------------------------------------------------- HRESULT CNetVoice::Free() { HRESULT hr; if( m_pVoiceClient ) { // Have all the clients disconnect from the session if( FAILED( hr = VoiceSessionDisconnect() ) ) return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionDisconnect"), hr ); } if( m_pVoiceServer ) { // Have all the host player destroy the session if( FAILED( hr = VoiceSessionDestroy() ) ) return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionDestroy"), hr ); } return S_OK; } //----------------------------------------------------------------------------- // Name: HostMigrate() // Desc: Starts the DirectPlayVoice session // The host player should call this to create the voice session. It // stores the server interface, and addref's it. //----------------------------------------------------------------------------- HRESULT CNetVoice::HostMigrate( LPDIRECTPLAYVOICESERVER pdvServerInterface ) { if( pdvServerInterface == NULL ) return E_INVALIDARG; SAFE_RELEASE( m_pVoiceServer ); m_pVoiceServer = pdvServerInterface; // Addref the server since we are storing the pointer. m_pVoiceServer->AddRef(); return S_OK; } //----------------------------------------------------------------------------- // Name: VoiceSessionTestAudioSetup() // Desc: Uses IDirectPlayVoiceSetup to test the voice setup. // All clients should call this once to test the voice audio setup. //----------------------------------------------------------------------------- HRESULT CNetVoice::VoiceSessionTestAudioSetup( HWND hDlg ) { HRESULT hr; LPDIRECTPLAYVOICETEST pVoiceSetup = NULL; // Create a DirectPlayVoice setup interface. if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceTest, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceTest, (LPVOID*) &pVoiceSetup) ) ) return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr ); // Check to see if the audio tests have been run yet GUID guidPlayback = DSDEVID_DefaultVoicePlayback; GUID guidCapture = DSDEVID_DefaultVoiceCapture; hr = pVoiceSetup->CheckAudioSetup( &guidPlayback, &guidCapture, hDlg, DVFLAGS_QUERYONLY ); if( hr == DVERR_RUNSETUP ) { // Perform the audio tests, since they need to be done before // any of the DPVoice calls will work. hr = pVoiceSetup->CheckAudioSetup( &guidPlayback, &guidCapture, hDlg, DVFLAGS_ALLOWBACK ); if( FAILED(hr) ) { SAFE_RELEASE( pVoiceSetup ); if( hr == DVERR_USERCANCEL || hr == DVERR_ALREADYPENDING ) return hr; return DXTRACE_ERR_MSGBOX( TEXT("CheckAudioSetup"), hr ); } } // Done with setup SAFE_RELEASE( pVoiceSetup ); return hr; } //----------------------------------------------------------------------------- // Name: VoiceSessionCreate() // Desc: Starts the DirectPlayVoice session // The host player should call this to create the voice session. //----------------------------------------------------------------------------- HRESULT CNetVoice::VoiceSessionCreate( LPUNKNOWN pDirectPlay, DWORD dwSessionType, GUID* pGuidCT ) { HRESULT hr; // Create a DirectPlayVoice server interface. if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceServer, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceServer, (LPVOID*) &m_pVoiceServer ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr ); // Init the DirectPlayVoice server if( FAILED( hr = m_pVoiceServer->Initialize( pDirectPlay, m_pfnDirectPlayServerVoiceMessageHandler, NULL, 0, 0 ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr ); // Setup and start a DirectPlay session based on globals set by user choices // in the config dlg box. DVSESSIONDESC dvSessionDesc; ZeroMemory( &dvSessionDesc, sizeof(DVSESSIONDESC) ); dvSessionDesc.dwSize = sizeof( DVSESSIONDESC ); dvSessionDesc.dwBufferAggressiveness = DVBUFFERAGGRESSIVENESS_DEFAULT; dvSessionDesc.dwBufferQuality = DVBUFFERQUALITY_DEFAULT; dvSessionDesc.dwFlags = 0; dvSessionDesc.dwSessionType = dwSessionType; dvSessionDesc.guidCT = *pGuidCT; if( FAILED( hr = m_pVoiceServer->StartSession( &dvSessionDesc, 0 ) ) ) return DXTRACE_ERR_MSGBOX( TEXT("StartSession"), hr ); return S_OK; } //----------------------------------------------------------------------------- // Name: VoiceSessionConnect() // Desc: Connects to the DirectPlayVoice session. /// All clients should call this once to join the voice session. //----------------------------------------------------------------------------- HRESULT CNetVoice::VoiceSessionConnect( HWND hDlg, LPUNKNOWN pDirectPlay, DVCLIENTCONFIG* pdvClientConfig, LPDIRECTSOUND lpds ) { HRESULT hr; DVSOUNDDEVICECONFIG dvSoundDeviceConfig = {0}; DVSOUNDDEVICECONFIG* pdvSoundDeviceConfig = NULL; // Create a DirectPlayVoice client interface. if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceClient, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceClient, (LPVOID*) &m_pVoiceClient ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr ); goto LCleanReturn; } // Init the DirectPlayVoice client, passing in VoiceMessageHandler() as the // callback handler for any messages sent to us. if( FAILED( hr = m_pVoiceClient->Initialize( pDirectPlay, m_pfnDirectPlayClientVoiceMessageHandler, (LPVOID*) hDlg, // context value 0, 0 ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr ); goto LCleanReturn; } // Setup the DirectPlayVoice sound devices. This just uses the defaults. dvSoundDeviceConfig.dwSize = sizeof( DVSOUNDDEVICECONFIG ); dvSoundDeviceConfig.dwFlags = 0; dvSoundDeviceConfig.guidPlaybackDevice = DSDEVID_DefaultVoicePlayback; dvSoundDeviceConfig.lpdsPlaybackDevice = lpds; dvSoundDeviceConfig.guidCaptureDevice = DSDEVID_DefaultVoiceCapture; dvSoundDeviceConfig.lpdsCaptureDevice = NULL; dvSoundDeviceConfig.hwndAppWindow = hDlg; dvSoundDeviceConfig.lpdsMainBuffer = NULL; dvSoundDeviceConfig.dwMainBufferFlags = 0; dvSoundDeviceConfig.dwMainBufferPriority = 0; // Connect to the voice session if( FAILED( hr = m_pVoiceClient->Connect( &dvSoundDeviceConfig, pdvClientConfig, DVFLAGS_SYNC ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("Connect"), hr ); goto LCleanReturn; } // Talk to everyone in the session DVID dvid; dvid = DVID_ALLPLAYERS; if( FAILED( hr = m_pVoiceClient->SetTransmitTargets( &dvid, 1, 0 ) ) ) { DXTRACE_ERR_MSGBOX( TEXT("SetTransmitTargets"), hr ); goto LCleanReturn; } // Get the sound device config and extract if its half duplex DWORD dwSize; dwSize = 0; hr = m_pVoiceClient->GetSoundDeviceConfig( pdvSoundDeviceConfig, &dwSize ); if( FAILED(hr) && hr != DVERR_BUFFERTOOSMALL ) { DXTRACE_ERR_MSGBOX( TEXT("GetSoundDeviceConfig"), hr ); goto LCleanReturn; } pdvSoundDeviceConfig = (DVSOUNDDEVICECONFIG*) new BYTE[ dwSize ]; if( NULL == pdvSoundDeviceConfig ) { hr = E_OUTOFMEMORY; DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionConnect"), hr ); goto LCleanReturn; } ZeroMemory( pdvSoundDeviceConfig, dwSize ); pdvSoundDeviceConfig->dwSize = sizeof(DVSOUNDDEVICECONFIG); hr = m_pVoiceClient->GetSoundDeviceConfig( pdvSoundDeviceConfig, &dwSize ); if( FAILED(hr) ) { DXTRACE_ERR_MSGBOX( TEXT("GetSoundDeviceConfig"), hr ); goto LCleanReturn; } m_bHalfDuplex = ( (pdvSoundDeviceConfig->dwFlags & DVSOUNDCONFIG_HALFDUPLEX) != 0 ); hr = S_OK; LCleanReturn: SAFE_DELETE_ARRAY( pdvSoundDeviceConfig ); return hr; } //----------------------------------------------------------------------------- // Name: ChangeVoiceClientSettings() // Desc: Changes the client config to globals set by user choices // in the config dlg box. //----------------------------------------------------------------------------- HRESULT CNetVoice::ChangeVoiceClientSettings( DVCLIENTCONFIG* pdvClientConfig ) { HRESULT hr; if( m_pVoiceClient == NULL ) return CO_E_NOTINITIALIZED; // Change the client config if( FAILED( hr = m_pVoiceClient->SetClientConfig( pdvClientConfig) ) ) return DXTRACE_ERR_MSGBOX( TEXT("SetClientConfig"), hr ); return S_OK; } //----------------------------------------------------------------------------- // Name: VoiceSessionDisconnect() // Desc: Disconnects from the DirectPlayVoice session // All clients should call this once to leave the voice session. //----------------------------------------------------------------------------- HRESULT CNetVoice::VoiceSessionDisconnect() { if( m_pVoiceClient ) { m_pVoiceClient->Disconnect( DVFLAGS_SYNC ); SAFE_RELEASE( m_pVoiceClient ); } return S_OK; } //----------------------------------------------------------------------------- // Name: VoiceSessionDestroy() // Desc: Stops the DirectPlayVoice session // The host player should call this once to destroy the voice session. //----------------------------------------------------------------------------- HRESULT CNetVoice::VoiceSessionDestroy() { if( m_pVoiceServer ) { m_pVoiceServer->StopSession( 0 ); SAFE_RELEASE( m_pVoiceServer ); } return S_OK; } #endif // !UNDER_CE