home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / directplay / voiceposition / voiceposition.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  76.1 KB  |  1,919 lines

  1. //-----------------------------------------------------------------------------
  2. // File: VoicePosition.cpp
  3. //
  4. // Desc: The main file for VoicePosition that shows how use DirectPlay along 
  5. //       with DirectPlayVoice to allow talking in a conference situation. 
  6. //
  7. // Copyright (c) 1999-2000 Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #define D3D_OVERLOADS
  11. #include <windows.h>
  12. #include <basetsd.h>
  13. #include <cguid.h>
  14. #include <stdio.h>
  15. #include <dxerr8.h>
  16. #include <d3dtypes.h>
  17. #include <dplay8.h>
  18. #include <dplobby8.h>
  19. #include <dvoice.h>
  20. #include <commctrl.h>
  21. #include <cguid.h>
  22. #include "NetConnect.h"
  23. #include "NetVoice.h"
  24. #include "DXUtil.h"
  25. #include "resource.h"
  26.  
  27.  
  28.  
  29.  
  30. //-----------------------------------------------------------------------------
  31. // Player context locking defines
  32. //-----------------------------------------------------------------------------
  33. CRITICAL_SECTION g_csPlayerContext;
  34. #define PLAYER_LOCK()                   EnterCriticalSection( &g_csPlayerContext ); 
  35. #define PLAYER_ADDREF( pPlayerInfo )    if( pPlayerInfo ) pPlayerInfo->lRefCount++;
  36. #define PLAYER_RELEASE( pPlayerInfo )   if( pPlayerInfo ) { pPlayerInfo->lRefCount--; if( pPlayerInfo->lRefCount <= 0 ) { DeleteCriticalSection( &pPlayerInfo->csPlayer ); SAFE_DELETE( pPlayerInfo );}  } pPlayerInfo = NULL;
  37. #define PLAYER_UNLOCK()                 LeaveCriticalSection( &g_csPlayerContext );
  38.  
  39.  
  40. //-----------------------------------------------------------------------------
  41. // Defines, and constants
  42. //-----------------------------------------------------------------------------
  43. #define DPLAY_SAMPLE_KEY        TEXT("Software\\Microsoft\\DirectX DirectPlay Samples")
  44. #define MAP_WIDTH               100
  45. #define MAP_HEIGHT              100
  46. #define MAX_PLAYER_NAME         14
  47. #define WM_APP_DISPLAY_PLAYERS  (WM_APP + 0)
  48. #define WM_APP_UPDATE_GRID      (WM_APP + 1)
  49. #define START_POSITION_X        ( MAP_WIDTH  / 2 )
  50. #define START_POSITION_Y        ( MAP_HEIGHT / 2 )
  51.  
  52. // This GUID allows DirectPlay to find other instances of the same game on
  53. // the network.  So it must be unique for every game, and the same for 
  54. // every instance of that game.  // {9363CC5D-F8BE-47cf-A288-E4DD73F0BCA6}
  55. GUID g_guidApp = { 0x9363cc5d, 0xf8be, 0x47cf, { 0xa2, 0x88, 0xe4, 0xdd, 0x73, 0xf0, 0xbc, 0xa6 } };
  56.  
  57. struct APP_PLAYER_INFO
  58. {
  59.     LONG         lRefCount;                        // Ref count so we can cleanup when all threads 
  60.                                                    // are done w/ this object
  61.     CRITICAL_SECTION csPlayer;                     // Critical section for DSB voice 
  62.     DPNID        dpnidPlayer;                      // dpnid of the player
  63.     BOOL         bTalking;                         // Is the player talking
  64.     BOOL         bHalfDuplex;                      // If true, then player cannot talk
  65.     POINT        pt;                               // Location of player
  66.     LPDIRECTSOUND3DBUFFER pDSBVoice;               // DirectSound 3D buffer for player
  67.     TCHAR        strPlayerName[MAX_PLAYER_NAME];   // Player name
  68. };
  69.  
  70.  
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // App specific DirectPlay messages and structures 
  75. //-----------------------------------------------------------------------------
  76. #define GAME_MSGID_PLAYERMOVED      1
  77.  
  78. // Change compiler pack alignment to be BYTE aligned, and pop the current value
  79. #pragma pack( push, 1 )
  80.  
  81. struct GAMEMSG_GENERIC
  82. {
  83.     DWORD dwType;
  84. };
  85.  
  86. struct GAMEMSG_PLAYERMOVED : public GAMEMSG_GENERIC
  87. {
  88.     POINT pt;
  89. };
  90.  
  91. // Pop the old pack alignment
  92. #pragma pack( pop )
  93.  
  94.  
  95.  
  96. //-----------------------------------------------------------------------------
  97. // Global variables
  98. //-----------------------------------------------------------------------------
  99. HINSTANCE          g_hInst                       = NULL;    // HINST of app
  100. HWND               g_hDlg                        = NULL;    // HWND of main dialog
  101. IDirectPlay8Peer*  g_pDP                         = NULL;    // DirectPlay peer object
  102. CNetConnectWizard* g_pNetConnectWizard           = NULL;    // Connection wizard
  103. CNetVoice*         g_pNetVoice                   = NULL;    // DirectPlay voice helper class
  104. IDirectPlay8LobbiedApplication* g_pLobbiedApp    = NULL;    // DirectPlay lobbied app 
  105. BOOL               g_bWasLobbyLaunched           = FALSE;   // TRUE if lobby launched
  106. TCHAR              g_strAppName[256]             = TEXT("VoicePosition");
  107. APP_PLAYER_INFO*   g_pPlayerLocal                = NULL;    // APP_PLAYER_INFO* of local player
  108. BOOL               g_bVoiceSessionInProgress     = FALSE;   // True if voice has been init'ed
  109. DPNID*             g_pPlayers                    = NULL;    // Array of DPNIDs
  110. DWORD              g_dwPlayersArraySize          = 0;       // Size of g_pPlayers
  111. HRESULT            g_hrDialog;                              // Exit code for app 
  112. TCHAR              g_strLocalPlayerName[MAX_PATH];          // Local player name
  113. TCHAR              g_strSessionName[MAX_PATH];              // Session name
  114. TCHAR              g_strPreferredProvider[MAX_PATH];        // Provider string
  115. BOOL               g_bHostPlayer                 = FALSE;   // TRUE if local player is host
  116. DPNID              g_LocalPlayerDPNID            = 0;       // DPNID of local player
  117. GUID               g_guidDVSessionCT;                       // GUID for choosen voice compression
  118. DVCLIENTCONFIG     g_dvClientConfig;                        // Voice client config
  119. LPDIRECTSOUND3DLISTENER g_pDSListener            = NULL;    // DirectSound 3D listener
  120. LPDIRECTSOUND      g_pDS                         = NULL;    // DirectSound object
  121. HANDLE             g_hSoundInit                  = NULL;    // Signaled if DirectSound inited
  122.  
  123.  
  124.  
  125.  
  126. //-----------------------------------------------------------------------------
  127. // Function-prototypes
  128. //-----------------------------------------------------------------------------
  129. INT_PTR CALLBACK VoiceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  130. HRESULT WINAPI   DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  131. HRESULT WINAPI   DirectPlayLobbyMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  132. HRESULT WINAPI   DirectPlayVoiceClientMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  133. HRESULT WINAPI   DirectPlayVoiceServerMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  134. HRESULT          InitDirectPlay();
  135. HRESULT          OnInitDialog( HWND hDlg );
  136. HRESULT          InitDirectSound( HWND hDlg );
  137. HRESULT          DisplayPlayersInChat( HWND hDlg );
  138. HRESULT          SendLocalPosition( HWND hDlg );
  139. VOID             DrawDotOnGrid( HWND hWndGrid, HDC hDC, BOOL bLocalDot, FLOAT fPosX, FLOAT fPosY );
  140. HRESULT          UpdateGrid( HWND hDlg );
  141. void             SetPlayerTalking( APP_PLAYER_INFO* pPlayerInfo, BOOL bTalking );
  142. INT_PTR CALLBACK VoiceConfigDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  143. HRESULT          VoiceConfigEnumCompressionCodecs( HWND hDlg );
  144. VOID             VoiceConfigDlgOnOK( HWND hDlg );
  145.  
  146.  
  147.  
  148.  
  149. //-----------------------------------------------------------------------------
  150. // Name: WinMain()
  151. // Desc: Entry point for the application.  Since we use a simple dialog for 
  152. //       user interaction we don't need to pump messages.
  153. //-----------------------------------------------------------------------------
  154. INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, 
  155.                       INT nCmdShow )
  156. {
  157.     HRESULT hr;
  158.     HKEY    hDPlaySampleRegKey;
  159.     BOOL    bConnectSuccess = FALSE;
  160.  
  161.     g_hInst = hInst;
  162.     InitializeCriticalSection( &g_csPlayerContext );
  163.     g_hSoundInit = CreateEvent( NULL, TRUE, FALSE, NULL );
  164.  
  165.     // Init player ID array 
  166.     g_dwPlayersArraySize = 10;
  167.     g_pPlayers = (DPNID*) malloc( sizeof(DPNID)*g_dwPlayersArraySize );
  168.  
  169.     // Read persistent state information from registry
  170.     RegCreateKeyEx( HKEY_CURRENT_USER, DPLAY_SAMPLE_KEY, 0, NULL,
  171.                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
  172.                     &hDPlaySampleRegKey, NULL );
  173.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), 
  174.                              g_strLocalPlayerName, MAX_PATH, TEXT("TestPlayer") );
  175.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), 
  176.                              g_strSessionName, MAX_PATH, TEXT("TestGame") );
  177.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), 
  178.                              g_strPreferredProvider, MAX_PATH, TEXT("DirectPlay8 TCP/IP Service Provider") );
  179.  
  180.     InitCommonControls();
  181.  
  182.     // Init COM so we can use CoCreateInstance
  183.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  184.  
  185.     // Create helper class
  186.     g_pNetConnectWizard = new CNetConnectWizard( hInst, g_strAppName, &g_guidApp );
  187.     g_pNetVoice         = new CNetVoice( DirectPlayVoiceClientMessageHandler, DirectPlayVoiceServerMessageHandler );
  188.  
  189.     if( FAILED( hr = InitDirectPlay() ) )
  190.     {
  191.         DXTRACE_ERR( TEXT("InitDirectPlay"), hr );
  192.         MessageBox( NULL, TEXT("Failed initializing IDirectPlay8Peer. ")
  193.                     TEXT("The sample will now quit."),
  194.                     TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  195.         return FALSE;
  196.     }
  197.  
  198.     // Check if we were launched from a lobby client
  199.     if( g_bWasLobbyLaunched && g_pNetConnectWizard->HaveConnectionSettingsFromLobby() )
  200.     {
  201.         // If were lobby launched then DPL_MSGID_CONNECT has already been
  202.         // handled, so we can just tell the wizard to connect to the lobby
  203.         // that has sent us a DPL_MSGID_CONNECT msg.
  204.         if( FAILED( hr = g_pNetConnectWizard->ConnectUsingLobbySettings() ) )
  205.         {
  206.             DXTRACE_ERR( TEXT("ConnectUsingLobbySettings"), hr );
  207.             MessageBox( NULL, TEXT("Failed to connect using lobby settings. ")
  208.                         TEXT("The sample will now quit."),
  209.                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  210.  
  211.             bConnectSuccess = FALSE;
  212.         }
  213.         else
  214.         {
  215.             // Read information from g_pNetConnectWizard
  216.             _tcscpy( g_strLocalPlayerName, g_pNetConnectWizard->GetPlayerName() );
  217.             g_bHostPlayer = g_pNetConnectWizard->IsHostPlayer();
  218.  
  219.             bConnectSuccess = TRUE; 
  220.         }
  221.     }
  222.     else
  223.     {
  224.         // If not lobby launched, prompt the user about the network 
  225.         // connection and which session they would like to join or 
  226.         // if they want to create a new one.
  227.  
  228.         // Setup connection wizard
  229.         g_pNetConnectWizard->SetPlayerName( g_strLocalPlayerName );
  230.         g_pNetConnectWizard->SetSessionName( g_strSessionName );
  231.         g_pNetConnectWizard->SetPreferredProvider( g_strPreferredProvider );
  232.  
  233.         // Do the connection wizard
  234.         hr = g_pNetConnectWizard->DoConnectWizard( FALSE );        
  235.         if( FAILED( hr ) ) 
  236.         {
  237.             DXTRACE_ERR( TEXT("DoConnectWizard"), hr );        
  238.             MessageBox( NULL, TEXT("Mutliplayer connect failed. ")
  239.                         TEXT("The sample will now quit."),
  240.                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  241.             bConnectSuccess = FALSE;
  242.         } 
  243.         else if( hr == NCW_S_QUIT ) 
  244.         {
  245.             // The user canceled the mutliplayer connect, so quit 
  246.             bConnectSuccess = FALSE;
  247.         }
  248.         else
  249.         {
  250.             bConnectSuccess = TRUE; 
  251.  
  252.             // Read information from g_pNetConnectWizard
  253.             _tcscpy( g_strLocalPlayerName, g_pNetConnectWizard->GetPlayerName() );
  254.             _tcscpy( g_strSessionName, g_pNetConnectWizard->GetSessionName() );
  255.             _tcscpy( g_strPreferredProvider, g_pNetConnectWizard->GetPreferredProvider() );
  256.             g_bHostPlayer = g_pNetConnectWizard->IsHostPlayer();
  257.  
  258.             // Write information to the registry
  259.             DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), g_strLocalPlayerName );
  260.             DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), g_strSessionName );
  261.             DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), g_strPreferredProvider );
  262.         }
  263.     }
  264.  
  265.     if( bConnectSuccess )
  266.     {
  267.         // Set default DirectPlayVoice setup options
  268.         ZeroMemory( &g_dvClientConfig, sizeof(g_dvClientConfig) );
  269.         g_dvClientConfig.dwSize                 = sizeof(g_dvClientConfig);
  270.         g_dvClientConfig.dwFlags                = DVCLIENTCONFIG_AUTOVOICEACTIVATED |
  271.                                                   DVCLIENTCONFIG_AUTORECORDVOLUME;
  272.         g_dvClientConfig.lPlaybackVolume        = DVPLAYBACKVOLUME_DEFAULT;
  273.         g_dvClientConfig.dwBufferQuality        = DVBUFFERQUALITY_DEFAULT;
  274.         g_dvClientConfig.dwBufferAggressiveness = DVBUFFERAGGRESSIVENESS_DEFAULT;
  275.         g_dvClientConfig.dwThreshold            = DVTHRESHOLD_UNUSED;
  276.         g_dvClientConfig.lRecordVolume          = DVRECORDVOLUME_LAST;
  277.         g_dvClientConfig.dwNotifyPeriod         = 0;
  278.  
  279.         g_guidDVSessionCT                       = DPVCTGUID_DEFAULT;
  280.  
  281.         // Ask the user for DirectPlayVoice setup params
  282.         DWORD dwResult = (DWORD)DialogBox( hInst, MAKEINTRESOURCE(IDD_VOICE_SETUP), 
  283.                                            NULL, VoiceConfigDlgProc );
  284.         if( dwResult != IDCANCEL )
  285.             g_pNetVoice->ChangeVoiceClientSettings( &g_dvClientConfig );
  286.     }
  287.  
  288.     if( bConnectSuccess )
  289.     {
  290.         // App is now connected via DirectPlay, so start the game.  
  291.  
  292.         // For this sample, we just start a simple dialog box game.
  293.         g_hrDialog = S_OK;
  294.         DialogBox( hInst, MAKEINTRESOURCE(IDD_MAIN_GAME), NULL, VoiceDlgProc );
  295.  
  296.         if( FAILED( g_hrDialog ) )
  297.         {
  298.             if( g_hrDialog == DPNERR_CONNECTIONLOST )
  299.             {
  300.                 MessageBox( NULL, TEXT("The DirectPlay session was lost. ")
  301.                             TEXT("The sample will now quit."),
  302.                             TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  303.             }
  304.             else
  305.             {
  306.                 DXTRACE_ERR( TEXT("DialogBox"), g_hrDialog );        
  307.                 MessageBox( NULL, TEXT("An error occured during the game. ")
  308.                             TEXT("The sample will now quit."),
  309.                             TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  310.             }
  311.         }
  312.     }
  313.     
  314.  
  315.     // Cleanup player ID array 
  316.     free( g_pPlayers );
  317.  
  318.     // Disconnect from the DirectPlayVoice session, 
  319.     // and destory it if we are the host player.
  320.     SAFE_DELETE( g_pNetVoice ); 
  321.  
  322.     // Cleanup DirectPlay and helper classes
  323.     g_pNetConnectWizard->Shutdown();
  324.  
  325.     if( g_pDP )
  326.     {
  327.         g_pDP->Close(0);
  328.         SAFE_RELEASE( g_pDP );
  329.     }
  330.  
  331.     if( g_pLobbiedApp )
  332.     {
  333.         g_pLobbiedApp->Close( 0 );
  334.         SAFE_RELEASE( g_pLobbiedApp );
  335.     }    
  336.  
  337.     // Don't delete the wizard until we know that 
  338.     // DirectPlay is out of its message handlers.
  339.     // This will be true after Close() has been called. 
  340.     SAFE_DELETE( g_pNetConnectWizard );
  341.  
  342.     // Release DirectSound interfaces
  343.     SAFE_RELEASE( g_pDSListener );
  344.     SAFE_RELEASE( g_pDS );
  345.  
  346.     RegCloseKey( hDPlaySampleRegKey );
  347.     CloseHandle( g_hSoundInit );
  348.     DeleteCriticalSection( &g_csPlayerContext );
  349.     CoUninitialize();
  350.  
  351.     return TRUE;
  352. }
  353.  
  354.  
  355.  
  356.  
  357. //-----------------------------------------------------------------------------
  358. // Name: InitDirectPlay()
  359. // Desc: 
  360. //-----------------------------------------------------------------------------
  361. HRESULT InitDirectPlay()
  362. {
  363.     DPNHANDLE hLobbyLaunchedConnection = NULL;
  364.     HRESULT hr;
  365.  
  366.     // Create IDirectPlay8Peer
  367.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL, 
  368.                                        CLSCTX_INPROC_SERVER,
  369.                                        IID_IDirectPlay8Peer, 
  370.                                        (LPVOID*) &g_pDP ) ) )
  371.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  372.  
  373.     // Create IDirectPlay8LobbiedApplication
  374.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8LobbiedApplication, NULL, 
  375.                                        CLSCTX_INPROC_SERVER,
  376.                                        IID_IDirectPlay8LobbiedApplication, 
  377.                                        (LPVOID*) &g_pLobbiedApp ) ) )
  378.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  379.  
  380.     // Init the helper class, now that g_pDP and g_pLobbiedApp are valid
  381.     g_pNetConnectWizard->Init( g_pDP, g_pLobbiedApp );
  382.  
  383.     // Init IDirectPlay8Peer
  384.     if( FAILED( hr = g_pDP->Initialize( NULL, DirectPlayMessageHandler, 0 ) ) )
  385.         return DXTRACE_ERR( TEXT("Initialize"), hr );
  386.  
  387.     // Init IDirectPlay8LobbiedApplication.  Before this Initialize() returns 
  388.     // a DPL_MSGID_CONNECT msg may come in to the DirectPlayLobbyMessageHandler 
  389.     // so be prepared ahead of time.
  390.     if( FAILED( hr = g_pLobbiedApp->Initialize( NULL, DirectPlayLobbyMessageHandler, 
  391.                                                 &hLobbyLaunchedConnection, 0 ) ) )
  392.         return DXTRACE_ERR( TEXT("Initialize"), hr );
  393.  
  394.     // IDirectPlay8LobbiedApplication::Initialize returns a handle to a connnection
  395.     // if we have been lobby launced.  Initialize is guanteeded to return after 
  396.     // the DPL_MSGID_CONNECT msg has been processed.  So unless a we are expected 
  397.     // multiple lobby connections, we do not need to remember the lobby connection
  398.     // handle since it will be recorded upon the DPL_MSGID_CONNECT msg.
  399.     g_bWasLobbyLaunched = ( hLobbyLaunchedConnection != NULL );
  400.  
  401.     return S_OK;
  402. }
  403.  
  404.  
  405.  
  406.  
  407. //-----------------------------------------------------------------------------
  408. // Name: VoiceDlgProc()
  409. // Desc: Handles dialog messages
  410. //-----------------------------------------------------------------------------
  411. INT_PTR CALLBACK VoiceDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  412. {
  413.     switch( msg ) 
  414.     {
  415.         case WM_INITDIALOG:
  416.             {
  417.                 if( FAILED( g_hrDialog = OnInitDialog( hDlg ) ) )
  418.                 {
  419.                     DXTRACE_ERR( TEXT("OnInitDialog"), g_hrDialog );        
  420.                     EndDialog( hDlg, 0 );
  421.                     break;
  422.                 }
  423.  
  424.                 g_hDlg = hDlg;
  425.  
  426.                 if( FAILED( g_hrDialog = g_pNetVoice->Init( hDlg, g_bHostPlayer, TRUE,
  427.                                                             g_pDP, DVSESSIONTYPE_PEER, 
  428.                                                             &g_guidDVSessionCT, &g_dvClientConfig, g_pDS ) ) )
  429.                 {
  430.                     if( g_hrDialog == DVERR_USERBACK )
  431.                     {
  432.                         MessageBox( hDlg, TEXT("The user backed out of the wizard.  ")
  433.                                     TEXT("This simple sample does not handle this case, so ")
  434.                                     TEXT("the sample will quit."), TEXT("DirectPlay Sample"), MB_OK );
  435.                         g_hrDialog = S_OK;
  436.                     }
  437.  
  438.                     if( g_hrDialog == DVERR_USERCANCEL )
  439.                     {
  440.                         MessageBox( hDlg, TEXT("The user canceled the wizard. ")
  441.                                     TEXT("This simple sample does not handle this case, so ")
  442.                                     TEXT("the sample will quit."), TEXT("DirectPlay Sample"), MB_OK );
  443.                         g_hrDialog = S_OK;
  444.                     }
  445.  
  446.                     if( FAILED(g_hrDialog) )
  447.                         DXTRACE_ERR( TEXT("Init"), g_hrDialog );        
  448.  
  449.                     EndDialog( hDlg, 0 );
  450.                     break;
  451.                 }
  452.  
  453.                 if( g_pNetVoice->IsHalfDuplex() ) 
  454.                 {
  455.                     MessageBox( hDlg, TEXT("You are running in half duplex mode. ")
  456.                                 TEXT("In half duplex mode no recording takes place."), 
  457.                                 TEXT("DirectPlay Sample"), MB_OK );
  458.                 }
  459.  
  460.                 g_bVoiceSessionInProgress = TRUE;
  461.             }
  462.             break;
  463.  
  464.         case WM_COMMAND:
  465.             switch( LOWORD(wParam) )
  466.             {
  467.                 case IDC_SETUP:
  468.                     {
  469.                         // Ask the user for DirectPlayVoice setup params
  470.                         DWORD dwResult = (DWORD)DialogBox( g_hInst, 
  471.                                                            MAKEINTRESOURCE(IDD_VOICE_SETUP), 
  472.                                                            hDlg, VoiceConfigDlgProc );
  473.                         if( dwResult != IDCANCEL )
  474.                             g_pNetVoice->ChangeVoiceClientSettings( &g_dvClientConfig );
  475.                     }
  476.                     return TRUE;
  477.  
  478.                 case IDCANCEL:
  479.                     g_hrDialog = S_OK;
  480.                     EndDialog( hDlg, 0 );
  481.                     return TRUE;
  482.             }
  483.             break;
  484.  
  485.         case WM_APP_DISPLAY_PLAYERS:
  486.         {
  487.             DisplayPlayersInChat( hDlg );
  488.             break;
  489.         }
  490.  
  491.         case WM_APP_UPDATE_GRID:
  492.         {
  493.             UpdateGrid( hDlg );
  494.             break;
  495.         }
  496.  
  497.         case WM_TIMER:
  498.         {
  499.             DWORD            dwNumPlayers;
  500.             DWORD            iIndex;
  501.             LVITEM           lvItem;
  502.             APP_PLAYER_INFO* pPlayerInfo = NULL;
  503.             HWND             hListView = GetDlgItem( hDlg, IDC_PEOPLE_LIST );
  504.  
  505.             dwNumPlayers = ListView_GetItemCount( hListView );
  506.  
  507.             // Now that they are added and the listview sorted them by name,
  508.             // run through them all caching the listview index with its dpnid
  509.             for( iIndex = 0; iIndex < dwNumPlayers; iIndex++ )
  510.             {
  511.                 HRESULT hr;
  512.                 APP_PLAYER_INFO* pPlayerInfo = NULL;
  513.                 DPNID dpnidPlayer;
  514.  
  515.                 lvItem.mask  = LVIF_PARAM;
  516.                 lvItem.iItem = iIndex;
  517.                 ListView_GetItem( hListView, &lvItem );
  518.  
  519.                 dpnidPlayer = (DPNID) lvItem.lParam;
  520.  
  521.                 PLAYER_LOCK(); // enter player context CS
  522.  
  523.                 // Get the player context accosicated with this DPNID
  524.                 hr = g_pDP->GetPlayerContext( dpnidPlayer, 
  525.                                               (LPVOID* const) &pPlayerInfo,
  526.                                               0);
  527.  
  528.  
  529.                 PLAYER_ADDREF( pPlayerInfo ); // addref player, since we are using it now
  530.                 PLAYER_UNLOCK(); // leave player context CS
  531.  
  532.                 if( FAILED(hr) || pPlayerInfo == NULL )
  533.                 {
  534.                     // The player who sent this may have gone away before this 
  535.                     // message was handled, so just ignore it
  536.                     continue;
  537.                 }
  538.  
  539.                 TCHAR strStatus[255];
  540.  
  541.                 if( pPlayerInfo->bHalfDuplex )
  542.                 {
  543.                     _tcscpy( strStatus, TEXT("Can't talk") );
  544.                 }
  545.                 else
  546.                 {
  547.                     if( pPlayerInfo->bTalking )
  548.                         _tcscpy( strStatus, TEXT("Talking") );
  549.                     else
  550.                         _tcscpy( strStatus, TEXT("Silent") );
  551.                 }
  552.  
  553.                 lvItem.iItem      = iIndex;
  554.                 lvItem.iSubItem   = 1;
  555.                 lvItem.mask       = LVIF_TEXT;
  556.                 lvItem.pszText    = strStatus;
  557.  
  558.                 PLAYER_LOCK();
  559.                 PLAYER_RELEASE( pPlayerInfo );  // Release player and cleanup if needed
  560.                 PLAYER_UNLOCK();
  561.  
  562.                 SendMessage( hListView, LVM_SETITEM, 0, (LPARAM) &lvItem );
  563.             }
  564.             break;
  565.         }
  566.  
  567.         case WM_PAINT:
  568.         {
  569.             DWORD            dwNumPlayers;
  570.             DWORD            iIndex;
  571.             LVITEM           lvItem;
  572.             APP_PLAYER_INFO* pPlayerInfo  = NULL;
  573.             HWND             hListView    = GetDlgItem( hDlg, IDC_PEOPLE_LIST );
  574.             HWND             hWndGrid     = GetDlgItem( hDlg, IDC_RENDER_WINDOW );
  575.             BOOL             bIsLocalPlayer;
  576.  
  577.             // Erase and redraw the grid window right now
  578.             RedrawWindow( hWndGrid, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | 
  579.                                                 RDW_INTERNALPAINT | RDW_UPDATENOW );
  580.             HDC hDC = GetDC( hWndGrid );
  581.  
  582.             dwNumPlayers = ListView_GetItemCount( hListView );
  583.  
  584.             // Now that they are added and the listview sorted them by name,
  585.             // run through them all caching the listview index with its dpnid
  586.             for( iIndex = 0; iIndex < dwNumPlayers; iIndex++ )
  587.             {
  588.                 HRESULT hr;
  589.                 APP_PLAYER_INFO* pPlayerInfo = NULL;
  590.                 DPNID dpnidPlayer;
  591.  
  592.                 lvItem.mask  = LVIF_PARAM;
  593.                 lvItem.iItem = iIndex;
  594.                 ListView_GetItem( hListView, &lvItem );
  595.  
  596.                 dpnidPlayer = (DPNID) lvItem.lParam;
  597.  
  598.                 PLAYER_LOCK(); // enter player context CS
  599.  
  600.                 // Get the player context accosicated with this DPNID
  601.                 hr = g_pDP->GetPlayerContext( dpnidPlayer, 
  602.                                               (LPVOID* const) &pPlayerInfo,
  603.                                               0);
  604.  
  605.  
  606.                 PLAYER_ADDREF( pPlayerInfo ); // addref player, since we are using it now
  607.                 PLAYER_UNLOCK(); // leave player context CS
  608.  
  609.                 if( FAILED(hr) || pPlayerInfo == NULL )
  610.                 {
  611.                     // The player who sent this may have gone away before this 
  612.                     // message was handled, so just ignore it
  613.                     continue;
  614.                 }
  615.  
  616.                 if( pPlayerInfo->dpnidPlayer == g_LocalPlayerDPNID )
  617.                     bIsLocalPlayer = TRUE;
  618.                 else
  619.                     bIsLocalPlayer = FALSE;
  620.                 
  621.                 DrawDotOnGrid( hWndGrid, hDC, bIsLocalPlayer,
  622.                                pPlayerInfo->pt.x / (float) MAP_WIDTH, 
  623.                                pPlayerInfo->pt.y / (float) MAP_HEIGHT );
  624.  
  625.                 PLAYER_LOCK();
  626.                 PLAYER_RELEASE( pPlayerInfo );  // Release player and cleanup if needed
  627.                 PLAYER_UNLOCK();
  628.                 
  629.             }
  630.  
  631.             ReleaseDC( hWndGrid, hDC );    
  632.             break;
  633.         }
  634.  
  635.         case WM_NOTIFY:
  636.             {
  637.                 LPNMLISTVIEW pnm = (LPNMLISTVIEW)lParam;
  638.  
  639.                 if( pnm->hdr.code == NM_CUSTOMDRAW &&
  640.                     (pnm->hdr.idFrom == IDC_VERTICAL_SLIDER || pnm->hdr.idFrom == IDC_HORIZONTAL_SLIDER) )
  641.                 {
  642.                     LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
  643.  
  644.                     if( lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT )
  645.                     {
  646.                         POINT pt;
  647.  
  648.                         pt.x = (LONG)SendDlgItemMessage( hDlg, IDC_HORIZONTAL_SLIDER, TBM_GETPOS, 0, 0 );
  649.                         pt.y = (LONG)SendDlgItemMessage( hDlg, IDC_VERTICAL_SLIDER,   TBM_GETPOS, 0, 0 );
  650.  
  651.                         if( NULL == g_pPlayerLocal )
  652.                             return CDRF_DODEFAULT;
  653.  
  654.                         // Don't do anything if nothing has changed.
  655.                         if( pt.x != g_pPlayerLocal->pt.x || pt.y != g_pPlayerLocal->pt.y )
  656.                         {
  657.                             g_pPlayerLocal->pt = pt;
  658.  
  659.                             if( FAILED( g_hrDialog = SendLocalPosition( hDlg ) ) )
  660.                             {
  661.                                 DXTRACE_ERR( TEXT("SendLocalPosition"), g_hrDialog );        
  662.                                 MessageBox( hDlg, TEXT("Error updating the local position.  ")
  663.                                             TEXT("Sample will now exit."), TEXT("DirectPlayVoice Sample"), 
  664.                                             MB_OK | MB_ICONERROR );
  665.                                 EndDialog( hDlg, 0 );
  666.                             }
  667.  
  668.                             // Update the grid
  669.                             PostMessage( hDlg, WM_APP_UPDATE_GRID, 0, 0 );
  670.                         }
  671.  
  672.                         return CDRF_DODEFAULT;
  673.                     }
  674.                 }
  675.             }
  676.             break;
  677.  
  678.         case WM_LBUTTONDOWN:
  679.             {
  680.                 POINT pt;
  681.                 RECT  rc;
  682.                 HWND  hWndGrid = GetDlgItem( hDlg, IDC_RENDER_WINDOW );
  683.  
  684.                 // Check to see if the click was inside the map position window
  685.                 // if it was then move the position there
  686.                 pt.x = LOWORD( lParam );
  687.                 pt.y = HIWORD( lParam );
  688.  
  689.                 ClientToScreen( hDlg, &pt );
  690.                 ScreenToClient( hWndGrid, &pt );
  691.                 GetClientRect( hWndGrid, &rc );
  692.  
  693.                 if( pt.x > rc.left && pt.x < rc.right &&
  694.                     pt.y > rc.top  && pt.y < rc.bottom )
  695.                 {
  696.                     // Set the position, but do it careful since we check the 
  697.                     // slider position's whenever a slider is redrawn, so 
  698.                     // be careful when the sliders are redrawn otherwise false
  699.                     // position messages will be sent to everyone in the session
  700.                     g_pPlayerLocal->pt.x = pt.x;
  701.                     SendDlgItemMessage( hDlg, IDC_HORIZONTAL_SLIDER, TBM_SETPOS, TRUE, pt.x );
  702.                     g_pPlayerLocal->pt.y = pt.y;
  703.                     SendDlgItemMessage( hDlg, IDC_VERTICAL_SLIDER, TBM_SETPOS, TRUE, pt.y );
  704.  
  705.                     if( FAILED( g_hrDialog = SendLocalPosition( hDlg ) ) )
  706.                     {
  707.                         DXTRACE_ERR( TEXT("SendLocalPosition"), g_hrDialog );        
  708.                         MessageBox( hDlg, TEXT("Error updating the local position.  ")
  709.                                     TEXT("Sample will now exit."), TEXT("DirectPlayVoice Sample"), 
  710.                                     MB_OK | MB_ICONERROR );
  711.                         EndDialog( g_hDlg, 0 );
  712.                     }   
  713.  
  714.                     // Update the grid
  715.                     PostMessage( hDlg, WM_APP_UPDATE_GRID, 0, 0 );
  716.                 }
  717.             }
  718.             break;
  719.     }
  720.  
  721.     return FALSE; // Didn't handle message
  722. }
  723.  
  724.  
  725.  
  726.  
  727. //-----------------------------------------------------------------------------
  728. // Name: OnInitDialog()
  729. // Desc: Inits the dialog 
  730. //-----------------------------------------------------------------------------
  731. HRESULT OnInitDialog( HWND hDlg )
  732. {
  733.     HRESULT  hr;
  734.     LVCOLUMN column;
  735.     RECT     rctListView;
  736.     TCHAR    strHeader[255];
  737.     DWORD    dwVertScrollBar;
  738.     DWORD    dwListViewWidth;
  739.  
  740.     // Setup DirectSound, and the 3D listener
  741.     if( FAILED( hr = InitDirectSound( hDlg ) ) )
  742.         return hr;
  743.  
  744.     // Load and set the icon
  745.     HICON hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  746.     SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  747.     SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  748.  
  749.     if( g_bHostPlayer )
  750.         SetWindowText( hDlg, TEXT("VoicePosition (Session Host)") );
  751.     else
  752.         SetWindowText( hDlg, TEXT("VoicePosition (Session Client)") );
  753.  
  754.     // Setup the listview
  755.     HWND hListView = GetDlgItem( hDlg, IDC_PEOPLE_LIST );
  756.     dwVertScrollBar = GetSystemMetrics( SM_CXVSCROLL );  
  757.     GetClientRect( hListView, &rctListView );
  758.     dwListViewWidth = rctListView.right - dwVertScrollBar;
  759.     column.mask     = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  760.     column.fmt      = LVCFMT_LEFT;
  761.     column.iSubItem = -1;
  762.  
  763.     // Insert the Name column
  764.     _tcscpy( strHeader, TEXT("Name") );
  765.     column.cx         = dwListViewWidth * 5 / 10;
  766.     column.pszText    = strHeader;
  767.     column.cchTextMax = _tcslen( strHeader );
  768.     ListView_InsertColumn( hListView, 0, &column );
  769.  
  770.     // Insert the Status column
  771.     _tcscpy( strHeader, TEXT("Status") );
  772.     column.cx         = dwListViewWidth * 5 / 10;
  773.     column.pszText    = strHeader;
  774.     column.cchTextMax = _tcslen( strHeader );
  775.     ListView_InsertColumn( hListView, 1, &column );
  776.  
  777.     SendDlgItemMessage( hDlg, IDC_HORIZONTAL_SLIDER, TBM_SETRANGE, 0, MAKELONG( 0, MAP_WIDTH ) );
  778.     SendDlgItemMessage( hDlg, IDC_VERTICAL_SLIDER,   TBM_SETRANGE, 0, MAKELONG( 0, MAP_HEIGHT ) );
  779.  
  780.     SendDlgItemMessage( hDlg, IDC_HORIZONTAL_SLIDER, TBM_SETPOS, TRUE, START_POSITION_X );
  781.     SendDlgItemMessage( hDlg, IDC_VERTICAL_SLIDER,   TBM_SETPOS, TRUE, START_POSITION_Y );
  782.  
  783.     // Send the local players postion to everyone
  784.     if( FAILED( hr = SendLocalPosition( hDlg ) ) ) 
  785.         return DXTRACE_ERR( TEXT("SendLocalPosition"), hr );        
  786.  
  787.     // Update the listbox 
  788.     PostMessage( hDlg, WM_APP_DISPLAY_PLAYERS, 0, 0 );
  789.  
  790.     // Update the grid
  791.     PostMessage( hDlg, WM_APP_UPDATE_GRID, 0, 0 );
  792.  
  793.     // Make a timer to update the listbox 
  794.     // 'Status' column every so often 
  795.     SetTimer( hDlg, 0, 250, NULL );
  796.  
  797.     return S_OK;
  798. }
  799.  
  800.  
  801.  
  802.  
  803. //-----------------------------------------------------------------------------
  804. // Name: InitDirectSound()
  805. // Desc: Initializes DirectSound
  806. //-----------------------------------------------------------------------------
  807. HRESULT InitDirectSound( HWND hDlg )
  808. {
  809.     HRESULT hr;
  810.   
  811.     if( FAILED( hr = DirectSoundCreate( &DSDEVID_DefaultVoicePlayback, &g_pDS, NULL ) ) )
  812.         return DXTRACE_ERR( TEXT("DirectSoundCreate"), hr );        
  813.  
  814.     if( FAILED( hr = g_pDS->SetCooperativeLevel( hDlg, DSSCL_PRIORITY ) ) )
  815.         return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr );        
  816.  
  817.     // Obtain primary buffer, asking it for 3D control
  818.     DSBUFFERDESC        dsbd;
  819.     LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
  820.  
  821.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  822.     dsbd.dwSize  = sizeof(DSBUFFERDESC);
  823.     dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
  824.     if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
  825.         return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );        
  826.  
  827.     if( FAILED( hr = pDSBPrimary->QueryInterface( IID_IDirectSound3DListener, 
  828.                                                   (VOID**)&g_pDSListener ) ) )
  829.         return DXTRACE_ERR( TEXT("QueryInterface"), hr );        
  830.  
  831.     // Done with the primary buffer, so release it
  832.     SAFE_RELEASE( pDSBPrimary );
  833.  
  834.     DS3DLISTENER dslsn;
  835.     ZeroMemory( &dslsn, sizeof(dslsn) );
  836.  
  837.     dslsn.dwSize = sizeof(dslsn);
  838.     dslsn.flDistanceFactor = 1.0f;  // All DSound3D units are in meters
  839.     dslsn.flDopplerFactor  = DS3D_DEFAULTDOPPLERFACTOR;
  840.  
  841.     // Use 3 times the real rolloff factor so that 
  842.     // the voices don't fade away too quickly
  843.     dslsn.flRolloffFactor  = 3.0f; 
  844.     dslsn.vOrientFront     = D3DVECTOR( 0.0f, 0.0f, 1.0f );
  845.     dslsn.vOrientTop       = D3DVECTOR( 0.0f, 1.0f, 0.0f );
  846.     dslsn.vPosition        = D3DVECTOR( 0.0f, 0.0f, 0.0f );
  847.     dslsn.vVelocity        = D3DVECTOR( 0.0f, 0.0f, 0.0f );
  848.  
  849.     if( FAILED( hr = g_pDSListener->SetAllParameters( &dslsn, DS3D_IMMEDIATE ) ) ) 
  850.         return DXTRACE_ERR( TEXT("SetAllParameters"), hr );        
  851.  
  852.     SetEvent( g_hSoundInit );
  853.  
  854.     return S_OK;
  855. }
  856.  
  857.  
  858.  
  859.  
  860. //-----------------------------------------------------------------------------
  861. // Name: SendLocalPosition()
  862. // Desc: Updates the local position, and sends the new position to all the players 
  863. //-----------------------------------------------------------------------------
  864. HRESULT SendLocalPosition( HWND hDlg )
  865. {
  866.     if( g_pPlayerLocal == NULL )
  867.         return S_OK;
  868.  
  869.     GAMEMSG_PLAYERMOVED msgPlayerMoved;
  870.     msgPlayerMoved.dwType = GAME_MSGID_PLAYERMOVED;
  871.     msgPlayerMoved.pt     = g_pPlayerLocal->pt;
  872.  
  873.     DPN_BUFFER_DESC bufferDesc;
  874.     bufferDesc.dwBufferSize = sizeof(GAMEMSG_PLAYERMOVED);
  875.     bufferDesc.pBufferData  = (BYTE*) &msgPlayerMoved;
  876.  
  877.     // Send it to all of the players
  878.     // DirectPlay will tell via the message handler 
  879.     // if there are any severe errors, so ignore any errors 
  880.     DPNHANDLE hAsync;
  881.     g_pDP->SendTo( DPNID_ALL_PLAYERS_GROUP, &bufferDesc, 1, 
  882.                    0, NULL, &hAsync, DPNSEND_NOLOOPBACK );
  883.  
  884.     return S_OK;
  885. }
  886.  
  887.  
  888.  
  889.  
  890. //-----------------------------------------------------------------------------
  891. // Name: DisplayPlayersInChat()
  892. // Desc: Displays the active players in the listview
  893. //-----------------------------------------------------------------------------
  894. HRESULT DisplayPlayersInChat( HWND hDlg )
  895. {
  896.     if( hDlg == NULL )
  897.         return S_OK;
  898.  
  899.     HRESULT hr;
  900.     LVITEM  lvItem;
  901.     HWND    hListView = GetDlgItem( hDlg, IDC_PEOPLE_LIST );
  902.     TCHAR   strStatus[32];
  903.     TCHAR   strNumberPlayers[32];
  904.     DWORD   dwNumPlayers;
  905.     APP_PLAYER_INFO* pPlayerInfo = NULL;
  906.  
  907.     // Remove all the players and re-add them in the player enum callback
  908.     ListView_DeleteAllItems( hListView );
  909.  
  910.     do
  911.     {
  912.         // Enum all players in the player ID array
  913.         dwNumPlayers = g_dwPlayersArraySize;
  914.         hr = g_pDP->EnumPlayersAndGroups( g_pPlayers, &dwNumPlayers, DPNENUM_PLAYERS );
  915.         if( SUCCEEDED(hr) )
  916.             break;
  917.  
  918.         if( hr == DPNERR_BUFFERTOOSMALL )
  919.         {
  920.             // Resize player pointer array     
  921.             g_dwPlayersArraySize += 10;
  922.             g_pPlayers = (DPNID*) realloc( g_pPlayers, sizeof(DPNID)*g_dwPlayersArraySize );
  923.         }
  924.     } 
  925.     while( hr == DPNERR_BUFFERTOOSMALL );
  926.     if( FAILED(hr) )
  927.         return DXTRACE_ERR( TEXT("EnumPlayersAndGroups"), hr );        
  928.  
  929.     for( DWORD i = 0; i<dwNumPlayers; i++ )
  930.     {
  931.         PLAYER_LOCK(); // enter player context CS
  932.  
  933.         // Get the player context accosicated with this DPNID
  934.         hr = g_pDP->GetPlayerContext( g_pPlayers[i], 
  935.                                       (LPVOID* const) &pPlayerInfo,
  936.                                       0);
  937.  
  938.         PLAYER_ADDREF( pPlayerInfo ); // addref player, since we are using it now
  939.         PLAYER_UNLOCK(); // leave player context CS
  940.  
  941.         if( FAILED(hr) || pPlayerInfo == NULL )
  942.         {
  943.             // The player who sent this may have gone away before this 
  944.             // message was handled, so just ignore it
  945.             continue;
  946.         }
  947.  
  948.         ZeroMemory( &lvItem, sizeof(lvItem) );
  949.  
  950.         // Add the item, saving the player's name and dpnid in the listview
  951.         lvItem.mask       = LVIF_TEXT | LVIF_PARAM;
  952.         lvItem.iItem      = 0;
  953.         lvItem.iSubItem   = 0;
  954.         lvItem.pszText    = pPlayerInfo->strPlayerName;
  955.         lvItem.lParam     = g_pPlayers[i];
  956.         lvItem.cchTextMax = _tcslen( pPlayerInfo->strPlayerName );
  957.         int nIndex = ListView_InsertItem( hListView, &lvItem );
  958.  
  959.         if( pPlayerInfo->bHalfDuplex )
  960.         {
  961.             _tcscpy( strStatus, TEXT("Can't talk") );
  962.         }
  963.         else
  964.         {
  965.             if( pPlayerInfo->bTalking )
  966.                 _tcscpy( strStatus, TEXT("Talking") );
  967.             else
  968.                 _tcscpy( strStatus, TEXT("Silent") );
  969.         }        
  970.  
  971.         PLAYER_LOCK();
  972.         PLAYER_RELEASE( pPlayerInfo );  // Release player and cleanup if needed
  973.         PLAYER_UNLOCK();
  974.  
  975.         // Start the player's status off as silent.  
  976.         lvItem.mask       = LVIF_TEXT;
  977.         lvItem.iItem      = nIndex;
  978.         lvItem.iSubItem   = 1;
  979.         lvItem.pszText    = strStatus;
  980.         lvItem.cchTextMax = _tcslen( strStatus );
  981.         ListView_SetItem( hListView, &lvItem );
  982.     }
  983.  
  984.     wsprintf( strNumberPlayers, TEXT("%d"), dwNumPlayers );
  985.     SetDlgItemText( hDlg, IDC_NUM_PLAYERS, strNumberPlayers );
  986.  
  987.     return S_OK;
  988. }
  989.  
  990.  
  991.  
  992.  
  993. //-----------------------------------------------------------------------------
  994. // Name: UpdateGrid()
  995. // Desc: Draws all the dots on dialog's grid bitmap 
  996. //-----------------------------------------------------------------------------
  997. HRESULT UpdateGrid( HWND hDlg )
  998. {
  999.     HRESULT hr;
  1000.     DWORD   dwNumPlayers;
  1001.     APP_PLAYER_INFO* pPlayerInfo = NULL;
  1002.  
  1003.     if( hDlg == NULL )
  1004.         return S_OK;
  1005.  
  1006.     HWND hWndGrid = GetDlgItem( hDlg, IDC_RENDER_WINDOW );
  1007.  
  1008.     // Erase and redraw the grid window right now
  1009.     RedrawWindow( hWndGrid, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | 
  1010.                                         RDW_INTERNALPAINT | RDW_UPDATENOW );
  1011.     HDC hDC = GetDC( hWndGrid );
  1012.  
  1013.     do
  1014.     {
  1015.         // Enum all players in the player ID array
  1016.         dwNumPlayers = g_dwPlayersArraySize;
  1017.         hr = g_pDP->EnumPlayersAndGroups( g_pPlayers, &dwNumPlayers, DPNENUM_PLAYERS );
  1018.         if( SUCCEEDED(hr) )
  1019.             break;
  1020.  
  1021.         if( hr == DPNERR_BUFFERTOOSMALL )
  1022.         {
  1023.             // Resize player pointer array     
  1024.             g_dwPlayersArraySize += 10;
  1025.             g_pPlayers = (DPNID*) realloc( g_pPlayers, g_dwPlayersArraySize );
  1026.         }
  1027.     } 
  1028.     while( hr == DPNERR_BUFFERTOOSMALL );
  1029.     if( FAILED(hr) )
  1030.         return DXTRACE_ERR( TEXT("EnumPlayersAndGroups"), hr );        
  1031.  
  1032.     for( DWORD i = 0; i<dwNumPlayers; i++ )
  1033.     {
  1034.         PLAYER_LOCK(); // enter player context CS
  1035.  
  1036.         // Get the player context accosicated with this DPNID
  1037.         hr = g_pDP->GetPlayerContext( g_pPlayers[i], 
  1038.                                       (LPVOID* const) &pPlayerInfo,
  1039.                                       0);
  1040.  
  1041.         PLAYER_ADDREF( pPlayerInfo ); // addref player, since we are using it now
  1042.         PLAYER_UNLOCK(); // leave player context CS
  1043.  
  1044.         if( FAILED(hr) || pPlayerInfo == NULL )
  1045.         {
  1046.             // The player who sent this may have gone away before this 
  1047.             // message was handled, so just ignore it
  1048.             continue;
  1049.         }
  1050.  
  1051.         EnterCriticalSection( &pPlayerInfo->csPlayer );
  1052.  
  1053.         FLOAT f3DPosX = (FLOAT) ( pPlayerInfo->pt.x - START_POSITION_X ) / 10.0f;
  1054.         FLOAT f3DPosZ = (FLOAT) ( pPlayerInfo->pt.y - START_POSITION_Y ) / 10.0f;
  1055.  
  1056.         if( pPlayerInfo->dpnidPlayer == g_LocalPlayerDPNID )
  1057.         {
  1058.             DrawDotOnGrid( hWndGrid, hDC, TRUE,
  1059.                            pPlayerInfo->pt.x / (float) MAP_WIDTH, 
  1060.                            pPlayerInfo->pt.y / (float) MAP_HEIGHT );
  1061.  
  1062.             if( g_pDSListener ) 
  1063.             {
  1064.                 if( FAILED( hr = g_pDSListener->SetPosition( f3DPosX, 0.0f, 
  1065.                                                              f3DPosZ, DS3D_DEFERRED ) ) ) 
  1066.                     return DXTRACE_ERR( TEXT("SetPosition"), hr );        
  1067.  
  1068.                 DXUtil_Trace( TEXT("Setting listener to (%0.1ff,0.0f,%0.1ff)\n"), 
  1069.                               f3DPosX, f3DPosZ );
  1070.             }
  1071.         }
  1072.         else
  1073.         {
  1074.             DrawDotOnGrid( hWndGrid, hDC, FALSE,
  1075.                            pPlayerInfo->pt.x / (float) MAP_WIDTH, 
  1076.                            pPlayerInfo->pt.y / (float) MAP_HEIGHT );
  1077.  
  1078.             if( pPlayerInfo->pDSBVoice )
  1079.             {
  1080.                 if( FAILED( hr = pPlayerInfo->pDSBVoice->SetPosition( f3DPosX, 0.0f, 
  1081.                                                                 f3DPosZ, DS3D_DEFERRED ) ) ) 
  1082.                     return DXTRACE_ERR( TEXT("SetPosition"), hr );        
  1083.  
  1084.                 DXUtil_Trace( TEXT("Setting player 0x%0.8x to (%0.1ff,0.0f,%0.1ff)\n"), 
  1085.                               pPlayerInfo->dpnidPlayer, f3DPosX, f3DPosZ );
  1086.             }
  1087.         }
  1088.  
  1089.         LeaveCriticalSection( &pPlayerInfo->csPlayer );
  1090.  
  1091.         PLAYER_LOCK();
  1092.         PLAYER_RELEASE( pPlayerInfo );  // Release player and cleanup if needed
  1093.         PLAYER_UNLOCK();
  1094.         
  1095.     }
  1096.  
  1097.     ReleaseDC( hWndGrid, hDC );    
  1098.  
  1099.     if( g_pDSListener )
  1100.         g_pDSListener->CommitDeferredSettings();
  1101.  
  1102.     return S_OK;
  1103. }
  1104.  
  1105.  
  1106.  
  1107.  
  1108. //-----------------------------------------------------------------------------
  1109. // Name: DrawDotOnGrid()
  1110. // Desc: Draws a dot in the dialog's grid bitmap at the x,y coordinate.
  1111. //-----------------------------------------------------------------------------
  1112. VOID DrawDotOnGrid( HWND hWndGrid, HDC hDC, BOOL bLocalDot, FLOAT fPosX, FLOAT fPosY )
  1113. {
  1114.     RECT     rc;
  1115.     DWORD    dwX;
  1116.     DWORD    dwY;
  1117.     COLORREF crDotColor;
  1118.  
  1119.     // Convert the world space x,y coordinates to pixel coordinates
  1120.     GetClientRect( hWndGrid, &rc );
  1121.     dwX = (DWORD) ( fPosX * (rc.left + rc.right  - 3 ) ) + 1;
  1122.     dwY = (DWORD) ( fPosY * (rc.top  + rc.bottom - 3 ) ) + 1;
  1123.  
  1124.     // Draw a crosshair object in red pixels
  1125.     if( bLocalDot )
  1126.         crDotColor = 0x0000FFFF;
  1127.     else
  1128.         crDotColor = 0x000000FF;
  1129.  
  1130.     SetPixel( hDC, dwX-1, dwY-1, crDotColor );
  1131.     SetPixel( hDC, dwX-1, dwY+0, crDotColor );
  1132.     SetPixel( hDC, dwX-1, dwY+1, crDotColor );
  1133.     SetPixel( hDC, dwX+0, dwY-1, crDotColor );
  1134.     SetPixel( hDC, dwX+0, dwY+0, crDotColor );
  1135.     SetPixel( hDC, dwX+0, dwY+1, crDotColor );
  1136.     SetPixel( hDC, dwX+1, dwY-1, crDotColor );
  1137.     SetPixel( hDC, dwX+1, dwY+0, crDotColor );
  1138.     SetPixel( hDC, dwX+1, dwY+1, crDotColor );
  1139. }
  1140.  
  1141.  
  1142.  
  1143.  
  1144. //-----------------------------------------------------------------------------
  1145. // Name: DirectPlayMessageHandler
  1146. // Desc: Handler for DirectPlay messages.  This function is called by
  1147. //       the DirectPlay message handler pool of threads, so be care of thread
  1148. //       synchronization problems with shared memory
  1149. //-----------------------------------------------------------------------------
  1150. HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, 
  1151.                                          DWORD dwMessageId, 
  1152.                                          PVOID pMsgBuffer )
  1153. {
  1154.     // Try not to stay in this message handler for too long, otherwise
  1155.     // there will be a backlog of data.  The best solution is to 
  1156.     // queue data as it comes in, and then handle it on other threads.
  1157.     
  1158.     // This function is called by the DirectPlay message handler pool of 
  1159.     // threads, so be care of thread synchronization problems with shared memory
  1160.  
  1161.     switch( dwMessageId )
  1162.     {
  1163.         case DPN_MSGID_CREATE_PLAYER:
  1164.         {
  1165.             HRESULT hr;
  1166.             PDPNMSG_CREATE_PLAYER pCreatePlayerMsg;
  1167.             pCreatePlayerMsg = (PDPNMSG_CREATE_PLAYER)pMsgBuffer;
  1168.  
  1169.             // Get the peer info and extract its name
  1170.             DWORD dwSize = 0;
  1171.             DPN_PLAYER_INFO* pdpPlayerInfo = NULL;
  1172.             hr = g_pDP->GetPeerInfo( pCreatePlayerMsg->dpnidPlayer, pdpPlayerInfo, &dwSize, 0 );
  1173.             if( FAILED(hr) && hr != DPNERR_BUFFERTOOSMALL )
  1174.                 return DXTRACE_ERR( TEXT("GetPeerInfo"), hr );        
  1175.             pdpPlayerInfo = (DPN_PLAYER_INFO*) new BYTE[ dwSize ];
  1176.             ZeroMemory( pdpPlayerInfo, dwSize );
  1177.             pdpPlayerInfo->dwSize = sizeof(DPN_PLAYER_INFO);
  1178.             hr = g_pDP->GetPeerInfo( pCreatePlayerMsg->dpnidPlayer, pdpPlayerInfo, &dwSize, 0 );
  1179.             if( FAILED(hr) )
  1180.                 return DXTRACE_ERR( TEXT("GetPeerInfo"), hr );        
  1181.  
  1182.             // Create a new and fill in a APP_PLAYER_INFO
  1183.             APP_PLAYER_INFO* pPlayerInfo = new APP_PLAYER_INFO;
  1184.             ZeroMemory( pPlayerInfo, sizeof(APP_PLAYER_INFO) ); 
  1185.             InitializeCriticalSection( &pPlayerInfo->csPlayer );
  1186.             pPlayerInfo->lRefCount   = 1;
  1187.             pPlayerInfo->dpnidPlayer = pCreatePlayerMsg->dpnidPlayer;
  1188.             pPlayerInfo->pt.x        = START_POSITION_X;
  1189.             pPlayerInfo->pt.y        = START_POSITION_Y;
  1190.  
  1191.             // This stores a extra TCHAR copy of the player name for 
  1192.             // easier access.  This will be redundent copy since DPlay 
  1193.             // also keeps a copy of the player name in GetPeerInfo()
  1194.             DXUtil_ConvertWideStringToGeneric( pPlayerInfo->strPlayerName, 
  1195.                                                pdpPlayerInfo->pwszName, MAX_PLAYER_NAME );
  1196.  
  1197.             // See if this is the local player
  1198.             if( (pdpPlayerInfo->dwPlayerFlags & DPNPLAYER_LOCAL) != 0 )
  1199.             {
  1200.                 g_pPlayerLocal          = pPlayerInfo;
  1201.                 g_pPlayerLocal->pt.x    = START_POSITION_X;
  1202.                 g_pPlayerLocal->pt.y    = START_POSITION_Y;
  1203.                 g_LocalPlayerDPNID      = pCreatePlayerMsg->dpnidPlayer;
  1204.             }
  1205.  
  1206.             SAFE_DELETE_ARRAY( pdpPlayerInfo );
  1207.  
  1208.             // Tell DirectPlay to store this pPlayerInfo 
  1209.             // pointer in the pvPlayerContext.
  1210.             pCreatePlayerMsg->pvPlayerContext = pPlayerInfo;
  1211.  
  1212.             // Post a message to the dialog thread to update the 
  1213.             // UI.  This keeps the DirectPlay message handler 
  1214.             // from blocking
  1215.             if( g_hDlg != NULL )
  1216.                 PostMessage( g_hDlg, WM_APP_DISPLAY_PLAYERS, 0, 0 );
  1217.  
  1218.             break;
  1219.         }
  1220.  
  1221.         case DPN_MSGID_DESTROY_PLAYER:
  1222.         {
  1223.             PDPNMSG_DESTROY_PLAYER pDestroyPlayerMsg;
  1224.             pDestroyPlayerMsg = (PDPNMSG_DESTROY_PLAYER)pMsgBuffer;
  1225.  
  1226.             APP_PLAYER_INFO* pPlayerInfo = (APP_PLAYER_INFO*) pDestroyPlayerMsg->pvPlayerContext;
  1227.             
  1228.             PLAYER_LOCK();                  // enter player context CS
  1229.             PLAYER_RELEASE( pPlayerInfo );  // Release player and cleanup if needed
  1230.             PLAYER_UNLOCK();                // leave player context CS
  1231.  
  1232.             // Post a message to the dialog thread to update the 
  1233.             // UI.  This keeps the DirectPlay message handler 
  1234.             // from blocking
  1235.             if( g_hDlg != NULL )
  1236.                 PostMessage( g_hDlg, WM_APP_DISPLAY_PLAYERS, 0, 0 );
  1237.  
  1238.             // Post a message to the dialog thread to update the 
  1239.             // UI.  This keeps the DirectPlay message handler 
  1240.             // from blocking
  1241.             if( g_hDlg != NULL )
  1242.                 PostMessage( g_hDlg, WM_APP_UPDATE_GRID, 0, 0 );
  1243.             break;
  1244.         }
  1245.  
  1246.         case DPN_MSGID_RECEIVE:
  1247.         {
  1248.             PDPNMSG_RECEIVE pReceiveMsg;
  1249.             pReceiveMsg = (PDPNMSG_RECEIVE)pMsgBuffer;
  1250.  
  1251.             GAMEMSG_GENERIC* pMsg = (GAMEMSG_GENERIC*) pReceiveMsg->pReceiveData;
  1252.             if( pMsg->dwType == GAME_MSGID_PLAYERMOVED )
  1253.             {
  1254.                 GAMEMSG_PLAYERMOVED* pPlayerMovedMsg;
  1255.                 pPlayerMovedMsg = (GAMEMSG_PLAYERMOVED*) pMsg;
  1256.  
  1257.                 APP_PLAYER_INFO* pPlayerInfo = (APP_PLAYER_INFO*) pReceiveMsg->pvPlayerContext;
  1258.                 EnterCriticalSection( &pPlayerInfo->csPlayer );
  1259.                 pPlayerInfo->pt = pPlayerMovedMsg->pt;
  1260.                 LeaveCriticalSection( &pPlayerInfo->csPlayer );
  1261.  
  1262.                 // Post a message to the dialog thread to update the 
  1263.                 // UI.  This keeps the DirectPlay message handler 
  1264.                 // from blocking
  1265.                 if( g_hDlg != NULL )
  1266.                     PostMessage( g_hDlg, WM_APP_UPDATE_GRID, 0, 0 );
  1267.             }
  1268.             break;
  1269.         }
  1270.  
  1271.         case DPN_MSGID_TERMINATE_SESSION:
  1272.         {
  1273.             PDPNMSG_TERMINATE_SESSION pTerminateSessionMsg;
  1274.             pTerminateSessionMsg = (PDPNMSG_TERMINATE_SESSION)pMsgBuffer;
  1275.  
  1276.             g_hrDialog = DPNERR_CONNECTIONLOST;
  1277.             EndDialog( g_hDlg, 0 );
  1278.             break;
  1279.         }
  1280.     }
  1281.  
  1282.     // Make sure the DirectPlay MessageHandler calls the CNetConnectWizard handler, 
  1283.     // so it can be informed of messages such as DPN_MSGID_ENUM_HOSTS_RESPONSE.
  1284.     if( g_pNetConnectWizard )
  1285.         return g_pNetConnectWizard->MessageHandler( pvUserContext, dwMessageId, pMsgBuffer );
  1286.     
  1287.     return S_OK;
  1288. }
  1289.  
  1290.  
  1291.  
  1292.  
  1293. //-----------------------------------------------------------------------------
  1294. // Name: DirectPlayLobbyMessageHandler
  1295. // Desc: Handler for DirectPlay lobby messages.  This function is called by
  1296. //       the DirectPlay lobby message handler pool of threads, so be careful of 
  1297. //       thread synchronization problems with shared memory
  1298. //-----------------------------------------------------------------------------
  1299. HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext, 
  1300.                                               DWORD dwMessageId, 
  1301.                                               PVOID pMsgBuffer )
  1302. {
  1303.     switch( dwMessageId )
  1304.     {
  1305.         case DPL_MSGID_CONNECT:
  1306.         {
  1307.             PDPL_MESSAGE_CONNECT pConnectMsg;
  1308.             pConnectMsg = (PDPL_MESSAGE_CONNECT)pMsgBuffer;
  1309.  
  1310.             // The CNetConnectWizard will handle this message for us,
  1311.             // so there is nothing we need to do here for this simple
  1312.             // sample.
  1313.             break;
  1314.         }
  1315.  
  1316.         case DPL_MSGID_DISCONNECT:
  1317.         {
  1318.             PDPL_MESSAGE_DISCONNECT pDisconnectMsg;
  1319.             pDisconnectMsg = (PDPL_MESSAGE_DISCONNECT)pMsgBuffer;
  1320.  
  1321.             // We should free any data associated with the lobby 
  1322.             // client here, but there is none.
  1323.             break;
  1324.         }
  1325.  
  1326.         case DPL_MSGID_RECEIVE:
  1327.         {
  1328.             PDPL_MESSAGE_RECEIVE pReceiveMsg;
  1329.             pReceiveMsg = (PDPL_MESSAGE_RECEIVE)pMsgBuffer;
  1330.  
  1331.             // The lobby client sent us data.  This sample doesn't
  1332.             // expected data from the client, but it is useful 
  1333.             // for more complex apps.
  1334.             break;
  1335.         }
  1336.  
  1337.         case DPL_MSGID_CONNECTION_SETTINGS:
  1338.         {
  1339.             PDPL_MESSAGE_CONNECTION_SETTINGS pConnectionStatusMsg;
  1340.             pConnectionStatusMsg = (PDPL_MESSAGE_CONNECTION_SETTINGS)pMsgBuffer;
  1341.  
  1342.             // The lobby client has changed the connection settings.  
  1343.             // This simple sample doesn't handle this, but more complex apps may
  1344.             // want to.
  1345.             break;
  1346.         }
  1347.     }
  1348.  
  1349.     // Make sure the DirectPlay MessageHandler calls the CNetConnectWizard handler, 
  1350.     // so the wizard can be informed of lobby messages such as DPL_MSGID_CONNECT
  1351.     if( g_pNetConnectWizard )
  1352.         return g_pNetConnectWizard->LobbyMessageHandler( pvUserContext, dwMessageId, 
  1353.                                                          pMsgBuffer );
  1354.     
  1355.     return S_OK;
  1356. }
  1357.  
  1358.  
  1359.  
  1360.  
  1361. //-----------------------------------------------------------------------------
  1362. // Name: DirectPlayVoiceServerMessageHandler()
  1363. // Desc: The callback for DirectPlayVoice server messages.  
  1364. //-----------------------------------------------------------------------------
  1365. HRESULT CALLBACK DirectPlayVoiceServerMessageHandler( LPVOID lpvUserContext, DWORD dwMessageType,
  1366.                                                       LPVOID lpMessage )
  1367. {
  1368.     // This simple sample doesn't respond to any server messages
  1369.     return S_OK;
  1370. }
  1371.  
  1372.  
  1373.  
  1374.  
  1375. //-----------------------------------------------------------------------------
  1376. // Name: DirectPlayVoiceClientMessageHandler()
  1377. // Desc: The callback for DirectPlayVoice client messages.  
  1378. //       This handles client messages and updates the UI the whenever a client 
  1379. //       starts or stops talking.  
  1380. //-----------------------------------------------------------------------------
  1381. HRESULT CALLBACK DirectPlayVoiceClientMessageHandler( LPVOID lpvUserContext, DWORD dwMessageType,
  1382.                                                       LPVOID lpMessage )
  1383. {
  1384.     // Try not to stay in this message handler for too long, otherwise
  1385.     // there will be a backlog of data.  The best solution is to 
  1386.     // queue data as it comes in, and then handle it on other threads.
  1387.     
  1388.     // This function is called by the DirectPlay message handler pool of 
  1389.     // threads, so be care of thread synchronization problems with shared memory
  1390.     HRESULT hr;
  1391.     HWND hDlg = (HWND) lpvUserContext;
  1392.  
  1393.     switch( dwMessageType )
  1394.     {
  1395.         case DVMSGID_SESSIONLOST:
  1396.             g_hrDialog = DPNERR_CONNECTIONLOST;
  1397.             EndDialog( g_hDlg, 0 );
  1398.             break;
  1399.  
  1400.         case DVMSGID_CREATEVOICEPLAYER:
  1401.             {
  1402.                 DVMSG_CREATEVOICEPLAYER* pCreateVoicePlayerMsg = (DVMSG_CREATEVOICEPLAYER*) lpMessage;
  1403.                 APP_PLAYER_INFO* pPlayerInfo = NULL;
  1404.  
  1405.                 PLAYER_LOCK(); // enter player context CS
  1406.  
  1407.                 // Get the player context accosicated with this DPNID
  1408.                 hr = g_pDP->GetPlayerContext( pCreateVoicePlayerMsg->dvidPlayer, 
  1409.                                               (LPVOID* const) &pPlayerInfo,
  1410.                                               0);
  1411.  
  1412.                 if( FAILED(hr) || pPlayerInfo == NULL )
  1413.                 {
  1414.                     // The player who sent this may have gone away before this 
  1415.                     // message was handled, so just ignore it
  1416.                     PLAYER_UNLOCK();
  1417.                     break;
  1418.                 }                
  1419.  
  1420.                 // Add and keep an extra reference for the voice context value
  1421.                 PLAYER_ADDREF( pPlayerInfo ); // addref player, since we are using it now
  1422.                 PLAYER_UNLOCK(); // leave player context CS
  1423.  
  1424.                 // Update the bHalfDuplex flag
  1425.                 pPlayerInfo->bHalfDuplex = ((pCreateVoicePlayerMsg->dwFlags & DVPLAYERCAPS_HALFDUPLEX) != 0);                
  1426.  
  1427.                 // Create a 3D buffer for all remote clients (but not the local one)
  1428.                 if( (DVID) pCreateVoicePlayerMsg->dvidPlayer != g_LocalPlayerDPNID )
  1429.                 {
  1430.                     DWORD dwResult = WaitForSingleObject( g_hSoundInit, 5000 );
  1431.                     if( dwResult == WAIT_TIMEOUT )
  1432.                         return E_FAIL;
  1433.  
  1434.                     LPDIRECTPLAYVOICECLIENT pVoiceClient = g_pNetVoice->GetVoiceClient();
  1435.  
  1436.                     EnterCriticalSection( &pPlayerInfo->csPlayer );
  1437.  
  1438.                     if( FAILED( hr = pVoiceClient->Create3DSoundBuffer( pCreateVoicePlayerMsg->dvidPlayer,
  1439.                                                                         NULL, 0, 0,
  1440.                                                                         &pPlayerInfo->pDSBVoice ) ) )
  1441.                         return DXTRACE_ERR( TEXT("Create3DSoundBuffer"), hr );        
  1442.  
  1443.                     if( FAILED( hr = pPlayerInfo->pDSBVoice->SetMinDistance( 5.0f, DS3D_DEFERRED ) ) )
  1444.                         return DXTRACE_ERR( TEXT("SetMinDistance"), hr );        
  1445.  
  1446.                     if( FAILED( hr = pPlayerInfo->pDSBVoice->SetMaxDistance( 20.0f, DS3D_DEFERRED ) ) )
  1447.                         return DXTRACE_ERR( TEXT("SetMaxDistance"), hr );        
  1448.  
  1449.                     FLOAT f3DPosX = (FLOAT) ( pPlayerInfo->pt.x - START_POSITION_X ) / 10.0f;
  1450.                     FLOAT f3DPosZ = (FLOAT) ( pPlayerInfo->pt.y - START_POSITION_Y ) / 10.0f;
  1451.  
  1452.                     if( FAILED( hr = pPlayerInfo->pDSBVoice->SetPosition( (FLOAT) f3DPosX, 0.0f, f3DPosZ, DS3D_DEFERRED ) ) )
  1453.                         return DXTRACE_ERR( TEXT("SetPosition"), hr );        
  1454.  
  1455.                     if( FAILED( hr = pPlayerInfo->pDSBVoice->SetVelocity( 0.0f, 0.0f, 0.0f, DS3D_DEFERRED ) ) )
  1456.                         return DXTRACE_ERR( TEXT("SetVelocity"), hr );        
  1457.  
  1458.                     LeaveCriticalSection( &pPlayerInfo->csPlayer );
  1459.  
  1460.                     if( FAILED( hr = g_pDSListener->CommitDeferredSettings() ) )
  1461.                         return DXTRACE_ERR( TEXT("CommitDeferredSettings"), hr );        
  1462.                 }
  1463.  
  1464.                 pCreateVoicePlayerMsg->pvPlayerContext = pPlayerInfo;
  1465.  
  1466.                 // Post a message to the dialog thread to update the 
  1467.                 // UI.  This keeps the DirectPlay message handler 
  1468.                 // from blocking
  1469.                 if( hDlg != NULL )
  1470.                     PostMessage( hDlg, WM_APP_DISPLAY_PLAYERS, 0, 0 );
  1471.  
  1472.                 SendLocalPosition( hDlg );
  1473.             }
  1474.             break;
  1475.  
  1476.         case DVMSGID_DELETEVOICEPLAYER:
  1477.         {
  1478.             DVMSG_DELETEVOICEPLAYER* pMsg = (DVMSG_DELETEVOICEPLAYER*) lpMessage;
  1479.             APP_PLAYER_INFO* pPlayerInfo = (APP_PLAYER_INFO*) pMsg->pvPlayerContext;
  1480.  
  1481.             EnterCriticalSection( &pPlayerInfo->csPlayer );
  1482.  
  1483.             // Don't update the dlg if this message is for the local 
  1484.             // client since the dlg will be gone.
  1485.             if( pMsg->dvidPlayer != g_LocalPlayerDPNID )
  1486.             {
  1487.                 // Post a message to the dialog thread to update the 
  1488.                 // UI.  This keeps the DirectPlay message handler 
  1489.                 // from blocking
  1490.                 if( hDlg != NULL )
  1491.                     PostMessage( hDlg, WM_APP_DISPLAY_PLAYERS, 0, 0 );
  1492.  
  1493.                 // Post a message to the dialog thread to update the 
  1494.                 // UI.  This keeps the DirectPlay message handler 
  1495.                 // from blocking
  1496.                 if( hDlg != NULL )
  1497.                     PostMessage( hDlg, WM_APP_UPDATE_GRID, 0, 0 );
  1498.  
  1499.                 LPDIRECTPLAYVOICECLIENT pVoiceClient = g_pNetVoice->GetVoiceClient();
  1500.                 if( FAILED( hr = pVoiceClient->Delete3DSoundBuffer( pPlayerInfo->dpnidPlayer,
  1501.                                                                     &pPlayerInfo->pDSBVoice ) ) )
  1502.                     DXTRACE_ERR( TEXT("Delete3DSoundBuffer"), hr );        
  1503.             }
  1504.  
  1505.             LeaveCriticalSection( &pPlayerInfo->csPlayer );
  1506.  
  1507.             // Release our extra reference on the player info that we have for the voice
  1508.             // context value.  
  1509.             //
  1510.             PLAYER_LOCK();
  1511.             PLAYER_RELEASE( pPlayerInfo );  
  1512.             PLAYER_UNLOCK();
  1513.             break;
  1514.         }
  1515.  
  1516.         case DVMSGID_HOSTMIGRATED:
  1517.         {
  1518.             DVMSG_HOSTMIGRATED* pMsg = (DVMSG_HOSTMIGRATED*) lpMessage;
  1519.  
  1520.             if( pMsg->pdvServerInterface != NULL )
  1521.             {           
  1522.                 // If we keep the pMsg->pdvServerInterface pointer around, then
  1523.                 // we must AddRef() it.  The CNetVoice::HostMigrate() automatically
  1524.                 // does this for us.
  1525.                 g_pNetVoice->HostMigrate( pMsg->pdvServerInterface );
  1526.  
  1527.                 g_bHostPlayer = TRUE;
  1528.                 SetWindowText( hDlg, TEXT("VoicePosition (Session Host)") );
  1529.             }
  1530.             break;
  1531.         }
  1532.  
  1533.         case DVMSGID_GAINFOCUS:
  1534.         case DVMSGID_LOSTFOCUS:
  1535.         {
  1536.             TCHAR strWindowName[MAX_PATH];
  1537.             wsprintf( strWindowName, TEXT("%s%s%s"), g_strAppName,
  1538.                 (g_bHostPlayer)                      ? TEXT(" (Session Host)") : TEXT(""),
  1539.                 (dwMessageType == DVMSGID_LOSTFOCUS) ? TEXT(" (Focus Lost)") : TEXT("") );
  1540.  
  1541.             SetWindowText( hDlg, strWindowName );
  1542.             break;
  1543.         }
  1544.  
  1545.         case DVMSGID_RECORDSTART:             
  1546.         { 
  1547.             DVMSG_RECORDSTART* pMsg = (DVMSG_RECORDSTART*) lpMessage;
  1548.             SetPlayerTalking( (APP_PLAYER_INFO*) pMsg->pvLocalPlayerContext, TRUE );
  1549.             break;
  1550.         }
  1551.         case DVMSGID_RECORDSTOP:             
  1552.         {
  1553.             DVMSG_RECORDSTOP* pMsg = (DVMSG_RECORDSTOP*) lpMessage;
  1554.             SetPlayerTalking( (APP_PLAYER_INFO*) pMsg->pvLocalPlayerContext, FALSE );
  1555.             break;
  1556.         }
  1557.         case DVMSGID_PLAYERVOICESTART:
  1558.         {
  1559.             DVMSG_PLAYERVOICESTART* pMsg = (DVMSG_PLAYERVOICESTART*) lpMessage;
  1560.             SetPlayerTalking( (APP_PLAYER_INFO*) pMsg->pvPlayerContext, TRUE );
  1561.             break;
  1562.         }
  1563.  
  1564.         case DVMSGID_PLAYERVOICESTOP:
  1565.         {
  1566.             DVMSG_PLAYERVOICESTOP* pMsg = (DVMSG_PLAYERVOICESTOP*) lpMessage;
  1567.             SetPlayerTalking( (APP_PLAYER_INFO*) pMsg->pvPlayerContext, FALSE );            
  1568.             break;
  1569.         }
  1570.     }
  1571.  
  1572.     return S_OK;
  1573. }
  1574.  
  1575.  
  1576.  
  1577.  
  1578. //-----------------------------------------------------------------------------
  1579. // Name: SetPlayerTalking()
  1580. // Desc: Set player talking flag
  1581. //-----------------------------------------------------------------------------
  1582. void SetPlayerTalking( APP_PLAYER_INFO* pPlayerInfo, BOOL bTalking )
  1583. {
  1584.     if( pPlayerInfo )
  1585.         pPlayerInfo->bTalking = bTalking;   
  1586. }
  1587.  
  1588.  
  1589.  
  1590.  
  1591. //-----------------------------------------------------------------------------
  1592. // Name: VoiceConfigDlgProc()
  1593. // Desc: Prompt the user for DirectPlayVoice setup options
  1594. //-----------------------------------------------------------------------------
  1595. INT_PTR CALLBACK VoiceConfigDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1596. {
  1597.     DWORD dwSliderPos;
  1598.  
  1599.     switch( msg ) 
  1600.     {
  1601.         case WM_INITDIALOG:
  1602.             // Set the range on the sliders
  1603.             SendDlgItemMessage( hDlg, IDC_PLAYBACK_SLIDER,       TBM_SETRANGE, FALSE, MAKELONG( 0, 100 ) );
  1604.             SendDlgItemMessage( hDlg, IDC_RECORD_SLIDER,         TBM_SETRANGE, FALSE, MAKELONG( 0, 100 ) );
  1605.             SendDlgItemMessage( hDlg, IDC_QUALITY_SLIDER,        TBM_SETRANGE, FALSE, MAKELONG( DVBUFFERQUALITY_MIN, DVBUFFERQUALITY_MAX ) );
  1606.             SendDlgItemMessage( hDlg, IDC_THRESHOLD_SLIDER,    TBM_SETRANGE, FALSE, MAKELONG( DVTHRESHOLD_MIN,  DVTHRESHOLD_MAX ) );
  1607.             SendDlgItemMessage( hDlg, IDC_AGGRESSIVENESS_SLIDER, TBM_SETRANGE, FALSE, MAKELONG( DVBUFFERAGGRESSIVENESS_MIN, DVBUFFERAGGRESSIVENESS_MAX ) );
  1608.  
  1609.             // Setup the dialog based on the globals 
  1610.  
  1611.             // Set the playback controls
  1612.             if( g_dvClientConfig.lPlaybackVolume == DVPLAYBACKVOLUME_DEFAULT )
  1613.             {
  1614.                 CheckRadioButton( hDlg, IDC_PLAYBACK_DEFAULT, IDC_PLAYBACK_SET, IDC_PLAYBACK_DEFAULT );
  1615.             }
  1616.             else
  1617.             {
  1618.                 dwSliderPos = (DWORD) ( ( g_dvClientConfig.lPlaybackVolume - DSBVOLUME_MIN ) * 
  1619.                                           100.0f / (DSBVOLUME_MAX-DSBVOLUME_MIN) );
  1620.                 CheckRadioButton( hDlg, IDC_PLAYBACK_DEFAULT, IDC_PLAYBACK_SET, IDC_PLAYBACK_SET );
  1621.                 SendDlgItemMessage( hDlg, IDC_PLAYBACK_SLIDER, TBM_SETPOS, TRUE, dwSliderPos );
  1622.             }
  1623.  
  1624.             // Set the record controls
  1625.             if( g_dvClientConfig.dwFlags & DVCLIENTCONFIG_AUTORECORDVOLUME )
  1626.             {
  1627.                 CheckRadioButton( hDlg, IDC_RECORD_DEFAULT, IDC_RECORD_AUTO, IDC_RECORD_AUTO );
  1628.             }
  1629.             else if( g_dvClientConfig.lRecordVolume == DVPLAYBACKVOLUME_DEFAULT )
  1630.             {
  1631.                 CheckRadioButton( hDlg, IDC_RECORD_DEFAULT, IDC_RECORD_AUTO, IDC_RECORD_DEFAULT );
  1632.             }
  1633.             else
  1634.             {
  1635.                 dwSliderPos = (DWORD) ( ( g_dvClientConfig.lRecordVolume - DSBVOLUME_MIN ) * 
  1636.                                           100.0f / (DSBVOLUME_MAX-DSBVOLUME_MIN) );
  1637.                 CheckRadioButton( hDlg, IDC_RECORD_DEFAULT, IDC_RECORD_AUTO, IDC_RECORD_SET );
  1638.                 SendDlgItemMessage( hDlg, IDC_RECORD_SLIDER, TBM_SETPOS, TRUE, dwSliderPos );
  1639.             }
  1640.  
  1641.             // Set the threshold controls
  1642.             if( g_dvClientConfig.dwFlags & DVCLIENTCONFIG_AUTOVOICEACTIVATED )
  1643.             {
  1644.                 CheckRadioButton( hDlg, IDC_THRESHOLD_DEFAULT, IDC_THRESHOLD_AUTO, IDC_THRESHOLD_AUTO );
  1645.             }
  1646.             else if( g_dvClientConfig.dwThreshold == DVTHRESHOLD_DEFAULT )
  1647.             {
  1648.                 CheckRadioButton( hDlg, IDC_THRESHOLD_DEFAULT, IDC_THRESHOLD_AUTO, IDC_THRESHOLD_DEFAULT );
  1649.             }
  1650.             else
  1651.             {
  1652.                 CheckRadioButton( hDlg, IDC_THRESHOLD_DEFAULT, IDC_THRESHOLD_AUTO, IDC_THRESHOLD_SET );
  1653.                 SendDlgItemMessage( hDlg, IDC_THRESHOLD_SLIDER, TBM_SETPOS, TRUE, g_dvClientConfig.dwThreshold );
  1654.             }
  1655.  
  1656.             // Set the quality controls
  1657.             if( g_dvClientConfig.dwBufferQuality == DVBUFFERQUALITY_DEFAULT )
  1658.             {
  1659.                 CheckRadioButton( hDlg, IDC_QUALITY_DEFAULT, IDC_QUALITY_SET, IDC_QUALITY_DEFAULT );
  1660.             }
  1661.             else
  1662.             {
  1663.                 CheckRadioButton( hDlg, IDC_QUALITY_DEFAULT, IDC_QUALITY_SET, IDC_QUALITY_SET );
  1664.                 SendDlgItemMessage( hDlg, IDC_QUALITY_SLIDER, TBM_SETPOS, TRUE, g_dvClientConfig.dwBufferQuality );
  1665.             }
  1666.  
  1667.             // Set the aggressiveness controls
  1668.             if( g_dvClientConfig.dwBufferAggressiveness == DVBUFFERAGGRESSIVENESS_DEFAULT )
  1669.             {
  1670.                 CheckRadioButton( hDlg, IDC_AGGRESSIVENESS_DEFAULT, IDC_AGGRESSIVENESS_SET, IDC_AGGRESSIVENESS_DEFAULT );
  1671.             }
  1672.             else
  1673.             {
  1674.                 CheckRadioButton( hDlg, IDC_AGGRESSIVENESS_DEFAULT, IDC_AGGRESSIVENESS_SET, IDC_AGGRESSIVENESS_SET );
  1675.                 SendDlgItemMessage( hDlg, IDC_AGGRESSIVENESS_SLIDER, TBM_SETPOS, TRUE, g_dvClientConfig.dwBufferAggressiveness );
  1676.             }
  1677.  
  1678.             if( !g_bHostPlayer || g_bVoiceSessionInProgress )
  1679.             {
  1680.                 // We are are not the host player then disable all the server only options 
  1681.                 EnableWindow( GetDlgItem( hDlg, IDC_COMPRESSION_COMBO ), FALSE );
  1682.                 EnableWindow( GetDlgItem( hDlg, IDC_SESSIONCOMPRESION_GROUP ), FALSE );
  1683.             }
  1684.             else
  1685.             {
  1686.                 VoiceConfigEnumCompressionCodecs( hDlg );   
  1687.                 EnableWindow( GetDlgItem( hDlg, IDCANCEL ), FALSE );
  1688.             }
  1689.  
  1690.             return TRUE;
  1691.  
  1692.         case WM_NOTIFY:
  1693.             #ifndef NM_RELEASEDCAPTURE
  1694.                 #define NM_RELEASEDCAPTURE (NM_FIRST-16)
  1695.             #endif
  1696.             if( ((LPNMHDR) lParam)->code == NM_RELEASEDCAPTURE )
  1697.             {
  1698.                 // If this is a release capture from a slider, then automatically check 
  1699.                 // its 'Set' radio button.
  1700.                 switch( ((LPNMHDR) lParam)->idFrom )
  1701.                 {
  1702.                 case IDC_PLAYBACK_SLIDER:
  1703.                     CheckRadioButton( hDlg, IDC_PLAYBACK_DEFAULT, IDC_PLAYBACK_SET, IDC_PLAYBACK_SET );
  1704.                     break;
  1705.     
  1706.                 case IDC_RECORD_SLIDER:
  1707.                     CheckRadioButton( hDlg, IDC_RECORD_DEFAULT, IDC_RECORD_AUTO, IDC_RECORD_SET );
  1708.                     break;
  1709.     
  1710.                 case IDC_THRESHOLD_SLIDER:
  1711.                     CheckRadioButton( hDlg, IDC_THRESHOLD_DEFAULT, IDC_THRESHOLD_AUTO, IDC_THRESHOLD_SET );
  1712.                     break;
  1713.     
  1714.                 case IDC_QUALITY_SLIDER:
  1715.                     CheckRadioButton( hDlg, IDC_QUALITY_DEFAULT, IDC_QUALITY_SET, IDC_QUALITY_SET );
  1716.                     break;
  1717.     
  1718.                 case IDC_AGGRESSIVENESS_SLIDER:
  1719.                     CheckRadioButton( hDlg, IDC_AGGRESSIVENESS_DEFAULT, IDC_AGGRESSIVENESS_SET, IDC_AGGRESSIVENESS_SET );
  1720.                     break;
  1721.                 }
  1722.             }
  1723.             return TRUE;            
  1724.  
  1725.         case WM_COMMAND:
  1726.             switch( LOWORD(wParam) )
  1727.             {
  1728.                 case IDOK:
  1729.                     VoiceConfigDlgOnOK( hDlg );
  1730.                     return TRUE;
  1731.  
  1732.                 case IDCANCEL:
  1733.                     EndDialog( hDlg, IDCANCEL );
  1734.                     return TRUE;
  1735.             }
  1736.             break;
  1737.  
  1738.         case WM_DESTROY:
  1739.         {
  1740.             GUID* pGuid;
  1741.             int nCount = (int)SendDlgItemMessage( hDlg, IDC_COMPRESSION_COMBO, CB_GETCOUNT, 0, 0 );
  1742.             for( int i=0; i<nCount; i++ )
  1743.             {
  1744.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_COMPRESSION_COMBO, CB_GETITEMDATA, i, 0 );
  1745.                 SAFE_DELETE( pGuid );
  1746.             }
  1747.             break;
  1748.         }
  1749.     }
  1750.  
  1751.     return FALSE; // Didn't handle message
  1752. }
  1753.  
  1754.  
  1755.  
  1756.  
  1757. //-----------------------------------------------------------------------------
  1758. // Name: VoiceConfigEnumCompressionCodecs()
  1759. // Desc: Asks DirectPlayVoice what voice compression codecs are availible
  1760. //       and fills the combo box thier names and GUIDs.
  1761. //-----------------------------------------------------------------------------
  1762. HRESULT VoiceConfigEnumCompressionCodecs( HWND hDlg )
  1763. {
  1764.     LPDIRECTPLAYVOICECLIENT pVoiceClient        = NULL;
  1765.     LPDVCOMPRESSIONINFO     pdvCompressionInfo  = NULL;
  1766.     LPGUID  pGuid         = NULL;
  1767.     LPBYTE  pBuffer       = NULL;
  1768.     DWORD   dwSize        = 0;
  1769.     DWORD   dwNumElements = 0;
  1770.     HWND    hPulldown     = GetDlgItem( hDlg, IDC_COMPRESSION_COMBO );
  1771.     HRESULT hr;
  1772.     LONG    lIndex;
  1773.     LONG    lFirst;
  1774.  
  1775.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  1776.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayVoiceClient, NULL, 
  1777.                                        CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceClient, 
  1778.                                        (VOID**) &pVoiceClient ) ) )
  1779.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );        
  1780.  
  1781.     hr = pVoiceClient->GetCompressionTypes( pBuffer, &dwSize, &dwNumElements, 0 );
  1782.     if( hr != DVERR_BUFFERTOOSMALL && FAILED(hr) )
  1783.         return DXTRACE_ERR( TEXT("GetCompressionTypes"), hr );        
  1784.  
  1785.     pBuffer = new BYTE[dwSize];
  1786.     if( FAILED( hr = pVoiceClient->GetCompressionTypes( pBuffer, &dwSize, 
  1787.                                                         &dwNumElements, 0 ) ) )
  1788.         return DXTRACE_ERR( TEXT("GetCompressionTypes"), hr );        
  1789.  
  1790.     SAFE_RELEASE( pVoiceClient );
  1791.     CoUninitialize();
  1792.  
  1793.     pdvCompressionInfo = (LPDVCOMPRESSIONINFO) pBuffer;
  1794.     for( DWORD dwIndex = 0; dwIndex < dwNumElements; dwIndex++ )
  1795.     {
  1796.         TCHAR strName[MAX_PATH];
  1797.  
  1798.         DXUtil_ConvertWideStringToGeneric( strName, pdvCompressionInfo[dwIndex].lpszName );
  1799.         lIndex = (LONG)SendMessage( hPulldown, CB_ADDSTRING, 0, (LPARAM) strName );
  1800.  
  1801.         pGuid = new GUID;
  1802.         (*pGuid) = pdvCompressionInfo[dwIndex].guidType;
  1803.         SendMessage( hPulldown, CB_SETITEMDATA, lIndex, (LPARAM) pGuid );
  1804.  
  1805.         if( pdvCompressionInfo[dwIndex].guidType == DPVCTGUID_SC03 )
  1806.             lFirst = lIndex;
  1807.     }
  1808.  
  1809.     SAFE_DELETE_ARRAY( pBuffer );
  1810.     SendMessage( hPulldown, CB_SETCURSEL, lFirst, 0 );
  1811.  
  1812.     return S_OK;
  1813. }
  1814.  
  1815.  
  1816.  
  1817.  
  1818. //-----------------------------------------------------------------------------
  1819. // Name: VoiceConfigDlgOnOK()
  1820. // Desc: Figure out all the DirectPlayVoice setup params from the dialog box,
  1821. //       and store them in global vars.
  1822. //-----------------------------------------------------------------------------
  1823. VOID VoiceConfigDlgOnOK( HWND hDlg )
  1824. {
  1825.     DWORD dwSliderPos;
  1826.  
  1827.     g_dvClientConfig.dwFlags = 0;
  1828.  
  1829.     // Figure out the playback params
  1830.     if( IsDlgButtonChecked( hDlg, IDC_PLAYBACK_DEFAULT ) )
  1831.     {
  1832.         g_dvClientConfig.lPlaybackVolume = DVPLAYBACKVOLUME_DEFAULT;
  1833.     }
  1834.     else 
  1835.     {
  1836.         dwSliderPos = (DWORD)SendDlgItemMessage( hDlg, IDC_PLAYBACK_SLIDER, TBM_GETPOS, 0, 0 );
  1837.         g_dvClientConfig.lPlaybackVolume = DSBVOLUME_MIN + (LONG) ( dwSliderPos / 100.0f * 
  1838.                                                                     (DSBVOLUME_MAX-DSBVOLUME_MIN) );
  1839.     }
  1840.  
  1841.     // Figure out the record params
  1842.     if( IsDlgButtonChecked( hDlg, IDC_RECORD_AUTO ) )
  1843.     {
  1844.         g_dvClientConfig.lRecordVolume = 0;
  1845.         g_dvClientConfig.dwFlags       |= DVCLIENTCONFIG_AUTORECORDVOLUME;
  1846.     }
  1847.     else if( IsDlgButtonChecked( hDlg, IDC_RECORD_DEFAULT ) )
  1848.     {
  1849.         g_dvClientConfig.lRecordVolume = DVPLAYBACKVOLUME_DEFAULT;
  1850.     }
  1851.     else 
  1852.     {
  1853.         dwSliderPos = (DWORD)SendDlgItemMessage( hDlg, IDC_RECORD_SLIDER, TBM_GETPOS, 0, 0 );
  1854.         g_dvClientConfig.lRecordVolume = DSBVOLUME_MIN + (LONG) ( dwSliderPos / 100.0f * 
  1855.                                                                   (DSBVOLUME_MAX-DSBVOLUME_MIN) );
  1856.     }
  1857.  
  1858.     // Figure out the threshold params
  1859.     if( IsDlgButtonChecked( hDlg, IDC_THRESHOLD_AUTO ) )
  1860.     {
  1861.         g_dvClientConfig.dwThreshold = DVTHRESHOLD_UNUSED;
  1862.         g_dvClientConfig.dwFlags       |= DVCLIENTCONFIG_AUTOVOICEACTIVATED;
  1863.     }
  1864.     else if( IsDlgButtonChecked( hDlg, IDC_THRESHOLD_DEFAULT ) )
  1865.     {
  1866.         g_dvClientConfig.dwThreshold = DVTHRESHOLD_DEFAULT;
  1867.         g_dvClientConfig.dwFlags       |= DVCLIENTCONFIG_MANUALVOICEACTIVATED;
  1868.     }
  1869.     else 
  1870.     {
  1871.         dwSliderPos = (DWORD)SendDlgItemMessage( hDlg, IDC_THRESHOLD_SLIDER, TBM_GETPOS, 0, 0 );
  1872.         g_dvClientConfig.dwThreshold = dwSliderPos;
  1873.         g_dvClientConfig.dwFlags       |= DVCLIENTCONFIG_MANUALVOICEACTIVATED;
  1874.     }
  1875.  
  1876.     // Figure out the quality params
  1877.     if( IsDlgButtonChecked( hDlg, IDC_QUALITY_DEFAULT ) )
  1878.     {
  1879.         g_dvClientConfig.dwBufferQuality = DVBUFFERQUALITY_DEFAULT;
  1880.     }
  1881.     else 
  1882.     {
  1883.         dwSliderPos = (DWORD)SendDlgItemMessage( hDlg, IDC_QUALITY_SLIDER, TBM_GETPOS, 0, 0 );
  1884.         g_dvClientConfig.dwBufferQuality = dwSliderPos;
  1885.     }
  1886.  
  1887.     // Figure out the aggressiveness params
  1888.     if( IsDlgButtonChecked( hDlg, IDC_AGGRESSIVENESS_DEFAULT ) )
  1889.     {
  1890.         g_dvClientConfig.dwBufferAggressiveness = DVBUFFERAGGRESSIVENESS_DEFAULT;
  1891.     }
  1892.     else 
  1893.     {
  1894.         dwSliderPos = (DWORD)SendDlgItemMessage( hDlg, IDC_AGGRESSIVENESS_SLIDER, TBM_GETPOS, 0, 0 );
  1895.         g_dvClientConfig.dwBufferAggressiveness = dwSliderPos;
  1896.     }
  1897.  
  1898.     if( g_bHostPlayer )
  1899.     {
  1900.         // Figure out the compression codec
  1901.         LONG lCurSelection;
  1902.         LPGUID pGuidCT;
  1903.  
  1904.         lCurSelection = (LONG)SendDlgItemMessage( hDlg, IDC_COMPRESSION_COMBO, CB_GETCURSEL, 0, 0 );
  1905.         if( lCurSelection != CB_ERR )
  1906.         {
  1907.             pGuidCT = (LPGUID) SendDlgItemMessage( hDlg, IDC_COMPRESSION_COMBO, 
  1908.                                                    CB_GETITEMDATA, lCurSelection, 0 );
  1909.             if( pGuidCT != NULL )
  1910.                 g_guidDVSessionCT = (*pGuidCT);
  1911.         }
  1912.     }
  1913.  
  1914.     EndDialog( hDlg, IDOK );
  1915. }
  1916.  
  1917.  
  1918.  
  1919.