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.

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