Counter Strike : Global Offensive Source Code
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.

412 lines
14 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "OptionsSubAudio.h"
  7. #include "CvarSlider.h"
  8. #include "EngineInterface.h"
  9. #include "ModInfo.h"
  10. #include "vgui_controls/ComboBox.h"
  11. #include "vgui_controls/QueryBox.h"
  12. #include "tier1/KeyValues.h"
  13. #include "tier1/convar.h"
  14. #include "vgui/IInput.h"
  15. #ifndef NO_STEAM
  16. #include "steam/steam_api.h"
  17. #endif
  18. #include "tier1/strtools.h"
  19. #include "gameui_util.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. using namespace vgui;
  23. // This member is static so that the updated audio language can be referenced during shutdown
  24. char* COptionsSubAudio::m_pchUpdatedAudioLanguage = (char*)GetLanguageShortName( k_Lang_English );
  25. enum SoundQuality_e
  26. {
  27. SOUNDQUALITY_LOW,
  28. SOUNDQUALITY_MEDIUM,
  29. SOUNDQUALITY_HIGH,
  30. };
  31. //-----------------------------------------------------------------------------
  32. // Purpose: Constructor
  33. //-----------------------------------------------------------------------------
  34. COptionsSubAudio::COptionsSubAudio(vgui::Panel *parent) : PropertyPage(parent, NULL)
  35. {
  36. m_pSFXSlider = new CCvarSlider( this, "SFXSlider", "#GameUI_SoundEffectVolume", 0.0f, 1.0f, "volume" );
  37. m_pMusicSlider = new CCvarSlider( this, "MusicSlider", "#GameUI_MusicVolume", 0.0f, 1.0f, "Snd_MusicVolume" );
  38. m_pCloseCaptionCombo = new ComboBox( this, "CloseCaptionCheck", 6, false );
  39. m_pCloseCaptionCombo->AddItem( "#GameUI_NoClosedCaptions", NULL );
  40. m_pCloseCaptionCombo->AddItem( "#GameUI_SubtitlesAndSoundEffects", NULL );
  41. m_pCloseCaptionCombo->AddItem( "#GameUI_Subtitles", NULL );
  42. m_pSoundQualityCombo = new ComboBox( this, "SoundQuality", 6, false );
  43. m_pSoundQualityCombo->AddItem( "#GameUI_High", new KeyValues("SoundQuality", "quality", SOUNDQUALITY_HIGH) );
  44. m_pSoundQualityCombo->AddItem( "#GameUI_Medium", new KeyValues("SoundQuality", "quality", SOUNDQUALITY_MEDIUM) );
  45. m_pSoundQualityCombo->AddItem( "#GameUI_Low", new KeyValues("SoundQuality", "quality", SOUNDQUALITY_LOW) );
  46. m_pSpeakerSetupCombo = new ComboBox( this, "SpeakerSetup", 6, false );
  47. m_pSpeakerSetupCombo->AddItem( "#GameUI_Headphones", new KeyValues("SpeakerSetup", "speakers", 0) );
  48. m_pSpeakerSetupCombo->AddItem( "#GameUI_2Speakers", new KeyValues("SpeakerSetup", "speakers", 2) );
  49. m_pSpeakerSetupCombo->AddItem( "#GameUI_4Speakers", new KeyValues("SpeakerSetup", "speakers", 4) );
  50. m_pSpeakerSetupCombo->AddItem( "#GameUI_5Speakers", new KeyValues("SpeakerSetup", "speakers", 5) );
  51. m_pSpeakerSetupCombo->AddItem( "#GameUI_7Speakers", new KeyValues("SpeakerSetup", "speakers", 7) );
  52. m_pSpokenLanguageCombo = new ComboBox (this, "AudioSpokenLanguage", 6, false );
  53. LoadControlSettings("Resource\\OptionsSubAudio.res");
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Destructor
  57. //-----------------------------------------------------------------------------
  58. COptionsSubAudio::~COptionsSubAudio()
  59. {
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Purpose: Reloads data
  63. //-----------------------------------------------------------------------------
  64. void COptionsSubAudio::OnResetData()
  65. {
  66. m_bRequireRestart = false;
  67. m_pSFXSlider->Reset();
  68. m_pMusicSlider->Reset();
  69. // reset the combo boxes
  70. // close captions
  71. CGameUIConVarRef closecaption("closecaption");
  72. CGameUIConVarRef cc_subtitles("cc_subtitles");
  73. if (closecaption.GetBool())
  74. {
  75. if (cc_subtitles.GetBool())
  76. {
  77. m_pCloseCaptionCombo->ActivateItem(2);
  78. }
  79. else
  80. {
  81. m_pCloseCaptionCombo->ActivateItem(1);
  82. }
  83. }
  84. else
  85. {
  86. m_pCloseCaptionCombo->ActivateItem(0);
  87. }
  88. // speakers
  89. CGameUIConVarRef snd_surround_speakers("Snd_Surround_Speakers");
  90. int speakers = snd_surround_speakers.GetInt();
  91. {for (int itemID = 0; itemID < m_pSpeakerSetupCombo->GetItemCount(); itemID++)
  92. {
  93. KeyValues *kv = m_pSpeakerSetupCombo->GetItemUserData(itemID);
  94. if (kv && kv->GetInt("speakers") == speakers)
  95. {
  96. m_pSpeakerSetupCombo->ActivateItem(itemID);
  97. }
  98. }}
  99. // sound quality is made up from several cvars
  100. CGameUIConVarRef Snd_PitchQuality("Snd_PitchQuality");
  101. CGameUIConVarRef dsp_slow_cpu("dsp_slow_cpu");
  102. int quality = SOUNDQUALITY_LOW;
  103. if (dsp_slow_cpu.GetBool() == false)
  104. {
  105. quality = SOUNDQUALITY_MEDIUM;
  106. }
  107. if (Snd_PitchQuality.GetBool())
  108. {
  109. quality = SOUNDQUALITY_HIGH;
  110. }
  111. // find the item in the list and activate it
  112. {for (int itemID = 0; itemID < m_pSoundQualityCombo->GetItemCount(); itemID++)
  113. {
  114. KeyValues *kv = m_pSoundQualityCombo->GetItemUserData(itemID);
  115. if (kv && kv->GetInt("quality") == quality)
  116. {
  117. m_pSoundQualityCombo->ActivateItem(itemID);
  118. }
  119. }}
  120. //
  121. // Audio Languages
  122. //
  123. char szCurrentLanguage[50] = "";
  124. char szAvailableLanguages[512] = "";
  125. szAvailableLanguages[0] = NULL;
  126. // Fallback to current engine language
  127. engine->GetUILanguage( szCurrentLanguage, sizeof( szCurrentLanguage ));
  128. // In a Steam environment we get the current language
  129. #if !defined( NO_STEAM )
  130. // When Steam isn't running we can't get the language info...
  131. if ( steamapicontext->SteamApps() )
  132. {
  133. Q_strncpy( szCurrentLanguage, steamapicontext->SteamApps()->GetCurrentGameLanguage(), sizeof(szCurrentLanguage) );
  134. Q_strncpy( szAvailableLanguages, steamapicontext->SteamApps()->GetAvailableGameLanguages(), sizeof(szAvailableLanguages) );
  135. }
  136. #endif
  137. // Get the spoken language and store it for comparison purposes
  138. m_nCurrentAudioLanguage = PchLanguageToELanguage( szCurrentLanguage );
  139. // Check to see if we have a list of languages from Steam
  140. if ( V_strlen( szAvailableLanguages ) )
  141. {
  142. // Populate the combo box with each available language
  143. CSplitString languagesList( szAvailableLanguages, "," );
  144. for ( int i=0; i < languagesList.Count(); i++ )
  145. {
  146. const ELanguage languageCode = PchLanguageToELanguage( languagesList[i] );
  147. m_pSpokenLanguageCombo->AddItem( GetLanguageVGUILocalization( languageCode ), new KeyValues ("Audio Languages", "language", languageCode) );
  148. }
  149. }
  150. else
  151. {
  152. // Add the current language to the combo
  153. m_pSpokenLanguageCombo->AddItem( GetLanguageVGUILocalization( m_nCurrentAudioLanguage ), new KeyValues ("Audio Languages", "language", m_nCurrentAudioLanguage) );
  154. }
  155. // Activate the current language in the combo
  156. {for (int itemID = 0; itemID < m_pSpokenLanguageCombo->GetItemCount(); itemID++)
  157. {
  158. KeyValues *kv = m_pSpokenLanguageCombo->GetItemUserData( itemID );
  159. if ( kv && kv->GetInt( "language" ) == m_nCurrentAudioLanguage )
  160. {
  161. m_pSpokenLanguageCombo->ActivateItem( itemID );
  162. break;
  163. }
  164. }}
  165. }
  166. //-----------------------------------------------------------------------------
  167. // Purpose: Applies changes
  168. //-----------------------------------------------------------------------------
  169. void COptionsSubAudio::OnApplyChanges()
  170. {
  171. m_pSFXSlider->ApplyChanges();
  172. m_pMusicSlider->ApplyChanges();
  173. // set the cvars appropriately
  174. // Tracker 28933: Note we can't do this because closecaption is marked
  175. // FCVAR_USERINFO and it won't get sent to server is we direct set it, we
  176. // need to pass it along to the engine parser!!!
  177. // ConVar *closecaption = (ConVar *)cvar->FindVar("closecaption");
  178. int closecaption_value = 0;
  179. CGameUIConVarRef cc_subtitles( "cc_subtitles" );
  180. switch (m_pCloseCaptionCombo->GetActiveItem())
  181. {
  182. default:
  183. case 0:
  184. closecaption_value = 0;
  185. cc_subtitles.SetValue( 0 );
  186. break;
  187. case 1:
  188. closecaption_value = 1;
  189. cc_subtitles.SetValue( 0 );
  190. break;
  191. case 2:
  192. closecaption_value = 1;
  193. cc_subtitles.SetValue( 1 );
  194. break;
  195. }
  196. // Stuff the close caption change to the console so that it can be
  197. // sent to the server (FCVAR_USERINFO) so that you don't have to restart
  198. // the level for the change to take effect.
  199. char cmd[ 64 ];
  200. Q_snprintf( cmd, sizeof( cmd ), "closecaption %i\n", closecaption_value );
  201. engine->ClientCmd_Unrestricted( cmd );
  202. CGameUIConVarRef snd_surround_speakers( "Snd_Surround_Speakers" );
  203. int speakers = m_pSpeakerSetupCombo->GetActiveItemUserData()->GetInt( "speakers" );
  204. snd_surround_speakers.SetValue( speakers );
  205. // quality
  206. CGameUIConVarRef Snd_PitchQuality( "Snd_PitchQuality" );
  207. CGameUIConVarRef dsp_slow_cpu( "dsp_slow_cpu" );
  208. int quality = m_pSoundQualityCombo->GetActiveItemUserData()->GetInt( "quality" );
  209. switch ( quality )
  210. {
  211. case SOUNDQUALITY_LOW:
  212. dsp_slow_cpu.SetValue(true);
  213. Snd_PitchQuality.SetValue(false);
  214. break;
  215. case SOUNDQUALITY_MEDIUM:
  216. dsp_slow_cpu.SetValue(false);
  217. Snd_PitchQuality.SetValue(false);
  218. break;
  219. default:
  220. Assert("Undefined sound quality setting.");
  221. case SOUNDQUALITY_HIGH:
  222. dsp_slow_cpu.SetValue(false);
  223. Snd_PitchQuality.SetValue(true);
  224. break;
  225. };
  226. // headphones at high quality get enhanced stereo turned on
  227. CGameUIConVarRef dsp_enhance_stereo( "dsp_enhance_stereo" );
  228. if (speakers == 0 && quality == SOUNDQUALITY_HIGH)
  229. {
  230. dsp_enhance_stereo.SetValue( 1 );
  231. }
  232. else
  233. {
  234. dsp_enhance_stereo.SetValue( 0 );
  235. }
  236. // Audio spoken language
  237. KeyValues *kv = m_pSpokenLanguageCombo->GetItemUserData( m_pSpokenLanguageCombo->GetActiveItem() );
  238. const ELanguage nUpdatedAudioLanguage = (ELanguage)( kv ? kv->GetInt( "language" ) : k_Lang_English );
  239. if ( nUpdatedAudioLanguage != m_nCurrentAudioLanguage )
  240. {
  241. // Store new language in static member so that it can be accessed during shutdown when this instance is gone
  242. m_pchUpdatedAudioLanguage = (char *) GetLanguageShortName( nUpdatedAudioLanguage );
  243. // Inform user that they need to restart in order change language at this time
  244. QueryBox *qb = new QueryBox( "#GameUI_ChangeLanguageRestart_Title", "#GameUI_ChangeLanguageRestart_Info", GetParent()->GetParent()->GetParent() );
  245. if (qb != NULL)
  246. {
  247. qb->SetOKCommand( new KeyValues( "Command", "command", "RestartWithNewLanguage" ) );
  248. qb->SetOKButtonText( "#GameUI_ChangeLanguageRestart_OkButton" );
  249. qb->SetCancelButtonText( "#GameUI_ChangeLanguageRestart_CancelButton" );
  250. qb->AddActionSignalTarget( GetParent()->GetParent()->GetParent() );
  251. qb->DoModal();
  252. }
  253. }
  254. }
  255. //-----------------------------------------------------------------------------
  256. // Purpose: Called on controls changing, enables the Apply button
  257. //-----------------------------------------------------------------------------
  258. void COptionsSubAudio::OnControlModified()
  259. {
  260. PostActionSignal(new KeyValues("ApplyButtonEnable"));
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose: returns true if the engine needs to be restarted
  264. //-----------------------------------------------------------------------------
  265. bool COptionsSubAudio::RequiresRestart()
  266. {
  267. // nothing in audio requires a restart like now
  268. return false;
  269. }
  270. //-----------------------------------------------------------------------------
  271. // Purpose:
  272. //-----------------------------------------------------------------------------
  273. void COptionsSubAudio::OnCommand( const char *command )
  274. {
  275. if ( !stricmp( command, "TestSpeakers" ) )
  276. {
  277. // ask them if they REALLY want to test the speakers if they're in a game already.
  278. if (engine->IsConnected())
  279. {
  280. QueryBox *qb = new QueryBox("#GameUI_TestSpeakersWarning_Title", "#GameUI_TestSpeakersWarning_Info" );
  281. if (qb != NULL)
  282. {
  283. qb->SetOKCommand(new KeyValues("RunTestSpeakers"));
  284. qb->SetOKButtonText("#GameUI_TestSpeakersWarning_OkButton");
  285. qb->SetCancelButtonText("#GameUI_TestSpeakersWarning_CancelButton");
  286. qb->AddActionSignalTarget( this );
  287. qb->DoModal();
  288. }
  289. else
  290. {
  291. // couldn't create the warning dialog for some reason, so just test the speakers.
  292. RunTestSpeakers();
  293. }
  294. }
  295. else
  296. {
  297. // player isn't connected to a game so there's no reason to warn them about being disconnected.
  298. // create the command to execute
  299. RunTestSpeakers();
  300. }
  301. }
  302. else if ( !stricmp( command, "ShowThirdPartyAudioCredits" ) )
  303. {
  304. OpenThirdPartySoundCreditsDialog();
  305. }
  306. BaseClass::OnCommand( command );
  307. }
  308. //-----------------------------------------------------------------------------
  309. // Purpose: Run the test speakers map.
  310. //-----------------------------------------------------------------------------
  311. void COptionsSubAudio::RunTestSpeakers()
  312. {
  313. engine->ClientCmd_Unrestricted( "disconnect\nwait\nwait\nsv_lan 1\nsetmaster enable\nmaxplayers 1\n\nhostname \"Speaker Test\"\nprogress_enable\nmap test_speakers\n" );
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Purpose: Open third party audio credits dialog
  317. //-----------------------------------------------------------------------------
  318. void COptionsSubAudio::OpenThirdPartySoundCreditsDialog()
  319. {
  320. if (!m_OptionsSubAudioThirdPartyCreditsDlg.Get())
  321. {
  322. m_OptionsSubAudioThirdPartyCreditsDlg = new COptionsSubAudioThirdPartyCreditsDlg(GetVParent());
  323. }
  324. m_OptionsSubAudioThirdPartyCreditsDlg->Activate();
  325. }
  326. COptionsSubAudioThirdPartyCreditsDlg::COptionsSubAudioThirdPartyCreditsDlg( vgui::VPANEL hParent ) : BaseClass( NULL, NULL )
  327. {
  328. SetProportional( true );
  329. #ifdef GAMEUI_BASEMODPANEL_VGUI
  330. // parent is ignored, since we want look like we're steal focus from the parent (we'll become modal below)
  331. SetScheme( GAMEUI_BASEMODPANEL_SCHEME );
  332. #endif
  333. SetTitle( "#GameUI_ThirdPartyAudio_Title", true );
  334. SetSize(
  335. vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), 500 ),
  336. vgui::scheme()->GetProportionalScaledValueEx( GetScheme(), 200 ) );
  337. MoveToCenterOfScreen();
  338. SetSizeable( false );
  339. SetDeleteSelfOnClose( true );
  340. }
  341. void COptionsSubAudioThirdPartyCreditsDlg::ApplySchemeSettings( IScheme *pScheme )
  342. {
  343. BaseClass::ApplySchemeSettings( pScheme );
  344. LoadControlSettings( "resource/OptionsSubAudioThirdPartyDlg.res" );
  345. }
  346. void COptionsSubAudioThirdPartyCreditsDlg::Activate()
  347. {
  348. BaseClass::Activate();
  349. input()->SetAppModalSurface(GetVPanel());
  350. }
  351. void COptionsSubAudioThirdPartyCreditsDlg::OnKeyCodeTyped(vgui::KeyCode code)
  352. {
  353. // force ourselves to be closed if the escape key it pressed
  354. if (code == KEY_ESCAPE)
  355. {
  356. Close();
  357. }
  358. else
  359. {
  360. BaseClass::OnKeyCodeTyped(code);
  361. }
  362. }