From 4131069d0f517180a92e8ebda20b4760ecaeb855 Mon Sep 17 00:00:00 2001
From: thickbrick
Date: Fri, 1 Apr 2011 15:28:48 +0300
Subject: Fix 829: Several changes to media filter

- Adds a "less annoying" mode, which attempts to only filter scripted
  streaming events. On by default (should we change that?)
- Adds UI to enable and disable the media filter, both from the filter
  floater and from the preferences floater.
- Adds a button to launch the filter floater to prefences.
- Some UI tweaks to the filter floater.
---
 linden/indra/newview/app_settings/settings.xml     |  11 ++
 linden/indra/newview/llfloaterpreference.cpp       |   1 +
 linden/indra/newview/llpanelaudioprefs.cpp         |  19 ++-
 linden/indra/newview/llpanelaudioprefs.h           |   4 +
 linden/indra/newview/llviewerparcelmedia.cpp       | 158 +++++++++++++++++----
 linden/indra/newview/llviewerparcelmedia.h         |  40 +++++-
 .../default/xui/en-us/floater_media_filter.xml     |  26 +++-
 .../default/xui/en-us/panel_preferences_audio.xml  |  15 +-
 linden/indra/newview/slfloatermediafilter.cpp      | 116 ++++++++-------
 linden/indra/newview/slfloatermediafilter.h        |   7 +
 10 files changed, 308 insertions(+), 89 deletions(-)

(limited to 'linden/indra')

diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml
index 2a508ee..5bd8c7e 100644
--- a/linden/indra/newview/app_settings/settings.xml
+++ b/linden/indra/newview/app_settings/settings.xml
@@ -8017,6 +8017,17 @@
       <integer>100</integer>
     </array>
   </map>
+  <key>MediaFilterOnlyRemoteCommands</key>
+  <map>
+    <key>Comment</key>
+    <string>Whether Media Filter should only filter actions initiated remotely</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>1</integer>
+  </map>
   <key>MediaOnAPrimUI</key>
   <map>
     <key>Comment</key>
diff --git a/linden/indra/newview/llfloaterpreference.cpp b/linden/indra/newview/llfloaterpreference.cpp
index 0f81be6..02c2014 100644
--- a/linden/indra/newview/llfloaterpreference.cpp
+++ b/linden/indra/newview/llfloaterpreference.cpp
@@ -365,6 +365,7 @@ void LLPreferenceCore::setPersonalInfo(const std::string& visibility, bool im_vi
 void LLPreferenceCore::updateIsLoggedIn(bool enable)
 {
 	mPrefsIM->preparePerAccountPrefs(enable);
+	mAudioPanel->updateIsLoggedIn(enable);
 }
 
 void LLPreferenceCore::refreshEnabledGraphics()
diff --git a/linden/indra/newview/llpanelaudioprefs.cpp b/linden/indra/newview/llpanelaudioprefs.cpp
index 1acfcbb..fab2771 100644
--- a/linden/indra/newview/llpanelaudioprefs.cpp
+++ b/linden/indra/newview/llpanelaudioprefs.cpp
@@ -55,12 +55,14 @@
 #include "llslider.h"
 #include "llsliderctrl.h"
 #include "llspinctrl.h"
+#include "llstartup.h"
 #include "lltextbox.h"
 #include "llui.h"
 #include "llviewerparcelmgr.h"
 #include "lluictrlfactory.h"
 #include "llviewerwindow.h"
 #include "llviewercontrol.h"
+#include "slfloatermediafilter.h"
 
 #include "hippogridmanager.h"
 
@@ -92,6 +94,8 @@ BOOL LLPanelAudioPrefs::postBuild()
 	refreshValues(); // initialize member data from saved settings
 	childSetLabelArg("L$ Change Threshold", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol());
 	childSetValue("mute_wind_check", !gSavedSettings.getBOOL("MuteWind"));
+	childSetAction("show_media_filter", onShowMediaFilter, this);
+	updateIsLoggedIn(LLStartUp::isLoggedIn());
 
 	return TRUE;
 }
@@ -112,7 +116,7 @@ void LLPanelAudioPrefs::refreshValues()
 
 	mPreviousStreamingMusic = gSavedSettings.getBOOL("AudioStreamingMusic");
 	mPreviousStreamingVideo = gSavedSettings.getBOOL("AudioStreamingVideo");
-
+	mPreviousEnableMediaFilter = gSavedSettings.getBOOL("MediaEnableFilter");
 	mPreviousMuteAudio = gSavedSettings.getBOOL("MuteAudio");
 	mPreviousMuteWhenMinimized = gSavedSettings.getBOOL("MuteWhenMinimized");
 }
@@ -140,8 +144,19 @@ void LLPanelAudioPrefs::cancel()
 
 	gSavedSettings.setBOOL("AudioStreamingMusic", mPreviousStreamingMusic );
 	gSavedSettings.setBOOL("AudioStreamingVideo", mPreviousStreamingVideo );
+	gSavedSettings.setBOOL("MediaEnableFilter", mPreviousEnableMediaFilter );
 
-	
 	gSavedSettings.setBOOL("MuteAudio", mPreviousMuteAudio );
 	gSavedSettings.setBOOL("MuteWhenMinimized", mPreviousMuteWhenMinimized );
 }
+
+//static
+void LLPanelAudioPrefs::onShowMediaFilter(void* data)
+{
+	SLFloaterMediaFilter::toggleInstance();
+}
+
+void LLPanelAudioPrefs::updateIsLoggedIn(const bool enable)
+{
+	childSetEnabled("show_media_filter", enable);
+}
diff --git a/linden/indra/newview/llpanelaudioprefs.h b/linden/indra/newview/llpanelaudioprefs.h
index 21d2f59..a0733ba 100644
--- a/linden/indra/newview/llpanelaudioprefs.h
+++ b/linden/indra/newview/llpanelaudioprefs.h
@@ -54,6 +54,9 @@ public:
 	virtual BOOL postBuild();
 
 	static void* createVolumePanel(void* data);
+	static void onShowMediaFilter(void* data);
+
+	void updateIsLoggedIn(const bool);
 	
 private:
 	void refreshValues();
@@ -75,6 +78,7 @@ private:
 
 	BOOL			mPreviousStreamingMusic;
 	BOOL			mPreviousStreamingVideo;
+	BOOL			mPreviousEnableMediaFilter;
 	BOOL            mPreviousMuteAudio;
 	BOOL            mPreviousMuteWhenMinimized;
 };
diff --git a/linden/indra/newview/llviewerparcelmedia.cpp b/linden/indra/newview/llviewerparcelmedia.cpp
index 01e86e2..386a86e 100644
--- a/linden/indra/newview/llviewerparcelmedia.cpp
+++ b/linden/indra/newview/llviewerparcelmedia.cpp
@@ -49,6 +49,7 @@
 #include "llpluginclassmedia.h"
 #include "llnotify.h"
 #include "llsdserialize.h"
+#include "llmemory.h"
 
 #include "lloverlaybar.h"
 #include "slfloatermediafilter.h"
@@ -64,6 +65,7 @@ LLSD LLViewerParcelMedia::sMediaFilterList;
 std::set<std::string> LLViewerParcelMedia::sMediaQueries;
 std::set<std::string> LLViewerParcelMedia::sAllowedMedia;
 std::set<std::string> LLViewerParcelMedia::sDeniedMedia;
+LLPointer<LLViewerParcelMediaInfo> LLViewerParcelMedia::sSavedMediaInfo;
 
 // Local functions
 bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel);
@@ -186,7 +188,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
 }
 
 // static
-void LLViewerParcelMedia::play(LLParcel* parcel, bool filter)
+void LLViewerParcelMedia::play(LLParcel* parcel, bool filter, const ECommandOrigin origin)
 {
 	lldebugs << "LLViewerParcelMedia::play" << llendl;
 
@@ -198,12 +200,13 @@ void LLViewerParcelMedia::play(LLParcel* parcel, bool filter)
 	std::string media_url = parcel->getMediaURL();
 	LLStringUtil::trim(media_url);
 
-	if (!media_url.empty() && gSavedSettings.getBOOL("MediaEnableFilter") && (filter || !allowedMedia(media_url)))
+	if (!media_url.empty() && gSavedSettings.getBOOL("MediaEnableFilter") && filter
+		&& (!allowedMedia(media_url) || origin == COMMAND_ORIGIN_REMOTE))
 	{
 		// If filtering is needed or in case media_url just changed
 		// to something we did not yet approve.
 		LLViewerParcelMediaAutoPlay::playStarted();
-		filterMedia(parcel, 0);
+		filterMedia(parcel, 0, origin);
 		return;
 	}
 
@@ -384,7 +387,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
 			else
 			{
 				LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-				play(parcel);
+				play(parcel, true, COMMAND_ORIGIN_REMOTE);
 			}
 		}
 		else
@@ -400,7 +403,7 @@ void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg
 		if(sMediaImpl.isNull())
 		{
 			LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-			play(parcel);
+			play(parcel, true, COMMAND_ORIGIN_REMOTE);
 		}
 		seek(time);
 	}
@@ -437,33 +440,38 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
 	}
 
 	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	BOOL same = FALSE;
 	if (parcel)
 	{
-		same = ((parcel->getMediaURL() == media_url) &&
-				(parcel->getMediaType() == media_type) &&
-				(parcel->getMediaID() == media_id) &&
-				(parcel->getMediaWidth() == media_width) &&
-				(parcel->getMediaHeight() == media_height) &&
-				(parcel->getMediaAutoScale() == media_auto_scale) &&
-				(parcel->getMediaLoop() == media_loop));
-
-		if (!same)
+		LLViewerParcelMediaInfo* new_info = new LLViewerParcelMediaInfo(media_url, media_type, media_id, media_width, media_height, media_auto_scale, media_loop);
+		LLViewerParcelMediaInfo* current_info = new LLViewerParcelMediaInfo(parcel);
+		if (new_info != current_info)
 		{
+			if (!sSavedMediaInfo || (sSavedMediaInfo && !sSavedMediaInfo->sameParcel(parcel)))
+			{
+				// only save if no previously saved media info, because
+				// we want to remeber the original parcel media info.
+				sSavedMediaInfo = current_info;
+			}
 			// temporarily store these new values in the parcel
-			parcel->setMediaURL(media_url);
-			parcel->setMediaType(media_type);
-			parcel->setMediaID(media_id);
-			parcel->setMediaWidth(media_width);
-			parcel->setMediaHeight(media_height);
-			parcel->setMediaAutoScale(media_auto_scale);
-			parcel->setMediaLoop(media_loop);
-
-			play(parcel);
+			new_info->applyToParcel(parcel);
+
+			play(parcel, true, COMMAND_ORIGIN_REMOTE);
 		}
 
 	}
 }
+
+//static
+void LLViewerParcelMedia::undoParcelMediaUpdate()
+{
+	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	if (sSavedMediaInfo.notNull() && parcel)
+	{
+		sSavedMediaInfo->applyToParcel(parcel);
+	}
+	sSavedMediaInfo = NULL;
+}
+
 // Static
 /////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerParcelMedia::sendMediaNavigateMessage(const std::string& url)
@@ -619,7 +627,7 @@ void LLViewerParcelMedia::playStreamingMusic(LLParcel* parcel, bool filter)
 	{
 		// If filtering is needed or in case music_url just changed
 		// to something we did not yet approve.
-		filterMedia(parcel, 1);
+		filterMedia(parcel, 1, COMMAND_ORIGIN_LOCAL);
 	}
 	else if (gAudioStream)
 	{
@@ -675,13 +683,13 @@ bool LLViewerParcelMedia::allowedMedia(std::string media_url)
 	return false;
 }
 
-void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
+void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type, const ECommandOrigin origin)
 {
 	std::string media_action;
 	std::string media_url;
 	std::string domain;
 	std::string ip;
-
+	
 	if (parcel != LLViewerParcelMgr::getInstance()->getAgentParcel())
 	{
 		// The parcel just changed (may occur right out after a TP)
@@ -775,12 +783,33 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
 	}
 	if (media_action == "ignore")
 	{
-		if (type == 1)
+		if (type == 0)
+		{
+			undoParcelMediaUpdate();
+		}
+		else if (type == 1)
 		{
 			LLViewerParcelMedia::stopStreamingMusic();
 		}
 		return;
 	}
+	// skip local-originating play commands, unless the url is blacklisted.
+	if (gSavedSettings.getBOOL("MediaFilterOnlyRemoteCommands")
+		&& (origin != COMMAND_ORIGIN_REMOTE)
+		&& (media_action != "ignore"))
+	{
+		sAllowedMedia.insert(domain);
+		SLFloaterMediaFilter::setDirty();
+		if (type == 0)
+		{
+			play(parcel, false);
+		}
+		else
+		{
+			playStreamingMusic(parcel, false);
+		}
+		return;
+	}
 
 	LLSD args;
 	if (ip != domain && domain.find('/') == std::string::npos)
@@ -795,6 +824,10 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type)
 	if (media_action == "deny")
 	{
 		LLNotifications::instance().add("MediaBlocked", args);
+		if (type == 0)
+		{
+			undoParcelMediaUpdate();
+		}
 		if (type == 1)
 		{
 			LLViewerParcelMedia::stopStreamingMusic();
@@ -873,10 +906,15 @@ void callback_media_alert(const LLSD &notification, const LLSD &response, LLParc
 		{
 			LLViewerParcelMedia::sDeniedMedia.insert(ip);
 		}
-		if (type == 1)
+		if (type == 0)
+		{
+			LLViewerParcelMedia::undoParcelMediaUpdate();
+		}
+		else if (type == 1)
 		{
 			LLViewerParcelMedia::stopStreamingMusic();
 		}
+		
 		if (option == 1) // Deny
 		{
 			LLNotifications::instance().add("MediaBlocked", args);
@@ -1040,3 +1078,65 @@ std::string LLViewerParcelMedia::extractDomain(std::string url)
 	return url;
 }
 
+LLViewerParcelMediaInfo::LLViewerParcelMediaInfo(const std::string url,
+												 const std::string type,
+												 const LLUUID media_id,
+												 const S32 width,
+												 const S32 height,
+												 const U8 scale,
+												 const U8 loop)
+	:
+	mMediaURL(url),
+	mMediaType(type),
+	mMediaID(media_id),
+	mMediaWidth(width),
+	mMediaHeight(height),
+	mMediaAutoScale(scale),
+	mMediaLoop(loop)
+{
+	LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+	mParcelLocalID = parcel ? parcel->getLocalID() : 0;
+}
+
+LLViewerParcelMediaInfo::LLViewerParcelMediaInfo(const LLParcel* parcel)
+{
+	mMediaURL = parcel->getMediaURL();
+	mMediaType = parcel->getMediaType();
+	mMediaID = parcel->getMediaID();
+	mMediaWidth = parcel->getMediaWidth();
+	mMediaHeight = parcel->getMediaHeight();
+	mMediaAutoScale = parcel->getMediaAutoScale();
+	mMediaLoop = parcel->getMediaLoop();
+	mParcelLocalID = parcel->getLocalID();
+}
+
+void LLViewerParcelMediaInfo::applyToParcel(LLParcel* parcel)
+{
+	if (parcel && sameParcel(parcel))
+	{
+		parcel->setMediaURL(mMediaURL);
+		parcel->setMediaType(mMediaType);
+		parcel->setMediaID(mMediaID);
+		parcel->setMediaWidth(mMediaWidth);
+		parcel->setMediaHeight(mMediaHeight);
+		parcel->setMediaAutoScale(mMediaAutoScale);
+		parcel->setMediaLoop(mMediaLoop);
+	}
+}
+
+bool LLViewerParcelMediaInfo::sameParcel(const LLParcel* parcel) const
+{
+	return parcel && (parcel->getLocalID() == mParcelLocalID);
+}
+
+bool LLViewerParcelMediaInfo::operator==(const LLViewerParcelMediaInfo &rhs) const
+{
+	return 	(mMediaURL == rhs.mMediaURL) &&
+			(mMediaType == rhs.mMediaType) &&
+			(mMediaID == rhs.mMediaID) &&
+			(mMediaWidth == rhs.mMediaWidth) &&
+			(mMediaHeight == rhs.mMediaHeight) &&
+			(mMediaAutoScale == rhs.mMediaAutoScale) &&
+			(mMediaLoop == rhs.mMediaLoop) &&
+			(mParcelLocalID == rhs.mParcelLocalID);
+}
\ No newline at end of file
diff --git a/linden/indra/newview/llviewerparcelmedia.h b/linden/indra/newview/llviewerparcelmedia.h
index 7531a0f..f4c4312 100644
--- a/linden/indra/newview/llviewerparcelmedia.h
+++ b/linden/indra/newview/llviewerparcelmedia.h
@@ -34,6 +34,7 @@
 #define LLVIEWERPARCELMEDIA_H
 
 #include "llviewermedia.h"
+#include "llmemory.h"
 
 // For use by other patches so they know that media filtering is implemented.
 #define MEDIA_FILTERING 1
@@ -41,6 +42,7 @@
 class LLMessageSystem;
 class LLParcel;
 class LLViewerParcelMediaNavigationObserver;
+class LLViewerParcelMediaInfo;
 
 
 // This class understands land parcels, network traffic, LSL media
@@ -49,6 +51,13 @@ class LLViewerParcelMediaNavigationObserver;
 class LLViewerParcelMedia : public LLViewerMediaObserver
 {
 	LOG_CLASS(LLViewerParcelMedia);
+	private:
+		typedef enum e_command_origin
+		{
+			COMMAND_ORIGIN_LOCAL,
+			COMMAND_ORIGIN_REMOTE
+		} ECommandOrigin;
+
 	public:
 		static void initClass();
 		static void cleanupClass();
@@ -57,14 +66,14 @@ class LLViewerParcelMedia : public LLViewerMediaObserver
 			// called when the agent's parcel has a new URL, or the agent has
 			// walked on to a new parcel with media
 
-		static void play(LLParcel* parcel, bool filter = true);
+		static void play(LLParcel* parcel, bool filter = true, const ECommandOrigin origin = COMMAND_ORIGIN_LOCAL);
 			// user clicked play button in media transport controls
 		static void playStreamingMusic(LLParcel* parcel, bool filter = true);
 			// play the parcel music stream
 		static void stopStreamingMusic();
 			// stop the parcel music stream
 
-		static void filterMedia(LLParcel* parcel, U32 type); // type: 0 = media, 1 = streaming music
+		static void filterMedia(LLParcel* parcel, U32 type, const ECommandOrigin origin); // type: 0 = media, 1 = streaming music
 		static bool allowedMedia(std::string media_url);
 
 		static bool loadDomainFilterList();
@@ -90,6 +99,7 @@ class LLViewerParcelMedia : public LLViewerMediaObserver
 
 		static void processParcelMediaCommandMessage( LLMessageSystem *msg, void ** );
 		static void processParcelMediaUpdate( LLMessageSystem *msg, void ** );
+		static void undoParcelMediaUpdate(); // reset the parcel's media to what it was before ParcelMediaUpdate
 		static void sendMediaNavigateMessage(const std::string& url);
 		
 		// inherited from LLViewerMediaObserver
@@ -107,6 +117,7 @@ class LLViewerParcelMedia : public LLViewerMediaObserver
 		static std::set<std::string> sMediaQueries;
 		static std::set<std::string> sAllowedMedia;
 		static std::set<std::string> sDeniedMedia;
+		static LLPointer<LLViewerParcelMediaInfo> sSavedMediaInfo; // The parcel original media (before a remote command is applied)
 };
 
 
@@ -120,4 +131,29 @@ public:
 
 };
 
+class LLViewerParcelMediaInfo : public LLRefCount
+{
+public:
+	LLViewerParcelMediaInfo(const std::string url, 
+							const std::string type,
+							const LLUUID media_id,
+							const S32 width,
+							const S32 height,
+							const U8 scale,
+							const U8 loop);
+	LLViewerParcelMediaInfo(const LLParcel* parcel);
+	~LLViewerParcelMediaInfo() {}
+	void applyToParcel(LLParcel* parcel);
+	bool sameParcel(const LLParcel* parcel) const;
+	bool operator==(const LLViewerParcelMediaInfo &rhs) const;
+private:
+	std::string			mMediaURL;
+	std::string 		mMediaType;
+	LLUUID				mMediaID;
+	S32					mMediaWidth;
+	S32					mMediaHeight;
+	U8					mMediaAutoScale;
+	U8                  mMediaLoop;
+	S32					mParcelLocalID;
+};
 #endif
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml b/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml
index 5faaf1a..f0fb3a3 100644
--- a/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_media_filter.xml
@@ -1,9 +1,22 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater name="floatermediafilter" title="Media Filter" rect_control="MediaFilterRect"
  can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="true"
- height="350" width="600" min_height="350" min_width="600">
+ height="410" width="600" min_height="350" min_width="600">
+
+	<check_box control_name="MediaEnableFilter" name="enable_mediafilter" label="Enable Media Filter"
+	 initial_value="true" tool_tip="Enables filtering media URLs by domain names."
+	 font="SansSerifSmall" mouse_opaque="true"
+	 left="14" height="16" bottom_delta="-45" width="4500" follows="left|top" />
+
+	<check_box control_name="MediaFilterOnlyRemoteCommands" name="filter_only_remote"
+	 label="Filter only when a script initiates the stream (less secure)" initial_value="false" 
+	 tool_tip="This will prevent popups asking about URLs that are permanently set on a parcel. 
+Only scripted changes to the media URL and scripted requests to start playing a stream will be filtered."
+	 font="SansSerifSmall" mouse_opaque="true"
+	 left_delta="14" height="16" width="450" follows="left|top" />
+
 	<text name="info1" font="SansSerif" mouse_opaque="true" halign="center"
-	 bottom_delta="-45" left="20" height="20" width="560" follows="left|right|top">
+	 bottom_delta="-40" left="20" height="20" width="560" follows="left|right|top">
 		Domains in bold are in the persistent list (i.e. they are whitelisted or blacklisted).
 	</text>
 	<text name="info2" font="SansSerif" mouse_opaque="true" halign="center"
@@ -14,7 +27,7 @@
 	<scroll_list name="whitelist_list" follows="top|bottom|left"
 	 background_visible="true" mouse_opaque="true"
 	 multi_select="false" column_padding="5" draw_border="true" draw_heading="true"
-	 bottom_delta="-205" left="15" height="200" width="280">
+	 bottom_delta="-200" left="15" height="200" width="280">
 		<column name="whitelist_col" label="Allowed domains or server objects" dynamicwidth="true" />
 	</scroll_list>
 
@@ -69,10 +82,13 @@
 	 tool_tip="Enter the new URL, domain name, IP or scripted object HTTP server path here"
 	 select_all_on_focus_received="true" select_on_focus="true"
 	 bevel_style="in" border_style="line" border_thickness="1"
-	 bottom_delta="-22"	right="-100" height="20" left="15" follows="left|bottom|right"/>
+	 bottom_delta="-22"	right="-180" height="20" left="15" follows="left|bottom|right"/>
 
+	<button name="cancel_domain" font="SansSerif" label="Cancel" halign="center" enabled="false"
+	 mouse_opaque="true" follows="bottom|right"
+	 bottom_delta="0" right="-15" height="20" width="80"/>
 	<button name="commit_domain" font="SansSerif" label="Add" halign="center" enabled="false"
 	 tool_tip="Add to the list"
 	 mouse_opaque="true" follows="bottom|right"
-	 bottom_delta="0" right="-15" height="20" width="80"/>
+	 bottom_delta="0" right="-95" height="20" width="80"/>
 </floater>
diff --git a/linden/indra/newview/skins/default/xui/en-us/panel_preferences_audio.xml b/linden/indra/newview/skins/default/xui/en-us/panel_preferences_audio.xml
index c6bb938..3415b1b 100644
--- a/linden/indra/newview/skins/default/xui/en-us/panel_preferences_audio.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/panel_preferences_audio.xml
@@ -9,13 +9,13 @@
 		Volume:
 	</text>
 	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
-	     bottom="-190" drop_shadow_visible="true" enabled="true" follows="left|top"
+	     bottom="-202" drop_shadow_visible="true" enabled="true" follows="left|top"
 	     font="SansSerifSmall" h_pad="0" halign="left" height="12" left="10"
 	     mouse_opaque="true" name="streaming_prefs_text" v_pad="0" width="128">
 		Streaming:
 	</text>
 	<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
-	     bottom="-285" drop_shadow_visible="true" enabled="true" follows="left|top"
+	     bottom="-315" drop_shadow_visible="true" enabled="true" follows="left|top"
 	     font="SansSerifSmall" h_pad="0" halign="left" height="12" left="10"
 	     mouse_opaque="true" name="audio_prefs_text" v_pad="0" width="128">
 		Audio:
@@ -42,7 +42,16 @@
 	     initial_value="true" label="Automatically play media" left="162"
 	     mouse_opaque="true" name="auto_streaming_video" radio_style="false"
 	     width="338" />
-	<check_box bottom_delta="-27" control_name="MuteWhenMinimized" enabled="true"
+	<check_box bottom_delta="-20" control_name="MediaEnableFilter" enabled="true"
+	     follows="left|top" font="SansSerifSmall" height="16"
+	     initial_value="true" label="Filter media URLs" left="142"
+	     mouse_opaque="true" name="enable_media_filter" radio_style="false"
+	     width="200" />
+	<button name="show_media_filter" font="SansSerif" label="Media Filter Settings" halign="center"
+	     tool_tip="Edit settings and the blocked and allowed lists for the Media Filter."
+	     enabled="false" mouse_opaque="true" follows="top|right"
+	     bottom_delta="-2" right="-15" height="20" width="180" />
+	<check_box bottom_delta="-33" control_name="MuteWhenMinimized" enabled="true"
 	     follows="left|top" font="SansSerifSmall" height="16" initial_value="true"
 	     label="Mute audio when window minimized" left="142" mouse_opaque="true"
 	     name="mute_when_minimized" radio_style="false" width="215" />
diff --git a/linden/indra/newview/slfloatermediafilter.cpp b/linden/indra/newview/slfloatermediafilter.cpp
index 7b287e0..b0d9c26 100644
--- a/linden/indra/newview/slfloatermediafilter.cpp
+++ b/linden/indra/newview/slfloatermediafilter.cpp
@@ -43,6 +43,7 @@
 
 SLFloaterMediaFilter* SLFloaterMediaFilter::sInstance = NULL;
 bool SLFloaterMediaFilter::sIsWhitelist = false;
+bool SLFloaterMediaFilter::sIsAdding = false;
 bool SLFloaterMediaFilter::sShowIPs = false;
 
 SLFloaterMediaFilter::SLFloaterMediaFilter() : LLFloater(std::string("media filter")), mIsDirty(false)
@@ -69,10 +70,12 @@ BOOL SLFloaterMediaFilter::postBuild()
 		childSetAction("add_blacklist", onBlacklistAdd, this);
 		childSetAction("remove_blacklist", onBlacklistRemove, this);
 		childSetAction("commit_domain", onCommitDomain, this);
+		childSetAction("cancel_domain", onCancelDomain, this);
 		childSetUserData("whitelist_list", this);
 		childSetUserData("blacklist_list", this);
 		mIsDirty = true;
 	}
+	gSavedSettings.getControl("MediaEnableFilter")->getSignal()->connect(boost::bind(&onMediaEnableFilterChanged, _1));
 
 	return TRUE;
 }
@@ -174,21 +177,7 @@ void SLFloaterMediaFilter::draw()
 		mWhitelistSLC->setScrollPos(whitescrollpos);
 		mBlacklistSLC->setScrollPos(blackscrollpos);
 
-		if (!gSavedSettings.getBOOL("MediaEnableFilter"))
-		{
-			childDisable("clear_lists");
-			childDisable("show_ips");
-			childDisable("blacklist_list");
-			childDisable("whitelist_list");
-			childDisable("remove_whitelist");
-			childDisable("add_whitelist");
-			childDisable("remove_blacklist");
-			childDisable("add_blacklist");
-			childDisable("match_ip");
-			childDisable("input_domain");
-			childDisable("commit_domain");
-			childSetText("add_text", std::string("****** WARNING: media filtering is currently DISABLED ******"));
-		}
+		updateWidgets();
 
 		mIsDirty = false;
 		sShowIPs = false;
@@ -197,6 +186,47 @@ void SLFloaterMediaFilter::draw()
 	LLFloater::draw();
 }
 
+void SLFloaterMediaFilter::updateWidgets()
+{
+	bool enabled = gSavedSettings.getBOOL("MediaEnableFilter");
+	childSetEnabled("clear_lists", enabled && !sIsAdding);
+	childSetEnabled("show_ips", enabled && !sIsAdding);
+	childSetEnabled("blacklist_list", enabled && !sIsAdding);
+	childSetEnabled("whitelist_list", enabled && !sIsAdding);
+	childSetEnabled("remove_whitelist", enabled && !sIsAdding);
+	childSetEnabled("add_whitelist", enabled && !sIsAdding);
+	childSetEnabled("remove_blacklist", enabled && !sIsAdding);
+	childSetEnabled("add_blacklist", enabled && !sIsAdding);
+	childSetEnabled("match_ip", enabled);
+	childSetEnabled("input_domain", enabled && sIsAdding);
+	childSetEnabled("commit_domain", enabled && sIsAdding);
+	childSetEnabled("cancel_domain", enabled && sIsAdding);
+	childSetEnabled("filter_only_remote", enabled);
+	childSetEnabled("info1", enabled);
+	childSetEnabled("info2", enabled);
+
+	std::string add_text("****** Media filtering is currently DISABLED ******");
+	if (enabled)
+	{
+		if (sIsAdding)
+		{
+			if (sIsWhitelist)
+			{
+				add_text = "Enter the domain/url to add to the white list:";
+			}
+			else
+			{
+				add_text = "Enter the domain/url to add to the black list:";
+			}
+		}
+		else
+		{
+			add_text = "New Domain:";
+		}
+	}
+	childSetText("add_text", add_text);
+}
+
 void SLFloaterMediaFilter::setDirty()
 {
     if (sInstance)
@@ -255,18 +285,9 @@ void SLFloaterMediaFilter::onWhitelistAdd(void* data)
 	{
 		return;
 	}
-	sInstance->childDisable("clear_lists");
-	sInstance->childDisable("show_ips");
-	sInstance->childDisable("blacklist_list");
-	sInstance->childDisable("whitelist_list");
-	sInstance->childDisable("remove_whitelist");
-	sInstance->childDisable("add_whitelist");
-	sInstance->childDisable("remove_blacklist");
-	sInstance->childDisable("add_blacklist");
-	sInstance->childEnable("input_domain");
-	sInstance->childEnable("commit_domain");
-	sInstance->childSetText("add_text", std::string("Enter the domain/url to add to the white list:"));
 	sIsWhitelist = true;
+	sIsAdding = true;
+	sInstance->updateWidgets();
 }
 
 void SLFloaterMediaFilter::onWhitelistRemove(void* data)
@@ -329,18 +350,9 @@ void SLFloaterMediaFilter::onBlacklistAdd(void* data)
 	{
 		return;
 	}
-	sInstance->childDisable("clear_lists");
-	sInstance->childDisable("show_ips");
-	sInstance->childDisable("blacklist_list");
-	sInstance->childDisable("whitelist_list");
-	sInstance->childDisable("remove_whitelist");
-	sInstance->childDisable("add_whitelist");
-	sInstance->childDisable("remove_blacklist");
-	sInstance->childDisable("add_blacklist");
-	sInstance->childEnable("input_domain");
-	sInstance->childEnable("commit_domain");
-	sInstance->childSetText("add_text", std::string("Enter the domain/url to add to the black list:"));
 	sIsWhitelist = false;
+	sIsAdding = true;
+	sInstance->updateWidgets();
 }
 
 void SLFloaterMediaFilter::onBlacklistRemove(void* data)
@@ -452,17 +464,25 @@ void SLFloaterMediaFilter::onCommitDomain(void* data)
 		LLViewerParcelMedia::saveDomainFilterList();
 	}
 
-	sInstance->childEnable("clear_lists");
-	sInstance->childEnable("show_ips");
-	sInstance->childEnable("blacklist_list");
-	sInstance->childEnable("whitelist_list");
-	sInstance->childEnable("remove_whitelist");
-	sInstance->childEnable("add_whitelist");
-	sInstance->childEnable("remove_blacklist");
-	sInstance->childEnable("add_blacklist");
-	sInstance->childDisable("input_domain");
-	sInstance->childDisable("commit_domain");
-	sInstance->childSetText("add_text", std::string("New domain:"));
 	sInstance->childSetText("input_domain", std::string(""));
+	sIsAdding = false;
+	setDirty();
+}
+
+//static
+void SLFloaterMediaFilter::onCancelDomain(void* data)
+{
+	if (!sInstance)
+	{
+		return;
+	}
+	sInstance->childSetText("input_domain", std::string(""));
+	sIsAdding = false;
+	setDirty();
+}
+
+//static
+void SLFloaterMediaFilter::onMediaEnableFilterChanged(const LLSD& newvalue)
+{
 	setDirty();
 }
diff --git a/linden/indra/newview/slfloatermediafilter.h b/linden/indra/newview/slfloatermediafilter.h
index aafa5a2..9067c74 100644
--- a/linden/indra/newview/slfloatermediafilter.h
+++ b/linden/indra/newview/slfloatermediafilter.h
@@ -38,6 +38,7 @@
 
 class LLScrollListCtrl;
 class LLButton;
+class LLSD;
 
 class SLFloaterMediaFilter : public LLFloater
 {
@@ -58,10 +59,16 @@ public:
 	static void onBlacklistAdd(void*);
 	static void onBlacklistRemove(void*);
 	static void onCommitDomain(void*);
+	static void onCancelDomain(void*);
+	static void onMediaEnableFilterChanged(const LLSD& newvalue);
+
+private:
+	void updateWidgets();
 
 private:
 	static bool sIsWhitelist;
 	static bool sShowIPs;
+	static bool sIsAdding;
 	LLScrollListCtrl* mWhitelistSLC;
 	LLScrollListCtrl* mBlacklistSLC;
 	bool mIsDirty;
-- 
cgit v1.1