llpanelnearbymedia.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:34k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpanelnearbymedia.cpp
  3.  * @brief Management interface for muting and controlling nearby media
  4.  *
  5.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2005-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 "llpanelnearbymedia.h"
  34. #include "llaudioengine.h"
  35. #include "llcheckboxctrl.h"
  36. #include "llcombobox.h"
  37. #include "llresizebar.h"
  38. #include "llresizehandle.h"
  39. #include "llscrolllistctrl.h"
  40. #include "llscrolllistitem.h"
  41. #include "llscrolllistcell.h"
  42. #include "llslider.h"
  43. #include "llsliderctrl.h"
  44. #include "llagent.h"
  45. #include "llagentui.h"
  46. #include "llbutton.h"
  47. #include "lltextbox.h"
  48. #include "llviewermedia.h"
  49. #include "llviewerparcelmedia.h"
  50. #include "llviewerregion.h"
  51. #include "llviewermediafocus.h"
  52. #include "llviewerparcelmgr.h"
  53. #include "llparcel.h"
  54. #include "llpluginclassmedia.h"
  55. #include "llvovolume.h"
  56. #include "llstatusbar.h"
  57. #include "llsdutil.h"
  58. #include "llfloaterreg.h"
  59. #include "llfloaterpreference.h" // for the gear icon
  60. #include "lltabcontainer.h"
  61. #include <stringize.h>
  62. extern LLControlGroup gSavedSettings;
  63. static const LLUUID PARCEL_MEDIA_LIST_ITEM_UUID = LLUUID("CAB5920F-E484-4233-8621-384CF373A321");
  64. static const LLUUID PARCEL_AUDIO_LIST_ITEM_UUID = LLUUID("DF4B020D-8A24-4B95-AB5D-CA970D694822");
  65. //
  66. // LLPanelNearByMedia
  67. //
  68. LLPanelNearByMedia::LLPanelNearByMedia()
  69. : mMediaList(NULL),
  70.   mEnableAllCtrl(NULL),
  71.   mAllMediaDisabled(false),
  72.   mDebugInfoVisible(false),
  73.   mParcelMediaItem(NULL),
  74.   mParcelAudioItem(NULL)
  75. {
  76. mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
  77. gSavedSettings.getBOOL("MediaTentativeAutoPlay");
  78. mCommitCallbackRegistrar.add("MediaListCtrl.EnableAll", boost::bind(&LLPanelNearByMedia::onClickEnableAll, this));
  79. mCommitCallbackRegistrar.add("MediaListCtrl.DisableAll", boost::bind(&LLPanelNearByMedia::onClickDisableAll, this));
  80. mCommitCallbackRegistrar.add("MediaListCtrl.GoMediaPrefs", boost::bind(&LLPanelNearByMedia::onAdvancedButtonClick, this));
  81. mCommitCallbackRegistrar.add("MediaListCtrl.MoreLess", boost::bind(&LLPanelNearByMedia::onMoreLess, this));
  82. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Stop", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaStop, this));
  83. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Play", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaPlay, this));
  84. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Pause", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaPause, this));
  85. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Mute", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaMute, this));
  86. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Volume", boost::bind(&LLPanelNearByMedia::onCommitSelectedMediaVolume, this));
  87. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Zoom", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaZoom, this));
  88. mCommitCallbackRegistrar.add("SelectedMediaCtrl.Unzoom", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaUnzoom, this));
  89. LLUICtrlFactory::instance().buildPanel(this, "panel_nearby_media.xml");
  90. }
  91. LLPanelNearByMedia::~LLPanelNearByMedia()
  92. {
  93. }
  94. BOOL LLPanelNearByMedia::postBuild()
  95. {
  96. LLPanel::postBuild();
  97. const S32 RESIZE_BAR_THICKNESS = 6;
  98. LLResizeBar::Params p;
  99. p.rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0);
  100. p.name = "resizebar_bottom";
  101. p.min_size = getRect().getHeight();
  102. p.side = LLResizeBar::BOTTOM;
  103. p.resizing_view = this;
  104. addChild( LLUICtrlFactory::create<LLResizeBar>(p) );
  105. p.rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0);
  106. p.name = "resizebar_left";
  107. p.min_size = getRect().getWidth();
  108. p.side = LLResizeBar::LEFT;
  109. addChild( LLUICtrlFactory::create<LLResizeBar>(p) );
  110. LLResizeHandle::Params resize_handle_p;
  111. resize_handle_p.rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 );
  112. resize_handle_p.mouse_opaque(false);
  113. resize_handle_p.min_width(getRect().getWidth());
  114. resize_handle_p.min_height(getRect().getHeight());
  115. resize_handle_p.corner(LLResizeHandle::LEFT_BOTTOM);
  116. addChild(LLUICtrlFactory::create<LLResizeHandle>(resize_handle_p));
  117. mNearbyMediaPanel = getChild<LLUICtrl>("nearby_media_panel");
  118. mMediaList = getChild<LLScrollListCtrl>("media_list");
  119. mEnableAllCtrl = getChild<LLUICtrl>("all_nearby_media_enable_btn");
  120. mDisableAllCtrl = getChild<LLUICtrl>("all_nearby_media_disable_btn");
  121. mItemCountText = getChild<LLTextBox>("media_item_count");
  122. mShowCtrl = getChild<LLComboBox>("show_combo");
  123. // Dynamic (selection-dependent) controls
  124. mStopCtrl = getChild<LLUICtrl>("stop");
  125. mPlayCtrl = getChild<LLUICtrl>("play");
  126. mPauseCtrl = getChild<LLUICtrl>("pause");
  127. mMuteCtrl = getChild<LLUICtrl>("mute");
  128. mVolumeSliderCtrl = getChild<LLUICtrl>("volume_slider_ctrl");
  129. mZoomCtrl = getChild<LLUICtrl>("zoom");
  130. mUnzoomCtrl = getChild<LLUICtrl>("unzoom");
  131. mVolumeSlider = getChild<LLSlider>("volume_slider");
  132. mMuteBtn = getChild<LLButton>("mute_btn");
  133. mEmptyNameString = getString("empty_item_text");
  134. mParcelMediaName = getString("parcel_media_name");
  135. mParcelAudioName = getString("parcel_audio_name");
  136. mPlayingString = getString("playing_suffix");
  137. mMediaList->setDoubleClickCallback(onZoomMedia, this);
  138. mMediaList->sortByColumnIndex(PROXIMITY_COLUMN, TRUE);
  139. mMediaList->sortByColumnIndex(VISIBILITY_COLUMN, FALSE);
  140. refreshList();
  141. updateControls();
  142. updateColumns();
  143. LLView* minimized_controls = getChildView("minimized_controls");
  144. mMoreRect = getRect();
  145. mLessRect = getRect();
  146. mLessRect.mBottom = minimized_controls->getRect().mBottom;
  147. getChild<LLUICtrl>("more_less_btn")->setValue(false);
  148. onMoreLess();
  149. return TRUE;
  150. }
  151. /*virtual*/
  152. void LLPanelNearByMedia::onMouseEnter(S32 x, S32 y, MASK mask)
  153. {
  154. mHoverTimer.stop();
  155. LLPanel::onMouseEnter(x,y,mask);
  156. }
  157. /*virtual*/
  158. void LLPanelNearByMedia::onMouseLeave(S32 x, S32 y, MASK mask)
  159. {
  160. mHoverTimer.start();
  161. LLPanel::onMouseLeave(x,y,mask);
  162. }
  163. /*virtual*/ 
  164. void LLPanelNearByMedia::handleVisibilityChange ( BOOL new_visibility )
  165. {
  166. if (new_visibility)
  167. {
  168. mHoverTimer.start(); // timer will be stopped when mouse hovers over panel
  169. //gFocusMgr.setTopCtrl(this);
  170. }
  171. else
  172. {
  173. mHoverTimer.stop();
  174. //if (gFocusMgr.getTopCtrl() == this)
  175. //{
  176. // gFocusMgr.setTopCtrl(NULL);
  177. //}
  178. }
  179. }
  180. /*virtual*/ 
  181. void LLPanelNearByMedia::onTopLost ()
  182. {
  183. //LLUICtrl* new_top = gFocusMgr.getTopCtrl();
  184. //if (!new_top || !new_top->hasAncestor(this))
  185. //{
  186. // setVisible(FALSE);
  187. //}
  188. }
  189. /*virtual*/
  190. void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent)
  191. {
  192. LLPanel::reshape(width, height, called_from_parent);
  193. LLButton* more_less_btn = getChild<LLButton>("more_less_btn");
  194. if (more_less_btn->getValue().asBoolean())
  195. {
  196. mMoreRect = getRect();
  197. }
  198. }
  199. const F32 AUTO_CLOSE_FADE_TIME_START= 4.0f;
  200. const F32 AUTO_CLOSE_FADE_TIME_END = 5.0f;
  201. void LLPanelNearByMedia::draw()
  202. {
  203. //LLUICtrl* new_top = gFocusMgr.getTopCtrl();
  204. //if (new_top != this)
  205. //{
  206. // // reassert top ctrl
  207. // gFocusMgr.setTopCtrl(this);
  208. //}
  209. // keep bottom of panel on screen
  210. LLRect screen_rect = calcScreenRect();
  211. if (screen_rect.mBottom < 0)
  212. {
  213. LLRect new_rect = getRect();
  214. new_rect.mBottom += 0 - screen_rect.mBottom;
  215. setShape(new_rect);
  216. }
  217. mItemCountText->setValue(llformat(getString("media_item_count_format").c_str(), mMediaList->getItemCount()));
  218. refreshList();
  219. updateControls();
  220. F32 alpha = mHoverTimer.getStarted() 
  221. ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), AUTO_CLOSE_FADE_TIME_START, AUTO_CLOSE_FADE_TIME_END, 1.f, 0.f)
  222. : 1.0f;
  223. LLViewDrawContext context(alpha);
  224. LLPanel::draw();
  225. if (alpha == 0.f)
  226. {
  227. setVisible(false);
  228. }
  229. }
  230. bool LLPanelNearByMedia::getParcelAudioAutoStart()
  231. {
  232. return mParcelAudioAutoStart;
  233. }
  234. LLScrollListItem* LLPanelNearByMedia::addListItem(const LLUUID &id)
  235. {
  236. if (NULL == mMediaList) return NULL;
  237. // Just set up the columns -- the values will be filled in by updateListItem().
  238. LLSD row;
  239. row["id"] = id;
  240. LLSD &columns = row["columns"];
  241. columns[CHECKBOX_COLUMN]["column"] = "media_checkbox_ctrl";
  242. columns[CHECKBOX_COLUMN]["type"] = "checkbox";
  243. //if(mDebugInfoVisible)
  244. {
  245. columns[PROXIMITY_COLUMN]["column"] = "media_proximity";
  246. columns[PROXIMITY_COLUMN]["value"] = "";
  247. columns[VISIBILITY_COLUMN]["column"] = "media_visibility";
  248. columns[VISIBILITY_COLUMN]["value"] = "";
  249. columns[CLASS_COLUMN]["column"] = "media_class";
  250. columns[CLASS_COLUMN]["type"] = "text";
  251. columns[CLASS_COLUMN]["value"] = "";
  252. }
  253. columns[NAME_COLUMN]["column"] = "media_name";
  254. columns[NAME_COLUMN]["type"] = "text";
  255. columns[NAME_COLUMN]["value"] = "";
  256. //if(mDebugInfoVisible)
  257. {
  258. columns[DEBUG_COLUMN]["column"] = "media_debug";
  259. columns[DEBUG_COLUMN]["type"] = "text";
  260. columns[DEBUG_COLUMN]["value"] = "";
  261. }
  262. LLScrollListItem* new_item = mMediaList->addElement(row);
  263. if (NULL != new_item)
  264. {
  265. LLScrollListCheck* scroll_list_check = dynamic_cast<LLScrollListCheck*>(new_item->getColumn(CHECKBOX_COLUMN));
  266. if (scroll_list_check)
  267. {
  268. LLCheckBoxCtrl *check = scroll_list_check->getCheckBox();
  269. check->setCommitCallback(boost::bind(&LLPanelNearByMedia::onCheckItem, this, _1, id));
  270. }
  271. }
  272. return new_item;
  273. }
  274. void LLPanelNearByMedia::updateListItem(LLScrollListItem* item, LLViewerMediaImpl* impl)
  275. {
  276. std::string item_name;
  277. std::string item_tooltip;
  278. std::string debug_str;
  279. LLPanelNearByMedia::MediaClass media_class = MEDIA_CLASS_ALL;
  280. getNameAndUrlHelper(impl, item_name, item_tooltip, mEmptyNameString);
  281. // Focused
  282. if (impl->hasFocus())
  283. {
  284. media_class = MEDIA_CLASS_FOCUSED;
  285. }
  286. // Is attached to another avatar?
  287. else if (impl->isAttachedToAnotherAvatar())
  288. {
  289. media_class = MEDIA_CLASS_ON_OTHERS;
  290. }
  291. // Outside agent parcel
  292. else if (!impl->isInAgentParcel())
  293. {
  294. media_class = MEDIA_CLASS_OUTSIDE_PARCEL;
  295. }
  296. else {
  297. // inside parcel
  298. media_class = MEDIA_CLASS_WITHIN_PARCEL;
  299. }
  300. if(mDebugInfoVisible)
  301. {
  302. debug_str += llformat("%g/", (float)impl->getInterest());
  303. // proximity distance is actually distance squared -- display it as straight distance.
  304. debug_str += llformat("%g/", fsqrtf(impl->getProximityDistance()));
  305. // s += llformat("%g/", (float)impl->getCPUUsage());
  306. // s += llformat("%g/", (float)impl->getApproximateTextureInterest());
  307. debug_str += llformat("%g/", (float)(NULL == impl->getSomeObject()) ? 0.0 : impl->getSomeObject()->getPixelArea());
  308. debug_str += LLPluginClassMedia::priorityToString(impl->getPriority());
  309. if(impl->hasMedia())
  310. {
  311. debug_str += '@';
  312. }
  313. else if(impl->isPlayable())
  314. {
  315. debug_str += '+';
  316. }
  317. else if(impl->isForcedUnloaded())
  318. {
  319. debug_str += '!';
  320. }
  321. }
  322. updateListItem(item,
  323.    item_name,
  324.    item_tooltip,
  325.    impl->getProximity(),
  326.    impl->isMediaDisabled(),
  327.    impl->hasMedia(),
  328.    impl->isMediaTimeBased() && impl->isMediaPlaying(),
  329.    media_class,
  330.    debug_str);
  331. }
  332. void LLPanelNearByMedia::updateListItem(LLScrollListItem* item,
  333.   const std::string &item_name,
  334.   const std::string &item_tooltip,
  335.   S32 proximity,
  336.   bool is_disabled,
  337.   bool has_media,
  338.   bool is_time_based_and_playing,
  339.   LLPanelNearByMedia::MediaClass media_class,
  340.   const std::string &debug_str)
  341. {
  342. LLScrollListCell* cell = item->getColumn(PROXIMITY_COLUMN);
  343. if(cell)
  344. {
  345. // since we are forced to sort by text, encode sort order as string
  346. std::string proximity_string = STRINGIZE(proximity);
  347. std::string old_proximity_string = cell->getValue().asString();
  348. if(proximity_string != old_proximity_string)
  349. {
  350. cell->setValue(proximity_string);
  351. mMediaList->setNeedsSort(true);
  352. }
  353. }
  354. cell = item->getColumn(CHECKBOX_COLUMN);
  355. if(cell)
  356. {
  357. cell->setValue(!is_disabled);
  358. }
  359. cell = item->getColumn(VISIBILITY_COLUMN);
  360. if(cell)
  361. {
  362. S32 old_visibility = cell->getValue();
  363. // *HACK ALERT: force ordering of Media before Audio before the rest of the list
  364. S32 new_visibility = 
  365. item->getUUID() == PARCEL_MEDIA_LIST_ITEM_UUID ? 3
  366. : item->getUUID() == PARCEL_AUDIO_LIST_ITEM_UUID ? 2
  367. : (has_media) ? 1 
  368. : ((is_disabled) ? 0
  369. : -1);
  370. cell->setValue(STRINGIZE(new_visibility));
  371. if (new_visibility != old_visibility)
  372. {
  373. mMediaList->setNeedsSort(true);
  374. }
  375. }
  376. cell = item->getColumn(NAME_COLUMN);
  377. if(cell)
  378. {
  379. std::string name = item_name;
  380. std::string old_name = cell->getValue().asString();
  381. if (has_media) 
  382. {
  383. name += " " + mPlayingString;
  384. }
  385. if (name != old_name)
  386. {
  387. cell->setValue(name);
  388. }
  389. cell->setToolTip(item_tooltip);
  390. // *TODO: Make these font styles/colors configurable via XUI
  391. U8 font_style = LLFontGL::NORMAL;
  392. LLColor4 cell_color = LLColor4::white;
  393. // Only colorize by class in debug
  394. if (mDebugInfoVisible)
  395. {
  396. switch (media_class) {
  397. case MEDIA_CLASS_FOCUSED:
  398. cell_color = LLColor4::yellow;
  399. break;
  400. case MEDIA_CLASS_ON_OTHERS:
  401. cell_color = LLColor4::red;
  402. break;
  403. case MEDIA_CLASS_OUTSIDE_PARCEL:
  404. cell_color = LLColor4::orange;
  405. break;
  406. case MEDIA_CLASS_WITHIN_PARCEL:
  407. default:
  408. break;
  409. }
  410. }
  411. if (is_disabled)
  412. {
  413. if (mDebugInfoVisible)
  414. {
  415. font_style |= LLFontGL::ITALIC;
  416. cell_color = LLColor4::black;
  417. }
  418. else {
  419. // Dim it if it is disabled
  420. cell_color.setAlpha(0.25);
  421. }
  422. }
  423. // Dim it if it isn't "showing"
  424. else if (!has_media)
  425. {
  426. cell_color.setAlpha(0.25);
  427. }
  428. // Bold it if it is time-based media and it is playing
  429. else if (is_time_based_and_playing)
  430. {
  431. if (mDebugInfoVisible) font_style |= LLFontGL::BOLD;
  432. }
  433. cell->setColor(cell_color);
  434. LLScrollListText *text_cell = dynamic_cast<LLScrollListText*> (cell);
  435. if (text_cell)
  436. {
  437. text_cell->setFontStyle(font_style);
  438. }
  439. }
  440. cell = item->getColumn(CLASS_COLUMN);
  441. if(cell)
  442. {
  443. // TODO: clean this up!
  444. cell->setValue(STRINGIZE(media_class));
  445. }
  446. if(mDebugInfoVisible)
  447. {
  448. cell = item->getColumn(DEBUG_COLUMN);
  449. if(cell)
  450. {
  451. cell->setValue(debug_str);
  452. }
  453. }
  454. }
  455.  
  456. void LLPanelNearByMedia::removeListItem(const LLUUID &id)
  457. {
  458. if (NULL == mMediaList) return;
  459. mMediaList->deleteSingleItem(mMediaList->getItemIndex(id));
  460. }
  461. void LLPanelNearByMedia::refreshParcelItems()
  462. {
  463. //
  464. // First add/remove the "fake" items Parcel Media and Parcel Audio.
  465. // These items will have special UUIDs 
  466. //    PARCEL_MEDIA_LIST_ITEM_UUID
  467. //    PARCEL_AUDIO_LIST_ITEM_UUID
  468. //
  469. // Get the filter choice.
  470. const LLSD &choice_llsd = mShowCtrl->getSelectedValue();
  471. MediaClass choice = (MediaClass)choice_llsd.asInteger();
  472. // Only show "special parcel items" if "All" or "Within" filter
  473. bool should_include = choice == MEDIA_CLASS_ALL || choice == MEDIA_CLASS_WITHIN_PARCEL;
  474. // First Parcel Media: add or remove it as necessary
  475. if (should_include && LLViewerMedia::hasParcelMedia())
  476. {
  477. // Yes, there is parcel media.
  478. if (NULL == mParcelMediaItem)
  479. {
  480. mParcelMediaItem = addListItem(PARCEL_MEDIA_LIST_ITEM_UUID);
  481. mMediaList->setNeedsSort(true);
  482. }
  483. }
  484. else {
  485. if (NULL != mParcelMediaItem) {
  486. removeListItem(PARCEL_MEDIA_LIST_ITEM_UUID);
  487. mParcelMediaItem = NULL;
  488. mMediaList->setNeedsSort(true);
  489. }
  490. }
  491. // ... then update it
  492. if (NULL != mParcelMediaItem)
  493. {
  494. std::string name, url, tooltip;
  495. getNameAndUrlHelper(LLViewerParcelMedia::getParcelMedia(), name, url, "");
  496. if (name.empty() || name == url)
  497. {
  498. tooltip = url;
  499. }
  500. else {
  501. tooltip = name + " : " + url;
  502. }
  503. LLViewerMediaImpl *impl = LLViewerParcelMedia::getParcelMedia();
  504. updateListItem(mParcelMediaItem,
  505.    mParcelMediaName,
  506.    tooltip,
  507.    -2, // Proximity closer than anything else, before Parcel Audio
  508.    impl == NULL || impl->isMediaDisabled(),
  509.    impl != NULL && !LLViewerParcelMedia::getURL().empty(),
  510.    impl != NULL && impl->isMediaTimeBased() && impl->isMediaPlaying(),
  511.    MEDIA_CLASS_ALL,
  512.    "parcel media");
  513. }
  514. // Next Parcel Audio: add or remove it as necessary
  515. if (should_include && LLViewerMedia::hasParcelAudio())
  516. {
  517. // Yes, there is parcel audio.
  518. if (NULL == mParcelAudioItem)
  519. {
  520. mParcelAudioItem = addListItem(PARCEL_AUDIO_LIST_ITEM_UUID);
  521. mMediaList->setNeedsSort(true);
  522. }
  523. }
  524. else {
  525. if (NULL != mParcelAudioItem) {
  526. removeListItem(PARCEL_AUDIO_LIST_ITEM_UUID);
  527. mParcelAudioItem = NULL;
  528. mMediaList->setNeedsSort(true);
  529. }
  530. }
  531. // ... then update it
  532. if (NULL != mParcelAudioItem)
  533. {
  534. bool is_playing = LLViewerMedia::isParcelAudioPlaying();
  535. updateListItem(mParcelAudioItem,
  536.    mParcelAudioName,
  537.    LLViewerMedia::getParcelAudioURL(),
  538.    -1, // Proximity after Parcel Media, but closer than anything else
  539.    !is_playing,
  540.    is_playing,
  541.    is_playing,
  542.    MEDIA_CLASS_ALL,
  543.    "parcel audio");
  544. }
  545. }
  546. void LLPanelNearByMedia::refreshList()
  547. {
  548. bool all_items_deleted = false;
  549. if(!mMediaList)
  550. {
  551. // None of this makes any sense if the media list isn't there.
  552. return;
  553. }
  554. // Check whether the debug column has been shown/hidden.
  555. bool debug_info_visible = gSavedSettings.getBOOL("MediaPerformanceManagerDebug");
  556. if(debug_info_visible != mDebugInfoVisible)
  557. {
  558. mDebugInfoVisible = debug_info_visible;
  559. // Clear all items so the list gets regenerated.
  560. mMediaList->deleteAllItems();
  561. mParcelAudioItem = NULL;
  562. mParcelMediaItem = NULL;
  563. all_items_deleted = true;
  564. updateColumns();
  565. }
  566. refreshParcelItems();
  567. // Get the canonical list from LLViewerMedia
  568. LLViewerMedia::impl_list impls = LLViewerMedia::getPriorityList();
  569. LLViewerMedia::impl_list::iterator priority_iter;
  570. U32 enabled_count = 0;
  571. U32 disabled_count = 0;
  572. // iterate over the impl list, creating rows as necessary.
  573. for(priority_iter = impls.begin(); priority_iter != impls.end(); priority_iter++)
  574. {
  575. LLViewerMediaImpl *impl = *priority_iter;
  576. // If we just emptied out the list, every flag needs to be reset.
  577. if(all_items_deleted)
  578. {
  579. impl->setInNearbyMediaList(false);
  580. }
  581. if (!impl->isParcelMedia())
  582. {
  583. LLUUID media_id = impl->getMediaTextureID();
  584. S32 proximity = impl->getProximity();
  585. // This is expensive (i.e. a linear search) -- don't use it here.  We now use mInNearbyMediaList instead.
  586. //S32 index = mMediaList->getItemIndex(media_id);
  587. if (proximity < 0 || !shouldShow(impl))
  588. {
  589. if (impl->getInNearbyMediaList())
  590. {
  591. // There's a row for this impl -- remove it.
  592. removeListItem(media_id);
  593. impl->setInNearbyMediaList(false);
  594. }
  595. }
  596. else
  597. {
  598. if (!impl->getInNearbyMediaList())
  599. {
  600. // We don't have a row for this impl -- add one.
  601. addListItem(media_id);
  602. impl->setInNearbyMediaList(true);
  603. }
  604. }
  605. // Update counts
  606. if (impl->isMediaDisabled())
  607. {
  608. disabled_count++;
  609. }
  610. else {
  611. enabled_count++;
  612. }
  613. }
  614. }
  615. mDisableAllCtrl->setEnabled(LLViewerMedia::isAnyMediaShowing() || 
  616. LLViewerMedia::isParcelMediaPlaying() ||
  617. LLViewerMedia::isParcelAudioPlaying());
  618. mEnableAllCtrl->setEnabled(disabled_count > 0 ||
  619.    // parcel media (if we have it, and it isn't playing, enable "start")
  620.    (LLViewerMedia::hasParcelMedia() && ! LLViewerMedia::isParcelMediaPlaying()) ||
  621.    // parcel audio (if we have it, and it isn't playing, enable "start")
  622.    (LLViewerMedia::hasParcelAudio() && ! LLViewerMedia::isParcelAudioPlaying()));
  623. // Iterate over the rows in the control, updating ones whose impl exists, and deleting ones whose impl has gone away.
  624. std::vector<LLScrollListItem*> items = mMediaList->getAllData();
  625. for (std::vector<LLScrollListItem*>::iterator item_it = items.begin();
  626. item_it != items.end();
  627. ++item_it)
  628. {
  629. LLScrollListItem* item = (*item_it);
  630. LLUUID row_id = item->getUUID();
  631. if (row_id != PARCEL_MEDIA_LIST_ITEM_UUID &&
  632. row_id != PARCEL_AUDIO_LIST_ITEM_UUID)
  633. {
  634. LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(row_id);
  635. if(impl)
  636. {
  637. updateListItem(item, impl);
  638. }
  639. else
  640. {
  641. // This item's impl has been deleted -- remove the row.
  642. // Removing the row won't throw off our iteration, since we have a local copy of the array.
  643. // We just need to make sure we don't access this item after the delete.
  644. removeListItem(row_id);
  645. }
  646. }
  647. }
  648. // Set the selection to whatever media impl the media focus/hover is on. 
  649. // This is an experiment, and can be removed by ifdefing out these 4 lines.
  650. LLUUID media_target = LLViewerMediaFocus::getInstance()->getControlsMediaID();
  651. if(media_target.notNull())
  652. {
  653. mMediaList->selectByID(media_target);
  654. }
  655. }
  656. void LLPanelNearByMedia::updateColumns()
  657. {
  658. if (!mDebugInfoVisible)
  659. {
  660. if (mMediaList->getColumn(CHECKBOX_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(-1);
  661. if (mMediaList->getColumn(VISIBILITY_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(-1);
  662. if (mMediaList->getColumn(PROXIMITY_COLUMN)) mMediaList->getColumn(PROXIMITY_COLUMN)->setWidth(-1);
  663. if (mMediaList->getColumn(CLASS_COLUMN)) mMediaList->getColumn(CLASS_COLUMN)->setWidth(-1);
  664. if (mMediaList->getColumn(DEBUG_COLUMN)) mMediaList->getColumn(DEBUG_COLUMN)->setWidth(-1);
  665. }
  666. else {
  667. if (mMediaList->getColumn(CHECKBOX_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(20);
  668. if (mMediaList->getColumn(VISIBILITY_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(20);
  669. if (mMediaList->getColumn(PROXIMITY_COLUMN)) mMediaList->getColumn(PROXIMITY_COLUMN)->setWidth(30);
  670. if (mMediaList->getColumn(CLASS_COLUMN)) mMediaList->getColumn(CLASS_COLUMN)->setWidth(20);
  671. if (mMediaList->getColumn(DEBUG_COLUMN)) mMediaList->getColumn(DEBUG_COLUMN)->setWidth(200);
  672. }
  673. }
  674. void LLPanelNearByMedia::onClickEnableAll()
  675. {
  676. LLViewerMedia::setAllMediaEnabled(true);
  677. }
  678. void LLPanelNearByMedia::onClickDisableAll()
  679. {
  680. LLViewerMedia::setAllMediaEnabled(false);
  681. }
  682. void LLPanelNearByMedia::onClickEnableParcelMedia()
  683. {
  684. if ( ! LLViewerMedia::isParcelMediaPlaying() )
  685. {
  686. LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
  687. }
  688. }
  689. void LLPanelNearByMedia::onClickDisableParcelMedia()
  690. {
  691. // This actually unloads the impl, as opposed to "stop"ping the media
  692. LLViewerParcelMedia::stop();
  693. }
  694. void LLPanelNearByMedia::onCheckItem(LLUICtrl* ctrl, const LLUUID &row_id)
  695. {
  696. LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
  697. setDisabled(row_id, ! check->getValue());
  698. }
  699. bool LLPanelNearByMedia::setDisabled(const LLUUID &row_id, bool disabled)
  700. {
  701. if (row_id == PARCEL_AUDIO_LIST_ITEM_UUID)
  702. {
  703. if (disabled) onClickParcelAudioStop();
  704. else onClickParcelAudioStart();
  705. return true;
  706. }
  707. else if (row_id == PARCEL_MEDIA_LIST_ITEM_UUID)
  708. {
  709. if (disabled) onClickDisableParcelMedia();
  710. else onClickEnableParcelMedia();
  711. return true;
  712. }
  713. else {
  714. LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(row_id);
  715. if(impl)
  716. {
  717. impl->setDisabled(disabled, true);
  718. return true;
  719. }
  720. }
  721. return false;
  722. }
  723. //static
  724. void LLPanelNearByMedia::onZoomMedia(void* user_data)
  725. {
  726. LLPanelNearByMedia* panelp = (LLPanelNearByMedia*)user_data;
  727. LLUUID media_id = panelp->mMediaList->getValue().asUUID();
  728. LLViewerMediaFocus::getInstance()->focusZoomOnMedia(media_id);
  729. }
  730. void LLPanelNearByMedia::onClickParcelMediaPlay()
  731. {
  732. LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
  733. }
  734. void LLPanelNearByMedia::onClickParcelMediaStop()
  735. {
  736. if (LLViewerParcelMedia::getParcelMedia())
  737. {
  738. // This stops the media playing, as opposed to unloading it like
  739. // LLViewerParcelMedia::stop() does
  740. LLViewerParcelMedia::getParcelMedia()->stop();
  741. }
  742. }
  743. void LLPanelNearByMedia::onClickParcelMediaPause()
  744. {
  745. LLViewerParcelMedia::pause();
  746. }
  747. void LLPanelNearByMedia::onClickParcelAudioStart()
  748. {
  749. // User *explicitly* started the internet stream, so keep the stream
  750. // playing and updated as they cross to other parcels etc.
  751. mParcelAudioAutoStart = true;
  752. if (!gAudiop)
  753. return;
  754. gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
  755. }
  756. void LLPanelNearByMedia::onClickParcelAudioPlay()
  757. {
  758. // User *explicitly* started the internet stream, so keep the stream
  759. // playing and updated as they cross to other parcels etc.
  760. mParcelAudioAutoStart = true;
  761. if (!gAudiop)
  762. return;
  763. if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying())
  764. {
  765. // 'false' means unpause
  766. gAudiop->pauseInternetStream(false);
  767. }
  768. else {
  769. gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
  770. }
  771. }
  772. void LLPanelNearByMedia::onClickParcelAudioStop()
  773. {
  774. // User *explicitly* stopped the internet stream, so don't
  775. // re-start audio when i.e. they move to another parcel, until
  776. // they explicitly start it again.
  777. mParcelAudioAutoStart = false;
  778. if (!gAudiop)
  779. return;
  780. gAudiop->stopInternetStream();
  781. }
  782. void LLPanelNearByMedia::onClickParcelAudioPause()
  783. {
  784. if (!gAudiop)
  785. return;
  786. // 'true' means pause
  787. gAudiop->pauseInternetStream(true);
  788. }
  789. bool LLPanelNearByMedia::shouldShow(LLViewerMediaImpl* impl)
  790. {
  791. const LLSD &choice_llsd = mShowCtrl->getSelectedValue();
  792. MediaClass choice = (MediaClass)choice_llsd.asInteger();
  793. switch (choice)
  794. {
  795. case MEDIA_CLASS_ALL:
  796. return true;
  797. break;
  798. case MEDIA_CLASS_WITHIN_PARCEL:
  799. return impl->isInAgentParcel();
  800. break;
  801. case MEDIA_CLASS_OUTSIDE_PARCEL:
  802. return ! impl->isInAgentParcel();
  803. break;
  804. case MEDIA_CLASS_ON_OTHERS:
  805. return impl->isAttachedToAnotherAvatar();
  806. break;
  807. default:
  808. break;
  809. }
  810. return true;
  811. }
  812. void LLPanelNearByMedia::onAdvancedButtonClick()
  813. {
  814. // bring up the prefs floater
  815. LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*>(LLFloaterReg::showInstance("preferences"));
  816. if (prefsfloater)
  817. {
  818. // grab the 'audio' panel from the preferences floater and
  819. // bring it the front!
  820. LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core");
  821. LLPanel* audiopanel = prefsfloater->getChild<LLPanel>("audio");
  822. if (tabcontainer && audiopanel)
  823. {
  824. tabcontainer->selectTabPanel(audiopanel);
  825. }
  826. }
  827. }
  828. void LLPanelNearByMedia::onMoreLess()
  829. {
  830. bool is_more = getChild<LLUICtrl>("more_less_btn")->getValue();
  831. mNearbyMediaPanel->setVisible(is_more);
  832. // enable resizing when expanded
  833. getChildView("resizebar_bottom")->setEnabled(is_more);
  834. LLRect new_rect = is_more ? mMoreRect : mLessRect;
  835. new_rect.translate(getRect().mRight - new_rect.mRight, getRect().mTop - new_rect.mTop);
  836. setShape(new_rect);
  837. }
  838. void LLPanelNearByMedia::updateControls()
  839. {
  840. LLUUID selected_media_id = mMediaList->getValue().asUUID();
  841. if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
  842. {
  843. showTimeBasedControls(LLViewerMedia::isParcelAudioPlaying(),
  844.   false, // include_zoom
  845.   false, // is_zoomed
  846.   gSavedSettings.getBOOL("MuteMusic"), 
  847.   gSavedSettings.getF32("AudioLevelMusic") );
  848. }
  849. else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
  850. {
  851. if (!LLViewerMedia::hasParcelMedia())
  852. {
  853. // Shouldn't happen, but do this anyway
  854. showDisabledControls();
  855. }
  856. else {
  857. LLViewerMediaImpl* impl = LLViewerParcelMedia::getParcelMedia();
  858. if (NULL == impl)
  859. {
  860. // Just means it hasn't started yet
  861. showBasicControls(false, false, false);
  862. }
  863. else if (impl->isMediaTimeBased())
  864. {
  865. showTimeBasedControls(impl->isMediaPlaying(), 
  866.   false, // include_zoom
  867.   false, // is_zoomed
  868.   impl->getVolume() == 0.0,
  869.   impl->getVolume() );
  870. }
  871. else {
  872. // non-time-based parcel media
  873. showBasicControls(LLViewerMedia::isParcelMediaPlaying(), false, false);
  874. }
  875. }
  876. }
  877. else {
  878. LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
  879. if (NULL == impl)
  880. {
  881. showDisabledControls();
  882. }
  883. else {
  884. if (impl->isMediaTimeBased())
  885. {
  886. showTimeBasedControls(impl->isMediaPlaying(), 
  887.   ! impl->isParcelMedia(),  // include_zoom
  888.   LLViewerMediaFocus::getInstance()->isZoomed(),
  889.   impl->getVolume() == 0.0,
  890.   impl->getVolume());
  891. }
  892. else {
  893. showBasicControls(!impl->isMediaDisabled(), 
  894.   ! impl->isParcelMedia(),  // include_zoom
  895.   LLViewerMediaFocus::getInstance()->isZoomed());
  896. }
  897. }
  898. }
  899. }
  900. void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed)
  901. {
  902. mStopCtrl->setVisible(playing);
  903. mPlayCtrl->setVisible(!playing);
  904. mPauseCtrl->setVisible(false);
  905. mMuteCtrl->setVisible(false);
  906. mVolumeSliderCtrl->setVisible(false);
  907. mZoomCtrl->setVisible(include_zoom && !is_zoomed);
  908. mUnzoomCtrl->setVisible(include_zoom && is_zoomed);
  909. mStopCtrl->setEnabled(true);
  910. mZoomCtrl->setEnabled(true);
  911. }
  912. void LLPanelNearByMedia::showTimeBasedControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume)
  913. {
  914. mStopCtrl->setVisible(true);
  915. mPlayCtrl->setVisible(!playing);
  916. mPauseCtrl->setVisible(playing);
  917. mMuteCtrl->setVisible(true);
  918. mVolumeSliderCtrl->setVisible(true);
  919. mZoomCtrl->setVisible(include_zoom);
  920. mZoomCtrl->setVisible(include_zoom && !is_zoomed);
  921. mUnzoomCtrl->setVisible(include_zoom && is_zoomed);
  922. mStopCtrl->setEnabled(true);
  923. mZoomCtrl->setEnabled(true);
  924. mMuteBtn->setValue(muted);
  925. mVolumeSlider->setValue(volume);
  926. }
  927. void LLPanelNearByMedia::showDisabledControls()
  928. {
  929. mStopCtrl->setVisible(true);
  930. mPlayCtrl->setVisible(false);
  931. mPauseCtrl->setVisible(false);
  932. mMuteCtrl->setVisible(false);
  933. mVolumeSliderCtrl->setVisible(false);
  934. mZoomCtrl->setVisible(true);
  935. mUnzoomCtrl->setVisible(false);
  936. mStopCtrl->setEnabled(false);
  937. mZoomCtrl->setEnabled(false);
  938. }
  939. void LLPanelNearByMedia::onClickSelectedMediaStop()
  940. {
  941. setDisabled(mMediaList->getValue().asUUID(), true);
  942. }
  943. void LLPanelNearByMedia::onClickSelectedMediaPlay()
  944. {
  945. LLUUID selected_media_id = mMediaList->getValue().asUUID();
  946. // First enable it
  947. setDisabled(selected_media_id, false);
  948. // Special code to make play "unpause" if time-based and playing
  949. if (selected_media_id != PARCEL_AUDIO_LIST_ITEM_UUID)
  950. {
  951. LLViewerMediaImpl *impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
  952. ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
  953. if (NULL != impl && impl->isMediaTimeBased() && impl->isMediaPaused())
  954. {
  955. // Aha!  It's really time-based media that's paused, so unpause
  956. impl->play();
  957. return;
  958. }
  959. else if (impl->isParcelMedia())
  960. {
  961. LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
  962. }
  963. }
  964. }
  965. void LLPanelNearByMedia::onClickSelectedMediaPause()
  966. {
  967. LLUUID selected_media_id = mMediaList->getValue().asUUID();
  968. if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
  969. {
  970. onClickParcelAudioPause();
  971. }
  972. else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) 
  973. {
  974. onClickParcelMediaPause();
  975. }
  976. else {
  977. LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
  978. if (NULL != impl && impl->isMediaTimeBased() && impl->isMediaPlaying())
  979. {
  980. impl->pause();
  981. }
  982. }
  983. }
  984. void LLPanelNearByMedia::onClickSelectedMediaMute()
  985. {
  986. LLUUID selected_media_id = mMediaList->getValue().asUUID();
  987. if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
  988. {
  989. gSavedSettings.setBOOL("MuteMusic", mMuteBtn->getValue());
  990. }
  991. else {
  992. LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
  993. ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
  994. if (NULL != impl && impl->isMediaTimeBased())
  995. {
  996. F32 volume = impl->getVolume();
  997. if(volume > 0.0)
  998. {
  999. impl->setVolume(0.0);
  1000. }
  1001. else if (mVolumeSlider->getValueF32() == 0.0)
  1002. {
  1003. impl->setVolume(1.0);
  1004. mVolumeSlider->setValue(1.0);
  1005. }
  1006. else 
  1007. {
  1008. impl->setVolume(mVolumeSlider->getValueF32());
  1009. }
  1010. }
  1011. }
  1012. }
  1013. void LLPanelNearByMedia::onCommitSelectedMediaVolume()
  1014. {
  1015. LLUUID selected_media_id = mMediaList->getValue().asUUID();
  1016. if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
  1017. {
  1018. F32 vol = mVolumeSlider->getValueF32();
  1019. gSavedSettings.setF32("AudioLevelMusic", vol);
  1020. }
  1021. else {
  1022. LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
  1023. ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
  1024. if (NULL != impl && impl->isMediaTimeBased())
  1025. {
  1026. impl->setVolume(mVolumeSlider->getValueF32());
  1027. }
  1028. }
  1029. }
  1030. void LLPanelNearByMedia::onClickSelectedMediaZoom()
  1031. {
  1032. LLUUID selected_media_id = mMediaList->getValue().asUUID();
  1033. if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID || selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
  1034. return;
  1035. LLViewerMediaFocus::getInstance()->focusZoomOnMedia(selected_media_id);
  1036. }
  1037. void LLPanelNearByMedia::onClickSelectedMediaUnzoom()
  1038. {
  1039. LLViewerMediaFocus::getInstance()->unZoom();
  1040. }
  1041. // static
  1042. void LLPanelNearByMedia::getNameAndUrlHelper(LLViewerMediaImpl* impl, std::string& name, std::string & url, const std::string &defaultName)
  1043. {
  1044. if (NULL == impl) return;
  1045. name = impl->getName();
  1046. url = impl->getCurrentMediaURL(); // This is the URL the media impl actually has loaded
  1047. if (url.empty())
  1048. {
  1049. url = impl->getMediaEntryURL(); // This is the current URL from the media data
  1050. }
  1051. if (url.empty())
  1052. {
  1053. url = impl->getHomeURL(); // This is the home URL from the media data
  1054. }
  1055. if (name.empty())
  1056. {
  1057. name = url;
  1058. }
  1059. if (name.empty())
  1060. {
  1061. name = defaultName;
  1062. }
  1063. }