llfloatervoicedevicesettings.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /**
  2. * @file llfloatervoicedevicesettings.cpp
  3. * @author Richard Nelson
  4. * @brief Voice communication set-up
  5. *
  6. * $LicenseInfo:firstyear=2007&license=viewergpl$
  7. *
  8. * Copyright (c) 2007-2009, Linden Research, Inc.
  9. * Copyright (c) 2024 Henri Beauchamp (largely rewritten).
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #include "llviewerprecompiledheaders.h"
  35. #include "llfloatervoicedevicesettings.h"
  36. #include "llbutton.h"
  37. #include "llcombobox.h"
  38. #include "llsliderctrl.h"
  39. #include "lltextbox.h"
  40. #include "lluictrlfactory.h"
  41. #include "llagent.h"
  42. #include "llprefsvoice.h"
  43. #include "llviewercontrol.h"
  44. #include "llvoicechannel.h"
  45. #include "llvoiceclient.h"
  46. LLFloaterVoiceDeviceSettings::LLFloaterVoiceDeviceSettings(const LLSD&)
  47. : LLFloater("voice settings"),
  48. mSpeakingColor(gSavedSettings.getColor4("SpeakingColor")),
  49. mOverdrivenColor(gSavedSettings.getColor4("OverdrivenColor")),
  50. mMicVolume(gSavedSettings.getF32("AudioLevelMic")),
  51. mLastMicTune(-1.f),
  52. mDevicesUpdated(false)
  53. {
  54. // Note: "VoiceServerType" is kept in sync with the current voice server
  55. // type; should it change while this floater is open (user changing sim
  56. // with floater still open and arrival sim using a different voice server
  57. // type), the settings observer in llviewercontrol.cpp would trigger a
  58. // cancel(), which would also close this floater. HB
  59. mUseWebRTC = gSavedSettings.getString("VoiceServerType") == "webrtc";
  60. if (mUseWebRTC)
  61. {
  62. mInputDevice = gSavedSettings.getString("VoiceWebRTCInputAudioDevice");
  63. mOutputDevice =
  64. gSavedSettings.getString("VoiceWebRTCOutputAudioDevice");
  65. }
  66. else
  67. {
  68. mInputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
  69. mOutputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
  70. }
  71. LLUICtrlFactory::getInstance()->buildFloater(this,
  72. "floater_device_settings.xml");
  73. center();
  74. // Ask for new enumeration of audio devices
  75. gVoiceClient.refreshDeviceLists(true, mUseWebRTC);
  76. // Put voice client in "tuning" mode
  77. gVoiceClient.tuningStart(mUseWebRTC);
  78. LLVoiceChannel::suspend();
  79. }
  80. //virtual
  81. LLFloaterVoiceDeviceSettings::~LLFloaterVoiceDeviceSettings()
  82. {
  83. gVoiceClient.tuningStop(mUseWebRTC);
  84. LLVoiceChannel::resume();
  85. }
  86. //virtual
  87. bool LLFloaterVoiceDeviceSettings::postBuild()
  88. {
  89. LLTextBox* textp = getChild<LLTextBox>("audio_devices");
  90. if (mUseWebRTC)
  91. {
  92. textp->setText(getString("devices_webrtc"));
  93. }
  94. else
  95. {
  96. textp->setText(getString("devices_vivox"));
  97. }
  98. mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
  99. mCtrlInputDevices->setCommitCallback(onCommitInputDevice);
  100. mCtrlInputDevices->setCallbackUserData(this);
  101. mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device");
  102. mCtrlOutputDevices->setCommitCallback(onCommitOutputDevice);
  103. mCtrlOutputDevices->setCallbackUserData(this);
  104. mCtrlMicVolume = getChild<LLSliderCtrl>("mic_volume_slider");
  105. mCtrlMicVolume->setValue(mMicVolume);
  106. mCtrlInputLoadingText = getChild<LLTextBox>("input_device_loading");
  107. mCtrlOutputLoadingText = getChild<LLTextBox>("output_device_loading");
  108. mCtrlWaitText = getChild<LLTextBox>("wait_text");
  109. childSetAction("cancel_btn", onCancel, this);
  110. childSetAction("apply_btn", onApply, this);
  111. mDefaultDeviceName = getString("default_text");
  112. return true;
  113. }
  114. //virtual
  115. void LLFloaterVoiceDeviceSettings::draw()
  116. {
  117. refresh();
  118. // Let the user know that volume indicator is not yet available
  119. bool is_in_tuning_mode = gVoiceClient.inTuningMode(mUseWebRTC);
  120. mCtrlWaitText->setVisible(!is_in_tuning_mode);
  121. LLFloater::draw();
  122. F32 voice_power = gVoiceClient.tuningGetEnergy(mUseWebRTC);
  123. S32 discrete_power = 0;
  124. if (!is_in_tuning_mode)
  125. {
  126. discrete_power = 0;
  127. }
  128. else
  129. {
  130. discrete_power =
  131. llmin(4, S32(voice_power * 4.f / OVERDRIVEN_POWER_LEVEL));
  132. }
  133. if (is_in_tuning_mode)
  134. {
  135. for (S32 power_bar_idx = 0; power_bar_idx < 5; power_bar_idx++)
  136. {
  137. std::string view_name = llformat("%s%d", "bar", power_bar_idx);
  138. LLView* bar_view = getChild<LLView>(view_name.c_str());
  139. if (bar_view)
  140. {
  141. if (power_bar_idx < discrete_power)
  142. {
  143. LLColor4 color = power_bar_idx >= 3 ? mOverdrivenColor
  144. : mSpeakingColor;
  145. gl_rect_2d(bar_view->getRect(), color, true);
  146. }
  147. gl_rect_2d(bar_view->getRect(), LLColor4::grey, false);
  148. }
  149. }
  150. }
  151. }
  152. //virtual
  153. void LLFloaterVoiceDeviceSettings::refresh()
  154. {
  155. bool has_device_list = gVoiceClient.deviceSettingsAvailable(mUseWebRTC);
  156. mCtrlInputDevices->setEnabled(has_device_list);
  157. mCtrlOutputDevices->setEnabled(has_device_list);
  158. mCtrlInputLoadingText->setVisible(!has_device_list);
  159. mCtrlOutputLoadingText->setVisible(!has_device_list);
  160. if (!has_device_list)
  161. {
  162. // The combo boxes are disabled, since we cannot get the device
  163. // settings from the voice server just now. Put the currently set
  164. // default (ONLY) in the box, and select it.
  165. mCtrlInputDevices->removeall();
  166. mCtrlInputDevices->add(mInputDevice, "Default", ADD_BOTTOM);
  167. mCtrlInputDevices->setSimple(mInputDevice);
  168. mCtrlOutputDevices->removeall();
  169. mCtrlOutputDevices->add(mOutputDevice, "Default", ADD_BOTTOM);
  170. mCtrlOutputDevices->setSimple(mOutputDevice);
  171. mDevicesUpdated = false;
  172. return;
  173. }
  174. F32 tuned_vol = mCtrlMicVolume->getValue().asReal();
  175. if (mLastMicTune != tuned_vol)
  176. {
  177. // Set mic volume tuning slider based on last mic volume setting
  178. gVoiceClient.tuningSetMicVolume(tuned_vol, mUseWebRTC);
  179. mLastMicTune = tuned_vol;
  180. }
  181. if (mDevicesUpdated)
  182. {
  183. return; // No lists refresh needed
  184. }
  185. mDevicesUpdated = true;
  186. typedef LLVoiceClient::device_map_t::const_iterator dev_iterator;
  187. const LLVoiceClient::device_map_t& input_devices =
  188. gVoiceClient.getCaptureDevices(mUseWebRTC);
  189. mCtrlInputDevices->removeall();
  190. mCtrlInputDevices->add(mDefaultDeviceName, "Default", ADD_BOTTOM);
  191. for (dev_iterator it = input_devices.begin(), end = input_devices.end();
  192. it != end; ++it)
  193. {
  194. mCtrlInputDevices->add(it->first, it->second, ADD_BOTTOM);
  195. }
  196. if (!mCtrlInputDevices->setSelectedByValue(mInputDevice, true))
  197. {
  198. mCtrlInputDevices->setSimple(mDefaultDeviceName);
  199. }
  200. const LLVoiceClient::device_map_t& output_devices =
  201. gVoiceClient.getRenderDevices(mUseWebRTC);
  202. mCtrlOutputDevices->removeall();
  203. mCtrlOutputDevices->add(mDefaultDeviceName, "Default", ADD_BOTTOM);
  204. for (dev_iterator it = output_devices.begin(), end = output_devices.end();
  205. it != end; ++it)
  206. {
  207. mCtrlOutputDevices->add(it->first, it->second, ADD_BOTTOM);
  208. }
  209. if (!mCtrlOutputDevices->setSelectedByValue(mOutputDevice, true))
  210. {
  211. mCtrlOutputDevices->setSimple(mDefaultDeviceName);
  212. }
  213. }
  214. void LLFloaterVoiceDeviceSettings::apply()
  215. {
  216. std::string device_id = mCtrlInputDevices->getValue().asString();
  217. if (mUseWebRTC)
  218. {
  219. gSavedSettings.setString("VoiceWebRTCInputAudioDevice", device_id);
  220. }
  221. else
  222. {
  223. gSavedSettings.setString("VoiceInputAudioDevice", device_id);
  224. }
  225. mInputDevice = device_id;
  226. device_id = mCtrlOutputDevices->getValue().asString();
  227. if (mUseWebRTC)
  228. {
  229. gSavedSettings.setString("VoiceWebRTCOutputAudioDevice", device_id);
  230. }
  231. else
  232. {
  233. gSavedSettings.setString("VoiceOutputAudioDevice", device_id);
  234. }
  235. mOutputDevice = device_id;
  236. mMicVolume = mCtrlMicVolume->getValue().asReal();
  237. gSavedSettings.setF32("AudioLevelMic", mMicVolume);
  238. }
  239. //static
  240. void LLFloaterVoiceDeviceSettings::onApply(void* datap)
  241. {
  242. LLFloaterVoiceDeviceSettings* self = (LLFloaterVoiceDeviceSettings*)datap;
  243. if (self)
  244. {
  245. self->apply();
  246. self->close();
  247. }
  248. }
  249. void LLFloaterVoiceDeviceSettings::cancel()
  250. {
  251. // Note: these setting variables are observed in llviewercontrol.cpp and
  252. // their changes are automatically get propagated to the voice client.
  253. if (mUseWebRTC)
  254. {
  255. gSavedSettings.setString("VoiceWebRTCInputAudioDevice", mInputDevice);
  256. gSavedSettings.setString("VoiceWebRTCOutputAudioDevice",
  257. mOutputDevice);
  258. }
  259. else
  260. {
  261. gSavedSettings.setString("VoiceInputAudioDevice", mInputDevice);
  262. gSavedSettings.setString("VoiceOutputAudioDevice", mOutputDevice);
  263. }
  264. gSavedSettings.setF32("AudioLevelMic", mMicVolume);
  265. // Any cancel event on this floater implicitely closes it as well. HB
  266. close();
  267. }
  268. //static
  269. void LLFloaterVoiceDeviceSettings::onCancel(void* datap)
  270. {
  271. LLFloaterVoiceDeviceSettings* self = (LLFloaterVoiceDeviceSettings*)datap;
  272. if (self)
  273. {
  274. self->cancel(); // Also calls close()
  275. }
  276. }
  277. //static
  278. void LLFloaterVoiceDeviceSettings::onCommitInputDevice(LLUICtrl* ctrlp,
  279. void* datap)
  280. {
  281. LLFloaterVoiceDeviceSettings* self = (LLFloaterVoiceDeviceSettings*)datap;
  282. if (self && ctrlp)
  283. {
  284. gVoiceClient.setCaptureDevice(ctrlp->getValue().asString(),
  285. self->mUseWebRTC);
  286. }
  287. }
  288. //static
  289. void LLFloaterVoiceDeviceSettings::onCommitOutputDevice(LLUICtrl* ctrlp,
  290. void* datap)
  291. {
  292. LLFloaterVoiceDeviceSettings* self = (LLFloaterVoiceDeviceSettings*)datap;
  293. if (self && ctrlp)
  294. {
  295. gVoiceClient.setRenderDevice(ctrlp->getValue().asString(),
  296. self->mUseWebRTC);
  297. }
  298. }