diff --git a/doc/contributions.txt b/doc/contributions.txt
index 4b36c44a5f7b5921e3a5ea110c2807ebd7fab119..cf10ecccfbbc46a1de4231072ddd11babfde302f 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -600,6 +600,7 @@ Tharax Ferraris
 Thickbrick Sleaford
 	VWR-7109
 	VWR-9287
+	VWR-13483
 	VWR-13947
 Thraxis Epsilon
 	SVC-371
diff --git a/indra/develop.py b/indra/develop.py
index 05ad12f20e2b46a883e0633ced2330f435ff8d3e..eaecdd0ab662a6baa9db79ca59aa40fc55a6a040 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -573,7 +573,7 @@ def get_build_cmd(self):
             if self.gens[self.generator]['ver'] in [ r'8.0', r'9.0' ]:
                 config = '\"%s|Win32\"' % config
 
-            return "buildconsole %s.sln /build %s" % (self.project_name, config)
+            return "buildconsole %(prj)s.sln /build /cfg=%(cfg)s" % {'prj': self.project_name, 'cfg': config}
 
         # devenv.com is CLI friendly, devenv.exe... not so much.
         return ('"%sdevenv.com" %s.sln /build %s' % 
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
index 109e20f179c9f7aa0b1b8a30ed5360300ac8792f..484948bd9fce330b8f32da52bf63295d7d723889 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -108,7 +108,7 @@ gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
 	
 	slvideo = GST_SLVIDEO(bsink);
 	
-	DEBUGMSG("\n\ntransferring a frame of %dx%d <- %p (%d)\n\n",
+	DEBUGMSG("transferring a frame of %dx%d <- %p (%d)",
 		 slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
 		 slvideo->format);
 
@@ -336,7 +336,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 #define MAXDEPTHHACK 4
 	
 	GST_OBJECT_LOCK(slvideo);
-	if (slvideo->resize_forced)
+	if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
 	{
 		gint slwantwidth, slwantheight;
 		slwantwidth = slvideo->resize_try_width;
@@ -385,6 +385,8 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 		}
 	}
 
+	GST_OBJECT_UNLOCK(slvideo);
+
 	if (!made_bufferdata_ptr) // need to fallback to malloc at original size
 	{
 		GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
@@ -393,8 +395,6 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
 		llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
 	}
 
-	GST_OBJECT_UNLOCK(slvideo);
-
 	*buf = GST_BUFFER_CAST(newbuf);
 
 	return GST_FLOW_OK;
@@ -458,7 +458,7 @@ gst_slvideo_init (GstSLVideo * filter,
 	filter->retained_frame_format = SLV_PF_UNKNOWN;
 	GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS);
 	llgst_caps_replace (&filter->caps, caps);
-	filter->resize_forced = false;
+	filter->resize_forced_always = false;
 	filter->resize_try_width = -1;
 	filter->resize_try_height = -1;
 	GST_OBJECT_UNLOCK(filter);
@@ -499,7 +499,7 @@ gst_slvideo_get_property (GObject * object, guint prop_id,
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
-	DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n");
+	DEBUGMSG("PLUGIN INIT");
 
 	GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
 				 0, (gchar*)"Second Life Video Sink");
@@ -527,7 +527,7 @@ void gst_slvideo_init_class (void)
 				  "http://www.secondlife.com/");
 #undef PACKAGE
 	ll_gst_plugin_register_static (&gst_plugin_desc);
-	DEBUGMSG("\n\n\nCLASS INIT\n\n\n");
+	DEBUGMSG("CLASS INIT");
 }
 
 #endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
index 208523e8d027d8c63474d5cedcead01f76c879a7..8f1cf84978dc3fc0d0056966071cd521a042c7f0 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
@@ -90,7 +90,7 @@ struct _GstSLVideo
 	int retained_frame_width, retained_frame_height;
 	SLVPixelFormat retained_frame_format;
 	// sticky resize info
-	bool resize_forced;
+	bool resize_forced_always;
 	int resize_try_width;
 	int resize_try_height;
 };
diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
index 8e850ed7ffd44de4efb4c53bdcdacae3cff91eb8..26173314a7f8ea52d2802291ea0a0fcb1873b549 100644
--- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
+++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
@@ -105,7 +105,7 @@ class MediaPluginGStreamer010 : public MediaPluginBase
         void mouseUp( int x, int y );
         void mouseMove( int x, int y );
 
-        bool sizeChanged();
+        void sizeChanged();
 	
 	static bool mDoneInit;
 	
@@ -477,9 +477,8 @@ MediaPluginGStreamer010::update(int milliseconds)
 			    mCurrentWidth <= mWidth &&
 			    !mTextureSegmentName.empty())
 			{
-				
 				// we're gonna totally consume this frame - reset 'ready' flag
-				mVideoSink->retained_frame_ready = FALSE;				
+				mVideoSink->retained_frame_ready = FALSE;
 				int destination_rowbytes = mWidth * mDepth;
 				for (int row=0; row<mCurrentHeight; ++row)
 				{
@@ -840,7 +839,7 @@ MediaPluginGStreamer010::startup()
 }
 
 
-bool
+void
 MediaPluginGStreamer010::sizeChanged()
 {
 	// the shared writing space has possibly changed size/location/whatever
@@ -855,8 +854,9 @@ MediaPluginGStreamer010::sizeChanged()
 			 mNaturalWidth, mNaturalHeight);
 	}
 
+	// if the size has changed then the shm has changed and the app needs telling
 	if (mCurrentWidth != mPreviousWidth ||
-	    mCurrentHeight != mPreviousHeight) // if the size has changed then the shm has changed and the app needs telling
+	    mCurrentHeight != mPreviousHeight)
 	{
 		mPreviousWidth = mCurrentWidth;
 		mPreviousHeight = mCurrentHeight;
@@ -865,11 +865,9 @@ MediaPluginGStreamer010::sizeChanged()
 		message.setValue("name", mTextureSegmentName);
 		message.setValueS32("width", mNaturalWidth);
 		message.setValueS32("height", mNaturalHeight);
-		DEBUGMSG("<--- Sending size change request to application with name: '%s' - size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);
+		DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight);
 		sendMessage(message);
 	}
-	
-	return true;
 }
 
 
@@ -1000,7 +998,6 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
 				INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress);
 
 				mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
-
 			}
 			else if(message_name == "shm_remove")
 			{
@@ -1079,7 +1076,7 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
 							INFOMSG("**** = REAL RESIZE REQUEST FROM APP");
 							
 							GST_OBJECT_LOCK(mVideoSink);
-							mVideoSink->resize_forced = true;
+							mVideoSink->resize_forced_always = true;
 							mVideoSink->resize_try_width = texture_width;
 							mVideoSink->resize_try_height = texture_height;
 							GST_OBJECT_UNLOCK(mVideoSink);
diff --git a/indra/newview/linux_tools/register_secondlifeprotocol.sh b/indra/newview/linux_tools/register_secondlifeprotocol.sh
index c7b4d5546114c44ea2a4a035d1d45b5a040d60d2..16e73cb854f7aaad73c69500ed28af6460f371d6 100755
--- a/indra/newview/linux_tools/register_secondlifeprotocol.sh
+++ b/indra/newview/linux_tools/register_secondlifeprotocol.sh
@@ -22,13 +22,12 @@ else
 fi
 
 # Register handler for KDE-aware apps
-if [ -z "$KDEHOME" ]; then
-    KDEHOME=~/.kde
-fi
-LLKDEPROTDIR=${KDEHOME}/share/services
-if [ -d "$LLKDEPROTDIR" ]; then
-    LLKDEPROTFILE=${LLKDEPROTDIR}/secondlife.protocol
-    cat > ${LLKDEPROTFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTFILE}
+for LLKDECONFIG in kde-config kde4-config; do
+    if [ `which $LLKDECONFIG` ]; then
+        LLKDEPROTODIR=`$LLKDECONFIG --path services | cut -d ':' -f 1`
+        if [ -d "$LLKDEPROTODIR" ]; then
+            LLKDEPROTOFILE=${LLKDEPROTODIR}/secondlife.protocol
+            cat > ${LLKDEPROTOFILE} <<EOF || echo Warning: Did not register secondlife:// handler with KDE: Could not write ${LLKDEPROTOFILE} 
 [Protocol]
 exec=${HANDLER} '%u'
 protocol=secondlife
@@ -41,6 +40,9 @@ writing=false
 makedir=false
 deleting=false
 EOF
-else
-    echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTDIR does not exist.
-fi
+        else
+            echo Warning: Did not register secondlife:// handler with KDE: Directory $LLKDEPROTODIR does not exist.
+        fi
+    fi
+done
+
diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp
index 90cfb858219ee7820f0d23a3b3857aff64d05a92..e9293ac5a476e052b96fcd992f84d0e2cd156d2c 100644
--- a/indra/newview/llviewermedia_streamingaudio.cpp
+++ b/indra/newview/llviewermedia_streamingaudio.cpp
@@ -1,7 +1,7 @@
 /** 
  * @file llviewermedia_streamingaudio.h
  * @author Tofu Linden, Sam Kolb
- * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugins API.
+ * @brief LLStreamingAudio_MediaPlugins implementation - an implementation of the streaming audio interface which is implemented as a client of the media plugin API.
  *
  * $LicenseInfo:firstyear=2009&license=viewergpl$
  * 
@@ -33,6 +33,7 @@
 #include "llviewerprecompiledheaders.h"
 #include "linden_common.h"
 #include "llpluginclassmedia.h"
+#include "llpluginclassmediaowner.h"
 #include "llviewermedia.h"
 
 #include "llviewermedia_streamingaudio.h"
@@ -61,18 +62,18 @@ void LLStreamingAudio_MediaPlugins::start(const std::string& url)
 	if (!mMediaPlugin) // lazy-init the underlying media plugin
 	{
 		mMediaPlugin = initializeMedia("audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis.
-		llinfos << "mMediaPlugin is now " << mMediaPlugin << llendl;
+		llinfos << "steaming audio mMediaPlugin is now " << mMediaPlugin << llendl;
 	}
 
 	if(!mMediaPlugin)
 		return;
-	
+
 	if (!url.empty()) {
 		llinfos << "Starting internet stream: " << url << llendl;
 		mURL = url;
 		mMediaPlugin->loadURI ( url );
 		mMediaPlugin->start();
-		llinfos << "Playing....." << llendl;		
+		llinfos << "Playing stream..." << llendl;		
 	} else {
 		llinfos << "setting stream to NULL"<< llendl;
 		mURL.clear();
@@ -82,6 +83,7 @@ void LLStreamingAudio_MediaPlugins::start(const std::string& url)
 
 void LLStreamingAudio_MediaPlugins::stop()
 {
+	llinfos << "Stopping internet stream." << llendl;
 	if(mMediaPlugin)
 	{
 		mMediaPlugin->stop();
@@ -97,10 +99,12 @@ void LLStreamingAudio_MediaPlugins::pause(int pause)
 	
 	if(pause)
 	{
+		llinfos << "Pausing internet stream." << llendl;
 		mMediaPlugin->pause();
 	} 
 	else 
 	{
+		llinfos << "Unpausing internet stream." << llendl;
 		mMediaPlugin->start();
 	}
 }
@@ -114,20 +118,21 @@ void LLStreamingAudio_MediaPlugins::update()
 int LLStreamingAudio_MediaPlugins::isPlaying()
 {
 	if (!mMediaPlugin)
-		return 0;
+		return 0; // stopped
 	
-	// *TODO: can probably do better than this
-	if (mMediaPlugin->isPluginRunning())
-	{
-		return 1; // Active and playing
-	}	
+	LLPluginClassMediaOwner::EMediaStatus status =
+		mMediaPlugin->getStatus();
 
-	if (mMediaPlugin->isPluginExited())
+	switch (status)
 	{
+	case LLPluginClassMediaOwner::MEDIA_LOADING: // but not MEDIA_LOADED
+	case LLPluginClassMediaOwner::MEDIA_PLAYING:
+		return 1; // Active and playing
+	case LLPluginClassMediaOwner::MEDIA_PAUSED:
+		return 2; // paused
+	default:
 		return 0; // stopped
 	}
-
-	return 2; // paused
 }
 
 void LLStreamingAudio_MediaPlugins::setGain(F32 vol)