summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorRick Pasetto <rick@lindenlab.com>2010-02-16 15:54:32 -0800
committerRick Pasetto <rick@lindenlab.com>2010-02-16 15:54:32 -0800
commit204ff1edd9139b253e2f2b32fa75c04a737d77bf (patch)
tree7d441a50b18872c6a0e32c91f0a1ca147dc32b29 /indra/newview
parent1513643e62a88531888f330e57aa1eb623061729 (diff)
parent4dfed6e353ff880fcd45b4c8b402bf0f5a2f19f2 (diff)
Automated merge with ssh://rick@hg.lindenlab.com/viewer/viewer-2-0
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/settings.xml44
-rw-r--r--indra/newview/llpanelnearbymedia.cpp1180
-rw-r--r--indra/newview/llpanelnearbymedia.h185
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp6
-rw-r--r--indra/newview/llpanelprimmediacontrols.h17
-rw-r--r--indra/newview/llpanelvolumepulldown.cpp5
-rw-r--r--indra/newview/llrootview.h1
-rw-r--r--indra/newview/llstatusbar.cpp140
-rw-r--r--indra/newview/llstatusbar.h11
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp274
-rw-r--r--indra/newview/llviewermedia.h134
-rw-r--r--indra/newview/llviewermediafocus.cpp13
-rw-r--r--indra/newview/llviewermediafocus.h3
-rw-r--r--indra/newview/llviewerparcelmgr.cpp13
-rw-r--r--indra/newview/llviewerwindow.cpp1
-rw-r--r--indra/newview/skins/default/textures/windows/Flyout_Pointer_Up.pngbin0 -> 260 bytes
-rw-r--r--indra/newview/skins/default/xui/en/main_view.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_media.xml476
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml22
22 files changed, 2414 insertions, 131 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b74530e49a..6634fe5379 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -183,7 +183,6 @@ set(viewer_SOURCE_FILES
llfloatermediasettings.cpp
llfloatermemleak.cpp
llfloaternamedesc.cpp
- llfloaternearbymedia.cpp
llfloaternotificationsconsole.cpp
llfloateropenobject.cpp
llfloaterparcel.cpp
@@ -323,6 +322,7 @@ set(viewer_SOURCE_FILES
llpanelmediasettingspermissions.cpp
llpanelmediasettingssecurity.cpp
llpanelme.cpp
+ llpanelnearbymedia.cpp
llpanelobject.cpp
llpanelobjectinventory.cpp
llpaneloutfitsinventory.cpp
@@ -683,7 +683,6 @@ set(viewer_HEADER_FILES
llfloatermediasettings.h
llfloatermemleak.h
llfloaternamedesc.h
- llfloaternearbymedia.h
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
@@ -818,6 +817,7 @@ set(viewer_HEADER_FILES
llpanelmediasettingspermissions.h
llpanelmediasettingssecurity.h
llpanelme.h
+ llpanelnearbymedia.h
llpanelobject.h
llpanelobjectinventory.h
llpaneloutfitsinventory.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c0cf8ec1ad..e962ea1815 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4578,6 +4578,50 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>MediaShowOnOthers</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not to show media on other avatars</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MediaShowOutsideParcel</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not to show media from outside the current parcel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>MediaShowWithinParcel</key>
+ <map>
+ <key>Comment</key>
+ <string>Whether or not to show media within the current parcel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MediaTentativeAutoPlay</key>
+ <map>
+ <key>Comment</key>
+ <string>This is a tentative flag that may be temporarily set off by the user, until she teleports</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>MemoryLogFrequency</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
new file mode 100644
index 0000000000..6a88c916d7
--- /dev/null
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -0,0 +1,1180 @@
+/**
+ * @file llpanelnearbymedia.cpp
+ * @brief Management interface for muting and controlling nearby media
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelnearbymedia.h"
+
+#include "llaudioengine.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llresizebar.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llscrolllistcell.h"
+#include "llslider.h"
+#include "llsliderctrl.h"
+#include "llagent.h"
+#include "llagentui.h"
+#include "llbutton.h"
+#include "lltextbox.h"
+#include "llviewermedia.h"
+#include "llviewerparcelmedia.h"
+#include "llviewerregion.h"
+#include "llviewermediafocus.h"
+#include "llviewerparcelmgr.h"
+#include "llparcel.h"
+#include "llpluginclassmedia.h"
+#include "llvovolume.h"
+#include "llstatusbar.h"
+#include "llsdutil.h"
+
+#include "llfloaterreg.h"
+#include "llfloaterpreference.h" // for the gear icon
+#include "lltabcontainer.h"
+
+#include <stringize.h>
+
+extern LLControlGroup gSavedSettings;
+
+static const LLUUID PARCEL_MEDIA_LIST_ITEM_UUID = LLUUID("CAB5920F-E484-4233-8621-384CF373A321");
+static const LLUUID PARCEL_AUDIO_LIST_ITEM_UUID = LLUUID("DF4B020D-8A24-4B95-AB5D-CA970D694822");
+
+//
+// LLPanelNearByMedia
+//
+
+LLPanelNearByMedia::LLPanelNearByMedia()
+: mMediaList(NULL),
+ mEnableAllCtrl(NULL),
+ mAllMediaDisabled(false),
+ mDebugInfoVisible(false),
+ mParcelMediaItem(NULL),
+ mParcelAudioItem(NULL)
+{
+ mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+ gSavedSettings.getBOOL("MediaTentativeAutoPlay");
+
+ mCommitCallbackRegistrar.add("MediaListCtrl.EnableAll", boost::bind(&LLPanelNearByMedia::onClickEnableAll, this));
+ mCommitCallbackRegistrar.add("MediaListCtrl.DisableAll", boost::bind(&LLPanelNearByMedia::onClickDisableAll, this));
+ mCommitCallbackRegistrar.add("MediaListCtrl.GoMediaPrefs", boost::bind(&LLPanelNearByMedia::onAdvancedButtonClick, this));
+ mCommitCallbackRegistrar.add("MediaListCtrl.MoreLess", boost::bind(&LLPanelNearByMedia::onMoreLess, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Stop", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaStop, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Play", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaPlay, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Pause", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaPause, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Mute", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaMute, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Volume", boost::bind(&LLPanelNearByMedia::onCommitSelectedMediaVolume, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Zoom", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaZoom, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Unzoom", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaUnzoom, this));
+
+ LLUICtrlFactory::instance().buildPanel(this, "panel_nearby_media.xml");
+}
+
+LLPanelNearByMedia::~LLPanelNearByMedia()
+{
+}
+
+BOOL LLPanelNearByMedia::postBuild()
+{
+ LLPanel::postBuild();
+
+ const S32 RESIZE_BAR_THICKNESS = 6;
+ LLResizeBar::Params p;
+ p.rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0);
+ p.name = "resizebar_bottom";
+ p.min_size = getRect().getHeight();
+ p.side = LLResizeBar::BOTTOM;
+ p.resizing_view = this;
+ addChild( LLUICtrlFactory::create<LLResizeBar>(p) );
+
+ mNearbyMediaPanel = getChild<LLUICtrl>("nearby_media_panel");
+ mMediaList = getChild<LLScrollListCtrl>("media_list");
+ mEnableAllCtrl = getChild<LLUICtrl>("all_nearby_media_enable_btn");
+ mDisableAllCtrl = getChild<LLUICtrl>("all_nearby_media_disable_btn");
+ mItemCountText = getChild<LLTextBox>("media_item_count");
+ mShowCtrl = getChild<LLComboBox>("show_combo");
+
+ // Dynamic (selection-dependent) controls
+ mStopCtrl = getChild<LLUICtrl>("stop");
+ mPlayCtrl = getChild<LLUICtrl>("play");
+ mPauseCtrl = getChild<LLUICtrl>("pause");
+ mMuteCtrl = getChild<LLUICtrl>("mute");
+ mVolumeSliderCtrl = getChild<LLUICtrl>("volume_slider_ctrl");
+ mZoomCtrl = getChild<LLUICtrl>("zoom");
+ mUnzoomCtrl = getChild<LLUICtrl>("unzoom");
+ mVolumeSlider = getChild<LLSlider>("volume_slider");
+ mMuteBtn = getChild<LLButton>("mute_btn");
+
+ mEmptyNameString = getString("empty_item_text");
+ mParcelMediaName = getString("parcel_media_name");
+ mParcelAudioName = getString("parcel_audio_name");
+ mPlayingString = getString("playing_suffix");
+
+ mMediaList->setDoubleClickCallback(onZoomMedia, this);
+ mMediaList->sortByColumnIndex(PROXIMITY_COLUMN, TRUE);
+ mMediaList->sortByColumnIndex(VISIBILITY_COLUMN, FALSE);
+
+ refreshList();
+ updateControls();
+ updateColumns();
+
+ LLView* minimized_controls = getChildView("minimized_controls");
+ mMoreHeight = getRect().getHeight();
+ mLessHeight = getRect().getHeight() - minimized_controls->getRect().mBottom;
+ getChild<LLUICtrl>("more_less_btn")->setValue(false);
+ onMoreLess();
+
+ return TRUE;
+}
+
+/*virtual*/
+void LLPanelNearByMedia::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ mHoverTimer.stop();
+ LLPanel::onMouseEnter(x,y,mask);
+}
+
+
+/*virtual*/
+void LLPanelNearByMedia::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ mHoverTimer.start();
+ LLPanel::onMouseLeave(x,y,mask);
+}
+
+/*virtual*/
+void LLPanelNearByMedia::handleVisibilityChange ( BOOL new_visibility )
+{
+ if (new_visibility)
+ {
+ mHoverTimer.start(); // timer will be stopped when mouse hovers over panel
+ //gFocusMgr.setTopCtrl(this);
+ }
+ else
+ {
+ mHoverTimer.stop();
+ //if (gFocusMgr.getTopCtrl() == this)
+ //{
+ // gFocusMgr.setTopCtrl(NULL);
+ //}
+ }
+}
+
+/*virtual*/
+void LLPanelNearByMedia::onTopLost ()
+{
+ //LLUICtrl* new_top = gFocusMgr.getTopCtrl();
+ //if (!new_top || !new_top->hasAncestor(this))
+ //{
+ // setVisible(FALSE);
+ //}
+}
+
+/*virtual*/
+void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+ LLPanel::reshape(width, height, called_from_parent);
+
+ LLButton* more_less_btn = getChild<LLButton>("more_less_btn");
+ if (more_less_btn->getValue().asBoolean())
+ {
+ mMoreHeight = getRect().getHeight();
+ }
+
+}
+
+const F32 AUTO_CLOSE_FADE_TIME_START= 4.0f;
+const F32 AUTO_CLOSE_FADE_TIME_END = 5.0f;
+
+void LLPanelNearByMedia::draw()
+{
+ //LLUICtrl* new_top = gFocusMgr.getTopCtrl();
+ //if (new_top != this)
+ //{
+ // // reassert top ctrl
+ // gFocusMgr.setTopCtrl(this);
+ //}
+
+ // keep bottom of panel on screen
+ LLRect screen_rect = calcScreenRect();
+ if (screen_rect.mBottom < 0)
+ {
+ LLRect new_rect = getRect();
+ new_rect.mBottom += 0 - screen_rect.mBottom;
+ setShape(new_rect);
+ }
+
+ mItemCountText->setValue(llformat(getString("media_item_count_format").c_str(), mMediaList->getItemCount()));
+
+ refreshList();
+ updateControls();
+
+ F32 alpha = mHoverTimer.getStarted()
+ ? clamp_rescale(mHoverTimer.getElapsedTimeF32(), AUTO_CLOSE_FADE_TIME_START, AUTO_CLOSE_FADE_TIME_END, 1.f, 0.f)
+ : 1.0f;
+ LLViewDrawContext context(alpha);
+
+ LLPanel::draw();
+
+ if (alpha == 0.f)
+ {
+ setVisible(false);
+ }
+}
+
+bool LLPanelNearByMedia::getParcelAudioAutoStart()
+{
+ return mParcelAudioAutoStart;
+}
+
+LLScrollListItem* LLPanelNearByMedia::addListItem(const LLUUID &id)
+{
+ if (NULL == mMediaList) return NULL;
+
+ // Just set up the columns -- the values will be filled in by updateListItem().
+
+ LLSD row;
+ row["id"] = id;
+
+ LLSD &columns = row["columns"];
+
+ columns[CHECKBOX_COLUMN]["column"] = "media_checkbox_ctrl";
+ columns[CHECKBOX_COLUMN]["type"] = "checkbox";
+ //if(mDebugInfoVisible)
+ {
+ columns[PROXIMITY_COLUMN]["column"] = "media_proximity";
+ columns[PROXIMITY_COLUMN]["value"] = "";
+ columns[VISIBILITY_COLUMN]["column"] = "media_visibility";
+ columns[VISIBILITY_COLUMN]["value"] = "";
+ columns[CLASS_COLUMN]["column"] = "media_class";
+ columns[CLASS_COLUMN]["type"] = "text";
+ columns[CLASS_COLUMN]["value"] = "";
+ }
+ columns[NAME_COLUMN]["column"] = "media_name";
+ columns[NAME_COLUMN]["type"] = "text";
+ columns[NAME_COLUMN]["value"] = "";
+ //if(mDebugInfoVisible)
+ {
+ columns[DEBUG_COLUMN]["column"] = "media_debug";
+ columns[DEBUG_COLUMN]["type"] = "text";
+ columns[DEBUG_COLUMN]["value"] = "";
+ }
+
+ LLScrollListItem* new_item = mMediaList->addElement(row);
+ if (NULL != new_item)
+ {
+ LLScrollListCheck* scroll_list_check = dynamic_cast<LLScrollListCheck*>(new_item->getColumn(CHECKBOX_COLUMN));
+ if (scroll_list_check)
+ {
+ LLCheckBoxCtrl *check = scroll_list_check->getCheckBox();
+ check->setCommitCallback(boost::bind(&LLPanelNearByMedia::onCheckItem, this, _1, id));
+ }
+ }
+ return new_item;
+}
+
+void LLPanelNearByMedia::updateListItem(LLScrollListItem* item, LLViewerMediaImpl* impl)
+{
+ std::string item_name;
+ std::string item_tooltip;
+ std::string debug_str;
+ LLPanelNearByMedia::MediaClass media_class = MEDIA_CLASS_ALL;
+
+ getNameAndUrlHelper(impl, item_name, item_tooltip, mEmptyNameString);
+ // Focused
+ if (impl->hasFocus())
+ {
+ media_class = MEDIA_CLASS_FOCUSED;
+ }
+ // Is attached to another avatar?
+ else if (impl->isAttachedToAnotherAvatar())
+ {
+ media_class = MEDIA_CLASS_ON_OTHERS;
+ }
+ // Outside agent parcel
+ else if (!impl->isInAgentParcel())
+ {
+ media_class = MEDIA_CLASS_OUTSIDE_PARCEL;
+ }
+ else {
+ // inside parcel
+ media_class = MEDIA_CLASS_WITHIN_PARCEL;
+ }
+
+ if(mDebugInfoVisible)
+ {
+ debug_str += llformat("%g/", (float)impl->getInterest());
+
+ // proximity distance is actually distance squared -- display it as straight distance.
+ debug_str += llformat("%g/", fsqrtf(impl->getProximityDistance()));
+
+ // s += llformat("%g/", (float)impl->getCPUUsage());
+ // s += llformat("%g/", (float)impl->getApproximateTextureInterest());
+ debug_str += llformat("%g/", (float)(NULL == impl->getSomeObject()) ? 0.0 : impl->getSomeObject()->getPixelArea());
+
+ debug_str += LLPluginClassMedia::priorityToString(impl->getPriority());
+
+ if(impl->hasMedia())
+ {
+ debug_str += '@';
+ }
+ else if(impl->isPlayable())
+ {
+ debug_str += '+';
+ }
+ else if(impl->isForcedUnloaded())
+ {
+ debug_str += '!';
+ }
+ }
+
+ updateListItem(item,
+ item_name,
+ item_tooltip,
+ impl->getProximity(),
+ impl->isMediaDisabled(),
+ impl->hasMedia(),
+ impl->isMediaTimeBased() && impl->isMediaPlaying(),
+ media_class,
+ debug_str);
+}
+
+void LLPanelNearByMedia::updateListItem(LLScrollListItem* item,
+ const std::string &item_name,
+ const std::string &item_tooltip,
+ S32 proximity,
+ bool is_disabled,
+ bool has_media,
+ bool is_time_based_and_playing,
+ LLPanelNearByMedia::MediaClass media_class,
+ const std::string &debug_str)
+{
+ LLScrollListCell* cell = item->getColumn(PROXIMITY_COLUMN);
+ if(cell)
+ {
+ // since we are forced to sort by text, encode sort order as string
+ std::string proximity_string = STRINGIZE(proximity);
+ std::string old_proximity_string = cell->getValue().asString();
+ if(proximity_string != old_proximity_string)
+ {
+ cell->setValue(proximity_string);
+ mMediaList->setNeedsSort(true);
+ }
+ }
+
+ cell = item->getColumn(CHECKBOX_COLUMN);
+ if(cell)
+ {
+ cell->setValue(!is_disabled);
+ }
+
+ cell = item->getColumn(VISIBILITY_COLUMN);
+ if(cell)
+ {
+ S32 old_visibility = cell->getValue();
+ // *HACK ALERT: force ordering of Media before Audio before the rest of the list
+ S32 new_visibility =
+ item->getUUID() == PARCEL_MEDIA_LIST_ITEM_UUID ? 3
+ : item->getUUID() == PARCEL_AUDIO_LIST_ITEM_UUID ? 2
+ : (has_media) ? 1
+ : ((is_disabled) ? 0
+ : -1);
+ cell->setValue(STRINGIZE(new_visibility));
+ if (new_visibility != old_visibility)
+ {
+ mMediaList->setNeedsSort(true);
+ }
+ }
+
+ cell = item->getColumn(NAME_COLUMN);
+ if(cell)
+ {
+ std::string name = item_name;
+ std::string old_name = cell->getValue().asString();
+ if (has_media)
+ {
+ name += " " + mPlayingString;
+ }
+ if (name != old_name)
+ {
+ cell->setValue(name);
+ }
+ cell->setToolTip(item_tooltip);
+
+ // *TODO: Make these font styles/colors configurable via XUI
+ U8 font_style = LLFontGL::NORMAL;
+ LLColor4 cell_color = LLColor4::white;
+
+ // Only colorize by class in debug
+ if (mDebugInfoVisible)
+ {
+ switch (media_class) {
+ case MEDIA_CLASS_FOCUSED:
+ cell_color = LLColor4::yellow;
+ break;
+ case MEDIA_CLASS_ON_OTHERS:
+ cell_color = LLColor4::red;
+ break;
+ case MEDIA_CLASS_OUTSIDE_PARCEL:
+ cell_color = LLColor4::orange;
+ break;
+ case MEDIA_CLASS_WITHIN_PARCEL:
+ default:
+ break;
+ }
+ }
+ if (is_disabled)
+ {
+ if (mDebugInfoVisible)
+ {
+ font_style |= LLFontGL::ITALIC;
+ cell_color = LLColor4::black;
+ }
+ else {
+ // Dim it if it is disabled
+ cell_color.setAlpha(0.25);
+ }
+ }
+ // Dim it if it isn't "showing"
+ else if (!has_media)
+ {
+ cell_color.setAlpha(0.25);
+ }
+ // Bold it if it is time-based media and it is playing
+ else if (is_time_based_and_playing)
+ {
+ if (mDebugInfoVisible) font_style |= LLFontGL::BOLD;
+ }
+ cell->setColor(cell_color);
+ LLScrollListText *text_cell = dynamic_cast<LLScrollListText*> (cell);
+ if (text_cell)
+ {
+ text_cell->setFontStyle(font_style);
+ }
+ }
+
+ cell = item->getColumn(CLASS_COLUMN);
+ if(cell)
+ {
+ // TODO: clean this up!
+ cell->setValue(STRINGIZE(media_class));
+ }
+
+ if(mDebugInfoVisible)
+ {
+ cell = item->getColumn(DEBUG_COLUMN);
+ if(cell)
+ {
+ cell->setValue(debug_str);
+ }
+ }
+}
+
+void LLPanelNearByMedia::removeListItem(const LLUUID &id)
+{
+ if (NULL == mMediaList) return;
+
+ mMediaList->deleteSingleItem(mMediaList->getItemIndex(id));
+}
+
+void LLPanelNearByMedia::refreshParcelItems()
+{
+ //
+ // First add/remove the "fake" items Parcel Media and Parcel Audio.
+ // These items will have special UUIDs
+ // PARCEL_MEDIA_LIST_ITEM_UUID
+ // PARCEL_AUDIO_LIST_ITEM_UUID
+ //
+ // Get the filter choice.
+ const LLSD &choice_llsd = mShowCtrl->getSelectedValue();
+ MediaClass choice = (MediaClass)choice_llsd.asInteger();
+ // Only show "special parcel items" if "All" or "Within" filter
+ bool should_include = choice == MEDIA_CLASS_ALL || choice == MEDIA_CLASS_WITHIN_PARCEL;
+
+ // First Parcel Media: add or remove it as necessary
+ if (should_include && LLViewerMedia::hasParcelMedia())
+ {
+ // Yes, there is parcel media.
+ if (NULL == mParcelMediaItem)
+ {
+ mParcelMediaItem = addListItem(PARCEL_MEDIA_LIST_ITEM_UUID);
+ mMediaList->setNeedsSort(true);
+ }
+ }
+ else {
+ if (NULL != mParcelMediaItem) {
+ removeListItem(PARCEL_MEDIA_LIST_ITEM_UUID);
+ mParcelMediaItem = NULL;
+ mMediaList->setNeedsSort(true);
+ }
+ }
+
+ // ... then update it
+ if (NULL != mParcelMediaItem)
+ {
+ std::string name, url, tooltip;
+ getNameAndUrlHelper(LLViewerParcelMedia::getParcelMedia(), name, url, "");
+ if (name.empty() || name == url)
+ {
+ tooltip = url;
+ }
+ else {
+ tooltip = name + " : " + url;
+ }
+ LLViewerMediaImpl *impl = LLViewerParcelMedia::getParcelMedia();
+ updateListItem(mParcelMediaItem,
+ mParcelMediaName,
+ tooltip,
+ -2, // Proximity closer than anything else, before Parcel Audio
+ impl == NULL || impl->isMediaDisabled(),
+ impl != NULL && !LLViewerParcelMedia::getURL().empty(),
+ impl != NULL && impl->isMediaTimeBased() && impl->isMediaPlaying(),
+ MEDIA_CLASS_ALL,
+ "parcel media");
+ }
+
+ // Next Parcel Audio: add or remove it as necessary
+ if (should_include && LLViewerMedia::hasParcelAudio())
+ {
+ // Yes, there is parcel audio.
+ if (NULL == mParcelAudioItem)
+ {
+ mParcelAudioItem = addListItem(PARCEL_AUDIO_LIST_ITEM_UUID);
+ mMediaList->setNeedsSort(true);
+ }
+ }
+ else {
+ if (NULL != mParcelAudioItem) {
+ removeListItem(PARCEL_AUDIO_LIST_ITEM_UUID);
+ mParcelAudioItem = NULL;
+ mMediaList->setNeedsSort(true);
+ }
+ }
+
+ // ... then update it
+ if (NULL != mParcelAudioItem)
+ {
+ bool is_playing = LLViewerMedia::isParcelAudioPlaying();
+ updateListItem(mParcelAudioItem,
+ mParcelAudioName,
+ LLViewerMedia::getParcelAudioURL(),
+ -1, // Proximity after Parcel Media, but closer than anything else
+ !is_playing,
+ is_playing,
+ is_playing,
+ MEDIA_CLASS_ALL,
+ "parcel audio");
+ }
+}
+
+void LLPanelNearByMedia::refreshList()
+{
+ bool all_items_deleted = false;
+
+ if(!mMediaList)
+ {
+ // None of this makes any sense if the media list isn't there.
+ return;
+ }
+
+ // Check whether the debug column has been shown/hidden.
+ bool debug_info_visible = gSavedSettings.getBOOL("MediaPerformanceManagerDebug");
+ if(debug_info_visible != mDebugInfoVisible)
+ {
+ mDebugInfoVisible = debug_info_visible;
+
+ // Clear all items so the list gets regenerated.
+ mMediaList->deleteAllItems();
+ all_items_deleted = true;
+
+ updateColumns();
+ }
+
+ refreshParcelItems();
+
+ // Get the canonical list from LLViewerMedia
+ LLViewerMedia::impl_list impls = LLViewerMedia::getPriorityList();
+ LLViewerMedia::impl_list::iterator priority_iter;
+
+ U32 enabled_count = 0;
+ U32 disabled_count = 0;
+
+ // iterate over the impl list, creating rows as necessary.
+ for(priority_iter = impls.begin(); priority_iter != impls.end(); priority_iter++)
+ {
+ LLViewerMediaImpl *impl = *priority_iter;
+
+ // If we just emptied out the list, every flag needs to be reset.
+ if(all_items_deleted)
+ {
+ impl->setInNearbyMediaList(false);
+ }
+
+ if (!impl->isParcelMedia())
+ {
+ LLUUID media_id = impl->getMediaTextureID();
+ S32 proximity = impl->getProximity();
+ // This is expensive (i.e. a linear search) -- don't use it here. We now use mInNearbyMediaList instead.
+ //S32 index = mMediaList->getItemIndex(media_id);
+ if (proximity < 0 || !shouldShow(impl))
+ {
+ if (impl->getInNearbyMediaList())
+ {
+ // There's a row for this impl -- remove it.
+ removeListItem(media_id);
+ impl->setInNearbyMediaList(false);
+ }
+ }
+ else
+ {
+ if (!impl->getInNearbyMediaList())
+ {
+ // We don't have a row for this impl -- add one.
+ addListItem(media_id);
+ impl->setInNearbyMediaList(true);
+ }
+ }
+ // Update counts
+ if (impl->isMediaDisabled())
+ {
+ disabled_count++;
+ }
+ else {
+ enabled_count++;
+ }
+ }
+ }
+ mDisableAllCtrl->setEnabled(LLViewerMedia::isAnyMediaShowing() ||
+ LLViewerMedia::isParcelMediaPlaying() ||
+ LLViewerMedia::isParcelAudioPlaying());
+ mEnableAllCtrl->setEnabled(disabled_count > 0 ||
+ // parcel media (if we have it, and it isn't playing, enable "start")
+ (LLViewerMedia::hasParcelMedia() && ! LLViewerMedia::isParcelMediaPlaying()) ||
+ // parcel audio (if we have it, and it isn't playing, enable "start")
+ (LLViewerMedia::hasParcelAudio() && ! LLViewerMedia::isParcelAudioPlaying()));
+
+ // Iterate over the rows in the control, updating ones whose impl exists, and deleting ones whose impl has gone away.
+ std::vector<LLScrollListItem*> items = mMediaList->getAllData();
+
+ for (std::vector<LLScrollListItem*>::iterator item_it = items.begin();
+ item_it != items.end();
+ ++item_it)
+ {
+ LLScrollListItem* item = (*item_it);
+ LLUUID row_id = item->getUUID();
+
+ if (row_id != PARCEL_MEDIA_LIST_ITEM_UUID &&
+ row_id != PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(row_id);
+ if(impl)
+ {
+ updateListItem(item, impl);
+ }
+ else
+ {
+ // This item's impl has been deleted -- remove the row.
+ // Removing the row won't throw off our iteration, since we have a local copy of the array.
+ // We just need to make sure we don't access this item after the delete.
+ removeListItem(row_id);
+ }
+ }
+ }
+
+ // Set the selection to whatever media impl the media focus/hover is on.
+ // This is an experiment, and can be removed by ifdefing out these 4 lines.
+ LLUUID media_target = LLViewerMediaFocus::getInstance()->getControlsMediaID();
+ if(media_target.notNull())
+ {
+ mMediaList->selectByID(media_target);
+ }
+}
+
+void LLPanelNearByMedia::updateColumns()
+{
+ if (!mDebugInfoVisible)
+ {
+ if (mMediaList->getColumn(CHECKBOX_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(-1);
+ if (mMediaList->getColumn(VISIBILITY_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(-1);
+ if (mMediaList->getColumn(PROXIMITY_COLUMN)) mMediaList->getColumn(PROXIMITY_COLUMN)->setWidth(-1);
+ if (mMediaList->getColumn(CLASS_COLUMN)) mMediaList->getColumn(CLASS_COLUMN)->setWidth(-1);
+ if (mMediaList->getColumn(DEBUG_COLUMN)) mMediaList->getColumn(DEBUG_COLUMN)->setWidth(-1);
+ }
+ else {
+ if (mMediaList->getColumn(CHECKBOX_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(20);
+ if (mMediaList->getColumn(VISIBILITY_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(20);
+ if (mMediaList->getColumn(PROXIMITY_COLUMN)) mMediaList->getColumn(PROXIMITY_COLUMN)->setWidth(30);
+ if (mMediaList->getColumn(CLASS_COLUMN)) mMediaList->getColumn(CLASS_COLUMN)->setWidth(20);
+ if (mMediaList->getColumn(DEBUG_COLUMN)) mMediaList->getColumn(DEBUG_COLUMN)->setWidth(200);
+ }
+}
+
+void LLPanelNearByMedia::onClickEnableAll()
+{
+ LLViewerMedia::setAllMediaEnabled(true);
+}
+
+void LLPanelNearByMedia::onClickDisableAll()
+{
+ LLViewerMedia::setAllMediaEnabled(false);
+}
+
+void LLPanelNearByMedia::onClickEnableParcelMedia()
+{
+ if ( ! LLViewerMedia::isParcelMediaPlaying() )
+ {
+ LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+ }
+}
+
+void LLPanelNearByMedia::onClickDisableParcelMedia()
+{
+ // This actually unloads the impl, as opposed to "stop"ping the media
+ LLViewerParcelMedia::stop();
+}
+
+void LLPanelNearByMedia::onCheckItem(LLUICtrl* ctrl, const LLUUID &row_id)
+{
+ LLCheckBoxCtrl* check = static_cast<LLCheckBoxCtrl*>(ctrl);
+
+ setDisabled(row_id, ! check->getValue());
+}
+
+bool LLPanelNearByMedia::setDisabled(const LLUUID &row_id, bool disabled)
+{
+ if (row_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ if (disabled) onClickParcelAudioStop();
+ else onClickParcelAudioStart();
+ return true;
+ }
+ else if (row_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ {
+ if (disabled) onClickDisableParcelMedia();
+ else onClickEnableParcelMedia();
+ return true;
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(row_id);
+ if(impl)
+ {
+ impl->setDisabled(disabled, true);
+ return true;
+ }
+ }
+ return false;
+}
+
+//static
+void LLPanelNearByMedia::onZoomMedia(void* user_data)
+{
+ LLPanelNearByMedia* panelp = (LLPanelNearByMedia*)user_data;
+ LLUUID media_id = panelp->mMediaList->getValue().asUUID();
+
+ LLViewerMediaFocus::getInstance()->focusZoomOnMedia(media_id);
+}
+
+void LLPanelNearByMedia::onClickParcelMediaPlay()
+{
+ LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+}
+
+void LLPanelNearByMedia::onClickParcelMediaStop()
+{
+ if (LLViewerParcelMedia::getParcelMedia())
+ {
+ // This stops the media playing, as opposed to unloading it like
+ // LLViewerParcelMedia::stop() does
+ LLViewerParcelMedia::getParcelMedia()->stop();
+ }
+}
+
+void LLPanelNearByMedia::onClickParcelMediaPause()
+{
+ LLViewerParcelMedia::pause();
+}
+
+void LLPanelNearByMedia::onClickParcelAudioStart()
+{
+ // User *explicitly* started the internet stream, so keep the stream
+ // playing and updated as they cross to other parcels etc.
+ mParcelAudioAutoStart = true;
+
+ if (!gAudiop)
+ return;
+
+ gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
+}
+
+void LLPanelNearByMedia::onClickParcelAudioPlay()
+{
+ // User *explicitly* started the internet stream, so keep the stream
+ // playing and updated as they cross to other parcels etc.
+ mParcelAudioAutoStart = true;
+
+ if (!gAudiop)
+ return;
+
+ if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying())
+ {
+ // 'false' means unpause
+ gAudiop->pauseInternetStream(false);
+ }
+ else {
+ gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
+ }
+}
+
+void LLPanelNearByMedia::onClickParcelAudioStop()
+{
+ // User *explicitly* stopped the internet stream, so don't
+ // re-start audio when i.e. they move to another parcel, until
+ // they explicitly start it again.
+ mParcelAudioAutoStart = false;
+
+ if (!gAudiop)
+ return;
+
+ gAudiop->stopInternetStream();
+}
+
+void LLPanelNearByMedia::onClickParcelAudioPause()
+{
+ if (!gAudiop)
+ return;
+
+ // 'true' means pause
+ gAudiop->pauseInternetStream(true);
+}
+
+bool LLPanelNearByMedia::shouldShow(LLViewerMediaImpl* impl)
+{
+ const LLSD &choice_llsd = mShowCtrl->getSelectedValue();
+ MediaClass choice = (MediaClass)choice_llsd.asInteger();
+
+ switch (choice)
+ {
+ case MEDIA_CLASS_ALL:
+ return true;
+ break;
+ case MEDIA_CLASS_WITHIN_PARCEL:
+ return impl->isInAgentParcel();
+ break;
+ case MEDIA_CLASS_OUTSIDE_PARCEL:
+ return ! impl->isInAgentParcel();
+ break;
+ case MEDIA_CLASS_ON_OTHERS:
+ return impl->isAttachedToAnotherAvatar();
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+void LLPanelNearByMedia::onAdvancedButtonClick()
+{
+ // bring up the prefs floater
+ LLFloaterPreference* prefsfloater = dynamic_cast<LLFloaterPreference*>(LLFloaterReg::showInstance("preferences"));
+ if (prefsfloater)
+ {
+ // grab the 'audio' panel from the preferences floater and
+ // bring it the front!
+ LLTabContainer* tabcontainer = prefsfloater->getChild<LLTabContainer>("pref core");
+ LLPanel* audiopanel = prefsfloater->getChild<LLPanel>("audio");
+ if (tabcontainer && audiopanel)
+ {
+ tabcontainer->selectTabPanel(audiopanel);
+ }
+ }
+}
+
+void LLPanelNearByMedia::onMoreLess()
+{
+ bool is_more = getChild<LLUICtrl>("more_less_btn")->getValue();
+ mNearbyMediaPanel->setVisible(is_more);
+
+ // enable resizing when expanded
+ getChildView("resizebar_bottom")->setEnabled(is_more);
+
+ S32 new_height = is_more ? mMoreHeight : mLessHeight;
+
+ LLRect new_rect = getRect();
+ new_rect.mBottom = new_rect.mTop - new_height;
+
+ setShape(new_rect);
+}
+
+void LLPanelNearByMedia::updateControls()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ showTimeBasedControls(LLViewerMedia::isParcelAudioPlaying(),
+ false, // include_zoom
+ false, // is_zoomed
+ gSavedSettings.getBOOL("MuteMusic"),
+ gSavedSettings.getF32("AudioLevelMusic") );
+ }
+ else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ {
+ if (!LLViewerMedia::hasParcelMedia())
+ {
+ // Shouldn't happen, but do this anyway
+ showDisabledControls();
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerParcelMedia::getParcelMedia();
+ if (NULL == impl)
+ {
+ // Just means it hasn't started yet
+ showBasicControls(false, false, false);
+ }
+ else if (impl->isMediaTimeBased())
+ {
+ showTimeBasedControls(impl->isMediaPlaying(),
+ false, // include_zoom
+ false, // is_zoomed
+ impl->getVolume() == 0.0,
+ impl->getVolume() );
+ }
+ else {
+ // non-time-based parcel media
+ showBasicControls(LLViewerMedia::isParcelMediaPlaying(), false, false);
+ }
+ }
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+
+ if (NULL == impl)
+ {
+ showDisabledControls();
+ }
+ else {
+ if (impl->isMediaTimeBased())
+ {
+ showTimeBasedControls(impl->isMediaPlaying(),
+ ! impl->isParcelMedia(), // include_zoom
+ LLViewerMediaFocus::getInstance()->isZoomed(),
+ impl->getVolume() == 0.0,
+ impl->getVolume());
+ }
+ else {
+ showBasicControls(!impl->isMediaDisabled(),
+ ! impl->isParcelMedia(), // include_zoom
+ LLViewerMediaFocus::getInstance()->isZoomed());
+ }
+ }
+ }
+}
+
+void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed)
+{
+ mStopCtrl->setVisible(playing);
+ mPlayCtrl->setVisible(!playing);
+ mPauseCtrl->setVisible(false);
+ mMuteCtrl->setVisible(false);
+ mVolumeSliderCtrl->setVisible(false);
+ mZoomCtrl->setVisible(include_zoom && !is_zoomed);
+ mUnzoomCtrl->setVisible(include_zoom && is_zoomed);
+ mStopCtrl->setEnabled(true);
+ mZoomCtrl->setEnabled(true);
+}
+
+void LLPanelNearByMedia::showTimeBasedControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume)
+{
+ mStopCtrl->setVisible(true);
+ mPlayCtrl->setVisible(!playing);
+ mPauseCtrl->setVisible(playing);
+ mMuteCtrl->setVisible(true);
+ mVolumeSliderCtrl->setVisible(true);
+ mZoomCtrl->setVisible(include_zoom);
+ mZoomCtrl->setVisible(include_zoom && !is_zoomed);
+ mUnzoomCtrl->setVisible(include_zoom && is_zoomed);
+ mStopCtrl->setEnabled(true);
+ mZoomCtrl->setEnabled(true);
+ mMuteBtn->setValue(muted);
+ mVolumeSlider->setValue(volume);
+}
+
+void LLPanelNearByMedia::showDisabledControls()
+{
+ mStopCtrl->setVisible(true);
+ mPlayCtrl->setVisible(false);
+ mPauseCtrl->setVisible(false);
+ mMuteCtrl->setVisible(false);
+ mVolumeSliderCtrl->setVisible(false);
+ mZoomCtrl->setVisible(true);
+ mUnzoomCtrl->setVisible(false);
+ mStopCtrl->setEnabled(false);
+ mZoomCtrl->setEnabled(false);
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaStop()
+{
+ setDisabled(mMediaList->getValue().asUUID(), true);
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaPlay()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+
+ // First enable it
+ setDisabled(selected_media_id, false);
+
+ // Special code to make play "unpause" if time-based and playing
+ if (selected_media_id != PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ LLViewerMediaImpl *impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
+ ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased() && impl->isMediaPaused())
+ {
+ // Aha! It's really time-based media that's paused, so unpause
+ impl->play();
+ return;
+ }
+ else if (impl->isParcelMedia())
+ {
+ LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+ }
+ }
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaPause()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ onClickParcelAudioPause();
+ }
+ else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ {
+ onClickParcelMediaPause();
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased() && impl->isMediaPlaying())
+ {
+ impl->pause();
+ }
+ }
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaMute()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ gSavedSettings.setBOOL("MuteMusic", mMuteBtn->getValue());
+ }
+ else {
+ LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
+ ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased())
+ {
+ F32 volume = impl->getVolume();
+ if(volume > 0.0)
+ {
+ impl->setVolume(0.0);
+ }
+ else if (mVolumeSlider->getValueF32() == 0.0)
+ {
+ impl->setVolume(1.0);
+ mVolumeSlider->setValue(1.0);
+ }
+ else
+ {
+ impl->setVolume(mVolumeSlider->getValueF32());
+ }
+ }
+ }
+}
+
+void LLPanelNearByMedia::onCommitSelectedMediaVolume()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ F32 vol = mVolumeSlider->getValueF32();
+ gSavedSettings.setF32("AudioLevelMusic", vol);
+ }
+ else {
+ LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
+ ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased())
+ {
+ impl->setVolume(mVolumeSlider->getValueF32());
+ }
+ }
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaZoom()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID || selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ return;
+ LLViewerMediaFocus::getInstance()->focusZoomOnMedia(selected_media_id);
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaUnzoom()
+{
+ LLViewerMediaFocus::getInstance()->unZoom();
+}
+
+
+// static
+void LLPanelNearByMedia::getNameAndUrlHelper(LLViewerMediaImpl* impl, std::string& name, std::string & url, const std::string &defaultName)
+{
+ if (NULL == impl) return;
+
+ name = impl->getName();
+ url = impl->getCurrentMediaURL(); // This is the URL the media impl actually has loaded
+ if (url.empty())
+ {
+ url = impl->getMediaEntryURL(); // This is the current URL from the media data
+ }
+ if (url.empty())
+ {
+ url = impl->getHomeURL(); // This is the home URL from the media data
+ }
+ if (name.empty())
+ {
+ name = url;
+ }
+ if (name.empty())
+ {
+ name = defaultName;
+ }
+}
+
diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h
new file mode 100644
index 0000000000..eedfd447de
--- /dev/null
+++ b/indra/newview/llpanelnearbymedia.h
@@ -0,0 +1,185 @@
+/**
+ * @file llpanelnearbymedia.h
+ * @brief Management interface for muting and controlling nearby media
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELNEARBYMEDIA_H
+#define LL_LLPANELNEARBYMEDIA_H
+
+#include "llpanel.h"
+
+class LLPanelNearbyMedia;
+class LLButton;
+class LLScrollListCtrl;
+class LLSlider;
+class LLSliderCtrl;
+class LLCheckBoxCtrl;
+class LLTextBox;
+class LLComboBox;
+class LLViewerMediaImpl;
+
+class LLPanelNearByMedia : public LLPanel
+{
+public:
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+ /*virtual*/ void handleVisibilityChange ( BOOL new_visibility );
+ /*virtual*/ void onTopLost ();
+ /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
+
+ // this is part of the nearby media *dialog* so we can track whether
+ // the user *implicitly* wants audio on or off via their *explicit*
+ // interaction with our buttons.
+ bool getParcelAudioAutoStart();
+
+ LLPanelNearByMedia();
+ virtual ~LLPanelNearByMedia();
+
+private:
+
+ enum ColumnIndex {
+ CHECKBOX_COLUMN = 0,
+ PROXIMITY_COLUMN = 1,
+ VISIBILITY_COLUMN = 2,
+ CLASS_COLUMN = 3,
+ NAME_COLUMN = 4,
+ DEBUG_COLUMN = 5
+ };
+
+ // Media "class" enumeration
+ enum MediaClass {
+ MEDIA_CLASS_ALL = 0,
+ MEDIA_CLASS_FOCUSED = 1,
+ MEDIA_CLASS_WITHIN_PARCEL = 2,
+ MEDIA_CLASS_OUTSIDE_PARCEL = 3,
+ MEDIA_CLASS_ON_OTHERS = 4
+ };
+
+ // Add/remove an LLViewerMediaImpl to/from the list
+ LLScrollListItem* addListItem(const LLUUID &id);
+ void updateListItem(LLScrollListItem* item, LLViewerMediaImpl* impl);
+ void updateListItem(LLScrollListItem* item,
+ const std::string &item_name,
+ const std::string &item_tooltip,
+ S32 proximity,
+ bool is_disabled,
+ bool has_media,
+ bool is_time_based_and_playing,
+ MediaClass media_class,
+ const std::string &debug_str);
+ void removeListItem(const LLUUID &id);
+
+ // Refresh the list in the UI
+ void refreshList();
+
+ void refreshParcelItems();
+
+ // UI Callbacks
+ void onClickEnableAll();
+ void onClickDisableAll();
+ void onClickEnableParcelMedia();
+ void onClickDisableParcelMedia();
+ void onClickMuteParcelMedia();
+ void onParcelMediaVolumeSlider();
+ void onClickParcelMediaPlay();
+ void onClickParcelMediaStop();
+ void onClickParcelMediaPause();
+ void onClickParcelAudioPlay();
+ void onClickParcelAudioStop();
+ void onClickParcelAudioStart();
+ void onClickParcelAudioPause();
+ void onCheckAutoPlay();
+ void onAdvancedButtonClick();
+ void onMoreLess();
+
+ void onCheckItem(LLUICtrl* ctrl, const LLUUID &row_id);
+
+ static void onZoomMedia(void* user_data);
+
+private:
+ bool setDisabled(const LLUUID &id, bool disabled);
+
+ static void getNameAndUrlHelper(LLViewerMediaImpl* impl, std::string& name, std::string & url, const std::string &defaultName);
+
+ void updateColumns();
+
+ bool shouldShow(LLViewerMediaImpl* impl);
+
+ void showBasicControls(bool playing, bool include_zoom, bool is_zoomed);
+ void showTimeBasedControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume);
+ void showDisabledControls();
+ void updateControls();
+
+ void onClickSelectedMediaStop();
+ void onClickSelectedMediaPlay();
+ void onClickSelectedMediaPause();
+ void onClickSelectedMediaMute();
+ void onCommitSelectedMediaVolume();
+ void onClickSelectedMediaZoom();
+ void onClickSelectedMediaUnzoom();
+
+ LLUICtrl* mNearbyMediaPanel;
+ LLTextBox* mItemCountText;
+ LLScrollListCtrl* mMediaList;
+ LLUICtrl* mEnableAllCtrl;
+ LLUICtrl* mDisableAllCtrl;
+ LLComboBox* mShowCtrl;
+
+ // Dynamic (selection-dependent) controls
+ LLUICtrl* mStopCtrl;
+ LLUICtrl* mPlayCtrl;
+ LLUICtrl* mPauseCtrl;
+ LLUICtrl* mMuteCtrl;
+ LLUICtrl* mVolumeSliderCtrl;
+ LLUICtrl* mZoomCtrl;
+ LLUICtrl* mUnzoomCtrl;
+ LLSlider* mVolumeSlider;
+ LLButton* mMuteBtn;
+
+ bool mAllMediaDisabled;
+ bool mDebugInfoVisible;
+ bool mParcelAudioAutoStart;
+ std::string mEmptyNameString;
+ std::string mPlayingString;
+ std::string mParcelMediaName;
+ std::string mParcelAudioName;
+
+ S32 mMoreHeight;
+ S32 mLessHeight;
+ LLFrameTimer mHoverTimer;
+ LLScrollListItem* mParcelMediaItem;
+ LLScrollListItem* mParcelAudioItem;
+};
+
+
+#endif // LL_LLPANELNEARBYMEDIA_H
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 479769ee20..a53a3ba1ad 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -724,10 +724,10 @@ void LLPanelPrimMediaControls::draw()
mMediaControlsStack->updateLayout();
// adjust for layout stack spacing
- S32 space = mMediaControlsStack->getPanelSpacing() + 1;
+ S32 space = mMediaControlsStack->getPanelSpacing() + 2;
LLRect controls_bg_area = mMediaControlsStack->getRect();
- controls_bg_area.mTop += space;
+ controls_bg_area.mTop += space + 2;
// adjust to ignore space from volume slider
controls_bg_area.mBottom += mVolumeSliderCtrl->getRect().getHeight();
@@ -736,7 +736,7 @@ void LLPanelPrimMediaControls::draw()
controls_bg_area.mLeft += mLeftBookend->getRect().getWidth() - space;
// ignore space from right bookend padding
- controls_bg_area.mRight -= mRightBookend->getRect().getWidth() - space;
+ controls_bg_area.mRight -= mRightBookend->getRect().getWidth() - space - 2;
// draw control background UI image
mBackgroundImage->draw( controls_bg_area, UI_VERTEX_COLOR % alpha);
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 743cec70a1..2e0de7866c 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -58,6 +58,16 @@ public:
void updateShape();
bool isMouseOver();
+
+ enum EZoomLevel
+ {
+ ZOOM_NONE = 0,
+ ZOOM_FAR,
+ ZOOM_MEDIUM,
+ ZOOM_NEAR
+ };
+
+ EZoomLevel getZoomLevel() const { return mCurrentZoom; }
void nextZoomLevel();
void resetZoomLevel(bool reset_camera = true);
void close();
@@ -66,13 +76,6 @@ public:
void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
- enum EZoomLevel
- {
- ZOOM_NONE = 0,
- ZOOM_FAR,
- ZOOM_MEDIUM,
- ZOOM_NEAR
- };
static const EZoomLevel kZoomLevels[];
static const int kNumZoomLevels;
diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp
index 74e37efe4e..247134ad63 100644
--- a/indra/newview/llpanelvolumepulldown.cpp
+++ b/indra/newview/llpanelvolumepulldown.cpp
@@ -96,7 +96,10 @@ void LLPanelVolumePulldown::handleVisibilityChange ( BOOL new_visibility )
else
{
mHoverTimer.stop();
- gFocusMgr.setTopCtrl(NULL);
+ if (gFocusMgr.getTopCtrl() == this)
+ {
+ gFocusMgr.setTopCtrl(NULL);
+ }
}
}
diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h
index 760b1a7a4c..38029e3a9d 100644
--- a/indra/newview/llrootview.h
+++ b/indra/newview/llrootview.h
@@ -35,6 +35,7 @@
#include "llview.h"
#include "lluictrlfactory.h"
+#include "lltooltip.h"
class LLRootViewRegistry : public LLChildRegistry<LLRootViewRegistry>
{};
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index bff32af228..923e1e42fb 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -41,6 +41,7 @@
#include "llviewercontrol.h"
#include "llfloaterbuycurrency.h"
#include "llfloaterlagmeter.h"
+#include "llpanelnearbymedia.h"
#include "llpanelvolumepulldown.h"
#include "llfloaterregioninfo.h"
#include "llfloaterscriptdebug.h"
@@ -49,6 +50,7 @@
#include "llkeyboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
+#include "llrootview.h"
#include "llsd.h"
#include "lltextbox.h"
#include "llui.h"
@@ -61,6 +63,7 @@
#include "llresmgr.h"
#include "llworld.h"
#include "llstatgraph.h"
+#include "llviewermedia.h"
#include "llviewermenu.h" // for gMenuBarView
#include "llviewerparcelmgr.h"
#include "llviewerthrottle.h"
@@ -130,7 +133,6 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
// status bar can possible overlay menus?
setMouseOpaque(FALSE);
- setIsChrome(TRUE);
// size of day of the weeks and year
sDays.reserve(7);
@@ -140,9 +142,39 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
mHealthTimer = new LLFrameTimer();
LLUICtrlFactory::getInstance()->buildPanel(this,"panel_status_bar.xml");
+}
+
+LLStatusBar::~LLStatusBar()
+{
+ delete mBalanceTimer;
+ mBalanceTimer = NULL;
+
+ delete mHealthTimer;
+ mHealthTimer = NULL;
+
+ // LLView destructor cleans up children
+}
+
+//-----------------------------------------------------------------------
+// Overrides
+//-----------------------------------------------------------------------
+
+// virtual
+void LLStatusBar::draw()
+{
+ refresh();
+ LLPanel::draw();
+}
- // status bar can never get a tab
- setFocusRoot(FALSE);
+BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ show_navbar_context_menu(this,x,y);
+ return TRUE;
+}
+
+BOOL LLStatusBar::postBuild()
+{
+ gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3));
// build date necessary data (must do after panel built)
setupDate();
@@ -158,7 +190,10 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
mBtnVolume = getChild<LLButton>( "volume_btn" );
mBtnVolume->setClickedCallback( onClickVolume, this );
mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this));
- mBtnVolume->setIsChrome(TRUE);
+
+ mMediaToggle = getChild<LLButton>("media_toggle_btn");
+ mMediaToggle->setClickedCallback( &LLStatusBar::onClickMediaToggle, this );
+ mMediaToggle->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterNearbyMedia, this));
gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2));
@@ -207,6 +242,13 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
mPanelVolumePulldown = new LLPanelVolumePulldown();
addChild(mPanelVolumePulldown);
+ mPanelNearByMedia = new LLPanelNearByMedia();
+ LLView* popup_holder = gViewerWindow->getRootView()->getChildView("popup_holder");
+ popup_holder->addChild(mPanelNearByMedia);
+ gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(&LLStatusBar::onClickScreen, this, _1, _2));
+ mPanelNearByMedia->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
+ mPanelNearByMedia->setVisible(FALSE);
+
LLRect volume_pulldown_rect = mPanelVolumePulldown->getRect();
LLButton* volbtn = getChild<LLButton>( "volume_btn" );
volume_pulldown_rect.setLeftTopAndSize(volbtn->getRect().mLeft -
@@ -218,39 +260,6 @@ LLStatusBar::LLStatusBar(const LLRect& rect)
mPanelVolumePulldown->setShape(volume_pulldown_rect);
mPanelVolumePulldown->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
mPanelVolumePulldown->setVisible(FALSE);
-}
-
-LLStatusBar::~LLStatusBar()
-{
- delete mBalanceTimer;
- mBalanceTimer = NULL;
-
- delete mHealthTimer;
- mHealthTimer = NULL;
-
- // LLView destructor cleans up children
-}
-
-//-----------------------------------------------------------------------
-// Overrides
-//-----------------------------------------------------------------------
-
-// virtual
-void LLStatusBar::draw()
-{
- refresh();
- LLPanel::draw();
-}
-
-BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- show_navbar_context_menu(this,x,y);
- return TRUE;
-}
-
-BOOL LLStatusBar::postBuild()
-{
- gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3));
return TRUE;
}
@@ -356,6 +365,13 @@ void LLStatusBar::refresh()
// update the master volume button state
bool mute_audio = LLAppViewer::instance()->getMasterSystemAudioMute();
mBtnVolume->setToggleState(mute_audio);
+
+ // Don't show media toggle if there's no media, parcel media, and no parcel audio
+ mMediaToggle->setVisible(LLViewerMedia::hasInWorldMedia() || LLViewerMedia::hasParcelMedia() || LLViewerMedia::hasParcelAudio());
+ // Note the "sense" of the toggle is opposite whether media is playing or not
+ mMediaToggle->setValue(! (LLViewerMedia::isAnyMediaShowing() ||
+ LLViewerMedia::isParcelMediaPlaying() ||
+ LLViewerMedia::isParcelAudioPlaying()));
}
void LLStatusBar::setVisibleForMouselook(bool visible)
@@ -385,8 +401,8 @@ void LLStatusBar::setBalance(S32 balance)
LLButton* btn_buy_currency = getChild<LLButton>("buycurrency");
LLStringUtil::format_map_t string_args;
string_args["[AMT]"] = llformat("%s", money_str.c_str());
- std::string labe_str = getString("buycurrencylabel", string_args);
- btn_buy_currency->setLabel(labe_str);
+ std::string label_str = getString("buycurrencylabel", string_args);
+ btn_buy_currency->setLabel(label_str);
// Resize the balance button so that the label fits it, and the button expands to the left.
// *TODO: LLButton should have an option where to expand.
@@ -513,13 +529,32 @@ static void onClickScriptDebug(void*)
LLFloaterScriptDebug::show(LLUUID::null);
}
-//static
-void LLStatusBar::onMouseEnterVolume(LLUICtrl* ctrl)
+void LLStatusBar::onMouseEnterVolume()
{
// show the master volume pull-down
- gStatusBar->mPanelVolumePulldown->setVisible(TRUE);
+ mPanelVolumePulldown->setVisible(TRUE);
}
+void LLStatusBar::onMouseEnterNearbyMedia()
+{
+ LLView* popup_holder = gViewerWindow->getRootView()->getChildView("popup_holder");
+ LLRect nearby_media_rect = mPanelNearByMedia->getRect();
+ LLButton* nearby_media_btn = getChild<LLButton>( "media_toggle_btn" );
+ LLRect nearby_media_btn_rect = nearby_media_btn->calcScreenRect();
+ nearby_media_rect.setLeftTopAndSize(nearby_media_btn_rect.mLeft -
+ (nearby_media_rect.getWidth() - nearby_media_btn_rect.getWidth())/2,
+ nearby_media_btn_rect.mBottom,
+ nearby_media_rect.getWidth(),
+ nearby_media_rect.getHeight());
+ // force onscreen
+ nearby_media_rect.translate(popup_holder->getRect().getWidth() - nearby_media_rect.mRight, 0);
+
+ // show the master volume pull-down
+ mPanelNearByMedia->setShape(nearby_media_rect);
+ mPanelNearByMedia->setVisible(TRUE);
+}
+
+
static void onClickVolume(void* data)
{
// toggle the master mute setting
@@ -527,6 +562,15 @@ static void onClickVolume(void* data)
LLAppViewer::instance()->setMasterSystemAudioMute(!mute_audio);
}
+//static
+void LLStatusBar::onClickMediaToggle(void* data)
+{
+ LLStatusBar *status_bar = (LLStatusBar*)data;
+ // "Selected" means it was showing the "play" icon (so media was playing), and now it shows "pause", so turn off media
+ bool enable = ! status_bar->mMediaToggle->getValue();
+ LLViewerMedia::setAllMediaEnabled(enable);
+}
+
// sets the static variables necessary for the date
void LLStatusBar::setupDate()
{
@@ -596,6 +640,18 @@ void LLStatusBar::onClickStatGraph(void* data)
LLFloaterReg::showInstance("lagmeter");
}
+void LLStatusBar::onClickScreen(S32 x, S32 y)
+{
+ if (mPanelNearByMedia->getVisible())
+ {
+ LLRect screen_rect = mPanelNearByMedia->calcScreenRect();
+ if (!screen_rect.pointInRect(x, y))
+ {
+ mPanelNearByMedia->setVisible(FALSE);
+ }
+ }
+}
+
BOOL can_afford_transaction(S32 cost)
{
return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost)));
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index 21a98dd753..e5240fcc3e 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -48,6 +48,7 @@ class LLUUID;
class LLFrameTimer;
class LLStatGraph;
class LLPanelVolumePulldown;
+class LLPanelNearByMedia;
class LLStatusBar
: public LLPanel
@@ -87,6 +88,8 @@ public:
S32 getSquareMetersCommitted() const;
S32 getSquareMetersLeft() const;
+ LLPanelNearByMedia* getNearbyMediaPanel() { return mPanelNearByMedia; }
+
private:
// simple method to setup the part that holds the date
void setupDate();
@@ -94,9 +97,13 @@ private:
void onClickBuyCurrency();
void onVolumeChanged(const LLSD& newvalue);
- static void onMouseEnterVolume(LLUICtrl* ctrl);
+ void onMouseEnterVolume();
+ void onMouseEnterNearbyMedia();
+ void onClickScreen(S32 x, S32 y);
static void onClickStatGraph(void* data);
+ static void onClickMediaToggle(void* data);
+
private:
LLTextBox *mTextHealth;
LLTextBox *mTextTime;
@@ -105,6 +112,7 @@ private:
LLStatGraph *mSGPacketLoss;
LLButton *mBtnVolume;
+ LLButton *mMediaToggle;
S32 mBalance;
S32 mHealth;
@@ -113,6 +121,7 @@ private:
LLFrameTimer* mBalanceTimer;
LLFrameTimer* mHealthTimer;
LLPanelVolumePulldown* mPanelVolumePulldown;
+ LLPanelNearByMedia* mPanelNearByMedia;
static std::vector<std::string> sDays;
static std::vector<std::string> sMonths;
static const U32 MAX_DATE_STRING_LENGTH;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index eb070fb3ef..8370c98470 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -78,7 +78,6 @@
#include "llfloatermap.h"
#include "llfloatermemleak.h"
#include "llfloaternamedesc.h"
-#include "llfloaternearbymedia.h"
#include "llfloaternotificationsconsole.h"
#include "llfloateropenobject.h"
#include "llfloaterpay.h"
@@ -197,7 +196,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
- LLFloaterReg::add("nearby_media", "floater_nearby_media.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNearbyMedia>);
LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
LLFloaterReg::add("notification_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNotificationWellWindow>);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 25c843cf15..642f672faf 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -50,6 +50,9 @@
#include "llcallbacklist.h"
#include "llparcel.h"
#include "llaudioengine.h" // for gAudiop
+#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llviewerregion.h"
#include "llevent.h" // LLSimpleListener
#include "llnotificationsutil.h"
@@ -63,6 +66,10 @@
#include <boost/signals2.hpp>
/*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable";
+/*static*/ const char* LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING = "MediaShowOnOthers";
+/*static*/ const char* LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING = "MediaShowWithinParcel";
+/*static*/ const char* LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING = "MediaShowOutsideParcel";
+
// Move this to its own file.
@@ -254,6 +261,8 @@ static LLTimer sMediaCreateTimer;
static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
static F32 sGlobalVolume = 1.0f;
static F64 sLowestLoadableImplInterest = 0.0f;
+static bool sAnyMediaShowing = false;
+static boost::signals2::connection sTeleportFinishConnection;
//////////////////////////////////////////////////////////////////////////////////////////
static void add_media_impl(LLViewerMediaImpl* media)
@@ -366,8 +375,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
// The current media URL is not empty.
// If (the media was already loaded OR the media was set to autoplay) AND this update didn't come from this agent,
// do a navigate.
- bool auto_play = (media_impl->mMediaAutoPlay && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING));
-
+ bool auto_play = media_impl->isAutoPlayable();
if((was_loaded || auto_play) && !update_from_self)
{
needs_navigate = url_changed;
@@ -391,7 +399,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
media_impl->mMediaEntryURL = media_entry->getCurrentURL();
- if(media_impl->mMediaAutoPlay && gSavedSettings.getBOOL(AUTO_PLAY_MEDIA_SETTING))
+ if(media_impl->isAutoPlayable())
{
needs_navigate = true;
}
@@ -688,6 +696,7 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi
// static
void LLViewerMedia::updateMedia(void *dummy_arg)
{
+ sAnyMediaShowing = false;
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
@@ -818,7 +827,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
impl_count_total++;
}
-
+
// Overrides if the window is minimized or we lost focus (taking care
// not to accidentally "raise" the priority either)
if (!gViewerWindow->getActive() /* viewer window minimized? */
@@ -840,7 +849,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
new_priority = LLPluginClassMedia::PRIORITY_UNLOADED;
}
}
-
+
pimpl->setPriority(new_priority);
if(pimpl->getUsedInUI())
@@ -854,6 +863,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
}
total_cpu += pimpl->getCPUUsage();
+
+ if (!pimpl->getUsedInUI() && pimpl->hasMedia())
+ {
+ sAnyMediaShowing = true;
+ }
+
}
// Re-calculate this every time.
@@ -895,9 +910,113 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
//////////////////////////////////////////////////////////////////////////////////////////
// static
+bool LLViewerMedia::isAnyMediaShowing()
+{
+ return sAnyMediaShowing;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setAllMediaEnabled(bool val)
+{
+ // Set "tentative" autoplay first. We need to do this here or else
+ // re-enabling won't start up the media below.
+ gSavedSettings.setBOOL("MediaTentativeAutoPlay", val);
+
+ // Then
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if (!pimpl->getUsedInUI())
+ {
+ pimpl->setDisabled(!val);
+ }
+ }
+
+ // Also do Parcel Media and Parcel Audio
+ if (val)
+ {
+ if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
+ {
+ LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+ }
+
+ if (!LLViewerMedia::isParcelAudioPlaying() && gAudiop && LLViewerMedia::hasParcelAudio())
+ {
+ gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
+ }
+ }
+ else {
+ // This actually unloads the impl, as opposed to "stop"ping the media
+ LLViewerParcelMedia::stop();
+ if (gAudiop) gAudiop->stopInternetStream();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isParcelMediaPlaying()
+{
+ return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::isParcelAudioPlaying()
+{
+ return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
+}
+
+bool LLViewerMedia::hasInWorldMedia()
+{
+ if (! gSavedSettings.getBOOL("AudioStreamingMedia")) return false;
+ if (sInWorldMediaDisabled) return false;
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+ // This should be quick, because there should be very few non-in-world-media impls
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if (!pimpl->getUsedInUI() && !pimpl->isParcelMedia())
+ {
+ // Found an in-world media impl
+ return true;
+ }
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::hasParcelMedia()
+{
+ return !LLViewerParcelMedia::getURL().empty();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::hasParcelAudio()
+{
+ return !LLViewerMedia::getParcelAudioURL().empty();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+std::string LLViewerMedia::getParcelAudioURL()
+{
+ return LLViewerParcelMgr::getInstance()->getAgentParcel()->getMusicURL();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
void LLViewerMedia::initClass()
{
- gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
+ gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
+ sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
+ setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -905,6 +1024,15 @@ void LLViewerMedia::initClass()
void LLViewerMedia::cleanupClass()
{
gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL);
+ sTeleportFinishConnection.disconnect();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::onTeleportFinished()
+{
+ // On teleport, clear this setting (i.e. set it to true)
+ gSavedSettings.setBOOL("MediaTentativeAutoPlay", true);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -2057,6 +2185,21 @@ void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y)
#endif
}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+bool LLViewerMediaImpl::isMediaTimeBased()
+{
+ bool result = false;
+
+ if(mMediaSource)
+ {
+ result = mMediaSource->pluginSupportsMediaTime();
+ }
+
+ return result;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
bool LLViewerMediaImpl::isMediaPlaying()
{
@@ -2103,7 +2246,7 @@ void LLViewerMediaImpl::resetPreviousMediaState()
//////////////////////////////////////////////////////////////////////////////////////////
//
-void LLViewerMediaImpl::setDisabled(bool disabled)
+void LLViewerMediaImpl::setDisabled(bool disabled, bool forcePlayOnEnable)
{
if(mIsDisabled != disabled)
{
@@ -2118,7 +2261,7 @@ void LLViewerMediaImpl::setDisabled(bool disabled)
else
{
// We just (re)enabled this media. Do a navigate if auto-play is in order.
- if(mMediaAutoPlay && gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING))
+ if(isAutoPlayable() || forcePlayOnEnable)
{
navigateTo(mMediaEntryURL, "", true, true);
}
@@ -2145,6 +2288,12 @@ bool LLViewerMediaImpl::isForcedUnloaded() const
}
}
+ // If this media's class is not supposed to be shown, unload
+ if (!shouldShowBasedOnClass())
+ {
+ return true;
+ }
+
return false;
}
@@ -2639,3 +2788,112 @@ void LLViewerMediaImpl::setTextureID(LLUUID id)
}
}
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isAutoPlayable() const
+{
+ return (mMediaAutoPlay &&
+ gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+ gSavedSettings.getBOOL("MediaTentativeAutoPlay"));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::shouldShowBasedOnClass() const
+{
+ // If this is parcel media or in the UI, return true always
+ if (getUsedInUI() || isParcelMedia()) return true;
+
+ bool attached_to_another_avatar = isAttachedToAnotherAvatar();
+ bool inside_parcel = isInAgentParcel();
+
+ // llinfos << " hasFocus = " << hasFocus() <<
+ // " others = " << (attached_to_another_avatar && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING)) <<
+ // " within = " << (inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING)) <<
+ // " outside = " << (!inside_parcel && gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING)) << llendl;
+
+ // If it has focus, we should show it
+ if (hasFocus())
+ return true;
+
+ // If it is attached to an avatar and the pref is off, we shouldn't show it
+ if (attached_to_another_avatar)
+ return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING);
+
+ if (inside_parcel)
+ return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING);
+ else
+ return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isAttachedToAnotherAvatar() const
+{
+ bool result = false;
+
+ std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
+ std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
+ for ( ; iter != end; iter++)
+ {
+ if (isObjectAttachedToAnotherAvatar(*iter))
+ {
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+//static
+bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj)
+{
+ bool result = false;
+ LLXform *xform = obj;
+ // Walk up parent chain
+ while (NULL != xform)
+ {
+ LLViewerObject *object = dynamic_cast<LLViewerObject*> (xform);
+ if (NULL != object)
+ {
+ LLVOAvatar *avatar = object->asAvatar();
+ if (NULL != avatar && avatar != gAgent.getAvatarObject())
+ {
+ result = true;
+ break;
+ }
+ }
+ xform = xform->getParent();
+ }
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+bool LLViewerMediaImpl::isInAgentParcel() const
+{
+ bool result = false;
+
+ std::list< LLVOVolume* >::const_iterator iter = mObjectList.begin();
+ std::list< LLVOVolume* >::const_iterator end = mObjectList.end();
+ for ( ; iter != end; iter++)
+ {
+ LLVOVolume *object = *iter;
+ if (LLViewerMediaImpl::isObjectInAgentParcel(object))
+ {
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+// static
+bool LLViewerMediaImpl::isObjectInAgentParcel(LLVOVolume *obj)
+{
+ return (LLViewerParcelMgr::getInstance()->inAgentParcel(obj->getPositionGlobal()));
+}
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index daad70f14f..9dbffa78b3 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -48,7 +48,7 @@ class LLViewerMediaImpl;
class LLUUID;
class LLViewerMediaTexture;
class LLMediaEntry;
-class LLVOVolume ;
+class LLVOVolume;
class LLMimeDiscoveryResponder;
typedef LLPointer<LLViewerMediaImpl> viewer_media_t;
@@ -73,50 +73,68 @@ class LLViewerMediaImpl;
class LLViewerMedia
{
LOG_CLASS(LLViewerMedia);
- public:
-
- // String to get/set media autoplay in gSavedSettings
- static const char *AUTO_PLAY_MEDIA_SETTING;
+public:
- typedef std::vector<LLViewerMediaImpl*> impl_list;
-
- typedef std::map<LLUUID, LLViewerMediaImpl*> impl_id_map;
-
- // Special case early init for just web browser component
- // so we can show login screen. See .cpp file for details. JC
-
- static viewer_media_t newMediaImpl(const LLUUID& texture_id,
- S32 media_width = 0,
- S32 media_height = 0,
- U8 media_auto_scale = false,
- U8 media_loop = false);
-
- static viewer_media_t updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self);
- static LLViewerMediaImpl* getMediaImplFromTextureID(const LLUUID& texture_id);
- static std::string getCurrentUserAgent();
- static void updateBrowserUserAgent();
- static bool handleSkinCurrentChanged(const LLSD& /*newvalue*/);
- static bool textureHasMedia(const LLUUID& texture_id);
- static void setVolume(F32 volume);
-
- static void updateMedia(void* dummy_arg = NULL);
-
- static void initClass();
- static void cleanupClass();
-
- static F32 getVolume();
- static void muteListChanged();
- static void setInWorldMediaDisabled(bool disabled);
- static bool getInWorldMediaDisabled();
-
- static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest);
+ // String to get/set media autoplay in gSavedSettings
+ static const char* AUTO_PLAY_MEDIA_SETTING;
+ static const char* SHOW_MEDIA_ON_OTHERS_SETTING;
+ static const char* SHOW_MEDIA_WITHIN_PARCEL_SETTING;
+ static const char* SHOW_MEDIA_OUTSIDE_PARCEL_SETTING;
- // Returns the priority-sorted list of all media impls.
- static impl_list &getPriorityList();
-
- // This is the comparitor used to sort the list.
- static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2);
-
+ typedef std::vector<LLViewerMediaImpl*> impl_list;
+
+ typedef std::map<LLUUID, LLViewerMediaImpl*> impl_id_map;
+
+ // Special case early init for just web browser component
+ // so we can show login screen. See .cpp file for details. JC
+
+ static viewer_media_t newMediaImpl(const LLUUID& texture_id,
+ S32 media_width = 0,
+ S32 media_height = 0,
+ U8 media_auto_scale = false,
+ U8 media_loop = false);
+
+ static viewer_media_t updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self);
+ static LLViewerMediaImpl* getMediaImplFromTextureID(const LLUUID& texture_id);
+ static std::string getCurrentUserAgent();
+ static void updateBrowserUserAgent();
+ static bool handleSkinCurrentChanged(const LLSD& /*newvalue*/);
+ static bool textureHasMedia(const LLUUID& texture_id);
+ static void setVolume(F32 volume);
+
+ // Is any media currently "showing"? Includes Parcel Media. Does not include media in the UI.
+ static bool isAnyMediaShowing();
+ // Set all media enabled or disabled, depending on val. Does not include media in the UI.
+ static void setAllMediaEnabled(bool val);
+
+ static void updateMedia(void* dummy_arg = NULL);
+
+ static void initClass();
+ static void cleanupClass();
+
+ static F32 getVolume();
+ static void muteListChanged();
+ static void setInWorldMediaDisabled(bool disabled);
+ static bool getInWorldMediaDisabled();
+
+ static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest);
+
+ // Returns the priority-sorted list of all media impls.
+ static impl_list &getPriorityList();
+
+ // This is the comparitor used to sort the list.
+ static bool priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2);
+
+ // These are just helper functions for the convenience of others working with media
+ static bool hasInWorldMedia();
+ static std::string getParcelAudioURL();
+ static bool hasParcelMedia();
+ static bool hasParcelAudio();
+ static bool isParcelMediaPlaying();
+ static bool isParcelAudioPlaying();
+
+private:
+ static void onTeleportFinished();
};
// Implementation functions not exported into header file
@@ -199,18 +217,20 @@ public:
void updateImagesMediaStreams();
LLUUID getMediaTextureID() const;
- void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; };
+ void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; }
void setVisible(bool visible);
- bool getVisible() const { return mVisible; };
+ bool getVisible() const { return mVisible; }
+ bool isVisible() const { return mVisible; }
+ bool isMediaTimeBased();
bool isMediaPlaying();
bool isMediaPaused();
bool hasMedia() const;
- bool isMediaFailed() const { return mMediaSourceFailed; };
+ bool isMediaFailed() const { return mMediaSourceFailed; }
void setMediaFailed(bool val) { mMediaSourceFailed = val; }
void resetPreviousMediaState();
- void setDisabled(bool disabled);
+ void setDisabled(bool disabled, bool forcePlayOnEnable = false);
bool isMediaDisabled() const { return mIsDisabled; };
void setInNearbyMediaList(bool in_list) { mInNearbyMediaList = in_list; }
@@ -222,10 +242,10 @@ public:
// returns true if this instance could be playable based on autoplay setting, current load state, etc.
bool isPlayable() const;
- void setIsParcelMedia(bool is_parcel_media) { mIsParcelMedia = is_parcel_media; };
- bool isParcelMedia() const { return mIsParcelMedia; };
+ void setIsParcelMedia(bool is_parcel_media) { mIsParcelMedia = is_parcel_media; }
+ bool isParcelMedia() const { return mIsParcelMedia; }
- ECursorType getLastSetCursor() { return mLastSetCursor; };
+ ECursorType getLastSetCursor() { return mLastSetCursor; }
// utility function to create a ready-to-use media instance from a desired media type.
static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height);
@@ -326,6 +346,18 @@ public:
void cancelMimeTypeProbe();
+ // Is this media attached to an avatar *not* self
+ bool isAttachedToAnotherAvatar() const;
+
+ // Is this media in the agent's parcel?
+ bool isInAgentParcel() const;
+
+private:
+ bool isAutoPlayable() const;
+ bool shouldShowBasedOnClass() const;
+ static bool isObjectAttachedToAnotherAvatar(LLVOVolume *obj);
+ static bool isObjectInAgentParcel(LLVOVolume *obj);
+
private:
// a single media url with some data and an impl.
LLPluginClassMedia* mMediaSource;
@@ -368,7 +400,7 @@ private:
LLMimeDiscoveryResponder *mMimeTypeProbe;
bool mMediaAutoPlay;
std::string mMediaEntryURL;
- bool mInNearbyMediaList; // used by LLFloaterNearbyMedia::refreshList() for performance reasons
+ bool mInNearbyMediaList; // used by LLPanelNearbyMedia::refreshList() for performance reasons
bool mClearCache;
LLColor4 mBackgroundColor;
bool mNavigateSuspended;
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index f508a3462a..88e7cfec86 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -559,6 +559,19 @@ void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id)
}
}
+void LLViewerMediaFocus::unZoom()
+{
+ if(mMediaControls.get())
+ {
+ mMediaControls.get()->resetZoomLevel();
+ }
+}
+
+bool LLViewerMediaFocus::isZoomed() const
+{
+ return (mMediaControls.get() && mMediaControls.get()->getZoomLevel() != LLPanelPrimMediaControls::ZOOM_NONE);
+}
+
LLUUID LLViewerMediaFocus::getControlsMediaID()
{
if(getFocusedMediaImpl())
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index 002044ea2e..d9ddc7432b 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -85,6 +85,9 @@ public:
// Try to focus/zoom on the specified media (if it's on an object in world).
void focusZoomOnMedia(LLUUID media_id);
+ // Are we zoomed in?
+ bool isZoomed() const;
+ void unZoom();
// Return the ID of the media instance the controls are currently attached to (either focus or hover).
LLUUID getControlsMediaID();
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 07c8867e26..1f6bbcbae8 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -53,7 +53,7 @@
//#include "llfirstuse.h"
#include "llfloaterbuyland.h"
#include "llfloatergroups.h"
-#include "llfloaternearbymedia.h"
+#include "llpanelnearbymedia.h"
#include "llfloatersellland.h"
#include "llfloatertools.h"
#include "llparcelselection.h"
@@ -1795,12 +1795,13 @@ void optionally_start_music(const std::string& music_url)
{
// only play music when you enter a new parcel if the UI control for this
// was not *explicitly* stopped by the user. (part of SL-4878)
- LLFloaterNearbyMedia *nearby_media_floater = LLFloaterReg::findTypedInstance<LLFloaterNearbyMedia>("nearby_media");
- if ((nearby_media_floater &&
- nearby_media_floater->getParcelAudioAutoStart()) ||
+ LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();;
+ if ((nearby_media_panel &&
+ nearby_media_panel->getParcelAudioAutoStart()) ||
// or they have expressed no opinion in the UI, but have autoplay on...
- (!nearby_media_floater &&
- gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)))
+ (!nearby_media_panel &&
+ gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+ gSavedSettings.getBOOL("MediaTentativeAutoPlay")))
{
llinfos << "Starting parcel music " << music_url << llendl;
gAudiop->startInternetStream(music_url);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 1dcc7389cb..1669ce6312 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -997,6 +997,7 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window)
// Note: we won't get this if we have captured the mouse.
llassert( gFocusMgr.getMouseCapture() == NULL );
mMouseInWindow = FALSE;
+ LLToolTipMgr::instance().blockToolTips();
}
BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
diff --git a/indra/newview/skins/default/textures/windows/Flyout_Pointer_Up.png b/indra/newview/skins/default/textures/windows/Flyout_Pointer_Up.png
new file mode 100644
index 0000000000..361fab59e0
--- /dev/null
+++ b/indra/newview/skins/default/textures/windows/Flyout_Pointer_Up.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml
index 1d4377e339..7b6081d7be 100644
--- a/indra/newview/skins/default/xui/en/main_view.xml
+++ b/indra/newview/skins/default/xui/en/main_view.xml
@@ -162,6 +162,12 @@
mouse_opaque="false"
name="Menu Holder"
width="1024"/>
+ <panel top="0"
+ follows="all"
+ height="768"
+ mouse_opaque="false"
+ name="popup_holder"
+ width="1024"/>
<snapshot_floater_view enabled="false"
follows="all"
height="768"
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_media.xml b/indra/newview/skins/default/xui/en/panel_nearby_media.xml
new file mode 100644
index 0000000000..4a71be370e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_nearby_media.xml
@@ -0,0 +1,476 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ can_resize="true"
+ can_close="false"
+ background_opaque="true"
+ background_visible="true"
+ layout="topleft"
+ width="270"
+ height="325"
+ name="nearby_media"
+ help_topic="nearby_media">
+ <string name="media_item_count_format">(%ld media items)</string>
+ <string name="empty_item_text">&lt;empty&gt;</string>
+ <string name="parcel_media_name">Parcel Streaming Media</string>
+ <string name="parcel_audio_name">Parcel Streaming Audio</string>
+ <string name="playing_suffix">(playing)</string>
+ <panel
+ bevel_style="in"
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ bg_opaque_image="Toast_Background"
+ follows="left|right|top"
+ top="0"
+ height="30"
+ name="minimized_controls"
+ left="0">
+ <button
+ name="all_nearby_media_disable_btn"
+ follows="left"
+ tool_tip="Turn all nearby media off"
+ left="15"
+ width="60"
+ height="22"
+ label="Stop All">
+ <button.commit_callback
+ function="MediaListCtrl.DisableAll" />
+ </button>
+ <button
+ name="all_nearby_media_enable_btn"
+ follows="left"
+ tool_tip="Turn all nearby media on"
+ left_pad="4"
+ width="60"
+ height="22"
+ label="Start All">
+ <button.commit_callback
+ function="MediaListCtrl.EnableAll" />
+ </button>
+ <button
+ name="open_prefs_btn"
+ image_overlay="Icon_Gear_Foreground"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ tool_tip = "Bring up media prefs"
+ top_delta="0"
+ left_pad="4"
+ height="22"
+ min_width="28"
+ width="28">
+ <button.commit_callback
+ function="MediaListCtrl.GoMediaPrefs" />
+ </button>
+ <button
+ name="more_less_btn"
+ follows="right"
+ tool_tip="Advanced Controls"
+ top_delta="0"
+ right="-10"
+ width="60"
+ height="22"
+ toggle="true"
+ label="More &gt;&gt;"
+ label_selected="Less &lt;&lt;">
+ <button.commit_callback
+ function="MediaListCtrl.MoreLess" />
+ </button>
+ </panel>
+ <panel
+ name="nearby_media_panel"
+ bevel_style="in"
+ border_style="line"
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|right|top|bottom"
+ top_delta="30"
+ right="-1"
+ left="0"
+ height="295">
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ left="10"
+ width="100">
+ Nearby Media
+ </text>
+ <!-- nix for now
+ <text
+ bottom_delta="1"
+ type="string"
+ follows="top|left|right"
+ font="SansSerif"
+ font.style="ITALIC"
+ font.size="Small"
+ name="media_item_count"
+ left="115"
+ right="-10">
+ (?? media items)
+ </text>
+ -->
+ <text
+ type="string"
+ length="1"
+ follows="top|left"
+ font="SansSerif"
+ top_pad="15"
+ left="10"
+ width="40">
+ Show:
+ </text>
+ <combo_box
+ height="23"
+ left="50"
+ width="140"
+ top_delta="-5"
+ follows="left|top"
+ name="show_combo">
+ <combo_box.item
+ label="All"
+ value="0"
+ name="All" />
+ <combo_box.item
+ label="In this Parcel"
+ value="2"
+ name="WithinParcel" />
+ <combo_box.item
+ label="Outside this Parcel"
+ value="3"
+ name="OutsideParcel" />
+ <combo_box.item
+ label="On other Avatars"
+ value="4"
+ ame="OnOthers" />
+ </combo_box>
+ <scroll_list
+ follows="left|top|bottom|right"
+ column_padding="0"
+ height="100"
+ draw_heading="false"
+ draw_stripes="true"
+ bg_stripe_color="0.25 0.25 0.25 0.25"
+ top_pad="8"
+ left="10"
+ right="-10"
+ name="media_list">
+ <scroll_list.columns
+ type="checkbox"
+ width="-1"
+ label=""
+ name="media_checkbox_ctrl" />
+ <scroll_list.columns
+ sort_column="media_proximity"
+ width="-1"
+ label="Proximity"
+ name="media_proximity" />
+ <scroll_list.columns
+ sort_column="media_visibility"
+ width="-1"
+ label="Visible"
+ name="media_visibility" />
+ <scroll_list.columns
+ sort_column="media_class"
+ width="-1"
+ label="Class"
+ name="media_class" />
+ <scroll_list.columns
+ label="Name"
+ name="media_name" />
+ <scroll_list.columns
+ sort_column="media_debug"
+ width="-1"
+ label="Debug"
+ name="media_debug" />
+ </scroll_list>
+ <panel
+ bevel_style="in"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 1.0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|right|bottom"
+ top_pad="5"
+ height="30"
+ left="10"
+ right="-10">
+ <layout_stack
+ name="media_controls"
+ follows="left|right|top"
+ animate="false"
+ height="75"
+ layout="topleft"
+ top="4"
+ left="10"
+ right="-10"
+ border_size="0"
+ mouse_opaque="false"
+ orientation="horizontal">
+ <layout_panel
+ name="stop"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="stop_btn"
+ follows="top"
+ image_overlay="Stop_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip="Stop selected media"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="play"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="play_btn"
+ follows="top"
+ image_overlay="Play_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip = "Play selected media"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Play" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="pause"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="22"
+ width="22">
+ <button
+ name="pause_btn"
+ follows="top"
+ image_overlay="Pause_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ top="0"
+ height="22"
+ width="22"
+ tool_tip = "Pause selected media">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Pause" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="volume_slider_ctrl"
+ mouse_opaque="false"
+ auto_resize="true"
+ user_resize="false"
+ follows="left|right"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="100"
+ width="200">
+ <slider_bar
+ name="volume_slider"
+ follows="left|right|top"
+ top="0"
+ height="22"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ tool_tip="Audio volume for selected media"
+ width="200">
+ <slider_bar.commit_callback
+ function="SelectedMediaCtrl.Volume" />
+ </slider_bar>
+ </layout_panel>
+ <layout_panel
+ name="mute"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="72"
+ min_width="22"
+ width="22">
+ <button
+ name="mute_btn"
+ follows="top"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="AudioMute_Off"
+ image_unselected="Audio_Off"
+ hover_glow_amount="0.15"
+ is_toggle="true"
+ layout="topleft"
+ scale_image="false"
+ tool_tip="Mute audio on selected media"
+ top="0"
+ height="20"
+ width="22" >
+ <button.commit_callback
+ function="SelectedMediaCtrl.Mute" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="zoom"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="28"
+ min_width="22"
+ width="22">
+ <button
+ name="zoom_btn"
+ follows="top"
+ image_overlay="Zoom_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ layout="topleft"
+ tool_tip="Zoom into selected media"
+ width="22">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Zoom" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="unzoom"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="21"
+ width="21" >
+ <button
+ name="unzoom_btn"
+ follows="top"
+ image_overlay="UnZoom_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ layout="topleft"
+ tool_tip ="Zoom back from selected media"
+ top_delta="-4"
+ width="21" >
+ <button.commit_callback
+ function="SelectedMediaCtrl.Unzoom" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="right_bookend"
+ width="0"
+ mouse_opaque="false"
+ user_resize="false" />
+ </layout_stack>
+ </panel>
+ <panel
+ bevel_style="in"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 1.0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|right|bottom"
+ top_pad="5"
+ height="90"
+ left="10"
+ right="-10">
+ <check_box
+ name="media_enabled_btn"
+ control_name="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Check this to enable all media"
+ label="All Media Enabled"
+ top="10"
+ left="10"/>
+ <check_box
+ name="media_auto_play_btn"
+ control_name="ParcelMediaAutoPlayEnable"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Check this to let media auto-play if it wants"
+ label="Allow Media to auto-play"
+ top_pad="5"
+ left="10"/>
+ <!--
+ <check_box
+ name="media_show_within_parcel_btn"
+ control_name="MediaShowWithinParcel"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Uncheck this to hide media within the parcel you are standing in"
+ label="Show media within current parcel"
+ left="10"/>
+ -->
+ <check_box
+ name="media_show_outside_parcel_btn"
+ control_name="MediaShowOutsideParcel"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Uncheck this to hide media outside the parcel you are standing in"
+ label="Show media outside current parcel"
+ left="10"/>
+ <check_box
+ name="media_show_on_others_btn"
+ control_name="MediaShowOnOthers"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Uncheck this to hide media attached to other avatars nearby"
+ label="Show media attached to other avatars"
+ left="10"/>
+ </panel>
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
index e1d8ee241d..6b5f0c3896 100644
--- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -71,7 +71,7 @@
layout="topleft"
top="0"
left="0"
- border_size="1"
+ border_size="0"
mouse_opaque="false"
orientation="horizontal">
<!-- outer layout_panels center the inner one -->
@@ -260,7 +260,7 @@
top="0"
height="22"
min_width="22"
- width="24">
+ width="22">
<button
name="play_btn"
follows="top"
@@ -272,7 +272,6 @@
hover_glow_amount="0.15"
layout="topleft"
tool_tip = "Play media"
- left_delta="2"
top="0"
height="22"
width="22">
@@ -288,7 +287,7 @@
layout="topleft"
top="0"
min_width="22"
- width="24">
+ width="22">
<button
name="pause_btn"
follows="top"
@@ -302,7 +301,6 @@
top="0"
height="22"
width="22"
- left_delta="-1"
tool_tip = "Pause media">
<button.commit_callback
function="MediaCtrl.Pause" />
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 5754f67045..96c61b69f5 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -3,6 +3,7 @@
background_opaque="true"
background_visible="true"
bg_opaque_color="MouseGray"
+ chrome="true"
follows="top|right"
height="19"
layout="topleft"
@@ -10,6 +11,7 @@
mouse_opaque="false"
name="status"
top="19"
+ tab_stop="false"
width="1000">
<panel.string
name="StatBarDaysOfWeek">
@@ -73,7 +75,7 @@
pad_bottom="2"
tool_tip="Click to buy more L$"
top="2"
- width="71" />
+ width="45" />
<text
type="string"
font="SansSerifSmall"
@@ -86,17 +88,31 @@
left_pad="0"
name="TimeText"
tool_tip="Current time (Pacific)"
- width="89">
+ width="80">
24:00 AM PST
</text>
<button
follows="right|top"
height="15"
+ image_selected="Pause_Off"
+ image_unselected="Play_Off"
+ image_pressed="Play_Press"
+ image_pressed_selected="Pause_Press"
+ is_toggle="true"
+ left_pad="15"
+ top="2"
+ name="media_toggle_btn"
+ tool_tip="Click to toggle media"
+ width="16" >
+ </button>
+ <button
+ follows="right|top"
+ height="15"
image_selected="AudioMute_Off"
image_pressed="Audio_Press"
image_unselected="Audio_Off"
is_toggle="true"
- left_pad="18"
+ left_pad="5"
top="2"
name="volume_btn"
tool_tip="Global Volume Control"