diff options
| -rw-r--r-- | indra/media_plugins/webkit/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | indra/media_plugins/webkit/windows_volume_catcher.cpp | 209 | 
2 files changed, 126 insertions, 92 deletions
| diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt index 40722622a4..c33a26b637 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 b01986db56..1c1ef0b42f 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 @@ public:  	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;  } | 
