📄 alsamixer.c
字号:
static intmixer_conv(int val, int omin, int omax, int nmin, int nmax){ float orange = omax - omin, nrange = nmax - nmin; if (orange == 0) return 0; return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;}static intmixer_calc_volume(snd_mixer_elem_t *elem, int vol, int type, snd_mixer_selem_channel_id_t chn){ int vol1; long v; long min, max; if (type != MIXER_ELEM_CAPTURE) snd_mixer_selem_get_playback_volume_range(elem, &min, &max); else snd_mixer_selem_get_capture_volume_range(elem, &min, &max); vol1 = (vol < 0) ? -vol : vol; if (vol1 > 0) { if (vol1 > 100) vol1 = max; else vol1 = mixer_conv(vol1, 0, 100, min, max); /* Note: we have delta in vol1 and we need to map our */ /* delta value to hardware range */ vol1 -= min; if (vol1 <= 0) vol1 = 1; if (vol < 0) vol1 = -vol1; } if (type != MIXER_ELEM_CAPTURE) snd_mixer_selem_get_playback_volume(elem, chn, &v); else snd_mixer_selem_get_capture_volume(elem, chn, &v); vol1 += v; return CLAMP(vol1, min, max);}static intmixer_convert_volume(snd_mixer_elem_t *elem, int vol, int type){ long min, max; if (type != MIXER_ELEM_CAPTURE) snd_mixer_selem_get_playback_volume_range(elem, &min, &max); else snd_mixer_selem_get_capture_volume_range(elem, &min, &max); return mixer_conv(vol, 0, 100, min, max);}/* update enum list */static void update_enum_list(snd_mixer_elem_t *elem, int chn, int delta){ unsigned int eidx; if (snd_mixer_selem_get_enum_item(elem, chn, &eidx) < 0) return; if (delta < 0) { if (eidx == 0) return; eidx--; } else { int items = snd_mixer_selem_get_enum_items(elem); if (items < 0) return; eidx++; if (eidx >= items) return; } snd_mixer_selem_set_enum_item(elem, chn, eidx);}/* set new channel values */static voidmixer_write_cbar (int elem_index){ snd_mixer_elem_t *elem; int vleft, vright, vbalance; int type; snd_mixer_selem_id_t *sid; snd_mixer_selem_channel_id_t chn_left, chn_right, chn; int sw; if (mixer_sid == NULL) return; sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]); elem = snd_mixer_find_selem(mixer_handle, sid); if (elem == NULL) CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL); type = mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK; chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT]; chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT]; if (chn_right != SND_MIXER_SCHN_UNKNOWN) { if (type != MIXER_ELEM_CAPTURE) { if (!snd_mixer_selem_has_playback_channel(elem, chn_right)) chn_right = SND_MIXER_SCHN_UNKNOWN; } else { if (!snd_mixer_selem_has_capture_channel(elem, chn_right)) chn_right = SND_MIXER_SCHN_UNKNOWN; } } /* volume */ if ((mixer_volume_delta[MIXER_CHN_LEFT] || mixer_volume_delta[MIXER_CHN_RIGHT] || mixer_volume_absolute != -1 || mixer_balance_volumes) && (mixer_type[elem_index] & MIXER_ELEM_HAS_VOLUME)) { int mono; int joined; mono = (chn_right == SND_MIXER_SCHN_UNKNOWN); if (type != MIXER_ELEM_CAPTURE) joined = snd_mixer_selem_has_playback_volume_joined(elem); else joined = snd_mixer_selem_has_capture_volume_joined(elem); mono |= joined; if (mixer_volume_absolute != -1) { vbalance = vright = vleft = mixer_convert_volume(elem, mixer_volume_absolute, type); } else { if (mono && !mixer_volume_delta[MIXER_CHN_LEFT]) mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT]; vleft = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_LEFT], type, chn_left); vbalance = vleft; if (! mono) { vright = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_RIGHT], type, chn_right); vbalance += vright; vbalance /= 2; } else { vright = vleft; } } if (joined) { for (chn = 0; chn < SND_MIXER_SCHN_LAST; chn++) if (type != MIXER_ELEM_CAPTURE) { if (snd_mixer_selem_has_playback_channel(elem, chn)) snd_mixer_selem_set_playback_volume(elem, chn, vleft); } else { if (snd_mixer_selem_has_capture_channel(elem, chn)) snd_mixer_selem_set_capture_volume(elem, chn, vleft); } } else { if (mixer_balance_volumes) vleft = vright = vbalance; if (type != MIXER_ELEM_CAPTURE) { if (snd_mixer_selem_has_playback_volume(elem) && snd_mixer_selem_has_playback_channel(elem, chn_left)) snd_mixer_selem_set_playback_volume(elem, chn_left, vleft); } else { if (snd_mixer_selem_has_capture_volume(elem) && snd_mixer_selem_has_capture_channel(elem, chn_left)) snd_mixer_selem_set_capture_volume(elem, chn_left, vleft); } if (! mono) { if (type != MIXER_ELEM_CAPTURE) { if (snd_mixer_selem_has_playback_volume(elem) && snd_mixer_selem_has_playback_channel(elem, chn_right)) snd_mixer_selem_set_playback_volume(elem, chn_right, vright); } else { if (snd_mixer_selem_has_capture_volume(elem) && snd_mixer_selem_has_capture_channel(elem, chn_right)) snd_mixer_selem_set_capture_volume(elem, chn_right, vright); } } } } /* mute */ if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) { if (mixer_toggle_mute) { if (snd_mixer_selem_has_playback_switch_joined(elem)) { snd_mixer_selem_get_playback_switch(elem, chn_left, &sw); snd_mixer_selem_set_playback_switch_all(elem, !sw); } else { if (mixer_toggle_mute & MIXER_MASK_LEFT) { snd_mixer_selem_get_playback_switch(elem, chn_left, &sw); snd_mixer_selem_set_playback_switch(elem, chn_left, !sw); } if (chn_right != SND_MIXER_SCHN_UNKNOWN && (mixer_toggle_mute & MIXER_MASK_RIGHT)) { snd_mixer_selem_get_playback_switch(elem, chn_right, &sw); snd_mixer_selem_set_playback_switch(elem, chn_right, !sw); } } } } mixer_toggle_mute = 0; /* capture */ if (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SWITCH) { if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) { if (snd_mixer_selem_has_capture_switch_joined(elem)) { snd_mixer_selem_get_capture_switch(elem, chn_left, &sw); snd_mixer_selem_set_capture_switch_all(elem, !sw); } else { if ((mixer_toggle_capture & MIXER_MASK_LEFT) && snd_mixer_selem_has_capture_channel(elem, chn_left)) { snd_mixer_selem_get_capture_switch(elem, chn_left, &sw); snd_mixer_selem_set_capture_switch(elem, chn_left, !sw); } if (chn_right != SND_MIXER_SCHN_UNKNOWN && snd_mixer_selem_has_capture_channel(elem, chn_right) && (mixer_toggle_capture & MIXER_MASK_RIGHT)) { snd_mixer_selem_get_capture_switch(elem, chn_right, &sw); snd_mixer_selem_set_capture_switch(elem, chn_right, !sw); } } } } mixer_toggle_capture = 0; /* enum list */ if (type == MIXER_ELEM_ENUM || type == MIXER_ELEM_CAPTURE_ENUM) { if (mixer_volume_delta[MIXER_CHN_LEFT]) update_enum_list(elem, MIXER_CHN_LEFT, mixer_volume_delta[MIXER_CHN_LEFT]); if (mixer_volume_delta[MIXER_CHN_RIGHT]) update_enum_list(elem, MIXER_CHN_RIGHT, mixer_volume_delta[MIXER_CHN_RIGHT]); } mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT] = 0; mixer_volume_absolute = -1; mixer_balance_volumes = 0;}static void draw_blank(int x, int y, int lines){ int i; mixer_dc (DC_TEXT); for (i = 0; i < lines; i++) mvaddstr (y - i, x, " ");}/* show the current view mode */static void display_view_info(void){ mixer_dc (DC_PROMPT); mvaddstr (3, 2, "View: Playback Capture All "); mixer_dc (DC_TEXT); switch (mixer_view) { case VIEW_PLAYBACK: mvaddstr (3, 8, "[Playback]"); break; case VIEW_CAPTURE: mvaddstr (3, 18, "[Capture]"); break; default: mvaddstr (3, 27, "[All]"); break; }}/* show the information of the focused item */static void display_item_info(int elem_index, snd_mixer_selem_id_t *sid, char *extra_info){ char string[64], idxstr[10]; int idx; int i, xlen = mixer_max_x - 8; if (xlen > sizeof(string) - 1) xlen = sizeof(string) - 1; mixer_dc (DC_PROMPT); mvaddstr (4, 2, "Item: "); mixer_dc (DC_TEXT); idx = snd_mixer_selem_id_get_index(sid); if (idx > 0) snprintf(idxstr, sizeof(idxstr), " %i", snd_mixer_selem_id_get_index(sid)); snprintf(string, sizeof(string), "%s%s%s%s", snd_mixer_selem_id_get_name(sid), (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SUFFIX) ? " Capture" : "", idx > 0 ? idxstr : "", extra_info); for (i = strlen(string); i < sizeof(string) - 1; i++) string[i] = ' '; string[xlen] = '\0'; addstr(string);}/* show the bar item name */static void display_item_name(int x, int y, int elem_index, snd_mixer_selem_id_t *sid){ const char *suffix; char string1[9], string[9]; int i; mixer_dc (elem_index == mixer_focus_elem ? DC_CBAR_FOCUS_LABEL : DC_CBAR_LABEL); if (mixer_type[elem_index] & MIXER_ELEM_CAPTURE_SUFFIX) suffix = " Capture"; else suffix = ""; if (snd_mixer_selem_id_get_index(sid) > 0) snprintf(string1, sizeof(string1), "%s%s %d", snd_mixer_selem_id_get_name(sid), suffix, snd_mixer_selem_id_get_index(sid)); else snprintf(string1, sizeof(string1), "%s%s", snd_mixer_selem_id_get_name(sid), suffix); string[8] = 0; for (i = 0; i < 8; i++) string[i] = ' '; memcpy(string + (8 - strlen (string1)) / 2, string1, strlen(string1)); mvaddstr (y, x, string);}static void display_enum_list(snd_mixer_elem_t *elem, int y, int x){ int cury, ch, err; draw_blank(x, y, mixer_cbar_height + (mixer_view == VIEW_PLAYBACK ? 5 : 6)); cury = y - 4; for (ch = 0; ch < 2; ch++) { unsigned int eidx, ofs; char tmp[9]; err = snd_mixer_selem_get_enum_item(elem, ch, &eidx); if (err < 0) break; if (snd_mixer_selem_get_enum_item_name(elem, eidx, sizeof(tmp) - 1, tmp) < 0) break; tmp[8] = 0; ofs = (8 - strlen(tmp)) / 2; mvaddstr(cury, x + ofs, tmp); cury += 2; }}static void draw_volume_bar(int x, int y, int elem_index, long vleft, long vright){ int i, dc; mixer_dc (DC_CBAR_FRAME); if (mixer_type[elem_index] & MIXER_ELEM_MUTE_SWITCH) { mvaddch (y, x + 2, ACS_LTEE); mvaddch (y, x + 5, ACS_RTEE); } else { mvaddch (y, x + 2, ACS_LLCORNER); mvaddch (y, x + 3, ACS_HLINE); mvaddch (y, x + 4, ACS_HLINE); mvaddch (y, x + 5, ACS_LRCORNER); } y--; for (i = 0; i < mixer_cbar_height; i++) { mvaddstr (y - i, x, " "); mvaddch (y - i, x + 2, ACS_VLINE); mvaddch (y - i, x + 5, ACS_VLINE); } for (i = 0; i < mixer_cbar_height; i++) { if (i + 1 >= 0.8 * mixer_cbar_height) dc = DC_ANY_3; else if (i + 1 >= 0.4 * mixer_cbar_height) dc = DC_ANY_2; else dc = DC_ANY_1; mvaddch (y, x + 3, mixer_dc (vleft > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); mvaddch (y, x + 4, mixer_dc (vright > i * 100 / mixer_cbar_height ? dc : DC_CBAR_EMPTY)); y--; } mixer_dc (DC_CBAR_FRAME); mvaddstr (y, x, " "); mvaddch (y, x + 2, ACS_ULCORNER); mvaddch (y, x + 3, ACS_HLINE); mvaddch (y, x + 4, ACS_HLINE); mvaddch (y, x + 5, ACS_URCORNER);}static void draw_playback_switch(int x, int y, int elem_index, int swl, int swr){ int dc; mixer_dc (DC_CBAR_FRAME); mvaddch (y, x + 2, ACS_LLCORNER); mvaddch (y, x + 3, ACS_HLINE); mvaddch (y, x + 4, ACS_HLINE); mvaddch (y, x + 5, ACS_LRCORNER); mvaddstr (y - 1, x, " "); mvaddch (y - 1, x + 2, ACS_VLINE); mvaddch (y - 1, x + 5, ACS_VLINE); mvaddstr (y - 2, x, " "); mvaddch (y - 2, x + 2, ACS_ULCORNER); mvaddch (y - 2, x + 3, ACS_HLINE); mvaddch (y - 2, x + 4, ACS_HLINE); mvaddch (y - 2, x + 5, ACS_URCORNER); dc = swl ? DC_CBAR_NOMUTE : DC_CBAR_MUTE; mvaddch (y - 1, x + 3, mixer_dc (dc)); dc = swr ? DC_CBAR_NOMUTE : DC_CBAR_MUTE; mvaddch (y - 1, x + 4, mixer_dc (dc));}static void draw_capture_switch(int x, int y, int elem_index, int swl, int swr){ int i; if (swl || swr) { mixer_dc (DC_CBAR_CAPTURE); mvaddstr (y, x + 1, "CAPTUR"); } else { for (i = 0; i < 6; i++) mvaddch(y, x + i + 1, mixer_dc(DC_CBAR_NOCAPTURE)); } mixer_dc (DC_CBAR_CAPTURE); mvaddch (y - 1, x + 1, swl ? 'L' : ' '); mvaddch (y - 1, x + 6, swr ? 'R' : ' ');}#ifndef SND_CTL_TLV_DB_GAIN_MUTE#define SND_CTL_TLV_DB_GAIN_MUTE -9999999#endifstatic void dB_value(char *s, long val){ if (val <= SND_CTL_TLV_DB_GAIN_MUTE) strcpy(s, "mute"); else snprintf(s, 10, "%3.2f", (float)val / 100);} static voidmixer_update_cbar (int elem_index){ snd_mixer_elem_t *elem; long vleft, vright; int type; snd_mixer_selem_id_t *sid; snd_mixer_selem_channel_id_t chn_left, chn_right; int x, y; int swl, swr; char * extra_info; /* set new scontrol indices and read info */ if (mixer_sid == NULL) return; sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]); elem = snd_mixer_find_selem(mixer_handle, sid); if (elem == NULL) CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL); type = mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK; chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT]; chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT]; if (chn_right != SND_MIXER_SCHN_UNKNOWN) { if (type != MIXER_ELEM_CAPTURE) { if (!snd_mixer_selem_has_playback_channel(elem, chn_right)) chn_right = SND_MIXER_SCHN_UNKNOWN; } else { if (!snd_mixer_selem_has_capture_channel(elem, chn_right)) chn_right = SND_MIXER_SCHN_UNKNOWN; } } vleft = vright = 0; if (type != MIXER_ELEM_CAPTURE && snd_mixer_selem_has_playback_volume(elem)) { long vmin, vmax; snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax); snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft); vleft = mixer_conv(vleft, vmin, vmax, 0, 100); if (chn_right != SND_MIXER_SCHN_UNKNOWN) { snd_mixer_selem_get_playback_volume(elem, chn_right, &vright); vright = mixer_conv(vright, vmin, vmax, 0, 100); } else { vright = vleft; } } if (type == MIXER_ELEM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)) { long vmin, vmax; snd_mixer_selem_get_capture_volume_range(elem, &vmin, &vmax); snd_mixer_selem_get_capture_volume(elem, chn_left, &vleft);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -