公告
财富商城
积分规则
提问
发文
2019-07-10 02:45发布
Anthone
In C/C++ on windows xp how to get master volume or how to change master volume...?
Thanks in advance...
The starting point for API documentation in the MSDN library would be here.
Helpful code can be found by searching for MIXERCONTROL_CONTROLTYPE_VOLUME, yielding code like this (taken from here)
MIXERCONTROL_CONTROLTYPE_VOLUME
static const unsigned MAXIMUM_VOLUME_LEVEL_DEFINED_BY_USER = 100; Win32VolumeControl::Win32VolumeControl(const AudioDevice & audioDevice) { std::string deviceName = audioDevice.getData()[0]; //String deviceId = audioDevice.getData()[1]; EnumDeviceType::DeviceType deviceType = EnumDeviceType::toDeviceType(audioDevice.getData()[2]); _hMixer = NULL; int deviceId = Win32AudioDeviceId::getMixerDeviceId(deviceName); MMRESULT mr = initVolumeControl(deviceId, deviceType); if (mr != MMSYSERR_NOERROR) { _hMixer = NULL; _isSettable = false; if (deviceType == EnumDeviceType::DeviceTypeWaveIn) { deviceType = EnumDeviceType::DeviceTypeMicrophoneIn; MMRESULT mr = initVolumeControl(deviceId, deviceType); if (mr == MMSYSERR_NOERROR) { _isSettable = true; } } } else { _isSettable = true; } } Win32VolumeControl::~Win32VolumeControl() { close(); } int Win32VolumeControl::getLevel() { if (!_isSettable) { return 0; } MMRESULT mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_VOLUME); if (mr != MMSYSERR_NOERROR) { return -1; } const unsigned MINIMUM_VOLUME_LEVEL = _mxc.Bounds.dwMinimum; const unsigned MAXIMUM_VOLUME_LEVEL = _mxc.Bounds.dwMaximum; MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = _mxc.dwControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = &mxcdVolume; mr = ::mixerGetControlDetailsA((HMIXEROBJ) _hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't get the volume level, mixerGetControlDetailsA() failed"); return -1; } return (int) (((float) ((mxcdVolume.dwValue - MINIMUM_VOLUME_LEVEL) * MAXIMUM_VOLUME_LEVEL_DEFINED_BY_USER) / (float) (MAXIMUM_VOLUME_LEVEL - MINIMUM_VOLUME_LEVEL)) + 0.5); } bool Win32VolumeControl::setLevel(unsigned level) { if (!_isSettable) { return false; } MMRESULT mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_VOLUME); if (mr != MMSYSERR_NOERROR) { return false; } const unsigned MINIMUM_VOLUME_LEVEL = _mxc.Bounds.dwMinimum; const unsigned MAXIMUM_VOLUME_LEVEL = _mxc.Bounds.dwMaximum; MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; mxcdVolume.dwValue = level * (MAXIMUM_VOLUME_LEVEL - MINIMUM_VOLUME_LEVEL) / MAXIMUM_VOLUME_LEVEL_DEFINED_BY_USER; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = _mxc.dwControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = &mxcdVolume; mr = ::mixerSetControlDetails((HMIXEROBJ) _hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't set the volume level, mixerSetControlDetails() failed"); return false; } return true; } bool Win32VolumeControl::setMute(bool mute) { if (!_isSettable) { return false; } MMRESULT mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_MUTE); if (mr != MMSYSERR_NOERROR) { return false; } MIXERCONTROLDETAILS_BOOLEAN mxcbMute; mxcbMute.fValue = mute; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = _mxc.dwControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = &mxcbMute; mr = ::mixerSetControlDetails((HMIXEROBJ) _hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't mute/unmute the audio device, mixerSetControlDetails() failed"); return false; } return true; } bool Win32VolumeControl::isMuted() { if (!_isSettable) { return false; } MMRESULT mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_MUTE); if (mr != MMSYSERR_NOERROR) { return false; } MIXERCONTROLDETAILS_BOOLEAN mxcbMute; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = _mxc.dwControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = &mxcbMute; mr = ::mixerGetControlDetailsA((HMIXEROBJ) _hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't get if the audio device is mute/unmute, mixerGetControlDetailsA() failed"); return false; } return mxcbMute.fValue; } bool Win32VolumeControl::selectAsRecordDevice() { if (!_isSettable) { return false; } MMRESULT mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_MUX); if (mr != MMSYSERR_NOERROR) { return false; } MIXERCONTROLDETAILS_BOOLEAN mxcbSelect; mxcbSelect.fValue = true; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = _mxc.dwControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = &mxcbSelect; mr = ::mixerSetControlDetails((HMIXEROBJ) _hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't select the audio device as the record device, mixerSetControlDetails() failed"); return false; } return true; } bool Win32VolumeControl::isSelectedAsRecordDevice() { if (!_isSettable) { return false; } MMRESULT mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_MUX); if (mr != MMSYSERR_NOERROR) { return false; } MIXERCONTROLDETAILS_BOOLEAN mxcbSelect; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = _mxc.dwControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = &mxcbSelect; mr = ::mixerGetControlDetailsA((HMIXEROBJ) _hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't select the audio device as the record device, mixerSetControlDetails() failed"); return false; } return mxcbSelect.fValue; } bool Win32VolumeControl::close() { if (!_isSettable) { return false; } if (_hMixer) { MMRESULT mr = ::mixerClose(_hMixer); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("couldn't close the mixer, mixerClose() failed"); return false; } return true; } return false; } Win32VolumeControl::initVolumeControl(unsigned deviceId, EnumDeviceType::DeviceType deviceType) { MMRESULT mr = ::mixerOpen(&_hMixer, deviceId, NULL, NULL, MIXER_OBJECTF_MIXER); if (mr != MMSYSERR_NOERROR) { _hMixer = NULL; return mr; } MIXERCAPSA mxcaps; mr = ::mixerGetDevCapsA(deviceId, &mxcaps, sizeof(MIXERCAPSA)); if (mr != MMSYSERR_NOERROR) { return mr; } LOG_DEBUG("manufacturer's name for the mixer=" + std::string(mxcaps.szPname) + " " + String::fromNumber(mxcaps.wMid) + " " + String::fromNumber(mxcaps.wPid)); DWORD dwComponentType; switch (deviceType) { case EnumDeviceType::DeviceTypeWaveOut: dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; break; case EnumDeviceType::DeviceTypeWaveIn: dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; break; case EnumDeviceType::DeviceTypeCDOut: dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; break; case EnumDeviceType::DeviceTypeMicrophoneOut: dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; break; case EnumDeviceType::DeviceTypeMicrophoneIn: dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; break; case EnumDeviceType::DeviceTypeMasterVolume: dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; break; default: LOG_FATAL("unknow device type=" + EnumDeviceType::toString(deviceType)); } mr = createMixerLine(dwComponentType); if (mr != MMSYSERR_NOERROR) { return mr; } //For microphone in, we first look for the wave in mixer //and then for the microphone if (deviceType == EnumDeviceType::DeviceTypeMicrophoneIn) { mr = createSecondMixerLine(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE); if (mr != MMSYSERR_NOERROR) { return mr; } } // mr = createMixerControl(MIXERCONTROL_CONTROLTYPE_VOLUME); if (mr != MMSYSERR_NOERROR) { return mr; } LOG_DEBUG("destination line name=" + std::string(_mxl.szName) + " volume controller name=" + std::string(_mxc.szName)); //Everything went fine return mr; } MMRESULT Win32VolumeControl::createMixerLine(DWORD dwComponentType) { _mxl.cbStruct = sizeof(MIXERLINEA); _mxl.dwComponentType = dwComponentType; MMRESULT mr = ::mixerGetLineInfoA((HMIXEROBJ) _hMixer, &_mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("mixerGetLineInfoA() failed using dwComponentType=" + String::fromNumber(dwComponentType)); } return mr; } MMRESULT Win32VolumeControl::createSecondMixerLine(DWORD dwComponentType) { unsigned connections = _mxl.cConnections; DWORD destination = _mxl.dwDestination; MMRESULT mr; for (unsigned i = 0; i < connections; ++i) { _mxl.cbStruct = sizeof(MIXERLINEA); _mxl.dwSource = i; _mxl.dwDestination = destination; mr = ::mixerGetLineInfoA((HMIXEROBJ) _hMixer, &_mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE); if (mr == MMSYSERR_NOERROR && _mxl.dwComponentType == dwComponentType) { break; } } if (mr != MMSYSERR_NOERROR) { LOG_ERROR("mixerGetLineInfoA() failed using dwComponentType=" + String::fromNumber(dwComponentType)); } return mr; } MMRESULT Win32VolumeControl::createMixerControl(DWORD dwControlType) { _mxlc.cbStruct = sizeof(MIXERLINECONTROLSA); _mxlc.dwLineID = _mxl.dwLineID; //MIXERCONTROL_CONTROLTYPE_VOLUME //MIXERCONTROL_CONTROLTYPE_MIXER //MIXERCONTROL_CONTROLTYPE_MUX //MIXERCONTROL_CONTROLTYPE_MUTE _mxlc.dwControlType = dwControlType; _mxlc.cControls = 1; _mxlc.cbmxctrl = sizeof(MIXERCONTROLA); _mxlc.pamxctrl = &_mxc; MMRESULT mr = ::mixerGetLineControlsA((HMIXEROBJ) _hMixer, &_mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); if (mr != MMSYSERR_NOERROR) { LOG_ERROR("mixerGetLineControlsA() failed using dwControType=" + String::fromNumber(dwControlType)); } return mr; }
The legacy mixer API can be difficult to use. I'd recommend using the WASAPI API.
WASAPI - http://msdn.microsoft.com/en-us/library/dd371455(v=VS.85).aspx
Here.
#include <windows.h> #pragma comment(lib, "winmm") // to mute: waveOutSetVolume(NULL, 0); // full volume: waveOutSetVolume(NULL, 0xFFFF);
最多设置5个标签!
The starting point for API documentation in the MSDN library would be here.
Helpful code can be found by searching for
MIXERCONTROL_CONTROLTYPE_VOLUME
, yielding code like this (taken from here)The legacy mixer API can be difficult to use. I'd recommend using the WASAPI API.
WASAPI - http://msdn.microsoft.com/en-us/library/dd371455(v=VS.85).aspx
Here.