From c8ee05a2712e56a7cdcb2b9e25c8b092c088d4d4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Feb 2024 01:31:05 +0200 Subject: Triage Issue #49 Better inspection of media urls Part 1: Ability to copy urls from nearby media for inspection --- indra/newview/llpanelnearbymedia.cpp | 84 ++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 8 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index 3c3cd5d522..c911f102a1 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -30,6 +30,7 @@ #include "llaudioengine.h" #include "llcheckboxctrl.h" +#include "llclipboard.h" #include "llcombobox.h" #include "llresizebar.h" #include "llresizehandle.h" @@ -53,7 +54,9 @@ #include "llvovolume.h" #include "llstatusbar.h" #include "llsdutil.h" +#include "lltoggleablemenu.h" #include "llvieweraudio.h" +#include "llviewermenu.h" #include "llfloaterreg.h" #include "llfloaterpreference.h" // for the gear icon @@ -77,7 +80,8 @@ LLPanelNearByMedia::LLPanelNearByMedia() mAllMediaDisabled(false), mDebugInfoVisible(false), mParcelMediaItem(NULL), - mParcelAudioItem(NULL) + mParcelAudioItem(NULL), + mMoreLessBtn(NULL) { // This is just an initial value, mParcelAudioAutoStart does not affect ParcelMediaAutoPlayEnable mParcelAudioAutoStart = gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0 @@ -96,7 +100,14 @@ LLPanelNearByMedia::LLPanelNearByMedia() 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)); - + + // Context menu handler. + mCommitCallbackRegistrar.add("SelectedMediaCtrl.Action", + [this](LLUICtrl* ctrl, const LLSD& data) + { + onMenuAction(data); + }); + buildFromFile( "panel_nearby_media.xml"); } @@ -147,7 +158,8 @@ BOOL LLPanelNearByMedia::postBuild() mUnzoomCtrl = getChild("unzoom"); mVolumeSlider = getChild("volume_slider"); mMuteBtn = getChild("mute_btn"); - + mMoreLessBtn = getChild("more_btn"); + mEmptyNameString = getString("empty_item_text"); mParcelMediaName = getString("parcel_media_name"); mParcelAudioName = getString("parcel_audio_name"); @@ -166,8 +178,13 @@ BOOL LLPanelNearByMedia::postBuild() mLessRect = getRect(); mLessRect.mBottom = minimized_controls->getRect().mBottom; - getChild("more_btn")->setVisible(false); + mMoreLessBtn->setVisible(false); onMoreLess(); + + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile( + "menu_nearby_media.xml", + gMenuHolder, + LLViewerMenuHolderGL::child_registry_t::instance()); return TRUE; } @@ -193,8 +210,7 @@ void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent) { LLPanelPulldown::reshape(width, height, called_from_parent); - LLButton* more_btn = findChild("more_btn"); - if (more_btn && more_btn->getValue().asBoolean()) + if (mMoreLessBtn && mMoreLessBtn->getValue().asBoolean()) { mMoreRect = getRect(); } @@ -234,6 +250,26 @@ BOOL LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) return true; } +BOOL LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + S32 x_list, y_list; + localPointToOtherView(x, y, &x_list, &y_list, mMediaList); + if (mMoreLessBtn->getToggleState() + && mMediaList->pointInView(x_list, y_list) + && mMediaList->selectItemAt(x_list, y_list, mask)) + { + if (mContextMenu) + { + mContextMenu->buildDrawLabels(); + mContextMenu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, mContextMenu, x, y); + return TRUE; + } + } + + return LLPanelPulldown::handleRightMouseDown(x, y, mask); +} + bool LLPanelNearByMedia::getParcelAudioAutoStart() { return mParcelAudioAutoStart; @@ -923,7 +959,7 @@ void LLPanelNearByMedia::onAdvancedButtonClick() void LLPanelNearByMedia::onMoreLess() { - bool is_more = getChild("more_btn")->getToggleState(); + bool is_more = mMoreLessBtn->getToggleState(); mNearbyMediaPanel->setVisible(is_more); // enable resizing when expanded @@ -934,7 +970,7 @@ void LLPanelNearByMedia::onMoreLess() setShape(new_rect); - getChild("more_btn")->setVisible(true); + mMoreLessBtn->setVisible(true); } void LLPanelNearByMedia::updateControls() @@ -1174,6 +1210,38 @@ void LLPanelNearByMedia::onClickSelectedMediaUnzoom() LLViewerMediaFocus::getInstance()->unZoom(); } +void LLPanelNearByMedia::onMenuAction(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + if ("copy" == command_name) + { + LLClipboard::instance().reset(); + LLUUID selected_media_id = mMediaList->getValue().asUUID(); + std::string url; + + if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) + { + url = LLViewerMedia::getInstance()->getParcelAudioURL(); + } + else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) + { + url = LLViewerParcelMedia::getInstance()->getURL(); + } + else + { + LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + if (NULL != impl) + { + url = impl->getCurrentMediaURL(); + } + } + + if (!url.empty()) + { + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); + } + } +} // static void LLPanelNearByMedia::getNameAndUrlHelper(LLViewerMediaImpl* impl, std::string& name, std::string & url, const std::string &defaultName) -- cgit v1.2.3 From b8952923ac2564f85b83da6893f89a6a45c952fd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Feb 2024 23:06:55 +0200 Subject: Triage Issue #49 Better inspection of data urls in media --- indra/newview/llpanelnearbymedia.cpp | 83 ++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 14 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index c911f102a1..83f0fca1be 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -29,6 +29,7 @@ #include "llpanelnearbymedia.h" #include "llaudioengine.h" +#include "llbase64.h" #include "llcheckboxctrl.h" #include "llclipboard.h" #include "llcombobox.h" @@ -107,6 +108,11 @@ LLPanelNearByMedia::LLPanelNearByMedia() { onMenuAction(data); }); + mEnableCallbackRegistrar.add("SelectedMediaCtrl.Visible", + [this](LLUICtrl* ctrl, const LLSD& data) + { + return onMenuVisible(data); + }); buildFromFile( "panel_nearby_media.xml"); } @@ -270,6 +276,16 @@ BOOL LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLPanelPulldown::handleRightMouseDown(x, y, mask); } + +void LLPanelNearByMedia::onVisibilityChange(BOOL new_visibility) +{ + if (!new_visibility && mContextMenu->getVisible()) + { + gMenuHolder->hideMenus(); + } + LLPanelPulldown::onVisibilityChange(new_visibility); +} + bool LLPanelNearByMedia::getParcelAudioAutoStart() { return mParcelAudioAutoStart; @@ -1213,34 +1229,49 @@ void LLPanelNearByMedia::onClickSelectedMediaUnzoom() void LLPanelNearByMedia::onMenuAction(const LLSD& userdata) { const std::string command_name = userdata.asString(); - if ("copy" == command_name) + if ("copy_url" == command_name) { LLClipboard::instance().reset(); - LLUUID selected_media_id = mMediaList->getValue().asUUID(); - std::string url; + std::string url = getSelectedUrl(); - if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) + if (!url.empty()) { - url = LLViewerMedia::getInstance()->getParcelAudioURL(); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); } - else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) + } + else if ("copy_data" == command_name) + { + LLClipboard::instance().reset(); + std::string url = getSelectedUrl(); + static const std::string encoding_specifier = "base64,"; + size_t pos = url.find(encoding_specifier); + if (pos != std::string::npos) { - url = LLViewerParcelMedia::getInstance()->getURL(); + pos += encoding_specifier.size(); + std::string res = LLBase64::decodeAsString(url.substr(pos)); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(res), 0, res.size()); } else { - LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); - if (NULL != impl) - { - url = impl->getCurrentMediaURL(); - } + url = LLURI::unescape(url); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); } + } +} - if (!url.empty()) +bool LLPanelNearByMedia::onMenuVisible(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + if ("copy_data" == command_name) + { + std::string url = getSelectedUrl(); + if (url.rfind("data:", 0) == 0) { - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); + // might be a a good idea to permit text/html only + return true; } } + return false; } // static @@ -1268,3 +1299,27 @@ void LLPanelNearByMedia::getNameAndUrlHelper(LLViewerMediaImpl* impl, std::strin } } +std::string LLPanelNearByMedia::getSelectedUrl() +{ + std::string url; + LLUUID selected_media_id = mMediaList->getValue().asUUID(); + if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) + { + url = LLViewerMedia::getInstance()->getParcelAudioURL(); + } + else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) + { + url = LLViewerParcelMedia::getInstance()->getURL(); + } + else + { + LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + if (NULL != impl) + { + std::string name; + getNameAndUrlHelper(impl, name, url, mEmptyNameString); + } + } + return url; +} + -- cgit v1.2.3 From 165f7bf35047e9106a7ccb2530fd2bfdf8e6259c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 10 Feb 2024 00:02:29 +0200 Subject: Triage Issue #49 Fix MacOS build failure --- indra/newview/llpanelnearbymedia.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index 83f0fca1be..eaf339a295 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -78,7 +78,6 @@ static const LLUUID PARCEL_AUDIO_LIST_ITEM_UUID = LLUUID("DF4B020D-8A24-4B95-AB5 LLPanelNearByMedia::LLPanelNearByMedia() : mMediaList(NULL), mEnableAllCtrl(NULL), - mAllMediaDisabled(false), mDebugInfoVisible(false), mParcelMediaItem(NULL), mParcelAudioItem(NULL), -- cgit v1.2.3 From c285f59ce2a05703e3a1232fcaf3ee3aea714b3f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 18 Feb 2024 12:52:19 +0100 Subject: Replace BOOL with bool in llwindow and dependent classes --- indra/newview/llpanelnearbymedia.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index eaf339a295..aed7c34a64 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -241,7 +241,7 @@ void LLPanelNearByMedia::draw() } /*virtual*/ -BOOL LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) +bool LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) { LLPanelPulldown::handleHover(x, y, mask); @@ -255,7 +255,7 @@ BOOL LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) return true; } -BOOL LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) +bool LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) { S32 x_list, y_list; localPointToOtherView(x, y, &x_list, &y_list, mMediaList); @@ -268,7 +268,7 @@ BOOL LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) mContextMenu->buildDrawLabels(); mContextMenu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, mContextMenu, x, y); - return TRUE; + return true; } } -- cgit v1.2.3 From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llpanelnearbymedia.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index aed7c34a64..a8553b654e 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -120,7 +120,7 @@ LLPanelNearByMedia::~LLPanelNearByMedia() { } -BOOL LLPanelNearByMedia::postBuild() +bool LLPanelNearByMedia::postBuild() { LLPanelPulldown::postBuild(); @@ -171,8 +171,8 @@ BOOL LLPanelNearByMedia::postBuild() mPlayingString = getString("playing_suffix"); mMediaList->setDoubleClickCallback(onZoomMedia, this); - mMediaList->sortByColumnIndex(PROXIMITY_COLUMN, TRUE); - mMediaList->sortByColumnIndex(VISIBILITY_COLUMN, FALSE); + mMediaList->sortByColumnIndex(PROXIMITY_COLUMN, true); + mMediaList->sortByColumnIndex(VISIBILITY_COLUMN, false); refreshList(); updateControls(); @@ -191,7 +191,7 @@ BOOL LLPanelNearByMedia::postBuild() gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - return TRUE; + return true; } void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) @@ -211,7 +211,7 @@ void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) } /*virtual*/ -void LLPanelNearByMedia::reshape(S32 width, S32 height, BOOL called_from_parent) +void LLPanelNearByMedia::reshape(S32 width, S32 height, bool called_from_parent) { LLPanelPulldown::reshape(width, height, called_from_parent); @@ -276,7 +276,7 @@ bool LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) } -void LLPanelNearByMedia::onVisibilityChange(BOOL new_visibility) +void LLPanelNearByMedia::onVisibilityChange(bool new_visibility) { if (!new_visibility && mContextMenu->getVisible()) { -- cgit v1.2.3 From fb17c00f14b2ee9238287284f0d660311f1e4f54 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 14 May 2024 20:55:27 +0300 Subject: triage#49 Menu didn't work for already selected items --- indra/newview/llpanelnearbymedia.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index a8553b654e..36605fed7a 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -260,10 +260,16 @@ bool LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) S32 x_list, y_list; localPointToOtherView(x, y, &x_list, &y_list, mMediaList); if (mMoreLessBtn->getToggleState() - && mMediaList->pointInView(x_list, y_list) - && mMediaList->selectItemAt(x_list, y_list, mask)) + && mMediaList->pointInView(x_list, y_list)) { - if (mContextMenu) + LLScrollListItem* hit_item = mMediaList->hitItem(x_list, y_list); + bool selected = hit_item && hit_item->getSelected(); + if (!selected) + { + selected = mMediaList->selectItemAt(x_list, y_list, mask); + } + + if (selected && mContextMenu) { mContextMenu->buildDrawLabels(); mContextMenu->updateParent(LLMenuGL::sMenuContainer); -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llpanelnearbymedia.cpp | 2660 +++++++++++++++++----------------- 1 file changed, 1330 insertions(+), 1330 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index 22ca26e500..aa60c5cf6c 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -1,1330 +1,1330 @@ -/** - * @file llpanelnearbymedia.cpp - * @brief Management interface for muting and controlling nearby media - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelnearbymedia.h" - -#include "llaudioengine.h" -#include "llbase64.h" -#include "llcheckboxctrl.h" -#include "llclipboard.h" -#include "llcombobox.h" -#include "llresizebar.h" -#include "llresizehandle.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 "llviewerparcelaskplay.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 "lltoggleablemenu.h" -#include "llvieweraudio.h" -#include "llviewermenu.h" - -#include "llfloaterreg.h" -#include "llfloaterpreference.h" // for the gear icon -#include "lltabcontainer.h" - -#include - -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), - mDebugInfoVisible(false), - mParcelMediaItem(NULL), - mParcelAudioItem(NULL), - mMoreLessBtn(NULL) -{ - // This is just an initial value, mParcelAudioAutoStart does not affect ParcelMediaAutoPlayEnable - mParcelAudioAutoStart = gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0 - && gSavedSettings.getBOOL("MediaTentativeAutoPlay"); - - gSavedSettings.getControl("ParcelMediaAutoPlayEnable")->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2)); - - 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)); - - // Context menu handler. - mCommitCallbackRegistrar.add("SelectedMediaCtrl.Action", - [this](LLUICtrl* ctrl, const LLSD& data) - { - onMenuAction(data); - }); - mEnableCallbackRegistrar.add("SelectedMediaCtrl.Visible", - [this](LLUICtrl* ctrl, const LLSD& data) - { - return onMenuVisible(data); - }); - - buildFromFile( "panel_nearby_media.xml"); -} - -LLPanelNearByMedia::~LLPanelNearByMedia() -{ -} - -bool LLPanelNearByMedia::postBuild() -{ - LLPanelPulldown::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(p) ); - - p.rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); - p.name = "resizebar_left"; - p.min_size = getRect().getWidth(); - p.side = LLResizeBar::LEFT; - addChild( LLUICtrlFactory::create(p) ); - - LLResizeHandle::Params resize_handle_p; - resize_handle_p.rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); - resize_handle_p.mouse_opaque(false); - resize_handle_p.min_width(getRect().getWidth()); - resize_handle_p.min_height(getRect().getHeight()); - resize_handle_p.corner(LLResizeHandle::LEFT_BOTTOM); - addChild(LLUICtrlFactory::create(resize_handle_p)); - - mNearbyMediaPanel = getChild("nearby_media_panel"); - mMediaList = getChild("media_list"); - mEnableAllCtrl = getChild("all_nearby_media_enable_btn"); - mDisableAllCtrl = getChild("all_nearby_media_disable_btn"); - mShowCtrl = getChild("show_combo"); - - // Dynamic (selection-dependent) controls - mStopCtrl = getChild("stop"); - mPlayCtrl = getChild("play"); - mPauseCtrl = getChild("pause"); - mMuteCtrl = getChild("mute"); - mVolumeSliderCtrl = getChild("volume_slider_ctrl"); - mZoomCtrl = getChild("zoom"); - mUnzoomCtrl = getChild("unzoom"); - mVolumeSlider = getChild("volume_slider"); - mMuteBtn = getChild("mute_btn"); - mMoreLessBtn = getChild("more_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"); - mMoreRect = getRect(); - mLessRect = getRect(); - mLessRect.mBottom = minimized_controls->getRect().mBottom; - - mMoreLessBtn->setVisible(false); - onMoreLess(); - - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile( - "menu_nearby_media.xml", - gMenuHolder, - LLViewerMenuHolderGL::child_registry_t::instance()); - - return true; -} - -void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) -{ - // update mParcelAudioAutoStartMode if "ParcelMediaAutoPlayEnable" changes - S32 value = gSavedSettings.getS32("ParcelMediaAutoPlayEnable"); - mParcelAudioAutoStart = value != 0 - && gSavedSettings.getBOOL("MediaTentativeAutoPlay"); - - LLViewerParcelAskPlay *inst = LLViewerParcelAskPlay::getInstance(); - if (value == 2 && !inst->hasData()) - { - // Init if nessesary - inst->loadSettings(); - } - inst->cancelNotification(); -} - -/*virtual*/ -void LLPanelNearByMedia::reshape(S32 width, S32 height, bool called_from_parent) -{ - LLPanelPulldown::reshape(width, height, called_from_parent); - - if (mMoreLessBtn && mMoreLessBtn->getValue().asBoolean()) - { - mMoreRect = getRect(); - } - -} - -/*virtual*/ -void LLPanelNearByMedia::draw() -{ - // 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); - } - - refreshList(); - updateControls(); - - LLPanelPulldown::draw(); -} - -/*virtual*/ -bool LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) -{ - LLPanelPulldown::handleHover(x, y, mask); - - // If we are hovering over this panel, make sure to clear any hovered media - // ID. Note that the more general solution would be to clear this ID when - // the mouse leaves the in-scene view, but that proved to be problematic. - // See EXT-5517 - LLViewerMediaFocus::getInstance()->clearHover(); - - // Always handle - return true; -} - -bool LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) -{ - S32 x_list, y_list; - localPointToOtherView(x, y, &x_list, &y_list, mMediaList); - if (mMoreLessBtn->getToggleState() - && mMediaList->pointInView(x_list, y_list)) - { - LLScrollListItem* hit_item = mMediaList->hitItem(x_list, y_list); - bool selected = hit_item && hit_item->getSelected(); - if (!selected) - { - selected = mMediaList->selectItemAt(x_list, y_list, mask); - } - - if (selected && mContextMenu) - { - mContextMenu->buildDrawLabels(); - mContextMenu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, mContextMenu, x, y); - return true; - } - } - - return LLPanelPulldown::handleRightMouseDown(x, y, mask); -} - - -void LLPanelNearByMedia::onVisibilityChange(bool new_visibility) -{ - if (!new_visibility && mContextMenu->getVisible()) - { - gMenuHolder->hideMenus(); - } - LLPanelPulldown::onVisibilityChange(new_visibility); -} - -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(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/", (F32) sqrt(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 (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)); - mMediaList->updateLayout(); -} - -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 - // (and if media is "enabled") - bool should_include = (choice == MEDIA_CLASS_ALL || choice == MEDIA_CLASS_WITHIN_PARCEL); - LLViewerMedia* media_inst = LLViewerMedia::getInstance(); - - // First Parcel Media: add or remove it as necessary - if (gSavedSettings.getBOOL("AudioStreamingMedia") && should_include && media_inst->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::getInstance()->getParcelMedia(), name, url, ""); - if (name.empty() || name == url) - { - tooltip = url; - } - else - { - tooltip = name + " : " + url; - } - LLViewerMediaImpl *impl = LLViewerParcelMedia::getInstance()->getParcelMedia(); - updateListItem(mParcelMediaItem, - mParcelMediaName, - tooltip, - -2, // Proximity closer than anything else, before Parcel Audio - impl == NULL || impl->isMediaDisabled(), - impl != NULL && !LLViewerParcelMedia::getInstance()->getURL().empty(), - impl != NULL && impl->isMediaTimeBased() && impl->isMediaPlaying(), - MEDIA_CLASS_ALL, - "parcel media"); - } - - // Next Parcel Audio: add or remove it as necessary (don't show if disabled in prefs) - if (should_include && media_inst->hasParcelAudio() && gSavedSettings.getBOOL("AudioStreamingMusic")) - { - // 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 = media_inst->isParcelAudioPlaying(); - - std::string url; - url = media_inst->getParcelAudioURL(); - - updateListItem(mParcelAudioItem, - mParcelAudioName, - url, - -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(); - mParcelAudioItem = NULL; - mParcelMediaItem = NULL; - all_items_deleted = true; - - updateColumns(); - } - - refreshParcelItems(); - - // Get the canonical list from LLViewerMedia - LLViewerMedia* media_inst = LLViewerMedia::getInstance(); - LLViewerMedia::impl_list impls = media_inst->getPriorityList(); - LLViewerMedia::impl_list::iterator priority_iter; - - 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++; - } - } - } - mDisableAllCtrl->setEnabled((gSavedSettings.getBOOL("AudioStreamingMusic") || - gSavedSettings.getBOOL("AudioStreamingMedia")) && - (media_inst->isAnyMediaShowing() || - media_inst->isParcelMediaPlaying() || - media_inst->isParcelAudioPlaying())); - - mEnableAllCtrl->setEnabled( (gSavedSettings.getBOOL("AudioStreamingMusic") || - gSavedSettings.getBOOL("AudioStreamingMedia")) && - (disabled_count > 0 || - // parcel media (if we have it, and it isn't playing, enable "start") - (media_inst->hasParcelMedia() && ! media_inst->isParcelMediaPlaying()) || - // parcel audio (if we have it, and it isn't playing, enable "start") - (media_inst->hasParcelAudio() && ! media_inst->isParcelAudioPlaying()))); - - // Iterate over the rows in the control, updating ones whose impl exists, and deleting ones whose impl has gone away. - std::vector items = mMediaList->getAllData(); - - for (std::vector::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 = media_inst->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::getInstance()->setAllMediaEnabled(true); -} - -void LLPanelNearByMedia::onClickDisableAll() -{ - LLViewerMedia::getInstance()->setAllMediaEnabled(false); -} - -void LLPanelNearByMedia::onClickEnableParcelMedia() -{ - if ( ! LLViewerMedia::getInstance()->isParcelMediaPlaying() ) - { - LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); - } -} - -void LLPanelNearByMedia::onClickDisableParcelMedia() -{ - // This actually unloads the impl, as opposed to "stop"ping the media - LLViewerParcelMedia::getInstance()->stop(); -} - -void LLPanelNearByMedia::onCheckItem(LLUICtrl* ctrl, const LLUUID &row_id) -{ - LLCheckBoxCtrl* check = static_cast(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 - { - onClickParcelAudioPlay(); - } - return true; - } - else if (row_id == PARCEL_MEDIA_LIST_ITEM_UUID) - { - if (disabled) - { - onClickDisableParcelMedia(); - } - else - { - onClickEnableParcelMedia(); - } - return true; - } - else { - LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->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::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); -} - -void LLPanelNearByMedia::onClickParcelMediaStop() -{ - if (LLViewerParcelMedia::getInstance()->getParcelMedia()) - { - // This stops the media playing, as opposed to unloading it like - // LLViewerParcelMedia::stop() does - LLViewerParcelMedia::getInstance()->getParcelMedia()->stop(); - } -} - -void LLPanelNearByMedia::onClickParcelMediaPause() -{ - LLViewerParcelMedia::getInstance()->pause(); -} - -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) - { - LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; - return; - } - - if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying()) - { - // 'false' means unpause - gAudiop->pauseInternetStream(false); - } - else - { - LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLViewerMedia::getInstance()->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) - { - LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; - return; - } - - LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade(); -} - -void LLPanelNearByMedia::onClickParcelAudioPause() -{ - if (!gAudiop) - { - LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; - 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(LLFloaterReg::showInstance("preferences")); - if (prefsfloater) - { - // grab the 'audio' panel from the preferences floater and - // bring it the front! - LLTabContainer* tabcontainer = prefsfloater->getChild("pref core"); - LLPanel* audiopanel = prefsfloater->getChild("audio"); - if (tabcontainer && audiopanel) - { - tabcontainer->selectTabPanel(audiopanel); - } - } -} - -void LLPanelNearByMedia::onMoreLess() -{ - bool is_more = mMoreLessBtn->getToggleState(); - mNearbyMediaPanel->setVisible(is_more); - - // enable resizing when expanded - getChildView("resizebar_bottom")->setEnabled(is_more); - - LLRect new_rect = is_more ? mMoreRect : mLessRect; - new_rect.translate(getRect().mRight - new_rect.mRight, getRect().mTop - new_rect.mTop); - - setShape(new_rect); - - mMoreLessBtn->setVisible(true); -} - -void LLPanelNearByMedia::updateControls() -{ - LLUUID selected_media_id = mMediaList->getValue().asUUID(); - LLViewerMedia* media_inst = LLViewerMedia::getInstance(); - - if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) - { - if (!media_inst->getInstance()->hasParcelAudio() || !gSavedSettings.getBOOL("AudioStreamingMusic")) - { - // disable controls if audio streaming music is disabled from preference - showDisabledControls(); - } - else { - showTimeBasedControls(media_inst->isParcelAudioPlaying(), - false, // include_zoom - false, // is_zoomed - gSavedSettings.getBOOL("MuteMusic"), - gSavedSettings.getF32("AudioLevelMusic") ); - } - } - else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) - { - if (!media_inst->hasParcelMedia() || !gSavedSettings.getBOOL("AudioStreamingMedia")) - { - // disable controls if audio streaming media is disabled from preference - showDisabledControls(); - } - else { - LLViewerMediaImpl* impl = LLViewerParcelMedia::getInstance()->getParcelMedia(); - if (NULL == impl) - { - // Just means it hasn't started yet - showBasicControls(false, false, false, false, 0); - } - 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(media_inst->isParcelMediaPlaying(), - false, - false, - impl->getVolume() == 0.0, - impl->getVolume()); - } - } - } - else { - LLViewerMediaImpl* impl = media_inst->getMediaImplFromTextureID(selected_media_id); - - if (NULL == impl || !gSavedSettings.getBOOL("AudioStreamingMedia")) - { - 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()->isZoomedOnMedia(impl->getMediaTextureID()), - impl->getVolume() == 0.0, - impl->getVolume()); - } - } - } -} - -void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume) -{ - mStopCtrl->setVisible(playing); - mPlayCtrl->setVisible(!playing); - mPauseCtrl->setVisible(false); - mVolumeSliderCtrl->setVisible(true); - mMuteCtrl->setVisible(true); - mMuteBtn->setValue(muted); - mVolumeSlider->setValue(volume); - 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::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); - if (NULL != impl) - { - if (impl->isMediaTimeBased() && impl->isMediaPaused()) - { - // Aha! It's really time-based media that's paused, so unpause - impl->play(); - return; - } - else if (impl->isParcelMedia()) - { - LLViewerParcelMedia::getInstance()->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::getInstance()->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::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); - if (NULL != impl) - { - F32 volume = impl->getVolume(); - if(volume > 0.0) - { - impl->setMute(true); - } - else if (mVolumeSlider->getValueF32() == 0.0) - { - impl->setMute(false); - mVolumeSlider->setValue(impl->getVolume()); - } - 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::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); - if (NULL != impl) - { - 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(); -} - -void LLPanelNearByMedia::onMenuAction(const LLSD& userdata) -{ - const std::string command_name = userdata.asString(); - if ("copy_url" == command_name) - { - LLClipboard::instance().reset(); - std::string url = getSelectedUrl(); - - if (!url.empty()) - { - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); - } - } - else if ("copy_data" == command_name) - { - LLClipboard::instance().reset(); - std::string url = getSelectedUrl(); - static const std::string encoding_specifier = "base64,"; - size_t pos = url.find(encoding_specifier); - if (pos != std::string::npos) - { - pos += encoding_specifier.size(); - std::string res = LLBase64::decodeAsString(url.substr(pos)); - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(res), 0, res.size()); - } - else - { - url = LLURI::unescape(url); - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); - } - } -} - -bool LLPanelNearByMedia::onMenuVisible(const LLSD& userdata) -{ - const std::string command_name = userdata.asString(); - if ("copy_data" == command_name) - { - std::string url = getSelectedUrl(); - if (url.rfind("data:", 0) == 0) - { - // might be a a good idea to permit text/html only - return true; - } - } - return false; -} - -// 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; - } -} - -std::string LLPanelNearByMedia::getSelectedUrl() -{ - std::string url; - LLUUID selected_media_id = mMediaList->getValue().asUUID(); - if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) - { - url = LLViewerMedia::getInstance()->getParcelAudioURL(); - } - else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) - { - url = LLViewerParcelMedia::getInstance()->getURL(); - } - else - { - LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); - if (NULL != impl) - { - std::string name; - getNameAndUrlHelper(impl, name, url, mEmptyNameString); - } - } - return url; -} - +/** + * @file llpanelnearbymedia.cpp + * @brief Management interface for muting and controlling nearby media + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelnearbymedia.h" + +#include "llaudioengine.h" +#include "llbase64.h" +#include "llcheckboxctrl.h" +#include "llclipboard.h" +#include "llcombobox.h" +#include "llresizebar.h" +#include "llresizehandle.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 "llviewerparcelaskplay.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 "lltoggleablemenu.h" +#include "llvieweraudio.h" +#include "llviewermenu.h" + +#include "llfloaterreg.h" +#include "llfloaterpreference.h" // for the gear icon +#include "lltabcontainer.h" + +#include + +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), + mDebugInfoVisible(false), + mParcelMediaItem(NULL), + mParcelAudioItem(NULL), + mMoreLessBtn(NULL) +{ + // This is just an initial value, mParcelAudioAutoStart does not affect ParcelMediaAutoPlayEnable + mParcelAudioAutoStart = gSavedSettings.getS32("ParcelMediaAutoPlayEnable") != 0 + && gSavedSettings.getBOOL("MediaTentativeAutoPlay"); + + gSavedSettings.getControl("ParcelMediaAutoPlayEnable")->getSignal()->connect(boost::bind(&LLPanelNearByMedia::handleMediaAutoPlayChanged, this, _2)); + + 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)); + + // Context menu handler. + mCommitCallbackRegistrar.add("SelectedMediaCtrl.Action", + [this](LLUICtrl* ctrl, const LLSD& data) + { + onMenuAction(data); + }); + mEnableCallbackRegistrar.add("SelectedMediaCtrl.Visible", + [this](LLUICtrl* ctrl, const LLSD& data) + { + return onMenuVisible(data); + }); + + buildFromFile( "panel_nearby_media.xml"); +} + +LLPanelNearByMedia::~LLPanelNearByMedia() +{ +} + +bool LLPanelNearByMedia::postBuild() +{ + LLPanelPulldown::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(p) ); + + p.rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); + p.name = "resizebar_left"; + p.min_size = getRect().getWidth(); + p.side = LLResizeBar::LEFT; + addChild( LLUICtrlFactory::create(p) ); + + LLResizeHandle::Params resize_handle_p; + resize_handle_p.rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); + resize_handle_p.mouse_opaque(false); + resize_handle_p.min_width(getRect().getWidth()); + resize_handle_p.min_height(getRect().getHeight()); + resize_handle_p.corner(LLResizeHandle::LEFT_BOTTOM); + addChild(LLUICtrlFactory::create(resize_handle_p)); + + mNearbyMediaPanel = getChild("nearby_media_panel"); + mMediaList = getChild("media_list"); + mEnableAllCtrl = getChild("all_nearby_media_enable_btn"); + mDisableAllCtrl = getChild("all_nearby_media_disable_btn"); + mShowCtrl = getChild("show_combo"); + + // Dynamic (selection-dependent) controls + mStopCtrl = getChild("stop"); + mPlayCtrl = getChild("play"); + mPauseCtrl = getChild("pause"); + mMuteCtrl = getChild("mute"); + mVolumeSliderCtrl = getChild("volume_slider_ctrl"); + mZoomCtrl = getChild("zoom"); + mUnzoomCtrl = getChild("unzoom"); + mVolumeSlider = getChild("volume_slider"); + mMuteBtn = getChild("mute_btn"); + mMoreLessBtn = getChild("more_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"); + mMoreRect = getRect(); + mLessRect = getRect(); + mLessRect.mBottom = minimized_controls->getRect().mBottom; + + mMoreLessBtn->setVisible(false); + onMoreLess(); + + mContextMenu = LLUICtrlFactory::getInstance()->createFromFile( + "menu_nearby_media.xml", + gMenuHolder, + LLViewerMenuHolderGL::child_registry_t::instance()); + + return true; +} + +void LLPanelNearByMedia::handleMediaAutoPlayChanged(const LLSD& newvalue) +{ + // update mParcelAudioAutoStartMode if "ParcelMediaAutoPlayEnable" changes + S32 value = gSavedSettings.getS32("ParcelMediaAutoPlayEnable"); + mParcelAudioAutoStart = value != 0 + && gSavedSettings.getBOOL("MediaTentativeAutoPlay"); + + LLViewerParcelAskPlay *inst = LLViewerParcelAskPlay::getInstance(); + if (value == 2 && !inst->hasData()) + { + // Init if nessesary + inst->loadSettings(); + } + inst->cancelNotification(); +} + +/*virtual*/ +void LLPanelNearByMedia::reshape(S32 width, S32 height, bool called_from_parent) +{ + LLPanelPulldown::reshape(width, height, called_from_parent); + + if (mMoreLessBtn && mMoreLessBtn->getValue().asBoolean()) + { + mMoreRect = getRect(); + } + +} + +/*virtual*/ +void LLPanelNearByMedia::draw() +{ + // 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); + } + + refreshList(); + updateControls(); + + LLPanelPulldown::draw(); +} + +/*virtual*/ +bool LLPanelNearByMedia::handleHover(S32 x, S32 y, MASK mask) +{ + LLPanelPulldown::handleHover(x, y, mask); + + // If we are hovering over this panel, make sure to clear any hovered media + // ID. Note that the more general solution would be to clear this ID when + // the mouse leaves the in-scene view, but that proved to be problematic. + // See EXT-5517 + LLViewerMediaFocus::getInstance()->clearHover(); + + // Always handle + return true; +} + +bool LLPanelNearByMedia::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + S32 x_list, y_list; + localPointToOtherView(x, y, &x_list, &y_list, mMediaList); + if (mMoreLessBtn->getToggleState() + && mMediaList->pointInView(x_list, y_list)) + { + LLScrollListItem* hit_item = mMediaList->hitItem(x_list, y_list); + bool selected = hit_item && hit_item->getSelected(); + if (!selected) + { + selected = mMediaList->selectItemAt(x_list, y_list, mask); + } + + if (selected && mContextMenu) + { + mContextMenu->buildDrawLabels(); + mContextMenu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, mContextMenu, x, y); + return true; + } + } + + return LLPanelPulldown::handleRightMouseDown(x, y, mask); +} + + +void LLPanelNearByMedia::onVisibilityChange(bool new_visibility) +{ + if (!new_visibility && mContextMenu->getVisible()) + { + gMenuHolder->hideMenus(); + } + LLPanelPulldown::onVisibilityChange(new_visibility); +} + +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(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/", (F32) sqrt(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 (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)); + mMediaList->updateLayout(); +} + +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 + // (and if media is "enabled") + bool should_include = (choice == MEDIA_CLASS_ALL || choice == MEDIA_CLASS_WITHIN_PARCEL); + LLViewerMedia* media_inst = LLViewerMedia::getInstance(); + + // First Parcel Media: add or remove it as necessary + if (gSavedSettings.getBOOL("AudioStreamingMedia") && should_include && media_inst->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::getInstance()->getParcelMedia(), name, url, ""); + if (name.empty() || name == url) + { + tooltip = url; + } + else + { + tooltip = name + " : " + url; + } + LLViewerMediaImpl *impl = LLViewerParcelMedia::getInstance()->getParcelMedia(); + updateListItem(mParcelMediaItem, + mParcelMediaName, + tooltip, + -2, // Proximity closer than anything else, before Parcel Audio + impl == NULL || impl->isMediaDisabled(), + impl != NULL && !LLViewerParcelMedia::getInstance()->getURL().empty(), + impl != NULL && impl->isMediaTimeBased() && impl->isMediaPlaying(), + MEDIA_CLASS_ALL, + "parcel media"); + } + + // Next Parcel Audio: add or remove it as necessary (don't show if disabled in prefs) + if (should_include && media_inst->hasParcelAudio() && gSavedSettings.getBOOL("AudioStreamingMusic")) + { + // 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 = media_inst->isParcelAudioPlaying(); + + std::string url; + url = media_inst->getParcelAudioURL(); + + updateListItem(mParcelAudioItem, + mParcelAudioName, + url, + -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(); + mParcelAudioItem = NULL; + mParcelMediaItem = NULL; + all_items_deleted = true; + + updateColumns(); + } + + refreshParcelItems(); + + // Get the canonical list from LLViewerMedia + LLViewerMedia* media_inst = LLViewerMedia::getInstance(); + LLViewerMedia::impl_list impls = media_inst->getPriorityList(); + LLViewerMedia::impl_list::iterator priority_iter; + + 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++; + } + } + } + mDisableAllCtrl->setEnabled((gSavedSettings.getBOOL("AudioStreamingMusic") || + gSavedSettings.getBOOL("AudioStreamingMedia")) && + (media_inst->isAnyMediaShowing() || + media_inst->isParcelMediaPlaying() || + media_inst->isParcelAudioPlaying())); + + mEnableAllCtrl->setEnabled( (gSavedSettings.getBOOL("AudioStreamingMusic") || + gSavedSettings.getBOOL("AudioStreamingMedia")) && + (disabled_count > 0 || + // parcel media (if we have it, and it isn't playing, enable "start") + (media_inst->hasParcelMedia() && ! media_inst->isParcelMediaPlaying()) || + // parcel audio (if we have it, and it isn't playing, enable "start") + (media_inst->hasParcelAudio() && ! media_inst->isParcelAudioPlaying()))); + + // Iterate over the rows in the control, updating ones whose impl exists, and deleting ones whose impl has gone away. + std::vector items = mMediaList->getAllData(); + + for (std::vector::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 = media_inst->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::getInstance()->setAllMediaEnabled(true); +} + +void LLPanelNearByMedia::onClickDisableAll() +{ + LLViewerMedia::getInstance()->setAllMediaEnabled(false); +} + +void LLPanelNearByMedia::onClickEnableParcelMedia() +{ + if ( ! LLViewerMedia::getInstance()->isParcelMediaPlaying() ) + { + LLViewerParcelMedia::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + } +} + +void LLPanelNearByMedia::onClickDisableParcelMedia() +{ + // This actually unloads the impl, as opposed to "stop"ping the media + LLViewerParcelMedia::getInstance()->stop(); +} + +void LLPanelNearByMedia::onCheckItem(LLUICtrl* ctrl, const LLUUID &row_id) +{ + LLCheckBoxCtrl* check = static_cast(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 + { + onClickParcelAudioPlay(); + } + return true; + } + else if (row_id == PARCEL_MEDIA_LIST_ITEM_UUID) + { + if (disabled) + { + onClickDisableParcelMedia(); + } + else + { + onClickEnableParcelMedia(); + } + return true; + } + else { + LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->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::getInstance()->play(LLViewerParcelMgr::getInstance()->getAgentParcel()); +} + +void LLPanelNearByMedia::onClickParcelMediaStop() +{ + if (LLViewerParcelMedia::getInstance()->getParcelMedia()) + { + // This stops the media playing, as opposed to unloading it like + // LLViewerParcelMedia::stop() does + LLViewerParcelMedia::getInstance()->getParcelMedia()->stop(); + } +} + +void LLPanelNearByMedia::onClickParcelMediaPause() +{ + LLViewerParcelMedia::getInstance()->pause(); +} + +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) + { + LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; + return; + } + + if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying()) + { + // 'false' means unpause + gAudiop->pauseInternetStream(false); + } + else + { + LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLViewerMedia::getInstance()->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) + { + LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; + return; + } + + LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade(); +} + +void LLPanelNearByMedia::onClickParcelAudioPause() +{ + if (!gAudiop) + { + LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; + 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(LLFloaterReg::showInstance("preferences")); + if (prefsfloater) + { + // grab the 'audio' panel from the preferences floater and + // bring it the front! + LLTabContainer* tabcontainer = prefsfloater->getChild("pref core"); + LLPanel* audiopanel = prefsfloater->getChild("audio"); + if (tabcontainer && audiopanel) + { + tabcontainer->selectTabPanel(audiopanel); + } + } +} + +void LLPanelNearByMedia::onMoreLess() +{ + bool is_more = mMoreLessBtn->getToggleState(); + mNearbyMediaPanel->setVisible(is_more); + + // enable resizing when expanded + getChildView("resizebar_bottom")->setEnabled(is_more); + + LLRect new_rect = is_more ? mMoreRect : mLessRect; + new_rect.translate(getRect().mRight - new_rect.mRight, getRect().mTop - new_rect.mTop); + + setShape(new_rect); + + mMoreLessBtn->setVisible(true); +} + +void LLPanelNearByMedia::updateControls() +{ + LLUUID selected_media_id = mMediaList->getValue().asUUID(); + LLViewerMedia* media_inst = LLViewerMedia::getInstance(); + + if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) + { + if (!media_inst->getInstance()->hasParcelAudio() || !gSavedSettings.getBOOL("AudioStreamingMusic")) + { + // disable controls if audio streaming music is disabled from preference + showDisabledControls(); + } + else { + showTimeBasedControls(media_inst->isParcelAudioPlaying(), + false, // include_zoom + false, // is_zoomed + gSavedSettings.getBOOL("MuteMusic"), + gSavedSettings.getF32("AudioLevelMusic") ); + } + } + else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) + { + if (!media_inst->hasParcelMedia() || !gSavedSettings.getBOOL("AudioStreamingMedia")) + { + // disable controls if audio streaming media is disabled from preference + showDisabledControls(); + } + else { + LLViewerMediaImpl* impl = LLViewerParcelMedia::getInstance()->getParcelMedia(); + if (NULL == impl) + { + // Just means it hasn't started yet + showBasicControls(false, false, false, false, 0); + } + 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(media_inst->isParcelMediaPlaying(), + false, + false, + impl->getVolume() == 0.0, + impl->getVolume()); + } + } + } + else { + LLViewerMediaImpl* impl = media_inst->getMediaImplFromTextureID(selected_media_id); + + if (NULL == impl || !gSavedSettings.getBOOL("AudioStreamingMedia")) + { + 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()->isZoomedOnMedia(impl->getMediaTextureID()), + impl->getVolume() == 0.0, + impl->getVolume()); + } + } + } +} + +void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume) +{ + mStopCtrl->setVisible(playing); + mPlayCtrl->setVisible(!playing); + mPauseCtrl->setVisible(false); + mVolumeSliderCtrl->setVisible(true); + mMuteCtrl->setVisible(true); + mMuteBtn->setValue(muted); + mVolumeSlider->setValue(volume); + 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::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + if (NULL != impl) + { + if (impl->isMediaTimeBased() && impl->isMediaPaused()) + { + // Aha! It's really time-based media that's paused, so unpause + impl->play(); + return; + } + else if (impl->isParcelMedia()) + { + LLViewerParcelMedia::getInstance()->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::getInstance()->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::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + if (NULL != impl) + { + F32 volume = impl->getVolume(); + if(volume > 0.0) + { + impl->setMute(true); + } + else if (mVolumeSlider->getValueF32() == 0.0) + { + impl->setMute(false); + mVolumeSlider->setValue(impl->getVolume()); + } + 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::getInstance()->getParcelMedia()) : LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + if (NULL != impl) + { + 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(); +} + +void LLPanelNearByMedia::onMenuAction(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + if ("copy_url" == command_name) + { + LLClipboard::instance().reset(); + std::string url = getSelectedUrl(); + + if (!url.empty()) + { + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); + } + } + else if ("copy_data" == command_name) + { + LLClipboard::instance().reset(); + std::string url = getSelectedUrl(); + static const std::string encoding_specifier = "base64,"; + size_t pos = url.find(encoding_specifier); + if (pos != std::string::npos) + { + pos += encoding_specifier.size(); + std::string res = LLBase64::decodeAsString(url.substr(pos)); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(res), 0, res.size()); + } + else + { + url = LLURI::unescape(url); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); + } + } +} + +bool LLPanelNearByMedia::onMenuVisible(const LLSD& userdata) +{ + const std::string command_name = userdata.asString(); + if ("copy_data" == command_name) + { + std::string url = getSelectedUrl(); + if (url.rfind("data:", 0) == 0) + { + // might be a a good idea to permit text/html only + return true; + } + } + return false; +} + +// 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; + } +} + +std::string LLPanelNearByMedia::getSelectedUrl() +{ + std::string url; + LLUUID selected_media_id = mMediaList->getValue().asUUID(); + if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID) + { + url = LLViewerMedia::getInstance()->getParcelAudioURL(); + } + else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) + { + url = LLViewerParcelMedia::getInstance()->getURL(); + } + else + { + LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(selected_media_id); + if (NULL != impl) + { + std::string name; + getNameAndUrlHelper(impl, name, url, mEmptyNameString); + } + } + return url; +} + -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llpanelnearbymedia.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llpanelnearbymedia.cpp') diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index aa60c5cf6c..2dd4866da3 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -1241,7 +1241,7 @@ void LLPanelNearByMedia::onMenuAction(const LLSD& userdata) if (!url.empty()) { - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, static_cast(url.size())); } } else if ("copy_data" == command_name) @@ -1254,12 +1254,12 @@ void LLPanelNearByMedia::onMenuAction(const LLSD& userdata) { pos += encoding_specifier.size(); std::string res = LLBase64::decodeAsString(url.substr(pos)); - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(res), 0, res.size()); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(res), 0, static_cast(res.size())); } else { url = LLURI::unescape(url); - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, url.size()); + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(url), 0, static_cast(url.size())); } } } -- cgit v1.2.3