summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Linden <none@none>2010-04-16 12:10:57 -0700
committerRichard Linden <none@none>2010-04-16 12:10:57 -0700
commite6daa50c5878885b27f4145eeeeee9745e12086a (patch)
tree7621490630443e254d2a51f3b23ac58c82f83158
parent882436ba06826a604e7a201f823ddff266fe9abd (diff)
windows_volume_catcher.cpp, now with comments!
also added volume_catcher.h to project
-rw-r--r--indra/media_plugins/webkit/CMakeLists.txt9
-rw-r--r--indra/media_plugins/webkit/windows_volume_catcher.cpp209
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;
}