📄 mixerdrv.cpp
字号:
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineInfo: invalid source line %d\r\n"), pQuery->dwSource));
return MIXERR_INVALLINE;
}
usLineID = pLine->pSources[pQuery->dwSource];
}
break;
case MIXER_GETLINEINFOF_COMPONENTTYPE:
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineInfo COMPONENT\r\n")));
break;
case MIXER_GETLINEINFOF_TARGETTYPE:
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineInfo TARGET\r\n")));
// valid query, but we're not going to form usLineID
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineInfo: invalid query %08x\r\n"), dwFlags & MIXER_GETLINEINFOF_QUERYMASK));
return MMSYSERR_INVALPARAM;
}
switch (dwFlags & MIXER_GETLINEINFOF_QUERYMASK) {
case MIXER_GETLINEINFOF_COMPONENTTYPE:
// scan for line of proper type
for (i = 0; i < nlines; i++) {
if (g_mixerline[i].dwComponentType == pQuery->dwComponentType) {
pFound = &g_mixerline[i];
break;
}
}
#ifdef DEBUG
if (pFound == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineInfo: no line of component type %08x\r\n"), pQuery->dwComponentType));
}
#endif
break;
case MIXER_GETLINEINFOF_TARGETTYPE:
// scan for target type
for (i = 0; i < nlines; i++) {
if (g_mixerline[i].dwTargetType == pQuery->Target.dwType) {
pFound = &g_mixerline[i];
break;
}
}
#ifdef DEBUG
if (pFound == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineInfo: no line of target type %08x\r\n"), pQuery->Target.dwType));
}
#endif
break;
case MIXER_GETLINEINFOF_DESTINATION:
case MIXER_GETLINEINFOF_LINEID:
case MIXER_GETLINEINFOF_SOURCE:
pFound = LookupMxLine(usLineID);
if (pFound == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineInfo: invalid line ID %08x\r\n"), usLineID));
return MMSYSERR_ERROR;
}
break;
default:
// should never happen - we filter for this in the first switch()
break;
}
if (pFound != NULL) {
pQuery->cChannels = pFound->ucChannels;
pQuery->cConnections = pFound->ucConnections;
pQuery->cControls = pFound->ucControls;
pQuery->dwComponentType = pFound->dwComponentType;
pQuery->dwLineID = pFound->usLineID;
pQuery->dwDestination = pFound->ucDstIndex;
pQuery->dwSource = pFound->ucSrcIndex;
pQuery->fdwLine = pFound->ucFlags;
pQuery->Target.dwDeviceID = 0;
pQuery->Target.dwType = pFound->dwTargetType;
pQuery->Target.vDriverVersion = DRIVER_VERSION;
pQuery->Target.wMid = MM_MICROSOFT;
pQuery->Target.wPid = MM_MSFT_WSS_MIXER;
wcscpy(pQuery->szName, pFound->szName);
wcscpy(pQuery->szShortName, pFound->szShortName);
wcscpy(pQuery->Target.szPname, DEVICE_NAME);
mmRet = MMSYSERR_NOERROR;
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineInfo: \"%s\" %08x\r\n"), pFound->szName, pFound->ucFlags));
}
return mmRet;
}
DWORD
wdev_MXDM_GETLINECONTROLS (PMIXERLINECONTROLS pQuery, DWORD dwFlags)
{
UINT i;
PMIXERCONTROL pDstControl = pQuery->pamxctrl;
USHORT usLineID = (USHORT) pQuery->dwLineID;
DWORD dwCount = pQuery->cControls;
switch (dwFlags & MIXER_GETLINECONTROLSF_QUERYMASK) {
case MIXER_GETLINECONTROLSF_ALL:
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineControls: ALL %x\r\n"), usLineID));
// retrieve all controls for the line pQuery->dwLineID
{
PMXLINEDESC pFound = LookupMxLine(usLineID);
if (pFound == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: invalid line ID %04x\r\n"), usLineID));
return MIXERR_INVALLINE;
}
if (pFound->ucControls != dwCount) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: incorrect number of controls. Expect %d, found %d.\r\n"),dwCount,pFound->ucControls));
return MMSYSERR_INVALPARAM;
}
for (i = 0; i < ncontrols && dwCount > 0; i++) {
PMXCONTROLDESC pSrcControl = &g_controls[i];
if (pSrcControl->usLineID == usLineID) {
CopyMixerControl(pDstControl, pSrcControl, i);
pDstControl++;
dwCount--;
}
}
}
break;
case MIXER_GETLINECONTROLSF_ONEBYID:
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineControls: ONEBYID %x\r\n"), pQuery->dwControlID));
// retrieve the control specified by pQuery->dwControlID
if (pQuery->dwControlID >= ncontrols) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: invalid control ID %d (max %d)\r\n"), pQuery->dwControlID, ncontrols));
return MIXERR_INVALCONTROL;
}
if (dwCount < 1) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: control count must be nonzero\r\n")));
return MMSYSERR_INVALPARAM;
}
CopyMixerControl(pDstControl, &g_controls[pQuery->dwControlID], pQuery->dwControlID);
pQuery->dwLineID = g_controls[pQuery->dwControlID].usLineID;
break;
case MIXER_GETLINECONTROLSF_ONEBYTYPE:
// retrieve the control specified by pQuery->dwLineID and pQuery->dwControlType
{
UINT index;
PMXLINEDESC pFound = LookupMxLine(usLineID);
if (pFound == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: invalid line ID %04x\r\n"), usLineID));
return MIXERR_INVALLINE;
}
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineControls: ONEBYTYPE %x \"%s\"\r\n"), usLineID, pFound->szName));
if (dwCount < 1) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: control count must be non zero\r\n")));
return MMSYSERR_INVALPARAM;
}
index = LookupMxControl(usLineID, pQuery->dwControlType);
if (index >= ncontrols) {
// not to be alarmed: SndVol32 queries for LOTS of control types we don't have
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerLineControls: line %04x (%s) has no control of type %s (%08x)\r\n"), usLineID, pFound->szName, COMPTYPE(pQuery->dwControlType), pQuery->dwControlType));
return MMSYSERR_INVALPARAM;
}
CopyMixerControl(pDstControl, &g_controls[index], index);
return MMSYSERR_NOERROR;
// if we fall out of the search loop, we return failure
}
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerLineControls: invalid query %08x\r\n"), dwFlags & MIXER_GETLINECONTROLSF_QUERYMASK));
break;
}
return MMSYSERR_NOERROR;
}
DWORD
wdev_MXDM_GETCONTROLDETAILS (PMIXERCONTROLDETAILS pQuery, DWORD dwFlags)
{
PMXCONTROLDESC pSrcControlDesc;
PMXLINEDESC pLine;
ULONG ulControlValue = 0;
// API guarantees that pQuery points to accessible, aligned, properly sized MIXERCONTROLDETAILS structure
DEBUGMSG(ZONE_HWMIXER, (TEXT("GetMixerControlDetails(%d)\r\n"), pQuery->dwControlID));
if (pQuery->dwControlID >= ncontrols) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerControlDetails: invalid control %d (max %d)\r\n"), pQuery->dwControlID, ncontrols));
return MIXERR_INVALCONTROL;
}
pSrcControlDesc = &g_controls[pQuery->dwControlID];
pLine = LookupMxLine(pSrcControlDesc->usLineID);
if (pLine == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerControlDetails: inconsistent internal mixer line table\r\n")));
return MMSYSERR_ERROR;
}
switch (dwFlags & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
case MIXER_GETCONTROLDETAILSF_VALUE:
switch(pSrcControlDesc->dwType) {
case MIXERCONTROL_CONTROLTYPE_VOLUME:
{
switch (GET_MXLINE_DST(pSrcControlDesc->usLineID)) {
case LINE_OUT:
ulControlValue = g_pHWContext->GetOutputGain();
break;
case PCM_IN:
ulControlValue = g_pHWContext->GetInputGain();
break;
default:
DEBUGCHK(0);
break;
}
MIXERCONTROLDETAILS_UNSIGNED * pValue = (MIXERCONTROLDETAILS_UNSIGNED * ) pQuery->paDetails;
ULONG ulVolR, ulVolL;
ulVolR = ulControlValue & 0xffff;
if (pLine->ucChannels == 2) {
ulVolL = (ulControlValue >> 16) & 0xffff;
}
else {
ulVolL = ulVolR;
}
if (pQuery->cChannels == 1) {
pValue[0].dwValue = (ulVolR + ulVolL)/2;
}
else {
pValue[0].dwValue = ulVolL;
pValue[1].dwValue = ulVolR;
}
}
break;
case MIXERCONTROL_CONTROLTYPE_ONOFF:
case MIXERCONTROL_CONTROLTYPE_MUTE:
{
switch (GET_MXLINE_DST(pSrcControlDesc->usLineID)) {
case LINE_OUT:
ulControlValue = g_pHWContext->GetOutputMute();
break;
case PCM_IN:
ulControlValue = g_pHWContext->GetInputMute();
break;
default:
DEBUGCHK(0);
break;
}
MIXERCONTROLDETAILS_BOOLEAN * pValue = (MIXERCONTROLDETAILS_BOOLEAN *) pQuery->paDetails;
pValue[0].fValue = ulControlValue;
}
break;
default:
DEBUGCHK(0);
break;
}
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerControlDetails: invalid query %08x\r\n"), dwFlags & MIXER_GETCONTROLDETAILSF_QUERYMASK));
break;
}
return MMSYSERR_NOERROR;
}
DWORD
wdev_MXDM_SETCONTROLDETAILS (PMIXERCONTROLDETAILS pDetail, DWORD dwFlags)
{
PMXCONTROLDESC pSrcControlDesc;
PMXLINEDESC pLine;
MIXERCONTROLDETAILS_UNSIGNED * pValue = (MIXERCONTROLDETAILS_UNSIGNED * ) pDetail->paDetails;
DWORD dwSetting;
// API guarantees that pDetail points to accessible, aligned, properly siezd MIXERCONTROLDETAILS structure
DEBUGMSG(ZONE_HWMIXER, (TEXT("SetMixerControlDetails(%d)\r\n"), pDetail->dwControlID));
if (pDetail->dwControlID >= ncontrols) {
DEBUGMSG(ZONE_ERROR, (TEXT("SetMixerControlDetails: invalid control %d (max %d)\r\n"), pDetail->dwControlID, ncontrols));
return MIXERR_INVALCONTROL;
}
pSrcControlDesc = &g_controls[pDetail->dwControlID];
pLine = LookupMxLine(pSrcControlDesc->usLineID);
if (pLine == NULL) {
DEBUGMSG(ZONE_ERROR, (TEXT("SetMixerControlDetails: inconsistent internal mixer line table\r\n")));
return MMSYSERR_ERROR;
}
switch(pSrcControlDesc->dwType) {
case MIXERCONTROL_CONTROLTYPE_VOLUME:
{
DWORD dwSettingL, dwSettingR;
dwSettingL = pValue[0].dwValue & 0xffff;
// setting might be mono or stereo. For mono, apply same volume to both channels
if (pDetail->cChannels == 2) {
dwSettingR = pValue[1].dwValue & 0xffff;
}
else {
dwSettingR = dwSettingL;
}
if (pLine->ucChannels == 1) {
dwSetting = (dwSettingL + dwSettingR) / 2;
}
else {
dwSetting = (dwSettingL << 16) | dwSettingR;
}
// now apply the setting to the hardware
switch (GET_MXLINE_DST(pSrcControlDesc->usLineID)) {
case LINE_OUT:
g_pHWContext->SetOutputGain(dwSetting);
break;
case PCM_IN:
g_pHWContext->SetInputGain(dwSetting);
break;
default:
DEBUGCHK(0);
break;
}
DEBUGMSG(ZONE_VOLUME, (TEXT("wdev_MXDM_SETCONTROLDETAILS: %08x %08x %08x\r\n"), dwSettingL, dwSettingR, dwSetting));
}
break;
case MIXERCONTROL_CONTROLTYPE_ONOFF:
case MIXERCONTROL_CONTROLTYPE_MUTE:
{
// now apply the setting to the hardware
switch (GET_MXLINE_DST(pSrcControlDesc->usLineID)) {
case LINE_OUT:
g_pHWContext->SetOutputMute(pValue[0].dwValue);
break;
case PCM_IN:
g_pHWContext->SetInputMute(pValue[0].dwValue);
break;
default:
DEBUGCHK(0);
break;
}
}
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerControlDetails: unexpected control type %08x\r\n"), pSrcControlDesc->dwType));
ASSERT(0);
return MMSYSERR_ERROR;
}
PerformMixerCallbacks (MM_MIXM_CONTROL_CHANGE, GET_MXCONTROL_ID(pSrcControlDesc));
return MMSYSERR_NOERROR;
}
BOOL HandleMixerMessage(PMMDRV_MESSAGE_PARAMS pParams, DWORD *pdwResult)
{
MMRESULT dwRet;
switch (pParams->uMsg) {
case MXDM_GETNUMDEVS:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_GETNUMDEVS\r\n")));
dwRet = 1;
break;
case MXDM_GETDEVCAPS:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_GETDEVCAPS\r\n")));
dwRet = wdev_MXDM_GETDEVCAPS((PMIXERCAPS) pParams->dwParam1, pParams->dwParam2);
break;
case MXDM_OPEN:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_OPEN\r\n")));
dwRet = wdev_MXDM_OPEN((PDWORD) pParams->dwUser, (PMIXEROPENDESC) pParams->dwParam1, pParams->dwParam2);
break;
case MXDM_CLOSE:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_CLOSE\r\n")));
dwRet = wdev_MXDM_CLOSE(pParams->dwUser);
break;
case MXDM_GETLINEINFO:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_GETLINEINFO\r\n")));
dwRet = wdev_MXDM_GETLINEINFO((PMIXERLINE) pParams->dwParam1, pParams->dwParam2);
break;
case MXDM_GETLINECONTROLS:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_GETLINECONTROLS\r\n")));
dwRet = wdev_MXDM_GETLINECONTROLS((PMIXERLINECONTROLS) pParams->dwParam1, pParams->dwParam2);
break;
case MXDM_GETCONTROLDETAILS:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_GETCONTROLDETAILS\r\n")));
dwRet = wdev_MXDM_GETCONTROLDETAILS((PMIXERCONTROLDETAILS) pParams->dwParam1, pParams->dwParam2);
break;
case MXDM_SETCONTROLDETAILS:
PRINTMSG(ZONE_WODM, (TEXT("MXDM_SETCONTROLDETAILS\r\n")));
dwRet = wdev_MXDM_SETCONTROLDETAILS((PMIXERCONTROLDETAILS) pParams->dwParam1, pParams->dwParam2);
break;
default:
ERRMSG("Unsupported mixer message");
dwRet = MMSYSERR_NOTSUPPORTED;
break;
} // switch (pParams->uMsg)
*pdwResult = dwRet;
return TRUE;
}
struct _global_volume
{
ULONG dwMasterVolume;
BOOL fMasterMute;
ULONG dwMicVolume;
BOOL fMicMute;
} g_VolumeSettings;
MMRESULT GetMixerValue(DWORD dwControl, PDWORD pdwSetting)
{
switch (dwControl) {
case WPDMX_MASTER_VOL:
*pdwSetting = g_VolumeSettings.dwMasterVolume;
break;
case WPDMX_MASTER_MUTE:
*pdwSetting = g_VolumeSettings.fMasterMute;
break;
case WPDMX_MIC_VOL:
*pdwSetting = g_VolumeSettings.dwMicVolume;
break;
case WPDMX_MIC_MUTE:
*pdwSetting = g_VolumeSettings.fMicMute;
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT("GetMixerValue: unrecognized control")));
return MMSYSERR_NOTSUPPORTED;
}
return MMSYSERR_NOERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -