diff options
author | Richard Linden <none@none> | 2010-04-16 12:10:57 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2010-04-16 12:10:57 -0700 |
commit | e6daa50c5878885b27f4145eeeeee9745e12086a (patch) | |
tree | 7621490630443e254d2a51f3b23ac58c82f83158 | |
parent | 882436ba06826a604e7a201f823ddff266fe9abd (diff) |
windows_volume_catcher.cpp, now with comments!
also added volume_catcher.h to project
-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; } |