Team Fortress 2 Source Code as on 22/4/2020
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.

278 lines
7.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. #include "audio_pch.h"
  3. //#include "matchmaking/IMatchFramework.h"
  4. #include "tier2/tier2.h"
  5. #include "audio/public/voice.h"
  6. #if !defined( DEDICATED ) && ( defined( OSX ) || defined( _WIN32 ) ) && !defined( NO_STEAM )
  7. #include "cl_steamauth.h"
  8. #endif
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. CEngineVoiceStub *Audio_GetEngineVoiceStub()
  12. {
  13. static CEngineVoiceStub s_EngineVoiceStub;
  14. return &s_EngineVoiceStub;
  15. }
  16. #if !defined( DEDICATED ) && ( defined( OSX ) || defined( _WIN32 ) ) && !defined( NO_STEAM )
  17. class CEngineVoiceSteam : public IEngineVoice
  18. {
  19. public:
  20. CEngineVoiceSteam();
  21. public:
  22. virtual bool IsHeadsetPresent( int iController );
  23. virtual bool IsLocalPlayerTalking( int iController );
  24. virtual void AddPlayerToVoiceList( XUID xPlayer, int iController );
  25. virtual void RemovePlayerFromVoiceList( XUID xPlayer, int iController );
  26. virtual void GetRemoteTalkers( int *pNumTalkers, XUID *pRemoteTalkers );
  27. virtual bool VoiceUpdateData( int iController );
  28. virtual void GetVoiceData( int iController, const byte **ppvVoiceDataBuffer, unsigned int *pnumVoiceDataBytes );
  29. virtual void VoiceResetLocalData( int iController );
  30. virtual void SetPlaybackPriority( XUID remoteTalker, int iController, int iAllowPlayback );
  31. virtual void PlayIncomingVoiceData( XUID xuid, const byte *pbData, unsigned int dwDataSize, const bool *bAudiblePlayers = NULL );
  32. virtual void RemoveAllTalkers();
  33. protected:
  34. void AudioInitializationUpdate();
  35. public:
  36. bool m_bLocalVoice[ XUSER_MAX_COUNT ];
  37. CUtlVector< XUID > m_arrRemoteVoice;
  38. bool m_bInitializedAudio;
  39. byte m_pbVoiceData[ 1024 * XUSER_MAX_COUNT ];
  40. };
  41. CEngineVoiceSteam::CEngineVoiceSteam()
  42. {
  43. memset( m_bLocalVoice, 0, sizeof( m_bLocalVoice ) );
  44. memset( m_pbVoiceData, 0, sizeof( m_pbVoiceData ) );
  45. m_bInitializedAudio = false;
  46. }
  47. bool CEngineVoiceSteam::IsHeadsetPresent( int iController )
  48. {
  49. return false;
  50. }
  51. bool CEngineVoiceSteam::IsLocalPlayerTalking( int iController )
  52. {
  53. uint32 nBytes = 0;
  54. EVoiceResult res = Steam3Client().SteamUser()->GetAvailableVoice( &nBytes, NULL, 0 );
  55. switch ( res )
  56. {
  57. case k_EVoiceResultOK:
  58. case k_EVoiceResultNoData:
  59. case k_EVoiceResultBufferTooSmall:
  60. return true;
  61. default:
  62. return false;
  63. }
  64. }
  65. void CEngineVoiceSteam::AddPlayerToVoiceList( XUID xPlayer, int iController )
  66. {
  67. if ( !xPlayer && iController >= 0 && iController < XUSER_MAX_COUNT )
  68. {
  69. // Add local player
  70. m_bLocalVoice[ iController ] = true;
  71. AudioInitializationUpdate();
  72. }
  73. if ( xPlayer )
  74. {
  75. if ( m_arrRemoteVoice.Find( xPlayer ) == m_arrRemoteVoice.InvalidIndex() )
  76. {
  77. m_arrRemoteVoice.AddToTail( xPlayer );
  78. AudioInitializationUpdate();
  79. }
  80. }
  81. }
  82. void CEngineVoiceSteam::RemovePlayerFromVoiceList( XUID xPlayer, int iController )
  83. {
  84. if ( !xPlayer && iController >= 0 && iController < XUSER_MAX_COUNT )
  85. {
  86. // Remove local player
  87. m_bLocalVoice[ iController ] = false;
  88. AudioInitializationUpdate();
  89. }
  90. if ( xPlayer )
  91. {
  92. int idx = m_arrRemoteVoice.Find( xPlayer );
  93. if ( idx != m_arrRemoteVoice.InvalidIndex() )
  94. {
  95. m_arrRemoteVoice.FastRemove( idx );
  96. AudioInitializationUpdate();
  97. }
  98. }
  99. }
  100. void CEngineVoiceSteam::GetRemoteTalkers( int *pNumTalkers, XUID *pRemoteTalkers )
  101. {
  102. if ( pNumTalkers )
  103. *pNumTalkers = m_arrRemoteVoice.Count();
  104. if ( pRemoteTalkers )
  105. {
  106. for ( int k = 0; k < m_arrRemoteVoice.Count(); ++ k )
  107. pRemoteTalkers[k] = m_arrRemoteVoice[k];
  108. }
  109. }
  110. bool CEngineVoiceSteam::VoiceUpdateData( int iController )
  111. {
  112. uint32 nBytes = 0;
  113. EVoiceResult res = Steam3Client().SteamUser()->GetAvailableVoice( &nBytes, NULL, 0 );
  114. switch ( res )
  115. {
  116. case k_EVoiceResultOK:
  117. // case k_EVoiceResultNoData: - no data means false
  118. case k_EVoiceResultBufferTooSmall:
  119. return true;
  120. default:
  121. return false;
  122. }
  123. }
  124. void CEngineVoiceSteam::GetVoiceData( int iController, const byte **ppvVoiceDataBuffer, unsigned int *pnumVoiceDataBytes )
  125. {
  126. const int size = ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT;
  127. byte *pbVoiceData = m_pbVoiceData + iController * ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT;
  128. *ppvVoiceDataBuffer = pbVoiceData;
  129. EVoiceResult res = Steam3Client().SteamUser()->GetVoice( true, pbVoiceData, size, pnumVoiceDataBytes, false, NULL, 0, NULL, 0 );
  130. switch ( res )
  131. {
  132. case k_EVoiceResultNoData:
  133. case k_EVoiceResultOK:
  134. return;
  135. default:
  136. *pnumVoiceDataBytes = 0;
  137. *ppvVoiceDataBuffer = NULL;
  138. return;
  139. }
  140. }
  141. void CEngineVoiceSteam::VoiceResetLocalData( int iController )
  142. {
  143. const int size = ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT;
  144. byte *pbVoiceData = m_pbVoiceData + iController * ARRAYSIZE( m_pbVoiceData ) / XUSER_MAX_COUNT;
  145. memset( pbVoiceData, 0, size );
  146. }
  147. void CEngineVoiceSteam::SetPlaybackPriority( XUID remoteTalker, int iController, int iAllowPlayback )
  148. {
  149. ;
  150. }
  151. void CEngineVoiceSteam::PlayIncomingVoiceData( XUID xuid, const byte *pbData, unsigned int dwDataSize, const bool *bAudiblePlayers /* = NULL */ )
  152. {
  153. for ( DWORD dwSlot = 0; dwSlot < XBX_GetNumGameUsers(); ++ dwSlot )
  154. {
  155. IPlayerLocal *pPlayer = g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetLocalPlayer( dwSlot );
  156. if ( pPlayer && pPlayer->GetXUID() == xuid )
  157. //Hack: Don't play stuff that comes from ourselves.
  158. return;
  159. }
  160. // Make sure voice playback is allowed for the specified user
  161. if ( !g_pMatchFramework->GetMatchSystem()->GetMatchVoice()->CanPlaybackTalker( xuid ) )
  162. return;
  163. // Uncompress the voice data
  164. char pbUncompressedVoice[ 11025 * 2 ];
  165. uint32 numUncompressedBytes;
  166. EVoiceResult res = Steam3Client().SteamUser()->DecompressVoice( const_cast< byte * >( pbData ), dwDataSize,
  167. pbUncompressedVoice, sizeof( pbUncompressedVoice ), &numUncompressedBytes, 0 );
  168. if ( res != k_EVoiceResultOK )
  169. return;
  170. // Voice channel index
  171. int idxVoiceChan = 0;
  172. int idxRemoteTalker = m_arrRemoteVoice.Find( xuid );
  173. if ( idxRemoteTalker != m_arrRemoteVoice.InvalidIndex() )
  174. idxVoiceChan = idxRemoteTalker;
  175. int nChannel = Voice_GetChannel( idxVoiceChan );
  176. if ( nChannel == VOICE_CHANNEL_ERROR )
  177. {
  178. // Create a channel in the voice engine and a channel in the sound engine for this guy.
  179. nChannel = Voice_AssignChannel( idxVoiceChan, false, 0.0f );
  180. }
  181. // Give the voice engine the data (it in turn gives it to the mixer for the sound engine).
  182. if ( nChannel != VOICE_CHANNEL_ERROR )
  183. {
  184. Voice_AddIncomingData( nChannel, pbUncompressedVoice, numUncompressedBytes, 0, false );
  185. }
  186. }
  187. void CEngineVoiceSteam::RemoveAllTalkers()
  188. {
  189. memset( m_bLocalVoice, 0, sizeof( m_bLocalVoice ) );
  190. m_arrRemoteVoice.RemoveAll();
  191. AudioInitializationUpdate();
  192. }
  193. void CEngineVoiceSteam::AudioInitializationUpdate()
  194. {
  195. bool bHasTalkers = ( m_arrRemoteVoice.Count() > 0 );
  196. for ( int k = 0; k < ARRAYSIZE( m_bLocalVoice ); ++ k )
  197. {
  198. if ( m_bLocalVoice[k] )
  199. {
  200. bHasTalkers = true;
  201. break;
  202. }
  203. }
  204. // Initialized already
  205. if ( bHasTalkers == m_bInitializedAudio )
  206. return;
  207. // Clear out voice buffers
  208. memset( m_pbVoiceData, 0, sizeof( m_pbVoiceData ) );
  209. // Init or deinit voice system
  210. if ( bHasTalkers )
  211. {
  212. Voice_ForceInit();
  213. }
  214. else
  215. {
  216. Voice_Deinit();
  217. }
  218. m_bInitializedAudio = bHasTalkers;
  219. }
  220. IEngineVoice *Audio_GetEngineVoiceSteam()
  221. {
  222. static CEngineVoiceSteam s_EngineVoiceSteam;
  223. return &s_EngineVoiceSteam;
  224. }
  225. #else
  226. IEngineVoice *Audio_GetEngineVoiceSteam()
  227. {
  228. return Audio_GetEngineVoiceStub();
  229. }
  230. #endif