diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
index 40722622a4247f209200cf7f547ef62ce8eb8f47..c33a26b6379e71fcf93e656e8779ee1f3c20fce2 100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -36,6 +36,10 @@ set(media_plugin_webkit_SOURCE_FILES
     media_plugin_webkit.cpp
     )
 
+set(media_plugin_webkit_HEADER_FILES
+	volume_catcher.h
+	)
+	
 set(media_plugin_webkit_LINK_LIBRARIES
   ${LLPLUGIN_LIBRARIES}
   ${MEDIA_PLUGIN_BASE_LIBRARIES}
@@ -66,6 +70,11 @@ else (LINUX AND PULSEAUDIO)
   list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp)
 endif (LINUX AND PULSEAUDIO)
 
+set_source_files_properties(${media_plugin_webkit_HEADER_FILES}
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND media_plugin_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES})
+
 add_library(media_plugin_webkit
     SHARED
     ${media_plugin_webkit_SOURCE_FILES}
diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp
index b01986db56b790f74e2ca85b4ba6c0fa402bf268..1c1ef0b42f10a8ef5c542b992ee1573526160fa9 100644
--- a/indra/media_plugins/webkit/windows_volume_catcher.cpp
+++ b/indra/media_plugins/webkit/windows_volume_catcher.cpp
@@ -32,8 +32,12 @@
  */
 
 #include "volume_catcher.h"
-#include <windows.h>
+#include <windows.h>
 
+//
+// Abstracts a Win32 mixer line and associated state
+// for muting and changing volume on a given output
+//
 class Mixer
 {
 public:
@@ -44,81 +48,91 @@ class Mixer
 	void setVolume(F32 volume_left, F32 volume_right);
 
 private:
+	// use create(index) to create a Mixer
 	Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_volume, U32 max_volume);
 
-	HMIXER	mHandle;
-	U32		mMuteControlID;
-	U32		mVolumeControlID;
-	U32		mMinVolume;
-	U32		mMaxVolume;
+	HMIXER	mHandle;		
+	U32		mMuteControlID;		// handle to mixer controller for muting
+	U32		mVolumeControlID;	// handle to mixer controller for changing volume
+	U32		mMinVolume;			// value that specifies minimum volume as reported by mixer
+	U32		mMaxVolume;			// value that specifies maximum volume as reported by mixer
 };
 
+// factory function that attempts to create a Mixer object associated with a given mixer line index
+// returns NULL if creation failed
+// static 
 Mixer* Mixer::create(U32 index)
 {
+	// get handle to mixer object
 	HMIXER mixer_handle;
-	MMRESULT result = mixerOpen( &mixer_handle,
-							index,	
-							0,	// HWND to call when state changes - not used
-							0,	// user data for callback - not used
-							MIXER_OBJECTF_MIXER );
+	MMRESULT result = mixerOpen( &mixer_handle,
+							index,	
+							0,	// HWND to call when state changes - not used
+							0,	// user data for callback - not used
+							MIXER_OBJECTF_MIXER );
 
 	if (result == MMSYSERR_NOERROR)
 	{
-		MIXERLINE mixer_line;
-		mixer_line.cbStruct = sizeof( MIXERLINE );
-		// try speakers first
+		MIXERLINE mixer_line;
+		mixer_line.cbStruct = sizeof( MIXERLINE );
+
+		// try speakers first
 		mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
 
-		MMRESULT result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
-								&mixer_line,
-								MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
-		if (result != MMSYSERR_NOERROR)
-		{
-			// failed - try headphones next
-			mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES;
-			result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
-									&mixer_line,
-									MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
-		}
+		MMRESULT result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
+								&mixer_line,
+								MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
+		if (result != MMSYSERR_NOERROR)
+		{	// failed - try headphones next
+			mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES;
+			result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
+									&mixer_line,
+									MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
+		}
 
 		if (result == MMSYSERR_NOERROR)
-		{
-			// get control id
-			MIXERCONTROL mixer_control;
-			MIXERLINECONTROLS mixer_line_controls;
-			mixer_line_controls.cbStruct = sizeof( MIXERLINECONTROLS );
-			mixer_line_controls.dwLineID = mixer_line.dwLineID;
-			mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
-			mixer_line_controls.cControls = 1;
-			mixer_line_controls.cbmxctrl = sizeof( MIXERCONTROL );
-			mixer_line_controls.pamxctrl = &mixer_control;
-
-			result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
-				&mixer_line_controls,
-				MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
-			if (result == MMSYSERR_NOERROR )
-			{
-				// We have a mute mixer.  Remember the mute control id
-				U32 mute_control_id = mixer_control.dwControlID;
-
-				// now query for volume controls
-				mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
-				result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
-					&mixer_line_controls,
-					MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
-
-				if (result == MMSYSERR_NOERROR)
-				{
-					// we have both mute and volume controls for this mixer, so remember it
-					return new Mixer(mixer_handle, 
-								mute_control_id, 
-								mixer_control.dwControlID, 
-								mixer_control.Bounds.dwMinimum, 
-								mixer_control.Bounds.dwMaximum);
-				}
-			}
-		}
+		{	// successfully found mixer line object, now use it to get volume and mute controls
+
+			// reuse these objects to query for both volume and mute controls
+			MIXERCONTROL mixer_control;
+			MIXERLINECONTROLS mixer_line_controls;
+			mixer_line_controls.cbStruct = sizeof( MIXERLINECONTROLS );
+			mixer_line_controls.dwLineID = mixer_line.dwLineID;
+			mixer_line_controls.cControls = 1;
+			mixer_line_controls.cbmxctrl = sizeof( MIXERCONTROL );
+			mixer_line_controls.pamxctrl = &mixer_control;
+
+			// first, query for mute
+			mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
+
+			// get control id for mute controls
+			result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
+				&mixer_line_controls,
+				MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
+			if (result == MMSYSERR_NOERROR )
+			{	// we have a mute controls.  Remember the mute control id and then query for 
+				// volume controls using the same struct, but different dwControlType
+
+				U32 mute_control_id = mixer_control.dwControlID;
+				mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
+				result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
+					&mixer_line_controls,
+					MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
+
+				if (result == MMSYSERR_NOERROR)
+				{	// we have both mute and volume controls for this mixer, so we're keeping it
+					return new Mixer(mixer_handle, 
+								mute_control_id, 
+								mixer_control.dwControlID, 
+								mixer_control.Bounds.dwMinimum, 
+								mixer_control.Bounds.dwMaximum);
+				}
+			}
+		}
 	}
+
+	// if we got here, we didn't successfully create a Mixer object
+	mixerClose(mixer_handle);
 	return NULL;
 }
 
@@ -131,47 +145,55 @@ Mixer::Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_
 {}
 
 Mixer::~Mixer()
-{
-}
+{}
 
+// toggle mute for this mixer
+// if mute is set, then volume level will be ignored
 void Mixer::setMute(bool mute)
 {
-	MIXERCONTROLDETAILS_BOOLEAN mixer_control_details_bool = { mute };
-	MIXERCONTROLDETAILS mixer_control_details;
-	mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS );
-	mixer_control_details.dwControlID = mMuteControlID;
-	mixer_control_details.cChannels = 1;
-	mixer_control_details.cMultipleItems = 0;
-	mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN );
-	mixer_control_details.paDetails = &mixer_control_details_bool;
-
-	mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ),
-								 &mixer_control_details,
-								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE );
+	MIXERCONTROLDETAILS_BOOLEAN mixer_control_details_bool = { mute };
+	MIXERCONTROLDETAILS mixer_control_details;
+	mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS );
+	mixer_control_details.dwControlID = mMuteControlID;
+	mixer_control_details.cChannels = 1;
+	mixer_control_details.cMultipleItems = 0;
+	mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN );
+	mixer_control_details.paDetails = &mixer_control_details_bool;
+
+	mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ),
+								 &mixer_control_details,
+								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE );
 }
 
+// set individual volume levels for left and right channels
+// if mute is set, then these values will apply once mute is unset
 void Mixer::setVolume(F32 volume_left, F32 volume_right)
 {
+	// assuming pan is in range [-1, 1] set volume levels accordingly
+	// if pan == -1 then	volume_left_mixer = volume_left	&& volume_right_mixer = 0
+	// if pan == 0 then		volume_left_mixer = volume_left	&& volume_right_mixer = volume_right
+	// if pan == 1 then		volume_left_mixer = 0			&& volume_right_mixer = volume_right
 	U32 volume_left_mixer = (U32)
 							((F32)mMinVolume 
 								+ (volume_left * ((F32)mMaxVolume - (F32)mMinVolume)));
 	U32 volume_right_mixer = (U32)
 							((F32)mMinVolume 
 								+ (volume_right * ((F32)mMaxVolume - (F32)mMinVolume)));
-	MIXERCONTROLDETAILS_UNSIGNED mixer_control_details_unsigned[ 2 ] = { volume_left_mixer, volume_right_mixer };
-	MIXERCONTROLDETAILS mixer_control_details;
-	mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS );
-	mixer_control_details.dwControlID = mVolumeControlID;
-	mixer_control_details.cChannels = 2;
-	mixer_control_details.cMultipleItems = 0;
-	mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_UNSIGNED );
-	mixer_control_details.paDetails = &mixer_control_details_unsigned;
-
-	mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ),
-								 &mixer_control_details,
-								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE );
-}
 
+	// pass volume levels on to mixer
+	MIXERCONTROLDETAILS_UNSIGNED mixer_control_details_unsigned[ 2 ] = { volume_left_mixer, volume_right_mixer };
+	MIXERCONTROLDETAILS mixer_control_details;
+	mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS );
+	mixer_control_details.dwControlID = mVolumeControlID;
+	mixer_control_details.cChannels = 2;
+	mixer_control_details.cMultipleItems = 0;
+	mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_UNSIGNED );
+	mixer_control_details.paDetails = &mixer_control_details_unsigned;
+
+	mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ),
+								 &mixer_control_details,
+								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE );
+}
 
 class VolumeCatcherImpl
 {
@@ -207,9 +229,10 @@ VolumeCatcherImpl *VolumeCatcherImpl::getInstance()
 }
 
 VolumeCatcherImpl::VolumeCatcherImpl()
-:	mVolume(1.0f),
-	mPan(0.f) // 0 is centered
+:	mVolume(1.0f),	// default volume is max
+	mPan(0.f)		// default pan is centered
 {
+	// for each reported mixer "device", create a proxy object and add to list
 	U32 num_mixers = mixerGetNumDevs();
 	for (U32 mixer_index = 0; mixer_index < num_mixers; ++mixer_index)
 	{
@@ -241,7 +264,9 @@ void VolumeCatcherImpl::setVolume(F32 volume)
 	for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end();
 		it != end_it;
 		++it)
-	{
+	{	// set volume levels and mute for each mixer
+		// note that a muted mixer will ignore this volume level
+
 		(*it)->setVolume(left_volume, right_volume);
 		
 		if (volume == 0.f && mVolume != 0.f)
@@ -258,7 +283,7 @@ void VolumeCatcherImpl::setVolume(F32 volume)
 }
 
 void VolumeCatcherImpl::setPan(F32 pan)
-{
+{	// remember pan for calculating individual channel levels later
 	mPan = pan;
 }