Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1078 lines
30 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995-1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: voice.cpp
  6. * Content: Voice Support Routines
  7. * History:
  8. *
  9. * Date By Reason
  10. * ==== == ======
  11. * 10/15/99 rodtoll created it
  12. * rodtoll Plugged resource leak
  13. * 10/20/99 rodtoll Fix: Bug #113686 Not shutting down when receiving lobby message
  14. * 10/25/99 rodtoll Removed lpszVoicePassword member from sessiondesc
  15. * 10/28/99 pnewson Bug #114176 updated DVSOUNDDEVICECONFIG struct
  16. * 11/02/99 rodtoll Bug #116677 - Can't use lobby clients that don't hang around
  17. * 11/12/99 rodtoll Added support for the new waveIN/waveOut flags and the
  18. * echo suppression flag.
  19. * 11/29/99 rodtoll Bug #120249 - Modem host does not wait for connections. Added
  20. * message loop in voice thread.
  21. * 12/01/99 rodtoll Updated to use user selections for playback/record device
  22. * 12/07/99 rodtoll Bug #122628 Make error messages silent when running in silent mode
  23. * 12/08/99 rodtoll Bug #121054 Added support for flags to control new capture focus
  24. * 01/10/2000 pnewson Added support for dynamic Tx and Rx display for AGC & VA tuning
  25. * 01/14/2000 rodtoll Updated with API changes
  26. * 01/27/2000 rodtoll Updated with API changes
  27. * 01/28/2000 rodtoll Updated so Volume Set failures don't exit app (for records w/o volume)
  28. * 02/08/2000 rodtoll Bug #131496 - Selecting DVTHRESHOLD_DEFAULT results in voice
  29. * never being detected
  30. * 03/03/2000 rodtoll Updated to handle alternative gamevoice build.
  31. * 06/21/2000 rodtoll Bug #35767 - Implement ability for Dsound effects processing if dpvoice buffers
  32. * Updated DPVHELP to use new parameters
  33. * 06/27/2000 rodtoll Added support for new host migration message
  34. * 06/28/2000 rodtoll Prefix Bug #38033
  35. * 08/31/2000 rodtoll Bug #43804 - DVOICE: dwSensitivity structure member is confusing - should be dwThreshold
  36. * 04/02/2001 simonpow Bug #354859 - Fixes for PREfast
  37. * (removal unecessary local vars in DVMessageHandlerClient)
  38. *
  39. ***************************************************************************/
  40. #include "dxvhelppch.h"
  41. #define DVHELPER_CONNECT_TIMEOUT 15000
  42. #define DPLSYS_LOBBYCLIENTRELEASE 0x0000000B
  43. void VoiceManager_DisplayStatus( PDXVHELP_RTINFO prtInfo, LPTSTR lpstrStatus )
  44. {
  45. if( prtInfo->hMainDialog )
  46. {
  47. MainDialog_DisplayStatus( prtInfo->hMainDialog, lpstrStatus );
  48. }
  49. }
  50. BOOL VoiceManager_LobbyConnect( PDXVHELP_RTINFO prtInfo )
  51. {
  52. HRESULT hr;
  53. LPBYTE lpBuffer = NULL;
  54. DWORD dwSize = 0;
  55. BYTE *lpAddressBuffer = NULL;
  56. DWORD dwAddressSize = 0;
  57. LPDPLCONNECTION lpdplConnection = NULL;
  58. LPDPLMSG_GENERIC lpdlmGeneric = NULL;
  59. DWORD dwFlags;
  60. hr = CoCreateInstance( DPLAY_CLSID_DPLOBBY, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A, (void **) &prtInfo->lpdpLobby );
  61. if( FAILED( hr ) )
  62. {
  63. DPVDX_DPERRDisplay( hr, _T("Unable to to get ct info"), prtInfo->dxvParameters.fSilent);
  64. return FALSE;
  65. }
  66. dwSize = 0;
  67. if( prtInfo->dxvParameters.fWaitForSettings )
  68. {
  69. VoiceManager_DisplayStatus( prtInfo, _T("Waiting for settings") );
  70. hr = prtInfo->lpdpLobby->WaitForConnectionSettings( 0 );
  71. if( FAILED( hr ) )
  72. {
  73. DPVDX_DPERRDisplay( hr, _T("WaitForConnection FAILED"), prtInfo->dxvParameters.fSilent );
  74. goto LOBBY_CONNECT_CLEANUP;
  75. }
  76. lpBuffer = new BYTE[2000];
  77. lpdlmGeneric = (LPDPLMSG_GENERIC) lpBuffer;
  78. while( 1 )
  79. {
  80. if( WaitForSingleObject( prtInfo->hShutdown, 0 ) != WAIT_TIMEOUT )
  81. {
  82. goto LOBBY_CONNECT_CLEANUP;
  83. }
  84. dwSize = 2000;
  85. hr = prtInfo->lpdpLobby->ReceiveLobbyMessage( 0, 0, &dwFlags, lpBuffer, &dwSize );
  86. if( hr == DP_OK )
  87. {
  88. if( lpdlmGeneric->dwType == DPLSYS_NEWCONNECTIONSETTINGS )
  89. {
  90. break;
  91. }
  92. }
  93. Sleep( 50 );
  94. }
  95. delete [] lpBuffer;
  96. lpBuffer = NULL;
  97. }
  98. VoiceManager_DisplayStatus( prtInfo, _T("Getting Settings") );
  99. hr = prtInfo->lpdpLobby->GetConnectionSettings( 0, NULL, &dwSize );
  100. if( hr != DPERR_BUFFERTOOSMALL )
  101. {
  102. DPVDX_DPERRDisplay( hr, _T("Error retrieving connection settings size"), prtInfo->dxvParameters.fSilent );
  103. goto LOBBY_CONNECT_CLEANUP;
  104. }
  105. lpBuffer = new BYTE[dwSize];
  106. if( lpBuffer == NULL )
  107. {
  108. DPVDX_DPERRDisplay( DVERR_OUTOFMEMORY, _T("Failure allocating memory"), prtInfo->dxvParameters.fSilent );
  109. goto LOBBY_CONNECT_CLEANUP;
  110. }
  111. lpdplConnection = (LPDPLCONNECTION) lpBuffer;
  112. hr = prtInfo->lpdpLobby->GetConnectionSettings( 0, lpBuffer, &dwSize );
  113. if( FAILED( hr ) )
  114. {
  115. DPVDX_DPERRDisplay( hr, _T("Failed to retrieve settings"), prtInfo->dxvParameters.fSilent );
  116. goto LOBBY_CONNECT_CLEANUP;
  117. }
  118. // If we're connecting to a session we need to find the session
  119. if( !(lpdplConnection->dwFlags & DPLCONNECTION_CREATESESSION) )
  120. {
  121. prtInfo->dxvParameters.fHost = FALSE;
  122. VoiceManager_DisplayStatus( prtInfo, _T("Finding Session") );
  123. }
  124. else
  125. {
  126. // Over-ride protocol settings from lobby launch
  127. lpdplConnection->lpSessionDesc->dwFlags |= DPSESSION_DIRECTPLAYPROTOCOL | DPSESSION_KEEPALIVE | DPSESSION_MIGRATEHOST;
  128. prtInfo->dxvParameters.fHost = TRUE;
  129. // Launching from a session where the GetPlayerAddress on the server doesn't
  130. // allow getting a player's address
  131. if( lpdplConnection->lpAddress == NULL )
  132. {
  133. DPCOMPOUNDADDRESSELEMENT element;
  134. element.guidDataType = DPAID_ServiceProvider;
  135. element.dwDataSize = sizeof( GUID );
  136. element.lpData = &lpdplConnection->guidSP;
  137. hr = prtInfo->lpdpLobby->CreateCompoundAddress( &element, 1, NULL, &dwAddressSize );
  138. if( hr != DPERR_BUFFERTOOSMALL )
  139. {
  140. DPVDX_DPERRDisplay( hr, _T("Unable to create compound address for session host"), prtInfo->dxvParameters.fSilent );
  141. goto LOBBY_CONNECT_CLEANUP;
  142. }
  143. lpAddressBuffer = new BYTE[dwAddressSize];
  144. hr = prtInfo->lpdpLobby->CreateCompoundAddress( &element, 1, lpAddressBuffer, &dwAddressSize );
  145. if( FAILED( hr ) )
  146. {
  147. DPVDX_DPERRDisplay( hr, _T("Unable to create compound address for session host"), prtInfo->dxvParameters.fSilent );
  148. goto LOBBY_CONNECT_CLEANUP;
  149. }
  150. lpdplConnection->lpAddress = lpAddressBuffer;
  151. lpdplConnection->dwAddressSize = dwAddressSize;
  152. }
  153. }
  154. hr = prtInfo->lpdpLobby->SetConnectionSettings( 0, 0, lpdplConnection );
  155. if( FAILED( hr ) )
  156. {
  157. DPVDX_DPERRDisplay( hr, _T("Unable to set connection settings"), prtInfo->dxvParameters.fSilent );
  158. goto LOBBY_CONNECT_CLEANUP;
  159. }
  160. prtInfo->hLobbyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  161. hr = prtInfo->lpdpLobby->SetLobbyMessageEvent( 0, 0, prtInfo->hLobbyEvent );
  162. VoiceManager_DisplayStatus( prtInfo, _T("Connect/Start") );
  163. hr = prtInfo->lpdpLobby->ConnectEx( 0, IID_IDirectPlay4A, (void **) &prtInfo->lpdpDirectPlay, NULL );
  164. if( FAILED( hr ) )
  165. {
  166. DPVDX_DPERRDisplay( hr, _T("Failed to ConnectEx"), prtInfo->dxvParameters.fSilent );
  167. goto LOBBY_CONNECT_CLEANUP;
  168. }
  169. prtInfo->hReceiveEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  170. hr = prtInfo->lpdpDirectPlay->CreatePlayer( &prtInfo->dpidLocalPlayer, NULL, prtInfo->hReceiveEvent, NULL, 0, 0 );
  171. if( FAILED( hr ) )
  172. {
  173. DPVDX_DPERRDisplay( hr, _T("CreatePlayer Failed"), prtInfo->dxvParameters.fSilent );
  174. goto LOBBY_CONNECT_CLEANUP;
  175. }
  176. if( lpBuffer )
  177. delete [] lpBuffer;
  178. return TRUE;
  179. LOBBY_CONNECT_CLEANUP:
  180. if( prtInfo->lpdpLobby != NULL )
  181. {
  182. prtInfo->lpdpLobby->Release();
  183. }
  184. if( lpAddressBuffer != NULL )
  185. {
  186. delete [] lpAddressBuffer;
  187. }
  188. if( lpBuffer != NULL )
  189. {
  190. delete [] lpBuffer;
  191. }
  192. if( prtInfo->lpdpDirectPlay != NULL )
  193. {
  194. prtInfo->lpdpDirectPlay->Release();
  195. }
  196. return FALSE;
  197. }
  198. BOOL VoiceManager_StandardConnect( PDXVHELP_RTINFO prtInfo )
  199. {
  200. HRESULT hr;
  201. DWORD dwFlags = 0;
  202. GUID guidInstance;
  203. VoiceManager_DisplayStatus( prtInfo, _T("Creating dplay") );
  204. hr = CoCreateInstance( DPLAY_CLSID_DPLAY, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (void **) &prtInfo->lpdpDirectPlay );
  205. if( FAILED( hr ) )
  206. {
  207. DPVDX_DPERRDisplay( hr, _T("Unable to Create Lobby Object"), prtInfo->dxvParameters.fSilent );
  208. return FALSE;
  209. }
  210. hr = DPVDX_DP_Init( prtInfo->lpdpDirectPlay, DPSPGUID_TCPIP, (prtInfo->dxvParameters.fHost) ? NULL : prtInfo->dxvParameters.lpszConnectAddress );
  211. if( FAILED( hr ) )
  212. {
  213. DPVDX_DPERRDisplay( hr, _T("Initialize DirectPlay"), prtInfo->dxvParameters.fSilent );
  214. return FALSE;
  215. }
  216. if( prtInfo->dxvParameters.fHost )
  217. {
  218. dwFlags = DPSESSION_KEEPALIVE | DPSESSION_DIRECTPLAYPROTOCOL;
  219. if( prtInfo->dxvParameters.dwSessionType == DVSESSIONTYPE_PEER )
  220. {
  221. dwFlags |= DPSESSION_MIGRATEHOST;
  222. }
  223. VoiceManager_DisplayStatus( prtInfo, _T("Starting Session") );
  224. hr = DPVDX_DP_StartSession( prtInfo->lpdpDirectPlay, DPVHELP_PUBLIC_APPID, dwFlags, NULL, NULL, 0, &prtInfo->dpidLocalPlayer, &prtInfo->hReceiveEvent, &guidInstance ) ;
  225. if( FAILED( hr ) )
  226. {
  227. DPVDX_DPERRDisplay( hr, _T("Starting Session"), prtInfo->dxvParameters.fSilent );
  228. return FALSE;
  229. }
  230. }
  231. else
  232. {
  233. VoiceManager_DisplayStatus( prtInfo, _T("Finding Session") );
  234. hr = DPVDX_DP_FindSessionGUID( prtInfo->lpdpDirectPlay, DPVHELP_PUBLIC_APPID, DVHELPER_CONNECT_TIMEOUT, &guidInstance );
  235. if( FAILED( hr ) )
  236. {
  237. DPVDX_DPERRDisplay( hr, _T("Finding Session"), prtInfo->dxvParameters.fSilent );
  238. return FALSE;
  239. }
  240. VoiceManager_DisplayStatus( prtInfo, _T("Connecting") );
  241. hr = DPVDX_DP_ConnectToSession( prtInfo->lpdpDirectPlay, DPVHELP_PUBLIC_APPID, guidInstance, NULL, &prtInfo->dpidLocalPlayer, &prtInfo->hReceiveEvent );
  242. if( FAILED( hr ) )
  243. {
  244. DPVDX_DPERRDisplay( hr, _T("Connect To Session"), prtInfo->dxvParameters.fSilent );
  245. return FALSE;
  246. }
  247. }
  248. VoiceManager_DisplayStatus( prtInfo, _T("Dplay started") );
  249. return TRUE;
  250. }
  251. HRESULT PASCAL DVMessageHandlerServer(
  252. LPVOID lpvUserContext,
  253. DWORD dwMessageType,
  254. LPVOID lpMessage
  255. )
  256. {
  257. TCHAR szTmpString[180];
  258. PDXVHELP_RTINFO prtInfo = (PDXVHELP_RTINFO) lpvUserContext;
  259. PDVMSG_SESSIONLOST pdvSessionLost = NULL;
  260. PDVMSG_DELETEVOICEPLAYER pdvDeletePlayer = NULL;
  261. PDVMSG_CREATEVOICEPLAYER pdvCreatePlayer = NULL;
  262. switch( dwMessageType )
  263. {
  264. case DVMSGID_CREATEVOICEPLAYER:
  265. pdvCreatePlayer = (PDVMSG_CREATEVOICEPLAYER) lpMessage;
  266. pdvCreatePlayer->pvPlayerContext = (PVOID) (DWORD_PTR) pdvCreatePlayer->dvidPlayer;
  267. _stprintf( szTmpString, _T("[DVMSGID_CREATEVOICEPLAYER] **SERVER** ID=0x%x"), pdvCreatePlayer->dvidPlayer );
  268. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  269. break;
  270. case DVMSGID_DELETEVOICEPLAYER:
  271. pdvDeletePlayer = (PDVMSG_DELETEVOICEPLAYER) lpMessage;
  272. _stprintf( szTmpString, _T("[DVMSGID_DELETEVOICEPLAYER] **SERVER** ID=0x%x"), pdvDeletePlayer->dvidPlayer );
  273. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  274. break;
  275. case DVMSGID_SESSIONLOST:
  276. pdvSessionLost = (PDVMSG_SESSIONLOST) lpMessage;
  277. _stprintf( szTmpString, _T("[DVMSGID_SESSIONLOST] **SERVER** Reason=0x%x"), pdvSessionLost->hrResult );
  278. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  279. if( !prtInfo->dxvParameters.fSilent )
  280. {
  281. MessageBox( NULL, _T("Server Session lost!"),_T("Voice Conference"), MB_OK );
  282. }
  283. SetEvent( prtInfo->hShutdown );
  284. break;
  285. }
  286. return DV_OK;
  287. }
  288. HRESULT PASCAL DVMessageHandlerClient(
  289. LPVOID lpvUserContext,
  290. DWORD dwMessageType,
  291. LPVOID lpMessage
  292. )
  293. {
  294. TCHAR szTmpString[180];
  295. PDXVHELP_RTINFO prtInfo = (PDXVHELP_RTINFO) lpvUserContext;
  296. HWND hwndItem = NULL;
  297. PDVMSG_INPUTLEVEL pdvInputLevel = NULL;
  298. PDVMSG_OUTPUTLEVEL pdvOutputLevel = NULL;
  299. PDVMSG_HOSTMIGRATED pdvHostMigrated = NULL;
  300. PDVMSG_SESSIONLOST pdvSessionLost = NULL;
  301. PDVMSG_DELETEVOICEPLAYER pdvDeletePlayer = NULL;
  302. PDVMSG_CREATEVOICEPLAYER pdvCreatePlayer = NULL;
  303. PDVMSG_LOCALHOSTSETUP pdvLocalHostSetup = NULL;
  304. PDVMSG_PLAYERVOICESTART pdvPlayerVoiceStart = NULL;
  305. PDVMSG_PLAYERVOICESTOP pdvPlayerVoiceStop = NULL;
  306. PDVMSG_RECORDSTART pdvRecordStart = NULL;
  307. PDVMSG_RECORDSTOP pdvRecordStop = NULL;
  308. static int s_iRxCount = 0;
  309. char numBuffer[80];
  310. switch( dwMessageType )
  311. {
  312. case DVMSGID_LOCALHOSTSETUP:
  313. pdvLocalHostSetup = (PDVMSG_LOCALHOSTSETUP) lpMessage;
  314. _stprintf( szTmpString, _T("[DVMSGID_LOCALHOSTSETUP] Local client is to become host") );
  315. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  316. pdvLocalHostSetup->pMessageHandler = DVMessageHandlerServer;
  317. pdvLocalHostSetup->pvContext = lpvUserContext;
  318. break;
  319. case DVMSGID_CREATEVOICEPLAYER:
  320. pdvCreatePlayer = (PDVMSG_CREATEVOICEPLAYER) lpMessage;
  321. _stprintf( szTmpString, _T("[DVMSGID_CREATEVOICEPLAYER] ID=0x%x"), pdvCreatePlayer->dvidPlayer );
  322. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  323. MainDialog_AddVoicePlayer( prtInfo->hMainDialog, pdvCreatePlayer->dvidPlayer );
  324. prtInfo->dwNumClients++;
  325. wsprintf( numBuffer, "%d", prtInfo->dwNumClients );
  326. if( prtInfo->hMainDialog != NULL )
  327. {
  328. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_PLAYERS );
  329. if( hwndItem != NULL )
  330. {
  331. SetWindowText( hwndItem, numBuffer );
  332. }
  333. }
  334. pdvCreatePlayer->pvPlayerContext = (PVOID) (DWORD_PTR) pdvCreatePlayer->dvidPlayer;
  335. break;
  336. case DVMSGID_DELETEVOICEPLAYER:
  337. pdvDeletePlayer = (PDVMSG_DELETEVOICEPLAYER) lpMessage;
  338. _stprintf( szTmpString, _T("[DVMSGID_DELETEVOICEPLAYER] ID=0x%x"), pdvDeletePlayer->dvidPlayer );
  339. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  340. MainDialog_RemoveVoicePlayer( prtInfo->hMainDialog, pdvDeletePlayer->dvidPlayer );
  341. prtInfo->dwNumClients--;
  342. wsprintf( numBuffer, "%d", prtInfo->dwNumClients );
  343. if( prtInfo->hMainDialog != NULL )
  344. {
  345. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_PLAYERS );
  346. if( hwndItem != NULL )
  347. {
  348. SetWindowText( hwndItem, numBuffer );
  349. }
  350. }
  351. break;
  352. case DVMSGID_SESSIONLOST:
  353. pdvSessionLost = (PDVMSG_SESSIONLOST) lpMessage;
  354. _stprintf( szTmpString, _T("[DVMSGID_SESSIONLOST] Reason=0x%x"), pdvSessionLost->hrResult );
  355. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  356. if( !prtInfo->dxvParameters.fSilent )
  357. {
  358. MessageBox( NULL, _T("Session lost!"),_T("Voice Conference"), MB_OK );
  359. }
  360. SetEvent( prtInfo->hShutdown );
  361. break;
  362. case DVMSGID_INPUTLEVEL:
  363. pdvInputLevel = (PDVMSG_INPUTLEVEL) lpMessage;
  364. if( prtInfo->hMainDialog != NULL )
  365. {
  366. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_PROGRESS_TX );
  367. if( hwndItem != NULL )
  368. {
  369. SendMessage( hwndItem, PBM_SETPOS, (WPARAM) pdvInputLevel->dwPeakLevel, 0 );
  370. }
  371. }
  372. break;
  373. case DVMSGID_OUTPUTLEVEL:
  374. pdvOutputLevel = (PDVMSG_OUTPUTLEVEL) lpMessage;
  375. if( prtInfo->hMainDialog != NULL )
  376. {
  377. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_PROGRESS_RX );
  378. if( hwndItem != NULL )
  379. {
  380. SendMessage( hwndItem, PBM_SETPOS, (WPARAM) pdvOutputLevel->dwPeakLevel, 0 );
  381. }
  382. }
  383. break;
  384. case DVMSGID_RECORDSTART:
  385. if( prtInfo->hMainDialog != NULL )
  386. {
  387. pdvRecordStart = (PDVMSG_RECORDSTART) lpMessage;
  388. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_TX );
  389. if( hwndItem != NULL )
  390. {
  391. SendMessage( hwndItem, WM_SETTEXT, NULL, (LPARAM)"Tx" );
  392. }
  393. _stprintf( szTmpString, _T("[DVMSGID_RECORDSTART]") );
  394. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  395. }
  396. break;
  397. case DVMSGID_RECORDSTOP:
  398. if( prtInfo->hMainDialog != NULL )
  399. {
  400. pdvRecordStop = (PDVMSG_RECORDSTOP) lpMessage;
  401. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_TX );
  402. if( hwndItem != NULL )
  403. {
  404. SendMessage( hwndItem, WM_SETTEXT, NULL, (LPARAM)"" );
  405. }
  406. _stprintf( szTmpString, _T("[DVMSGID_RECORDSTOP]") );
  407. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  408. }
  409. break;
  410. case DVMSGID_PLAYERVOICESTART:
  411. pdvPlayerVoiceStart = (PDVMSG_PLAYERVOICESTART) lpMessage;
  412. if( prtInfo->hMainDialog != NULL )
  413. {
  414. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_RX );
  415. if( hwndItem != NULL )
  416. {
  417. ++s_iRxCount;
  418. SendMessage( hwndItem, WM_SETTEXT, NULL, (LPARAM)"Rx" );
  419. }
  420. _stprintf( szTmpString, _T("[DVMSGID_PLAYERVOICESTART] ID=0x%x"),
  421. pdvPlayerVoiceStart->dvidSourcePlayerID );
  422. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  423. }
  424. break;
  425. case DVMSGID_PLAYERVOICESTOP:
  426. pdvPlayerVoiceStop = (PDVMSG_PLAYERVOICESTOP) lpMessage;
  427. if( prtInfo->hMainDialog != NULL )
  428. {
  429. hwndItem = GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_RX );
  430. if( hwndItem != NULL )
  431. {
  432. --s_iRxCount;
  433. if (s_iRxCount <= 0)
  434. {
  435. SendMessage( hwndItem, WM_SETTEXT, NULL, (LPARAM)"" );
  436. }
  437. }
  438. _stprintf( szTmpString, _T("[DVMSGID_PLAYERVOICESTOP] ID=0x%x"),
  439. pdvPlayerVoiceStop->dvidSourcePlayerID );
  440. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  441. }
  442. break;
  443. case DVMSGID_HOSTMIGRATED:
  444. pdvHostMigrated = (PDVMSG_HOSTMIGRATED) lpMessage;
  445. _stprintf( szTmpString, _T("0x%x"), pdvHostMigrated->dvidNewHostID );
  446. SetWindowText( GetDlgItem( prtInfo->hMainDialog, IDC_STATIC_HOST ), szTmpString );
  447. _stprintf( szTmpString, _T("[DVMSGID_HOSTMIGRATED] New Voice Host=0x%x Local=%s"), pdvHostMigrated->dvidNewHostID, pdvHostMigrated->pdvServerInterface ? _T("Yes") : _T("No") );
  448. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  449. break;
  450. case DVMSGID_LOSTFOCUS:
  451. if( prtInfo->hMainDialog != NULL )
  452. {
  453. VoiceManager_DisplayStatus( prtInfo, _T( "Connected (Focus Lost)" ) );
  454. }
  455. _stprintf( szTmpString, _T("[DVMSGID_LOSTFOCUS]" ) );
  456. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  457. break;
  458. case DVMSGID_GAINFOCUS:
  459. if( prtInfo->hMainDialog != NULL )
  460. {
  461. VoiceManager_DisplayStatus( prtInfo, _T( "Connected" ) );
  462. }
  463. _stprintf( szTmpString, _T("[DVMSGID_GAINFOCUS]" ));
  464. MainDialog_AddToLog( prtInfo->hMainDialog, szTmpString );
  465. break;
  466. default:
  467. break;
  468. }
  469. return DV_OK;
  470. }
  471. void VoiceManager_MessageLoop( PDXVHELP_RTINFO prtInfo )
  472. {
  473. LPBYTE lpbDataBuffer = (LPBYTE) new BYTE[30000];
  474. if( lpbDataBuffer == NULL )
  475. {
  476. goto BREAK_OUT;
  477. }
  478. DWORD dwSize;
  479. HRESULT hr;
  480. LONG lWakeResult;
  481. DWORD dwFlags;
  482. MSG msg;
  483. HANDLE hEvents[3];
  484. LPDPLMSG_SYSTEMMESSAGE lpSysMessage;
  485. LPDPMSG_GENERIC lpGenericMessage;
  486. LPDPMSG_CREATEPLAYERORGROUP lpCreatePlayerMessage;
  487. LPDPMSG_DESTROYPLAYERORGROUP lpDeletePlayerMessage;
  488. BOOL bGotMsg;
  489. DPID dpidFrom, dpidTo;
  490. hEvents[0] = prtInfo->hShutdown;
  491. hEvents[1] = prtInfo->hReceiveEvent;
  492. hEvents[2] = prtInfo->hLobbyEvent;
  493. // hr = prtInfo->lpdpDirectPlay->CreatePlayer( &prtInfo->dpidLocalPlayer, NULL, prtInfo->hReceiveEvent, NULL, 0, 0 );
  494. while( 1 )
  495. {
  496. if( !prtInfo->dxvParameters.fLobbyLaunched )
  497. {
  498. lWakeResult = MsgWaitForMultipleObjects( 2, hEvents, FALSE, INFINITE, QS_ALLINPUT);
  499. }
  500. else
  501. {
  502. lWakeResult = MsgWaitForMultipleObjects( 3, hEvents, FALSE, INFINITE, QS_ALLINPUT);
  503. }
  504. if( lWakeResult == WAIT_OBJECT_0 )
  505. {
  506. break;
  507. }
  508. else if( lWakeResult == (WAIT_OBJECT_0+1) )
  509. {
  510. while( 1 )
  511. {
  512. dwSize = 30000;
  513. hr = prtInfo->lpdpDirectPlay->Receive( &dpidFrom, &dpidTo, DPRECEIVE_ALL, lpbDataBuffer, &dwSize );
  514. if( hr == DPERR_NOMESSAGES )
  515. {
  516. break;
  517. }
  518. lpGenericMessage = (LPDPMSG_GENERIC) lpbDataBuffer;
  519. switch( lpGenericMessage->dwType )
  520. {
  521. case DPSYS_HOST:
  522. {
  523. MainDialog_AddToLog( prtInfo->hMainDialog, _T("[DPMSG_HOST] This client has just become the DPLAY host") );
  524. }
  525. break;
  526. case DPSYS_CREATEPLAYERORGROUP:
  527. {
  528. TCHAR tszMessage[100];
  529. lpCreatePlayerMessage = (LPDPMSG_CREATEPLAYERORGROUP) lpbDataBuffer;
  530. if( lpCreatePlayerMessage->dwPlayerType == DPPLAYERTYPE_PLAYER )
  531. {
  532. _stprintf( tszMessage, _T("[DPMSG_CREATEPLAYER] Client 0x%x has just entered the session."), lpCreatePlayerMessage->dpId );
  533. MainDialog_AddToLog( prtInfo->hMainDialog, tszMessage );
  534. }
  535. MainDialog_AddTransportPlayer( prtInfo->hMainDialog, lpCreatePlayerMessage->dpId );
  536. }
  537. break;
  538. case DPSYS_DESTROYPLAYERORGROUP:
  539. {
  540. TCHAR tszMessage[100];
  541. lpDeletePlayerMessage = (LPDPMSG_DESTROYPLAYERORGROUP) lpbDataBuffer;
  542. if( lpDeletePlayerMessage->dwPlayerType == DPPLAYERTYPE_PLAYER )
  543. {
  544. _stprintf( tszMessage, _T("[DPMSG_DELETEPLAYER] Client 0x%x has just left the session."), lpDeletePlayerMessage->dpId );
  545. MainDialog_AddToLog( prtInfo->hMainDialog, tszMessage );
  546. }
  547. MainDialog_RemoveTransportPlayer( prtInfo->hMainDialog, lpDeletePlayerMessage->dpId );
  548. }
  549. break;
  550. }
  551. }
  552. }
  553. else if( prtInfo->dxvParameters.fLobbyLaunched && lWakeResult == (WAIT_OBJECT_0+2) )
  554. {
  555. hr = DP_OK;
  556. while( hr != DPERR_NOMESSAGES )
  557. {
  558. dwSize = 30000;
  559. hr = prtInfo->lpdpLobby->ReceiveLobbyMessage( 0, 0, &dwFlags, lpbDataBuffer, &dwSize );
  560. if( hr == DPERR_NOMESSAGES )
  561. {
  562. break;
  563. }
  564. else if( hr == DP_OK )
  565. {
  566. if( !prtInfo->dxvParameters.fIgnoreLobbyDestroy )
  567. {
  568. if( dwFlags == 0 )
  569. {
  570. goto BREAK_OUT;
  571. }
  572. else if( dwFlags && DPLMSG_SYSTEM )
  573. {
  574. lpSysMessage = (LPDPLMSG_SYSTEMMESSAGE) lpbDataBuffer;
  575. if( lpSysMessage->dwType == DPLSYS_LOBBYCLIENTRELEASE )
  576. {
  577. goto BREAK_OUT;
  578. }
  579. }
  580. }
  581. }
  582. else
  583. {
  584. DPVDX_DPERRDisplay( hr, _T("Receive Lobby Message Error"), prtInfo->dxvParameters.fSilent );
  585. }
  586. }
  587. }
  588. else
  589. {
  590. bGotMsg = TRUE;
  591. while( bGotMsg )
  592. {
  593. bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
  594. if( bGotMsg )
  595. {
  596. TranslateMessage( &msg );
  597. DispatchMessage( &msg );
  598. }
  599. }
  600. }
  601. }
  602. BREAK_OUT:
  603. if( lpbDataBuffer )
  604. delete [] lpbDataBuffer;
  605. return;
  606. }
  607. void VoiceManager_Shutdown( PDXVHELP_RTINFO prtInfo )
  608. {
  609. HRESULT hr;
  610. VoiceManager_DisplayStatus( prtInfo, _T("Disconnecting") );
  611. if( prtInfo->lpdpLobby != NULL )
  612. {
  613. prtInfo->lpdpLobby->Release();
  614. prtInfo->lpdpLobby = NULL;
  615. }
  616. if( prtInfo->lpdvClient != NULL )
  617. {
  618. VoiceManager_DisplayStatus( prtInfo, _T("Disconnecting") );
  619. hr = prtInfo->lpdvClient->Disconnect( DVFLAGS_SYNC );
  620. if( FAILED( hr ) )
  621. {
  622. DPVDX_DPERRDisplay( hr, _T("Disconnect FAILED "), prtInfo->dxvParameters.fSilent );
  623. }
  624. prtInfo->lpdvClient->Release();
  625. }
  626. if( prtInfo->lpdvServer != NULL )
  627. {
  628. VoiceManager_DisplayStatus( prtInfo, _T("Stopping Session") );
  629. hr = prtInfo->lpdvServer->StopSession( 0 );
  630. if( FAILED( hr ) )
  631. {
  632. DPVDX_DPERRDisplay( hr, _T("StopSession FAILED "), prtInfo->dxvParameters.fSilent );
  633. }
  634. prtInfo->lpdvServer->Release();
  635. }
  636. if( prtInfo->lpdpDirectPlay != NULL )
  637. {
  638. VoiceManager_DisplayStatus( prtInfo, _T("Stopping Dplay") );
  639. prtInfo->lpdpDirectPlay->Close();
  640. prtInfo->lpdpDirectPlay->Release();
  641. }
  642. CloseHandle( prtInfo->hReceiveEvent );
  643. if( prtInfo->hLobbyEvent != NULL )
  644. {
  645. CloseHandle( prtInfo->hLobbyEvent );
  646. }
  647. MainDialog_SetIdleState( prtInfo->hMainDialog, prtInfo );
  648. }
  649. BOOL VoiceManager_VoiceConnect( PDXVHELP_RTINFO prtInfo )
  650. {
  651. DVSESSIONDESC dvSessionDesc;
  652. DVCLIENTCONFIG dvClientConfig;
  653. DVSOUNDDEVICECONFIG dvSoundDeviceConfig;
  654. HRESULT hr;
  655. DVID dvidAllPlayers = DVID_ALLPLAYERS;
  656. // We're the host
  657. if( prtInfo->dxvParameters.fHost )
  658. {
  659. VoiceManager_DisplayStatus( prtInfo, _T("Start Voice Host") );
  660. hr = CoCreateInstance( DPVOICE_CLSID_DPVOICE, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceServer, (void **) &prtInfo->lpdvServer );
  661. if( FAILED( hr ) )
  662. {
  663. DPVDX_DVERRDisplay( hr, _T("Create of voice server failed"), prtInfo->dxvParameters.fSilent );
  664. goto EXIT_CLEANUP;
  665. }
  666. hr = prtInfo->lpdvServer->Initialize( prtInfo->lpdpDirectPlay, DVMessageHandlerServer, prtInfo, NULL, 0 );
  667. if( FAILED( hr ) )
  668. {
  669. DPVDX_DVERRDisplay( hr, _T("Initialize FAILED"), prtInfo->dxvParameters.fSilent );
  670. goto EXIT_CLEANUP;
  671. }
  672. dvSessionDesc.dwSize = sizeof( DVSESSIONDESC );
  673. dvSessionDesc.dwBufferAggressiveness = DVBUFFERAGGRESSIVENESS_DEFAULT;
  674. dvSessionDesc.dwBufferQuality = DVBUFFERQUALITY_DEFAULT;
  675. dvSessionDesc.dwFlags = 0;
  676. dvSessionDesc.dwSessionType = prtInfo->dxvParameters.dwSessionType;
  677. dvSessionDesc.guidCT = prtInfo->dxvParameters.guidCT;
  678. hr = prtInfo->lpdvServer->StartSession( &dvSessionDesc, 0 );
  679. if( FAILED( hr ) )
  680. {
  681. DPVDX_DVERRDisplay( hr, _T("StartSession FAILED"), prtInfo->dxvParameters.fSilent );
  682. goto EXIT_CLEANUP;
  683. }
  684. }
  685. VoiceManager_DisplayStatus( prtInfo, _T("Start Client") );
  686. hr = CoCreateInstance( DPVOICE_CLSID_DPVOICE, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayVoiceClient, (void **) &prtInfo->lpdvClient );
  687. if( FAILED( hr ) )
  688. {
  689. DPVDX_DVERRDisplay( hr, _T("Create of client failed"), prtInfo->dxvParameters.fSilent );
  690. goto EXIT_CLEANUP;
  691. }
  692. hr = prtInfo->lpdvClient->Initialize( prtInfo->lpdpDirectPlay, DVMessageHandlerClient, prtInfo, NULL, 0 );
  693. if( FAILED( hr ) )
  694. {
  695. DPVDX_DVERRDisplay( hr, _T("Initialize FAILED"), prtInfo->dxvParameters.fSilent );
  696. goto EXIT_CLEANUP;
  697. }
  698. dvSoundDeviceConfig.dwSize = sizeof( DVSOUNDDEVICECONFIG );
  699. dvSoundDeviceConfig.hwndAppWindow = prtInfo->hMainWnd;
  700. dvSoundDeviceConfig.dwFlags = 0;
  701. if( prtInfo->dxvParameters.fForceWaveOut )
  702. {
  703. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_FORCEWAVEOUT;
  704. }
  705. else if( prtInfo->dxvParameters.fAllowWaveOut )
  706. {
  707. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_ALLOWWAVEOUT;
  708. }
  709. if( prtInfo->dxvParameters.fForceWaveIn )
  710. {
  711. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_FORCEWAVEIN;
  712. }
  713. else if( prtInfo->dxvParameters.fAllowWaveIn )
  714. {
  715. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_ALLOWWAVEIN;
  716. }
  717. if( prtInfo->dxvParameters.fAutoSelectMic )
  718. {
  719. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_AUTOSELECT;
  720. }
  721. if( prtInfo->dxvParameters.fDisableFocus )
  722. {
  723. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_NOFOCUS;
  724. }
  725. else if( prtInfo->dxvParameters.fStrictFocus )
  726. {
  727. dvSoundDeviceConfig.dwFlags |= DVSOUNDCONFIG_STRICTFOCUS;
  728. }
  729. dvSoundDeviceConfig.guidCaptureDevice = prtInfo->dxvParameters.guidRecordDevice;
  730. dvSoundDeviceConfig.guidPlaybackDevice = prtInfo->dxvParameters.guidPlaybackDevice;
  731. dvSoundDeviceConfig.lpdsPlaybackDevice = NULL;
  732. dvSoundDeviceConfig.lpdsCaptureDevice = NULL;
  733. dvSoundDeviceConfig.lpdsMainBuffer = NULL;
  734. dvSoundDeviceConfig.dwMainBufferFlags = 0;
  735. dvSoundDeviceConfig.dwMainBufferPriority = 0;
  736. dvClientConfig.lRecordVolume = DSBVOLUME_MAX;
  737. MicrophoneGetVolume( 0, dvClientConfig.lRecordVolume );
  738. prtInfo->dxvParameters.lRecordVolume = dvClientConfig.lRecordVolume;
  739. dvClientConfig.dwFlags = DVCLIENTCONFIG_AUTOVOICEACTIVATED;
  740. if( prtInfo->dxvParameters.fAGC )
  741. {
  742. dvClientConfig.dwFlags |= DVCLIENTCONFIG_AUTORECORDVOLUME;
  743. dvClientConfig.lRecordVolume = DVRECORDVOLUME_LAST;
  744. }
  745. if( prtInfo->dxvParameters.fEchoSuppression )
  746. {
  747. dvClientConfig.dwFlags |= DVCLIENTCONFIG_ECHOSUPPRESSION;
  748. }
  749. dvClientConfig.dwThreshold = DVTHRESHOLD_UNUSED;
  750. dvClientConfig.lPlaybackVolume = DSBVOLUME_MAX;
  751. dvClientConfig.dwNotifyPeriod = 51;
  752. dvClientConfig.dwBufferQuality = DVBUFFERQUALITY_DEFAULT;
  753. dvClientConfig.dwBufferAggressiveness = DVBUFFERAGGRESSIVENESS_DEFAULT;
  754. dvClientConfig.dwSize = sizeof( DVCLIENTCONFIG );
  755. VoiceManager_DisplayStatus( prtInfo, _T("Connecting Voice") );
  756. hr = prtInfo->lpdvClient->Connect( &dvSoundDeviceConfig, &dvClientConfig, DVFLAGS_SYNC );
  757. if( hr != DV_OK && hr != DVERR_PENDING )
  758. {
  759. DPVDX_DVERRDisplay( hr, _T("Connect FAILED"), prtInfo->dxvParameters.fSilent );
  760. goto EXIT_CLEANUP;
  761. }
  762. MainDialog_DisplayVolumeSettings( prtInfo->hMainDialog, prtInfo );
  763. VoiceManager_DisplayStatus( prtInfo, _T("Connected") );
  764. MainDialog_ShowSessionSettings( prtInfo->hMainDialog, prtInfo);
  765. prtInfo->lpdvClient->SetTransmitTargets( &dvidAllPlayers, 1, 0 );
  766. return TRUE;
  767. EXIT_CLEANUP:
  768. if( prtInfo->lpdvClient != NULL )
  769. {
  770. prtInfo->lpdvClient->Release();
  771. }
  772. if( prtInfo->lpdvServer != NULL )
  773. {
  774. prtInfo->lpdvServer->Release();
  775. }
  776. MainDialog_SetIdleState( prtInfo->hMainDialog, prtInfo );
  777. VoiceManager_DisplayStatus( prtInfo, _T("Aborted") );
  778. return FALSE;
  779. }
  780. // ManagerThread
  781. //
  782. // This thread is responsible for running the session, allowing the main interface
  783. // to remain responsive.
  784. //
  785. DWORD WINAPI VoiceManager_ThreadProc( LPVOID lpParameter )
  786. {
  787. PDXVHELP_RTINFO prtInfo = (PDXVHELP_RTINFO) lpParameter;
  788. BOOL fResult;
  789. HANDLE hEventArray[2];
  790. HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  791. if( FAILED( hr ) )
  792. {
  793. goto EXIT_ERROR;
  794. }
  795. hEventArray[0] = prtInfo->hShutdown; // Cancel
  796. hEventArray[1] = prtInfo->hGo; // Start Session
  797. // Wait to be cancelled or started
  798. if( WaitForMultipleObjects( 2, hEventArray, FALSE, INFINITE ) != WAIT_OBJECT_0 )
  799. {
  800. if( prtInfo->dxvParameters.fLobbyLaunched )
  801. {
  802. fResult = VoiceManager_LobbyConnect( prtInfo );
  803. }
  804. else
  805. {
  806. fResult = VoiceManager_StandardConnect( prtInfo );
  807. }
  808. if( fResult )
  809. {
  810. fResult = VoiceManager_VoiceConnect( prtInfo );
  811. if( fResult )
  812. {
  813. VoiceManager_MessageLoop( prtInfo );
  814. VoiceManager_Shutdown( prtInfo );
  815. }
  816. }
  817. }
  818. CoUninitialize();
  819. EXIT_ERROR:
  820. SetEvent( prtInfo->hThreadDone );
  821. return 0;
  822. }
  823. BOOL VoiceManager_Start( PDXVHELP_RTINFO prtInfo )
  824. {
  825. DWORD dwThreadID = 0;
  826. prtInfo->hManagerThread = CreateThread( NULL, 0, VoiceManager_ThreadProc, prtInfo, 0, &dwThreadID );
  827. return TRUE;
  828. }
  829. BOOL VoiceManager_Stop( PDXVHELP_RTINFO prtInfo )
  830. {
  831. WaitForSingleObject( prtInfo->hThreadDone, INFINITE );
  832. CloseHandle( prtInfo->hManagerThread );
  833. return TRUE;
  834. }