📄 alsamixer.c
字号:
mixer_iteration (void){ int count, err; struct pollfd *fds; int finished = 0; int key = 0; int old_view; unsigned short revents; /* setup for select on stdin and the mixer fd */ if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0) mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors_count", count); fds = calloc(count + 1, sizeof(struct pollfd)); if (fds == NULL) mixer_abort (ERR_FCN, "malloc", 0); fds->fd = fileno(stdin); fds->events = POLLIN; if ((err = snd_mixer_poll_descriptors(mixer_handle, fds + 1, count)) < 0) mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors", err); if (err != count) mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (err != count)", 0); finished = poll(fds, count + 1, -1); /* don't abort on handled signals */ if (finished < 0 && errno == EINTR) finished = 0; if (mixer_needs_resize) mixer_resize (); if (finished > 0) { if (fds->revents & POLLIN) { key = getch (); finished--; } } else { key = 0; } if (finished > 0) { if (snd_mixer_poll_descriptors_revents(mixer_handle, fds + 1, count, &revents) >= 0) { if (revents & POLLNVAL) mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (POLLNVAL)", 0); if (revents & POLLERR) mixer_abort (ERR_FCN, "snd_mixer_poll_descriptors (POLLERR)", 0); if (revents & POLLIN) snd_mixer_handle_events(mixer_handle); } } finished = 0; free(fds); old_view = mixer_view; #if 0 /* DISABLED: it's not so usefull rather annoying... */ /* feature Escape prefixing for some keys */ if (key == 27) { GETCH_BLOCK (0); key = getch (); GETCH_BLOCK (1); switch (key) { case 9: /* Tab */ key = KEY_BTAB; break; default: key = 27; break; } }#endif /* DISABLED */ /* general keys */ switch (key) { case 0: /* ignore */ break; case 27: /* Escape */ case KEY_F (10): finished = 1; key = 0; break; case 13: /* Return */ case 10: /* NewLine */ if (mixer_view != mixer_view_saved) { mixer_view = mixer_view_saved; mixer_changed_state=1; mixer_reinit (); } key = 0; break; case 'h': case 'H': case '?': case KEY_F (1): mixer_view = VIEW_HELP; key = 0; break; case '/': case KEY_F (2): mixer_view = VIEW_PROCINFO; key = 0; break; case KEY_F (3): if (mixer_view == VIEW_PLAYBACK) { mixer_clear (FALSE); } else { mixer_view = mixer_view_saved = VIEW_PLAYBACK; mixer_changed_state=1; mixer_reinit (); } key = 0; break; case KEY_F (4): if (mixer_view == VIEW_CAPTURE) { mixer_clear (FALSE); } else { mixer_view = mixer_view_saved = VIEW_CAPTURE; mixer_changed_state=1; mixer_reinit (); } key = 0; break; case KEY_F (5): if (mixer_view == VIEW_CHANNELS) { mixer_clear (FALSE); } else { mixer_view = mixer_view_saved = VIEW_CHANNELS; mixer_changed_state=1; mixer_reinit (); } key = 0; break; case 9: /* Tab */ if (mixer_view >= VIEW_CHANNELS && mixer_view <= VIEW_CAPTURE) { mixer_view = (mixer_view + 1) % 3 + VIEW_CHANNELS; mixer_view_saved = mixer_view; mixer_changed_state = 1; mixer_reinit (); key = 0; } break; case '\014': case 'L': case 'l': mixer_clear (TRUE); break; } if (key && (mixer_view == VIEW_HELP || mixer_view == VIEW_PROCINFO)) switch (key) { case 9: /* Tab */ mixer_hscroll_delta += 8; break; case KEY_BTAB: mixer_hscroll_delta -= 8; break; case KEY_A1: mixer_hscroll_delta -= 1; mixer_vscroll_delta -= 1; break; case KEY_A3: mixer_hscroll_delta += 1; mixer_vscroll_delta -= 1; break; case KEY_C1: mixer_hscroll_delta -= 1; mixer_vscroll_delta += 1; break; case KEY_C3: mixer_hscroll_delta += 1; mixer_vscroll_delta += 1; break; case KEY_RIGHT: case 'n': mixer_hscroll_delta += 1; break; case KEY_LEFT: case 'p': mixer_hscroll_delta -= 1; break; case KEY_UP: case 'w': case 'W': mixer_vscroll_delta -= 1; break; case KEY_DOWN: case 'x': case 'X': mixer_vscroll_delta += 1; break; case KEY_PPAGE: case 'B': case 'b': mixer_vscroll_delta -= (mixer_max_y - 5) / 2; break; case KEY_NPAGE: case ' ': mixer_vscroll_delta += (mixer_max_y - 5) / 2; break; case KEY_BEG: case KEY_HOME: mixer_hscroll_delta -= 0xffffff; break; case KEY_LL: case KEY_END: mixer_hscroll_delta += 0xffffff; break; } if (key && ((mixer_view == VIEW_CHANNELS) || (mixer_view == VIEW_PLAYBACK) || (mixer_view == VIEW_CAPTURE)) ) switch (key) { case KEY_RIGHT: case 'n': mixer_focus_elem += 1; break; case KEY_LEFT: case 'p': mixer_focus_elem -= 1; break; case KEY_PPAGE: mixer_set_delta(5); break; case KEY_NPAGE: mixer_set_delta(-5); break;#if 0 case KEY_BEG: case KEY_HOME: mixer_set_delta(100); break;#endif case KEY_LL: case KEY_END: mixer_set_delta(-100); break; case '+': mixer_set_delta(1); break; case '-': mixer_set_delta(-1); break; case 'w': case KEY_UP: mixer_set_delta(1); case 'W': mixer_add_delta(1); break; case 'x': case KEY_DOWN: mixer_set_delta(-1); case 'X': mixer_add_delta(-1); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': mixer_volume_absolute = 10 * (key - '0'); break; case 'q': mixer_volume_delta[MIXER_CHN_LEFT] = 1; case 'Q': mixer_volume_delta[MIXER_CHN_LEFT] += 1; break; case 'y': case 'z': mixer_volume_delta[MIXER_CHN_LEFT] = -1; case 'Y': case 'Z': mixer_volume_delta[MIXER_CHN_LEFT] += -1; break; case 'e': mixer_volume_delta[MIXER_CHN_RIGHT] = 1; case 'E': mixer_volume_delta[MIXER_CHN_RIGHT] += 1; break; case 'c': mixer_volume_delta[MIXER_CHN_RIGHT] = -1; case 'C': mixer_volume_delta[MIXER_CHN_RIGHT] += -1; break; case 'm': case 'M': mixer_toggle_mute |= MIXER_MASK_STEREO; break; case 'b': case 'B': case '=': mixer_balance_volumes = 1; break; case '<': case ',': mixer_toggle_mute |= MIXER_MASK_LEFT; break; case '>': case '.': mixer_toggle_mute |= MIXER_MASK_RIGHT; break; case ' ': mixer_toggle_capture |= MIXER_MASK_STEREO; break; case KEY_IC: case ';': mixer_toggle_capture |= MIXER_MASK_LEFT; break; case '\'': case KEY_DC: mixer_toggle_capture |= MIXER_MASK_RIGHT; break; } if (old_view != mixer_view) mixer_clear (FALSE); if (! mixer_n_view_elems) mixer_focus_elem = 0; else mixer_focus_elem = CLAMP (mixer_focus_elem, 0, mixer_n_view_elems - 1); return finished;}static voidmixer_winch (void){ signal (SIGWINCH, (void*) mixer_winch); mixer_needs_resize++;}static voidmixer_signal_handler (int signal){ if (signal != SIGSEGV) mixer_abort (ERR_SIGNAL, strsignal(signal), 0); else { fprintf (stderr, "\nSegmentation fault.\n"); _exit (11); }}intmain (int argc, char **argv){ int opt; /* parse args */ do { opt = getopt (argc, argv, "c:D:shgV:a:"); switch (opt) { case '?': case 'h': printf ("%s v%s\n", PRGNAME_UPPER, VERSION); printf ("Usage: %s [-h] [-c <card: 0...7>] [-D <mixer device>] [-g] [-s] [-V <view>] [-a <abst>]\n", PRGNAME); return 1; case 'c': { int i = snd_card_get_index(optarg); if (i < 0 || i > 31) { fprintf (stderr, "wrong -c argument '%s'\n", optarg); mixer_abort (ERR_NONE, "", 0); } sprintf(card_id, "hw:%i", i); } break; case 'D': strncpy(card_id, optarg, sizeof(card_id)); card_id[sizeof(card_id)-1] = '\0'; break; case 'g': mixer_do_color = !mixer_do_color; break; case 's': mixer_minimize = 1; break; case 'V': if (*optarg == 'p' || *optarg == 'P') mixer_view = VIEW_PLAYBACK; else if (*optarg == 'c' || *optarg == 'C') mixer_view = VIEW_CAPTURE; else mixer_view = VIEW_CHANNELS; break; case 'a': mixer_level = 1; memset(&mixer_options, 0, sizeof(mixer_options)); mixer_options.ver = 1; if (!strcmp(optarg, "none")) mixer_options.abstract = SND_MIXER_SABSTRACT_NONE; else if (!strcmp(optarg, "basic")) mixer_options.abstract = SND_MIXER_SABSTRACT_BASIC; else { fprintf(stderr, "Select correct abstraction level (none or basic)...\n"); mixer_abort (ERR_NONE, "", 0); } break; } } while (opt > 0); mixer_options.device = card_id; /* initialize mixer */ mixer_init (); mixer_reinit (); if (mixer_n_elems == 0) { fprintf(stderr, "No mixer elems found\n"); mixer_abort (ERR_NONE, "", 0); } /* setup signal handlers */ signal (SIGINT, mixer_signal_handler); signal (SIGTRAP, mixer_signal_handler); // signal (SIGABRT, mixer_signal_handler); signal (SIGQUIT, mixer_signal_handler); signal (SIGBUS, mixer_signal_handler); signal (SIGSEGV, mixer_signal_handler); signal (SIGPIPE, mixer_signal_handler); signal (SIGTERM, mixer_signal_handler); /* initialize ncurses */ mixer_init_window (); if (mixer_max_x < MIXER_MIN_X || mixer_max_y < MIXER_MIN_Y) beep (); // mixer_abort (ERR_WINSIZE, ""); signal (SIGWINCH, (void*) mixer_winch); do { /* draw window upon every iteration */ if (!mixer_needs_resize) { switch (mixer_view) { case VIEW_CHANNELS: case VIEW_PLAYBACK: case VIEW_CAPTURE: mixer_update_cbars (); break; case VIEW_HELP: mixer_show_text ("Help", mixer_help_text, &mixer_help_xoffs, &mixer_help_yoffs); break; case VIEW_PROCINFO: mixer_show_procinfo (); break; } mixer_draw_frame (); refresh (); } } while (!mixer_iteration ()); mixer_abort (ERR_NONE, "", 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -