📄 mixer.cpp
字号:
// Mixer.cpp: implementation of the CMixer class.
//
//////////////////////////////////////////////////////////////////////
#include "Mixer.h"
#include "ErrorHandling.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
namespace AudioEngine {
const CMixerLine CMixer::Master(MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
const CMixerLine CMixer::WaveOut(MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
const CMixerLine CMixer::CDAudio(MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS);
// returns true if the given mixer supports this line
bool CMixerLine::IsValidForMixer(HMIXER mixer, int &lineid, int &channels) const
{
int result;
// make sure the destination line is valid
MIXERLINE line;
line.cbStruct = sizeof(MIXERLINE);
line.dwComponentType = m_Dest;
result = mixerGetLineInfo((HMIXEROBJ)mixer, &line, MIXER_GETLINEINFOF_COMPONENTTYPE);
if (result) {
// failed!
return(false);
}
lineid = line.dwLineID; // just in case source is undefined...
channels = line.cChannels;
// make sure source line is valid... to do this, iterate through each connection
// of the (known valid) destination line.
if (m_Source != MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED) {
bool valid = false;
for (int connection=0; connection < line.cConnections; connection++) {
MIXERLINE srcline;
memcpy(&srcline, &line, sizeof(MIXERLINE));
srcline.cbStruct = sizeof(MIXERLINE);
srcline.dwSource = connection;
result = mixerGetLineInfo((HMIXEROBJ)mixer, &srcline, MIXER_GETLINEINFOF_SOURCE);
if (result) {
// failed!
Throw("CMixerLine::IsValidForMixer: mixerGetLineInfo failed while trying to validate source.");
}
if (srcline.dwComponentType == m_Source) {
// it's valid!
valid = true;
lineid = srcline.dwLineID;
channels = srcline.cChannels;
break;
}
if (!valid) return(false);
}
}
return(true);
}
void CMixerLine::GetControlInfo(HMIXER mixer, int controltype, int lineid, int &id) const
{
MIXERCONTROL control;
MIXERLINECONTROLS linecontrols;
ZeroMemory(&control, sizeof(MIXERCONTROL));
ZeroMemory(&linecontrols, sizeof(MIXERLINECONTROLS));
linecontrols.cbStruct = sizeof(MIXERLINECONTROLS);
linecontrols.dwLineID = lineid;
linecontrols.dwControlType = controltype;
linecontrols.cControls = 1;
linecontrols.cbmxctrl = sizeof(MIXERCONTROL);
linecontrols.pamxctrl = &control;
control.cbStruct = sizeof(MIXERCONTROL);
if (mixerGetLineControls((HMIXEROBJ)mixer, &linecontrols, MIXER_GETLINECONTROLSF_ONEBYTYPE)) {
Throw("CMixerLine::GetControlInfo: mixerGetLineControls failed.");
}
id = control.dwControlID;
}
bool CMixerLine::SetControlValue(HMIXER mixer, int lineid, int control, int channels, int value) const
{
MIXERCONTROLDETAILS controldetails;
MIXERCONTROLDETAILS_UNSIGNED controldetailsunsigned[128];
if (channels > 128) { Throw("CMixerLine::SetControlValue: Channel overflow."); }
int id=0; GetControlInfo(mixer, control, lineid, id);
ZeroMemory(&controldetails, sizeof(MIXERCONTROLDETAILS));
controldetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
controldetails.dwControlID = id;
controldetails.cChannels = channels;
controldetails.cbDetails = sizeof(controldetailsunsigned);
controldetails.paDetails = &controldetailsunsigned[0];
// all channels of this control get the same value.
// if you want to do things like set the left and right volume
// independently, you'll need to change this.
for (int q=0; q < controldetails.cChannels; q++) {
controldetailsunsigned[q].dwValue = value;
}
// set
if (mixerSetControlDetails((HMIXEROBJ)mixer, &controldetails, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE )) {
return(false);
}
return(true);
}
int CMixerLine::GetControlValue(HMIXER mixer, int lineid, int control, int channels) const
{
MIXERCONTROLDETAILS controldetails;
MIXERCONTROLDETAILS_UNSIGNED controldetailsunsigned;
int id; GetControlInfo(mixer, control, lineid, id);
ZeroMemory(&controldetails, sizeof(MIXERCONTROLDETAILS));
controldetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
controldetails.dwControlID = id;
controldetails.cChannels = channels;
controldetails.cbDetails = sizeof(controldetailsunsigned);
controldetails.paDetails = &controldetailsunsigned;
// validate
if (mixerGetControlDetails((HMIXEROBJ)mixer, &controldetails, 0)) {
Throw("CMixerLine::GetControlValue: mixerGetControlDetails failed.");
}
return(controldetailsunsigned.dwValue);
}
CMixer::CMixer()
{
m_hMixer = NULL;
}
CMixer::~CMixer()
{
}
void CMixer::Init()
{
if (mixerOpen(&m_hMixer, 0, 0, 0, CALLBACK_NULL)) {
Throw("CMixer::Init(): mixerOpen failed.");
}
}
void CMixer::UnInit()
{
mixerClose(m_hMixer);
m_hMixer = NULL;
}
bool CMixer::SetVolume(const CMixerLine &line, int vol_0_to_65535)
{
int lineid, channels;
if (!line.IsValidForMixer(m_hMixer, lineid, channels)) return(false);
return(line.SetControlValue(m_hMixer, lineid, MIXERCONTROL_CONTROLTYPE_VOLUME, channels, vol_0_to_65535));
}
int CMixer::GetVolume(const CMixerLine &line)
{
int lineid, channels;
if (!line.IsValidForMixer(m_hMixer, lineid, channels)) return(false);
return(line.GetControlValue(m_hMixer, lineid, MIXERCONTROL_CONTROLTYPE_VOLUME, channels));
}
bool CMixer::Mute(const CMixerLine &line)
{
int lineid, channels;
if (!line.IsValidForMixer(m_hMixer, lineid, channels)) return(false);
return(line.SetControlValue(m_hMixer, lineid, MIXERCONTROL_CONTROLTYPE_MUTE, channels, 1));
}
bool CMixer::UnMute(const CMixerLine &line)
{
int lineid, channels;
if (!line.IsValidForMixer(m_hMixer, lineid, channels)) return(false);
return(line.SetControlValue(m_hMixer, lineid, MIXERCONTROL_CONTROLTYPE_MUTE, channels, 0));
}
}; // namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -