📄 mixer.c
字号:
}/****************************************************************** * MIX_SetRecSrc * * */static BOOL MIX_SetRecSrc(struct mixer* mix, unsigned mask){ int mixer; BOOL ret = FALSE; if ((mixer = open(mix->name, O_RDWR)) >= 0) { if (ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &mask) < 0) { ERR("Can't write new mixer settings\n"); } else ret = TRUE; close(mixer); } return ret;}/************************************************************************** * MIX_GetDevCaps [internal] */static DWORD MIX_GetDevCaps(WORD wDevID, LPMIXERCAPSA lpCaps, DWORD dwSize){ struct mixer* mix; TRACE("(%04X, %p, %lu);\n", wDevID, lpCaps, dwSize); if (lpCaps == NULL) return MMSYSERR_INVALPARAM; if (!(mix = MIX_Get(wDevID))) return MMSYSERR_BADDEVICEID; lpCaps->wMid = WINE_MIXER_MANUF_ID; lpCaps->wPid = WINE_MIXER_PRODUCT_ID; lpCaps->vDriverVersion = WINE_MIXER_VERSION; strcpy(lpCaps->szPname, WINE_MIXER_NAME); lpCaps->cDestinations = 2; /* speakers & record */ lpCaps->fdwSupport = 0; /* No bits defined yet */ return MMSYSERR_NOERROR;}/************************************************************************** * MIX_GetLineInfoDst [internal] */static DWORD MIX_GetLineInfoDst(struct mixer* mix, LPMIXERLINEA lpMl, DWORD dst){ unsigned mask; int j; lpMl->dwDestination = dst; switch (dst) { case 0: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; mask = mix->devMask; j = SOUND_MIXER_VOLUME; break; case 1: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; mask = mix->recMask; j = SOUND_MIXER_RECLEV; break; default: FIXME("shouldn't happen\n"); return MMSYSERR_ERROR; } lpMl->dwSource = 0xFFFFFFFF; lstrcpynA(lpMl->szShortName, MIX_Labels[j], MIXER_SHORT_NAME_CHARS); lstrcpynA(lpMl->szName, MIX_Names[j], MIXER_LONG_NAME_CHARS); /* we have all connections found in the MIX_DevMask */ lpMl->cConnections = 0; for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) if (WINE_CHN_SUPPORTS(mask, j)) lpMl->cConnections++; lpMl->cChannels = 1; if (WINE_CHN_SUPPORTS(mix->stereoMask, lpMl->dwLineID)) lpMl->cChannels++; lpMl->dwLineID = MAKELONG(dst, LINEID_DST); lpMl->cControls = 0; for (j = 0; j < mix->numCtrl; j++) if (mix->ctrl[j].dwLineID == lpMl->dwLineID) lpMl->cControls++; return MMSYSERR_NOERROR;}/************************************************************************** * MIX_GetLineInfoSrc [internal] */static DWORD MIX_GetLineInfoSrc(struct mixer* mix, LPMIXERLINEA lpMl, DWORD idx, DWORD dst){ int i, j; unsigned mask = (dst) ? mix->recMask : mix->devMask; strcpy(lpMl->szShortName, MIX_Labels[idx]); strcpy(lpMl->szName, MIX_Names[idx]); lpMl->dwLineID = MAKELONG(dst, idx); lpMl->dwDestination = dst; lpMl->cConnections = 1; lpMl->cControls = 0; for (i = 0; i < mix->numCtrl; i++) if (mix->ctrl[i].dwLineID == lpMl->dwLineID) lpMl->cControls++; switch (idx) { case SOUND_MIXER_SYNTH: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER; lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_CD: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_LINE: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE; lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_MIC: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_PCM: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE; break; case SOUND_MIXER_IMIX: lpMl->dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED; lpMl->fdwLine |= MIXERLINE_LINEF_SOURCE; break; default: WARN("Index %ld not handled.\n", idx); return MIXERR_INVALLINE; } lpMl->cChannels = 1; if (dst == 0 && WINE_CHN_SUPPORTS(mix->stereoMask, idx)) lpMl->cChannels++; for (i = j = 0; j < SOUND_MIXER_NRDEVICES; j++) { if (WINE_CHN_SUPPORTS(mask, j)) { if (j == idx) break; i++; } } lpMl->dwSource = i; return MMSYSERR_NOERROR;}/****************************************************************** * MIX_CheckLine */static BOOL MIX_CheckLine(DWORD lineID){ return ((HIWORD(lineID) < SOUND_MIXER_NRDEVICES && LOWORD(lineID) < 2) || (HIWORD(lineID) == LINEID_DST && LOWORD(lineID) < SOUND_MIXER_NRDEVICES));}/************************************************************************** * MIX_GetLineInfo [internal] */static DWORD MIX_GetLineInfo(WORD wDevID, LPMIXERLINEA lpMl, DWORD fdwInfo){ int i, j; DWORD ret = MMSYSERR_NOERROR; unsigned mask; struct mixer* mix; TRACE("(%04X, %p, %lu);\n", wDevID, lpMl, fdwInfo); if (lpMl == NULL || lpMl->cbStruct != sizeof(*lpMl)) return MMSYSERR_INVALPARAM; if ((mix = MIX_Get(wDevID)) == NULL) return MMSYSERR_BADDEVICEID; /* FIXME: set all the variables correctly... the lines below * are very wrong... */ lpMl->fdwLine = MIXERLINE_LINEF_ACTIVE; lpMl->dwUser = 0; switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) { case MIXER_GETLINEINFOF_DESTINATION: TRACE("DESTINATION (%08lx)\n", lpMl->dwDestination); if (lpMl->dwDestination >= 2) return MMSYSERR_INVALPARAM; if ((ret = MIX_GetLineInfoDst(mix, lpMl, lpMl->dwDestination)) != MMSYSERR_NOERROR) return ret; break; case MIXER_GETLINEINFOF_SOURCE: TRACE("SOURCE (%08lx), dst=%08lx\n", lpMl->dwSource, lpMl->dwDestination); switch (lpMl->dwDestination) { case 0: mask = mix->devMask; break; case 1: mask = mix->recMask; break; default: return MMSYSERR_INVALPARAM; } i = lpMl->dwSource; for (j = 0; j < SOUND_MIXER_NRDEVICES; j++) { if (WINE_CHN_SUPPORTS(mask, j) && (i-- == 0)) break; } if (j >= SOUND_MIXER_NRDEVICES) return MIXERR_INVALLINE; if ((ret = MIX_GetLineInfoSrc(mix, lpMl, j, lpMl->dwDestination)) != MMSYSERR_NOERROR) return ret; break; case MIXER_GETLINEINFOF_LINEID: TRACE("LINEID (%08lx)\n", lpMl->dwLineID); if (!MIX_CheckLine(lpMl->dwLineID)) return MIXERR_INVALLINE; if (HIWORD(lpMl->dwLineID) == LINEID_DST) ret = MIX_GetLineInfoDst(mix, lpMl, LOWORD(lpMl->dwLineID)); else ret = MIX_GetLineInfoSrc(mix, lpMl, HIWORD(lpMl->dwLineID), LOWORD(lpMl->dwLineID)); if (ret != MMSYSERR_NOERROR) return ret; break; case MIXER_GETLINEINFOF_COMPONENTTYPE: TRACE("COMPONENT TYPE (%08lx)\n", lpMl->dwComponentType); switch (lpMl->dwComponentType) { case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS: ret = MIX_GetLineInfoDst(mix, lpMl, 0); break; case MIXERLINE_COMPONENTTYPE_DST_WAVEIN: ret = MIX_GetLineInfoDst(mix, lpMl, 1); break; case MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER: ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_SYNTH, 0); break; case MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC: ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_CD, 0); break; case MIXERLINE_COMPONENTTYPE_SRC_LINE: ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_LINE, 0); break; case MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE: ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_MIC, 1); break; case MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT: ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_PCM, 0); break; case MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED: ret = MIX_GetLineInfoSrc(mix, lpMl, SOUND_MIXER_IMIX, 1); break; default: FIXME("Unhandled component type (%08lx)\n", lpMl->dwComponentType); return MMSYSERR_INVALPARAM; } break; case MIXER_GETLINEINFOF_TARGETTYPE: FIXME("_TARGETTYPE not implemented yet.\n"); break; default: WARN("Unknown flag (%08lx)\n", fdwInfo & MIXER_GETLINEINFOF_QUERYMASK); break; } lpMl->Target.dwType = MIXERLINE_TARGETTYPE_AUX; /* FIXME */ lpMl->Target.dwDeviceID = 0xFFFFFFFF; lpMl->Target.wMid = WINE_MIXER_MANUF_ID; lpMl->Target.wPid = WINE_MIXER_PRODUCT_ID; lpMl->Target.vDriverVersion = WINE_MIXER_VERSION; strcpy(lpMl->Target.szPname, WINE_MIXER_NAME); return ret;}/****************************************************************** * MIX_CheckControl * */static BOOL MIX_CheckControl(struct mixer* mix, DWORD ctrlID){ return (ctrlID >= 1 && ctrlID <= mix->numCtrl);}/************************************************************************** * MIX_GetLineControls [internal] */static DWORD MIX_GetLineControls(WORD wDevID, LPMIXERLINECONTROLSA lpMlc, DWORD flags){ DWORD dwRet = MMSYSERR_NOERROR; struct mixer* mix; TRACE("(%04X, %p, %lu);\n", wDevID, lpMlc, flags); if (lpMlc == NULL) return MMSYSERR_INVALPARAM; if (lpMlc->cbStruct < sizeof(*lpMlc) || lpMlc->cbmxctrl < sizeof(MIXERCONTROLA)) return MMSYSERR_INVALPARAM; if ((mix = MIX_Get(wDevID)) == NULL) return MMSYSERR_BADDEVICEID; switch (flags & MIXER_GETLINECONTROLSF_QUERYMASK) { case MIXER_GETLINECONTROLSF_ALL: { int i, j; TRACE("line=%08lx GLCF_ALL (%ld)\n", lpMlc->dwLineID, lpMlc->cControls); for (i = j = 0; i < mix->numCtrl; i++) { if (mix->ctrl[i].dwLineID == lpMlc->dwLineID) j++; } if (!j || lpMlc->cControls != j) dwRet = MMSYSERR_INVALPARAM; else if (!MIX_CheckLine(lpMlc->dwLineID)) dwRet = MIXERR_INVALLINE; else { for (i = j = 0; i < mix->numCtrl; i++) { if (mix->ctrl[i].dwLineID == lpMlc->dwLineID) { TRACE("[%d] => [%2d]: typ=%08lx\n", j, i + 1, mix->ctrl[i].ctrl.dwControlType); lpMlc->pamxctrl[j++] = mix->ctrl[i].ctrl; } } } } break; case MIXER_GETLINECONTROLSF_ONEBYID: TRACE("line=%08lx GLCF_ONEBYID (%lx)\n", lpMlc->dwLineID, lpMlc->u.dwControlID); if (!MIX_CheckControl(mix, lpMlc->u.dwControlID) || mix->ctrl[lpMlc->u.dwControlID - 1].dwLineID != lpMlc->dwLineID) dwRet = MMSYSERR_INVALPARAM; else lpMlc->pamxctrl[0] = mix->ctrl[lpMlc->u.dwControlID - 1].ctrl; break; case MIXER_GETLINECONTROLSF_ONEBYTYPE: TRACE("line=%08lx GLCF_ONEBYTYPE (%lx)\n", lpMlc->dwLineID, lpMlc->u.dwControlType); if (!MIX_CheckLine(lpMlc->dwLineID)) dwRet = MIXERR_INVALLINE; else { int i; DWORD ct = lpMlc->u.dwControlType & MIXERCONTROL_CT_CLASS_MASK; for (i = 0; i < mix->numCtrl; i++) { if (mix->ctrl[i].dwLineID == lpMlc->dwLineID && ct == (mix->ctrl[i].ctrl.dwControlType & MIXERCONTROL_CT_CLASS_MASK)) { lpMlc->pamxctrl[0] = mix->ctrl[i].ctrl; break; } } if (i == mix->numCtrl) dwRet = MMSYSERR_INVALPARAM; } break; default: ERR("Unknown flag %08lx\n", flags & MIXER_GETLINECONTROLSF_QUERYMASK); dwRet = MMSYSERR_INVALPARAM; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -