netvoice.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:14k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: NetVoice.cpp
  3. //
  4. // Desc: DirectPlay Voice framework class. Feel free to use 
  5. //       this class as a starting point for adding extra functionality.
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #ifndef UNDER_CE
  10. #ifndef STRICT
  11. #define STRICT
  12. #endif // !STRICT
  13. #include <windows.h>
  14. #include <dxerr9.h>
  15. #include <dvoice.h>
  16. #include "NetVoice.h"
  17. #include "DXUtil.h"
  18. //-----------------------------------------------------------------------------
  19. // Name: CNetVoice
  20. // Desc: 
  21. //-----------------------------------------------------------------------------
  22. CNetVoice::CNetVoice( LPDVMESSAGEHANDLER pfnDirectPlayClientVoiceMessageHandler,
  23.                       LPDVMESSAGEHANDLER pfnDirectPlayServerVoiceMessageHandler )
  24. {
  25.     m_bHalfDuplex  = FALSE;
  26.     m_pVoiceClient = NULL;
  27.     m_pVoiceServer = NULL;
  28.     m_pfnDirectPlayClientVoiceMessageHandler = pfnDirectPlayClientVoiceMessageHandler;
  29.     m_pfnDirectPlayServerVoiceMessageHandler = pfnDirectPlayServerVoiceMessageHandler;
  30. }
  31. //-----------------------------------------------------------------------------
  32. // Name: ~CNetVoice
  33. // Desc: 
  34. //-----------------------------------------------------------------------------
  35. CNetVoice::~CNetVoice()
  36. {
  37.     Free();
  38. }
  39. //-----------------------------------------------------------------------------
  40. // Name: Init()
  41. // Desc: Initializes DirectPlay Voice.  
  42. // Params:  hDlg: the HWND of the parent window for use by the voice setup wizard
  43. //          bCreateSession:     if TRUE then it creates the DirectPlay Voice sesson.
  44. //          bConnectToSession:  if TRUE then it connects to the DirectPlay Voice
  45. //                              session.  
  46. //          pDirectPlay:        inteface to the IDirectPlay8Client or 
  47. //                              IDirectPlay8Peer interface 
  48. //          pGuidCT:            guid of the voice compression codec
  49. //          pdvClientConfig:    client config. Can be NULL if bConnectToSession is FALSE.
  50. //          lpds:               pointer to an existing DirectSound object, or NULL 
  51. //                              if none exists yet.
  52. //-----------------------------------------------------------------------------
  53. HRESULT CNetVoice::Init( HWND hDlg, BOOL bCreateSession, BOOL bConnectToSession,
  54.                          LPUNKNOWN pDirectPlay, DWORD dwSessionType, 
  55.                          GUID* pGuidCT, DVCLIENTCONFIG* pdvClientConfig, LPDIRECTSOUND lpds )
  56. {
  57.     HRESULT hr;
  58.     // Validate required parameters
  59.     if( NULL == pDirectPlay )
  60.         return E_INVALIDARG;
  61.     // Typically the host player creates the voice session 
  62.     if( bCreateSession )
  63.     {
  64.         if( FAILED( hr = VoiceSessionCreate( pDirectPlay, dwSessionType, pGuidCT ) ) )
  65.             return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionCreate"), hr );
  66.     }
  67.     if( bConnectToSession )
  68.     {
  69.         // Test the voice setup to make sure the voice setup wizard has been run
  70.         if( FAILED( hr = VoiceSessionTestAudioSetup( hDlg ) ) )
  71.         {
  72.             if( hr == DVERR_USERCANCEL || hr == DVERR_ALREADYPENDING )
  73.                 return hr;
  74.             
  75.             return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionTestAudioSetup"), hr );
  76.         }
  77.         // Typically all of the clients connect to the voice session
  78.         if( FAILED( hr = VoiceSessionConnect( hDlg, pDirectPlay, pdvClientConfig, lpds ) ) )
  79.             return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionConnect"), hr );
  80.     }
  81.     return S_OK;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Name: Free()
  85. // Desc: Frees DirectPlayVoice
  86. //-----------------------------------------------------------------------------
  87. HRESULT CNetVoice::Free()
  88. {
  89.     HRESULT hr;
  90.     if( m_pVoiceClient )
  91.     {
  92.         // Have all the clients disconnect from the session
  93.         if( FAILED( hr = VoiceSessionDisconnect() ) )
  94.             return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionDisconnect"), hr );
  95.     }
  96.     if( m_pVoiceServer )
  97.     {
  98.         // Have all the host player destroy the session 
  99.         if( FAILED( hr = VoiceSessionDestroy() ) )
  100.             return DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionDestroy"), hr );
  101.     }
  102.     return S_OK;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Name: HostMigrate()
  106. // Desc: Starts the DirectPlayVoice session
  107. //       The host player should call this to create the voice session.  It
  108. //       stores the server interface, and addref's it.
  109. //-----------------------------------------------------------------------------
  110. HRESULT CNetVoice::HostMigrate( LPDIRECTPLAYVOICESERVER pdvServerInterface )
  111. {
  112.     if( pdvServerInterface == NULL )
  113.         return E_INVALIDARG;
  114.     SAFE_RELEASE( m_pVoiceServer );
  115.     m_pVoiceServer = pdvServerInterface;
  116.     // Addref the server since we are storing the pointer.
  117.     m_pVoiceServer->AddRef();
  118.     return S_OK;
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Name: VoiceSessionTestAudioSetup()
  122. // Desc: Uses IDirectPlayVoiceSetup to test the voice setup.
  123. //       All clients should call this once to test the voice audio setup.
  124. //-----------------------------------------------------------------------------
  125. HRESULT CNetVoice::VoiceSessionTestAudioSetup( HWND hDlg )
  126. {
  127.     HRESULT hr;
  128.     LPDIRECTPLAYVOICETEST pVoiceSetup = NULL;
  129.     // Create a DirectPlayVoice setup interface.
  130.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceTest, NULL, 
  131.                                        CLSCTX_INPROC_SERVER,
  132.                                        IID_IDirectPlayVoiceTest, 
  133.                                        (LPVOID*) &pVoiceSetup) ) )
  134.         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  135.     // Check to see if the audio tests have been run yet
  136.     GUID guidPlayback = DSDEVID_DefaultVoicePlayback;
  137.     GUID guidCapture  = DSDEVID_DefaultVoiceCapture;
  138.     hr = pVoiceSetup->CheckAudioSetup( &guidPlayback, 
  139.                                        &guidCapture, 
  140.                                        hDlg, DVFLAGS_QUERYONLY );
  141.     if( hr == DVERR_RUNSETUP )
  142.     {
  143.         // Perform the audio tests, since they need to be done before 
  144.         // any of the DPVoice calls will work.
  145.         hr = pVoiceSetup->CheckAudioSetup( &guidPlayback, &guidCapture, hDlg, DVFLAGS_ALLOWBACK );
  146.         if( FAILED(hr) )
  147.         {
  148.             SAFE_RELEASE( pVoiceSetup );
  149.             
  150.             if( hr == DVERR_USERCANCEL || hr == DVERR_ALREADYPENDING )
  151.                 return hr;
  152.             return DXTRACE_ERR_MSGBOX( TEXT("CheckAudioSetup"), hr );
  153.         }
  154.     }
  155.     // Done with setup
  156.     SAFE_RELEASE( pVoiceSetup );
  157.     return hr;
  158. }
  159. //-----------------------------------------------------------------------------
  160. // Name: VoiceSessionCreate()
  161. // Desc: Starts the DirectPlayVoice session
  162. //       The host player should call this to create the voice session.
  163. //-----------------------------------------------------------------------------
  164. HRESULT CNetVoice::VoiceSessionCreate( LPUNKNOWN pDirectPlay, DWORD dwSessionType, 
  165.                                        GUID* pGuidCT )
  166. {
  167.     HRESULT hr;
  168.     // Create a DirectPlayVoice server interface.
  169.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceServer, NULL, 
  170.                                        CLSCTX_INPROC_SERVER,
  171.                                        IID_IDirectPlayVoiceServer, 
  172.                                        (LPVOID*) &m_pVoiceServer ) ) )
  173.         return DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  174.     // Init the DirectPlayVoice server
  175.     if( FAILED( hr = m_pVoiceServer->Initialize( pDirectPlay, m_pfnDirectPlayServerVoiceMessageHandler, 
  176.                                                  NULL, 0, 0 ) ) )
  177.         return DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr );
  178.     // Setup and start a DirectPlay session based on globals set by user choices 
  179.     // in the config dlg box.
  180.     DVSESSIONDESC dvSessionDesc;
  181.     ZeroMemory( &dvSessionDesc, sizeof(DVSESSIONDESC) );
  182.     dvSessionDesc.dwSize                 = sizeof( DVSESSIONDESC );
  183.     dvSessionDesc.dwBufferAggressiveness = DVBUFFERAGGRESSIVENESS_DEFAULT;
  184.     dvSessionDesc.dwBufferQuality        = DVBUFFERQUALITY_DEFAULT;
  185.     dvSessionDesc.dwFlags                = 0;
  186.     dvSessionDesc.dwSessionType          = dwSessionType;
  187.     dvSessionDesc.guidCT                 = *pGuidCT;
  188.     if( FAILED( hr = m_pVoiceServer->StartSession( &dvSessionDesc, 0 ) ) )
  189.         return DXTRACE_ERR_MSGBOX( TEXT("StartSession"), hr );
  190.     return S_OK;
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Name: VoiceSessionConnect()
  194. // Desc: Connects to the DirectPlayVoice session.  
  195. ///      All clients should call this once to join the voice session.
  196. //-----------------------------------------------------------------------------
  197. HRESULT CNetVoice::VoiceSessionConnect( HWND hDlg, LPUNKNOWN pDirectPlay, 
  198.                                         DVCLIENTCONFIG* pdvClientConfig, LPDIRECTSOUND lpds )
  199. {
  200.     HRESULT hr;
  201.     DVSOUNDDEVICECONFIG  dvSoundDeviceConfig  = {0};
  202.     DVSOUNDDEVICECONFIG* pdvSoundDeviceConfig = NULL;
  203.     
  204.     // Create a DirectPlayVoice client interface.
  205.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceClient, NULL, 
  206.                                        CLSCTX_INPROC_SERVER,
  207.                                        IID_IDirectPlayVoiceClient, 
  208.                                        (LPVOID*) &m_pVoiceClient ) ) )
  209.     {
  210.         DXTRACE_ERR_MSGBOX( TEXT("CoCreateInstance"), hr );
  211.         goto LCleanReturn;
  212.     }
  213.     // Init the DirectPlayVoice client, passing in VoiceMessageHandler() as the
  214.     // callback handler for any messages sent to us.
  215.     if( FAILED( hr = m_pVoiceClient->Initialize( pDirectPlay, 
  216.                                                  m_pfnDirectPlayClientVoiceMessageHandler, 
  217.                                                  (LPVOID*) hDlg, // context value
  218.                                                  0, 0 ) ) )
  219.     {
  220.          DXTRACE_ERR_MSGBOX( TEXT("Initialize"), hr );
  221.          goto LCleanReturn;
  222.     }
  223.     // Setup the DirectPlayVoice sound devices.  This just uses the defaults.
  224.     dvSoundDeviceConfig.dwSize                    = sizeof( DVSOUNDDEVICECONFIG );
  225.     dvSoundDeviceConfig.dwFlags                   = 0;
  226.     dvSoundDeviceConfig.guidPlaybackDevice        = DSDEVID_DefaultVoicePlayback; 
  227.     dvSoundDeviceConfig.lpdsPlaybackDevice        = lpds;
  228.     dvSoundDeviceConfig.guidCaptureDevice         = DSDEVID_DefaultVoiceCapture; 
  229.     dvSoundDeviceConfig.lpdsCaptureDevice         = NULL;
  230.     dvSoundDeviceConfig.hwndAppWindow             = hDlg;
  231.     dvSoundDeviceConfig.lpdsMainBuffer            = NULL;
  232.     dvSoundDeviceConfig.dwMainBufferFlags         = 0;
  233.     dvSoundDeviceConfig.dwMainBufferPriority      = 0;
  234.     // Connect to the voice session
  235.     if( FAILED( hr = m_pVoiceClient->Connect( &dvSoundDeviceConfig, 
  236.                                               pdvClientConfig, 
  237.                                               DVFLAGS_SYNC ) ) )
  238.     {
  239.         DXTRACE_ERR_MSGBOX( TEXT("Connect"), hr );
  240.         goto LCleanReturn;
  241.     }
  242.         
  243.     // Talk to everyone in the session
  244.     DVID dvid;
  245.     dvid = DVID_ALLPLAYERS;
  246.     if( FAILED( hr = m_pVoiceClient->SetTransmitTargets( &dvid, 1, 0 ) ) )
  247.     {
  248.         DXTRACE_ERR_MSGBOX( TEXT("SetTransmitTargets"), hr );
  249.         goto LCleanReturn;
  250.     }
  251.     // Get the sound device config and extract if its half duplex
  252.     DWORD dwSize;
  253.     dwSize = 0;
  254.     hr = m_pVoiceClient->GetSoundDeviceConfig( pdvSoundDeviceConfig, &dwSize );
  255.     if( FAILED(hr) && hr != DVERR_BUFFERTOOSMALL )
  256.     {
  257.         DXTRACE_ERR_MSGBOX( TEXT("GetSoundDeviceConfig"), hr );
  258.         goto LCleanReturn;
  259.     }
  260.     pdvSoundDeviceConfig = (DVSOUNDDEVICECONFIG*) new BYTE[ dwSize ];
  261.     if( NULL == pdvSoundDeviceConfig )
  262.     {
  263.         hr = E_OUTOFMEMORY;
  264.         DXTRACE_ERR_MSGBOX( TEXT("VoiceSessionConnect"), hr );
  265.         goto LCleanReturn;
  266.     }
  267.     ZeroMemory( pdvSoundDeviceConfig, dwSize );
  268.     pdvSoundDeviceConfig->dwSize = sizeof(DVSOUNDDEVICECONFIG);
  269.     hr = m_pVoiceClient->GetSoundDeviceConfig( pdvSoundDeviceConfig, &dwSize );
  270.     if( FAILED(hr) )
  271.     {
  272.         DXTRACE_ERR_MSGBOX( TEXT("GetSoundDeviceConfig"), hr );
  273.         goto LCleanReturn;
  274.     }
  275.     m_bHalfDuplex = ( (pdvSoundDeviceConfig->dwFlags & DVSOUNDCONFIG_HALFDUPLEX) != 0 );
  276.     
  277.     hr = S_OK;
  278. LCleanReturn:
  279.     SAFE_DELETE_ARRAY( pdvSoundDeviceConfig );
  280.     return hr;
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Name: ChangeVoiceClientSettings()
  284. // Desc: Changes the client config to globals set by user choices 
  285. //       in the config dlg box.
  286. //-----------------------------------------------------------------------------
  287. HRESULT CNetVoice::ChangeVoiceClientSettings( DVCLIENTCONFIG* pdvClientConfig )
  288. {
  289.     HRESULT hr;
  290.     if( m_pVoiceClient == NULL )
  291.         return CO_E_NOTINITIALIZED;
  292.     // Change the client config
  293.     if( FAILED( hr = m_pVoiceClient->SetClientConfig( pdvClientConfig) ) )
  294.         return DXTRACE_ERR_MSGBOX( TEXT("SetClientConfig"), hr );
  295.     return S_OK;
  296. }
  297. //-----------------------------------------------------------------------------
  298. // Name: VoiceSessionDisconnect()
  299. // Desc: Disconnects from the DirectPlayVoice session
  300. //       All clients should call this once to leave the voice session.
  301. //-----------------------------------------------------------------------------
  302. HRESULT CNetVoice::VoiceSessionDisconnect()
  303. {
  304.     if( m_pVoiceClient )
  305.     {
  306.         m_pVoiceClient->Disconnect( DVFLAGS_SYNC );
  307.         SAFE_RELEASE( m_pVoiceClient );
  308.     }
  309.     return S_OK;
  310. }
  311. //-----------------------------------------------------------------------------
  312. // Name: VoiceSessionDestroy()
  313. // Desc: Stops the DirectPlayVoice session
  314. //       The host player should call this once to destroy the voice session.
  315. //-----------------------------------------------------------------------------
  316. HRESULT CNetVoice::VoiceSessionDestroy()
  317. {
  318.     if( m_pVoiceServer )
  319.     {
  320.         m_pVoiceServer->StopSession( 0 );
  321.         SAFE_RELEASE( m_pVoiceServer );
  322.     }
  323.     return S_OK;
  324. }
  325. #endif // !UNDER_CE