diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index 232478577c79e2d24a21152dfd7357fe87b0f27b..40e4a4268d1207a11be0d1eaffc0524baf50dd96 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -92,7 +92,7 @@ const U32 REGION_FLAGS_DENY_ANONYMOUS			= (1 << 23);
 
 const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES		= (1 << 26);
 
-const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27);
+// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR
 
 const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
 
diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp
index 3c69a69d28a8e480fe5fa08675819af6da363b43..9c18b410c75b6cf0b4bc16160db55f03de48bb6e 100644
--- a/indra/llplugin/llpluginsharedmemory.cpp
+++ b/indra/llplugin/llpluginsharedmemory.cpp
@@ -1,6 +1,6 @@
 /** 
  * @file llpluginsharedmemory.cpp
- * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
+ * LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
  *
  * @cond
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -96,6 +96,10 @@ std::string LLPluginSharedMemory::createName(void)
 	return newname.str();
 }
 
+/**
+ * @brief LLPluginSharedMemoryImpl is the platform-dependent implementation of LLPluginSharedMemory. TODO:DOC is this necessary/sufficient? kinda obvious.
+ *
+ */
 class LLPluginSharedMemoryPlatformImpl
 {
 public:
@@ -112,6 +116,9 @@ class LLPluginSharedMemoryPlatformImpl
 
 };
 
+/**
+ * Constructor. Creates a shared memory segment.
+ */
 LLPluginSharedMemory::LLPluginSharedMemory()
 {
 	mSize = 0;
@@ -121,6 +128,9 @@ LLPluginSharedMemory::LLPluginSharedMemory()
 	mImpl = new LLPluginSharedMemoryPlatformImpl;
 }
 
+/**
+ * Destructor. Uses destroy() and detach() to ensure shared memory segment is cleaned up.
+ */
 LLPluginSharedMemory::~LLPluginSharedMemory()
 {
 	if(mNeedsDestroy)
diff --git a/indra/llplugin/llpluginsharedmemory.h b/indra/llplugin/llpluginsharedmemory.h
index 4014620c520edc7ef0b35b6c7fda902567b14b6f..00c54ef08caf917403b224f881a2011a691a8d1f 100644
--- a/indra/llplugin/llpluginsharedmemory.h
+++ b/indra/llplugin/llpluginsharedmemory.h
@@ -1,6 +1,5 @@
 /** 
  * @file llpluginsharedmemory.h
- * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
  *
  * @cond
  * $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -36,6 +35,10 @@
 
 class LLPluginSharedMemoryPlatformImpl;
 
+/**
+ * @brief LLPluginSharedMemory manages a shared memory segment for use by the LLPlugin API.
+ *
+ */
 class LLPluginSharedMemory
 {
 	LOG_CLASS(LLPluginSharedMemory);
@@ -46,16 +49,62 @@ class LLPluginSharedMemory
 	// Parent will use create/destroy, child will use attach/detach.
 	// Message transactions will ensure child attaches after parent creates and detaches before parent destroys.
 	
-	// create() implicitly creates a name for the segment which is guaranteed to be unique on the host at the current time.
+   /** 
+    * Creates a shared memory segment, with a name which is guaranteed to be unique on the host at the current time. Used by parent.
+    * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys.
+    *
+    * @param[in] size Shared memory size in TODO:DOC units = bytes?.
+    *
+    * @return False for failure, true for success.
+    */
 	bool create(size_t size);
+   /** 
+    * Destroys a shared memory segment. Used by parent.
+    * Message transactions will (? TODO:DOC - should? must?) ensure child attaches after parent creates and detaches before parent destroys.
+    *
+    * @return True. TODO:DOC - always returns true. Is this the intended behavior?
+    */
 	bool destroy(void);
 	
+   /** 
+    * Creates and attaches a name to a shared memory segment. TODO:DOC what's the difference between attach() and create()?
+    *
+    * @param[in] name Name to attach to memory segment
+    * @param[in] size Size of memory segment TODO:DOC in bytes?
+    *
+    * @return False on failure, true otherwise.
+    */
 	bool attach(const std::string &name, size_t size);
+   /** 
+    * Detaches shared memory segment.
+    *
+    * @return False on failure, true otherwise.
+    */
 	bool detach(void);
 
+   /** 
+    * Checks if shared memory is mapped to a non-null address.
+    *
+    * @return True if memory address is non-null, false otherwise.
+    */
 	bool isMapped(void) const { return (mMappedAddress != NULL); };
+   /** 
+    * Get pointer to shared memory.
+    *
+    * @return Pointer to shared memory.
+    */
 	void *getMappedAddress(void) const { return mMappedAddress; };
+   /** 
+    * Get size of shared memory.
+    *
+    * @return Size of shared memory in bytes. TODO:DOC are bytes the correct unit?
+    */
 	size_t getSize(void) const { return mSize; };
+   /** 
+    * Get name of shared memory.
+    *
+    * @return Name of shared memory.
+    */
 	std::string getName() const { return mName; };
 	
 private:
diff --git a/indra/llui/llhelp.h b/indra/llui/llhelp.h
index 82c3bc385f322434a033b356f1ea94fd8a0214cf..938419d374d6b6e0e802d4a0aeaa0244b19cf713 100644
--- a/indra/llui/llhelp.h
+++ b/indra/llui/llhelp.h
@@ -42,6 +42,8 @@ class LLHelp
 	virtual std::string defaultTopic() = 0;
 	// return topic to use before the user logs in
 	virtual std::string preLoginTopic() = 0;
+	// return topic to use for the top-level help, invoked by F1
+	virtual std::string f1HelpTopic() = 0;
 };
 
 #endif // headerguard
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index be6bce8054f6c658f563bd205db6e33bdf799f12..72630cc413fbdf8b9bc3c661ccdd71fdcaf646e9 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -104,6 +104,7 @@ set(viewer_SOURCE_FILES
     llclassifiedstatsresponder.cpp
     llcloud.cpp
     llcolorswatch.cpp
+    llcommanddispatcherlistener.cpp
     llcommandhandler.cpp
     llcommandlineparser.cpp
     llcompilequeue.cpp
@@ -324,6 +325,7 @@ set(viewer_SOURCE_FILES
     llpanellandmarks.cpp
     llpanellandmedia.cpp
     llpanellogin.cpp
+    llpanelloginlistener.cpp
     llpanellookinfo.cpp
     llpanelmaininventory.cpp
     llpanelmediasettingsgeneral.cpp
@@ -444,6 +446,7 @@ set(viewer_SOURCE_FILES
     lluploaddialog.cpp
     llurl.cpp
     llurldispatcher.cpp
+    llurldispatcherlistener.cpp
     llurlhistory.cpp
     llurllineeditorctrl.cpp
     llurlsimstring.cpp
@@ -611,6 +614,7 @@ set(viewer_HEADER_FILES
     llclassifiedstatsresponder.h
     llcloud.h
     llcolorswatch.h
+    llcommanddispatcherlistener.h
     llcommandhandler.h
     llcommandlineparser.h
     llcompilequeue.h
@@ -826,6 +830,7 @@ set(viewer_HEADER_FILES
     llpanellandmarks.h
     llpanellandmedia.h
     llpanellogin.h
+    llpanelloginlistener.h
     llpanellookinfo.h
     llpanelmaininventory.h
     llpanelmediasettingsgeneral.h
@@ -950,6 +955,7 @@ set(viewer_HEADER_FILES
     lluploaddialog.h
     llurl.h
     llurldispatcher.h
+    llurldispatcherlistener.h
     llurlhistory.h
     llurllineeditorctrl.h
     llurlsimstring.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 289e900eaff12dfcd59ba76ac89c2f1e8038f7db..eed84671c1ec3bb60ac6ac25039fe390b5180d77 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5514,6 +5514,28 @@
       <string>F32</string>
       <key>Value</key>
       <real>5.0</real>
+    </map>
+	<key>PrimMediaMaxSortedQueueSize</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of objects the viewer will load media for initially</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>100000</integer>
+    </map>
+	<key>PrimMediaMaxRoundRobinQueueSize</key>
+    <map>
+      <key>Comment</key>
+      <string>Maximum number of objects the viewer will continuously update media for</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>100000</integer>
     </map>
     <key>ProbeHardwareOnStartup</key>
     <map>
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index d7182dfaab2fd036bf59392490f8f5087f4a26ce..ae89eb4413579f36aa16560388f35653d7224a7d 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -9283,7 +9283,7 @@ render_pass="bump">
      wearable="skin"
      edit_group="skin_facedetail"
      edit_group_order="3"
-     name="wrinkles"
+     name="Wrinkles"
      label_min="Less"
      label_max="More"
      value_min="0"
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9a1b749ba7f1d2084bc0d267d13858d13d811746..3250343b253abbee297ed097d83744e58e491bcf 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -746,7 +746,15 @@ bool LLAppViewer::init()
 	LLViewerJointMesh::updateVectorize();
 
 	// load MIME type -> media impl mappings
-	LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") ); 
+	std::string mime_types_name;
+#if LL_DARWIN
+	mime_types_name = "mime_types_mac.xml";
+#elif LL_LINUX
+	mime_types_name = "mime_types_linux.xml";
+#else
+	mime_types_name = "mime_types.xml";
+#endif
+	LLMIMETypes::parseMIMETypes( mime_types_name ); 
 
 	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers
 	settings_to_globals();
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index 7cda2d31e66ec154a91874b993a04e6913b0acaa..33e5046f5062b5fa90a99dc510a9ae2f226d9a96 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -440,11 +440,17 @@ void LLAvatarPropertiesProcessor::notifyObservers(const LLUUID& id,void* data, E
 	// Copy the map (because observers may delete themselves when updated?)
 	LLAvatarPropertiesProcessor::observer_multimap_t observers = mObservers;
 
-	observer_multimap_t::iterator oi = observers.lower_bound(id);
-	observer_multimap_t::iterator end = observers.upper_bound(id);
+	observer_multimap_t::iterator oi = observers.begin();
+	observer_multimap_t::iterator end = observers.end();
 	for (; oi != end; ++oi)
 	{
-		oi->second->processProperties(data,type);
+		// only notify observers for the same agent, or if the observer
+		// didn't know the agent ID and passed a NULL id.
+		const LLUUID &agent_id = oi->first;
+		if (agent_id == id || agent_id.isNull())
+		{
+			oi->second->processProperties(data,type);
+		}
 	}
 }
 
diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..00a20de30edc4639671fd432adfb938282c39275
--- /dev/null
+++ b/indra/newview/llcommanddispatcherlistener.cpp
@@ -0,0 +1,47 @@
+/**
+ * @file   llcommanddispatcherlistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-12-10
+ * @brief  Implementation for llcommanddispatcherlistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llcommanddispatcherlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llcommandhandler.h"
+
+LLCommandDispatcherListener::LLCommandDispatcherListener(/* LLCommandDispatcher* instance */):
+    LLEventAPI("LLCommandDispatcher", "Access to LLCommandHandler commands") /* ,
+    mDispatcher(instance) */
+{
+    add("dispatch",
+        "Execute a command registered as an LLCommandHandler,\n"
+        "passing any required parameters:\n"
+        "[\"cmd\"] string command name\n"
+        "[\"params\"] array of parameters, as if from components of URL path\n"
+        "[\"query\"] map of parameters, as if from ?key1=val&key2=val\n"
+        "[\"trusted\"] boolean indicating trusted browser [default true]",
+        &LLCommandDispatcherListener::dispatch);
+}
+
+void LLCommandDispatcherListener::dispatch(const LLSD& params) const
+{
+    // For most purposes, we expect callers to want to be trusted.
+    bool trusted_browser = true;
+    if (params.has("trusted"))
+    {
+        // But for testing, allow a caller to specify untrusted.
+        trusted_browser = params["trusted"].asBoolean();
+    }
+    LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL,
+                                  trusted_browser);
+}
diff --git a/indra/newview/llcommanddispatcherlistener.h b/indra/newview/llcommanddispatcherlistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0070ddd711caf8d13fe3866e70b5cf7f0b2425d
--- /dev/null
+++ b/indra/newview/llcommanddispatcherlistener.h
@@ -0,0 +1,30 @@
+/**
+ * @file   llcommanddispatcherlistener.h
+ * @author Nat Goodspeed
+ * @date   2009-12-10
+ * @brief  LLEventAPI for LLCommandDispatcher
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCOMMANDDISPATCHERLISTENER_H)
+#define LL_LLCOMMANDDISPATCHERLISTENER_H
+
+#include "lleventapi.h"
+class LLCommandDispatcher;
+class LLSD;
+
+class LLCommandDispatcherListener: public LLEventAPI
+{
+public:
+    LLCommandDispatcherListener(/* LLCommandDispatcher* instance */); // all static members
+
+private:
+    void dispatch(const LLSD& params) const;
+
+    //LLCommandDispatcher* mDispatcher;
+};
+
+#endif /* ! defined(LL_LLCOMMANDDISPATCHERLISTENER_H) */
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 1d92661ea2af208e0bcf00dce1de0ce92f752a0c..8c7e7bea83b91be92abf6a0680ddca920c787726 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -35,12 +35,15 @@
 
 #include "llcommandhandler.h"
 #include "llnotificationsutil.h"
+#include "llcommanddispatcherlistener.h"
 
 // system includes
 #include <boost/tokenizer.hpp>
 
 #define THROTTLE_PERIOD    15    // required secs between throttled commands
 
+static LLCommandDispatcherListener sCommandDispatcherListener;
+
 //---------------------------------------------------------------------------
 // Underlying registry for command handlers, not directly accessible.
 //---------------------------------------------------------------------------
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index ed0f24d16052fce9f35a04ad0e0bb75b1072a4ab..5b03292b22b4d95e0def974c3528e4bbdf928f7e 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -2300,7 +2300,7 @@ void LLPanelLandAccess::refresh()
 		mListBanned->deleteAllItems();
 	
 	LLParcel *parcel = mParcel->getParcel();
-	
+		
 	// Display options
 	if (parcel)
 	{
@@ -2396,22 +2396,40 @@ void LLPanelLandAccess::refresh()
 				mListBanned->addNameItem(entry.mID, ADD_SORTED, TRUE, suffix);
 			}
 		}
+		
+		LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+		if(region)
+		{
+			std::string region_access = "(";
+			region_access += region->getSimAccessString();
+			region_access += ")";
+			childSetLabelArg( "public_access", "[MATURITY]", region_access );
+		}
+		else
+		{
+			childSetLabelArg( "public_access", "[MATURITY]", std::string() );
+		}
+
 
 		if(parcel->getRegionDenyAnonymousOverride())
 		{
 			childSetValue("limit_payment", TRUE);
+			childSetLabelArg( "limit_payment", "[ESTATE_PAYMENT_LIMIT]", getString("access_estate_defined") );
 		}
 		else
 		{
 			childSetValue("limit_payment", (parcel->getParcelFlag(PF_DENY_ANONYMOUS)));
+			childSetLabelArg( "limit_payment", "[ESTATE_PAYMENT_LIMIT]", std::string() );
 		}
 		if(parcel->getRegionDenyAgeUnverifiedOverride())
 		{
 			childSetValue("limit_age_verified", TRUE);
+			childSetLabelArg( "limit_age_verified", "[ESTATE_AGE_LIMIT]", getString("access_estate_defined") );
 		}
 		else
 		{
 			childSetValue("limit_age_verified", (parcel->getParcelFlag(PF_DENY_AGEUNVERIFIED)));
+			childSetLabelArg( "limit_age_verified", "[ESTATE_AGE_LIMIT]", std::string() );
 		}
 		
 		BOOL use_pass = parcel->getParcelFlag(PF_USE_PASS_LIST);
diff --git a/indra/newview/llfloaterparcel.cpp b/indra/newview/llfloaterparcel.cpp
index 88a39a495fd6702cbd733c665af033ac8ccfc637..e2be78411634090a054c32db79dee80f7535d1da 100644
--- a/indra/newview/llfloaterparcel.cpp
+++ b/indra/newview/llfloaterparcel.cpp
@@ -40,6 +40,7 @@
 // viewer project includes
 #include "llcommandhandler.h"
 #include "llpanelplace.h"
+#include "llsidetray.h"
 
 // linden library includes
 #include "lluuid.h"
@@ -70,7 +71,10 @@ class LLParcelHandler : public LLCommandHandler
 		{
 			if (parcel_id.notNull())
 			{
-				LLFloaterReg::showInstance("parcel_info", LLSD(parcel_id));
+				LLSD key;
+				key["type"] = "remote_place";
+				key["id"] = parcel_id;
+				LLSideTray::getInstance()->showPanel("panel_places", key);
 				return true;
 			}
 		}
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 05a46ad89451e4b40a34d1acffe2f0bbeb048fe5..8a26078f3d3fe4643664a169ebd0fa525e8104af 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -88,8 +88,6 @@
 #include "lltrans.h"
 #include "llagentui.h"
 
-#define ELAR_ENABLED 0 // Enable when server support is implemented
-
 const S32 TERRAIN_TEXTURE_COUNT = 4;
 const S32 CORNER_COUNT = 4;
 
@@ -1995,11 +1993,6 @@ void LLPanelEstateInfo::updateControls(LLViewerRegion* region)
 	childSetEnabled("remove_banned_avatar_btn",		god || owner || manager);
 	childSetEnabled("message_estate_btn",			god || owner || manager);
 	childSetEnabled("kick_user_from_estate_btn",	god || owner || manager);
-#if ELAR_ENABLED
-	childSetEnabled("abuse_email_address", 			god || owner || manager);
-#else
-	childSetEnabled("abuse_email_address", 			false);
-#endif
 
 	// estate managers can't add estate managers
 	childSetEnabled("add_estate_manager_btn",		god || owner);
@@ -2065,8 +2058,6 @@ BOOL LLPanelEstateInfo::postBuild()
 	initCtrl("limit_payment");
 	initCtrl("limit_age_verified");
 	initCtrl("voice_chat_check");
-	getChild<LLUICtrl>("abuse_email_address")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAnything, this));
-	getChild<LLLineEditor>("abuse_email_address")->setKeystrokeCallback(onChangeText, this);
 
 	// set up the use global time checkbox
 	getChild<LLUICtrl>("use_global_time_check")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeUseGlobalTime, this));
@@ -2276,8 +2267,6 @@ bool LLPanelEstateInfo::commitEstateInfoCaps()
 	}
 	body["sun_hour"] = sun_hour;
 
-	body["owner_abuse_email"] = childGetValue("abuse_email_address").asString();
-
 	// we use a responder so that we can re-get the data after committing to the database
 	LLHTTPClient::post(url, body, new LLEstateChangeInfoResponder(this));
     return true;
@@ -2436,16 +2425,6 @@ void LLPanelEstateInfo::setOwnerName(const std::string& name)
 	childSetValue("estate_owner", LLSD(name));
 }
 
-const std::string LLPanelEstateInfo::getAbuseEmailAddress() const
-{
-	return childGetValue("abuse_email_address").asString();
-}
-
-void LLPanelEstateInfo::setAbuseEmailAddress(const std::string& address)
-{
-	childSetValue("abuse_email_address", LLSD(address));
-}
-
 void LLPanelEstateInfo::setAccessAllowedEnabled(bool enable_agent,
 												bool enable_group,
 												bool enable_ban)
@@ -2954,18 +2933,6 @@ bool LLDispatchEstateUpdateInfo::operator()(
 	std::string estate_name = strings[0].c_str(); // preserve c_str() call!
 	panel->setEstateName(estate_name);
 	
-#if ELAR_ENABLED
-	if (strings.size() > 9)
-	{
-		std::string abuse_email = strings[9].c_str(); // preserve c_str() call!
-		panel->setAbuseEmailAddress(abuse_email);
-	}
-	else
-#endif
-	{
-		panel->setAbuseEmailAddress(panel->getString("email_unsupported"));
-	}
-
 	LLViewerRegion* regionp = gAgent.getRegion();
 
 	LLUUID owner_id(strings[1]);
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index a3b91223b78bed0785923fcaf73af96104e99f8b..704166d1065e66b22c612f04290a5b5039bd2993 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -330,9 +330,6 @@ class LLPanelEstateInfo : public LLPanelRegionInfo
 	const std::string getOwnerName() const;
 	void setOwnerName(const std::string& name);
 
-	const std::string getAbuseEmailAddress() const;
-	void setAbuseEmailAddress(const std::string& address);
-
 	// If visible from mainland, allowed agent and allowed groups
 	// are ignored, so must disable UI.
 	void setAccessAllowedEnabled(bool enable_agent, bool enable_group, bool enable_ban);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 408303a1e0474f142b6b9d9f8057a65ea836244f..932e49c79be542cd5e015149938fed648da7232d 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -95,7 +95,6 @@ const U32 INCLUDE_SCREENSHOT  = 0x01 << 0;
 LLFloaterReporter::LLFloaterReporter(const LLSD& key)
 :	LLFloater(key),
 	mReportType(COMPLAINT_REPORT),
-	mEmailToEstateOwner(FALSE),
 	mObjectID(),
 	mScreenID(),
 	mAbuserID(),
@@ -117,18 +116,7 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
 	
 	if ( LLFloaterReg::instanceVisible("reporter") )
 	{
-		LLFloaterReporter *f = LLFloaterReg::findTypedInstance<LLFloaterReporter>("reporter");
-		BOOL email_to_estate_owner = ( region_flags & REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER );
-		f->mEmailToEstateOwner = email_to_estate_owner;
-
-		if ( email_to_estate_owner )
-		{
-			LLNotificationsUtil::add("HelpReportAbuseEmailEO");
-		}
-		else
-		{
-			LLNotificationsUtil::add("HelpReportAbuseEmailLL");
-		}
+		LLNotificationsUtil::add("HelpReportAbuseEmailLL");
 	};
 }
 // virtual
@@ -218,17 +206,7 @@ LLFloaterReporter::~LLFloaterReporter()
 // virtual
 void LLFloaterReporter::draw()
 {
-	// this is set by a static callback sometime after the dialog is created.
-	// Only disable screenshot for abuse reports to estate owners
-	if ( mEmailToEstateOwner )
-	{
-		childSetValue("screen_check", FALSE );
-		childSetEnabled("screen_check", FALSE );
-	}
-	else
-	{
-		childSetEnabled("screen_check", TRUE );
-	}
+	childSetEnabled("screen_check", TRUE );
 
 	LLFloater::draw();
 }
@@ -637,11 +615,7 @@ LLSD LLFloaterReporter::gatherReport()
 	LLUUID screenshot_id = LLUUID::null;
 	if (childGetValue("screen_check"))
 	{
-
-		if ( mEmailToEstateOwner == FALSE )
-		{
-			screenshot_id = childGetValue("screenshot");
-		}
+		screenshot_id = childGetValue("screenshot");
 	};
 
 	LLSD report = LLSD::emptyMap();
diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h
index 917f51364170d4617d4f29bbaa6e59b325427433..a3776f3d279715f90a1a4240af71a87c56d42abc 100644
--- a/indra/newview/llfloaterreporter.h
+++ b/indra/newview/llfloaterreporter.h
@@ -124,7 +124,6 @@ class LLFloaterReporter
 
 private:
 	EReportType		mReportType;
-	BOOL			mEmailToEstateOwner;
 	LLUUID 			mObjectID;
 	LLUUID			mScreenID;
 	LLUUID			mAbuserID;
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 6ba032c152651f77d49c68a5c4b0e03f8f230396..7fb71d4d4f583fcabaf5ff9e632496c5f646fbbc 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -991,7 +991,7 @@ S32 LLFloaterTools::calcRenderCost()
 			if (viewer_volume)
 			{
 				cost += viewer_volume->getRenderCost(textures);
-				cost += textures.size() * 5;
+				cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
 				textures.clear();
 			}
 		}
@@ -1080,7 +1080,7 @@ void LLFloaterTools::getMediaState()
 {
 	LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection();
 	LLViewerObject* first_object = selected_objects->getFirstObject();
-	LLLineEditor* media_info = getChild<LLLineEditor>("media_info");
+	LLTextBox* media_info = getChild<LLTextBox>("media_info");
 	
 	if( !(first_object 
 		  && first_object->getPCode() == LL_PCODE_VOLUME
@@ -1088,12 +1088,6 @@ void LLFloaterTools::getMediaState()
 	      ))
 	{
 		childSetEnabled("Add_Media",  FALSE);
-/*		childSetEnabled("media_tex", FALSE);
-		childSetEnabled("add_media", FALSE);
-		childSetEnabled("delete_media", FALSE);
-		childSetEnabled("edit_media", FALSE);
-		childSetEnabled("media_info", FALSE);
-		media_info->setEnabled(FALSE);*/
 		media_info->clear();
 		clearMediaSettings();
 		return;
@@ -1105,13 +1099,6 @@ void LLFloaterTools::getMediaState()
 	if(!has_media_capability)
 	{
 		childSetEnabled("Add_Media",  FALSE);
-	/*	childSetEnabled("media_tex", FALSE);
-		childSetEnabled("add_media", FALSE);
-		childSetEnabled("delete_media", FALSE);
-		childSetEnabled("edit_media", FALSE);
-		childSetEnabled("media_info", FALSE);
-		media_info->setEnabled(FALSE);
-		media_info->clear();*/
 		LL_WARNS("LLFloaterTools: media") << "Media not enabled (no capability) in this region!" << LL_ENDL;
 		clearMediaSettings();
 		return;
@@ -1233,7 +1220,6 @@ void LLFloaterTools::getMediaState()
 		childSetEnabled( "edit_media", bool_has_media & editable );
 		childSetEnabled( "delete_media", bool_has_media & editable );
 		childSetEnabled( "add_media", ( ! bool_has_media ) & editable );
-		media_info->setEnabled(false);
 			// TODO: display a list of all media on the face - use 'identical' flag
 	}
 	else // not all face has media but at least one does.
@@ -1260,8 +1246,6 @@ void LLFloaterTools::getMediaState()
 			}
 		}
 		
-		media_info->setEnabled(false);
-		media_info->setTentative(true);
 		childSetEnabled("media_tex",  TRUE);
 		childSetEnabled( "edit_media", TRUE);
 		childSetEnabled( "delete_media", TRUE);
@@ -1392,7 +1376,7 @@ void LLFloaterTools::updateMediaTitle()
 		if ( ! media_title.empty() )
 		{
 			// update the UI widget
-			LLLineEditor* media_title_field = getChild<LLLineEditor>("media_info");
+			LLTextBox* media_title_field = getChild<LLTextBox>("media_info");
 			if ( media_title_field )
 			{
 				media_title_field->setText( media_title );
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index 43024a4bd03fd3ae7178fda4dc29feb774d0cf73..3951f4291f7b7ce3fd4fe3e069e51f97ea2acf7c 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -40,7 +40,6 @@
 #include "llcombobox.h"
 #include "llfocusmgr.h"
 #include "lliconctrl.h"
-#include "llsliderctrl.h"
 #include "llviewercontrol.h"
 #include "llvoiceclient.h"
 #include "llvoicechannel.h"
@@ -61,9 +60,6 @@ LLPanelVoiceDeviceSettings::LLPanelVoiceDeviceSettings()
 	mOutputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
 	mDevicesUpdated = FALSE;
 
-	// grab "live" mic volume level
-	mMicVolume = gSavedSettings.getF32("AudioLevelMic");
-
 	// ask for new device enumeration
 	// now do this in onOpen() instead...
 	//gVoiceClient->refreshDeviceLists();
@@ -75,10 +71,6 @@ LLPanelVoiceDeviceSettings::~LLPanelVoiceDeviceSettings()
 
 BOOL LLPanelVoiceDeviceSettings::postBuild()
 {
-	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
-	// set mic volume tuning slider based on last mic volume setting
-	volume_slider->setValue(mMicVolume);
-
 	childSetCommitCallback("voice_input_device", onCommitInputDevice, this);
 	childSetCommitCallback("voice_output_device", onCommitOutputDevice, this);
 	
@@ -157,15 +149,6 @@ void LLPanelVoiceDeviceSettings::apply()
 		gSavedSettings.setString("VoiceOutputAudioDevice", s);
 		mOutputDevice = s;
 	}
-
-	// assume we are being destroyed by closing our embedding window
-	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
-	if(volume_slider)
-	{
-		F32 slider_value = (F32)volume_slider->getValue().asReal();
-		gSavedSettings.setF32("AudioLevelMic", slider_value);
-		mMicVolume = slider_value;
-	}
 }
 
 void LLPanelVoiceDeviceSettings::cancel()
@@ -178,22 +161,12 @@ void LLPanelVoiceDeviceSettings::cancel()
 
 	if(mCtrlOutputDevices)
 		mCtrlOutputDevices->setSimple(mOutputDevice);
-
-	gSavedSettings.setF32("AudioLevelMic", mMicVolume);
-	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
-	if(volume_slider)
-	{
-		volume_slider->setValue(mMicVolume);
-	}
 }
 
 void LLPanelVoiceDeviceSettings::refresh()
 {
-	//grab current volume
-	LLSlider* volume_slider = getChild<LLSlider>("mic_volume_slider");
-	// set mic volume tuning slider based on last mic volume setting
-	F32 current_volume = (F32)volume_slider->getValue().asReal();
-	gVoiceClient->tuningSetMicVolume(current_volume);
+	// update the live input level display
+	gVoiceClient->tuningSetMicVolume();
 
 	// Fill in popup menus
 	mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
@@ -263,7 +236,6 @@ void LLPanelVoiceDeviceSettings::initialize()
 {
 	mInputDevice = gSavedSettings.getString("VoiceInputAudioDevice");
 	mOutputDevice = gSavedSettings.getString("VoiceOutputAudioDevice");
-	mMicVolume = gSavedSettings.getF32("AudioLevelMic");
 	mDevicesUpdated = FALSE;
 
 	// ask for new device enumeration
diff --git a/indra/newview/llfloatervoicedevicesettings.h b/indra/newview/llfloatervoicedevicesettings.h
index d67283d0a224d5a4357bbeb4cb97c086998a3806..20958af780c37b084e1791a79ccc3c4fb30c2c99 100644
--- a/indra/newview/llfloatervoicedevicesettings.h
+++ b/indra/newview/llfloatervoicedevicesettings.h
@@ -56,7 +56,6 @@ class LLPanelVoiceDeviceSettings : public LLPanel
 	static void onCommitInputDevice(LLUICtrl* ctrl, void* user_data);
 	static void onCommitOutputDevice(LLUICtrl* ctrl, void* user_data);
 
-	F32 mMicVolume;
 	std::string mInputDevice;
 	std::string mOutputDevice;
 	class LLComboBox		*mCtrlInputDevices;
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 5bef3064851ef3223dcc1e9224e456cf0eca49b3..fe793fbcb8afddd9b469dd72b3b6b9e8074eb5fc 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -40,6 +40,7 @@
 #include "llinventoryfilter.h"
 #include "llpanel.h"
 #include "llviewercontrol.h"	// gSavedSettings
+#include "llviewerinventory.h"
 #include "llviewerwindow.h"		// Argh, only for setCursor()
 
 // linden library includes
@@ -603,6 +604,11 @@ const std::string& LLFolderViewItem::getSearchableLabel() const
 	return mSearchableLabel;
 }
 
+LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void)
+{
+	return gInventory.getItem(getListener()->getUUID());
+}
+
 std::string LLFolderViewItem::getName( void ) const
 {
 	if(mListener)
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 0ea031108bdb1e70f545126bc270daec77c97f76..43a5fd8de52337be1c8cdc52fc6d7a2a9e438ab9 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -45,6 +45,7 @@ class LLFolderViewListenerFunctor;
 class LLInventoryFilter;
 class LLMenuGL;
 class LLUIImage;
+class LLViewerInventoryItem;
 
 // These are grouping of inventory types.
 // Order matters when sorting system folders to the top.
@@ -281,6 +282,9 @@ class LLFolderViewItem : public LLView
 
 	const LLFolderViewEventListener* getListener( void ) const { return mListener; }
 	LLFolderViewEventListener* getListener( void ) { return mListener; }
+	
+	// Gets the inventory item if it exists (null otherwise)
+	LLViewerInventoryItem * getInventoryItem(void);
 
 	// just rename the object.
 	void rename(const std::string& new_name);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 3746e9cfeb55263099722134b9a96359c3490b66..26a8a707b87b1530491ceb6f876cdaeaec351eab 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -506,12 +506,59 @@ void hide_context_entries(LLMenuGL& menu,
 	}
 }
 
+bool isWornLink(LLUUID link_id)
+{
+	LLViewerInventoryItem *link = gInventory.getItem(link_id);
+	if (!link)
+		return false;
+	LLViewerInventoryItem *item = link->getLinkedItem();
+	if (!item)
+		return false;
+	
+	switch(item->getType())
+	{
+	case LLAssetType::AT_OBJECT:
+	{
+		LLVOAvatarSelf* my_avatar = gAgent.getAvatarObject();
+		if(my_avatar && my_avatar->isWearingAttachment(item->getUUID()))
+			return true;
+	}
+	break;
+
+	case LLAssetType::AT_BODYPART:
+	case LLAssetType::AT_CLOTHING:
+		if(gAgentWearables.isWearingItem(item->getUUID()))
+			return true;
+		break;
+
+	case LLAssetType::AT_GESTURE:
+		if (LLGestureManager::instance().isGestureActive(item->getUUID()))
+			return true;
+		break;
+	default:
+		break;
+	}
+	return false;
+}
+
 // Helper for commonly-used entries
 void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 										std::vector<std::string> &items,
 										std::vector<std::string> &disabled_items, U32 flags)
 {
 	const LLInventoryObject *obj = getInventoryObject();
+
+	bool is_sidepanel = isInOutfitsSidePanel();
+	if (is_sidepanel)
+	{
+		// Sidepanel includes restricted menu.
+		if (obj && obj->getIsLinkType() && !isWornLink(mUUID))
+		{
+			items.push_back(std::string("Remove Link"));
+		}
+		return;
+	}
+
 	if (obj)
 	{
 		if (obj->getIsLinkType())
@@ -566,6 +613,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
 	}
 	items.push_back(std::string("Paste Separator"));
 
+
+	if (obj && obj->getIsLinkType() && !isWornLink(mUUID))
+	{
+		items.push_back(std::string("Remove Link"));
+	}
+
 	items.push_back(std::string("Delete"));
 	if (!isItemRemovable())
 	{
@@ -913,6 +966,16 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
 	}
 }
 
+bool LLInvFVBridge::isInOutfitsSidePanel() const
+{
+	LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+	LLPanelOutfitsInventory *outfit_panel =
+		dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
+	if (!outfit_panel)
+		return false;
+	return outfit_panel->isAccordionPanel(my_panel);
+}
+
 // +=================================================+
 // |        InventoryFVBridgeBuilder                 |
 // +=================================================+
@@ -2386,19 +2449,6 @@ void LLFolderBridge::staticFolderOptionsMenu()
 	sSelf->folderOptionsMenu();
 }
 
-bool isInOutfitsSidePanel(LLPanel *panel)
-{
-	LLInventoryPanel *my_panel = dynamic_cast<LLInventoryPanel*>(panel);
-	LLPanelOutfitsInventory *outfit_panel =
-		dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory"));
-	if (!outfit_panel)
-		return false;
-	return outfit_panel->isAccordionPanel(my_panel);
-
-	//LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL;
-	//return (my_panel && (my_panel == outfit_inv_panel));
-}
-
 void LLFolderBridge::folderOptionsMenu()
 {
 	std::vector<std::string> disabled_items;
@@ -2412,13 +2462,12 @@ void LLFolderBridge::folderOptionsMenu()
 	// BAP change once we're no longer treating regular categories as ensembles.
 	const bool is_ensemble = category && (type == LLFolderType::FT_NONE ||
 										  LLFolderType::lookupIsEnsembleType(type));
-	const bool is_sidepanel = isInOutfitsSidePanel(mInventoryPanel.get());
 
 	// calling card related functionality for folders.
 
+	const bool is_sidepanel = isInOutfitsSidePanel();
 	if (is_sidepanel)
 	{
-		mItems.clear();
 		mItems.push_back("Rename");
 		mItems.push_back("Delete");
 	}
@@ -2488,14 +2537,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	mDisabledItems.clear();
 
 	lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
+
 //	std::vector<std::string> disabled_items;
 	LLInventoryModel* model = getInventoryModel();
 	if(!model) return;
 	const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
 	const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 
-	mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
-	mDisabledItems.clear(); //adding code to clear out disabled members from previous
 	if (lost_and_found_id == mUUID)
 	  {
 		// This is the lost+found folder.
@@ -2524,7 +2572,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		LLViewerInventoryCategory *cat =  getCategory();
 		// BAP removed protected check to re-enable standard ops in untyped folders.
 		// Not sure what the right thing is to do here.
-		if (!isCOFFolder() && cat /*&&
+		if (!isCOFFolder() && cat && cat->getPreferredType()!=LLFolderType::FT_OUTFIT /*&&
 			LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
 		{
 			// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
@@ -3150,6 +3198,22 @@ void LLTextureBridge::openItem()
 	}
 }
 
+bool LLTextureBridge::canSaveTexture(void)
+{
+	const LLInventoryModel* model = getInventoryModel();
+	if(!model) 
+	{
+		return false;
+	}
+	
+	const LLViewerInventoryItem *item = model->getItem(mUUID);
+	if (item)
+	{
+		return item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
+	}
+	return false;
+}
+
 void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 {
 	lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
@@ -3174,6 +3238,10 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 
 		items.push_back(std::string("Texture Separator"));
 		items.push_back(std::string("Save As"));
+		if (!canSaveTexture())
+		{
+			disabled_items.push_back(std::string("Save As"));
+		}
 	}
 	hide_context_entries(menu, items, disabled_items);	
 }
@@ -3776,8 +3844,13 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}
 	else
 	{
-		items.push_back(std::string("Open"));
-		items.push_back(std::string("Properties"));
+		bool is_sidepanel = isInOutfitsSidePanel();
+
+		if (!is_sidepanel)
+		{
+			items.push_back(std::string("Open"));
+			items.push_back(std::string("Properties"));
+		}
 
 		getClipboardEntries(true, items, disabled_items, flags);
 
@@ -4101,13 +4174,18 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	}
 	else
 	{
-		items.push_back(std::string("Properties"));
+		bool is_sidepanel = isInOutfitsSidePanel();
+
+		if (!is_sidepanel)
+		{
+			items.push_back(std::string("Properties"));
+		}
 
-		LLInventoryItem *item = getItem();
 		getClipboardEntries(true, items, disabled_items, flags);
 
 		LLObjectBridge::sContextMenuItemID = mUUID;
 
+		LLInventoryItem *item = getItem();
 		if(item)
 		{
 			LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
@@ -4533,19 +4611,23 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 		{
 			can_open = FALSE;
 		}
-		if (can_open)
+
+		bool is_sidepanel = isInOutfitsSidePanel();
+		
+		if (can_open && !is_sidepanel)
 		{
 			items.push_back(std::string("Open"));
 		}
 
-		items.push_back(std::string("Properties"));
+		if (!is_sidepanel)
+		{
+			items.push_back(std::string("Properties"));
+		}
 
 		getClipboardEntries(true, items, disabled_items, flags);
 
 		items.push_back(std::string("Wearable Separator"));
 
-		items.push_back(std::string("Wearable Wear"));
-		items.push_back(std::string("Wearable Add"));
 		items.push_back(std::string("Wearable Edit"));
 
 		if ((flags & FIRST_SELECTED_ITEM) == 0)
@@ -4575,6 +4657,8 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 					}
 					else
 					{
+						items.push_back(std::string("Wearable Wear"));
+						items.push_back(std::string("Wearable Add"));
 						disabled_items.push_back(std::string("Take Off"));
 					}
 					break;
@@ -4744,7 +4828,8 @@ void LLWearableBridge::onEditOnAvatar(void* user_data)
 
 void LLWearableBridge::editOnAvatar()
 {
-	const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
+	LLUUID linked_id = gInventory.getLinkedItemID(mUUID);
+	const LLWearable* wearable = gAgentWearables.getWearableFromItemID(linked_id);
 	if( wearable )
 	{
 		// Set the tab to the right wearable.
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 63be9dcdb82de1cc0d4e553404092cc2742e741d..117e32c6be516de1505fd35118839555a8fc3074 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -182,6 +182,9 @@ class LLInvFVBridge : public LLFolderViewEventListener
 	// LLInvFVBridge functionality
 	virtual void clearDisplayName() {}
 
+	// Allow context menus to be customized for side panel.
+	bool isInOutfitsSidePanel() const;
+
 protected:
 	LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid);
 
@@ -377,6 +380,7 @@ class LLTextureBridge : public LLItemBridge
 protected:
 	LLTextureBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type) :
 		LLItemBridge(inventory, uuid), mInvType(type) {}
+	bool canSaveTexture(void);
 	LLInventoryType::EType mInvType;
 };
 
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 3c337961e1af2bdec6a2737a99416187875d1714..2694075a58c8b08a3a928f51c297045e8a326765 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -58,251 +58,342 @@
 // - Any request that gets a 503 still goes through the retry logic
 //
 
+//
+// Forward decls
+//
 const F32 LLMediaDataClient::QUEUE_TIMER_DELAY = 1.0; // seconds(s)
 const F32 LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY = 5.0; // secs
 const U32 LLMediaDataClient::MAX_RETRIES = 4;
+const U32 LLMediaDataClient::MAX_SORTED_QUEUE_SIZE = 10000;
+const U32 LLMediaDataClient::MAX_ROUND_ROBIN_QUEUE_SIZE = 10000;
+
+// << operators
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q);
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &q);
 
 //////////////////////////////////////////////////////////////////////////////////////
 //
-// LLMediaDataClient::Request
+// LLMediaDataClient
 //
 //////////////////////////////////////////////////////////////////////////////////////
-/*static*/U32 LLMediaDataClient::Request::sNum = 0;
 
-LLMediaDataClient::Request::Request(const std::string &cap_name, 
-									const LLSD& sd_payload,
-									LLMediaDataClientObject *obj, 
-									LLMediaDataClient *mdc)
-	: mCapName(cap_name), 
-	  mPayload(sd_payload), 
-	  mObject(obj),
-	  mNum(++sNum), 
-	  mRetryCount(0),
-	  mMDC(mdc)
+LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
+									 F32 retry_timer_delay,
+									 U32 max_retries,
+									 U32 max_sorted_queue_size,
+									 U32 max_round_robin_queue_size)
+	: mQueueTimerDelay(queue_timer_delay),
+	  mRetryTimerDelay(retry_timer_delay),
+	  mMaxNumRetries(max_retries),
+	  mMaxSortedQueueSize(max_sorted_queue_size),
+	  mMaxRoundRobinQueueSize(max_round_robin_queue_size),
+	  mQueueTimerIsRunning(false),
+	  mCurrentQueueIsTheSortedQueue(true)
 {
 }
 
-LLMediaDataClient::Request::~Request()
+LLMediaDataClient::~LLMediaDataClient()
 {
-	LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL;
-	mMDC = NULL;
-	mObject = NULL;
-}
+	stopQueueTimer();
 
-													  
-std::string LLMediaDataClient::Request::getCapability() const
-{
-	return getObject()->getCapabilityUrl(getCapName());
+	// This should clear the queue, and hopefully call all the destructors.
+	LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " << 
+		(isEmpty() ? "<empty> " : "<not empty> ") << LL_ENDL;
+	
+	mSortedQueue.clear();
+	mRoundRobinQueue.clear();
 }
 
-// Helper function to get the "type" of request, which just pokes around to
-// discover it.
-LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const
+bool LLMediaDataClient::isEmpty() const
 {
-	if (mCapName == "ObjectMediaNavigate")
-	{
-		return NAVIGATE;
-	}
-	else if (mCapName == "ObjectMedia")
-	{
-		const std::string &verb = mPayload["verb"];
-		if (verb == "GET")
-		{
-			return GET;
-		}
-		else if (verb == "UPDATE")
-		{
-			return UPDATE;
-		}
-	}
-	llassert(false);
-	return GET;
+	return mSortedQueue.empty() && mRoundRobinQueue.empty();
 }
 
-const char *LLMediaDataClient::Request::getTypeAsString() const
+bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object)
 {
-	Type t = getType();
-	switch (t)
-	{
-		case GET:
-			return "GET";
-			break;
-		case UPDATE:
-			return "UPDATE";
-			break;
-		case NAVIGATE:
-			return "NAVIGATE";
-			break;
-	}
-	return "";
+	return (LLMediaDataClient::findOrRemove(mSortedQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()
+		|| (LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, false/*remove*/, LLMediaDataClient::Request::ANY).notNull()));
 }
-	
 
-void LLMediaDataClient::Request::reEnqueue() const
+bool LLMediaDataClient::removeFromQueue(const LLMediaDataClientObject::ptr_t &object)
 {
-	// I sure hope this doesn't deref a bad pointer:
-	mMDC->enqueue(this);
+	bool removedFromSortedQueue = LLMediaDataClient::findOrRemove(mSortedQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull();
+	bool removedFromRoundRobinQueue = LLMediaDataClient::findOrRemove(mRoundRobinQueue, object, true/*remove*/, LLMediaDataClient::Request::ANY).notNull();
+	return removedFromSortedQueue || removedFromRoundRobinQueue;
 }
 
-F32 LLMediaDataClient::Request::getRetryTimerDelay() const
+//static
+LLMediaDataClient::request_ptr_t LLMediaDataClient::findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, LLMediaDataClient::Request::Type type)
 {
-	return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY :
-		mMDC->mRetryTimerDelay; 
+	request_ptr_t result;
+	request_queue_t::iterator iter = queue.begin();
+	request_queue_t::iterator end = queue.end();
+	while (iter != end)
+	{
+		if (obj->getID() == (*iter)->getObject()->getID() && (type == LLMediaDataClient::Request::ANY || type == (*iter)->getType()))
+		{
+			result = *iter;
+			if (remove) queue.erase(iter);
+			break;
+		}
+		iter++;
+	}
+	return result;
 }
 
-U32 LLMediaDataClient::Request::getMaxNumRetries() const
+void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
 {
-	return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries;
+	if (object.isNull() || ! object->hasMedia()) return; 
+	
+	// Push the object on the queue
+	enqueue(new Request(getCapabilityName(), payload, object, this));
 }
 
-std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
+void LLMediaDataClient::enqueue(const Request *request)
 {
-	s << "<request>" 
-	  << "<num>" << r.getNum() << "</num>"
-	  << "<type>" << r.getTypeAsString() << "</type>"
-	  << "<object_id>" << r.getObject()->getID() << "</object_id>"
-	  << "<num_retries>" << r.getRetryCount() << "</num_retries>"
-	  << "</request> ";
-	return s;
+	if (request->isNew())
+	{		
+		// Add to sorted queue
+		if (LLMediaDataClient::findOrRemove(mSortedQueue, request->getObject(), true/*remove*/, request->getType()).notNull())
+		{
+			LL_DEBUGS("LLMediaDataClient") << "REMOVING OLD request for " << *request << " ALREADY THERE!" << LL_ENDL;
+		}
+		
+		LL_DEBUGS("LLMediaDataClient") << "Queuing SORTED request for " << *request << LL_ENDL;
+		
+		// Sadly, we have to const-cast because items put into the queue are not const
+		mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request));
+		
+		LL_DEBUGS("LLMediaDataClient") << "SORTED queue:" << mSortedQueue << LL_ENDL;
+	}
+	else {
+		if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize) 
+		{
+			LL_INFOS_ONCE("LLMediaDataClient") << "RR QUEUE MAXED OUT!!!" << LL_ENDL;
+			LL_DEBUGS("LLMediaDataClient") << "Not queuing " << *request << LL_ENDL;
+			return;
+		}
+				
+		// ROUND ROBIN: if it is there, and it is a GET request, leave it.  If not, put at front!		
+		request_ptr_t existing_request;
+		if (request->getType() == Request::GET)
+		{
+			existing_request = LLMediaDataClient::findOrRemove(mRoundRobinQueue, request->getObject(), false/*remove*/, request->getType());
+		}
+		if (existing_request.isNull())
+		{
+			LL_DEBUGS("LLMediaDataClient") << "Queuing RR request for " << *request << LL_ENDL;
+			// Push the request on the pending queue
+			// Sadly, we have to const-cast because items put into the queue are not const
+			mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request));
+			
+			LL_DEBUGS("LLMediaDataClient") << "RR queue:" << mRoundRobinQueue << LL_ENDL;			
+		}
+		else
+		{
+			LL_DEBUGS("LLMediaDataClient") << "ALREADY THERE: NOT Queuing request for " << *request << LL_ENDL;
+						
+			existing_request->markSent(false);
+		}
+	}	
+	// Start the timer if not already running
+	startQueueTimer();
 }
 
-
-//////////////////////////////////////////////////////////////////////////////////////
-//
-// LLMediaDataClient::Responder::RetryTimer
-//
-//////////////////////////////////////////////////////////////////////////////////////
-
-LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
-	: LLEventTimer(time), mResponder(mdr)
+void LLMediaDataClient::startQueueTimer() 
 {
+	if (! mQueueTimerIsRunning)
+	{
+		LL_DEBUGS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
+		// LLEventTimer automagically takes care of the lifetime of this object
+		new QueueTimer(mQueueTimerDelay, this);
+	}
+	else { 
+		LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
+	}
 }
 
-// virtual 
-LLMediaDataClient::Responder::RetryTimer::~RetryTimer() 
+void LLMediaDataClient::stopQueueTimer()
 {
-	LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
-
-	// XXX This is weird: Instead of doing the work in tick()  (which re-schedules
-	// a timer, which might be risky), do it here, in the destructor.  Yes, it is very odd.
-	// Instead of retrying, we just put the request back onto the queue
-	LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << "retrying" << LL_ENDL;
-	mResponder->getRequest()->reEnqueue();
-
-	// Release the ref to the responder.
-	mResponder = NULL;
+	mQueueTimerIsRunning = false;
 }
 
-// virtual
-BOOL LLMediaDataClient::Responder::RetryTimer::tick()
+bool LLMediaDataClient::processQueueTimer()
 {
-	// Don't fire again
-	return TRUE;
+	sortQueue();
+	
+	if(!isEmpty())
+	{
+		LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is:	  " << mSortedQueue.size() 
+			<< ", RR queue size is:	  " << mRoundRobinQueue.size() << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue is:	  " << mSortedQueue << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, RR queue is:	  " << mRoundRobinQueue << LL_ENDL;
+	}
+	
+	serviceQueue();
+	
+	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is:	  " << mSortedQueue.size() 
+		<< ", RR queue size is:	  " << mRoundRobinQueue.size() << LL_ENDL;
+	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue is:	  " << mSortedQueue << LL_ENDL;
+	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, RR queue is:	  " << mRoundRobinQueue << LL_ENDL;
+	
+	return isEmpty();
 }
 
-
-//////////////////////////////////////////////////////////////////////////////////////
-//
-// LLMediaDataClient::Responder
-//
-//////////////////////////////////////////////////////////////////////////////////////
-
-LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
-	: mRequest(request)
+void LLMediaDataClient::sortQueue()
 {
+	if(!mSortedQueue.empty())
+	{
+		// Score all items first
+		request_queue_t::iterator iter = mSortedQueue.begin();
+		request_queue_t::iterator end = mSortedQueue.end();
+		while (iter != end)
+		{
+			(*iter)->updateScore();
+			iter++;
+		}
+		
+		// Re-sort the list...
+		// NOTE: should this be a stable_sort?  If so we need to change to using a vector.
+		mSortedQueue.sort(LLMediaDataClient::compareRequests);
+		
+		// ...then cull items over the max
+		U32 size = mSortedQueue.size();
+		if (size > mMaxSortedQueueSize) 
+		{
+			U32 num_to_cull = (size - mMaxSortedQueueSize);
+			LL_INFOS("LLMediaDataClient") << "sorted queue MAXED OUT!  Culling " 
+				<< num_to_cull << " items" << LL_ENDL;
+			while (num_to_cull-- > 0)
+			{
+				mSortedQueue.pop_back();
+			}
+		}
+	}
 }
 
-LLMediaDataClient::Responder::~Responder()
+// static
+bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2)
 {
-	LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL;
-	mRequest = NULL;
+	if (o2.isNull()) return true;
+	if (o1.isNull()) return false;
+	return ( o1->getScore() > o2->getScore() );
 }
 
-/*virtual*/
-void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
-{
-	if (status == HTTP_SERVICE_UNAVAILABLE)
+void LLMediaDataClient::serviceQueue()
+{	
+	request_queue_t *queue_p = getCurrentQueue();
+	
+	// quick retry loop for cases where we shouldn't wait for the next timer tick
+	while(true)
 	{
-		F32 retry_timeout = mRequest->getRetryTimerDelay();
-
-		mRequest->incRetryCount();
+		if (queue_p->empty())
+		{
+			LL_DEBUGS("LLMediaDataClient") << "queue empty: " << (*queue_p) << LL_ENDL;
+			break;
+		}
 		
-		if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) 
+		// Peel one off of the items from the queue, and execute request
+		request_ptr_t request = queue_p->front();
+		llassert(!request.isNull());
+		const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
+		llassert(NULL != object);
+		
+		// Check for conditions that would make us just pop and rapidly loop through
+		// the queue.
+		if(request.isNull() ||
+		   request->isMarkedSent() ||
+		   NULL == object ||
+		   object->isDead() ||
+		   !object->hasMedia())
 		{
-			LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+			if (request.isNull()) 
+			{
+				LL_INFOS("LLMediaDataClient") << "Skipping NULL request" << LL_ENDL;
+			}
+			else {
+				LL_INFOS("LLMediaDataClient") << "Skipping : " << *request << " " 
+				<< ((request->isMarkedSent()) ? " request is marked sent" :
+					((NULL == object) ? " object is NULL " :
+					 ((object->isDead()) ? "object is dead" : 
+					  ((!object->hasMedia()) ? "object has no media!" : "BADNESS!")))) << LL_ENDL;
+			}
+			queue_p->pop_front();
+			continue;	// jump back to the start of the quick retry loop
+		}
+		
+		// Next, ask if this is "interesting enough" to fetch.  If not, just stop
+		// and wait for the next timer go-round.  Only do this for the sorted 
+		// queue.
+		if (mCurrentQueueIsTheSortedQueue && !object->isInterestingEnough())
+		{
+			LL_DEBUGS("LLMediaDataClient") << "Not fetching " << *request << ": not interesting enough" << LL_ENDL;
+			break;
+		}
+		
+		// Finally, try to send the HTTP message to the cap url
+		std::string url = request->getCapability();
+		bool maybe_retry = false;
+		if (!url.empty())
+		{
+			const LLSD &sd_payload = request->getPayload();
+			LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL;
+			
+			// Call the subclass for creating the responder
+			LLHTTPClient::post(url, sd_payload, createResponder(request));
+		}
+		else {
+			LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
+			maybe_retry = true;
+		}
 
-			// Start timer (instances are automagically tracked by
-			// InstanceTracker<> and LLEventTimer)
-			new RetryTimer(F32(retry_timeout/*secs*/), this);
+		bool exceeded_retries = request->getRetryCount() > mMaxNumRetries;
+		if (maybe_retry && ! exceeded_retries) // Try N times before giving up 
+		{
+			// We got an empty cap, but in that case we will retry again next
+			// timer fire.
+			request->incRetryCount();
 		}
 		else {
-			LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retry count " << 
-				mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
+			if (exceeded_retries)
+			{
+				LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " 
+					<< mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL; 
+				// XXX Should we bring up a warning dialog??
+			}
+			
+			queue_p->pop_front();
+			
+			if (! mCurrentQueueIsTheSortedQueue) {
+				// Round robin
+				request->markSent(true);
+				mRoundRobinQueue.push_back(request);				
+			}
 		}
+		
+ 		// end of quick loop -- any cases where we want to loop will use 'continue' to jump back to the start.
+ 		break;
 	}
-	else {
-		std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason;
-		LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL;
-	}
+	
+	swapCurrentQueue();
 }
 
-
-/*virtual*/
-void LLMediaDataClient::Responder::result(const LLSD& content)
+void LLMediaDataClient::swapCurrentQueue()
 {
-	LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL;
+	// Swap
+	mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue;
+	// If its empty, swap back
+	if (getCurrentQueue()->empty()) 
+	{
+		mCurrentQueueIsTheSortedQueue = !mCurrentQueueIsTheSortedQueue;
+	}
 }
 
-
-//////////////////////////////////////////////////////////////////////////////////////
-//
-// LLMediaDataClient::Comparator
-//
-//////////////////////////////////////////////////////////////////////////////////////
-
-// static
-bool LLMediaDataClient::compareRequests(const request_ptr_t &o1, const request_ptr_t &o2)
+LLMediaDataClient::request_queue_t *LLMediaDataClient::getCurrentQueue()
 {
-	if (o2.isNull()) return true;
-	if (o1.isNull()) return false;
-
-	// The score is intended to be a measure of how close an object is or
-	// how much screen real estate (interest) it takes up
-	// Further away = lower score.
-	// Lesser interest = lower score
-	// For instance, here are some cases:
-	// 1: Two items with no impl, closest one wins
-	// 2: Two items with an impl: interest should rule, but distance is
-	// still taken into account (i.e. something really close might take
-	// precedence over a large item far away)
-	// 3: One item with an impl, another without: item with impl wins 
-	//	  (XXX is that what we want?)		 
-	// Calculate the scores for each.  
-	F64 o1_score = getObjectScore(o1->getObject());
-	F64 o2_score = getObjectScore(o2->getObject());
-	return ( o1_score > o2_score );
+	return (mCurrentQueueIsTheSortedQueue) ? &mSortedQueue : &mRoundRobinQueue;
 }
 
-// static
-F64 LLMediaDataClient::getObjectScore(const LLMediaDataClientObject::ptr_t &obj)
-{
-	// *TODO: make this less expensive?
-	F64 dist = obj->getDistanceFromAvatar() + 0.1;	 // avoids div by 0
-	// square the distance so that they are in the same "unit magnitude" as
-	// the interest (which is an area) 
-	dist *= dist;
-	F64 interest = obj->getTotalMediaInterest() + 1.0;
-		
-	return interest/dist;	   
-}
-
-//////////////////////////////////////////////////////////////////////////////////////
-//
-// LLMediaDataClient::PriorityQueue
-// Queue of LLMediaDataClientObject smart pointers to request media for.
-//
-//////////////////////////////////////////////////////////////////////////////////////
-
 // dump the queue
 std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue_t &q)
 {
@@ -318,22 +409,6 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::request_queue
 	return s;
 }
 
-// find the given object in the queue.
-bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const
-{
-	request_queue_t::const_iterator iter = pRequestQueue->begin();
-	request_queue_t::const_iterator end = pRequestQueue->end();
-	while (iter != end)
-	{
-		if (obj->getID() == (*iter)->getObject()->getID())
-		{
-			return true;
-		}
-		iter++;
-	}
-	return false;
-}
-
 //////////////////////////////////////////////////////////////////////////////////////
 //
 // LLMediaDataClient::QueueTimer
@@ -342,7 +417,7 @@ bool LLMediaDataClient::find(const LLMediaDataClientObject::ptr_t &obj) const
 //////////////////////////////////////////////////////////////////////////////////////
 
 LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
-	: LLEventTimer(time), mMDC(mdc)
+: LLEventTimer(time), mMDC(mdc)
 {
 	mMDC->setIsRunning(true);
 }
@@ -357,177 +432,224 @@ LLMediaDataClient::QueueTimer::~QueueTimer()
 // virtual
 BOOL LLMediaDataClient::QueueTimer::tick()
 {
-	if (NULL == mMDC->pRequestQueue)
-	{
-		// Shutting down?  stop.
-		LL_DEBUGS("LLMediaDataClient") << "queue gone" << LL_ENDL;
-		return TRUE;
-	}
-	
-	request_queue_t &queue = *(mMDC->pRequestQueue);
+	if (mMDC.isNull()) return TRUE;
+	return mMDC->processQueueTimer();
+}
 
-	if(!queue.empty())
-	{
-		LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is:	  " << queue << LL_ENDL;
 
-		// Re-sort the list every time...
-		// XXX Is this really what we want?
-		queue.sort(LLMediaDataClient::compareRequests);
-	}
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Responder::RetryTimer
+//
+//////////////////////////////////////////////////////////////////////////////////////
+
+LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *mdr)
+: LLEventTimer(time), mResponder(mdr)
+{
+}
+
+// virtual 
+LLMediaDataClient::Responder::RetryTimer::~RetryTimer() 
+{
+	LL_DEBUGS("LLMediaDataClient") << "~RetryTimer" << *(mResponder->getRequest()) << LL_ENDL;
 	
-	// quick retry loop for cases where we shouldn't wait for the next timer tick
-	while(true)
-	{
-		if (queue.empty())
-		{
-			LL_DEBUGS("LLMediaDataClient") << "queue empty: " << queue << LL_ENDL;
-			return TRUE;
-		}
+	// XXX This is weird: Instead of doing the work in tick()  (which re-schedules
+	// a timer, which might be risky), do it here, in the destructor.  Yes, it is very odd.
+	// Instead of retrying, we just put the request back onto the queue
+	LL_INFOS("LLMediaDataClient") << "RetryTimer fired for: " << *(mResponder->getRequest()) << " retrying" << LL_ENDL;
+	mResponder->getRequest()->reEnqueue();
 	
-		// Peel one off of the items from the queue, and execute request
-		request_ptr_t request = queue.front();
-		llassert(!request.isNull());
-		const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
-		bool performed_request = false;
-		bool error = false;
-		llassert(NULL != object);
+	// Release the ref to the responder.
+	mResponder = NULL;
+}
 
-		if(object->isDead())
-		{
-			// This object has been marked dead.  Pop it and move on to the next item in the queue immediately.
-			LL_INFOS("LLMediaDataClient") << "Skipping " << *request << ": object is dead!" << LL_ENDL;
-			queue.pop_front();
-			continue;	// jump back to the start of the quick retry loop
-		}
+// virtual
+BOOL LLMediaDataClient::Responder::RetryTimer::tick()
+{
+	// Don't fire again
+	return TRUE;
+}
 
-		if (NULL != object && object->hasMedia())
-		{
-			std::string url = request->getCapability();
-			if (!url.empty())
-			{
-				const LLSD &sd_payload = request->getPayload();
-				LL_INFOS("LLMediaDataClient") << "Sending request for " << *request << LL_ENDL;
 
-				// Call the subclass for creating the responder
-				LLHTTPClient::post(url, sd_payload, mMDC->createResponder(request));
-				performed_request = true;
-			}
-			else {
-				LL_INFOS("LLMediaDataClient") << "NOT Sending request for " << *request << ": empty cap url!" << LL_ENDL;
-			}
-		}
-		else {
-			if (request.isNull()) 
-			{
-				LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL;
-			}
-			else if (NULL == object) 
-			{
-				LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL;
-			}
-			else if (!object->hasMedia())
-			{
-				LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
-			}
-			error = true;
-		}
-		bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries;
-		if (performed_request || exceeded_retries || error) // Try N times before giving up 
-		{
-			if (exceeded_retries)
-			{
-				LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " 
-											  << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL; 
-				// XXX Should we bring up a warning dialog??
-			}
-			queue.pop_front();
-		}
-		else {
-			request->incRetryCount();
-		}
-		
- 		// end of quick retry loop -- any cases where we want to loop will use 'continue' to jump back to the start.
- 		break;
-	}  
+//////////////////////////////////////////////////////////////////////////////////////
+//
+// LLMediaDataClient::Request
+//
+//////////////////////////////////////////////////////////////////////////////////////
+/*static*/U32 LLMediaDataClient::Request::sNum = 0;
 
-	LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, queue is now: " << (*(mMDC->pRequestQueue)) << LL_ENDL;
+LLMediaDataClient::Request::Request(const char *cap_name, 
+									const LLSD& sd_payload,
+									LLMediaDataClientObject *obj, 
+									LLMediaDataClient *mdc)
+: mCapName(cap_name), 
+  mPayload(sd_payload), 
+  mObject(obj),
+  mNum(++sNum), 
+  mRetryCount(0),
+  mMDC(mdc),
+  mMarkedSent(false),
+  mScore((F64)0.0)
+{
+}
 
-	return queue.empty();
+LLMediaDataClient::Request::~Request()
+{
+	LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL;
+	mMDC = NULL;
+	mObject = NULL;
 }
-	
-void LLMediaDataClient::startQueueTimer() 
+
+
+std::string LLMediaDataClient::Request::getCapability() const
 {
-	if (! mQueueTimerIsRunning)
+	return getObject()->getCapabilityUrl(getCapName());
+}
+
+// Helper function to get the "type" of request, which just pokes around to
+// discover it.
+LLMediaDataClient::Request::Type LLMediaDataClient::Request::getType() const
+{
+	if (0 == strcmp(mCapName, "ObjectMediaNavigate"))
 	{
-		LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
-		// LLEventTimer automagically takes care of the lifetime of this object
-		new QueueTimer(mQueueTimerDelay, this);
+		return NAVIGATE;
 	}
-	else { 
-		LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
+	else if (0 == strcmp(mCapName, "ObjectMedia"))
+	{
+		const std::string &verb = mPayload["verb"];
+		if (verb == "GET")
+		{
+			return GET;
+		}
+		else if (verb == "UPDATE")
+		{
+			return UPDATE;
+		}
 	}
+	llassert(false);
+	return GET;
 }
-	
-void LLMediaDataClient::stopQueueTimer()
+
+const char *LLMediaDataClient::Request::getTypeAsString() const
 {
-	mQueueTimerIsRunning = false;
+	Type t = getType();
+	switch (t)
+	{
+		case GET:
+			return "GET";
+			break;
+		case UPDATE:
+			return "UPDATE";
+			break;
+		case NAVIGATE:
+			return "NAVIGATE";
+			break;
+		case ANY:
+			return "ANY";
+			break;
+	}
+	return "";
 }
-	
-void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
+
+
+void LLMediaDataClient::Request::reEnqueue() const
 {
-	if (object.isNull() || ! object->hasMedia()) return; 
+	// I sure hope this doesn't deref a bad pointer:
+	mMDC->enqueue(this);
+}
 
-	// Push the object on the priority queue
-	enqueue(new Request(getCapabilityName(), payload, object, this));
+F32 LLMediaDataClient::Request::getRetryTimerDelay() const
+{
+	return (mMDC == NULL) ? LLMediaDataClient::UNAVAILABLE_RETRY_TIMER_DELAY :
+	mMDC->mRetryTimerDelay; 
 }
 
-void LLMediaDataClient::enqueue(const Request *request)
+U32 LLMediaDataClient::Request::getMaxNumRetries() const
 {
-	LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL;
-	// Push the request on the priority queue
-	// Sadly, we have to const-cast because items put into the queue are not const
-	pRequestQueue->push_back(const_cast<LLMediaDataClient::Request*>(request));
-	LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL;
-	// Start the timer if not already running
-	startQueueTimer();
+	return (mMDC == NULL) ? LLMediaDataClient::MAX_RETRIES : mMDC->mMaxNumRetries;
 }
 
+void LLMediaDataClient::Request::markSent(bool flag)
+{
+	 if (mMarkedSent != flag)
+	 {
+		 mMarkedSent = flag;
+		 if (!mMarkedSent)
+		 {
+			 mNum = ++sNum;
+		 }
+	 }
+}
+		   
+void LLMediaDataClient::Request::updateScore()
+{				
+	F64 tmp = mObject->getMediaInterest();
+	if (tmp != mScore)
+	{
+		LL_DEBUGS("LLMediaDataClient") << "Score for " << mObject->getID() << " changed from " << mScore << " to " << tmp << LL_ENDL; 
+		mScore = tmp;
+	}
+}
+		   
+std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
+{
+	s << "request: num=" << r.getNum() 
+	<< " type=" << r.getTypeAsString() 
+	<< " ID=" << r.getObject()->getID() 
+	<< " #retries=" << r.getRetryCount();
+	return s;
+}
+
+			
 //////////////////////////////////////////////////////////////////////////////////////
 //
-// LLMediaDataClient
+// LLMediaDataClient::Responder
 //
 //////////////////////////////////////////////////////////////////////////////////////
 
-LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
-									 F32 retry_timer_delay,
-									 U32 max_retries)
-	: mQueueTimerDelay(queue_timer_delay),
-	  mRetryTimerDelay(retry_timer_delay),
-	  mMaxNumRetries(max_retries),
-	  mQueueTimerIsRunning(false)
+LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
+: mRequest(request)
 {
-	pRequestQueue = new request_queue_t();
 }
 
-LLMediaDataClient::~LLMediaDataClient()
+LLMediaDataClient::Responder::~Responder()
 {
-	stopQueueTimer();
-
-	// This should clear the queue, and hopefully call all the destructors.
-	LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " << 
-		(pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL;
-	delete pRequestQueue;
-	pRequestQueue = NULL;
+	LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL;
+	mRequest = NULL;
 }
 
-bool LLMediaDataClient::isEmpty() const
+/*virtual*/
+void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
 {
-	return (NULL == pRequestQueue) ? true : pRequestQueue->empty();
+	if (status == HTTP_SERVICE_UNAVAILABLE)
+	{
+		F32 retry_timeout = mRequest->getRetryTimerDelay();
+		
+		mRequest->incRetryCount();
+		
+		if (mRequest->getRetryCount() < mRequest->getMaxNumRetries()) 
+		{
+			LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+			
+			// Start timer (instances are automagically tracked by
+			// InstanceTracker<> and LLEventTimer)
+			new RetryTimer(F32(retry_timeout/*secs*/), this);
+		}
+		else {
+			LL_INFOS("LLMediaDataClient") << *mRequest << " got SERVICE_UNAVAILABLE...retry count " << 
+			mRequest->getRetryCount() << " exceeds " << mRequest->getMaxNumRetries() << ", not retrying" << LL_ENDL;
+		}
+	}
+	else {
+		std::string msg = boost::lexical_cast<std::string>(status) + ": " + reason;
+		LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL;
+	}
 }
 
-bool LLMediaDataClient::isInQueue(const LLMediaDataClientObject::ptr_t &object) const
+/*virtual*/
+void LLMediaDataClient::Responder::result(const LLSD& content)
 {
-	return (NULL == pRequestQueue) ? false : find(object);
+	LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -569,7 +691,7 @@ void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
 	}
 	sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
 		
-	LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;
+	LL_DEBUGS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_print_sd(sd_payload) << LL_ENDL;
 	
 	request(object, sd_payload);
 }
@@ -581,7 +703,7 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
 	llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
 	if (type == LLMediaDataClient::Request::GET)
 	{
-		LL_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_print_sd(content) << LL_ENDL;
+		LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
 		
 		// Look for an error
 		if (content.has("error"))
@@ -598,12 +720,13 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
 			if (object_id != getRequest()->getObject()->getID()) 
 			{
 				// NOT good, wrong object id!!
-				LL_WARNS("LLMediaDataClient") << *(getRequest()) << "DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
+				LL_WARNS("LLMediaDataClient") << *(getRequest()) << " DROPPING response with wrong object id (" << object_id << ")" << LL_ENDL;
 				return;
 			}
 			
 			// Otherwise, update with object media data
-			getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY]);
+			getRequest()->getObject()->updateObjectMediaData(content[LLTextureEntry::OBJECT_MEDIA_DATA_KEY],
+															 content[LLTextureEntry::MEDIA_VERSION_KEY]);
 		}
 	}
 	else if (type == LLMediaDataClient::Request::UPDATE)
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 812e9cbdec808b7308ba1ada10d0b4a5b400ecfc..75d32e707b49cc7f8801d4902ca7ac0353c8b5cb 100755
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -55,15 +55,19 @@ class LLMediaDataClientObject : public LLRefCount
 	// Does this object have media?
 	virtual bool hasMedia() const = 0;
 	// Update the object's media data to the given array
-	virtual void updateObjectMediaData(LLSD const &media_data_array) = 0;
-	// Return the distance from the object to the avatar
-	virtual F64 getDistanceFromAvatar() const = 0;
+	virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &version_string) = 0;
 	// Return the total "interest" of the media (on-screen area)
-	virtual F64 getTotalMediaInterest() const = 0;
+	virtual F64 getMediaInterest() const = 0;
 	// Return the given cap url
 	virtual std::string getCapabilityUrl(const std::string &name) const = 0;
 	// Return whether the object has been marked dead
 	virtual bool isDead() const = 0;
+	// Returns a media version number for the object
+	virtual U32 getMediaVersion() const = 0;
+	// Returns whether the object is "interesting enough" to fetch
+	virtual bool isInterestingEnough() const = 0;
+	// Returns whether we've seen this object yet or not
+	virtual bool isNew() const = 0;
 
 	// smart pointer
 	typedef LLPointer<LLMediaDataClientObject> ptr_t;
@@ -79,11 +83,15 @@ class LLMediaDataClient : public LLRefCount
     const static F32 QUEUE_TIMER_DELAY;// = 1.0; // seconds(s)
 	const static F32 UNAVAILABLE_RETRY_TIMER_DELAY;// = 5.0; // secs
 	const static U32 MAX_RETRIES;// = 4;
+	const static U32 MAX_SORTED_QUEUE_SIZE;// = 10000;
+	const static U32 MAX_ROUND_ROBIN_QUEUE_SIZE;// = 10000;
 
 	// Constructor
 	LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
 					  F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
-		              U32 max_retries = MAX_RETRIES);
+		              U32 max_retries = MAX_RETRIES,
+					  U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+					  U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE);
 	
 	// Make the request
 	void request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload);
@@ -94,7 +102,13 @@ class LLMediaDataClient : public LLRefCount
 	bool isEmpty() const;
 	
 	// Returns true iff the given object is in the queue
-	bool isInQueue(const LLMediaDataClientObject::ptr_t &object) const;
+	bool isInQueue(const LLMediaDataClientObject::ptr_t &object);
+	
+	// Remove the given object from the queue. Returns true iff the given object is removed.
+	bool removeFromQueue(const LLMediaDataClientObject::ptr_t &object);
+	
+	// Called only by the Queue timer and tests (potentially)
+	bool processQueueTimer();
 	
 protected:
 	// Destructor
@@ -107,11 +121,12 @@ class LLMediaDataClient : public LLRefCount
         enum Type {
             GET,
             UPDATE,
-            NAVIGATE
+            NAVIGATE,
+			ANY
         };
         
-		Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
-		const std::string &getCapName() const { return mCapName; }
+		Request(const char *cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
+		const char *getCapName() const { return mCapName; }
 		const LLSD &getPayload() const { return mPayload; }
 		LLMediaDataClientObject *getObject() const { return mObject; }
 
@@ -132,6 +147,12 @@ class LLMediaDataClient : public LLRefCount
 		F32 getRetryTimerDelay() const;
 		U32 getMaxNumRetries() const;
 		
+		bool isNew() const { return mObject.notNull() ? mObject->isNew() : false; }
+		void markSent(bool flag);
+		bool isMarkedSent() const { return mMarkedSent; }
+		void updateScore();
+		F64 getScore() const { return mScore; }
+		
 	public:
 		friend std::ostream& operator<<(std::ostream &s, const Request &q);
 		
@@ -139,14 +160,16 @@ class LLMediaDataClient : public LLRefCount
         virtual ~Request(); // use unref();
         
 	private:
-		std::string mCapName;
+		const char *mCapName;
 		LLSD mPayload;
 		LLMediaDataClientObject::ptr_t mObject;
 		// Simple tracking
-		const U32 mNum;
+		U32 mNum;
 		static U32 sNum;
         U32 mRetryCount;
-		
+		F64 mScore;
+		bool mMarkedSent;
+
 		// Back pointer to the MDC...not a ref!
 		LLMediaDataClient *mMDC;
 	};
@@ -184,18 +207,23 @@ class LLMediaDataClient : public LLRefCount
 	};
 	
 protected:
-	
-	void enqueue(const Request*);
-	
+
 	// Subclasses must override this factory method to return a new responder
 	virtual Responder *createResponder(const request_ptr_t &request) const = 0;
 	
 	// Subclasses must override to return a cap name
 	virtual const char *getCapabilityName() const = 0;
 	
-private:
+	virtual void sortQueue();
+	virtual void serviceQueue();
 	
+private:
 	typedef std::list<request_ptr_t> request_queue_t;
+		
+	void enqueue(const Request*);
+	
+	// Return whether the given object is/was in the queue
+	static LLMediaDataClient::request_ptr_t findOrRemove(request_queue_t &queue, const LLMediaDataClientObject::ptr_t &obj, bool remove, Request::Type type);
 	
 	// Comparator for sorting
 	static bool compareRequests(const request_ptr_t &o1, const request_ptr_t &o2);
@@ -215,34 +243,40 @@ class LLMediaDataClient : public LLRefCount
 		// back-pointer
 		LLPointer<LLMediaDataClient> mMDC;
 	};
-
-	// Return whether the given object is in the queue
-	bool find(const LLMediaDataClientObject::ptr_t &obj) const;
 	
 	void startQueueTimer();
 	void stopQueueTimer();
 	void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
-
+	
+	void swapCurrentQueue();
+	request_queue_t *getCurrentQueue();
+	
 	const F32 mQueueTimerDelay;
 	const F32 mRetryTimerDelay;
 	const U32 mMaxNumRetries;
+	const U32 mMaxSortedQueueSize;
+	const U32 mMaxRoundRobinQueueSize;
 	
 	bool mQueueTimerIsRunning;
 	
-	request_queue_t *pRequestQueue;
+	request_queue_t mSortedQueue;
+	request_queue_t mRoundRobinQueue;
+	bool mCurrentQueueIsTheSortedQueue;
 };
 
 
-// MediaDataResponder specific for the ObjectMedia cap
+// MediaDataClient specific for the ObjectMedia cap
 class LLObjectMediaDataClient : public LLMediaDataClient
 {
 public:
     LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
 							F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
-							U32 max_retries = MAX_RETRIES)
+							U32 max_retries = MAX_RETRIES,
+							U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+							U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
 		: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
 		{}
-    ~LLObjectMediaDataClient() {}
+    virtual ~LLObjectMediaDataClient() {}
     
 	void fetchMedia(LLMediaDataClientObject *object); 
     void updateMedia(LLMediaDataClientObject *object);
@@ -264,7 +298,7 @@ class LLObjectMediaDataClient : public LLMediaDataClient
 };
 
 
-// MediaDataResponder specific for the ObjectMediaNavigate cap
+// MediaDataClient specific for the ObjectMediaNavigate cap
 class LLObjectMediaNavigateClient : public LLMediaDataClient
 {
 public:
@@ -273,10 +307,12 @@ class LLObjectMediaNavigateClient : public LLMediaDataClient
 	
     LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
 								F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
-								U32 max_retries = MAX_RETRIES)
+								U32 max_retries = MAX_RETRIES,
+								U32 max_sorted_queue_size = MAX_SORTED_QUEUE_SIZE,
+								U32 max_round_robin_queue_size = MAX_ROUND_ROBIN_QUEUE_SIZE)
 		: LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
 		{}
-    ~LLObjectMediaNavigateClient() {}
+    virtual ~LLObjectMediaNavigateClient() {}
     
     void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
     
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index a729b8c06ffc994088db83c309753d005797b305..a5bfa18851f3f0cae3ef51b6b501f1db78983e80 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -73,6 +73,11 @@
 #include "llfloatertos.h"
 #include "lltrans.h"
 #include "llglheaders.h"
+#include "llpanelloginlistener.h"
+
+#if LL_WINDOWS
+#pragma warning(disable: 4355)      // 'this' used in initializer list
+#endif  // LL_WINDOWS
 
 #define USE_VIEWER_AUTH 0
 
@@ -166,7 +171,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	mLogoImage(),
 	mCallback(callback),
 	mCallbackData(cb_data),
-	mHtmlAvailable( TRUE )
+	mHtmlAvailable( TRUE ),
+	mListener(new LLPanelLoginListener(this))
 {
 	setFocusRoot(TRUE);
 
@@ -452,7 +458,7 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask)
 	if ( KEY_F1 == key )
 	{
 		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-		vhelp->showTopic(vhelp->getTopicFromFocus());
+		vhelp->showTopic(vhelp->f1HelpTopic());
 		return TRUE;
 	}
 
@@ -972,7 +978,7 @@ void LLPanelLogin::onClickHelp(void*)
 	if (sInstance)
 	{
 		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-		vhelp->showTopic(vhelp->getTopicFromFocus());
+		vhelp->showTopic(vhelp->preLoginTopic());
 	}
 }
 
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index e3d30d7d0c028892e9ee553f6506e58abc08dfac..97350ce5c72a09654abb1145c0e3039bb7ef8f4d 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -36,10 +36,11 @@
 #include "llpanel.h"
 #include "llpointer.h"			// LLPointer<>
 #include "llmediactrl.h"	// LLMediaCtrlObserver
+#include <boost/scoped_ptr.hpp>
 
 class LLLineEditor;
 class LLUIImage;
-
+class LLPanelLoginListener;
 
 class LLPanelLogin:	
 	public LLPanel,
@@ -90,6 +91,7 @@ class LLPanelLogin:
 	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
 
 private:
+	friend class LLPanelLoginListener;
 	void reshapeBrowser();
 	static void onClickConnect(void*);
 	static void onClickNewAccount(void*);
@@ -103,6 +105,7 @@ class LLPanelLogin:
 	
 private:
 	LLPointer<LLUIImage> mLogoImage;
+	boost::scoped_ptr<LLPanelLoginListener> mListener;
 
 	void			(*mCallback)(S32 option, void *userdata);
 	void*			mCallbackData;
diff --git a/indra/newview/llpanelloginlistener.cpp b/indra/newview/llpanelloginlistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f7e59aaf54c6abaef7a710b6109daa0c25d201c5
--- /dev/null
+++ b/indra/newview/llpanelloginlistener.cpp
@@ -0,0 +1,34 @@
+/**
+ * @file   llpanelloginlistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-12-10
+ * @brief  Implementation for llpanelloginlistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llpanelloginlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llpanellogin.h"
+
+LLPanelLoginListener::LLPanelLoginListener(LLPanelLogin* instance):
+    LLEventAPI("LLPanelLogin", "Access to LLPanelLogin methods"),
+    mPanel(instance)
+{
+    add("onClickConnect",
+        "Pretend user clicked the \"Log In\" button",
+        &LLPanelLoginListener::onClickConnect);
+}
+
+void LLPanelLoginListener::onClickConnect(const LLSD&) const
+{
+    mPanel->onClickConnect(NULL);
+}
diff --git a/indra/newview/llpanelloginlistener.h b/indra/newview/llpanelloginlistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a56c75422d345f6ea73713abe34a53008ec48d6
--- /dev/null
+++ b/indra/newview/llpanelloginlistener.h
@@ -0,0 +1,30 @@
+/**
+ * @file   llpanelloginlistener.h
+ * @author Nat Goodspeed
+ * @date   2009-12-10
+ * @brief  LLEventAPI for LLPanelLogin
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLPANELLOGINLISTENER_H)
+#define LL_LLPANELLOGINLISTENER_H
+
+#include "lleventapi.h"
+class LLPanelLogin;
+class LLSD;
+
+class LLPanelLoginListener: public LLEventAPI
+{
+public:
+    LLPanelLoginListener(LLPanelLogin* instance);
+
+private:
+    void onClickConnect(const LLSD&) const;
+
+    LLPanelLogin* mPanel;
+};
+
+#endif /* ! defined(LL_LLPANELLOGINLISTENER_H) */
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 21627e84ff2cadcff30bfb994b3eb53b2517030d..cef21e85d6d584593b0115e4e740771e4eaca013 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -33,6 +33,7 @@
 #include "llviewerprecompiledheaders.h"
 #include "llpanelmaininventory.h"
 
+#include "llagent.h"
 #include "lldndbutton.h"
 #include "llfilepicker.h"
 #include "llfloaterinventory.h"
@@ -863,7 +864,6 @@ void LLPanelMainInventory::initListCommandsHandlers()
 	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
 	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	
 }
 
 void LLPanelMainInventory::updateListCommands()
@@ -909,6 +909,22 @@ void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)
 	getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
 }
 
+void LLPanelMainInventory::saveTexture(const LLSD& userdata)
+{
+	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+	if (!current_item)
+	{
+		return;
+	}
+	
+	const LLUUID& item_id = current_item->getListener()->getUUID();
+	LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);
+	if (preview_texture)
+	{
+		preview_texture->openToSave();
+	}
+}
+
 void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 {
 	if (!isActionEnabled(userdata))
@@ -953,18 +969,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 	}
 	if (command_name == "save_texture")
 	{
-		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
-		if (!current_item)
-		{
-			return;
-		}
-
-		const LLUUID& item_id = current_item->getListener()->getUUID();
-		LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);
-		if (preview_texture)
-		{
-			preview_texture->openToSave();
-		}
+		saveTexture(userdata);
 	}
 	// This doesn't currently work, since the viewer can't change an assetID an item.
 	if (command_name == "regenerate_link")
@@ -1008,6 +1013,22 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 	}
 }
 
+bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata)
+{
+	LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+	if (current_item) 
+	{
+		LLViewerInventoryItem *inv_item = current_item->getInventoryItem();
+		if(inv_item)
+		{
+			bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
+			LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType();
+			return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT);
+		}
+	}
+	return false;
+}
+
 BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
 {
 	const std::string command_name = userdata.asString();
@@ -1035,12 +1056,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
 	}
 	if (command_name == "save_texture")
 	{
-		LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
-		if (current_item)
-		{
-			return (current_item->getListener()->getInventoryType() == LLInventoryType::IT_TEXTURE);
-		}
-		return FALSE;
+		return isSaveTextureEnabled(userdata);
 	}
 	if (command_name == "find_original")
 	{
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index ae78d3bec82b0d1195c957b142fe4594596f8377..92443df369b28070a536c1432011b455895ed42c 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -110,6 +110,8 @@ class LLPanelMainInventory : public LLPanel, LLInventoryObserver
 	void doCreate(const LLSD& userdata);
 	void resetFilters();
 	void setSortBy(const LLSD& userdata);
+	void saveTexture(const LLSD& userdata);
+	bool isSaveTextureEnabled(const LLSD& userdata);
 	
 private:
 	LLFloaterInventoryFinder* getFinder();
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
index 3fa0e7bf8f882cd4724a18b3103cd1739a5c9bd8..88eba14553425ed758bef0eb3d32bd053e520e29 100644
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -94,7 +94,7 @@ BOOL LLPanelMediaSettingsGeneral::postBuild()
 	mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
 	mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY );
 	mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY );
-	mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY );
+	mCurrentURL = getChild< LLTextBox >( LLMediaEntry::CURRENT_URL_KEY );
 	mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY );
 	mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY );
 	mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY );
@@ -284,7 +284,7 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_
 		{ LLMediaEntry::AUTO_SCALE_KEY,				self->mAutoScale,		"LLCheckBoxCtrl" },
 		{ LLMediaEntry::AUTO_ZOOM_KEY,				self->mAutoZoom,		"LLCheckBoxCtrl" },
 		{ LLMediaEntry::CONTROLS_KEY,				self->mControls,		"LLComboBox" },
-		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLLineEditor" },
+		{ LLMediaEntry::CURRENT_URL_KEY,			self->mCurrentURL,		"LLTextBox" },
 		{ LLMediaEntry::HEIGHT_PIXELS_KEY,			self->mHeightPixels,	"LLSpinCtrl" },
 		{ LLMediaEntry::HOME_URL_KEY,				self->mHomeURL,			"LLLineEditor" },
 		{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY,	self->mFirstClick,		"LLCheckBoxCtrl" },
@@ -518,4 +518,9 @@ void LLPanelMediaSettingsGeneral::updateCurrentUrl()
 	bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_current_url, value_str );
 	mCurrentURL->setText(value_str);
 	mCurrentURL->setTentative(identical);
+
+	if ( LLPanelMediaSettingsGeneral::isMultiple() )
+	{
+		mCurrentURL->setText(LLTrans::getString("Multiple Media"));
+	}
 }	
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h
index 7782b25d63c5df37e37f8da8aa62701092101df8..c6895b1dc9f5cd0de7b5a3e66a5af15fb6f84ac6 100644
--- a/indra/newview/llpanelmediasettingsgeneral.h
+++ b/indra/newview/llpanelmediasettingsgeneral.h
@@ -99,7 +99,7 @@ class LLPanelMediaSettingsGeneral : public LLPanel
 	LLSpinCtrl* mWidthPixels;
 	LLSpinCtrl* mHeightPixels;
 	LLLineEditor* mHomeURL;
-	LLLineEditor* mCurrentURL;
+	LLTextBox* mCurrentURL;
 	LLMediaCtrl* mPreviewMedia;
 	LLTextBox* mFailWhiteListText;
 };
diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp
index d87c7608d5f6076dffbeee7b285cda495bc8a15c..aea6b0aa3b5deacdad2c0f83f1f737c931f89a42 100644
--- a/indra/newview/llpanelmediasettingssecurity.cpp
+++ b/indra/newview/llpanelmediasettingssecurity.cpp
@@ -167,6 +167,9 @@ void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media
 			data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
 		};
 	};
+
+	// initial update - hides/shows status messages etc.
+	self->updateWhitelistEnableStatus();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index 59a68bc12d04bb40e8ffa3176e823cb29e983051..7d21867efcbfaab673ba37797b091677ad3bb760 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -37,6 +37,7 @@
 #include "llagent.h"
 #include "llagentpicksinfo.h"
 #include "llavatarconstants.h"
+#include "llcommandhandler.h"
 #include "llflatlistview.h"
 #include "llfloaterreg.h"
 #include "llfloaterworldmap.h"
@@ -55,6 +56,8 @@
 #include "llpanelprofile.h"
 #include "llpanelpick.h"
 #include "llpanelclassified.h"
+#include "llpanelprofileview.h"
+#include "llsidetray.h"
 
 static const std::string XML_BTN_NEW = "new_btn";
 static const std::string XML_BTN_DELETE = "trash_btn";
@@ -72,6 +75,83 @@ static const std::string CLASSIFIED_NAME("classified_name");
 
 static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
 
+class LLClassifiedHandler :
+	public LLCommandHandler,
+	public LLAvatarPropertiesObserver
+{
+public:
+	// throttle calls from untrusted browsers
+	LLClassifiedHandler() :	LLCommandHandler("classified", UNTRUSTED_THROTTLE) {}
+
+	std::set<LLUUID> mClassifiedIds;
+
+	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
+	{
+		if (params.size() < 2)
+		{
+			return false;
+		}
+
+		// get the ID for the classified
+		LLUUID classified_id;
+		if (!classified_id.set(params[0], FALSE))
+		{
+			return false;
+		}
+
+		// show the classified in the side tray.
+		// need to ask the server for more info first though...
+		const std::string verb = params[1].asString();
+		if (verb == "about")
+		{
+			mClassifiedIds.insert(classified_id);
+			LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this);
+			LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id);
+			return true;
+		}
+
+		return false;
+	}
+
+	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type)
+	{
+		if (APT_CLASSIFIED_INFO != type)
+		{
+			return;
+		}
+
+		// is this the classified that we asked for?
+		LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+		if (!c_info || mClassifiedIds.find(c_info->classified_id) == mClassifiedIds.end())
+		{
+			return;
+		}
+
+		// open the people profile page for the classified's owner
+		LLSD params;
+		params["id"] = c_info->creator_id;
+		params["classified"] = c_info->classified_id;
+		params["open_tab_name"] = "panel_profile";
+		LLPanelProfileView *profile = dynamic_cast<LLPanelProfileView*>(LLSideTray::getInstance()->showPanel("panel_profile_view", params));
+
+		// then open the classified panel on this user's profile panel
+		if (profile)
+		{
+			LLPanelPicks* panel_picks = profile->getChild<LLPanelPicks>("panel_picks");
+			if (panel_picks)
+			{
+				panel_picks->openClassifiedInfo(c_info);
+			}
+		}
+
+		// remove our observer now that we're done
+		mClassifiedIds.erase(c_info->classified_id);
+		LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this);
+	}
+
+};
+LLClassifiedHandler gClassifiedHandler;
+
 //////////////////////////////////////////////////////////////////////////
 
 /**
@@ -624,6 +704,25 @@ void LLPanelPicks::openClassifiedInfo()
 	getProfilePanel()->openPanel(mPanelClassifiedInfo, params);
 }
 
+void LLPanelPicks::openClassifiedInfo(LLAvatarClassifiedInfo *c_info)
+{
+	if (! c_info)
+	{
+		return;
+	}
+
+	createClassifiedInfoPanel();
+
+	LLSD params;
+	params["classified_id"] = c_info->classified_id;
+	params["avatar_id"] = c_info->creator_id;
+	params["snapshot_id"] = c_info->snapshot_id;
+	params["name"] = c_info->name;
+	params["desc"] = c_info->description;
+
+	getProfilePanel()->openPanel(mPanelClassifiedInfo, params);
+}
+
 void LLPanelPicks::showAccordion(const std::string& name, bool show)
 {
 	LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name);
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 21794d56b2fe06ee952a33da2c3912d2cde5d132..893a0c53a3b1bcf0fc9ceb4a034a229089e8075f 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -86,6 +86,9 @@ class LLPanelPicks
 	// parent panels failed to work (picks related code was in my profile panel)
 	void setProfilePanel(LLPanelProfile* profile_panel);
 
+	// display the info panel for the given classified
+	void openClassifiedInfo(LLAvatarClassifiedInfo *c_info);
+
 protected:
 	/*virtual*/void updateButtons();
 
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 4a554c1b2c383dd0685dc28a736add5a0b6a13cb..e21eb01da341ce4e884a077756daa964e703ef66 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -278,12 +278,20 @@ void LLPanelPlaces::onOpen(const LLSD& key)
 	}
 	else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
 	{
-		mPosGlobal = LLVector3d(key["x"].asReal(),
-								key["y"].asReal(),
-								key["z"].asReal());
+		if (key.has("id"))
+		{
+			LLUUID parcel_id = key["id"].asUUID();
+			mPlaceProfile->setParcelID(parcel_id);
+		}
+		else
+		{
+			mPosGlobal = LLVector3d(key["x"].asReal(),
+									key["y"].asReal(),
+									key["z"].asReal());
+			mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
+		}
 
 		mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
-		mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
 	}
 	else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
 	{
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index aa2b7d4554b0f61b827552ff87e0d5d2acc016d0..3fe51106e4b34a56af0709feb45186ecf6d87191 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -150,7 +150,7 @@ BOOL LLPanelPrimMediaControls::postBuild()
 	mSkipFwdCtrl			= getChild<LLUICtrl>("skip_forward");
 	mSkipBackCtrl			= getChild<LLUICtrl>("skip_back");
 	mVolumeCtrl				= getChild<LLUICtrl>("media_volume");
-	mVolumeBtn				= getChild<LLButton>("media_volume_button");
+	mMuteBtn				= getChild<LLButton>("media_mute_button");
 	mVolumeUpCtrl			= getChild<LLUICtrl>("volume_up");
 	mVolumeDownCtrl			= getChild<LLUICtrl>("volume_down");
 	mVolumeSliderCtrl       = getChild<LLSliderCtrl>("volume_slider");
@@ -200,7 +200,7 @@ BOOL LLPanelPrimMediaControls::postBuild()
 		mScrollDownCtrl->setHeldDownCallback(onScrollDownHeld, this);
 		mScrollDownCtrl->setMouseUpCallback(onScrollStop, this);
 	}
-	
+		
 	mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
 	mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");
 	mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
@@ -215,11 +215,15 @@ void LLPanelPrimMediaControls::setMediaFace(LLPointer<LLViewerObject> objectp, S
 {
 	if (media_impl.notNull() && objectp.notNull())
 	{
+		LLUUID prev_id = mTargetImplID;
 		mTargetImplID = media_impl->getMediaTextureID();
 		mTargetObjectID = objectp->getID();
 		mTargetObjectFace = face;
 		mTargetObjectNormal = pick_normal;
 		mClearFaceOnFade = false;
+		
+		if (prev_id != mTargetImplID)
+			mVolumeSliderCtrl->setValue(media_impl->getVolume());
 	}
 	else
 	{
@@ -308,13 +312,12 @@ void LLPanelPrimMediaControls::updateShape()
 			enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
 			mini_controls = (LLMediaEntry::MINI == media_data->getControls());
 		}
-		
 		const bool is_hud = objectp->isHUDAttachment();
 		
 		//
 		// Set the state of the buttons
 		//
-				
+		
 		// XXX RSP: TODO: FIXME: clean this up so that it is clearer what mode we are in,
 		// and that only the proper controls get made visible/enabled according to that mode. 
 		mBackCtrl->setVisible(has_focus);
@@ -343,7 +346,7 @@ void LLPanelPrimMediaControls::updateShape()
 		mStopCtrl->setEnabled(has_focus && can_navigate);
 		mHomeCtrl->setEnabled(has_focus && can_navigate);
 		LLPluginClassMediaOwner::EMediaStatus result = ((media_impl != NULL) && media_impl->hasMedia()) ? media_plugin->getStatus() : LLPluginClassMediaOwner::MEDIA_NONE;
-
+		
 		if(media_plugin && media_plugin->pluginSupportsMediaTime())
 		{
 			mReloadCtrl->setEnabled(false);
@@ -360,14 +363,14 @@ void LLPanelPrimMediaControls::updateShape()
 			mSkipFwdCtrl->setEnabled(has_focus && !mini_controls);
 			mSkipBackCtrl->setVisible(has_focus && !mini_controls);
 			mSkipBackCtrl->setEnabled(has_focus && !mini_controls);
-				
+			
 			mVolumeCtrl->setVisible(has_focus);
 			mVolumeUpCtrl->setVisible(has_focus);
 			mVolumeDownCtrl->setVisible(has_focus);
 			mVolumeCtrl->setEnabled(has_focus);
 			mVolumeSliderCtrl->setEnabled(has_focus && mVolumeSliderVisible);
 			mVolumeSliderCtrl->setVisible(has_focus && mVolumeSliderVisible);
-
+			
 			mWhitelistIcon->setVisible(false);
 			mSecureLockIcon->setVisible(false);
 			if (mMediaPanelScroll)
@@ -378,7 +381,7 @@ void LLPanelPrimMediaControls::updateShape()
 				mScrollRightCtrl->setVisible(false);
 				mScrollDownCtrl->setVisible(false);
 			}
-				
+			
 			F32 volume = media_impl->getVolume();
 			// movie's url changed
 			if(mCurrentURL!=mPreviousURL)
@@ -386,7 +389,7 @@ void LLPanelPrimMediaControls::updateShape()
 				mMovieDuration = media_plugin->getDuration();
 				mPreviousURL = mCurrentURL;
 			}
-				
+			
 			if(mMovieDuration == 0) 
 			{
 				mMovieDuration = media_plugin->getDuration();
@@ -394,7 +397,7 @@ void LLPanelPrimMediaControls::updateShape()
 				mMediaPlaySliderCtrl->setEnabled(false);
 			}
 			// TODO: What if it's not fully loaded
-					
+			
 			if(mUpdateSlider && mMovieDuration!= 0)
 			{
 				F64 current_time =  media_plugin->getCurrentTime();
@@ -402,29 +405,27 @@ void LLPanelPrimMediaControls::updateShape()
 				mMediaPlaySliderCtrl->setValue(percent);
 				mMediaPlaySliderCtrl->setEnabled(true);
 			}
-				
+			
 			// video vloume
 			if(volume <= 0.0)
 			{
 				mVolumeUpCtrl->setEnabled(TRUE);
 				mVolumeDownCtrl->setEnabled(FALSE);
-				media_impl->setVolume(0.0);
-				mVolumeBtn->setToggleState(true);
+				mMuteBtn->setToggleState(true);
 			}
 			else if (volume >= 1.0)
 			{
 				mVolumeUpCtrl->setEnabled(FALSE);
 				mVolumeDownCtrl->setEnabled(TRUE);
-				media_impl->setVolume(1.0);
-				mVolumeBtn->setToggleState(false);
+				mMuteBtn->setToggleState(false);
 			}
 			else
 			{
+				mMuteBtn->setToggleState(false);
 				mVolumeUpCtrl->setEnabled(TRUE);
 				mVolumeDownCtrl->setEnabled(TRUE);
 			}
-			mVolumeSliderCtrl->setValue(volume);
-				
+			
 			switch(result)
 			{
 				case LLPluginClassMediaOwner::MEDIA_PLAYING:
@@ -453,7 +454,7 @@ void LLPanelPrimMediaControls::updateShape()
 			{
 				mCurrentURL.clear();
 			}
-				
+			
 			mPlayCtrl->setVisible(FALSE);
 			mPauseCtrl->setVisible(FALSE);
 			mMediaStopCtrl->setVisible(FALSE);
@@ -465,7 +466,7 @@ void LLPanelPrimMediaControls::updateShape()
 			mSkipFwdCtrl->setEnabled(FALSE);
 			mSkipBackCtrl->setVisible(FALSE);
 			mSkipBackCtrl->setEnabled(FALSE);
-				
+			
 			mVolumeCtrl->setVisible(FALSE);
 			mVolumeUpCtrl->setVisible(FALSE);
 			mVolumeDownCtrl->setVisible(FALSE);
@@ -491,13 +492,13 @@ void LLPanelPrimMediaControls::updateShape()
 			{
 				mSecureLockIcon->setVisible(has_focus);
 			}
-				
+			
 			if(mCurrentURL!=mPreviousURL)
 			{
 				setCurrentURL();
 				mPreviousURL = mCurrentURL;
 			}
-
+			
 			if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
 			{
 				mReloadCtrl->setEnabled(FALSE);
@@ -513,7 +514,7 @@ void LLPanelPrimMediaControls::updateShape()
 				mStopCtrl->setVisible(FALSE);
 			}
 		}
-
+		
 		
 		if(media_plugin)
 		{
@@ -530,7 +531,7 @@ void LLPanelPrimMediaControls::updateShape()
 				mMediaProgressPanel->setVisible(false);
 			}
 		}
-
+		
 		if(media_impl)
 		{
 			//
@@ -538,28 +539,28 @@ void LLPanelPrimMediaControls::updateShape()
 			//
 			switch (mScrollState) 
 			{
-			case SCROLL_UP:
-				media_impl->scrollWheel(0, -1, MASK_NONE);
-				break;
-			case SCROLL_DOWN:
-				media_impl->scrollWheel(0, 1, MASK_NONE);
-				break;
-			case SCROLL_LEFT:
-				media_impl->scrollWheel(1, 0, MASK_NONE);
-//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
-				break;
-			case SCROLL_RIGHT:
-				media_impl->scrollWheel(-1, 0, MASK_NONE);
-//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
-				break;
-			case SCROLL_NONE:
-			default:
-				break;
+				case SCROLL_UP:
+					media_impl->scrollWheel(0, -1, MASK_NONE);
+					break;
+				case SCROLL_DOWN:
+					media_impl->scrollWheel(0, 1, MASK_NONE);
+					break;
+				case SCROLL_LEFT:
+					media_impl->scrollWheel(1, 0, MASK_NONE);
+					//				media_impl->handleKeyHere(KEY_LEFT, MASK_NONE);
+					break;
+				case SCROLL_RIGHT:
+					media_impl->scrollWheel(-1, 0, MASK_NONE);
+					//				media_impl->handleKeyHere(KEY_RIGHT, MASK_NONE);
+					break;
+				case SCROLL_NONE:
+				default:
+					break;
 			}
 		}
 		
 		setVisible(enabled);
-
+		
 		//
 		// Calculate position and shape of the controls
 		//
@@ -569,31 +570,31 @@ void LLPanelPrimMediaControls::updateShape()
 		std::vector<LLVector3>::iterator vert_it;
 		std::vector<LLVector3>::iterator vert_end;
 		std::vector<LLVector3> vect_face;
-			
+		
 		LLVolume* volume = objectp->getVolume();
-			
+		
 		if (volume)
 		{
 			const LLVolumeFace& vf = volume->getVolumeFace(mTargetObjectFace);
-				
+			
 			const LLVector3* ext = vf.mExtents;
-				
+			
 			LLVector3 center = (ext[0]+ext[1])*0.5f;
 			LLVector3 size = (ext[1]-ext[0])*0.5f;
 			LLVector3 vert[] =
-				{
-					center + size.scaledVec(LLVector3(1,1,1)),
-					center + size.scaledVec(LLVector3(-1,1,1)),
-					center + size.scaledVec(LLVector3(1,-1,1)),
-					center + size.scaledVec(LLVector3(-1,-1,1)),
-					center + size.scaledVec(LLVector3(1,1,-1)),
-					center + size.scaledVec(LLVector3(-1,1,-1)),
-					center + size.scaledVec(LLVector3(1,-1,-1)),
-					center + size.scaledVec(LLVector3(-1,-1,-1)),
-				};
-				
+			{
+				center + size.scaledVec(LLVector3(1,1,1)),
+				center + size.scaledVec(LLVector3(-1,1,1)),
+				center + size.scaledVec(LLVector3(1,-1,1)),
+				center + size.scaledVec(LLVector3(-1,-1,1)),
+				center + size.scaledVec(LLVector3(1,1,-1)),
+				center + size.scaledVec(LLVector3(-1,1,-1)),
+				center + size.scaledVec(LLVector3(1,-1,-1)),
+				center + size.scaledVec(LLVector3(-1,-1,-1)),
+			};
+			
 			LLVOVolume* vo = (LLVOVolume*) objectp;
-				
+			
 			for (U32 i = 0; i < 8; i++)
 			{
 				vect_face.push_back(vo->volumePositionToAgent(vert[i]));
@@ -601,7 +602,7 @@ void LLPanelPrimMediaControls::updateShape()
 		}
 		vert_it = vect_face.begin();
 		vert_end = vect_face.end();
-			
+		
 		min = LLVector3(1,1,1);
 		max = LLVector3(-1,-1,-1);
 		for(; vert_it != vert_end; ++vert_it)
@@ -609,19 +610,19 @@ void LLPanelPrimMediaControls::updateShape()
 			// project silhouette vertices into screen space
 			glh::vec3f screen_vert = glh::vec3f(vert_it->mV); 
 			mat.mult_matrix_vec(screen_vert);
-				
+			
 			// add to screenspace bounding box
 			update_min_max(min, max, LLVector3(screen_vert.v));
 		}
-			
+		
 		LLCoordGL screen_min;
 		screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (min.mV[VX] + 1.f) * 0.5f);
 		screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (min.mV[VY] + 1.f) * 0.5f);
-
+		
 		LLCoordGL screen_max;
 		screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidthScaled() * (max.mV[VX] + 1.f) * 0.5f);
 		screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeightScaled() * (max.mV[VY] + 1.f) * 0.5f);
-
+		
 		// grow panel so that screenspace bounding box fits inside "media_region" element of HUD
 		LLRect media_controls_rect;
 		S32 volume_slider_height = mVolumeSliderCtrl->getRect().getHeight() - /*fudge*/ 2;
@@ -636,19 +637,19 @@ void LLPanelPrimMediaControls::updateShape()
 		
 		// clamp to minimum size, keeping centered
 		media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(),
-			llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight()));
-
+											 llmax(mMinWidth, media_controls_rect.getWidth()), llmax(mMinHeight, media_controls_rect.getHeight()));
+		
 		setShape(media_controls_rect, true);
-
+		
 		// Test mouse position to see if the cursor is stationary
 		LLCoordWindow cursor_pos_window;
 		getWindow()->getCursorPosition(&cursor_pos_window);
-
+		
 		// If last pos is not equal to current pos, the mouse has moved
 		// We need to reset the timer, and make sure the panel is visible
 		if(cursor_pos_window.mX != mLastCursorPos.mX ||
-			cursor_pos_window.mY != mLastCursorPos.mY ||
-			mScrollState != SCROLL_NONE)
+		   cursor_pos_window.mY != mLastCursorPos.mY ||
+		   mScrollState != SCROLL_NONE)
 		{
 			mInactivityTimer.start();
 			mLastCursorPos = cursor_pos_window;
@@ -673,7 +674,7 @@ void LLPanelPrimMediaControls::updateShape()
 		else
 		{
 			// I don't think this is correct anymore.  This is done in draw() after the fade has completed.
-//			setVisible(FALSE);
+			//			setVisible(FALSE);
 		}
 	}
 }
@@ -1193,7 +1194,7 @@ void LLPanelPrimMediaControls::onCommitVolumeUp()
 		}
 		
 		media_impl->setVolume(volume);
-		mVolumeBtn->setToggleState(false);
+		mMuteBtn->setToggleState(false);
 	}
 }		
 
@@ -1213,7 +1214,7 @@ void LLPanelPrimMediaControls::onCommitVolumeDown()
 		}
 
 		media_impl->setVolume(volume);
-		mVolumeBtn->setToggleState(false);
+		mMuteBtn->setToggleState(false);
 	}
 }		
 
@@ -1243,7 +1244,7 @@ void LLPanelPrimMediaControls::onToggleMute()
 		}
 		else 
 		{
-			media_impl->setVolume(0.5);
+			media_impl->setVolume(mVolumeSliderCtrl->getValueF32());
 		}
 	}
 }
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 06163051a5d39066cff3bad1a68d21f7b5871689..17e65b8b0c3698eec57b4079524bcbb288647da5 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -153,7 +153,7 @@ class LLPanelPrimMediaControls : public LLPanel
 	LLUICtrl *mMediaPlaySliderPanel;
 	LLUICtrl *mMediaPlaySliderCtrl;
 	LLUICtrl *mVolumeCtrl;
-	LLButton *mVolumeBtn;
+	LLButton *mMuteBtn;
 	LLUICtrl *mVolumeUpCtrl;
 	LLUICtrl *mVolumeDownCtrl;
 	LLSliderCtrl *mVolumeSliderCtrl;
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 698f6152b4ade605720148bd8f1b82fcc50e24ba..26694ac433cf03b3b8dc7de93b1741d510bdc838 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -76,29 +76,12 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key)
 	  mAspectRatio(0.f),
 	  mPreviewToSave(FALSE)
 {
-	const LLInventoryItem *item = getItem();
+	const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem());
 	if(item)
 	{
 		mShowKeepDiscard = item->getPermissions().getCreator() != gAgent.getID();
 		mImageID = item->getAssetUUID();
-		const LLPermissions& perm = item->getPermissions();
-		U32 mask = PERM_NONE;
-		if(perm.getOwner() == gAgent.getID())
-		{
-			mask = perm.getMaskBase();
-		}
-		else if(gAgent.isInGroup(perm.getGroup()))
-		{
-			mask = perm.getMaskGroup();
-		}
-		else
-		{
-			mask = perm.getMaskEveryone();
-		}
-		if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
-		{
-			mIsCopyable = TRUE;
-		}
+		mIsCopyable = item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED);
 	}
 	else // not an item, assume it's an asset id
 	{
@@ -145,6 +128,9 @@ BOOL LLPreviewTexture::postBuild()
 		childSetVisible("Discard", false);
 	}
 	
+	childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this);
+	childSetVisible("save_tex_btn", canSaveAs());
+	
 	if (!mCopyToInv) 
 	{
 		const LLInventoryItem* item = getItem();
@@ -164,6 +150,13 @@ BOOL LLPreviewTexture::postBuild()
 	return LLPreview::postBuild();
 }
 
+// static
+void LLPreviewTexture::onSaveAsBtn(void* data)
+{
+	LLPreviewTexture* self = (LLPreviewTexture*)data;
+	self->saveAs();
+}
+
 void LLPreviewTexture::draw()
 {
 	if (mUpdateDimensions)
@@ -576,6 +569,7 @@ void LLPreviewTexture::loadAsset()
 	mImage->forceToSaveRawImage(0) ;
 	mAssetStatus = PREVIEW_ASSET_LOADING;
 	updateDimensions();
+	childSetVisible("save_tex_btn", canSaveAs());
 }
 
 LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h
index 9b3c91d831253fff05ffe91cbbc67bd20dfbdeb7..980aecee6d63f8a3b9d946a156377da37b119d55 100644
--- a/indra/newview/llpreviewtexture.h
+++ b/indra/newview/llpreviewtexture.h
@@ -58,7 +58,6 @@ class LLPreviewTexture : public LLPreview
 	virtual void		reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
 	virtual void 		onFocusReceived();
 	
-	static void			saveToFile(void* userdata);
 	static void			onFileLoadedForSave( 
 							BOOL success,
 							LLViewerFetchedTexture *src_vi,
@@ -68,6 +67,8 @@ class LLPreviewTexture : public LLPreview
 							BOOL final,
 							void* userdata );
 	void 				openToSave();
+	
+	static void			onSaveAsBtn(void* data);
 protected:
 	void				init();
 	/* virtual */ BOOL	postBuild();
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index ca7a3b663a7105b5fbe2e15b44c45d8638370b59..5383158cd3f4d14ccd3d1d468c043a3f15c76009 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -235,8 +235,10 @@ void LLSidepanelInventory::updateVerbs()
 	if (!item)
 		return;
 
-	mInfoBtn->setEnabled(TRUE);
-	mShareBtn->setEnabled(TRUE);
+	bool is_single_selection = getSelectedCount() == 1;
+
+	mInfoBtn->setEnabled(is_single_selection);
+	mShareBtn->setEnabled(is_single_selection);
 
 	switch(item->getInventoryType())
 	{
@@ -274,6 +276,14 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()
 	return item;
 }
 
+U32 LLSidepanelInventory::getSelectedCount()
+{
+	LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+	std::set<LLUUID> selection_list;
+	panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList(selection_list);
+	return selection_list.size();
+}
+
 LLInventoryPanel *LLSidepanelInventory::getActivePanel()
 {
 	if (!getVisible())
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
index 231cdac9e1e923ad679b5980f8177f835d17aaa0..ee11fb6b5446e3ae0a09a5411a8971574d3c9489 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -56,6 +56,7 @@ class LLSidepanelInventory : public LLPanel
 protected:
 	// Tracks highlighted (selected) item in inventory panel.
 	LLInventoryItem *getSelectedItem();
+	U32 getSelectedCount();
 	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
 	// "wear", "teleport", etc.
 	void performActionOnSelection(const std::string &action);
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp
index 23931defdd2295e8df10e578c096dccb11547aec..793904faa8c4aad20390e66c400fb464e0038010 100644
--- a/indra/newview/llsidepanelinventorysubpanel.cpp
+++ b/indra/newview/llsidepanelinventorysubpanel.cpp
@@ -57,7 +57,6 @@ LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
   : LLPanel(),
 	mIsDirty(TRUE),
 	mIsEditing(FALSE),
-	mEditBtn(NULL),
 	mCancelBtn(NULL),
 	mSaveBtn(NULL)
 {
@@ -71,9 +70,6 @@ LLSidepanelInventorySubpanel::~LLSidepanelInventorySubpanel()
 // virtual
 BOOL LLSidepanelInventorySubpanel::postBuild()
 {
-	mEditBtn = getChild<LLButton>("edit_btn");
-	mEditBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onEditButtonClicked, this));
-
 	mSaveBtn = getChild<LLButton>("save_btn");
 	mSaveBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onSaveButtonClicked, this));
 
@@ -111,9 +107,9 @@ void LLSidepanelInventorySubpanel::draw()
 {
 	if (mIsDirty)
 	{
-		mIsDirty = FALSE;
 		refresh();
 		updateVerbs();
+		mIsDirty = FALSE;
 	}
 
 	LLPanel::draw();
@@ -127,7 +123,6 @@ void LLSidepanelInventorySubpanel::dirty()
 
 void LLSidepanelInventorySubpanel::updateVerbs()
 {
-	mEditBtn->setVisible(!mIsEditing);
 	mSaveBtn->setVisible(mIsEditing);
 	mCancelBtn->setVisible(mIsEditing);
 }
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h
index a74f4fdee61120100deba01f7c58c92606026b3c..b7bee6809f9e42e7596a4fa0c6ebb9148c55776d 100644
--- a/indra/newview/llsidepanelinventorysubpanel.h
+++ b/indra/newview/llsidepanelinventorysubpanel.h
@@ -70,7 +70,6 @@ class LLSidepanelInventorySubpanel : public LLPanel
 	void 						onEditButtonClicked();
 	void 						onSaveButtonClicked();
 	void 						onCancelButtonClicked();
-	LLButton*					mEditBtn;
 	LLButton*					mSaveBtn;
 	LLButton*					mCancelBtn;
 
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index ad6428e5153e33e05263c72851162c348c79fa2f..449bdefb8f8b0d3f9ff2309e4be254ab96d12df0 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -159,7 +159,6 @@ void LLSidepanelItemInfo::refresh()
 			setIsEditing(FALSE);
 			return;
 		}
-		mEditBtn->setEnabled(FALSE);
 	}
 
 	if (!getIsEditing())
@@ -251,6 +250,18 @@ void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item)
 											   GP_OBJECT_MANIPULATE)
 		&& is_obj_modify && is_complete;
 
+	const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+	bool item_in_trash = item->getUUID() == trash_id || gInventory.isObjectDescendentOf(item->getUUID(), trash_id);
+
+	if (is_modifiable && !item_in_trash)
+	{
+		setIsEditing(TRUE);
+	}
+	else
+	{
+		setIsEditing(FALSE);
+	}
+
 	childSetEnabled("LabelItemNameTitle",TRUE);
 	childSetEnabled("LabelItemName",is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
 	childSetText("LabelItemName",item->getName());
@@ -858,25 +869,6 @@ LLInventoryItem* LLSidepanelItemInfo::findItem() const
 	return item;
 }
 
-// virtual
-void LLSidepanelItemInfo::updateVerbs()
-{
-	LLSidepanelInventorySubpanel::updateVerbs();
-
-	const LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
-	if (item)
-	{
-		const LLPermissions& perm = item->getPermissions();
-		BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
-												   GP_OBJECT_MANIPULATE);
-		
-		const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
-		bool item_in_trash = item->getUUID() == trash_id || gInventory.isObjectDescendentOf(item->getUUID(), trash_id);
-		mEditBtn->setEnabled(is_modifiable && !item_in_trash);
-		
-	}
-}
-
 // virtual
 void LLSidepanelItemInfo::save()
 {
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 4bfbd56ea795096409c9bf13d3fd87dbc88f3c0b..21002327bcd4a444de43ee5532784c9deaec6395 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -62,7 +62,6 @@ class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
 protected:
 	/*virtual*/ void refresh();
 	/*virtual*/ void save();
-	/*virtual*/ void updateVerbs();
 
 	LLInventoryItem* findItem() const;
 	LLViewerObject*  findObject() const;
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index 464546cc77f8e67f425ec024ebbb8a05349ef023..2c40e948de7182e708740dc6dc3af2c14fdc130c 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -1047,8 +1047,8 @@ void LLSidepanelTaskInfo::updateVerbs()
 	mBuyBtn->setVisible(!getIsEditing());
 
 	mOpenBtn->setEnabled(enable_object_open());
-	const LLViewerObject *obj = getFirstSelectedObject();
-	mEditBtn->setEnabled(obj && obj->permModify());
+	//const LLViewerObject *obj = getFirstSelectedObject();
+	//mEditBtn->setEnabled(obj && obj->permModify());
 }
 
 void LLSidepanelTaskInfo::onOpenButtonClicked()
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index d8d1760c385ee741f15fb2dd507e672bdc77e023..93655eb1f1aeaa742d54ba2f5d2ad23832bb192e 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2695,12 +2695,15 @@ std::string LLStartUp::startupStateToString(EStartupState state)
 #define RTNENUM(E) case E: return #E
 	switch(state){
 		RTNENUM( STATE_FIRST );
+		RTNENUM( STATE_BROWSER_INIT );
 		RTNENUM( STATE_LOGIN_SHOW );
 		RTNENUM( STATE_LOGIN_WAIT );
 		RTNENUM( STATE_LOGIN_CLEANUP );
 		RTNENUM( STATE_LOGIN_AUTH_INIT );
 		RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
 		RTNENUM( STATE_WORLD_INIT );
+		RTNENUM( STATE_MULTIMEDIA_INIT );
+		RTNENUM( STATE_FONT_INIT );
 		RTNENUM( STATE_SEED_GRANTED_WAIT );
 		RTNENUM( STATE_SEED_CAP_GRANTED );
 		RTNENUM( STATE_WORLD_WAIT );
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 67007629c06523c5f82fa71f272d73dd4e8572e7..e29c96bec4f8da7d55a460d096d6c844cf519b9e 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -311,10 +311,10 @@ class HTTPGetResponder : public LLCurl::Responder
 		{
 			bool success = false;
 			bool partial = false;
-			if (200 <= status &&  status < 300)
+			if (HTTP_OK <= status &&  status < HTTP_MULTIPLE_CHOICES)
 			{
 				success = true;
-				if (203 == status) // partial information (i.e. last block)
+				if (HTTP_PARTIAL_CONTENT == status) // partial information (i.e. last block)
 				{
 					partial = true;
 				}
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index 46618d40268966533287006d1ca198c41af047ec..f8c82f8b22b64881feded6201ca025050166e8de 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -47,11 +47,14 @@
 #include "llurlsimstring.h"
 #include "llweb.h"
 #include "llworldmapmessage.h"
+#include "llurldispatcherlistener.h"
 
 // library includes
 #include "llnotificationsutil.h"
 #include "llsd.h"
 
+static LLURLDispatcherListener sURLDispatcherListener;
+
 class LLURLDispatcherImpl
 {
 public:
diff --git a/indra/newview/llurldispatcherlistener.cpp b/indra/newview/llurldispatcherlistener.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fea6a769c518a4600c3755de031e12b34e7899d8
--- /dev/null
+++ b/indra/newview/llurldispatcherlistener.cpp
@@ -0,0 +1,58 @@
+/**
+ * @file   llurldispatcherlistener.cpp
+ * @author Nat Goodspeed
+ * @date   2009-12-10
+ * @brief  Implementation for llurldispatcherlistener.
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "llviewerprecompiledheaders.h"
+// associated header
+#include "llurldispatcherlistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llurldispatcher.h"
+
+LLURLDispatcherListener::LLURLDispatcherListener(/* LLURLDispatcher* instance */):
+    LLEventAPI("LLURLDispatcher", "Internal URL handling") /* ,
+    mDispatcher(instance) */
+{
+    add("dispatch",
+        "At startup time or on clicks in internal web browsers,\n"
+        "teleport, open map, or run requested command.\n"
+        "[\"url\"] string url to dispatch\n"
+        "[\"trusted\"] boolean indicating trusted browser [default true]",
+        &LLURLDispatcherListener::dispatch);
+    add("dispatchRightClick", "Dispatch [\"url\"] as if from a right-click on a hot link.",
+        &LLURLDispatcherListener::dispatchRightClick);
+    add("dispatchFromTextEditor", "Dispatch [\"url\"] as if from an edit field.",
+        &LLURLDispatcherListener::dispatchFromTextEditor);
+}
+
+void LLURLDispatcherListener::dispatch(const LLSD& params) const
+{
+    // For most purposes, we expect callers to want to be trusted.
+    bool trusted_browser = true;
+    if (params.has("trusted"))
+    {
+        // But for testing, allow a caller to specify untrusted.
+        trusted_browser = params["trusted"].asBoolean();
+    }
+    LLURLDispatcher::dispatch(params["url"], NULL, trusted_browser);
+}
+
+void LLURLDispatcherListener::dispatchRightClick(const LLSD& params) const
+{
+    LLURLDispatcher::dispatchRightClick(params["url"]);
+}
+
+void LLURLDispatcherListener::dispatchFromTextEditor(const LLSD& params) const
+{
+    LLURLDispatcher::dispatchFromTextEditor(params["url"]);
+}
diff --git a/indra/newview/llurldispatcherlistener.h b/indra/newview/llurldispatcherlistener.h
new file mode 100644
index 0000000000000000000000000000000000000000..894afcbb5124a14b6606625423086ddc9b587d9d
--- /dev/null
+++ b/indra/newview/llurldispatcherlistener.h
@@ -0,0 +1,32 @@
+/**
+ * @file   llurldispatcherlistener.h
+ * @author Nat Goodspeed
+ * @date   2009-12-10
+ * @brief  LLEventAPI for LLURLDispatcher
+ * 
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLURLDISPATCHERLISTENER_H)
+#define LL_LLURLDISPATCHERLISTENER_H
+
+#include "lleventapi.h"
+class LLURLDispatcher;
+class LLSD;
+
+class LLURLDispatcherListener: public LLEventAPI
+{
+public:
+    LLURLDispatcherListener(/* LLURLDispatcher* instance */); // all static members
+
+private:
+    void dispatch(const LLSD& params) const;
+    void dispatchRightClick(const LLSD& params) const;
+    void dispatchFromTextEditor(const LLSD& params) const;
+
+    //LLURLDispatcher* mDispatcher;
+};
+
+#endif /* ! defined(LL_LLURLDISPATCHERLISTENER_H) */
diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp
index 297c0cc111ad97822dc7f72c3425babf8f99f753..b8f91697e5262a83b2d62774cf10f0f395c090ef 100644
--- a/indra/newview/llviewerhelp.cpp
+++ b/indra/newview/llviewerhelp.cpp
@@ -49,24 +49,38 @@
 
 void LLViewerHelp::showTopic(const std::string &topic)
 {
-	showHelp();
-	
 	// allow overriding the help server with a local help file
 	if( gSavedSettings.getBOOL("HelpUseLocal") )
 	{
+		showHelp();
 		LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
 		helpbrowser->navigateToLocalPage( "help-offline" , "index.html" );
 		return;
 	}
 
-	// use a special login topic before the user logs in
+	// if the help topic is empty, use the default topic
 	std::string help_topic = topic;
-	if (! LLLoginInstance::getInstance()->authSuccess())
+	if (help_topic.empty())
 	{
-		help_topic = preLoginTopic();
+		help_topic = defaultTopic();
+	}
+
+	// f1 help topic means: if user not logged in yet, show the
+	// pre-login topic, otherwise show help for the focused item
+	if (help_topic == f1HelpTopic())
+	{
+		if (! LLLoginInstance::getInstance()->authSuccess())
+		{
+			help_topic = preLoginTopic();
+		}
+		else
+		{
+			help_topic = getTopicFromFocus();
+		}
 	}
 
 	// work out the URL for this topic and display it 
+	showHelp();
 	const LLOSInfo& osinfo = LLAppViewer::instance()->getOSInfo();
 	std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic, gSavedSettings, osinfo );
 	setRawURL( helpURL );
@@ -84,6 +98,12 @@ std::string LLViewerHelp::preLoginTopic()
 	return "pre_login_help";
 }
 
+std::string LLViewerHelp::f1HelpTopic()
+{
+	// *hack: to be done properly
+	return "f1_help";
+}
+
 //////////////////////////////
 // our own interfaces
 
diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h
index dcb5ae32c98956b7349b37703e9adc723b2f9ffc..07971a593e919f645a72789358ebae576edef710 100644
--- a/indra/newview/llviewerhelp.h
+++ b/indra/newview/llviewerhelp.h
@@ -51,14 +51,17 @@ class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp>
 	/// display the specified help topic in the help viewer
 	/*virtual*/ void showTopic(const std::string &topic);
 
-	/// return default (fallback) topic name suitable for showTopic()
-	/*virtual*/ std::string defaultTopic();
-
 	// return topic derived from viewer UI focus, else default topic
 	std::string getTopicFromFocus();
 
+	/// return default (fallback) topic name suitable for showTopic()
+	/*virtual*/ std::string defaultTopic();
+
 	// return topic to use before the user logs in
-	std::string preLoginTopic();
+	/*virtual*/ std::string preLoginTopic();
+
+	// return topic to use for the top-level help, invoked by F1
+	/*virtual*/ std::string f1HelpTopic();
 
  private:
 	static void showHelp(); // make sure help UI is visible & raised
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 5417929dbb591c4f336005bf8b7fbfe0008a3db3..8dcd1b8f93a772bb221f8b734bb70bc247be9d0a 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1379,6 +1379,25 @@ LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const
 	return NULL;
 }
 
+bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const
+{
+	const LLPermissions& perm = getPermissions();
+	PermissionMask curr_mask = PERM_NONE;
+	if(perm.getOwner() == gAgent.getID())
+	{
+		curr_mask = perm.getMaskBase();
+	}
+	else if(gAgent.isInGroup(perm.getGroup()))
+	{
+		curr_mask = perm.getMaskGroup();
+	}
+	else
+	{
+		curr_mask = perm.getMaskEveryone();
+	}
+	return ((curr_mask & mask) == mask);
+}
+
 //----------
 
 void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name)
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 0156e7dab16c00f1d21e0950462263c7c8f85b2e..412a2c66e65dcaf881353bb59a6ebe905c541338 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -158,6 +158,9 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	bool getIsBrokenLink() const; // true if the baseitem this points to doesn't exist in memory.
 	LLViewerInventoryItem *getLinkedItem() const;
 	LLViewerInventoryCategory *getLinkedCategory() const;
+	
+	// Checks the items permissions (for owner, group, or everyone) and returns true if all mask bits are set.
+	bool checkPermissionsSet(PermissionMask mask) const;
 
 	// callback
 	void onCallingCardNameLookup(const LLUUID& id, const std::string& first_name, const std::string& last_name);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index ef8f63484ee73fc2b95647ef22b5213411efb5c4..57e4ed0c1ec67a0128569b4c4561918f082c4ae2 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -172,6 +172,11 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 			completeAny(status, "text/html");
 		}
 		else
+		if(status == 403)
+		{
+			completeAny(status, "text/html");
+		}
+		else
 		if(status == 404)
 		{
 			// 404 is content not found - sites often have bespoke 404 pages so
@@ -240,6 +245,7 @@ LOG_CLASS(LLMimeDiscoveryResponder);
 		bool mInitialized;
 };
 static LLViewerMedia::impl_list sViewerMediaImplList;
+static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
 static LLTimer sMediaCreateTimer;
 static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
 static F32 sGlobalVolume = 1.0f;
@@ -297,7 +303,7 @@ viewer_media_t LLViewerMedia::newMediaImpl(
 	else
 	{
 		media_impl->unload();
-		media_impl->mTextureId = texture_id;
+		media_impl->setTextureID(texture_id);
 		media_impl->mMediaWidth = media_width;
 		media_impl->mMediaHeight = media_height;
 		media_impl->mMediaAutoScale = media_auto_scale;
@@ -412,18 +418,16 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
 // static
 LLViewerMediaImpl* LLViewerMedia::getMediaImplFromTextureID(const LLUUID& texture_id)
 {
-	impl_list::iterator iter = sViewerMediaImplList.begin();
-	impl_list::iterator end = sViewerMediaImplList.end();
-
-	for(; iter != end; iter++)
+	LLViewerMediaImpl* result = NULL;
+	
+	// Look up the texture ID in the texture id->impl map.
+	impl_id_map::iterator iter = sViewerMediaTextureIDMap.find(texture_id);
+	if(iter != sViewerMediaTextureIDMap.end())
 	{
-		LLViewerMediaImpl* media_impl = *iter;
-		if(media_impl->getMediaTextureID() == texture_id)
-		{
-			return media_impl;
-		}
+		result = iter->second;
 	}
-	return NULL;
+
+	return result;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -626,7 +630,22 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView
 
 static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
 {
-	return (i1->getProximityDistance() < i2->getProximityDistance());
+	if(i1->getProximityDistance() < i2->getProximityDistance())
+	{
+		return true;
+	}
+	else if(i1->getProximityDistance() > i2->getProximityDistance())
+	{
+		return false;
+	}
+	else
+	{
+		// Both objects have the same distance.  This most likely means they're two faces of the same object.
+		// They may also be faces on different objects with exactly the same distance (like HUD objects).
+		// We don't actually care what the sort order is for this case, as long as it's stable and doesn't change when you enable/disable media.
+		// Comparing the impl pointers gives a completely arbitrary ordering, but it will be stable.
+		return (i1 < i2);
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -827,7 +846,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 :	
 	mMediaSource( NULL ),
 	mMovieImageHasMips(false),
-	mTextureId(texture_id),
 	mMediaWidth(media_width),
 	mMediaHeight(media_height),
 	mMediaAutoScale(media_auto_scale),
@@ -857,6 +875,7 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mProximityDistance(0.0f),
 	mMimeTypeProbe(NULL),
 	mMediaAutoPlay(false),
+	mInNearbyMediaList(false),
 	mIsUpdated(false)
 { 
 
@@ -868,6 +887,8 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	}
 	
 	add_media_impl(this);
+
+	setTextureID(texture_id);
 	
 	// connect this media_impl to the media texture, creating it if it doesn't exist.0
 	// This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded.
@@ -891,6 +912,7 @@ LLViewerMediaImpl::~LLViewerMediaImpl()
 	
 	LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ;
 
+	setTextureID();
 	remove_media_impl(this);
 }
 
@@ -2421,6 +2443,26 @@ LLVOVolume *LLViewerMediaImpl::getSomeObject()
 	return result;
 }
 
+void LLViewerMediaImpl::setTextureID(LLUUID id)
+{
+	if(id != mTextureId)
+	{
+		if(mTextureId.notNull())
+		{
+			// Remove this item's entry from the map
+			sViewerMediaTextureIDMap.erase(mTextureId);
+		}
+		
+		if(id.notNull())
+		{
+			sViewerMediaTextureIDMap.insert(LLViewerMedia::impl_id_map::value_type(id, this));
+		}
+		
+		mTextureId = id;
+	}
+}
+
+
 //////////////////////////////////////////////////////////////////////////////////////////
 //static
 void LLViewerMedia::toggleMusicPlay(void*)
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 713eb2710b12179795143541c1a24cde1bc32d16..349a66867a1d185c1a17651107cad4c6b85d9422 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -79,6 +79,8 @@ class LLViewerMedia
 	
 		typedef std::vector<LLViewerMediaImpl*> impl_list;
 
+		typedef std::map<LLUUID, LLViewerMediaImpl*> impl_id_map;
+
 		// Special case early init for just web browser component
 		// so we can show login screen.  See .cpp file for details. JC
 
@@ -287,6 +289,8 @@ class LLViewerMediaImpl
 	LLPluginClassMedia::EPriority getPriority() { return mPriority; };
 
 	void setLowPrioritySizeLimit(int size);
+
+	void setTextureID(LLUUID id = LLUUID::null);
 	
 	typedef enum 
 	{
@@ -348,6 +352,7 @@ class LLViewerMediaImpl
 	LLMimeDiscoveryResponder *mMimeTypeProbe;
 	bool mMediaAutoPlay;
 	std::string mMediaEntryURL;
+	bool mInNearbyMediaList;	// used by LLFloaterNearbyMedia::refreshList() for performance reasons
 	
 private:
 	BOOL mIsUpdated ;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 9def699708e6d5123daad4957220826c7849a6ba..36d9e7935ff0f650367ed7fa87af5affe3bb044c 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -5575,17 +5575,8 @@ class LLShowHelp : public view_listener_t
 	bool handleEvent(const LLSD& userdata)
 	{
 		std::string help_topic = userdata.asString();
-
 		LLViewerHelp* vhelp = LLViewerHelp::getInstance();
-		if (help_topic.empty())
-		{
-			vhelp->showTopic(vhelp->getTopicFromFocus());
-		}
-		else
-		{
-			vhelp->showTopic(help_topic);
-		}
-
+		vhelp->showTopic(help_topic);
 		return true;
 	}
 };
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 4b0dc8f668b4cbeeba39c186b10d444d562f11b7..a1c3806b27abcf533e7b2ee436d3efb3b9d3186c 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -71,15 +71,6 @@
 // system libraries
 #include <boost/tokenizer.hpp>
 
-class LLFileEnableSaveAs : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gFloaterView->getFrontmost() && gFloaterView->getFrontmost()->canSaveAs();
-		return new_value;
-	}
-};
-
 class LLFileEnableUpload : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -386,19 +377,6 @@ class LLFileCloseAllWindows : public view_listener_t
 	}
 };
 
-class LLFileSaveTexture : public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		LLFloater* top = gFloaterView->getFrontmost();
-		if (top)
-		{
-			top->saveAs();
-		}
-		return true;
-	}
-};
-
 class LLFileTakeSnapshotToDisk : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -1050,10 +1028,10 @@ void init_menu_file()
 	view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
 	view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow");
 	view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows");
-	view_listener_t::addCommit(new LLFileSaveTexture(), "File.SaveTexture");
 	view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk");
 	view_listener_t::addCommit(new LLFileQuit(), "File.Quit");
 
 	view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload");
-	view_listener_t::addEnable(new LLFileEnableSaveAs(), "File.EnableSaveAs");
+	
+	// "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled.
 }
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 0d29efaedf5acd27bacb941c43b26723380f3d43..a5a40e9c2cdba6709b20f718749b86deebea6e0e 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -2879,7 +2879,8 @@ BOOL LLViewerMediaTexture::findFaces()
 		}
 
 		S32 face_id = -1 ;
-		while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1)
+		S32 num_faces = obj->mDrawable->getNumFaces() ;
+		while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces)
 		{
 			LLFace* facep = obj->mDrawable->getFace(face_id) ;
 			if(facep)
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 93b0ad4a5b06b18f23f5b55f28495fc502d628e3..226d85ec9904526a7cc95ddab77da0ba3038ffc9 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -5994,7 +5994,7 @@ void LLVOAvatar::updateMeshTextures()
 			else
 			{
 				mBakedTextureDatas[i].mIsLoaded = FALSE;
-				if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+				if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
 				{
 					baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));	
 				}
@@ -6464,7 +6464,7 @@ void LLVOAvatar::onFirstTEMessageReceived()
 				LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
 				mBakedTextureDatas[i].mLastTextureIndex = image->getID();
 				// If we have more than one texture for the other baked layers, we'll want to call this for them too.
-				if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+				if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
 				{
 					image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
 				}
@@ -7651,6 +7651,9 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di
 
 void LLVOAvatar::idleUpdateRenderCost()
 {
+	static const U32 ARC_BODY_PART_COST = 20;
+	static const U32 ARC_LIMIT = 2048;
+
 	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
 	{
 		return;
@@ -7667,7 +7670,7 @@ void LLVOAvatar::idleUpdateRenderCost()
 		{
 			if (isTextureVisible(tex_index))
 			{
-				cost +=20;
+				cost +=ARC_BODY_PART_COST;
 			}
 		}
 	}
@@ -7687,7 +7690,6 @@ void LLVOAvatar::idleUpdateRenderCost()
 				const LLDrawable* drawable = attached_object->mDrawable;
 				if (drawable)
 				{
-					cost += 10;
 					const LLVOVolume* volume = drawable->getVOVolume();
 					if (volume)
 					{
@@ -7698,11 +7700,11 @@ void LLVOAvatar::idleUpdateRenderCost()
 		}
 	}
 
-	cost += textures.size() * 5;
+	cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
 
 	setDebugText(llformat("%d", cost));
-	F32 green = 1.f-llclamp(((F32) cost-1024.f)/1024.f, 0.f, 1.f);
-	F32 red = llmin((F32) cost/1024.f, 1.f);
+	F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
+	F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
 	mText->setColor(LLColor4(red,green,0,1));
 }
 
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 63acba50e75e115223be391076ad181c83ba6b26..aa69b46857988168d9ef20ddfe53d247d2508e81 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -128,16 +128,8 @@ static int scale_mic_volume(float volume)
 static int scale_speaker_volume(float volume)
 {
 	// incoming volume has the range [0.0 ... 1.0], with 0.5 as the default.
-	// Map it as follows: 0.0 -> 0, 0.5 -> 62, 1.0 -> 75
-	
-	volume -= 0.5f;		// offset volume to the range [-0.5 ... 0.5], with 0 at the default.
-	int scaled_volume = 62;	// offset scaled_volume by its default level
-	if(volume < 0.0f)
-		scaled_volume += ((int)(volume * 124.0f));	// (62 - 0) * 2
-	else
-		scaled_volume += ((int)(volume * 26.0f));	// (75 - 62) * 2
-	
-	return scaled_volume;
+	// Map it as follows: 0.0 -> 0, 0.5 -> 50, 1.0 -> 100
+	return (int)(volume * 100.0f);
 }
 
 class LLViewerVoiceAccountProvisionResponder :
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index edfe0173f8dfc1ea9b0f62e70af2cd757c8a34bc..92e79a004d8973d69455fa557b0239ed27a142d9 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -125,7 +125,7 @@ class LLVoiceClient: public LLSingleton<LLVoiceClient>
 		void tuningCaptureStartSendMessage(int duration);
 		void tuningCaptureStopSendMessage();
 		
-		void tuningSetMicVolume(float volume);
+		void tuningSetMicVolume(float volume=0.5f);
 		void tuningSetSpeakerVolume(float volume);
 		float tuningGetEnergy(void);
 				
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index cf61994feac796b39e308ceaf55cf734368cb7e9..08e12f4ad910867941a03071187bc7eb23de7daf 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -92,7 +92,7 @@ static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
 class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
 {
 public:
-	LLMediaDataClientObjectImpl(LLVOVolume *obj) : mObject(obj) {}
+	LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) {}
 	LLMediaDataClientObjectImpl() { mObject = NULL; }
 	
 	virtual U8 getMediaDataCount() const 
@@ -128,14 +128,19 @@ class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
 	virtual bool hasMedia() const
 		{ return mObject->hasMedia(); }
 	
-	virtual void updateObjectMediaData(LLSD const &data) 
-		{ mObject->updateObjectMediaData(data); }
-
-	virtual F64 getDistanceFromAvatar() const
-		{ return mObject->getRenderPosition().length(); }
+	virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) 
+		{ mObject->updateObjectMediaData(data, version_string); }
 	
-	virtual F64 getTotalMediaInterest() const 
-		{ return mObject->getTotalMediaInterest(); }
+	virtual F64 getMediaInterest() const 
+		{ 
+			F64 tmp = mObject->getTotalMediaInterest();  
+			return (tmp < 0.0) ? mObject->getPixelArea() : tmp; 
+		}
+	virtual bool isInterestingEnough() const
+		{
+			// TODO: use performance manager to control this
+			return true;
+		}
 
 	virtual std::string getCapabilityUrl(const std::string &name) const
 		{ return mObject->getRegion()->getCapability(name); }
@@ -143,8 +148,15 @@ class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
 	virtual bool isDead() const
 		{ return mObject->isDead(); }
 	
+	virtual U32 getMediaVersion() const
+		{ return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); }
+	
+	virtual bool isNew() const
+		{ return mNew; }
+
 private:
 	LLPointer<LLVOVolume> mObject;
+	bool mNew;
 };
 
 
@@ -165,6 +177,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
 	mSpotLightPriority = 0.f;
 
 	mMediaImplList.resize(getNumTEs());
+	mLastFetchedMediaVersion = -1;
 }
 
 LLVOVolume::~LLVOVolume()
@@ -190,7 +203,9 @@ void LLVOVolume::markDead()
 {
 	if (!mDead)
 	{
-		// TODO: tell LLMediaDataClient to remove this object from its queue
+		LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
+		sObjectMediaClient->removeFromQueue(obj);
+		sObjectMediaNavigateClient->removeFromQueue(obj);
 		
 		// Detach all media impls from this object
 		for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
@@ -210,8 +225,12 @@ void LLVOVolume::initClass()
 	const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
 	const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
 	const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
-    sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries);
-    sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries);
+	const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize");
+	const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize");
+    sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, 
+													 max_sorted_queue_size, max_round_robin_queue_size);
+    sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, 
+																 max_retries, max_sorted_queue_size, max_round_robin_queue_size);
 }
 
 // static
@@ -406,7 +425,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
 			// If the media changed at all, request new media data
 			LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
                 ((mMedia) ?  mMedia->mMediaURL : std::string("")) << LL_ENDL;
-			requestMediaDataUpdate();
+			requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED);
 		}
         else {
             LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
@@ -1698,16 +1717,16 @@ LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id)
 	return result;
 }
 
-void LLVOVolume::requestMediaDataUpdate()
+void LLVOVolume::requestMediaDataUpdate(bool isNew)
 {
-    sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this));
+    sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew));
 }
 
 bool LLVOVolume::isMediaDataBeingFetched() const
 {
 	// I know what I'm doing by const_casting this away: this is just 
 	// a wrapper class that is only going to do a lookup.
-	return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this)));
+	return sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false));
 }
 
 void LLVOVolume::cleanUpMediaImpls()
@@ -1725,18 +1744,25 @@ void LLVOVolume::cleanUpMediaImpls()
 	}
 }
 
-void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array)
+void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version)
 {
 	// media_data_array is an array of media entry maps
+	// media_version is the version string in the response.
+	U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version);
 
-	//llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
-
-	LLSD::array_const_iterator iter = media_data_array.beginArray();
-	LLSD::array_const_iterator end = media_data_array.endArray();
-	U8 texture_index = 0;
-	for (; iter != end; ++iter, ++texture_index)
+	// Only update it if it is newer!
+	if ( (S32)fetched_version > mLastFetchedMediaVersion)
 	{
-		syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
+		mLastFetchedMediaVersion = fetched_version;
+		//llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
+		
+		LLSD::array_const_iterator iter = media_data_array.beginArray();
+		LLSD::array_const_iterator end = media_data_array.endArray();
+		U8 texture_index = 0;
+		for (; iter != end; ++iter, ++texture_index)
+		{
+			syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
+		}
 	}
 }
 
@@ -1904,7 +1930,7 @@ void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plu
 		
 		llinfos << "broadcasting navigate with URI " << new_location << llendl;
 
-		sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location);
+		sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location);
 	}
 }
 
@@ -1968,7 +1994,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
 
 void LLVOVolume::sendMediaDataUpdate()
 {
-    sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this));
+    sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false));
 }
 
 void LLVOVolume::removeMediaImpl(S32 texture_index)
@@ -2063,7 +2089,7 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
 
 F64 LLVOVolume::getTotalMediaInterest() const
 {
-	F64 interest = (F64)0.0;
+	F64 interest = (F64)-1.0;  // means not interested;
     int i = 0;
 	const int end = getNumTEs();
 	for ( ; i < end; ++i)
@@ -2071,6 +2097,7 @@ F64 LLVOVolume::getTotalMediaInterest() const
 		const viewer_media_t &impl = getMediaImpl(i);
 		if (!impl.isNull())
 		{
+			if (interest == (F64)-1.0) interest = (F64)0.0;
 			interest += impl->getInterest();
 		}
 	}
@@ -2587,7 +2614,22 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const
 // children, and cost should only be increased for unique textures  -Nyx
 U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
 {
-	U32 shame = 0;
+	// base cost of each prim should be 10 points
+	static const U32 ARC_PRIM_COST = 10;
+	// per-prim costs
+	static const U32 ARC_INVISI_COST = 1;
+	static const U32 ARC_SHINY_COST = 1;
+	static const U32 ARC_GLOW_COST = 1;
+	static const U32 ARC_FLEXI_COST = 8;
+	static const U32 ARC_PARTICLE_COST = 16;
+	static const U32 ARC_BUMP_COST = 4;
+
+	// per-face costs
+	static const U32 ARC_PLANAR_COST = 1;
+	static const U32 ARC_ANIM_TEX_COST = 4;
+	static const U32 ARC_ALPHA_COST = 4;
+
+	U32 shame = ARC_PRIM_COST;
 
 	U32 invisi = 0;
 	U32 shiny = 0;
@@ -2663,7 +2705,17 @@ U32 LLVOVolume::getRenderCost(std::set<LLUUID> &textures) const
 		}
 	}
 
-	shame += invisi + shiny + glow + alpha*4 + flexi*8 + animtex*4 + particles*16+bump*4+scale+planar;
+
+	shame += invisi * ARC_INVISI_COST;
+	shame += shiny * ARC_SHINY_COST;
+	shame += glow * ARC_GLOW_COST;
+	shame += alpha * ARC_ALPHA_COST;
+	shame += flexi * ARC_FLEXI_COST;
+	shame += animtex * ARC_ANIM_TEX_COST;
+	shame += particles * ARC_PARTICLE_COST;
+	shame += bump * ARC_BUMP_COST;
+	shame += planar * ARC_PLANAR_COST;
+	shame += scale;
 
 	LLViewerObject::const_child_list_t& child_list = getChildren();
 	for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 06e214b41e307cb9747bfaa55c0603b77cbdd6a5..743340494220eaccd905fc9b4b1e8f952182e729 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -238,7 +238,7 @@ class LLVOVolume : public LLViewerObject
     
     // Update this object's media data with the given media data array
     // (typically this is only called upon a response from a server request)
-	void updateObjectMediaData(const LLSD &media_data_array);
+	void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version);
     
     // Bounce back media at the given index to its current URL (or home URL, if current URL is empty)
 	void mediaNavigateBounceBack(U8 texture_index);
@@ -270,13 +270,16 @@ class LLVOVolume : public LLViewerObject
 	// Returns 'true' iff the media data for this object is in flight
 	bool isMediaDataBeingFetched() const;
 	
+	// Returns the "last fetched" media version, or -1 if not fetched yet
+	S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; }
+	
 protected:
 	S32	computeLODDetail(F32	distance, F32 radius);
 	BOOL calcLOD();
 	LLFace* addFace(S32 face_index);
 	void updateTEData();
 
-	void requestMediaDataUpdate();
+	void requestMediaDataUpdate(bool isNew);
 	void cleanUpMediaImpls();
 	void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
 	void removeMediaImpl(S32 texture_index) ;
@@ -300,6 +303,7 @@ class LLVOVolume : public LLViewerObject
 	LLPointer<LLViewerFetchedTexture> mSculptTexture;
 	LLPointer<LLViewerFetchedTexture> mLightTexture;
 	media_list_t mMediaImplList;
+	S32			mLastFetchedMediaVersion; // as fetched from the server, starts as -1
 	
 	// statics
 public:
@@ -310,6 +314,8 @@ class LLVOVolume : public LLViewerObject
 	static LLPointer<LLObjectMediaDataClient> sObjectMediaClient;
 	static LLPointer<LLObjectMediaNavigateClient> sObjectMediaNavigateClient;
 
+	static const U32 ARC_TEXTURE_COST = 5;
+
 protected:
 	static S32 sNumLODChanges;
 	
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index c8cc6a3d8ebe69540af02bf3bdcc929b7e614dad..697fefee3a5176a5a8686efe30d7a3b49d5873ed 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -91,7 +91,7 @@ LLWaterParamManager::~LLWaterParamManager()
 void LLWaterParamManager::loadAllPresets(const std::string& file_name)
 {
 	std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", ""));
-	LL_INFOS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
+	LL_DEBUGS2("AppInit", "Shaders") << "Loading Default water settings from " << path_name << LL_ENDL;
 			
 	bool found = true;			
 	while(found) 
@@ -117,7 +117,7 @@ void LLWaterParamManager::loadAllPresets(const std::string& file_name)
 	// And repeat for user presets, note the user presets will modify any system presets already loaded
 
 	std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
-	LL_INFOS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
+	LL_DEBUGS2("AppInit", "Shaders") << "Loading User water settings from " << path_name2 << LL_ENDL;
 			
 	found = true;			
 	while(found) 
@@ -152,7 +152,7 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate)
 	escaped_filename += ".xml";
 
 	std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", escaped_filename));
-	llinfos << "Loading water settings from " << pathName << llendl;
+	LL_DEBUGS2("AppInit", "Shaders") << "Loading water settings from " << pathName << LL_ENDL;
 	
 	llifstream presetsXML;
 	presetsXML.open(pathName.c_str());
@@ -161,7 +161,7 @@ void LLWaterParamManager::loadPreset(const std::string & name,bool propagate)
 	if(!presetsXML)
 	{
 		pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", escaped_filename);
-		llinfos << "Loading User water setting from " << pathName << llendl;
+		LL_DEBUGS2("AppInit", "Shaders") << "Loading User water setting from " << pathName << LL_ENDL;
 		presetsXML.clear();
         presetsXML.open(pathName.c_str());
 	}
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index c6fd35c1422522bec6160efcd86c63fbea01b1c3..c3a70705cfcb2ec6e2db8e7b44114e8513a8ea3d 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -109,7 +109,7 @@ LLWLParamManager::~LLWLParamManager()
 void LLWLParamManager::loadPresets(const std::string& file_name)
 {
 	std::string path_name(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", ""));
-	LL_INFOS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
+	LL_DEBUGS2("AppInit", "Shaders") << "Loading Default WindLight settings from " << path_name << LL_ENDL;
 			
 	bool found = true;			
 	while(found) 
@@ -135,7 +135,7 @@ void LLWLParamManager::loadPresets(const std::string& file_name)
 	// And repeat for user presets, note the user presets will modify any system presets already loaded
 
 	std::string path_name2(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
-	LL_INFOS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
+	LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight settings from " << path_name2 << LL_ENDL;
 			
 	found = true;			
 	while(found) 
@@ -196,7 +196,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate)
 	escaped_filename += ".xml";
 
 	std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", escaped_filename));
-	//llinfos << "Loading WindLight sky setting from " << pathName << llendl;
+	LL_DEBUGS2("AppInit", "Shaders") << "Loading WindLight sky setting from " << pathName << LL_ENDL;
 
 	llifstream presetsXML;
 	presetsXML.open(pathName.c_str());
@@ -205,7 +205,7 @@ void LLWLParamManager::loadPreset(const std::string & name,bool propagate)
 	if(!presetsXML)
 	{
 		pathName=gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", escaped_filename);
-		llinfos << "Loading User WindLight sky setting from " << pathName << llendl;
+		LL_DEBUGS2("AppInit", "Shaders") << "Loading User WindLight sky setting from " << pathName << LL_ENDL;
 		presetsXML.clear();
         presetsXML.open(pathName.c_str());
 	}
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index d1fd42bdd9077489cc3c44e4db68a47aa4217175..10b72144e709caa8423fd289c60d22237e500616 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -4,7 +4,6 @@
  height="420"
  layout="topleft"
  name="floaterland"
- help_topic="floaterland"
  save_rect="true"
  title="ABOUT LAND"
  width="490">
@@ -1857,6 +1856,10 @@ Select the thumbnail to choose a different texture.
          top="0"
          help_topic="land_access_tab"
          name="land_access_panel">
+			<panel.string
+			 name="access_estate_defined">
+				(Defined by the Estate)
+			</panel.string>
             <panel.string
              name="estate_override">
                 One or more of these options is set at the estate level
@@ -1877,7 +1880,7 @@ Select the thumbnail to choose a different texture.
             <check_box
              follows="top|left"
              height="16"
-             label="Allow Public Access"
+             label="Allow Public Access [MATURITY]"
              layout="topleft"
              left_delta="0"
              name="public_access"
@@ -1893,12 +1896,12 @@ Select the thumbnail to choose a different texture.
              name="Only Allow"
              top="49"
              width="278">
-                Block Access By:
+                Restrict Access to Residents verified by:
             </text>
             <check_box
              follows="top|left"
              height="16"
-             label="Residents who have not given payment info to Linden Lab"
+             label="Payment Information on File [ESTATE_PAYMENT_LIMIT]"
              layout="topleft"
              left_delta="0"
              name="limit_payment"
@@ -1908,7 +1911,7 @@ Select the thumbnail to choose a different texture.
             <check_box
              follows="top|left"
              height="16"
-             label="Residents who are not age verified adults"
+             label="Age Verification [ESTATE_AGE_LIMIT]"
              layout="topleft"
              left_delta="0"
              name="limit_age_verified"
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 75711cdf89e88eb9bfe0de60b5f8fb4cf4ddc0af..26b003cafe5d28faaba604d847c7696653e95c8f 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -222,7 +222,7 @@
      width="300"
      height="30"
      name="currency_links">
-      [http://www.secondlife.com/ payment method] | [http://www.secondlife.com/ currency] | [http://www.secondlife.com exchange rate]
+      [http://www.secondlife.com/ payment method] | [http://www.secondlife.com/ currency] | [http://www.secondlife.com/my/account/exchange_rates.php exchange rate]
     </text>
     <text
      type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 15655a920e3c3b77a5c3e6e0637cb74690711dce..2f26e5d0c146ad4bdb3879a18bb47c58d75fa14c 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -7,7 +7,6 @@
  height="460"
  layout="topleft"
  name="Preferences"
- help_topic="preferences"
  single_instance="true"
  title="PREFERENCES"
  width="620">
diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
index 52a19ac6b3ddb90ccd9df81ba24fa6441c8d8f6d..602a18ea56c421f9755b1e3b4ee972dba2e152df 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
@@ -61,7 +61,16 @@
      name="Discard"
      top_delta="0"
      width="100" />
-     <text
+    <button
+     follows="left|bottom"
+     height="22"
+     label="Save As"
+     layout="topleft"
+     left_pad="5"
+     name="save_tex_btn"
+     top_delta="0"
+     width="100" />
+    <text
      type="string"
      length="1"
      follows="left|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index e3851de8e79548d955326500265905c6bf74f22c..5e68850e30e6d0e7b16729c6a23183e27a24de1b 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -2669,16 +2669,15 @@ even though the user gets a free copy.
              top_pad="5"
              name="media_tex"
              width="260">
-              Media URL
+              Media
 			</text>
-			<line_editor
+			<text
 			 follows="left|top|right"
 			 height="18"
 			 layout="topleft"
 			 left="10"
 			 read_only="true"
 			 name="media_info"
-			 select_on_focus="true"
 			 width="180" />
 			<button
 			 follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
index 1ebc51f504ef494146e55cd33d88c75d03ce513f..c1a211967c18054804f1257e33cf150a7050031b 100644
--- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml
+++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml
@@ -105,26 +105,6 @@
                  top="0"
                  width="24" />
             </layout_panel>
-            <layout_panel
-             layout="topleft"
-             name="volume_slider_panel"
-             top="0"
-             user_resize="false"
-             width="138">
-                <slider_bar
-                 control_name="AudioLevelMic"
-                 follows="left|right|top"
-                 height="24"
-                 increment="0.05"
-                 layout="topleft"
-                 left="0"
-                 max_val="2"
-                 name="volume_slider_bar"
-                 tool_tip="Master Volume"
-                 top="0"
-                 value="0.75"
-                 width="138" />
-            </layout_panel>
             <layout_panel
              auto_resize="false"
              layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml
index 89492d8abc797cbfb18a0042c5722076a82a7a98..439d68282f7c5a9357c15eebf6a2ef09b72c0aa1 100644
--- a/indra/newview/skins/default/xui/en/floater_water.xml
+++ b/indra/newview/skins/default/xui/en/floater_water.xml
@@ -4,7 +4,6 @@
  height="240"
  layout="topleft"
  name="Water Floater"
- help_topic="water_floater"
  save_rect="true"
  title="ADVANCED WATER EDITOR"
  width="700">
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index a36bfb8ec10a20c518da4d0fd15595e30db10d5b..660e3858acde2a9f763ec0908619ee3e8bfbfd71 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -450,6 +450,14 @@
     </menu_item_call>
     <menu_item_separator
      layout="topleft" />
+    <menu_item_call
+     label="Remove Link"
+     layout="topleft"
+     name="Remove Link">
+        <menu_item_call.on_click
+         function="Inventory.DoToSelected"
+         parameter="delete" />
+    </menu_item_call>
     <menu_item_call
      label="Delete"
      layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 9b439c16e09b35c498310d2d80472ecfbef5e18c..53be40d7fd8604a3d918d0e6240e3c92168c9e10 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -45,7 +45,8 @@
          name="Second Life Help"
          shortcut="F1">
             <menu_item_call.on_click
-             function="ShowHelp" />
+             function="ShowHelp"
+             parameter="f1_help" />
         </menu_item_call>
         <menu_item_separator />
         <menu_item_call
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 861b0de2cfaa107c405e75cda141887a3e2682b0..0891afaf76343528c3a9e94444b3e2a8ef5b284c 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1064,7 +1064,8 @@
          name="Second Life Help"
          shortcut="F1">
             <menu_item_call.on_click
-             function="ShowHelp" />
+             function="ShowHelp"
+             parameter="f1_help" />
         </menu_item_call>
         <menu_item_call
          label="Tutorial"
@@ -1200,15 +1201,6 @@
              function="ToggleControl"
              parameter="CompressSnapshotsToDisk" />
         </menu_item_check>
-        <menu_item_call
-         label="Save Texture As"
-         layout="topleft"
-         name="Save Texture As">
-            <menu_item_call.on_click
-             function="File.SaveTexture" />
-            <menu_item_call.on_enable
-             function="File.EnableSaveAs" />
-        </menu_item_call>
         <menu_item_separator
          layout="topleft" />
         <menu
diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml
new file mode 100644
index 0000000000000000000000000000000000000000..05cd8507252d619e4e05944ffb3c6474d45fbc28
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<mimetypes name="default">
+	<defaultlabel>
+		(Unknown)
+	</defaultlabel>
+	<defaultwidget>
+		none
+	</defaultwidget>
+	<defaultimpl>
+		media_plugin_webkit
+	</defaultimpl>
+	<widgetset name="web">
+		<label name="web_label">
+			Web Content
+		</label>
+		<icon>
+			icn_media_web.tga
+		</icon>
+		<default_type>
+			text/html
+		</default_type>
+		<tooltip name="web_tooltip">
+			This location has Web content
+		</tooltip>
+		<playtip name="web_playtip">
+			Show Web content
+		</playtip>
+		<allow_resize>
+			true
+		</allow_resize>
+		<allow_looping>
+			false
+		</allow_looping>
+	</widgetset>
+	<widgetset name="movie">
+		<label name="movie_label">
+			Movie
+		</label>
+		<default_type>
+			video/*
+		</default_type>
+		<icon>
+			icn_media_movie.tga
+		</icon>
+		<tooltip name="movie_tooltip">
+			There is a movie to play here
+		</tooltip>
+		<playtip name="movie_playtip">
+			Play movie
+		</playtip>
+		<allow_resize>
+			false
+		</allow_resize>
+		<allow_looping>
+			true
+		</allow_looping>
+	</widgetset>
+	<widgetset name="image">
+		<label name="image_label">
+			Image
+		</label>
+		<icon>
+			icn_media_web.tga
+		</icon>
+		<default_type>
+			image/*
+		</default_type>
+		<tooltip name="image_tooltip">
+			There is an image at this location
+		</tooltip>
+		<playtip name="image_playtip">
+			View this location&apos;s image
+		</playtip>
+		<allow_resize>
+			false
+		</allow_resize>
+		<allow_looping>
+			false
+		</allow_looping>
+	</widgetset>
+	<widgetset name="audio">
+		<label name="audio_label">
+			Audio
+		</label>
+		<icon>
+			icn_media_web.tga
+		</icon>
+		<default_type>
+			audio/*
+		</default_type>
+		<tooltip name="audio_tooltip">
+			There is audio at this location
+		</tooltip>
+		<playtip name="audio_playtip">
+			Play this location&apos;s audio
+		</playtip>
+		<allow_resize>
+			false
+		</allow_resize>
+		<allow_looping>
+			true
+		</allow_looping>
+	</widgetset>
+	<scheme name="rtsp">
+		<label name="rtsp_label">
+			Real Time Streaming
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</scheme>
+	<mimetype name="blank">
+		<label name="blank_label">
+			- None -
+		</label>
+		<widgettype>
+			none
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="none/none">
+		<label name="none/none_label">
+			- None -
+		</label>
+		<widgettype>
+			none
+		</widgettype>
+	</mimetype>
+	<mimetype name="audio/*">
+		<label name="audio2_label">
+			Audio
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+	</mimetype>
+	<mimetype name="video/*">
+		<label name="video2_label">
+			Video
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+	</mimetype>
+	<mimetype name="image/*">
+		<label name="image2_label">
+			Image
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
+		<label name="vnd.secondlife.qt.legacy_label">
+			Movie (QuickTime)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="application/javascript">
+		<label name="application/javascript_label">
+			Javascript
+		</label>
+		<widgettype>
+			web
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/ogg">
+		<label name="application/ogg_label">
+			Ogg Audio/Video
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/pdf">
+		<label name="application/pdf_label">
+			PDF Document
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/postscript">
+		<label name="application/postscript_label">
+			Postscript Document
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/rtf">
+		<label name="application/rtf_label">
+			Rich Text (RTF)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/smil">
+		<label name="application/smil_label">
+			Synchronized Multimedia Integration Language (SMIL)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/xhtml+xml">
+		<label name="application/xhtml+xml_label">
+			Web Page (XHTML)
+		</label>
+		<widgettype>
+			web
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/x-director">
+		<label name="application/x-director_label">
+			Macromedia Director
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="audio/mid">
+		<label name="audio/mid_label">
+			Audio (MIDI)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="audio/mpeg">
+		<label name="audio/mpeg_label">
+			Audio (MP3)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="audio/x-aiff">
+		<label name="audio/x-aiff_label">
+			Audio (AIFF)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="audio/x-wav">
+		<label name="audio/x-wav_label">
+			Audio (WAV)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/bmp">
+		<label name="image/bmp_label">
+			Image (BMP)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/gif">
+		<label name="image/gif_label">
+			Image (GIF)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/jpeg">
+		<label name="image/jpeg_label">
+			Image (JPEG)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/png">
+		<label name="image/png_label">
+			Image (PNG)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype name="image/svg+xml">
+		<label name="image/svg+xml_label">
+			Image (SVG)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/tiff">
+		<label name="image/tiff_label">
+			Image (TIFF)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="text/html">
+		<label name="text/html_label">
+			Web Page
+		</label>
+		<widgettype>
+			web
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="text/plain">
+		<label name="text/plain_label">
+			Text
+		</label>
+		<widgettype>
+			text
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype name="text/xml">
+		<label name="text/xml_label">
+			XML
+		</label>
+		<widgettype>
+			text
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="video/mpeg">
+		<label name="video/mpeg_label">
+			Movie (MPEG)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="video/mp4">
+		<label name="video/mp4_label">
+			Movie (MP4)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="video/quicktime">
+		<label name="video/quicktime_label">
+			Movie (QuickTime)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="video/x-ms-asf">
+		<label name="video/x-ms-asf_label">
+			Movie (Windows Media ASF)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype name="video/x-ms-wmv">
+		<label name="video/x-ms-wmv_label">
+			Movie (Windows Media WMV)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="video/x-msvideo">
+		<label name="video/x-msvideo_label">
+			Movie (AVI)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_gstreamer
+		</impl>
+	</mimetype>
+</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/mime_types_mac.xml b/indra/newview/skins/default/xui/en/mime_types_mac.xml
new file mode 100644
index 0000000000000000000000000000000000000000..76c0d027f336f42203c0da977608ced2e2740164
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/mime_types_mac.xml
@@ -0,0 +1,442 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<mimetypes name="default">
+	<defaultlabel>
+		(Unknown)
+	</defaultlabel>
+	<defaultwidget>
+		none
+	</defaultwidget>
+	<defaultimpl>
+		media_plugin_webkit
+	</defaultimpl>
+	<widgetset name="web">
+		<label name="web_label">
+			Web Content
+		</label>
+		<icon>
+			icn_media_web.tga
+		</icon>
+		<default_type>
+			text/html
+		</default_type>
+		<tooltip name="web_tooltip">
+			This location has Web content
+		</tooltip>
+		<playtip name="web_playtip">
+			Show Web content
+		</playtip>
+		<allow_resize>
+			true
+		</allow_resize>
+		<allow_looping>
+			false
+		</allow_looping>
+	</widgetset>
+	<widgetset name="movie">
+		<label name="movie_label">
+			Movie
+		</label>
+		<default_type>
+			video/*
+		</default_type>
+		<icon>
+			icn_media_movie.tga
+		</icon>
+		<tooltip name="movie_tooltip">
+			There is a movie to play here
+		</tooltip>
+		<playtip name="movie_playtip">
+			Play movie
+		</playtip>
+		<allow_resize>
+			false
+		</allow_resize>
+		<allow_looping>
+			true
+		</allow_looping>
+	</widgetset>
+	<widgetset name="image">
+		<label name="image_label">
+			Image
+		</label>
+		<icon>
+			icn_media_web.tga
+		</icon>
+		<default_type>
+			image/*
+		</default_type>
+		<tooltip name="image_tooltip">
+			There is an image at this location
+		</tooltip>
+		<playtip name="image_playtip">
+			View this location&apos;s image
+		</playtip>
+		<allow_resize>
+			false
+		</allow_resize>
+		<allow_looping>
+			false
+		</allow_looping>
+	</widgetset>
+	<widgetset name="audio">
+		<label name="audio_label">
+			Audio
+		</label>
+		<icon>
+			icn_media_web.tga
+		</icon>
+		<default_type>
+			audio/*
+		</default_type>
+		<tooltip name="audio_tooltip">
+			There is audio at this location
+		</tooltip>
+		<playtip name="audio_playtip">
+			Play this location&apos;s audio
+		</playtip>
+		<allow_resize>
+			false
+		</allow_resize>
+		<allow_looping>
+			true
+		</allow_looping>
+	</widgetset>
+	<scheme name="rtsp">
+		<label name="rtsp_label">
+			Real Time Streaming
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</scheme>
+	<mimetype name="blank">
+		<label name="blank_label">
+			- None -
+		</label>
+		<widgettype>
+			none
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="none/none">
+		<label name="none/none_label">
+			- None -
+		</label>
+		<widgettype>
+			none
+		</widgettype>
+	</mimetype>
+	<mimetype name="audio/*">
+		<label name="audio2_label">
+			Audio
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+	</mimetype>
+	<mimetype name="video/*">
+		<label name="video2_label">
+			Video
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+	</mimetype>
+	<mimetype name="image/*">
+		<label name="image2_label">
+			Image
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype menu="1" name="video/vnd.secondlife.qt.legacy">
+		<label name="vnd.secondlife.qt.legacy_label">
+			Movie (QuickTime)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="application/javascript">
+		<label name="application/javascript_label">
+			Javascript
+		</label>
+		<widgettype>
+			web
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/ogg">
+		<label name="application/ogg_label">
+			Ogg Audio/Video
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/pdf">
+		<label name="application/pdf_label">
+			PDF Document
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/postscript">
+		<label name="application/postscript_label">
+			Postscript Document
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/rtf">
+		<label name="application/rtf_label">
+			Rich Text (RTF)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/smil">
+		<label name="application/smil_label">
+			Synchronized Multimedia Integration Language (SMIL)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/xhtml+xml">
+		<label name="application/xhtml+xml_label">
+			Web Page (XHTML)
+		</label>
+		<widgettype>
+			web
+		</widgettype>
+	</mimetype>
+	<mimetype name="application/x-director">
+		<label name="application/x-director_label">
+			Macromedia Director
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+	</mimetype>
+	<mimetype name="audio/mid">
+		<label name="audio/mid_label">
+			Audio (MIDI)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="audio/mpeg">
+		<label name="audio/mpeg_label">
+			Audio (MP3)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="audio/x-aiff">
+		<label name="audio/x-aiff_label">
+			Audio (AIFF)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="audio/x-wav">
+		<label name="audio/x-wav_label">
+			Audio (WAV)
+		</label>
+		<widgettype>
+			audio
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/bmp">
+		<label name="image/bmp_label">
+			Image (BMP)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/gif">
+		<label name="image/gif_label">
+			Image (GIF)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/jpeg">
+		<label name="image/jpeg_label">
+			Image (JPEG)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/png">
+		<label name="image/png_label">
+			Image (PNG)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype name="image/svg+xml">
+		<label name="image/svg+xml_label">
+			Image (SVG)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="image/tiff">
+		<label name="image/tiff_label">
+			Image (TIFF)
+		</label>
+		<widgettype>
+			image
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="text/html">
+		<label name="text/html_label">
+			Web Page
+		</label>
+		<widgettype>
+			web
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="text/plain">
+		<label name="text/plain_label">
+			Text
+		</label>
+		<widgettype>
+			text
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype name="text/xml">
+		<label name="text/xml_label">
+			XML
+		</label>
+		<widgettype>
+			text
+		</widgettype>
+		<impl>
+			media_plugin_webkit
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="video/mpeg">
+		<label name="video/mpeg_label">
+			Movie (MPEG)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="video/mp4">
+		<label name="video/mp4_label">
+			Movie (MP4)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="video/quicktime">
+		<label name="video/quicktime_label">
+			Movie (QuickTime)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="video/x-ms-asf">
+		<label name="video/x-ms-asf_label">
+			Movie (Windows Media ASF)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype name="video/x-ms-wmv">
+		<label name="video/x-ms-wmv_label">
+			Movie (Windows Media WMV)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+	<mimetype menu="1" name="video/x-msvideo">
+		<label name="video/x-msvideo_label">
+			Movie (AVI)
+		</label>
+		<widgettype>
+			movie
+		</widgettype>
+		<impl>
+			media_plugin_quicktime
+		</impl>
+	</mimetype>
+</mimetypes>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 22896d59c3a72af60618621ccd4f7ae6a808a1a2..4645bfea740418e2fcf80caf699cbb7bff9e43bd 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -579,7 +579,7 @@ Scripts must be allowed to run for weapons to work.
    type="alertmodal">
 Multiple faces are currently selected.
 If you continue this action, separate instances of media will be set on multiple faces of the object.
-To place the media on only one face, choose Select Texture and click on the desired face of that object then click Add.
+To place the media on only one face, choose Select Face and click on the desired face of that object then click Add.
     <usetemplate
       ignoretext="Media will be set on multiple selected faces"
       name="okcancelignore"
@@ -3539,6 +3539,8 @@ Type a short announcement which will be sent to everyone in this region.
    type="alertmodal">
 The maturity rating for this region has been updated.
 It may take some time for the change to be reflected on the map.
+
+To enter Adult regions, residents must be Account Verified, either by age-verification or payment-verification.
   </notification>
 
   <notification
@@ -3797,21 +3799,6 @@ All reported abuses are investigated and resolved. You can view the resolution b
    <unique/>
   </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   name="HelpReportAbuseEmailEO"
-   type="alertmodal">
-IMPORTANT: This report will go to the owner of the region you are currently in and not to Linden Lab.
-
-As a service to residents and visitors, the owner of the region you are in has elected to receive and resolve all reports originating in this region. Linden Lab will not investigate reports you file from this location.
-
-The region owner will resolve reports based on the local rules of this region as outlined in the estate Covenant.
-(View covenants by going to the World menu and selecting About Land.)
-
-The resolution of this report applies only to this Region. Residents&apos; access to other areas of [SECOND_LIFE] will not be affected by the outcome of this report. Only Linden Lab can restrict access to the entirety of [SECOND_LIFE].
-  <unique/>
-  </notification>
-
   <notification
    icon="alertmodal.tga"
    name="HelpReportAbuseSelectCategory"
diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
index b82a435b415c0739e5204a1c527824db7dd18455..24c40b32fba71044489b1eeae39d84bbc7d402d1 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
@@ -71,7 +71,7 @@
    name="current_url_label">
     Current URL:
   </text>
-  <line_editor 
+  <text 
    bottom_delta="-20" 
    enabled="false" 
    follows="left|top" 
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index 8aba8b9dd12368c874ee7525de191d241e8f53b7..b5c6b637e5116216d6985d272a3d65f6da5fab6d 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -92,11 +92,7 @@
          name="(Japanese)"
          value="ja" />
 
-        <combo_box.item
-         enabled="true"
-         label="Test Language"
-         name="TestLanguage"
-         value="test" />
+
     </combo_box>
     <text
      type="string"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 102a53ad902deed78d89af2d8b72f03be50c7d21..5332007bafaca34268828d8bfd33ce7f0cfa2330 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -399,31 +399,6 @@
      name="voice_input_device"
      top_pad="0"
      width="200" />
-   <text
-     type="string"
-     length="1"
-     follows="left|top"
-     height="16"
-     layout="topleft"
-     left="165"
-     name="My volume label"
-     top_pad="10"
-     width="200">
-        My volume:
-    </text>
-      <slider_bar
-        control_name="AudioLevelMic"
-     follows="left|top"
-     height="17"
-     increment="0.05"
-     initial_value="1.0"
-     layout="topleft"
-     left="160"
-     max_val="2"
-     name="mic_volume_slider"
-     tool_tip="Change the volume using this slider"
-     top_pad="0"
-     width="220" />
     <text
      type="string"
      text_color="EmphasisColor"
@@ -433,7 +408,7 @@
      layout="topleft"
      left_pad="5"
      name="wait_text"
-     top_delta="0"
+     top_delta="5"
      width="110">
         Please wait
     </text>
@@ -442,7 +417,7 @@
      layout="topleft"
      left_delta="0"
      name="bar0"
-     top_delta="5"
+     top_delta="-5"
      width="20" />
     <locate
      height="20"
@@ -472,23 +447,13 @@
      name="bar4"
      top_delta="0"
      width="20" />
-  <!--  <text
-     type="string"
-     height="37"
-     left="30"
-     name="voice_intro_text1"
-     top_pad="-4"
-     width="410"
-     word_wrap="true">
-        Adjust the slider to control how loud you sound to other people. To test your volume, simply speak into your microphone
-    </text>-->
           <icon
              height="18"
              image_name="Parcel_Voice_Light"
              left="80"
              name="speaker_icon"
              mouse_opaque="false"
-             top_pad="-8"
+             top_pad="4"
              visible="true"
              width="22" />
     <text
diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
index e21de314986ce40226ffc4ed9cd7397fbf31301b..b4f72a48bc285326dc7c760c0ca6dc7ad6fa9c6d 100644
--- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -380,7 +380,7 @@
 		  image_selected="AudioMute_Off"
 		  image_unselected="Audio_Off"
 		  hover_glow_amount="0.15"
-		  name="media_volume_button"
+		  name="media_mute_button"
 		  height="22"
 		  is_toggle="true"
 		  layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_region_covenant.xml b/indra/newview/skins/default/xui/en/panel_region_covenant.xml
index 75d7d85505f450068c224f8c14cbc7be3956cbb2..ff55090f162e9326e348430fa5aaaed23f4207ce 100644
--- a/indra/newview/skins/default/xui/en/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_covenant.xml
@@ -3,6 +3,7 @@
  border="true"
  follows="top|left"
  height="320"
+ help_topic="panel_region_covenant_tab"
  label="Covenant"
  layout="topleft"
  left="0"
diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml
index e07585d285e992431aaee6ca13426d7169d02ca3..a6b4ddd01e8c5471b67e0c255da8d0778c4a04ce 100644
--- a/indra/newview/skins/default/xui/en/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml
@@ -3,6 +3,7 @@
  border="true"
  follows="top|left"
  height="320"
+ help_topic="panel_region_debug_tab"
  label="Debug"
  layout="topleft"
  left="0"
diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml
index e25ff0d548503e4c47db38b5f0d277bebd58c468..ba39e880249daa24a57e32ef8f4271d9f2545f76 100644
--- a/indra/newview/skins/default/xui/en/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml
@@ -3,16 +3,13 @@
  border="false"
  follows="top|left"
  height="320"
+ help_topic="panel_region_estate_tab"
  label="Estate"
  layout="topleft"
  left="0"
  name="Estate"
  top="320"
  width="480">
-    <panel.string
-     name="email_unsupported">
-        Feature unsupported
-    </panel.string>
     <text
      type="string"
      length="1"
@@ -81,7 +78,7 @@ regions in the estate.
     <view_border
      bevel_style="in"
      follows="top|left"
-     height="310"
+     height="270"
      layout="topleft"
      left_delta="-4"
      top_pad="5"
@@ -141,12 +138,12 @@ regions in the estate.
      name="Only Allow"
      top="250"
      width="278">
-        Restrict Access To:
+        Restrict Access to Accounts Verified by:
     </text>
     <check_box
      follows="top|left"
      height="16"
-     label="Residents with payment info on file"
+     label="Payment Information on File"
      layout="topleft"
      left_delta="0"
      name="limit_payment"
@@ -156,7 +153,7 @@ regions in the estate.
     <check_box
      follows="top|left"
      height="16"
-     label="Age-verified adults"
+     label="Age Verification"
      layout="topleft"
      left_delta="0"
      name="limit_age_verified"
@@ -179,26 +176,6 @@ regions in the estate.
      name="allow_direct_teleport"
      top_pad="4"
      width="80" />
-    <text
-     type="string"
-     length="1"
-     follows="left|top"
-     height="20"
-     layout="topleft"
-     left="15"
-     name="abuse_email_text"
-     top_pad="10"
-     width="180">
-        Abuse email address:
-    </text>
-    <line_editor
-     follows="top|left"
-     height="23"
-     layout="topleft"
-     left="15"
-     name="abuse_email_address"
-     top_pad="-5"
-     width="230" />
     <button
      enabled="false"
      follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
index 79d8f3a0ee0dc07f272f5b6697003e3839ec3f69..26568c2a289c01e8ae60100ba023bea8f2ad6f4e 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -3,6 +3,7 @@
  border="true"
  follows="top|left"
  height="320"
+ help_topic="panel_region_general_tab"
  label="Region"
  layout="topleft"
  left="0"
diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml
index ffd51bf510fc1e60195f15cd00cbeed374fe75ac..5093c52129d53e7c6f7932a8bacc26e4b83da188 100644
--- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml
@@ -3,6 +3,7 @@
  border="true"
  follows="top|left"
  height="320"
+ help_topic="panel_region_terrain_tab"
  label="Terrain"
  layout="topleft"
  left="0"
diff --git a/indra/newview/skins/default/xui/en/panel_region_texture.xml b/indra/newview/skins/default/xui/en/panel_region_texture.xml
index 5089064c0752629cb6b9ba7cd26af40005618031..a4d24cb0fce95fc038916ab548f5d11917180e70 100644
--- a/indra/newview/skins/default/xui/en/panel_region_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_texture.xml
@@ -3,6 +3,7 @@
  border="true"
  follows="top|left"
  height="320"
+ help_topic="panel_region_texture_tab"
  label="Ground Textures"
  layout="topleft"
  left="0"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
index db8a844eb0fbb672625c441ede7510646ced95ba..d006fd0700216bd48e359f9fc01e4ee2b0caa3c9 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml
@@ -488,15 +488,6 @@
 		 left="5"
 		 bottom="5"
 		 width="313">
-	    <button
-		     follows="bottom|left"
-		     height="25"
-		     label="Edit"
-		     layout="topleft"
-		     left="0"
-		     name="edit_btn"
-		     top="0"
-		     width="50" />
 	    <button
 		     follows="bottom|right"
 		     height="25"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
index 348f0dfc095edf6a4bb8eb823a3ccab16b8a0cfc..eff2ca1fcdeb516846c561c6b157507de783f9d9 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml
@@ -482,16 +482,7 @@
 		 left="5"
 		 bottom="5"
 		 width="313">
-	    <button
-		     follows="bottom|left"
-		     height="25"
-		     label="Edit"
-		     layout="topleft"
-		     left="0"
-		     name="edit_btn"
-		     top="0"
-		     width="50" />
-	    <button
+        <button
 		     follows="bottom|left"
 		     height="25"
 		     label="Open"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c3650c71c34face96701472c294aed1f070153c0..3044f105732d2afbc5b1b0555dc1ed1ef9ccb25d 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -460,7 +460,7 @@ Returns the rotation of detected object number (returns &lt;0,0,0,1&gt; if numbe
 	</string>
 	<string name="LSLTipText_llDetectedGroup" translate="false">
 integer llDetectedGroup(integer number)
-Returns TRUE if detected object is part of same group as owner
+Returns an integer that is a boolean representing if the detected object or avatar is in the same group that the prim containing the script is set to
 	</string>
 	<string name="LSLTipText_llDetectedLinkNumber" translate="false">
 integer llDetectedLinkNumber(integer number)
@@ -812,7 +812,7 @@ Preloads a sound on viewers within range
 	</string>
 	<string name="LSLTipText_llRotLookAt" translate="false">
 llRotLookAt(rotation target, float strength, float damping)
-Causes object name to point its forward axis towards target
+Causes object to point its forward axis towards target
 	</string>
 	<string name="LSLTipText_llStringLength" translate="false">
 integer llStringLength(string str)
@@ -1471,7 +1471,7 @@ Returns the requested permission mask for the root object the task is attached t
 	</string>
 	<string name="LSLTipText_llSetObjectPermMask" translate="false">
 llSetObjectPermMask(integer mask, integer value)
-Sets the given permission mask to the new value on the root object the task is attached to
+Sets the given permission mask to the new value on the root object the task is attached to (requires God Mode)
 	</string>
 	<string name="LSLTipText_llGetInventoryPermMask" translate="false">
 integer llGetInventoryPermMask(string item, integer mask)
@@ -1479,7 +1479,7 @@ Returns the requested permission mask for the inventory item
 	</string>
 	<string name="LSLTipText_llSetInventoryPermMask" translate="false">
 llSetInventoryPermMask(string item, integer mask, integer value)
-Sets the given permission mask to the new value on the inventory item
+Sets the given permission mask to the new value on the inventory item (requires God Mode)
 	</string>
 	<string name="LSLTipText_llGetInventoryCreator" translate="false">
 key llGetInventoryCreator(string item)
diff --git a/indra/newview/tests/llmediadataclient_test.cpp b/indra/newview/tests/llmediadataclient_test.cpp
index 6ff2c9446e72d723e340d38d7c03786314d93d98..33d413bd21133757f8d28a9fa5bdba61dde71b4f 100644
--- a/indra/newview/tests/llmediadataclient_test.cpp
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -75,15 +75,13 @@
 <string>baz</string>										\
 </array>"
 
-#define _DATA_URLS(ID,DIST,INT,URL1,URL2) "					\
+#define _DATA_URLS(ID,INTEREST,NEW,URL1,URL2) "					\
 <llsd>											\
   <map>											\
     <key>uuid</key>								\
     <string>" ID "</string>						\
-    <key>distance</key>											\
-    <real>" DIST "</real>										\
     <key>interest</key>											\
-    <real>" INT "</real>											\
+    <real>" INTEREST "</real>											\
     <key>cap_urls</key>											\
     <map>														\
       <key>ObjectMedia</key>									\
@@ -93,21 +91,26 @@
     </map>														\
     <key>media_data</key>                                       \
 	" MEDIA_DATA "												\
+    <key>is_dead</key>											\
+	<boolean>false</boolean>									\
+	<key>is_new</key>											\
+	<boolean>" NEW "</boolean>									\
   </map>														\
 </llsd>"
 
-#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
+#define _DATA(ID,INTEREST,NEW) _DATA_URLS(ID,INTEREST,NEW,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
 
-const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0");
+const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","true");
 	
 #define STR(I) boost::lexical_cast<std::string>(I)
 
 #define LOG_TEST(N) LL_DEBUGS("LLMediaDataClient") << "\n" <<			\
 "================================================================================\n" << \
-"===================================== TEST " #N " ===================================\n" << \
+"==================================== TEST " #N " ===================================\n" << \
 "================================================================================\n" << LL_ENDL;
 
 LLSD *gPostRecords = NULL;
+F64   gMinimumInterestLevel = (F64)0.0;
 
 // stubs:
 void LLHTTPClient::post(
@@ -125,21 +128,20 @@ void LLHTTPClient::post(
 	gPostRecords->append(record);
 	
 	// Magic URL that triggers a 503:
+	LLSD result;
+	result[LLTextureEntry::OBJECT_ID_KEY] = body[LLTextureEntry::OBJECT_ID_KEY];
 	if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
 	{
 		responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
+		return;
 	}
 	else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR) 
 	{
-		LLSD result;
 		LLSD error;
 		error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
 		result["error"] = error;
-		responder->result(result);
-	}
-	else {
-		responder->result(LLSD());
-	}
+	}	
+	responder->result(result);
 }
 
 const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
@@ -152,13 +154,12 @@ class LLMediaDataClientObjectTest : public LLMediaDataClientObject
 			std::istringstream d(data);
 			LLSDSerialize::fromXML(mRep, d);
 			mNumBounceBacks = 0;
-			mDead = false;
             
            // std::cout << ll_pretty_print_sd(mRep) << std::endl;
            // std::cout << "ID: " << getID() << std::endl;
 		}
 	LLMediaDataClientObjectTest(const LLSD &rep) 
-		: mRep(rep), mNumBounceBacks(0), mDead(false) {}
+		: mRep(rep), mNumBounceBacks(0) {}
 	~LLMediaDataClientObjectTest()
 		{ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClientObjectTest" << LL_ENDL; }
 	
@@ -169,43 +170,47 @@ class LLMediaDataClientObjectTest : public LLMediaDataClientObject
 	virtual LLUUID getID() const 
 		{ return mRep["uuid"]; }
 	virtual void mediaNavigateBounceBack(U8 index)
-		{
-			mNumBounceBacks++;
-		}
+		{ mNumBounceBacks++; }	
 	
 	virtual bool hasMedia() const
 		{ return mRep.has("media_data"); }
 	
-	virtual void updateObjectMediaData(LLSD const &media_data_array)
-		{ mRep["media_data"] = media_data_array; }
+	virtual void updateObjectMediaData(LLSD const &media_data_array, const std::string &media_version)
+		{ mRep["media_data"] = media_data_array; mRep["media_version"] = media_version; }
+		
+	virtual F64 getMediaInterest() const
+		{ return (LLSD::Real)mRep["interest"]; }
 	
-	virtual F64 getDistanceFromAvatar() const
-		{ return (LLSD::Real)mRep["distance"]; }
+	virtual bool isInterestingEnough() const
+		{ return getMediaInterest() > gMinimumInterestLevel; }
 	
-	virtual F64 getTotalMediaInterest() const
-		{ return (LLSD::Real)mRep["interest"]; }
-
 	virtual std::string getCapabilityUrl(const std::string &name) const 
 		{ return mRep["cap_urls"][name]; }
 
 	virtual bool isDead() const
-		{ return mDead; }
-
-	void setDistanceFromAvatar(F64 val)
-		{ mRep["distance"] = val; }
+		{ return mRep["is_dead"]; }
+	
+	virtual U32 getMediaVersion() const
+		{ return (LLSD::Integer)mRep["media_version"]; }
+	
+	virtual bool isNew() const
+		{ return mRep["is_new"]; }
 	
-	void setTotalMediaInterest(F64 val)
+	void setMediaInterest(F64 val)
 		{ mRep["interest"] = val; }
 
 	int getNumBounceBacks() const
 		{ return mNumBounceBacks; }
 	
 	void markDead()
-		{ mDead = true; }
+		{ mRep["is_dead"] = true; }
+	
+	void markOld()
+		{ mRep["is_new"] = false; }
+	
 private:
 	LLSD mRep;
 	int mNumBounceBacks;
-	bool mDead;
 };
 
 // This special timer delay should ensure that the timer will fire on the very
@@ -224,10 +229,11 @@ namespace tut
     {
 		mediadataclient() {
 			gPostRecords = &mLLSD;
+			gMinimumInterestLevel = (F64)0.0;
 			
- 			//LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
- 			//LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG);
-			//LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);
+// 			LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+// 			LLError::setClassLevel("LLMediaDataClient", LLError::LEVEL_DEBUG);
+//			LLError::setTagLevel("MediaOnAPrim", LLError::LEVEL_DEBUG);
 		}
 		LLSD mLLSD;
     };
@@ -378,11 +384,11 @@ namespace tut
 		LOG_TEST(4);
 
 		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
-			_DATA(VALID_OBJECT_ID_1,"3.0","1.0"));
+			_DATA(VALID_OBJECT_ID_1,"1.0","true"));
 		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
-			_DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
+			_DATA(VALID_OBJECT_ID_2,"3.0","true"));
 		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
-			_DATA(VALID_OBJECT_ID_3,"2.0","1.0"));
+			_DATA(VALID_OBJECT_ID_3,"2.0","true"));
 		{
 			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);  
 			const char *ORDERED_OBJECT_IDS[] = { VALID_OBJECT_ID_2, VALID_OBJECT_ID_3, VALID_OBJECT_ID_1 };
@@ -428,8 +434,7 @@ namespace tut
 		
 		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
 			_DATA_URLS(VALID_OBJECT_ID,
-					   "1.0",
-					   "1.0",
+					   "1.0","true",
 					   FAKE_OBJECT_MEDIA_CAP_URL_503,
 					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL));
 		int num_refs_start = o->getNumRefs();
@@ -484,8 +489,7 @@ namespace tut
 
 		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(
 			_DATA_URLS(VALID_OBJECT_ID,
-					   "1.0",
-					   "1.0",
+					   "1.0","true",
 					   FAKE_OBJECT_MEDIA_CAP_URL,
 					   FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR));
 		{		
@@ -517,9 +521,9 @@ namespace tut
 		LOG_TEST(7);
 		
 		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(
-			_DATA(VALID_OBJECT_ID_1,"3.0","1.0"));
+			_DATA(VALID_OBJECT_ID_1,"3.0","true"));
 		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
-			_DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
+			_DATA(VALID_OBJECT_ID_2,"1.0","true"));
 		int num_refs_start = o1->getNumRefs();
 		{
 			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
@@ -551,10 +555,10 @@ namespace tut
 		// Test queue handling of objects that are marked dead.
 		LOG_TEST(8);
 		
-		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","1.0"));
-		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","1.0"));
-		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","1.0"));
-		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","1.0"));
+		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"4.0","true"));
+		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"3.0","true"));
+		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"2.0","true"));
+		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"1.0","true"));
 		{
 			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
 			
@@ -616,10 +620,11 @@ namespace tut
 		//
 		LOG_TEST(9);
 		
-		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"10.0","1.0"));
-		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"20.0","1.0"));
-		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"30.0","1.0"));
-		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"40.0","1.0"));
+		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"40.0","true"));
+		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"30.0","true"));
+		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"20.0","true"));
+		LLMediaDataClientObjectTest *object4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"10.0","true"));
+		LLMediaDataClientObject::ptr_t o4 = object4;
 		{
 			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
 			
@@ -630,53 +635,52 @@ namespace tut
 			mdc->fetchMedia(o3);
 			mdc->fetchMedia(o4);
 			
-			int test_num = 0;
+			int tick_num = 0;
 			
-			ensure(STR(test_num) + ". is in queue 1", mdc->isInQueue(o1));
-			ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2));
-			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3));
-			ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4));
-			ensure(STR(test_num) + ". post records", gPostRecords->size(), 0);
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
 			
 			::pump_timers();
-			++test_num;
+			++tick_num;
 			
 			// The first tick should remove the first one 
-			ensure(STR(test_num) + ". is not in queue 1", !mdc->isInQueue(o1));
-			ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2));
-			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3));
-			ensure(STR(test_num) + ". is in queue 4", mdc->isInQueue(o4));
-			ensure(STR(test_num) + ". post records", gPostRecords->size(), 1);
+			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
 			
 			// Now, pretend that object 4 moved relative to the avatar such
 			// that it is now closest
-			static_cast<LLMediaDataClientObjectTest*>(
-				static_cast<LLMediaDataClientObject*>(o4))->setDistanceFromAvatar(5.0);
+			object4->setMediaInterest(50.0);
 			
 			::pump_timers();
-			++test_num;
+			++tick_num;
 			
 			// The second tick should still pick off item 2, but then re-sort
 			// have picked off object 4
-			ensure(STR(test_num) + ". is in queue 2", mdc->isInQueue(o2));
-			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3));
-			ensure(STR(test_num) + ". is not in queue 4", !mdc->isInQueue(o4));
-			ensure(STR(test_num) + ". post records", gPostRecords->size(), 2);
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
 
 			::pump_timers();
-			++test_num;
+			++tick_num;
 			
 			// The third tick should pick off object 2
-			ensure(STR(test_num) + ". is not in queue 2", !mdc->isInQueue(o2));
-			ensure(STR(test_num) + ". is in queue 3", mdc->isInQueue(o3));
-			ensure(STR(test_num) + ". post records", gPostRecords->size(), 3);
+			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
 
 			// The fourth tick should pick off object 3
 			::pump_timers();
-			++test_num;
+			++tick_num;
 
-			ensure(STR(test_num) + ". is not in queue 3", !mdc->isInQueue(o3));
-			ensure(STR(test_num) + ". post records", gPostRecords->size(), 4);
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
 
 			ensure("queue empty", mdc->isEmpty());
 		}
@@ -686,4 +690,249 @@ namespace tut
 		ensure("refcount of o4", o4->getNumRefs(), 1);
     }
 	
+	
+	template<> template<>
+    void mediadataclient_object_t::test<10>()
+    {
+		//
+		// Test using the "round-robin" queue
+		//
+		LOG_TEST(10);
+		
+		LLMediaDataClientObject::ptr_t o1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
+		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
+		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","false"));
+		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","false"));
+		{
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+			
+			// queue up all 4 objects.  The first two should be in the sorted
+			// queue [2 1], the second in the round-robin queue.  The queues
+			// are serviced interleaved, so we should expect:
+			// 2, 4, 1, 3
+			mdc->fetchMedia(o1);
+			mdc->fetchMedia(o2);
+			mdc->fetchMedia(o3);
+			mdc->fetchMedia(o4);
+			
+			int tick_num = 0;
+			
+			// 0
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 1 The first tick should remove object 2
+			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_2));
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 2 The second tick should send object 4, but it will still be
+			// "in the queue"
+			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 3 The third tick should remove object 1
+			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 4 The fourth tick should send object 3, but it will still be
+			// "in the queue"
+			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[3]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));
+			
+			::pump_timers();
+			++tick_num;
+						
+			// 5 The fifth tick should now identify objects 3 and 4 as no longer
+			// needing "updating", and remove them from the queue
+			ensure(STR(tick_num) + ". is not in queue 2", !mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 4);
+			
+			::pump_timers();
+			
+			// Whew....better be empty
+			ensure("queue empty", mdc->isEmpty());
+		}
+		ensure("refcount of o1", o1->getNumRefs(), 1);
+		ensure("refcount of o2", o2->getNumRefs(), 1);
+		ensure("refcount of o3", o3->getNumRefs(), 1);
+		ensure("refcount of o4", o4->getNumRefs(), 1);		
+	}
+	
+	
+	template<> template<>
+	void mediadataclient_object_t::test<11>()
+	{
+		//
+		// Test LLMediaDataClient's destructor
+		//
+		LOG_TEST(11);
+		
+		LLMediaDataClientObject::ptr_t o = new LLMediaDataClientObjectTest(DATA);
+		int num_refs_start = o->getNumRefs();
+		{
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+			mdc->fetchMedia(o);
+			// must tick enough times to clear refcount of mdc
+			::pump_timers();
+		}		
+		// Make sure everyone's destroyed properly
+		ensure("REF COUNT", o->getNumRefs(), num_refs_start);
+	}
+	
+	template<> template<>
+    void mediadataclient_object_t::test<12>()
+    {
+		//
+		// Test the "not interesting enough" call
+		//
+		LOG_TEST(12);
+		
+		LLMediaDataClientObjectTest *object1 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_1,"1.0","true"));
+		LLMediaDataClientObject::ptr_t o1 = object1;
+		LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_2,"2.0","true"));
+		LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_3,"3.0","true"));
+		LLMediaDataClientObject::ptr_t o4 = new LLMediaDataClientObjectTest(_DATA(VALID_OBJECT_ID_4,"4.0","true"));
+		{
+			LLPointer<LLObjectMediaDataClient> mdc = new LLObjectMediaDataClient(NO_PERIOD,NO_PERIOD);
+			
+			// queue up all 4 objects.  The first two are "interesting enough".
+			// Firing the timer 4 times should therefore leave them.
+			// Note that they should be sorted 4,3,2,1
+			// Then, we'll make one "interesting enough", fire the timer a few 
+			// times, and make sure only it gets pulled off the queue
+			gMinimumInterestLevel = 2.5;
+			mdc->fetchMedia(o1);
+			mdc->fetchMedia(o2);
+			mdc->fetchMedia(o3);
+			mdc->fetchMedia(o4);
+			
+			int tick_num = 0;
+			
+			// 0
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is in queue 4", mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 0);
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 1 The first tick should remove object 4
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is in queue 3", mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 1);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[0]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_4));
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 2 The second tick should send object 3
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[1]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_3));
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 3 The third tick should not pull off anything
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+
+			::pump_timers();
+			++tick_num;
+			
+			// 4 The fourth tick (for good measure) should not pull off anything
+			ensure(STR(tick_num) + ". is in queue 1", mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 2);
+			
+			// Okay, now futz with object 1's interest, such that it is now 
+			// "interesting enough"
+			object1->setMediaInterest((F64)5.0);
+			
+			// This should sort so that the queue is now [1 2] 
+			::pump_timers();
+			++tick_num;
+			
+			// 5 The fifth tick should now identify objects 3 and 4 as no longer
+			// needing "updating", and remove them from the queue
+			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+			ensure(STR(tick_num) + ". post object id", (*gPostRecords)[2]["body"][LLTextureEntry::OBJECT_ID_KEY].asUUID(), LLUUID(VALID_OBJECT_ID_1));
+			
+			::pump_timers();
+			++tick_num;
+			
+			// 6 The sixth tick should not pull off anything
+			ensure(STR(tick_num) + ". is not in queue 1", !mdc->isInQueue(o1));
+			ensure(STR(tick_num) + ". is in queue 2", mdc->isInQueue(o2));
+			ensure(STR(tick_num) + ". is not in queue 3", !mdc->isInQueue(o3));
+			ensure(STR(tick_num) + ". is not in queue 4", !mdc->isInQueue(o4));
+			ensure(STR(tick_num) + ". post records", gPostRecords->size(), 3);
+			
+			::pump_timers();
+			++tick_num;
+		
+			// Whew....better NOT be empty ... o2 should still be there
+			ensure("queue not empty", !mdc->isEmpty());
+			
+			// But, we need to clear the queue, or else we won't destroy MDC...
+			// this is a strange interplay between the queue timer and the MDC
+			ensure("o2 couldn't be removed from queue", mdc->removeFromQueue(o2));
+			// tick
+			::pump_timers();
+		}
+		ensure("refcount of o1", o1->getNumRefs(), 1);
+		ensure("refcount of o2", o2->getNumRefs(), 1);
+		ensure("refcount of o3", o3->getNumRefs(), 1);
+		ensure("refcount of o4", o4->getNumRefs(), 1);		
+	}
 }
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 413331548050ab27cb9cdd1bf335bee0d836b340..32fdd41be2cdd6a7355f80700647a3ae56552cfb 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -803,7 +803,7 @@ def construct(self):
         # plugins
         if self.prefix(src="", dst="bin/llplugin"):
             self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so")
-            self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_quicktime.so")
+            self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so")
             self.end_prefix("bin/llplugin")
 
         self.path("featuretable_linux.txt")
diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp
index 30d338292e4c204159462bb39d96668895341474..d183aac208f1f5bdb622a570309f9e561b4f61d7 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -1537,7 +1537,7 @@ void LLMediaPluginTest::addMediaPanel( std::string url )
         char cwd[ FILENAME_MAX ];
 	if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
 	{
-		std::cerr << "Couldn't get cwd - probably too long - failing to init." << llendl;
+		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
 		return;
 	}
 	std::string user_data_path = std::string( cwd ) + "/";
@@ -1774,7 +1774,7 @@ void LLMediaPluginTest::replaceMediaPanel( mediaPanel* panel, std::string url )
         char cwd[ FILENAME_MAX ];
 	if (NULL == getcwd( cwd, FILENAME_MAX - 1 ))
 	{
-		std::cerr << "Couldn't get cwd - probably too long - failing to init." << llendl;
+		std::cerr << "Couldn't get cwd - probably too long - failing to init." << std::endl;
 		return;
 	}
 	std::string user_data_path = std::string( cwd ) + "/";