int Px_GetCurrentInputSource( PxMixer *mixer ) { PxInfo *info = (PxInfo *)mixer; MIXERCONTROLDETAILS details; MIXERCONTROLDETAILS_BOOLEAN flags[32]; MMRESULT result; int i; details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = info->muxID; details.cMultipleItems = info->numInputs; details.cChannels = 1; details.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); details.paDetails = (LPMIXERCONTROLDETAILS_BOOLEAN)&flags[0]; result = mixerGetControlDetails(info->hInputMixer, (LPMIXERCONTROLDETAILS)&details, MIXER_GETCONTROLDETAILSF_VALUE); if (result == MMSYSERR_NOERROR) { for(i=0; i<info->numInputs; i++) if (flags[i].fValue) return i; } return 0; }
DWORD CVolumeOutMaster::GetCurrentVolume() { if ( !m_bAvailable ) return BAD_DWORD; MIXERCONTROLDETAILS_UNSIGNED* aDetails = (MIXERCONTROLDETAILS_UNSIGNED*)malloc(m_nChannelCount*sizeof(MIXERCONTROLDETAILS_UNSIGNED)); if ( !aDetails ) return BAD_DWORD; MIXERCONTROLDETAILS ControlDetails; memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) ); ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS); ControlDetails.dwControlID = m_dwVolumeControlID; ControlDetails.cChannels = m_nChannelCount; ControlDetails.cMultipleItems = 0; ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); ControlDetails.paDetails = &aDetails[0]; MMRESULT mmResult = mixerGetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, MIXER_GETCONTROLDETAILSF_VALUE ); DWORD dw = aDetails[0].dwValue; free( aDetails ); if ( mmResult != MMSYSERR_NOERROR ) { ssi_wrn (".MasterOutputVolume: FAILURE: Could not get volume. mmResult=%d\n", mmResult ); return BAD_DWORD; } return dw; }
/* ------------------------------------------------------------------------------------ */ BOOL CMixer::SetControlValue(DWORD dw) { if(!m_bSuccess) return m_bSuccess; m_bSuccess = FALSE; MIXERCONTROLDETAILS mxcd; MIXERCONTROLDETAILS_UNSIGNED mxcd_u; mxcd.cbStruct = sizeof(mxcd); mxcd.dwControlID = m_iMixerControlID; mxcd.cChannels = m_dwChannels; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(mxcd_u); mxcd.paDetails = &mxcd_u; mmr = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(m_HMixer), &mxcd, 0L); if(MMSYSERR_NOERROR != mmr) return m_bSuccess; mxcd_u.dwValue = dw; mmr = mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(m_HMixer), &mxcd, 0L); if(MMSYSERR_NOERROR != mmr) return m_bSuccess; m_bSuccess = TRUE; return m_bSuccess; }
void VolumeFunction(HMIXEROBJ hMixer, DWORD controlID, PxVolume *volume) { MIXERCONTROLDETAILS details; MMRESULT result; unsigned short value = 0; details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = controlID; details.cChannels = 1; /* all channels */ details.cMultipleItems = 0; details.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); details.paDetails = &value; result = mixerGetControlDetails(hMixer, &details, MIXER_GETCONTROLDETAILSF_VALUE); if (*volume < 0.0) { *volume = (PxVolume)(value / 65535.0); } else { if (result != MMSYSERR_NOERROR) return; value = (unsigned short)(*volume * 65535.0); mixerSetControlDetails(hMixer, &details, MIXER_GETCONTROLDETAILSF_VALUE); } }
BOOL mixer_manipulate_mute(int channel, BOOL get, LPBOOL mute) { MIXERCONTROLDETAILS_BOOLEAN details; MIXERCONTROLDETAILS mcd; details.fValue = *mute; if (s_mutes.count == 0) return (FALSE); if (channel < 0 || channel >= s_mutes.count) return (FALSE); mcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mcd.dwControlID = s_mutes.mixers[channel].dwControlID; mcd.cChannels = 1; mcd.cMultipleItems = 0; mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mcd.paDetails = &details; if (get) { CHECK_MMRETURN(mixerGetControlDetails((HMIXEROBJ)s_hMixer, &mcd, MIXER_GETCONTROLDETAILSF_VALUE)); } else { CHECK_MMRETURN(mixerSetControlDetails((HMIXEROBJ)s_hMixer, &mcd, MIXER_SETCONTROLDETAILSF_VALUE)); } *mute = details.fValue; return (TRUE); }
bool Win32RedBookDevice::getVolume(F32 * volume) { if(!mAcquired) { setLastError("Device has not been acquired"); return(false); } if(!mVolumeInitialized) { setLastError("Volume failed to initialize"); return(false); } U32 vol = 0; if(mUsingMixer) { mixerGetControlDetails(mVolumeDeviceId, &mMixerVolumeDetails, MIXER_GETCONTROLDETAILSF_VALUE); vol = mMixerVolumeValue.dwValue; } else auxGetVolume(mAuxVolumeDeviceId, (unsigned long *)&vol); vol &= 0xffff; *volume = F32(vol) / 65535.f; setLastError(""); return(true); }
BOOL mixer_manipulate_volume(int channel, BOOL get, LPDWORD left, LPDWORD right) { MIXERCONTROLDETAILS_UNSIGNED details[2]; MIXERCONTROLDETAILS mcd; details[0].dwValue = *left; details[1].dwValue = *right; if (s_lines.count == 0) return (FALSE); if (channel < 0 || channel >= s_lines.count) return (FALSE); mcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mcd.dwControlID = s_lines.mixers[channel].dwControlID; mcd.cChannels = 2; mcd.cMultipleItems = 0; mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mcd.paDetails = &details; if (get) { CHECK_MMRETURN(mixerGetControlDetails((HMIXEROBJ)s_hMixer, &mcd, MIXER_GETCONTROLDETAILSF_VALUE)); } else { CHECK_MMRETURN(mixerSetControlDetails((HMIXEROBJ)s_hMixer, &mcd, MIXER_SETCONTROLDETAILSF_VALUE)); } *left = details[0].dwValue; *right = details[1].dwValue; return (TRUE); }
float CMicVolume::VolDevice(MCS *pData) { int nCnt = 1; //컨트롤수 float temp = 0; //임시 if(MIXERCONTROL_CONTROLF_MULTIPLE & pData->m_ctlMixerSpeaker.fdwControl) nCnt = pData->m_ctlMixerSpeaker.cMultipleItems; MIXERCONTROLDETAILS_UNSIGNED mixer_control_details_unsigned[10]; MIXERCONTROLDETAILS mixer_control_details; mixer_control_details.cbStruct = sizeof(MIXERCONTROLDETAILS); mixer_control_details.dwControlID = pData->m_ctlMixerSpeaker.dwControlID; mixer_control_details.cChannels = 1; mixer_control_details.cMultipleItems = pData->m_ctlMixerSpeaker.cMultipleItems; mixer_control_details.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mixer_control_details.paDetails = mixer_control_details_unsigned; if(mixerGetControlDetails((HMIXEROBJ)h_mix, &mixer_control_details, MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) { #ifdef _DEBUG MessageBox(NULL,"내부함수 오류(mixerGetControlDetails)", "내부 함수 오류", MB_ICONSTOP); #endif return -1; } for(int i = 0; i < nCnt; i++){ temp = ((float)mixer_control_details_unsigned[i].dwValue * (float)pData->nMax + 65535 /2) / 65535; } return temp; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //agenttype_mixer_notify //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void agenttype_mixer_notify_xp (agent *a, int notifytype, void *messagedata) { //Get the agent details AgentType_Mixer_XP * details = static_cast<AgentType_Mixer_XP *>(a->agentdetails); //Variables double *value_double = NULL; bool *value_bool = NULL; MIXERCONTROLDETAILS_UNSIGNED mixer_setcontrol_value_double; MIXERCONTROLDETAILS_BOOLEAN mixer_setcontrol_value_bool; switch (notifytype) { case NOTIFY_CHANGE: { //Set up the values if (a->agenttypeptr->format & CONTROL_FORMAT_SCALE) { value_double = (double *) messagedata; details->m_mixer_controldetails.paDetails = &mixer_setcontrol_value_double; } else if (a->agenttypeptr->format & CONTROL_FORMAT_BOOL) { value_bool = (bool *) messagedata; details->m_mixer_controldetails.paDetails = &mixer_setcontrol_value_bool; } //Retrieve the details if (MMSYSERR_NOERROR != mixerGetControlDetails((HMIXEROBJ) details->m_mixer_handle, &details->m_mixer_controldetails, MIXER_GETCONTROLDETAILSF_VALUE)) return; //Set the value if (a->agenttypeptr->format & CONTROL_FORMAT_SCALE) { mixer_setcontrol_value_double.dwValue = (ULONG) (*value_double * 65535); } else if (a->agenttypeptr->format & CONTROL_FORMAT_BOOL) { mixer_setcontrol_value_bool.fValue = *value_bool; } //Reload the details MMRESULT const res = mixerSetControlDetails((HMIXEROBJ) details->m_mixer_handle, &details->m_mixer_controldetails, MIXER_SETCONTROLDETAILSF_VALUE); if (MMSYSERR_NOERROR != res) return; break; } case NOTIFY_SAVE_AGENT: //Write existance char temp[30]; sprintf(temp, "%d %d %d", (int)details->m_device, (int)details->m_line, (int)details->m_control); config_write(config_get_control_setagent_c(a->controlptr, a->agentaction, a->agenttypeptr->agenttypename, temp)); break; } }
//--------------------------------------------------------------------------- unsigned int CMyVolumeCtrl::vGetVolumeValue(HMIXER hmixer ,MIXERCONTROL *mxc) { MIXERCONTROLDETAILS mxcd; MIXERCONTROLDETAILS_UNSIGNED vol; vol.dwValue=0; mxcd.hwndOwner = 0; mxcd.cbStruct = sizeof(mxcd); mxcd.dwControlID = mxc-> dwControlID; mxcd.cbDetails = sizeof(vol); mxcd.paDetails = &vol; mxcd.cChannels = 1; if(mixerGetControlDetails((HMIXEROBJ)hmixer, &mxcd, MIXER_OBJECTF_HMIXER|MIXER_GETCONTROLDETAILSF_VALUE)) return -1; return vol.dwValue; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //agenttype_mixer_getdata //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void * agenttype_mixer_getdata_xp (agent *a, int datatype) { MIXERCONTROLDETAILS_UNSIGNED mixer_setcontrol_value_double; MIXERCONTROLDETAILS_BOOLEAN mixer_setcontrol_value_bool; AgentType_Mixer_XP * details = static_cast<AgentType_Mixer_XP *>(a->agentdetails); if (!details) return NULL; switch (datatype) { case DATAFETCH_VALUE_TEXT: case DATAFETCH_VALUE_SCALE: case DATAFETCH_VALUE_BOOL: //Set up the values if (datatype == DATAFETCH_VALUE_BOOL) { details->m_mixer_controldetails.paDetails = &mixer_setcontrol_value_bool; } else { details->m_mixer_controldetails.paDetails = &mixer_setcontrol_value_double; } //Retrieve the details if (MMSYSERR_NOERROR != mixerGetControlDetails((HMIXEROBJ) details->m_mixer_handle, &details->m_mixer_controldetails, MIXER_GETCONTROLDETAILSF_VALUE)) return NULL; //Get and return the value if (datatype == DATAFETCH_VALUE_SCALE || datatype == DATAFETCH_VALUE_TEXT) { details->m_value_double = mixer_setcontrol_value_double.dwValue / 65535.0; if (details->m_value_double < 0.0) details->m_value_double = 0.0; if (details->m_value_double > 1.0) details->m_value_double = 1.0; //Return if it is the simple double value if (datatype == DATAFETCH_VALUE_SCALE) return &(details->m_value_double); //Otherwise, it must be text int intvalue = 100 * (details->m_value_double); sprintf(mixer_outputbuffer, "%d%%", intvalue); return mixer_outputbuffer; } else if (datatype == DATAFETCH_VALUE_BOOL) { details->m_value_bool = (!!mixer_setcontrol_value_bool.fValue); return &(details->m_value_bool); } } return NULL; }
//--------------------------------------------------------------------------- long CMyVolumeCtrl::vGetMuteValue(HMIXER hmixer ,MIXERCONTROL *mxc) { MIXERCONTROLDETAILS mxcd; MIXERCONTROLDETAILS_BOOLEAN mxcdMute; mxcd.hwndOwner = 0; mxcd.cbStruct = sizeof(mxcd); mxcd.dwControlID = mxc-> dwControlID; mxcd.cbDetails = sizeof(mxcdMute); mxcd.paDetails = &mxcdMute; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; if (mixerGetControlDetails((HMIXEROBJ)hmixer, &mxcd,MIXER_OBJECTF_HMIXER|MIXER_GETCONTROLDETAILSF_VALUE)) return -1; return mxcdMute.fValue; }
bool PortAudioInput::GetMicrophoneLevel(DWORD* dwLevel) { MMRESULT mmresult; MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = m_dwCntlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = &mxcdVolume; mmresult = mixerGetControlDetails(reinterpret_cast<HMIXEROBJ>(m_mixerMic), &mxcd, MIXER_GETCONTROLDETAILSF_VALUE); if (mmresult != MMSYSERR_NOERROR) return false; *dwLevel = mxcdVolume.dwValue; return true; }
INT SndMixerGetVolumeControlDetails(PSND_MIXER Mixer, DWORD dwControlID, DWORD cbDetails, LPVOID paDetails) { MIXERCONTROLDETAILS MixerDetails; if (Mixer->hmx) { MixerDetails.cbStruct = sizeof(MIXERCONTROLDETAILS); MixerDetails.dwControlID = dwControlID; MixerDetails.cChannels = 1; //FIXME MixerDetails.cMultipleItems = 0; MixerDetails.cbDetails = cbDetails; MixerDetails.paDetails = paDetails; if (mixerGetControlDetails((HMIXEROBJ)Mixer->hmx, &MixerDetails, MIXER_GETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER) == MMSYSERR_NOERROR) { return 1; } } return -1; }
bool CVolumeOutMaster::isMute() { MMRESULT mmResult; MIXERCONTROL Control; memset( &Control, 0, sizeof(MIXERCONTROL) ); Control.cbStruct = sizeof(MIXERCONTROL); MIXERLINECONTROLS LineControls; memset( &LineControls, 0, sizeof(MIXERLINECONTROLS) ); LineControls.cbStruct = sizeof(MIXERLINECONTROLS); LineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; LineControls.dwLineID = m_dwLineID; LineControls.cControls = 1; LineControls.cbmxctrl = sizeof(MIXERCONTROL); LineControls.pamxctrl = &Control; mmResult = mixerGetLineControls( (HMIXEROBJ)m_dwMixerHandle, &LineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE ); if ( !m_bAvailable ) return false; MIXERCONTROLDETAILS_BOOLEAN* aDetails = (MIXERCONTROLDETAILS_BOOLEAN*)malloc(m_nChannelCount*sizeof(MIXERCONTROLDETAILS_BOOLEAN)); if ( !aDetails ) return false; MIXERCONTROLDETAILS mcd; memset( &mcd, 0, sizeof(MIXERCONTROLDETAILS) ); mcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mcd.dwControlID = Control.dwControlID; mcd.cChannels = m_nChannelCount; mcd.cMultipleItems = 0; mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mcd.paDetails = &aDetails[0]; mmResult = mixerGetControlDetails((HMIXEROBJ)m_dwMixerHandle, &mcd, MIXER_GETCONTROLDETAILSF_VALUE); if(aDetails[0].fValue == 1) return true; return false; }
static PxVolume VolumeFunction(HMIXEROBJ hMixer, DWORD controlID, PxVolume volume) { MIXERCONTROLDETAILS details; MMRESULT result; MIXERCONTROLDETAILS_UNSIGNED value; if (hMixer == NULL) { return -1.0; } memset(&value, 0, sizeof(MIXERCONTROLDETAILS_UNSIGNED)); details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = controlID; details.cChannels = 1; /* all channels */ details.cMultipleItems = 0; details.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); details.paDetails = &value; if (volume < 0.0) { result = mixerGetControlDetails(hMixer, &details, MIXER_GETCONTROLDETAILSF_VALUE); if (result != MMSYSERR_NOERROR) return -1.0; return (PxVolume)(value.dwValue / 65535.0); } value.dwValue = (unsigned short)(volume * 65535.0); result = mixerSetControlDetails(hMixer, &details, MIXER_GETCONTROLDETAILSF_VALUE); if (result != MMSYSERR_NOERROR) return -1.0; return 0.0; }
VOID GetMuteState(PGLOBAL_DATA pGlobalData) { MIXERCONTROLDETAILS_BOOLEAN mxcdMute; MIXERCONTROLDETAILS mxcd; if (pGlobalData->hMixer == NULL) return; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = pGlobalData->muteControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = &mxcdMute; if (mixerGetControlDetails((HMIXEROBJ)pGlobalData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) return; pGlobalData->muteVal = mxcdMute.fValue; }
VOID GetVolumeValue(PGLOBAL_DATA pGlobalData) { MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; MIXERCONTROLDETAILS mxcd; if (pGlobalData->hMixer == NULL) return; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = pGlobalData->volumeControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = &mxcdVolume; if (mixerGetControlDetails((HMIXEROBJ)pGlobalData->hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) return; pGlobalData->volumeValue = mxcdVolume.dwValue; }
long CMixer::GetPan() { if (!m_bOK || m_dwControlPID==0) return 0; HMIXER hMixer; HRESULT hr; hr = mixerOpen(&hMixer, 0, 0, 0, 0); if (FAILED(hr)) return 0; MIXERCONTROLDETAILS mxcd; MIXERCONTROLDETAILS_SIGNED mxdu; mxcd.cMultipleItems = 0; mxcd.cChannels = 1; mxcd.cbStruct = sizeof(mxcd); mxcd.dwControlID = m_dwControlPID; mxcd.cbDetails = sizeof(mxdu); mxcd.paDetails = &mxdu; hr = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE); mixerClose(hMixer); return mxdu.lValue; }
BOOL LevelChange(WPARAM wParam, LPARAM lParam) { if (mixer.pmxcd == NULL) return FALSE; if (lParam == mixer.pmxcd->dwControlID) { // Get the value mixerGetControlDetails((HMIXEROBJ)mixer.hmx, mixer.pmxcd, MIXER_GETCONTROLDETAILSF_VALUE); // Set the slider int value = MAX_VOL - (mixer.pmxcdu->dwValue * (MAX_VOL - MIN_VOL) / (mixer.pmxc->Bounds.dwMaximum - mixer.pmxc->Bounds.dwMinimum)); SendMessage(level.hwnd, TBM_SETPOS, TRUE, value); } return TRUE; }
void CMixerControl::_RefreshStrings() { if(!(m_mc.fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE)) return; // We are guaranteed here that the control is a multiple-item control, // and therefore we're "ok to go" as ellie would say from Contact. MIXERCONTROLDETAILS mcd = {0}; mcd.cbStruct = sizeof(mcd); mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT); mcd.dwControlID = m_mc.dwControlID; mcd.cChannels = (m_mc.fdwControl & MIXERCONTROL_CONTROLF_UNIFORM) ? 1 : m_ml.cChannels; mcd.cMultipleItems = m_mc.cMultipleItems; mcd.paDetails = m_pStrings; if(MMSYSERR_NOERROR != mixerGetControlDetails((HMIXEROBJ)m_hMixer, &mcd, MIXER_GETCONTROLDETAILSF_LISTTEXT)) { //DebugBreak(); return; } return; }
BOOL AudioInput::SetMicrPhoneVolume(DWORD dwVolume) { BOOL bResult = FALSE; try { int mixerNum = (int)mixerGetNumDevs(); for(int i = 0; i < mixerNum; i ++) { DWORD dwSource = 0; HMIXER m_hMixer = NULL; MMRESULT mr = NULL; //打开Mixer设备 if(mixerOpen(&m_hMixer, i, 0, 0, MIXER_OBJECTF_MIXER) != MMSYSERR_NOERROR) continue; MIXERLINE MixerLine; //结构体的大小 MixerLine.cbStruct = sizeof(MixerLine); //录制设备总线 MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; //得到录制总线中的连接数 if(mixerGetLineInfo((HMIXEROBJ)m_hMixer, &MixerLine, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR) continue; //将连接数保存 DWORD dwConnections = MixerLine.cConnections; //准备获取麦克风设备的ID DWORD dwLineID = 0; for(DWORD i = 0; i < dwConnections; i++ ) { //枚举每一个设备,当Source的ID等于当前的迭代记数 MixerLine.dwSource = i; //根据SourceID获得连接的信息 if(mixerGetLineInfo((HMIXEROBJ)m_hMixer, &MixerLine, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE) != MMSYSERR_NOERROR) //判断函数执行错误 break; //如果当前设备类型是麦克风,则跳出循环。 if(MixerLine.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) { dwLineID = MixerLine.dwLineID; dwSource = MixerLine.dwSource; break; } } //如果没有找到,返回失败。 if(dwLineID == 0) continue; //get line id of destination line MIXERLINE lineinfo_Dest; ::ZeroMemory(&lineinfo_Dest, sizeof(MIXERLINE)); lineinfo_Dest.cbStruct = sizeof(MIXERLINE); lineinfo_Dest.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; if(::mixerGetLineInfo( (HMIXEROBJ)m_hMixer, &lineinfo_Dest, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR) continue; //get id of specified connector MIXERLINE lineinfo_Connector; ::ZeroMemory(&lineinfo_Connector, sizeof(MIXERLINE)); lineinfo_Connector.cbStruct = sizeof(MIXERLINE); lineinfo_Connector.dwDestination = lineinfo_Dest.dwLineID; lineinfo_Connector.dwSource = dwSource; if(::mixerGetLineInfo( (HMIXEROBJ)m_hMixer, &lineinfo_Connector, MIXER_GETLINEINFOF_SOURCE) != MMSYSERR_NOERROR) continue; MIXERCONTROL mxc; MIXERLINECONTROLS mxlc; mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = lineinfo_Connector.dwLineID; mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; mxlc.cControls = 1; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = &mxc; if(::mixerGetLineControls( reinterpret_cast<HMIXEROBJ>(m_hMixer), &mxlc, MIXER_OBJECTF_HMIXER|MIXER_GETLINECONTROLSF_ONEBYTYPE)!= MMSYSERR_NOERROR) continue; //get volume value range now 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; if(mixerGetControlDetails( reinterpret_cast<HMIXEROBJ>(m_hMixer), &mxcd, MIXER_GETCONTROLDETAILSF_VALUE)!= MMSYSERR_NOERROR) continue; //set volume MIXERCONTROLDETAILS_UNSIGNED mxcdVolume_Set = { mxc.Bounds.dwMaximum * dwVolume / 255 }; MIXERCONTROLDETAILS mxcd_Set; mxcd_Set.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd_Set.dwControlID = mxc.dwControlID; mxcd_Set.cChannels = 1; mxcd_Set.cMultipleItems = 0; mxcd_Set.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd_Set.paDetails = &mxcdVolume_Set; if(mixerSetControlDetails(reinterpret_cast<HMIXEROBJ>(m_hMixer), &mxcd_Set, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) continue; ::mixerClose(m_hMixer); m_hMixer = NULL; bResult = TRUE;; } } catch(...){ return FALSE; } return bResult; }
/* ============ CDAudio_AccessVolume JDH: get/set CD volume (code adpated from cd_player.c in avp package at icculus.org) ============ */ void CDAudio_AccessVolume (float *vol, CDDA_OP op) { int numDevs, i; HMIXEROBJ hMixer; MIXERLINEA line; MIXERLINECONTROLSA lineControls; MIXERCONTROL control; MIXERCONTROLDETAILS details; MIXERCONTROLDETAILS_UNSIGNED detailValue; DWORD range; numDevs = mixerGetNumDevs (); for (i = 0; i < numDevs; i++) { if (mixerOpen ((HMIXER *)&hMixer, i, 0, 0, MIXER_OBJECTF_MIXER) != MMSYSERR_NOERROR) continue; line.cbStruct = sizeof(MIXERLINE); line.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; if (mixerGetLineInfoA (hMixer, &line, MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR) { control.cbStruct = sizeof(MIXERCONTROL); lineControls.cbStruct = sizeof(MIXERLINECONTROLS); lineControls.dwLineID = line.dwLineID; lineControls.pamxctrl = &control; lineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; lineControls.cControls = 1; lineControls.cbmxctrl = sizeof(MIXERCONTROL); if (mixerGetLineControlsA (hMixer, &lineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR) { details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = control.dwControlID; details.cChannels = 1; details.cMultipleItems = 0; details.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); details.paDetails = &detailValue; range = control.Bounds.dwMaximum - control.Bounds.dwMinimum; if (op == CDDA_SETVOL) { detailValue.dwValue = control.Bounds.dwMinimum + (*vol * range); mixerSetControlDetails (hMixer, &details, MIXER_SETCONTROLDETAILSF_VALUE); } else { mixerGetControlDetails (hMixer, &details, MIXER_GETCONTROLDETAILSF_VALUE); *vol = (float)(detailValue.dwValue - control.Bounds.dwMinimum) / range; } mixerClose ((HMIXER) hMixer); return; } } mixerClose ((HMIXER) hMixer); } }
int iKX::mixer(int op,int j,int channel,int *ret) { int res=-10; dword val[2]={0,0}; if(j<0 || j>=KX_MIXER_LAST) { debug("iKX mixer: incorrect call [op=%d j=%d chn=%d]\n",op,j,channel); return -1; } HMIXER mixer=0; // open mixer for(int ttt=0;ttt<KX_MAX_WAVE_DEVICES;ttt++) { switch(j) { case KX_MIXER_WAVE23: case KX_MIXER_WAVE23_MUTE: ttt=1; break; case KX_MIXER_WAVE45: case KX_MIXER_WAVE45_MUTE: ttt=2; break; case KX_MIXER_WAVE67: case KX_MIXER_WAVE67_MUTE: ttt=3; break; case KX_MIXER_WAVEHQ: case KX_MIXER_WAVEHQ_MUTE: ttt=4; break; } if(ttt==KX_MAX_WAVE_DEVICES-1) // 4; 'HQ' if(mixer_handler[ttt]==0) continue; /* if(mixerOpen(&mixer,mixer_num[ttt],0,0,MIXER_OBJECTF_MIXER)!=MMSYSERR_NOERROR) { debug("iKX mixer: mixerOpen failed [%x] #%d\n",GetLastError(),mixer_num[ttt]); strcpy(error_name,"error opening mixer"); return -2; } */ mixer=(HMIXER)mixer_handler[ttt]; if(!mixer) break; //-------- // MIXERCAPS mc; // mixerGetDevCaps(mixer_num[ttt],&mc,sizeof(mc)); // debug("****** -- %s: [ttt=%d; #=%d]\n",mc.szPname,ttt,mixer_num[ttt]); //-------- int id=-1; for(int cnt=0;cnt<20;cnt++) { MIXERLINECONTROLS lc; MIXERCONTROL mc; lc.cbStruct=sizeof(lc); lc.dwControlID=cnt; lc.cControls=1; lc.cbmxctrl=sizeof(mc); lc.pamxctrl=&mc; mc.cbStruct=sizeof(lc); MMRESULT rr=mixerGetLineControls((HMIXEROBJ)mixer,&lc,MIXER_GETLINECONTROLSF_ONEBYID); if(rr!=MMSYSERR_NOERROR) { // debug("ikX: mmsystem: bug: %x [%x] -- %d %d %d [cnt=%d]\n",GetLastError(),rr,j,mixer_handler[ttt],ttt,cnt); continue; } id=-1; // ---- // debug("(tmp) kxmixer: [%d] %s/%s [ttt=%d]; type: %x\n",cnt,mc.szName,mc.szShortName,ttt,mc.dwControlType); // ---- // all names correspond to GUIDs if((strcmp(mc.szName,_KX_MASTERV_NAME)==0) && (j==KX_MIXER_MASTER)) id=cnt; else if((strcmp(mc.szName,_KX_MASTERM_NAME)==0) && (j==KX_MIXER_MASTER_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_SYNTH1V_NAME)==0) && (j==KX_MIXER_SYNTH)) id=cnt; else if((strcmp(mc.szName,_KX_SYNTH1M_NAME)==0) && (j==KX_MIXER_SYNTH_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_RECINV_NAME)==0) && (j==KX_MIXER_REC)) id=cnt; else if((strcmp(mc.szName,_KX_RECINM_NAME)==0) && (j==KX_MIXER_REC_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_LINEIN_NAME)==0) && (j==KX_MIXER_LINEIN)) id=cnt; else if((strcmp(mc.szName,_KX_LINEIN_MUTE_NAME)==0) && (j==KX_MIXER_LINEIN_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_MICIN_NAME)==0) && (j==KX_MIXER_MICIN)) id=cnt; else if((strcmp(mc.szName,_KX_MICIN_MUTE_NAME)==0) && (j==KX_MIXER_MICIN_MUTE)) id=cnt; else { // these are usually translated by Windows into 'Volume' and 'Mute', // and coincide with 'CD Player' and 'SW Synth' controls... if((strcmp(mc.szName,_KX_WAVEV_NAME)==0) && (j==KX_MIXER_WAVE)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEM_NAME)==0) && (j==KX_MIXER_WAVE_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEV_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUT23V_NAME)==0) && (j==KX_MIXER_WAVE23)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEM_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUT23M_NAME)==0) && (j==KX_MIXER_WAVE23_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEV_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUT45V_NAME)==0) && (j==KX_MIXER_WAVE45)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEM_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUT45M_NAME)==0) && (j==KX_MIXER_WAVE45_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEV_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUT67V_NAME)==0) && (j==KX_MIXER_WAVE67)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEM_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUT67M_NAME)==0) && (j==KX_MIXER_WAVE67_MUTE)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEV_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUTHQV_NAME)==0) && (j==KX_MIXER_WAVEHQ)) id=cnt; else if((strcmp(mc.szName,_KX_WAVEM_NAME)==0 || strcmp(mc.szName,_KX_WAVEOUTHQM_NAME)==0) && (j==KX_MIXER_WAVEHQ_MUTE)) id=cnt; else if((strcmp(mc.szName,"Volume")==0) && (j==KX_MIXER_WAVE || j==KX_MIXER_WAVE23 || j==KX_MIXER_WAVE45 || j==KX_MIXER_WAVE67 || j==KX_MIXER_WAVEHQ)) id=cnt; else if((strcmp(mc.szName,"Mute")==0) && (j==KX_MIXER_WAVE_MUTE || j==KX_MIXER_WAVE23_MUTE || j==KX_MIXER_WAVE45_MUTE || j==KX_MIXER_WAVE67_MUTE || j==KX_MIXER_WAVEHQ_MUTE)) id=cnt; } if(id==-1) { // debug(" not found -- /* %s [%d] - %d */\n",mc.szName,j,cnt); // fight with localization stuff if(j==KX_MIXER_WAVE || j==KX_MIXER_WAVE23 || j==KX_MIXER_WAVE45 || j==KX_MIXER_WAVE67 || j==KX_MIXER_WAVEHQ) { // Wave Volume / Wave Mute have following ids: // Wave 0/1 device: 2,3 // Wave 2/3, 4/5, 6/7 devices: 0,1 if(ttt==0 && cnt==2) id=2; else if(ttt!=0 && cnt==0) id=0; else continue; } else if(j==KX_MIXER_WAVE_MUTE || j==KX_MIXER_WAVE23_MUTE || j==KX_MIXER_WAVE45_MUTE || j==KX_MIXER_WAVE67_MUTE || j==KX_MIXER_WAVEHQ_MUTE) { if(ttt==0 && cnt==3) id=3; else if(ttt!=0 && cnt==1) id=1; else continue; } else continue; } // debug("setting '%s' [%d; cnt=%d; ttt=%d]\n",mc.szName,j,cnt,ttt); MIXERCONTROLDETAILS dets; memset(&dets,0,sizeof(dets)); dets.cbStruct=sizeof(MIXERCONTROLDETAILS); dets.dwControlID=id; dets.cMultipleItems=0; dets.paDetails=&val; if(j==KX_MIXER_MASTER_MUTE || j==KX_MIXER_SYNTH_MUTE || j==KX_MIXER_WAVE_MUTE || j==KX_MIXER_WAVE23_MUTE || j==KX_MIXER_WAVE45_MUTE || j==KX_MIXER_WAVE67_MUTE || j==KX_MIXER_WAVEHQ_MUTE || j==KX_MIXER_LINEIN_MUTE || j==KX_MIXER_MICIN_MUTE || j==KX_MIXER_REC_MUTE) // mutes { dets.cbDetails=sizeof(MIXERCONTROLDETAILS_UNSIGNED)*2; dets.cChannels=1; } else { dets.cbDetails=sizeof(MIXERCONTROLDETAILS_UNSIGNED); dets.cChannels=2; } if(mixerGetControlDetails((HMIXEROBJ)mixer,&dets,MIXER_GETCONTROLDETAILSF_VALUE)!=MMSYSERR_NOERROR) { debug("iKX mixer: getcontroldetails failed [%x]\n",GetLastError()); // error // mixerClose(mixer); return -3; } if(op&KX_PROP_GET) { // mixerClose(mixer); if(channel==0) *ret=val[0]; else *ret=val[1]; return 0; } if(channel==0) val[0]=*ret; else val[1]=*ret; if(mixerSetControlDetails((HMIXEROBJ)mixer,&dets,MIXER_SETCONTROLDETAILSF_VALUE)!=MMSYSERR_NOERROR) { debug("iKX mixer: setcontroldetails failed [%x]\n",GetLastError()); // error // mixerClose(mixer); return -5; } // success -- next mixer res=0; break; } // for each control if(id==-1) // still not found { // debug("kxmixer: [warning] mixer api: control '%d' not found [ttt=%d]\n",j,ttt); } // mixerClose(mixer); if((j==KX_MIXER_REC)||(j==KX_MIXER_REC_MUTE)||(j==KX_MIXER_WAVE23)||(j==KX_MIXER_WAVE45)||(j==KX_MIXER_WAVE67)||(j==KX_MIXER_WAVEHQ) ||(j==KX_MIXER_WAVE23_MUTE)||(j==KX_MIXER_WAVE45_MUTE)||(j==KX_MIXER_WAVE67_MUTE)||(j==KX_MIXER_WAVEHQ_MUTE)) break; } // for each wave device [ttt] return res; }
static void mixer_test_controlA(HMIXER mix, LPMIXERCONTROLA control) { MMRESULT rc; if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) || (control->dwControlType == MIXERCONTROL_CONTROLTYPE_UNSIGNED)) { MIXERCONTROLDETAILS details; MIXERCONTROLDETAILS_UNSIGNED value; details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = control->dwControlID; details.cChannels = 1; U(details).cMultipleItems = 0; details.paDetails = &value; details.cbDetails = sizeof(value); /* read the current control value */ rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); if (rc==MMSYSERR_NOERROR && winetest_interactive) { MIXERCONTROLDETAILS new_details; MIXERCONTROLDETAILS_UNSIGNED new_value; trace(" Value=%d\n",value.dwValue); if (value.dwValue + control->Metrics.cSteps < S1(control->Bounds).dwMaximum) new_value.dwValue = value.dwValue + control->Metrics.cSteps; else new_value.dwValue = value.dwValue - control->Metrics.cSteps; new_details.cbStruct = sizeof(MIXERCONTROLDETAILS); new_details.dwControlID = control->dwControlID; new_details.cChannels = 1; U(new_details).cMultipleItems = 0; new_details.paDetails = &new_value; new_details.cbDetails = sizeof(new_value); /* change the control value by one step */ rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); if (rc==MMSYSERR_NOERROR) { MIXERCONTROLDETAILS ret_details; MIXERCONTROLDETAILS_UNSIGNED ret_value; ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS); ret_details.dwControlID = control->dwControlID; ret_details.cChannels = 1; U(ret_details).cMultipleItems = 0; ret_details.paDetails = &ret_value; ret_details.cbDetails = sizeof(ret_value); /* read back the new control value */ rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); if (rc==MMSYSERR_NOERROR) { /* result may not match exactly because of rounding */ ok(abs(ret_value.dwValue-new_value.dwValue)<=1, "Couldn't change value from %d to %d, returned %d\n", value.dwValue,new_value.dwValue,ret_value.dwValue); if (abs(ret_value.dwValue-new_value.dwValue)<=1) { details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = control->dwControlID; details.cChannels = 1; U(details).cMultipleItems = 0; details.paDetails = &value; details.cbDetails = sizeof(value); /* restore original value */ rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); } } } } } else if ((control->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) || (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BOOLEAN) || (control->dwControlType == MIXERCONTROL_CONTROLTYPE_BUTTON)) { MIXERCONTROLDETAILS details; MIXERCONTROLDETAILS_BOOLEAN value; details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = control->dwControlID; details.cChannels = 1; U(details).cMultipleItems = 0; details.paDetails = &value; details.cbDetails = sizeof(value); rc=mixerGetControlDetails((HMIXEROBJ)mix,&details,MIXER_GETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); if (rc==MMSYSERR_NOERROR && winetest_interactive) { MIXERCONTROLDETAILS new_details; MIXERCONTROLDETAILS_BOOLEAN new_value; trace(" Value=%d\n",value.fValue); if (value.fValue == FALSE) new_value.fValue = TRUE; else new_value.fValue = FALSE; new_details.cbStruct = sizeof(MIXERCONTROLDETAILS); new_details.dwControlID = control->dwControlID; new_details.cChannels = 1; U(new_details).cMultipleItems = 0; new_details.paDetails = &new_value; new_details.cbDetails = sizeof(new_value); /* change the control value by one step */ rc=mixerSetControlDetails((HMIXEROBJ)mix,&new_details,MIXER_SETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); if (rc==MMSYSERR_NOERROR) { MIXERCONTROLDETAILS ret_details; MIXERCONTROLDETAILS_BOOLEAN ret_value; ret_details.cbStruct = sizeof(MIXERCONTROLDETAILS); ret_details.dwControlID = control->dwControlID; ret_details.cChannels = 1; U(ret_details).cMultipleItems = 0; ret_details.paDetails = &ret_value; ret_details.cbDetails = sizeof(ret_value); /* read back the new control value */ rc=mixerGetControlDetails((HMIXEROBJ)mix,&ret_details,MIXER_GETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerGetControlDetails(MIXER_GETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); if (rc==MMSYSERR_NOERROR) { /* result may not match exactly because of rounding */ ok(ret_value.fValue==new_value.fValue, "Couldn't change value from %d to %d, returned %d\n", value.fValue,new_value.fValue,ret_value.fValue); if (ret_value.fValue==new_value.fValue) { details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = control->dwControlID; details.cChannels = 1; U(details).cMultipleItems = 0; details.paDetails = &value; details.cbDetails = sizeof(value); /* restore original value */ rc=mixerSetControlDetails((HMIXEROBJ)mix,&details,MIXER_SETCONTROLDETAILSF_VALUE); ok(rc==MMSYSERR_NOERROR,"mixerSetControlDetails(MIXER_SETCONTROLDETAILSF_VALUE): " "MMSYSERR_NOERROR expected, got %s\n", mmsys_error(rc)); } } } } } else { /* FIXME */ } }
PxMixer *Px_OpenMixer( void *pa_stream, int index ) { internalPortAudioStream *past; PaWMMEStreamData *wmmeStreamData; HWAVEIN hWaveIn; HWAVEOUT hWaveOut; PxInfo *mixer; MMRESULT result; MIXERLINE line; MIXERLINECONTROLS controls; MIXERCONTROL control; MIXERCONTROLDETAILS details; MIXERCONTROLDETAILS_LISTTEXT mixList[32]; int j; mixer = (PxMixer *)malloc(sizeof(PxInfo)); mixer->hInputMixer = NULL; mixer->hOutputMixer = NULL; past = (internalPortAudioStream *) pa_stream; wmmeStreamData = (PaWMMEStreamData *) past->past_DeviceData; hWaveIn = wmmeStreamData->hWaveIn; if (hWaveIn) { result = mixerOpen((HMIXER *)&mixer->hInputMixer, (UINT)hWaveIn, 0, 0, MIXER_OBJECTF_HWAVEIN); if (result != MMSYSERR_NOERROR) { free(mixer); return NULL; } } hWaveOut = wmmeStreamData->hWaveOut; if (hWaveOut) { result = mixerOpen((HMIXER *)&mixer->hOutputMixer, (UINT)hWaveOut, 0, 0, MIXER_OBJECTF_HWAVEOUT); if (result != MMSYSERR_NOERROR) { free(mixer); return NULL; } } mixer->numInputs = 0; mixer->muxID = 0; /* * Find the input source selector (mux or mixer) and * get the names and IDs of all of the input sources */ if (mixer->hInputMixer) { line.cbStruct = sizeof(MIXERLINE); line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; result = mixerGetLineInfo(mixer->hInputMixer, &line, MIXER_GETLINEINFOF_COMPONENTTYPE); if (result == MMSYSERR_NOERROR) { controls.cbStruct = sizeof(MIXERLINECONTROLS); controls.dwLineID = line.dwLineID; controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX; controls.cbmxctrl = sizeof(MIXERCONTROL); controls.pamxctrl = &control; control.cbStruct = sizeof(MIXERCONTROL); result = mixerGetLineControls(mixer->hInputMixer, &controls, MIXER_GETLINECONTROLSF_ONEBYTYPE); if (result != MMSYSERR_NOERROR) { controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER; result = mixerGetLineControls(mixer->hInputMixer, &controls, MIXER_GETLINECONTROLSF_ONEBYTYPE); } if (result == MMSYSERR_NOERROR) { mixer->numInputs = control.cMultipleItems; mixer->muxID = control.dwControlID; details.cbStruct = sizeof(MIXERCONTROLDETAILS); details.dwControlID = mixer->muxID; details.cChannels = 1; details.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT); details.paDetails = (LPMIXERCONTROLDETAILS_LISTTEXT)&mixList[0]; details.cMultipleItems = mixer->numInputs; result = mixerGetControlDetails(mixer->hInputMixer, (LPMIXERCONTROLDETAILS)&details, MIXER_GETCONTROLDETAILSF_LISTTEXT); if (result != MMSYSERR_NOERROR) mixer->numInputs = 0; for(j=0; j<mixer->numInputs; j++) { mixer->src[j].lineID = mixList[j].dwParam1; strcpy(mixer->src[j].name, mixList[j].szName); } } /* * We've found the names - now we need to find the volume * controls for each one */ for(j=0; j<mixer->numInputs; j++) { controls.cbStruct = sizeof(MIXERLINECONTROLS); controls.dwLineID = mixer->src[j].lineID; controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; controls.cbmxctrl = sizeof(MIXERCONTROL); controls.pamxctrl = &control; control.cbStruct = sizeof(MIXERCONTROL); result = mixerGetLineControls(mixer->hInputMixer, &controls, MIXER_GETLINECONTROLSF_ONEBYTYPE); if (result == MMSYSERR_NOERROR) mixer->src[j].controlID = control.dwControlID; else mixer->src[j].controlID = 0; } } } /* * Find the ID of the output speaker volume control */ mixer->speakerID = 0; if (mixer->hOutputMixer) { line.cbStruct = sizeof(MIXERLINE); line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; result = mixerGetLineInfo(mixer->hOutputMixer, &line, MIXER_GETLINEINFOF_COMPONENTTYPE); if (result == MMSYSERR_NOERROR) { controls.cbStruct = sizeof(MIXERLINECONTROLS); controls.dwLineID = line.dwLineID; controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; controls.cbmxctrl = sizeof(MIXERCONTROL); controls.pamxctrl = &control; control.cbStruct = sizeof(MIXERCONTROL); result = mixerGetLineControls(mixer->hInputMixer, &controls, MIXER_GETLINECONTROLSF_ONEBYTYPE); if (result == MMSYSERR_NOERROR) mixer->speakerID = control.dwControlID; } } return (PxMixer *)mixer; }
int mixer4i(int device, int action, int control, int parm) { MIXERCONTROLDETAILS ctrlDetails; MIXERCONTROLDETAILS_UNSIGNED mcdUnsigned[2]; MIXERCONTROL *mctrl; MIXERLINE *mline; mixerdata_t *mix; int i; if(!initMixerOk) return MIX_ERROR; // This is quite specific at the moment. // Only allow setting the CD volume. if(device != MIX_CDAUDIO && device != MIX_MIDI) return MIX_ERROR; if(control != MIX_VOLUME) return MIX_ERROR; // Choose the mixer line. mix = (device == MIX_CDAUDIO ? &mixCD : &mixMidi); // Is the mixer line for the requested device available? if(!mix->available) return MIX_ERROR; mline = &mix->line; mctrl = &mix->volume; // Init the data structure. memset(&ctrlDetails, 0, sizeof(ctrlDetails)); ctrlDetails.cbStruct = sizeof(ctrlDetails); ctrlDetails.dwControlID = mctrl->dwControlID; ctrlDetails.cChannels = 1; //mline->cChannels; ctrlDetails.cbDetails = sizeof(mcdUnsigned); ctrlDetails.paDetails = &mcdUnsigned; switch(action) { case MIX_GET: res = mixerGetControlDetails((HMIXEROBJ) mixer, &ctrlDetails, MIXER_GETCONTROLDETAILSF_VALUE); if(res != MMSYSERR_NOERROR) return MIX_ERROR; // The bigger one is the real volume. i = mcdUnsigned[mcdUnsigned[0].dwValue > mcdUnsigned[1].dwValue ? 0 : 1].dwValue; // Return the value in range 0-255. return (255 * (i - mctrl->Bounds.dwMinimum)) / (mctrl->Bounds.dwMaximum - mctrl->Bounds.dwMinimum); case MIX_SET: // Clamp it. if(parm < 0) parm = 0; if(parm > 255) parm = 255; // Set both channels to the same volume (center balance). mcdUnsigned[0].dwValue = mcdUnsigned[1].dwValue = (parm * (mctrl->Bounds.dwMaximum - mctrl->Bounds.dwMinimum)) / 255 + mctrl->Bounds.dwMinimum; res = mixerSetControlDetails((HMIXEROBJ) mixer, &ctrlDetails, MIXER_SETCONTROLDETAILSF_VALUE); if(res != MMSYSERR_NOERROR) return MIX_ERROR; break; default: return MIX_ERROR; } return MIX_OK; }
int VolumeControl::getVolume() const { int volume = 0; #if defined (__APPLE__) #warning TODO: Not implemented for MacOS yet!!! return volume; #elif defined(__linux__) if (mixerElem != nullptr) { //get volume range long minVolume; long maxVolume; if (snd_mixer_selem_get_playback_volume_range(mixerElem, &minVolume, &maxVolume) == 0) { //ok. now get volume long rawVolume; if (snd_mixer_selem_get_playback_volume(mixerElem, SND_MIXER_SCHN_MONO, &rawVolume) == 0) { //worked. bring into range 0-100 rawVolume -= minVolume; if (rawVolume > 0) { volume = (rawVolume * 100) / (maxVolume - minVolume); } //else volume = 0; } else { LOG(LogError) << "VolumeControl::getVolume() - Failed to get mixer volume!"; } } else { LOG(LogError) << "VolumeControl::getVolume() - Failed to get volume range!"; } } #elif defined(WIN32) || defined(_WIN32) if (mixerHandle != nullptr) { //Windows older than Vista. use mixer API. get volume from line control MIXERCONTROLDETAILS_UNSIGNED value; MIXERCONTROLDETAILS mixerControlDetails; mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS); mixerControlDetails.dwControlID = mixerControl.dwControlID; mixerControlDetails.cChannels = 1; //always 1 for a MIXERCONTROL_CONTROLF_UNIFORM control mixerControlDetails.cMultipleItems = 0; //always 0 except for a MIXERCONTROL_CONTROLF_MULTIPLE control mixerControlDetails.paDetails = &value; mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); if (mixerGetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { volume = (uint8_t)round((value.dwValue * 100) / 65535); } else { LOG(LogError) << "VolumeControl::getVolume() - Failed to get mixer volume!"; } } else if (endpointVolume != nullptr) { //Windows Vista or above. use EndpointVolume API float floatVolume = 0.0f; //0-1 if (endpointVolume->GetMasterVolumeLevelScalar(&floatVolume) == S_OK) { volume = (uint8_t)round(floatVolume * 100.0f); }else{ LOG(LogError) << "VolumeControl::getVolume() - Failed to get master volume!"; } } #endif //clamp to 0-100 range if (volume < 0) { volume = 0; } if (volume > 100) { volume = 100; } return volume; }
static void PlatGetCDDAVolumeControl(void) { int i; int numDev = mixerGetNumDevs(); //go through the mixer devices searching for one that can deal with the cd volume for(i=0;i<numDev;i++) { HMIXER handle; if(mixerOpen(&handle,i,0,0,MIXER_OBJECTF_MIXER ) == MMSYSERR_NOERROR ) { //try to get the compact disc mixer line MIXERLINE line; line.cbStruct=sizeof(MIXERLINE); line.dwComponentType=MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; if(mixerGetLineInfo(handle,&line,MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR) { MIXERLINECONTROLS lineControls; MIXERCONTROL control; lineControls.cbStruct=sizeof(MIXERLINECONTROLS); lineControls.dwLineID=line.dwLineID; lineControls.pamxctrl=&control; lineControls.dwControlType=MIXERCONTROL_CONTROLTYPE_VOLUME ; lineControls.cControls=1; lineControls.cbmxctrl=sizeof(MIXERCONTROL); control.cbStruct=sizeof(MIXERCONTROL); //try to get the volume control if(mixerGetLineControls(handle,&lineControls,MIXER_GETLINECONTROLSF_ONEBYTYPE)==MMSYSERR_NOERROR) { MIXERCONTROLDETAILS details; MIXERCONTROLDETAILS_UNSIGNED detailValue; details.cbStruct=sizeof(MIXERCONTROLDETAILS); details.dwControlID=control.dwControlID; details.cChannels=1; details.cMultipleItems=0; details.cbDetails=sizeof(MIXERCONTROLDETAILS_UNSIGNED); details.paDetails=&detailValue; //get the current volume so that we can restore it later if(mixerGetControlDetails(handle,&details,MIXER_GETCONTROLDETAILSF_VALUE)==MMSYSERR_NOERROR) { PreGameCDVolume = detailValue.dwValue; mixerClose(handle); return; //success } } } mixerClose(handle); } } return; }
int SelectRecordingLine(unsigned int nMixerId, unsigned int nComponentID, char *user_mixer_line, unsigned int nLeftVolume, unsigned int nRightVolume) { // check windows version because this can't work on VIsta and Windows 7 OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(GetVersionEx(&osvi) == 0) return 1; // don't fail, just exit function // check if we have Vista or WIndows / if(osvi.dwMajorVersion > 5) return 1; unsigned int dwVolumeControlID = 0; unsigned int dwControlType = 0; unsigned int dwSelectControlID = 0; unsigned int dwMultipleItems = 0; unsigned int dwIndex = 0xFFFFFFFF; HMIXER hMixer = NULL; MIXERCAPS mxcaps; ::ZeroMemory(&mxcaps, sizeof(MIXERCAPS)); if(nComponentID >= WAVE_IN_NUM) return 0; // open mixer if(mixerOpen(&hMixer, (unsigned int) nMixerId, 0, 0, MIXER_OBJECTF_HWAVEIN) != MMSYSERR_NOERROR) return 0; if(mixerGetDevCaps((unsigned int) hMixer, &mxcaps, sizeof(MIXERCAPS)) != MMSYSERR_NOERROR) { ::mixerClose(hMixer); return 0; } // get control we need if (hMixer == NULL) return 0; // get dwLineID MIXERLINE mxl; mxl.cbStruct = sizeof(MIXERLINE); mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; if (mixerGetLineInfo((HMIXEROBJ) hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR) { mixerClose(hMixer); return 0; } // get dwControlID MIXERCONTROL mxc; MIXERLINECONTROLS mxlc; dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER; mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = mxl.dwLineID; mxlc.dwControlType = dwControlType; mxlc.cControls = 1; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = &mxc; if (mixerGetLineControls((HMIXEROBJ) hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR) { // no mixer, try MUX dwControlType = MIXERCONTROL_CONTROLTYPE_MUX; mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = mxl.dwLineID; mxlc.dwControlType = dwControlType; mxlc.cControls = 1; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = &mxc; if (mixerGetLineControls((HMIXEROBJ) hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR) { mixerClose(hMixer); return 0; } } // store dwControlID, cMultipleItems dwSelectControlID = mxc.dwControlID; dwMultipleItems = mxc.cMultipleItems; if (dwMultipleItems == 0) { mixerClose(hMixer); return 0; } DWORD dwControlID = 0; DWORD dwLine = 0; // get the index of the specified Select control MIXERCONTROLDETAILS_LISTTEXT *pmxcdSelectText = new MIXERCONTROLDETAILS_LISTTEXT[dwMultipleItems]; DWORD dwi = 0; if (pmxcdSelectText != NULL) { MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = dwSelectControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = dwMultipleItems; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT); mxcd.paDetails = pmxcdSelectText; if (mixerGetControlDetails((HMIXEROBJ) hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_LISTTEXT) == MMSYSERR_NOERROR) { for (dwi = 0; dwi < dwMultipleItems; dwi++) { // get the line information MIXERLINE mxl; mxl.cbStruct = sizeof(MIXERLINE); mxl.dwLineID = pmxcdSelectText[dwi].dwParam1; if (mixerGetLineInfo((HMIXEROBJ) hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID) == MMSYSERR_NOERROR && mxl.dwComponentType == g_wavein_id[nComponentID].id) { // check specified user name if(user_mixer_line) { if(strcmp(user_mixer_line, mxl.szShortName) != 0 && strcmp(user_mixer_line, mxl.szName) != 0) continue; } // found, dwi is the index. dwIndex = dwi; dwLine = pmxcdSelectText[dwIndex].dwParam1; break; } } if (dwi >= dwMultipleItems) { if(user_mixer_line) { // could not find it using line IDs, some mixer drivers have // different meaning for MIXERCONTROLDETAILS_LISTTEXT.dwParam1. // let's try comparing the item names. for (dwi = 0; dwi < dwMultipleItems; dwi++) { if (stricmp(pmxcdSelectText[dwi].szName, user_mixer_line) == 0) { // found, dwi is the index. dwIndex = dwi; dwLine = pmxcdSelectText[dwIndex].dwParam1; break; } } // error if (dwi >= dwMultipleItems) { mixerClose(hMixer); delete []pmxcdSelectText; return 0; } } } if (dwi >= dwMultipleItems) { // could not find it using line IDs, some mixer drivers have // different meaning for MIXERCONTROLDETAILS_LISTTEXT.dwParam1. // let's try comparing the item names. for (dwi = 0; dwi < dwMultipleItems; dwi++) { if (stricmp(pmxcdSelectText[dwi].szName, g_wavein_id[nComponentID].string_name1) == 0) { // found, dwi is the index. dwIndex = dwi; dwLine = pmxcdSelectText[dwIndex].dwParam1; break; } } } if (dwi >= dwMultipleItems) { // could not find it using line IDs, some mixer drivers have // different meaning for MIXERCONTROLDETAILS_LISTTEXT.dwParam1. // let's try comparing the item names. for (dwi = 0; dwi < dwMultipleItems; dwi++) { if (stricmp(pmxcdSelectText[dwi].szName, g_wavein_id[nComponentID].string_name2) == 0) { // found, dwi is the index. dwIndex = dwi; dwLine = pmxcdSelectText[dwIndex].dwParam1; break; } } } if (dwi >= dwMultipleItems) { // could not find it using line IDs, some mixer drivers have // different meaning for MIXERCONTROLDETAILS_LISTTEXT.dwParam1. // let's try comparing the item names. for (dwi = 0; dwi < dwMultipleItems; dwi++) { if (stricmp(pmxcdSelectText[dwi].szName, g_wavein_id[nComponentID].string_name3) == 0) { // found, dwi is the index. dwIndex = dwi; dwLine = pmxcdSelectText[dwIndex].dwParam1; break; } } } } delete []pmxcdSelectText; } // select component if (dwIndex >= dwMultipleItems) { mixerClose(hMixer); return 0; } // get the line information int ret = 0; // get all the values first MIXERCONTROLDETAILS_BOOLEAN *pmxcdSelectValue = new MIXERCONTROLDETAILS_BOOLEAN[dwMultipleItems]; if (pmxcdSelectValue != NULL) { // select control MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = dwSelectControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = dwMultipleItems; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = pmxcdSelectValue; if (mixerGetControlDetails((HMIXEROBJ) hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { // MUX restricts the line selection to one source line at a time. if (dwControlType == MIXERCONTROL_CONTROLTYPE_MUX) ZeroMemory(pmxcdSelectValue, dwMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN)); // set the value pmxcdSelectValue[dwIndex].fValue = 1; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = dwSelectControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = dwMultipleItems; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mxcd.paDetails = pmxcdSelectValue; if (mixerSetControlDetails((HMIXEROBJ) hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { ret = 1; } } delete []pmxcdSelectValue; } // set volume, if volume is larger than 100 skip volume change if(nLeftVolume <= 100 && nRightVolume <= 100) { mxl.cbStruct = sizeof(MIXERLINE); mxl.dwLineID = dwLine; if (mixerGetLineInfo((HMIXEROBJ) hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID) == MMSYSERR_NOERROR) { mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = dwLine; mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = &mxc; if (mixerGetLineControls((HMIXEROBJ) hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR) { if(nLeftVolume > 100) nLeftVolume = 100; if(nRightVolume > 100) nRightVolume = 100; MIXERCONTROLDETAILS_UNSIGNED mxcdVolume[2] = { mxc.Bounds.dwMaximum * nLeftVolume / 100, mxc.Bounds.dwMaximum * nRightVolume / 100}; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = mxc.dwControlID; mxcd.cChannels = mxl.cChannels; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = mxcdVolume; if (mixerSetControlDetails((HMIXEROBJ) hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) { // error, can't set volume } } else { // error can't set volume } } } mixerClose(hMixer); return ret; }