// SoundCtl.cpp : Implementation of CSoundCtl #include "stdafx.h" #include "Sndctl.h" #include "SoundCtl.h" #define SND_VALUE_MAX 0xffff //const DWORD gc_dwSoundTarget = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; //*************************************************************************************** MMRESULT CSoundCtl::AdjustLineVolume(HMIXEROBJ hmx, MIXERCONTROL *pmxctrl, DWORD cChannels, DWORD dwValue) { if (dwValue > SND_VALUE_MAX) return MIXERR_INVALVALUE; MIXERCONTROLDETAILS mxcd; BYTE data[64]; MIXERCONTROLDETAILS_UNSIGNED *pVolumeLeft, *pVolumeRight; MMRESULT mmResult; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.cChannels = cChannels; mxcd.dwControlID = pmxctrl->dwControlID; mxcd.cMultipleItems = pmxctrl->cMultipleItems; // should be 0! mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = (LPVOID)data; // 1st long=left channel, 2nd long=right channel mmResult = mixerGetControlDetails(hmx, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE); if (mmResult != MMSYSERR_NOERROR) return mmResult; pVolumeLeft = (MIXERCONTROLDETAILS_UNSIGNED *)data; pVolumeRight = pVolumeLeft + 1; DWORD dwMin = pmxctrl->Bounds.dwMinimum; DWORD dwMax = pmxctrl->Bounds.dwMaximum; // dwValue is a volume expressed on the scale 0..SND_VALUE_MAX. Map this linearly // to the scale dwMin..dwMax DWORD dwDesiredVolume = dwMin + ((dwMax-dwMin)*dwValue)/SND_VALUE_MAX; pVolumeLeft->dwValue = dwDesiredVolume; pVolumeRight->dwValue = dwDesiredVolume; return mixerSetControlDetails(hmx, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE); } //*************************************************************************************** MMRESULT CSoundCtl::AdjustLineMute(HMIXEROBJ hmx, MIXERCONTROL *pmxctrl, DWORD cChannels, DWORD dwValue) { MIXERCONTROLDETAILS mxcd; BYTE data[64]; MIXERCONTROLDETAILS_BOOLEAN *pMute; MMRESULT mmResult; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.cChannels = 1; // mixerGetControlDetails fails if this is cChannels mxcd.dwControlID = pmxctrl->dwControlID; mxcd.cMultipleItems = pmxctrl->cMultipleItems; // should be 0! mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = (LPVOID)data; // 1st bool=mute left, 2nd bool=mute right mmResult = mixerGetControlDetails(hmx, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE); if (mmResult != MMSYSERR_NOERROR) return mmResult; pMute = (MIXERCONTROLDETAILS_BOOLEAN *)data; pMute->fValue = dwValue; return mixerSetControlDetails(hmx, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE); } //*************************************************************************************** MMRESULT CSoundCtl::AdjustLine(HMIXEROBJ hmx, MIXERLINE *pmxl, DWORD dwControlType, DWORD dwValue) { MMRESULT mmResult = MMSYSERR_NOERROR; switch (pmxl->dwComponentType) { // TBD: Only handling volume level output for these destinations from mixer! // Currently hardcoded. case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS: case MIXERLINE_COMPONENTTYPE_DST_MONITOR: case MIXERLINE_COMPONENTTYPE_DST_HEADPHONES: case MIXERLINE_COMPONENTTYPE_DST_DIGITAL: case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT: case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC: case MIXERLINE_COMPONENTTYPE_SRC_ANALOG: case MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY: case MIXERLINE_COMPONENTTYPE_SRC_LINE: case MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED: case MIXERLINE_COMPONENTTYPE_SRC_DIGITAL: case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE: case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER: case MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE: case MIXERLINE_COMPONENTTYPE_SRC_PCSPEAKER: MIXERLINECONTROLS mxlc; MIXERCONTROL amxctrl[10]; mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = pmxl->dwLineID; mxlc.cControls = pmxl->cControls; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = amxctrl; MMRESULT mmResult; mmResult = mixerGetLineControls((hmx),(LPMIXERLINECONTROLS)&mxlc, MIXER_GETLINECONTROLSF_ALL); if ( mmResult != MMSYSERR_NOERROR ) return mmResult; DWORD iCtrl; for (iCtrl=0; iCtrl< pmxl->cControls; iCtrl++ ) { if (amxctrl[iCtrl].dwControlType == dwControlType) { switch (dwControlType) { case MIXERCONTROL_CONTROLTYPE_VOLUME: return AdjustLineVolume(hmx, &amxctrl[iCtrl], pmxl->cChannels, dwValue); case MIXERCONTROL_CONTROLTYPE_MUTE: return AdjustLineMute(hmx, &amxctrl[iCtrl], pmxl->cChannels, dwValue); default: return MIXERR_INVALCONTROL; } } } // Couldn't find a control of the desired type in this line return MIXERR_INVALCONTROL; default: // We don't yet support changing volume on this type of line return MIXERR_INVALLINE; } // This statement is unreachable return MIXERR_INVALLINE; } //**************************************************************************************** MMRESULT CSoundCtl::AdjustSound(DWORD dwComponentType, DWORD dwControlType, DWORD dwValue) { UINT nMixers = mixerGetNumDevs(); if ( nMixers == 0 ) { return MMSYSERR_NOERROR; } // Is the component we are changing parameters for one of the destinations of the // mixer? bool bComponentIsDestType = false; if (dwComponentType > MIXERLINE_COMPONENTTYPE_DST_FIRST && dwComponentType <= MIXERLINE_COMPONENTTYPE_DST_LAST) { bComponentIsDestType = true; } for ( UINT iMixer=0; iMixer