📄 mixer.c
字号:
return dwRet;}/************************************************************************** * MIX_GetControlDetails [internal] */static DWORD MIX_GetControlDetails(WORD wDevID, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails){ DWORD ret = MMSYSERR_NOTSUPPORTED; DWORD c, chnl; struct mixer* mix; TRACE("(%04X, %p, %lu);\n", wDevID, lpmcd, fdwDetails); if (lpmcd == NULL) return MMSYSERR_INVALPARAM; if ((mix = MIX_Get(wDevID)) == NULL) return MMSYSERR_BADDEVICEID; switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) { case MIXER_GETCONTROLDETAILSF_VALUE: TRACE("GCD VALUE (%08lx)\n", lpmcd->dwControlID); if (MIX_CheckControl(mix, lpmcd->dwControlID)) { c = lpmcd->dwControlID - 1; chnl = HIWORD(mix->ctrl[c].dwLineID); if (chnl == LINEID_DST) chnl = LOWORD(mix->ctrl[c].dwLineID) ? SOUND_MIXER_RECLEV : SOUND_MIXER_VOLUME; switch (mix->ctrl[c].ctrl.dwControlType) { case MIXERCONTROL_CONTROLTYPE_VOLUME: { LPMIXERCONTROLDETAILS_UNSIGNED mcdu; int val; TRACE(" <> %u %lu\n", sizeof(MIXERCONTROLDETAILS_UNSIGNED), lpmcd->cbDetails); /* return value is 00RL (4 bytes)... */ if ((val = mix->volume[chnl]) == -1 && !MIX_GetVal(mix, chnl, &val)) return MMSYSERR_INVALPARAM; switch (lpmcd->cChannels) { case 1: /* mono... so R = L */ mcdu = (LPMIXERCONTROLDETAILS_UNSIGNED)lpmcd->paDetails; mcdu->dwValue = (LOBYTE(LOWORD(val)) * 65536L) / 100; break; case 2: /* stereo, left is paDetails[0] */ mcdu = (LPMIXERCONTROLDETAILS_UNSIGNED)((char*)lpmcd->paDetails + 0 * lpmcd->cbDetails); mcdu->dwValue = (LOBYTE(LOWORD(val)) * 65536L) / 100; mcdu = (LPMIXERCONTROLDETAILS_UNSIGNED)((char*)lpmcd->paDetails + 1 * lpmcd->cbDetails); mcdu->dwValue = (HIBYTE(LOWORD(val)) * 65536L) / 100; break; default: WARN("Unknown cChannels (%ld)\n", lpmcd->cChannels); return MMSYSERR_INVALPARAM; } TRACE("=> %08lx\n", mcdu->dwValue); } break; case MIXERCONTROL_CONTROLTYPE_MUTE: case MIXERCONTROL_CONTROLTYPE_ONOFF: { LPMIXERCONTROLDETAILS_BOOLEAN mcdb; TRACE(" <> %u %lu\n", sizeof(MIXERCONTROLDETAILS_BOOLEAN), lpmcd->cbDetails); /* we mute both channels at the same time */ mcdb = (LPMIXERCONTROLDETAILS_BOOLEAN)lpmcd->paDetails; mcdb->fValue = (mix->volume[chnl] != -1); TRACE("=> %s\n", mcdb->fValue ? "on" : "off"); } break; case MIXERCONTROL_CONTROLTYPE_MIXER: case MIXERCONTROL_CONTROLTYPE_MUX: { unsigned mask; TRACE(" <> %u %lu\n", sizeof(MIXERCONTROLDETAILS_BOOLEAN), lpmcd->cbDetails); if (!MIX_GetRecSrc(mix, &mask)) { /* FIXME: ENXIO => no mixer installed */ WARN("mixer device not available !\n"); ret = MMSYSERR_ERROR; } else { LPMIXERCONTROLDETAILS_BOOLEAN mcdb; int i, j; /* we mute both channels at the same time */ mcdb = (LPMIXERCONTROLDETAILS_BOOLEAN)lpmcd->paDetails; for (i = j = 0; j < SOUND_MIXER_NRDEVICES; j++) { if (WINE_CHN_SUPPORTS(mix->recMask, j)) { if (i >= lpmcd->u.cMultipleItems) return MMSYSERR_INVALPARAM; mcdb[i++].fValue = WINE_CHN_SUPPORTS(mask, j); } } } } break; default: WARN("Unsupported\n"); } ret = MMSYSERR_NOERROR; } else { ret = MMSYSERR_INVALPARAM; } break; case MIXER_GETCONTROLDETAILSF_LISTTEXT: TRACE("LIST TEXT (%08lx)\n", lpmcd->dwControlID); ret = MMSYSERR_INVALPARAM; if (MIX_CheckControl(mix, lpmcd->dwControlID)) { int c = lpmcd->dwControlID - 1; if (mix->ctrl[c].ctrl.dwControlType == MIXERCONTROL_CONTROLTYPE_MUX || mix->ctrl[c].ctrl.dwControlType == MIXERCONTROL_CONTROLTYPE_MIXER) { LPMIXERCONTROLDETAILS_LISTTEXTA mcdlt; int i, j; mcdlt = (LPMIXERCONTROLDETAILS_LISTTEXTA)lpmcd->paDetails; for (i = j = 0; j < SOUND_MIXER_NRDEVICES; j++) { if (WINE_CHN_SUPPORTS(mix->recMask, j)) { mcdlt[i].dwParam1 = MAKELONG(LINEID_RECORD, j); mcdlt[i].dwParam2 = 0; strcpy(mcdlt[i].szName, MIX_Names[j]); i++; } } if (i != lpmcd->u.cMultipleItems) FIXME("bad count\n"); ret = MMSYSERR_NOERROR; } } break; default: WARN("Unknown flag (%08lx)\n", fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK); } return ret;}/************************************************************************** * MIX_SetControlDetails [internal] */static DWORD MIX_SetControlDetails(WORD wDevID, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails){ DWORD ret = MMSYSERR_NOTSUPPORTED; DWORD c, chnl; int val; struct mixer* mix; TRACE("(%04X, %p, %lu);\n", wDevID, lpmcd, fdwDetails); if (lpmcd == NULL) return MMSYSERR_INVALPARAM; if ((mix = MIX_Get(wDevID)) == NULL) return MMSYSERR_BADDEVICEID; switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) { case MIXER_GETCONTROLDETAILSF_VALUE: TRACE("GCD VALUE (%08lx)\n", lpmcd->dwControlID); if (MIX_CheckControl(mix, lpmcd->dwControlID)) { c = lpmcd->dwControlID - 1; chnl = HIWORD(mix->ctrl[c].dwLineID); if (chnl == LINEID_DST) chnl = LOWORD(mix->ctrl[c].dwLineID) ? SOUND_MIXER_RECLEV : SOUND_MIXER_VOLUME; switch (mix->ctrl[c].ctrl.dwControlType) { case MIXERCONTROL_CONTROLTYPE_VOLUME: { LPMIXERCONTROLDETAILS_UNSIGNED mcdu; TRACE(" <> %u %lu\n", sizeof(MIXERCONTROLDETAILS_UNSIGNED), lpmcd->cbDetails); /* val should contain 00RL */ switch (lpmcd->cChannels) { case 1: /* mono... so R = L */ mcdu = (LPMIXERCONTROLDETAILS_UNSIGNED)lpmcd->paDetails; TRACE("Setting RL to %08ld\n", mcdu->dwValue); val = 0x101 * ((mcdu->dwValue * 100) >> 16); break; case 2: /* stereo, left is paDetails[0] */ mcdu = (LPMIXERCONTROLDETAILS_UNSIGNED)((char*)lpmcd->paDetails + 0 * lpmcd->cbDetails); TRACE("Setting L to %08ld\n", mcdu->dwValue); val = ((mcdu->dwValue * 100) >> 16); mcdu = (LPMIXERCONTROLDETAILS_UNSIGNED)((char*)lpmcd->paDetails + 1 * lpmcd->cbDetails); TRACE("Setting R to %08ld\n", mcdu->dwValue); val += ((mcdu->dwValue * 100) >> 16) << 8; break; default: WARN("Unknown cChannels (%ld)\n", lpmcd->cChannels); return MMSYSERR_INVALPARAM; } if (mix->volume[chnl] == -1) { if (!MIX_SetVal(mix, chnl, val)) return MMSYSERR_INVALPARAM; } else { mix->volume[chnl] = val; } } ret = MMSYSERR_NOERROR; break; case MIXERCONTROL_CONTROLTYPE_MUTE: case MIXERCONTROL_CONTROLTYPE_ONOFF: { LPMIXERCONTROLDETAILS_BOOLEAN mcdb; TRACE(" <> %u %lu\n", sizeof(MIXERCONTROLDETAILS_BOOLEAN), lpmcd->cbDetails); mcdb = (LPMIXERCONTROLDETAILS_BOOLEAN)lpmcd->paDetails; if (mcdb->fValue) { if (!MIX_GetVal(mix, chnl, &mix->volume[chnl]) || !MIX_SetVal(mix, chnl, 0)) return MMSYSERR_INVALPARAM; } else { if (mix->volume[chnl] == -1) { ret = MMSYSERR_NOERROR; break; } if (!MIX_SetVal(mix, chnl, mix->volume[chnl])) return MMSYSERR_INVALPARAM; mix->volume[chnl] = -1; } } ret = MMSYSERR_NOERROR; break; case MIXERCONTROL_CONTROLTYPE_MIXER: case MIXERCONTROL_CONTROLTYPE_MUX: { LPMIXERCONTROLDETAILS_BOOLEAN mcdb; unsigned mask; int i, j; TRACE(" <> %u %lu\n", sizeof(MIXERCONTROLDETAILS_BOOLEAN), lpmcd->cbDetails); /* we mute both channels at the same time */ mcdb = (LPMIXERCONTROLDETAILS_BOOLEAN)lpmcd->paDetails; mask = 0; for (i = j = 0; j < SOUND_MIXER_NRDEVICES; j++) { if (WINE_CHN_SUPPORTS(mix->recMask, j) && mcdb[i++].fValue) { /* a mux can only select one line at a time... */ if (mix->singleRecChannel && mask != 0) { FIXME("!!!\n"); return MMSYSERR_INVALPARAM; } mask |= WINE_CHN_MASK(j); } } if (i != lpmcd->u.cMultipleItems) FIXME("bad count\n"); TRACE("writing %04x as rec src\n", mask); if (!MIX_SetRecSrc(mix, mask)) ERR("Can't write new mixer settings\n"); else ret = MMSYSERR_NOERROR; } break; } } break; default: WARN("Unknown SetControlDetails flag (%08lx)\n", fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK); } return ret;}/************************************************************************** * MIX_Init [internal] */static DWORD MIX_Init(void){ int mixer;#define MIXER_DEV "/dev/mixer" if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) { if (errno == ENODEV || errno == ENXIO) { /* no driver present */ return MMSYSERR_NODRIVER; } MIX_NumMixers = 0; return MMSYSERR_ERROR; } close(mixer); MIX_NumMixers = 1; MIX_Mixers[0].name = MIXER_DEV; MIX_Open(0, NULL, 0); /* FIXME */#undef MIXER_DEV return MMSYSERR_NOERROR;}/************************************************************************** * MIX_GetNumDevs [internal] */static DWORD MIX_GetNumDevs(void){ return MIX_NumMixers;}#endif /* HAVE_OSS *//************************************************************************** * mxdMessage (WINEOSS.3) */DWORD WINAPI OSS_mxdMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2){/* TRACE("(%04X, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); */#ifdef HAVE_OSS switch (wMsg) { case DRVM_INIT: return MIX_Init(); case DRVM_EXIT: case DRVM_ENABLE: case DRVM_DISABLE: /* FIXME: Pretend this is supported */ return 0; case MXDM_GETDEVCAPS: return MIX_GetDevCaps(wDevID, (LPMIXERCAPSA)dwParam1, dwParam2); case MXDM_GETLINEINFO: return MIX_GetLineInfo(wDevID, (LPMIXERLINEA)dwParam1, dwParam2); case MXDM_GETNUMDEVS: return MIX_GetNumDevs(); case MXDM_OPEN: return MMSYSERR_NOERROR; /* MIX_Open(wDevID, (LPMIXEROPENDESC)dwParam1, dwParam2); */ case MXDM_CLOSE: return MMSYSERR_NOERROR; case MXDM_GETLINECONTROLS: return MIX_GetLineControls(wDevID, (LPMIXERLINECONTROLSA)dwParam1, dwParam2); case MXDM_GETCONTROLDETAILS: return MIX_GetControlDetails(wDevID, (LPMIXERCONTROLDETAILS)dwParam1, dwParam2); case MXDM_SETCONTROLDETAILS: return MIX_SetControlDetails(wDevID, (LPMIXERCONTROLDETAILS)dwParam1, dwParam2); default: WARN("unknown message %d!\n", wMsg); return MMSYSERR_NOTSUPPORTED; }#else return MMSYSERR_NOTENABLED;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -