home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Common / src / netvoice.cpp < prev   
Encoding:
C/C++ Source or Header  |  2001-10-31  |  13.7 KB  |  373 lines

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