📄 alsamixer.c
字号:
if (block == '#' && ACS_BOARD == '#') { block = stipple; stipple = ACS_BLOCK; } /* lower scroll border */ l = x2 - x1 - 1; n = hscroll * l; r = (hoffs + 1.0 / (2 * (l - n - 1))) * (l - n - 1); for (i = 0; i < l; i++) mvaddch (y2, i + x1 + 1, hscroll >= 1 ? ACS_HLINE : i >= r && i <= r + n ? block : stipple); /* right scroll border */ l = y2 - y1 - 1; n = vscroll * l; r = (voffs + 1.0 / (2 * (l - n - 1))) * (l - n - 1); for (i = 0; i < l; i++) mvaddch (i + y1 + 1, x2, vscroll >= 1 ? ACS_VLINE : i >= r && i <= r + n ? block : stipple); /* show text */ x1++; y1++; for (i = 0; i < *yoffs; i++) { l = 0; mixer_offset_text (&text_offs, 0, &l); } for (i = y1; i < y2; i++) { l = x2 - x1; p = mixer_offset_text (&text_offs, *xoffs, &l); n = x1; while (l--) mvaddch (i, n++, *p++); while (n < x2) mvaddch (i, n++, ' '); }}struct vbuffer{ char *buffer; int size; int len;};static voidvbuffer_kill (struct vbuffer *vbuf){ if (vbuf->size) free (vbuf->buffer); vbuf->buffer = NULL; vbuf->size = 0; vbuf->len = 0;}#define vbuffer_append_string(vb,str) vbuffer_append (vb, str, strlen (str))static voidvbuffer_append (struct vbuffer *vbuf, char *text, int len){ if (vbuf->size - vbuf->len <= len) { vbuf->size += len + 1; vbuf->buffer = realloc (vbuf->buffer, vbuf->size); } memcpy (vbuf->buffer + vbuf->len, text, len); vbuf->len += len; vbuf->buffer[vbuf->len] = 0;}static intvbuffer_append_file (struct vbuffer *vbuf, char *name){ int fd; fd = open (name, O_RDONLY); if (fd >= 0) { char buffer[1025]; int l; do { l = read (fd, buffer, 1024); vbuffer_append (vbuf, buffer, MAX (0, l)); } while (l > 0 || (l < 0 && (errno == EAGAIN || errno == EINTR))); close (fd); return 0; } else return 1;}static voidmixer_show_procinfo (void){ struct vbuffer vbuf = { NULL, 0, 0 }; vbuffer_append_string (&vbuf, "\n"); vbuffer_append_string (&vbuf, "/proc/asound/version:\n"); vbuffer_append_string (&vbuf, "====================\n"); if (vbuffer_append_file (&vbuf, "/proc/asound/version")) { vbuffer_kill (&vbuf); mixer_procinfo_xoffs = mixer_procinfo_yoffs = 0; mixer_show_text ("/proc", " No /proc information available. ", &mixer_procinfo_xoffs, &mixer_procinfo_yoffs); return; } else vbuffer_append_file (&vbuf, "/proc/asound/meminfo"); vbuffer_append_string (&vbuf, "\n"); vbuffer_append_string (&vbuf, "/proc/asound/cards:\n"); vbuffer_append_string (&vbuf, "===================\n"); if (vbuffer_append_file (&vbuf, "/proc/asound/cards")) vbuffer_append_string (&vbuf, "No information available.\n"); vbuffer_append_string (&vbuf, "\n"); vbuffer_append_string (&vbuf, "/proc/asound/devices:\n"); vbuffer_append_string (&vbuf, "=====================\n"); if (vbuffer_append_file (&vbuf, "/proc/asound/devices")) vbuffer_append_string (&vbuf, "No information available.\n"); vbuffer_append_string (&vbuf, "\n"); vbuffer_append_string (&vbuf, "/proc/asound/oss/devices:\n"); vbuffer_append_string (&vbuf, "=========================\n"); if (vbuffer_append_file (&vbuf, "/proc/asound/oss/devices")) vbuffer_append_string (&vbuf, "No information available.\n"); vbuffer_append_string (&vbuf, "\n"); vbuffer_append_string (&vbuf, "/proc/asound/timers:\n"); vbuffer_append_string (&vbuf, "====================\n"); if (vbuffer_append_file (&vbuf, "/proc/asound/timers")) vbuffer_append_string (&vbuf, "No information available.\n"); vbuffer_append_string (&vbuf, "\n"); vbuffer_append_string (&vbuf, "/proc/asound/pcm:\n"); vbuffer_append_string (&vbuf, "=================\n"); if (vbuffer_append_file (&vbuf, "/proc/asound/pcm")) vbuffer_append_string (&vbuf, "No information available.\n"); mixer_show_text ("/proc", vbuf.buffer, &mixer_procinfo_xoffs, &mixer_procinfo_yoffs); vbuffer_kill (&vbuf);}static intmixer_event (snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem){ mixer_changed_state = 1; return 0;}static voidmixer_init (void){ snd_ctl_card_info_t *hw_info; snd_ctl_t *ctl_handle; int err; snd_ctl_card_info_alloca(&hw_info); if ((err = snd_ctl_open (&ctl_handle, card_id, 0)) < 0) mixer_abort (ERR_OPEN, "snd_ctl_open", err); if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0) mixer_abort (ERR_FCN, "snd_ctl_card_info", err); snd_ctl_close (ctl_handle); /* open mixer device */ if ((err = snd_mixer_open (&mixer_handle, 0)) < 0) mixer_abort (ERR_FCN, "snd_mixer_open", err); if (mixer_level == 0 && (err = snd_mixer_attach (mixer_handle, card_id)) < 0) mixer_abort (ERR_FCN, "snd_mixer_attach", err); if ((err = snd_mixer_selem_register (mixer_handle, mixer_level > 0 ? &mixer_options : NULL, NULL)) < 0) mixer_abort (ERR_FCN, "snd_mixer_selem_register", err); snd_mixer_set_callback (mixer_handle, mixer_event); if ((err = snd_mixer_load (mixer_handle)) < 0) mixer_abort (ERR_FCN, "snd_mixer_load", err); /* setup global variables */ strcpy(mixer_card_name, snd_ctl_card_info_get_name(hw_info)); strcpy(mixer_device_name, snd_ctl_card_info_get_mixername(hw_info));}/* init mixer screen */static voidrecalc_screen_size (void){ getmaxyx (mixer_window, mixer_max_y, mixer_max_x); if (mixer_minimize) { mixer_max_x = MIXER_MIN_X; mixer_max_y = MIXER_MIN_Y; } mixer_ofs_x = 2 /* extra begin padding: */ + 1; /* required allocations */ mixer_n_vis_elems = (mixer_max_x - mixer_ofs_x * 2 + 1) / 9; mixer_n_vis_elems = CLAMP (mixer_n_vis_elems, 1, mixer_n_view_elems); mixer_extra_space = mixer_max_x - mixer_ofs_x * 2 + 1 - mixer_n_vis_elems * 9; mixer_extra_space = MAX (0, mixer_extra_space / (mixer_n_vis_elems + 1)); mixer_text_y = MIXER_TEXT_Y; if (mixer_view == VIEW_PLAYBACK || mixer_view == VIEW_CHANNELS) mixer_text_y += 2; /* row for mute switch */ if (mixer_view == VIEW_CAPTURE || mixer_view == VIEW_CHANNELS) mixer_text_y++; /* row for capture switch */ if (mixer_text_y + MIXER_CBAR_STD_HGT < mixer_max_y) mixer_cbar_height = MIXER_CBAR_STD_HGT + MAX (1, mixer_max_y - mixer_text_y - MIXER_CBAR_STD_HGT + 1) / 2; else mixer_cbar_height = MAX (1, mixer_max_y - mixer_text_y);}static voidmixer_reinit (void){ snd_mixer_elem_t *elem; int idx, elem_index, i, j, selem_count; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_t *focus_gid; int focus_type = -1; snd_mixer_selem_id_alloca(&focus_gid); if (!mixer_changed_state) return; if (mixer_sid) { snd_mixer_selem_id_copy(focus_gid, (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[mixer_focus_elem])); focus_type = mixer_type[mixer_focus_elem] & MIXER_ELEM_TYPE_MASK; }__again: mixer_changed_state = 0; if (mixer_sid != NULL) free(mixer_sid); selem_count = snd_mixer_get_count(mixer_handle); mixer_sid = malloc(snd_mixer_selem_id_sizeof() * selem_count); if (mixer_sid == NULL) mixer_abort (ERR_FCN, "malloc", 0); mixer_n_selems = 0; for (elem = snd_mixer_first_elem(mixer_handle); elem; elem = snd_mixer_elem_next(elem)) { sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_n_selems); if (mixer_changed_state) goto __again; if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); mixer_n_selems++; } mixer_n_elems = 0; for (idx = 0; idx < mixer_n_selems; idx++) { int nelems_added = 0; sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx); if (mixer_changed_state) goto __again; elem = snd_mixer_find_selem(mixer_handle, sid); if (elem == NULL) CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL); for (i = 0; i < MIXER_ELEM_CAPTURE; i++) { int ok; for (j = ok = 0; j < 2; j++) { if (mixer_changed_state) goto __again; if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j])) ok++; } if (ok) { nelems_added++; mixer_n_elems++; } } if (snd_mixer_selem_has_capture_volume(elem) || (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem))) mixer_n_elems++; } if (mixer_type) free(mixer_type); mixer_type = (int *)calloc(mixer_n_elems, sizeof(int)); if (mixer_type == NULL) mixer_abort(ERR_FCN, "malloc", 0); if (mixer_grpidx) free(mixer_grpidx); mixer_grpidx = (int *)calloc(mixer_n_elems, sizeof(int)); if (mixer_grpidx == NULL) mixer_abort(ERR_FCN, "malloc", 0); elem_index = 0; for (idx = 0; idx < mixer_n_selems; idx++) { int nelems_added = 0; sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx); if (mixer_changed_state) goto __again; elem = snd_mixer_find_selem(mixer_handle, sid); if (elem == NULL) CHECK_ABORT (ERR_FCN, "snd_mixer_find_selem()", -EINVAL); if ( (mixer_view == VIEW_PLAYBACK) || (mixer_view == VIEW_CHANNELS) ) { for (i = MIXER_ELEM_FRONT; i <= MIXER_ELEM_SIDE; i++) { int ok; for (j = ok = 0; j < 2; j++) { if (mixer_changed_state) goto __again; if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j])) ok++; } if (ok) { sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx); mixer_grpidx[elem_index] = idx; if (snd_mixer_selem_is_enumerated(elem)) { if (mixer_view == VIEW_PLAYBACK && snd_mixer_selem_is_enum_capture(elem)) continue; mixer_type[elem_index] = MIXER_ELEM_ENUM; } else { mixer_type[elem_index] = i; if (i == 0 && snd_mixer_selem_has_playback_switch(elem)) mixer_type[elem_index] |= MIXER_ELEM_MUTE_SWITCH; if (snd_mixer_selem_has_playback_volume(elem)) mixer_type[elem_index] |= MIXER_ELEM_HAS_VOLUME; } if (mixer_view == VIEW_CHANNELS) { if (nelems_added == 0 && ! snd_mixer_selem_has_capture_volume(elem) && snd_mixer_selem_has_capture_switch(elem)) mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SWITCH; } elem_index++; nelems_added++; if (elem_index >= mixer_n_elems) break; } } } if ( (mixer_view == VIEW_CAPTURE) || (mixer_view == VIEW_CHANNELS) ) { int do_add = 0; if (snd_mixer_selem_has_capture_volume(elem) && (mixer_view == VIEW_CAPTURE || !snd_mixer_selem_has_common_volume(elem))) do_add = 1; if (!do_add && (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem)) && (mixer_view == VIEW_CAPTURE || !snd_mixer_selem_has_common_switch(elem))) do_add = 1; if (!do_add && mixer_view == VIEW_CAPTURE && snd_mixer_selem_is_enum_capture(elem)) do_add = 1; if (do_add) { mixer_grpidx[elem_index] = idx; if (snd_mixer_selem_is_enum_capture(elem)) mixer_type[elem_index] = MIXER_ELEM_CAPTURE_ENUM; else { mixer_type[elem_index] = MIXER_ELEM_CAPTURE; if (nelems_added == 0 && snd_mixer_selem_has_capture_switch(elem)) mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SWITCH; if (nelems_added) mixer_type[elem_index] |= MIXER_ELEM_CAPTURE_SUFFIX; if (snd_mixer_selem_has_capture_volume(elem)) mixer_type[elem_index] |= MIXER_ELEM_HAS_VOLUME; } elem_index++; if (elem_index >= mixer_n_elems) break; } } } mixer_n_view_elems = elem_index; recalc_screen_size(); mixer_focus_elem = 0; if (focus_type >= 0) { for (elem_index = 0; elem_index < mixer_n_view_elems; elem_index++) { sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_grpidx[elem_index]); if (!strcmp(snd_mixer_selem_id_get_name(focus_gid), snd_mixer_selem_id_get_name(sid)) && snd_mixer_selem_id_get_index(focus_gid) == snd_mixer_selem_id_get_index(sid) && (mixer_type[elem_index] & MIXER_ELEM_TYPE_MASK) == focus_type) { mixer_focus_elem = elem_index; break; } } } if (mixer_changed_state) goto __again;}static voidmixer_init_window (void){ /* initialize ncurses */ setlocale(LC_CTYPE, ""); mixer_window = initscr (); curs_set (0); /* hide the cursor */ mixer_no_lrcorner = tigetflag ("xenl") != 1 && tigetflag ("am") != 1; if (mixer_do_color) mixer_do_color = has_colors (); mixer_init_draw_contexts (); /* react on key presses */ cbreak (); noecho (); leaveok (mixer_window, TRUE); keypad (mixer_window, TRUE); GETCH_BLOCK (1); recalc_screen_size(); mixer_clear (TRUE);}static voidmixer_resize (void){ struct winsize winsz = { 0, }; mixer_needs_resize = 0; if (ioctl (fileno (stdout), TIOCGWINSZ, &winsz) >= 0 && winsz.ws_row && winsz.ws_col) { keypad (mixer_window, FALSE); leaveok (mixer_window, FALSE); endwin (); mixer_max_x = MAX (2, winsz.ws_col); mixer_max_y = MAX (2, winsz.ws_row); /* humpf, i don't get it, if only the number of rows change, * ncurses will segfault shortly after (could trigger that with mc as well). */ resizeterm (mixer_max_y + 1, mixer_max_x + 1); resizeterm (mixer_max_y, mixer_max_x); mixer_init_window (); if (mixer_max_x < MIXER_MIN_X || mixer_max_y < MIXER_MIN_Y) beep (); // mixer_abort (ERR_WINSIZE, ""); mixer_have_old_focus = 0; }}static voidmixer_set_delta(int delta){ int grp; for (grp = 0; grp < 2; grp++) mixer_volume_delta[grp] = delta;}static voidmixer_add_delta(int delta){ int grp; for (grp = 0; grp < 2; grp++) mixer_volume_delta[grp] += delta;}static int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -