windows_volume_catcher.cpp, now with comments!
also added volume_catcher.h to projectmeow-7.2.2
parent
882436ba06
commit
e6daa50c58
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue