llfloatermediasettings.cpp 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. /**
  2. * @file llfloatermediasettings.cpp
  3. * @brief Media settings floater - class implementation
  4. *
  5. * $LicenseInfo:firstyear=2010&license=viewergpl$
  6. *
  7. * Copyright (c) 2010, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llfloatermediasettings.h"
  34. #include "llbutton.h"
  35. #include "llcheckboxctrl.h"
  36. #include "llcombobox.h"
  37. #include "lllineeditor.h"
  38. #include "llmediaentry.h"
  39. #include "llnameeditor.h"
  40. #include "llscrolllistctrl.h"
  41. #include "llsdserialize.h"
  42. #include "llsdutil.h"
  43. #include "llspinctrl.h"
  44. #include "lltabcontainer.h"
  45. #include "lltextbox.h"
  46. #include "lltextureentry.h"
  47. #include "lluictrl.h"
  48. #include "lluictrlfactory.h"
  49. #include "llappviewer.h" // For gFrameTimeSeconds
  50. #include "llfloatertools.h"
  51. #include "llmediactrl.h"
  52. #include "llselectmgr.h"
  53. #include "llviewercontrol.h"
  54. #include "llviewermedia.h"
  55. #include "llvovolume.h"
  56. bool LLFloaterMediaSettings::sIdenticalHasMediaInfo = true;
  57. bool LLFloaterMediaSettings::sMultipleMedia = false;
  58. bool LLFloaterMediaSettings::sMultipleValidMedia = false;
  59. const char* CHECKERBOARD_DATA_URL =
  60. "data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%%22 height=%22100%%22 %3E%3Cdefs%3E%3Cpattern id=%22checker%22 patternUnits=%22userSpaceOnUse%22 x=%220%22 y=%220%22 width=%22128%22 height=%22128%22 viewBox=%220 0 128 128%22 %3E%3Crect x=%220%22 y=%220%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3Crect x=%2264%22 y=%2264%22 width=%2264%22 height=%2264%22 fill=%22#ddddff%22 /%3E%3C/pattern%3E%3C/defs%3E%3Crect x=%220%22 y=%220%22 width=%22100%%22 height=%22100%%22 fill=%22url(#checker)%22 /%3E%3C/svg%3E";
  61. LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD&)
  62. : mFirstRun(true),
  63. mGroupId(LLUUID::null),
  64. mMediaEditable(false),
  65. mHomeUrlCommitted(false),
  66. mTabContainer(NULL),
  67. mOKBtn(NULL),
  68. mCancelBtn(NULL),
  69. mApplyBtn(NULL),
  70. mResetCurrentUrlBtn(NULL),
  71. mAutoLoop(NULL),
  72. mFirstClick(NULL),
  73. mAutoZoom(NULL),
  74. mAutoPlay(NULL),
  75. mAutoScale(NULL),
  76. mWidthPixels(NULL),
  77. mHeightPixels(NULL),
  78. mHomeURL(NULL),
  79. mControls(NULL),
  80. mPermsOwnerInteract(NULL),
  81. mPermsOwnerControl(NULL),
  82. mPermsGroupName(NULL),
  83. mPermsGroupInteract(NULL),
  84. mPermsGroupControl(NULL),
  85. mPermsWorldInteract(NULL),
  86. mPermsWorldControl(NULL),
  87. mCurrentUrlLabel(NULL),
  88. mCurrentURL(NULL),
  89. mEnableWhiteList(NULL),
  90. mNewWhiteListPattern(NULL),
  91. mWhiteListList(NULL),
  92. mHomeUrlFailsWhiteListText(NULL),
  93. mDeleteBtn(NULL)
  94. {
  95. sIdenticalHasMediaInfo = true;
  96. sMultipleMedia = false;
  97. sMultipleValidMedia = false;
  98. LLUICtrlFactory::getInstance()->buildFloater(this,
  99. "floater_media_settings.xml",
  100. NULL, false); // do not open
  101. }
  102. //virtual
  103. bool LLFloaterMediaSettings::postBuild()
  104. {
  105. mTabContainer = getChild<LLTabContainer>("tabs");
  106. LLPanel* tab = mTabContainer->getChild<LLPanel>("media_settings_general");
  107. mTabContainer->setTabChangeCallback(tab, onTabChanged);
  108. mTabContainer->setTabUserData(tab, this);
  109. tab = mTabContainer->getChild<LLPanel>("media_settings_permissions");
  110. mTabContainer->setTabChangeCallback(tab, onTabChanged);
  111. mTabContainer->setTabUserData(tab, this);
  112. tab = mTabContainer->getChild<LLPanel>("media_settings_security");
  113. mTabContainer->setTabChangeCallback(tab, onTabChanged);
  114. mTabContainer->setTabUserData(tab, this);
  115. mApplyBtn = getChild<LLButton>("Apply");
  116. mApplyBtn->setClickedCallback(onBtnApply, this);
  117. mCancelBtn = getChild<LLButton>("Cancel");
  118. mCancelBtn->setClickedCallback(onBtnCancel, this);
  119. mOKBtn = getChild<LLButton>("OK");
  120. mOKBtn->setClickedCallback(onBtnOK, this);
  121. // General panel UI elements:
  122. mCurrentUrlLabel = getChild<LLTextBox>("current_url_label");
  123. mCurrentURL = getChild<LLTextBox>(LLMediaEntry::CURRENT_URL_KEY);
  124. mAutoLoop = getChild<LLCheckBoxCtrl>(LLMediaEntry::AUTO_LOOP_KEY);
  125. mAutoPlay = getChild<LLCheckBoxCtrl>(LLMediaEntry::AUTO_PLAY_KEY);
  126. mAutoScale = getChild<LLCheckBoxCtrl>(LLMediaEntry::AUTO_SCALE_KEY);
  127. mAutoZoom = getChild<LLCheckBoxCtrl>(LLMediaEntry::AUTO_ZOOM_KEY);
  128. mFirstClick =
  129. getChild<LLCheckBoxCtrl>(LLMediaEntry::FIRST_CLICK_INTERACT_KEY);
  130. mHeightPixels = getChild<LLSpinCtrl>(LLMediaEntry::HEIGHT_PIXELS_KEY);
  131. mHomeURL = getChild<LLLineEditor>(LLMediaEntry::HOME_URL_KEY);
  132. mHomeURL->setCommitCallback(onCommitHomeURL);
  133. mHomeURL->setCallbackUserData(this);
  134. mWidthPixels = getChild<LLSpinCtrl>(LLMediaEntry::WIDTH_PIXELS_KEY);
  135. mPreviewMedia = getChild<LLMediaCtrl>("preview_media");
  136. mFailWhiteListText = getChild<LLTextBox>("home_fails_whitelist_label");
  137. mResetCurrentUrlBtn = getChild<LLButton>("current_url_reset_btn");
  138. mResetCurrentUrlBtn->setClickedCallback(onBtnResetCurrentUrl, this);
  139. // interrogates controls and updates widgets as required
  140. updateMediaPreview();
  141. // Permissions tab UI elements:
  142. mControls = getChild<LLComboBox>(LLMediaEntry::CONTROLS_KEY);
  143. mPermsOwnerInteract =
  144. getChild<LLCheckBoxCtrl>(LLMediaEntry::PERMS_OWNER_INTERACT_KEY);
  145. mPermsOwnerControl =
  146. getChild<LLCheckBoxCtrl>(LLMediaEntry::PERMS_OWNER_CONTROL_KEY);
  147. mPermsGroupInteract =
  148. getChild<LLCheckBoxCtrl>(LLMediaEntry::PERMS_GROUP_INTERACT_KEY);
  149. mPermsGroupControl =
  150. getChild<LLCheckBoxCtrl>(LLMediaEntry::PERMS_GROUP_CONTROL_KEY);
  151. mPermsWorldInteract =
  152. getChild<LLCheckBoxCtrl>(LLMediaEntry::PERMS_ANYONE_INTERACT_KEY);
  153. mPermsWorldControl =
  154. getChild<LLCheckBoxCtrl>(LLMediaEntry::PERMS_ANYONE_CONTROL_KEY);
  155. mPermsGroupName = getChild<LLNameEditor>("perms_group_name");
  156. // Security tab UI elements:
  157. mEnableWhiteList =
  158. getChild<LLCheckBoxCtrl>(LLMediaEntry::WHITELIST_ENABLE_KEY);
  159. mNewWhiteListPattern = getChild<LLLineEditor>("new_pattern");
  160. mNewWhiteListPattern->setCommitCallback(onCommitNewPattern);
  161. mNewWhiteListPattern->setCallbackUserData(this);
  162. mWhiteListList = getChild<LLScrollListCtrl>(LLMediaEntry::WHITELIST_KEY);
  163. mHomeUrlFailsWhiteListText =
  164. getChild<LLTextBox>("home_url_fails_whitelist");
  165. mDeleteBtn = getChild<LLButton>("whitelist_del");
  166. mDeleteBtn->setClickedCallback(onBtnDel, this);
  167. return true;
  168. }
  169. //virtual
  170. void LLFloaterMediaSettings::close(bool app_quitting)
  171. {
  172. if (app_quitting || !LLFloaterTools::isVisible())
  173. {
  174. LLFloater::close(app_quitting);
  175. }
  176. else
  177. {
  178. setVisible(false);
  179. }
  180. }
  181. //virtual
  182. void LLFloaterMediaSettings::draw()
  183. {
  184. // Tab selection is delayed here because it would not work in postBuild()
  185. if (mFirstRun)
  186. {
  187. mFirstRun = false;
  188. mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab"));
  189. }
  190. // Do not perform the following operations every frame because they are
  191. // time consuming and do not change often.
  192. static F32 last_update = 0.f;
  193. if (gFrameTimeSeconds - last_update >= 0.25f)
  194. {
  195. // Floater:
  196. mApplyBtn->setEnabled(mMediaEditable && haveValuesChanged());
  197. // General tab:
  198. checkHomeUrlPassesWhitelist();
  199. updateCurrentUrl();
  200. // Enable/disable pixel values image entry based on auto scale checkbox
  201. bool custom_scale = !mAutoScale->getValue().asBoolean();
  202. mWidthPixels->setEnabled(custom_scale);
  203. mHeightPixels->setEnabled(custom_scale);
  204. // Enable/disable UI based on type of media
  205. bool reset_button_is_active = true;
  206. LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin();
  207. if (media_plugin)
  208. {
  209. // Turn off volume (if we can) for preview.
  210. media_plugin->setVolume(0.f);
  211. // Some controls are only appropriate for time or browser type
  212. // plugins so we selectively enable/disable them; we need to do it
  213. // in draw because the information from plugins arrives
  214. // assynchronously
  215. if (media_plugin->pluginSupportsMediaTime())
  216. {
  217. reset_button_is_active = false;
  218. mCurrentURL->setEnabled(false);
  219. mCurrentUrlLabel->setEnabled(false);
  220. mAutoLoop->setEnabled(true);
  221. }
  222. else
  223. {
  224. reset_button_is_active = true;
  225. mCurrentURL->setEnabled(true);
  226. mCurrentUrlLabel->setEnabled(true);
  227. mAutoLoop->setEnabled(false);
  228. }
  229. }
  230. // Several places modify this widget so we must collect states in one
  231. // place
  232. if (reset_button_is_active)
  233. {
  234. // User has perms to press reset button and it is active
  235. mResetCurrentUrlBtn->setEnabled(mMediaEditable);
  236. }
  237. else
  238. {
  239. // Reset button is inactive so we just slam it to off
  240. mResetCurrentUrlBtn->setEnabled(false);
  241. }
  242. // Permissions tab:
  243. LLUUID group_id;
  244. bool groups_identical = gSelectMgr.selectGetGroup(group_id);
  245. if (group_id != mGroupId)
  246. {
  247. if (groups_identical)
  248. {
  249. mPermsGroupName->setNameID(group_id, true);
  250. }
  251. else
  252. {
  253. mPermsGroupName->setNameID(LLUUID::null, true);
  254. mPermsGroupName->refresh(LLUUID::null, "", true);
  255. }
  256. mGroupId = group_id;
  257. }
  258. last_update = gFrameTimeSeconds;
  259. }
  260. LLFloater::draw();
  261. }
  262. void LLFloaterMediaSettings::getValues(LLSD& fill_me_in,
  263. bool include_tentative)
  264. {
  265. // General tab settings:
  266. if (include_tentative || !mAutoLoop->getTentative())
  267. {
  268. fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] =
  269. (LLSD::Boolean)mAutoLoop->getValue();
  270. }
  271. if (include_tentative || !mAutoPlay->getTentative())
  272. {
  273. fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] =
  274. (LLSD::Boolean)mAutoPlay->getValue();
  275. }
  276. if (include_tentative || !mAutoScale->getTentative())
  277. {
  278. fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] =
  279. (LLSD::Boolean)mAutoScale->getValue();
  280. }
  281. if (include_tentative || !mAutoZoom->getTentative())
  282. {
  283. fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] =
  284. (LLSD::Boolean)mAutoZoom->getValue();
  285. }
  286. #if 0 // Do not fill in current URL: this is only supposed to get changed via
  287. // navigate
  288. if (include_tentative || !mCurrentURL->getTentative())
  289. {
  290. fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
  291. }
  292. #endif
  293. if (include_tentative || !mHeightPixels->getTentative())
  294. {
  295. fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] =
  296. (LLSD::Integer)mHeightPixels->getValue();
  297. }
  298. // Do not fill in the home URL if it is the special "Multiple Media" string
  299. if ((include_tentative || mHomeUrlCommitted) &&
  300. mHomeURL->getValue().asString() != "Multiple Media")
  301. {
  302. fill_me_in[LLMediaEntry::HOME_URL_KEY] =
  303. (LLSD::String)mHomeURL->getValue();
  304. }
  305. if (include_tentative || !mFirstClick->getTentative())
  306. {
  307. fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] =
  308. (LLSD::Boolean)mFirstClick->getValue();
  309. }
  310. if (include_tentative || !mWidthPixels->getTentative())
  311. {
  312. fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] =
  313. (LLSD::Integer)mWidthPixels->getValue();
  314. }
  315. // Permissions tab settings:
  316. if (include_tentative || !mControls->getTentative())
  317. {
  318. fill_me_in[LLMediaEntry::CONTROLS_KEY] =
  319. (LLSD::Integer)mControls->getCurrentIndex();
  320. }
  321. // *NOTE: For some reason, gcc does not like these symbol references in the
  322. // expressions below (inside the static_casts). I have NO idea why :(.
  323. // For some reason, assigning them to const temp vars here fixes the link
  324. // error. Bizarre.
  325. constexpr U8 none = LLMediaEntry::PERM_NONE;
  326. constexpr U8 owner = LLMediaEntry::PERM_OWNER;
  327. constexpr U8 group = LLMediaEntry::PERM_GROUP;
  328. constexpr U8 anyone = LLMediaEntry::PERM_ANYONE;
  329. const LLSD::Integer control = static_cast<LLSD::Integer>(
  330. (mPermsOwnerControl->getValue() ? owner : none) |
  331. (mPermsGroupControl->getValue() ? group: none) |
  332. (mPermsWorldControl->getValue() ? anyone : none ));
  333. const LLSD::Integer interact = static_cast<LLSD::Integer>(
  334. (mPermsOwnerInteract->getValue() ? owner: none) |
  335. (mPermsGroupInteract->getValue() ? group : none) |
  336. (mPermsWorldInteract->getValue() ? anyone : none));
  337. // *TODO: This will fill in the values of all permissions values, even if
  338. // one or more is tentative. This is not quite the user expectation... What
  339. // it should do is only change the bit that was made "untentative", but in
  340. // a multiple-selection situation, this isn't possible given the
  341. // architecture for how settings are applied.
  342. if (include_tentative ||
  343. !mPermsOwnerControl->getTentative() ||
  344. !mPermsGroupControl->getTentative() ||
  345. !mPermsWorldControl->getTentative())
  346. {
  347. fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control;
  348. }
  349. if (include_tentative ||
  350. !mPermsOwnerInteract->getTentative() ||
  351. !mPermsGroupInteract->getTentative() ||
  352. !mPermsWorldInteract->getTentative())
  353. {
  354. fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact;
  355. }
  356. // Security tab settings:
  357. if (include_tentative || !mEnableWhiteList->getTentative())
  358. {
  359. fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] =
  360. (LLSD::Boolean)mEnableWhiteList->getValue();
  361. }
  362. if (include_tentative || !mWhiteListList->getTentative())
  363. {
  364. // iterate over white list and extract items
  365. std::vector<LLScrollListItem*> whitelist_items =
  366. mWhiteListList->getAllData();
  367. std::vector<LLScrollListItem*>::iterator iter =
  368. whitelist_items.begin();
  369. // *NOTE: need actually set the key to be an emptyArray(), or the merge
  370. // we do with this LLSD will think there's nothing to change.
  371. fill_me_in[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray();
  372. while (iter != whitelist_items.end())
  373. {
  374. LLScrollListCell* cell = (*iter++)->getColumn(0);
  375. std::string whitelist_url = cell->getValue().asString();
  376. fill_me_in[LLMediaEntry::WHITELIST_KEY].append(whitelist_url);
  377. }
  378. }
  379. LL_DEBUGS("MediaSettings") << "Media settings:\n";
  380. std::stringstream str;
  381. LLSDSerialize::toPrettyXML(fill_me_in, str);
  382. LL_CONT << str.str() << LL_ENDL;
  383. }
  384. bool LLFloaterMediaSettings::haveValuesChanged()
  385. {
  386. // *NOTE: The code below is very inefficient. Better to do this only when
  387. // data change.
  388. LLSD settings;
  389. getValues(settings, true);
  390. for (LLSD::map_const_iterator iter = settings.beginMap(),
  391. end = settings.endMap();
  392. iter != end; ++iter)
  393. {
  394. const std::string& current_key = iter->first;
  395. const LLSD& current_value = iter->second;
  396. if (!llsd_equals(current_value, mInitialValues[current_key]))
  397. {
  398. LL_DEBUGS("MediaSettings") << "Value for '" << current_key
  399. << "' has changed to: "
  400. << current_value.asString()
  401. << LL_ENDL;
  402. return true;
  403. }
  404. }
  405. LL_DEBUGS("MediaSettings") << "Values didn't change." << LL_ENDL;
  406. return false;
  407. }
  408. void LLFloaterMediaSettings::commitFields()
  409. {
  410. if (hasFocus())
  411. {
  412. LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocusUICtrl();
  413. if (cur_focus && cur_focus->acceptsTextInput())
  414. {
  415. cur_focus->onCommit();
  416. }
  417. }
  418. }
  419. void LLFloaterMediaSettings::apply()
  420. {
  421. // Pre-apply: make sure the home URL entry is committed
  422. mHomeURL->onCommit();
  423. if (haveValuesChanged())
  424. {
  425. LLSD settings;
  426. getValues(settings, false);
  427. gSelectMgr.selectionSetMedia(LLTextureEntry::MF_HAS_MEDIA, settings);
  428. // Post-apply: make sure to navigate to the home URL if the current URL
  429. // is empty and autoplay is on
  430. navigateHomeSelectedFace(true);
  431. }
  432. }
  433. void LLFloaterMediaSettings::updateMediaPreview()
  434. {
  435. if (mHomeURL->getValue().asString().length() > 0)
  436. {
  437. if (mPreviewMedia->getCurrentNavUrl() != mHomeURL->getValue().asString())
  438. {
  439. mPreviewMedia->navigateTo(mHomeURL->getValue().asString());
  440. // Mute the audio of the media while previewing it
  441. LLViewerMediaImpl* impl = mPreviewMedia->getMediaSource();
  442. if (impl)
  443. {
  444. impl->setVolume(0.f);
  445. }
  446. }
  447. }
  448. // New home URL will be empty if media is deleted so display a "preview
  449. // goes here" data url page
  450. else if (mPreviewMedia->getCurrentNavUrl() != CHECKERBOARD_DATA_URL)
  451. {
  452. mPreviewMedia->navigateTo(CHECKERBOARD_DATA_URL);
  453. }
  454. }
  455. bool LLFloaterMediaSettings::navigateHomeSelectedFace(bool only_if_current_is_empty)
  456. {
  457. struct functor_navigate_media : public LLSelectedTEGetFunctor<bool>
  458. {
  459. functor_navigate_media(bool flag)
  460. : only_if_current_is_empty(flag)
  461. {
  462. }
  463. bool get(LLViewerObject* objectp, S32 face) override
  464. {
  465. if (!objectp)
  466. {
  467. return false;
  468. }
  469. LLTextureEntry* tep = objectp->getTE(face);
  470. if (!tep || !objectp->permModify())
  471. {
  472. return false;
  473. }
  474. const LLMediaEntry* mdatap = tep->getMediaData();
  475. if (!mdatap)
  476. {
  477. return false;
  478. }
  479. if (!only_if_current_is_empty ||
  480. (mdatap->getCurrentURL().empty() && mdatap->getAutoPlay()))
  481. {
  482. viewer_media_t media_impl =
  483. LLViewerMedia::getMediaImplFromTextureID(mdatap->getMediaID());
  484. if (media_impl)
  485. {
  486. media_impl->navigateHome();
  487. if (!only_if_current_is_empty)
  488. {
  489. LLSD media_data;
  490. media_data[LLMediaEntry::CURRENT_URL_KEY] = "";
  491. tep->mergeIntoMediaData(media_data);
  492. }
  493. return true;
  494. }
  495. }
  496. return false;
  497. }
  498. bool only_if_current_is_empty;
  499. } functor_navigate_media(only_if_current_is_empty);
  500. bool all_face_media_navigated = false;
  501. LLObjectSelectionHandle selected_objects = gSelectMgr.getSelection();
  502. selected_objects->getSelectedTEValue(&functor_navigate_media,
  503. all_face_media_navigated);
  504. if (all_face_media_navigated)
  505. {
  506. struct functor_sync_to_server : public LLSelectedObjectFunctor
  507. {
  508. bool apply(LLViewerObject* objectp) override
  509. {
  510. LLVOVolume* vobjp = objectp->asVolume();
  511. if (vobjp)
  512. {
  513. vobjp->sendMediaDataUpdate();
  514. }
  515. return true;
  516. }
  517. } sendfunc;
  518. selected_objects->applyToObjects(&sendfunc);
  519. }
  520. // Note: we do not update the 'current URL' field until the media data
  521. // itself changes
  522. return all_face_media_navigated;
  523. }
  524. void LLFloaterMediaSettings::updateCurrentUrl()
  525. {
  526. // Get the current URL from the selection
  527. const LLMediaEntry default_media_data;
  528. std::string value_str = default_media_data.getCurrentURL();
  529. struct functor_getter_current_url
  530. : public LLSelectedTEGetFunctor<std::string>
  531. {
  532. functor_getter_current_url(const LLMediaEntry& entry)
  533. : mMediaEntry(entry)
  534. {
  535. }
  536. std::string get(LLViewerObject* object, S32 face) override
  537. {
  538. LLTextureEntry* tep = object ? object->getTE(face) : NULL;
  539. if (tep && tep->getMediaData())
  540. {
  541. return object->getTE(face)->getMediaData()->getCurrentURL();
  542. }
  543. return mMediaEntry.getCurrentURL();
  544. }
  545. const LLMediaEntry& mMediaEntry;
  546. } func_current_url(default_media_data);
  547. bool identical =
  548. gSelectMgr.getSelection()->getSelectedTEValue(&func_current_url,
  549. value_str);
  550. mCurrentURL->setText(value_str);
  551. mCurrentURL->setTentative(identical);
  552. if (isMultiple())
  553. {
  554. mCurrentURL->setText(std::string("Multiple Media"));
  555. }
  556. }
  557. const std::string LLFloaterMediaSettings::makeValidUrl(const std::string& src_url)
  558. {
  559. // Use LLURI to determine if we have a valid scheme
  560. LLURI candidate_url(src_url);
  561. if (candidate_url.scheme().empty())
  562. {
  563. // Build an URL comprised of default scheme and the original fragment
  564. const std::string default_scheme("http://");
  565. return default_scheme + src_url;
  566. }
  567. // We *could* test the "default scheme" + "original fragment" URL again
  568. // using LLURI to see if it is valid but I think the outcome is the same
  569. // in either case - our only option is to return the original URL
  570. // We *think* the original url passed in was valid
  571. return src_url;
  572. }
  573. // Wrapper for testing an URL against the whitelist. We grab entries from white
  574. // list list box widget and build a list to test against.
  575. bool LLFloaterMediaSettings::urlPassesWhiteList(const std::string& test_url)
  576. {
  577. // If the whitlelist list is tentative, it means we have multiple settings.
  578. // In that case, we have no choice but to return true
  579. if (mWhiteListList->getTentative())
  580. {
  581. return true;
  582. }
  583. // The checkUrlAgainstWhitelist(..) function works on a vector of strings
  584. // for the white list entries - in this panel, the white list is stored in
  585. // the widgets themselves so we need to build something compatible.
  586. std::vector<std::string> whitelist_strings;
  587. // Step through whitelist widget entries and grab them as strings
  588. std::vector<LLScrollListItem*> whitelist_items =
  589. mWhiteListList->getAllData();
  590. std::vector<LLScrollListItem*>::iterator iter = whitelist_items.begin();
  591. while (iter != whitelist_items.end())
  592. {
  593. LLScrollListCell* cell = (*iter++)->getColumn(0);
  594. std::string whitelist_url = cell->getValue().asString();
  595. whitelist_strings.emplace_back(whitelist_url);
  596. }
  597. // possible the URL is just a fragment so we validize it
  598. const std::string valid_url = makeValidUrl(test_url);
  599. // indicate if the URL passes whitelist
  600. return LLMediaEntry::checkUrlAgainstWhitelist(valid_url,
  601. whitelist_strings);
  602. }
  603. void LLFloaterMediaSettings::updateWhitelistEnableStatus()
  604. {
  605. // Get the value for home URL and make it a valid URL
  606. const std::string valid_url = makeValidUrl(getHomeUrl());
  607. // Now check to see if the home url passes the whitelist in its entirity
  608. if (urlPassesWhiteList(valid_url))
  609. {
  610. mEnableWhiteList->setEnabled(true);
  611. mHomeUrlFailsWhiteListText->setVisible(false);
  612. }
  613. else
  614. {
  615. mEnableWhiteList->set(false);
  616. mEnableWhiteList->setEnabled(false);
  617. mHomeUrlFailsWhiteListText->setVisible(true);
  618. }
  619. }
  620. void LLFloaterMediaSettings::addWhiteListEntry(const std::string& entry)
  621. {
  622. // Grab the home url
  623. std::string home_url = getHomeUrl();
  624. // Try to make a valid URL based on what the user entered - missing scheme
  625. // for example
  626. const std::string valid_url = makeValidUrl(home_url);
  627. // Check the home url against this single whitelist entry
  628. std::vector<std::string> whitelist_entries;
  629. whitelist_entries.emplace_back(entry);
  630. bool passes = LLMediaEntry::checkUrlAgainstWhitelist(valid_url,
  631. whitelist_entries);
  632. LLSD row;
  633. row["columns"][0]["type"] = "text";
  634. row["columns"][0]["value"] = entry;
  635. if (!passes && ! home_url.empty())
  636. {
  637. row["columns"][0]["color"] = LLColor4::red2.getValue();
  638. }
  639. // Add to the white list scroll box
  640. mWhiteListList->addElement(row);
  641. }
  642. bool LLFloaterMediaSettings::checkHomeUrlPassesWhitelist()
  643. {
  644. std::string home_url;
  645. if (mHomeURL)
  646. {
  647. home_url = mHomeURL->getValue().asString();
  648. }
  649. bool fail = !home_url.empty() && !urlPassesWhiteList(home_url);
  650. mFailWhiteListText->setVisible(fail);
  651. return !fail;
  652. }
  653. //static
  654. const std::string LLFloaterMediaSettings::getHomeUrl()
  655. {
  656. // This will create a new instance if needed:
  657. LLFloaterMediaSettings* self = getInstance();
  658. if (self->mHomeURL)
  659. {
  660. return self->mHomeURL->getValue().asString();
  661. }
  662. else
  663. {
  664. return LLStringUtil::null;
  665. }
  666. }
  667. //static
  668. bool LLFloaterMediaSettings::isMultiple()
  669. {
  670. if (sIdenticalHasMediaInfo)
  671. {
  672. if (sMultipleMedia)
  673. {
  674. return true;
  675. }
  676. }
  677. else
  678. {
  679. if (sMultipleValidMedia)
  680. {
  681. return true;
  682. }
  683. }
  684. return false;
  685. }
  686. //static
  687. void LLFloaterMediaSettings::initValues(LLSD& media_settings,
  688. bool editable)
  689. {
  690. // This will create a new instance if needed:
  691. LLFloaterMediaSettings* self = getInstance();
  692. if (self->hasFocus()) return;
  693. self->clearValues(editable);
  694. self->mMediaEditable = editable;
  695. // Update all panels with values from simulator
  696. if (isMultiple())
  697. {
  698. // *HACK: "edit" the incoming media_settings
  699. media_settings[LLMediaEntry::CURRENT_URL_KEY] = "Multiple Media";
  700. media_settings[LLMediaEntry::HOME_URL_KEY] = "Multiple Media";
  701. }
  702. std::string base_key, tentative_key;
  703. LLUICtrl* uictrlp;
  704. struct
  705. {
  706. std::string key_name;
  707. LLUICtrl* ctrl_ptr;
  708. std::string ctrl_type;
  709. } data_set [] =
  710. {
  711. { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" },
  712. { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" },
  713. { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" },
  714. { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" },
  715. { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLTextBox" },
  716. { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" },
  717. { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" },
  718. { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" },
  719. { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" },
  720. { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" },
  721. { LLMediaEntry::PERMS_OWNER_INTERACT_KEY, self->mPermsOwnerInteract, "LLCheckBoxCtrl" },
  722. { LLMediaEntry::PERMS_OWNER_CONTROL_KEY, self->mPermsOwnerControl, "LLCheckBoxCtrl" },
  723. { LLMediaEntry::PERMS_GROUP_INTERACT_KEY, self->mPermsGroupInteract, "LLCheckBoxCtrl" },
  724. { LLMediaEntry::PERMS_GROUP_CONTROL_KEY, self->mPermsGroupControl, "LLCheckBoxCtrl" },
  725. { LLMediaEntry::PERMS_ANYONE_INTERACT_KEY, self->mPermsWorldInteract, "LLCheckBoxCtrl" },
  726. { LLMediaEntry::PERMS_ANYONE_CONTROL_KEY, self->mPermsWorldControl, "LLCheckBoxCtrl" },
  727. { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" },
  728. { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" },
  729. { "", NULL , "" }
  730. };
  731. for (U32 i = 0; data_set[i].key_name.length() > 0; ++i)
  732. {
  733. bool enabled_overridden = false;
  734. base_key = std::string(data_set[i].key_name);
  735. tentative_key = base_key + std::string(LLMediaEntry::TENTATIVE_SUFFIX);
  736. uictrlp = data_set[i].ctrl_ptr;
  737. if (uictrlp && media_settings[base_key].isDefined())
  738. {
  739. if (data_set[i].ctrl_type == "LLLineEditor")
  740. {
  741. ((LLLineEditor*)uictrlp)->setText(media_settings[base_key].asString());
  742. }
  743. else if (data_set[i].ctrl_type == "LLCheckBoxCtrl")
  744. {
  745. ((LLCheckBoxCtrl*)uictrlp)->setValue(media_settings[base_key].asBoolean());
  746. }
  747. else if (data_set[i].ctrl_type == "LLComboBox")
  748. {
  749. ((LLComboBox*)uictrlp)->setCurrentByIndex(media_settings[base_key].asInteger());
  750. }
  751. else if (data_set[i].ctrl_type == "LLSpinCtrl")
  752. {
  753. ((LLSpinCtrl*)uictrlp)->setValue(media_settings[base_key].asInteger());
  754. }
  755. else if (data_set[i].ctrl_type == "LLScrollListCtrl")
  756. {
  757. LLScrollListCtrl* list = (LLScrollListCtrl*)uictrlp;
  758. list->deleteAllItems();
  759. // Points to list of white list URLs
  760. LLSD& url_list = media_settings[base_key];
  761. // If tentative, don't add entries
  762. if (media_settings[tentative_key].asBoolean())
  763. {
  764. self->mWhiteListList->setEnabled(false);
  765. enabled_overridden = true;
  766. }
  767. else
  768. {
  769. // Iterate over them and add to scroll list
  770. LLSD::array_iterator iter = url_list.beginArray();
  771. while (iter != url_list.endArray())
  772. {
  773. std::string entry = *iter++;
  774. self->addWhiteListEntry(entry);
  775. }
  776. }
  777. }
  778. if (!enabled_overridden)
  779. {
  780. uictrlp->setEnabled(editable);
  781. }
  782. uictrlp->setTentative(media_settings[tentative_key].asBoolean());
  783. }
  784. }
  785. // General tab specific init actions:
  786. // Interrogates controls and updates widgets as required
  787. self->updateMediaPreview();
  788. // Permissions tab specific init actions:
  789. // *NOTE: If any of a particular flavor is tentative, we have to disable
  790. // them all because of an architectural issue: namely that we represent
  791. // these as a bit field, and we can't selectively apply only one bit to
  792. // all selected faces if they don't match.
  793. if (self->mPermsOwnerInteract->getTentative() ||
  794. self->mPermsGroupInteract->getTentative() ||
  795. self->mPermsWorldInteract->getTentative())
  796. {
  797. self->mPermsOwnerInteract->setEnabled(false);
  798. self->mPermsGroupInteract->setEnabled(false);
  799. self->mPermsWorldInteract->setEnabled(false);
  800. }
  801. if (self->mPermsOwnerControl->getTentative() ||
  802. self->mPermsGroupControl->getTentative() ||
  803. self->mPermsWorldControl->getTentative())
  804. {
  805. self->mPermsOwnerControl->setEnabled(false);
  806. self->mPermsGroupControl->setEnabled(false);
  807. self->mPermsWorldControl->setEnabled(false);
  808. }
  809. self->childSetEnabled("controls_label", editable);
  810. self->childSetEnabled("owner_label", editable);
  811. self->childSetEnabled("group_label", editable);
  812. self->childSetEnabled("anyone_label", editable);
  813. // Security tab specific init actions:
  814. // initial update - hides/shows status messages etc.
  815. self->updateWhitelistEnableStatus();
  816. // Squirrel away initial values
  817. self->mInitialValues.clear();
  818. self->getValues(self->mInitialValues, true);
  819. self->mApplyBtn->setEnabled(editable);
  820. self->mOKBtn->setEnabled(editable);
  821. }
  822. //static
  823. void LLFloaterMediaSettings::clearValues(bool editable)
  824. {
  825. LLFloaterMediaSettings* self = findInstance();
  826. if (!self)
  827. {
  828. return;
  829. }
  830. self->mGroupId.setNull();
  831. // General tab:
  832. self->mAutoLoop->clear();
  833. self->mAutoPlay->clear();
  834. self->mAutoScale->clear();
  835. self->mAutoZoom->clear();
  836. self->mCurrentURL->clear();
  837. self->mFirstClick->clear();
  838. self->mHeightPixels->clear();
  839. self->mHomeURL->clear();
  840. self->mHomeUrlCommitted = false;
  841. self->mWidthPixels->clear();
  842. self->mAutoLoop->setEnabled(editable);
  843. self->mAutoPlay->setEnabled(editable);
  844. self->mAutoScale->setEnabled(editable);
  845. self->mAutoZoom->setEnabled(editable);
  846. self->mCurrentURL->setEnabled(editable);
  847. self->mFirstClick->setEnabled(editable);
  848. self->mHeightPixels->setEnabled(editable);
  849. self->mHomeURL->setEnabled(editable);
  850. self->mWidthPixels->setEnabled(editable);
  851. self->updateMediaPreview();
  852. // Permissions tab:
  853. self->mControls->clear();
  854. self->mPermsOwnerInteract->clear();
  855. self->mPermsOwnerControl->clear();
  856. self->mPermsGroupInteract->clear();
  857. self->mPermsGroupControl->clear();
  858. self->mPermsWorldInteract->clear();
  859. self->mPermsWorldControl->clear();
  860. self->mControls->setEnabled(editable);
  861. self->mPermsOwnerInteract->setEnabled(editable);
  862. self->mPermsOwnerControl->setEnabled(editable);
  863. self->mPermsGroupInteract->setEnabled(editable);
  864. self->mPermsGroupControl->setEnabled(editable);
  865. self->mPermsWorldInteract->setEnabled(editable);
  866. self->mPermsWorldControl->setEnabled(editable);
  867. self->childSetEnabled("controls_label", editable);
  868. self->childSetEnabled("owner_label", editable);
  869. self->childSetEnabled("group_label", editable);
  870. self->childSetEnabled("anyone_label", editable);
  871. // Security tab:
  872. self->mEnableWhiteList->clear();
  873. self->mWhiteListList->deleteAllItems();
  874. self->mEnableWhiteList->setEnabled(editable);
  875. self->mWhiteListList->setEnabled(editable);
  876. }
  877. //static
  878. void LLFloaterMediaSettings::onTabChanged(void* userdata, bool from_click)
  879. {
  880. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  881. if (self && self->mTabContainer)
  882. {
  883. gSavedSettings.setS32("LastMediaSettingsTab",
  884. self->mTabContainer->getCurrentPanelIndex());
  885. }
  886. }
  887. //static
  888. void LLFloaterMediaSettings::onCommitHomeURL(LLUICtrl* ctrl, void* userdata)
  889. {
  890. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  891. if (self)
  892. {
  893. // check home url passes whitelist and display warning if not
  894. self->mHomeUrlCommitted = self->checkHomeUrlPassesWhitelist();
  895. self->updateMediaPreview();
  896. }
  897. }
  898. //static
  899. void LLFloaterMediaSettings::onCommitNewPattern(LLUICtrl* ctrl, void* userdata)
  900. {
  901. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  902. if (self && self->mNewWhiteListPattern)
  903. {
  904. std::string entry = self->mNewWhiteListPattern->getText();
  905. if (!entry.empty())
  906. {
  907. self->addWhiteListEntry(entry);
  908. self->mNewWhiteListPattern->clear();
  909. }
  910. }
  911. }
  912. //static
  913. void LLFloaterMediaSettings::onBtnResetCurrentUrl(void* userdata)
  914. {
  915. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  916. if (self)
  917. {
  918. self->navigateHomeSelectedFace(false);
  919. }
  920. }
  921. // static
  922. void LLFloaterMediaSettings::onBtnDel(void* userdata)
  923. {
  924. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  925. if (self)
  926. {
  927. self->mWhiteListList->deleteSelectedItems();
  928. // contents of whitelist changed so recheck it against home url
  929. self->updateWhitelistEnableStatus();
  930. }
  931. }
  932. //static
  933. void LLFloaterMediaSettings::onBtnOK(void* userdata)
  934. {
  935. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  936. if (self)
  937. {
  938. self->commitFields();
  939. self->apply();
  940. self->close();
  941. }
  942. }
  943. //static
  944. void LLFloaterMediaSettings::onBtnApply(void* userdata)
  945. {
  946. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  947. if (self)
  948. {
  949. self->commitFields();
  950. self->apply();
  951. self->mInitialValues.clear();
  952. self->getValues(self->mInitialValues, true);
  953. }
  954. }
  955. //static
  956. void LLFloaterMediaSettings::onBtnCancel(void* userdata)
  957. {
  958. LLFloaterMediaSettings* self = (LLFloaterMediaSettings*)userdata;
  959. if (self)
  960. {
  961. self->close();
  962. }
  963. }