diff options
author | Rick Pasetto <rick@lindenlab.com> | 2010-02-16 15:54:32 -0800 |
---|---|---|
committer | Rick Pasetto <rick@lindenlab.com> | 2010-02-16 15:54:32 -0800 |
commit | 204ff1edd9139b253e2f2b32fa75c04a737d77bf (patch) | |
tree | 7d441a50b18872c6a0e32c91f0a1ca147dc32b29 /indra/newview | |
parent | 1513643e62a88531888f330e57aa1eb623061729 (diff) | |
parent | 4dfed6e353ff880fcd45b4c8b402bf0f5a2f19f2 (diff) |
Automated merge with ssh://rick@hg.lindenlab.com/viewer/viewer-2-0
Diffstat (limited to 'indra/newview')
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 Binary files differnew file mode 100644 index 0000000000..361fab59e0 --- /dev/null +++ b/indra/newview/skins/default/textures/windows/Flyout_Pointer_Up.png 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"><empty></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 >>" + label_selected="Less <<"> + <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" |