Skip to content
Snippets Groups Projects
Commit e6daa50c authored by Richard Linden's avatar Richard Linden
Browse files

windows_volume_catcher.cpp, now with comments!

also added volume_catcher.h to project
parent 882436ba
No related branches found
No related tags found
No related merge requests found
...@@ -36,6 +36,10 @@ set(media_plugin_webkit_SOURCE_FILES ...@@ -36,6 +36,10 @@ set(media_plugin_webkit_SOURCE_FILES
media_plugin_webkit.cpp media_plugin_webkit.cpp
) )
set(media_plugin_webkit_HEADER_FILES
volume_catcher.h
)
set(media_plugin_webkit_LINK_LIBRARIES set(media_plugin_webkit_LINK_LIBRARIES
${LLPLUGIN_LIBRARIES} ${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES}
...@@ -66,6 +70,11 @@ else (LINUX AND PULSEAUDIO) ...@@ -66,6 +70,11 @@ else (LINUX AND PULSEAUDIO)
list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp) list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp)
endif (LINUX AND PULSEAUDIO) 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 add_library(media_plugin_webkit
SHARED SHARED
${media_plugin_webkit_SOURCE_FILES} ${media_plugin_webkit_SOURCE_FILES}
......
...@@ -32,8 +32,12 @@ ...@@ -32,8 +32,12 @@
*/ */
#include "volume_catcher.h" #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 class Mixer
{ {
public: public:
...@@ -44,81 +48,91 @@ class Mixer ...@@ -44,81 +48,91 @@ class Mixer
void setVolume(F32 volume_left, F32 volume_right); void setVolume(F32 volume_left, F32 volume_right);
private: 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); Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_volume, U32 max_volume);
HMIXER mHandle; HMIXER mHandle;
U32 mMuteControlID; U32 mMuteControlID; // handle to mixer controller for muting
U32 mVolumeControlID; U32 mVolumeControlID; // handle to mixer controller for changing volume
U32 mMinVolume; U32 mMinVolume; // value that specifies minimum volume as reported by mixer
U32 mMaxVolume; 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) Mixer* Mixer::create(U32 index)
{ {
// get handle to mixer object
HMIXER mixer_handle; HMIXER mixer_handle;
MMRESULT result = mixerOpen( &mixer_handle, MMRESULT result = mixerOpen( &mixer_handle,
index, index,
0, // HWND to call when state changes - not used 0, // HWND to call when state changes - not used
0, // user data for callback - not used 0, // user data for callback - not used
MIXER_OBJECTF_MIXER ); MIXER_OBJECTF_MIXER );
if (result == MMSYSERR_NOERROR) if (result == MMSYSERR_NOERROR)
{ {
MIXERLINE mixer_line; MIXERLINE mixer_line;
mixer_line.cbStruct = sizeof( MIXERLINE ); mixer_line.cbStruct = sizeof( MIXERLINE );
// try speakers first
// try speakers first
mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
MMRESULT result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ), MMRESULT result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
&mixer_line, &mixer_line,
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
if (result != MMSYSERR_NOERROR) if (result != MMSYSERR_NOERROR)
{ { // failed - try headphones next
// failed - try headphones next mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES;
mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES; result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ), &mixer_line,
&mixer_line, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE );
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); }
}
if (result == MMSYSERR_NOERROR) if (result == MMSYSERR_NOERROR)
{ { // successfully found mixer line object, now use it to get volume and mute controls
// get control id
MIXERCONTROL mixer_control; // reuse these objects to query for both volume and mute controls
MIXERLINECONTROLS mixer_line_controls; MIXERCONTROL mixer_control;
mixer_line_controls.cbStruct = sizeof( MIXERLINECONTROLS ); MIXERLINECONTROLS mixer_line_controls;
mixer_line_controls.dwLineID = mixer_line.dwLineID; mixer_line_controls.cbStruct = sizeof( MIXERLINECONTROLS );
mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; mixer_line_controls.dwLineID = mixer_line.dwLineID;
mixer_line_controls.cControls = 1; mixer_line_controls.cControls = 1;
mixer_line_controls.cbmxctrl = sizeof( MIXERCONTROL ); mixer_line_controls.cbmxctrl = sizeof( MIXERCONTROL );
mixer_line_controls.pamxctrl = &mixer_control; mixer_line_controls.pamxctrl = &mixer_control;
result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ), // first, query for mute
&mixer_line_controls, mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
if (result == MMSYSERR_NOERROR ) // get control id for mute controls
{ result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
// We have a mute mixer. Remember the mute control id &mixer_line_controls,
U32 mute_control_id = mixer_control.dwControlID; MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
if (result == MMSYSERR_NOERROR )
// now query for volume controls { // we have a mute controls. Remember the mute control id and then query for
mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; // volume controls using the same struct, but different dwControlType
result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
&mixer_line_controls, U32 mute_control_id = mixer_control.dwControlID;
MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE ); mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ),
if (result == MMSYSERR_NOERROR) &mixer_line_controls,
{ MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE );
// we have both mute and volume controls for this mixer, so remember it
return new Mixer(mixer_handle, if (result == MMSYSERR_NOERROR)
mute_control_id, { // we have both mute and volume controls for this mixer, so we're keeping it
mixer_control.dwControlID, return new Mixer(mixer_handle,
mixer_control.Bounds.dwMinimum, mute_control_id,
mixer_control.Bounds.dwMaximum); 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; return NULL;
} }
...@@ -131,47 +145,55 @@ Mixer::Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_ ...@@ -131,47 +145,55 @@ Mixer::Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_
{} {}
Mixer::~Mixer() Mixer::~Mixer()
{ {}
}
// toggle mute for this mixer
// if mute is set, then volume level will be ignored
void Mixer::setMute(bool mute) void Mixer::setMute(bool mute)
{ {
MIXERCONTROLDETAILS_BOOLEAN mixer_control_details_bool = { mute }; MIXERCONTROLDETAILS_BOOLEAN mixer_control_details_bool = { mute };
MIXERCONTROLDETAILS mixer_control_details; MIXERCONTROLDETAILS mixer_control_details;
mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS ); mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS );
mixer_control_details.dwControlID = mMuteControlID; mixer_control_details.dwControlID = mMuteControlID;
mixer_control_details.cChannels = 1; mixer_control_details.cChannels = 1;
mixer_control_details.cMultipleItems = 0; mixer_control_details.cMultipleItems = 0;
mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN ); mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN );
mixer_control_details.paDetails = &mixer_control_details_bool; mixer_control_details.paDetails = &mixer_control_details_bool;
mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ), mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ),
&mixer_control_details, &mixer_control_details,
MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE ); 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) 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) U32 volume_left_mixer = (U32)
((F32)mMinVolume ((F32)mMinVolume
+ (volume_left * ((F32)mMaxVolume - (F32)mMinVolume))); + (volume_left * ((F32)mMaxVolume - (F32)mMinVolume)));
U32 volume_right_mixer = (U32) U32 volume_right_mixer = (U32)
((F32)mMinVolume ((F32)mMinVolume
+ (volume_right * ((F32)mMaxVolume - (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 class VolumeCatcherImpl
{ {
...@@ -207,9 +229,10 @@ VolumeCatcherImpl *VolumeCatcherImpl::getInstance() ...@@ -207,9 +229,10 @@ VolumeCatcherImpl *VolumeCatcherImpl::getInstance()
} }
VolumeCatcherImpl::VolumeCatcherImpl() VolumeCatcherImpl::VolumeCatcherImpl()
: mVolume(1.0f), : mVolume(1.0f), // default volume is max
mPan(0.f) // 0 is centered mPan(0.f) // default pan is centered
{ {
// for each reported mixer "device", create a proxy object and add to list
U32 num_mixers = mixerGetNumDevs(); U32 num_mixers = mixerGetNumDevs();
for (U32 mixer_index = 0; mixer_index < num_mixers; ++mixer_index) for (U32 mixer_index = 0; mixer_index < num_mixers; ++mixer_index)
{ {
...@@ -241,7 +264,9 @@ void VolumeCatcherImpl::setVolume(F32 volume) ...@@ -241,7 +264,9 @@ void VolumeCatcherImpl::setVolume(F32 volume)
for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end(); for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end();
it != end_it; it != end_it;
++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); (*it)->setVolume(left_volume, right_volume);
if (volume == 0.f && mVolume != 0.f) if (volume == 0.f && mVolume != 0.f)
...@@ -258,7 +283,7 @@ void VolumeCatcherImpl::setVolume(F32 volume) ...@@ -258,7 +283,7 @@ void VolumeCatcherImpl::setVolume(F32 volume)
} }
void VolumeCatcherImpl::setPan(F32 pan) void VolumeCatcherImpl::setPan(F32 pan)
{ { // remember pan for calculating individual channel levels later
mPan = pan; mPan = pan;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment