/* * Jamie Guinan, December 1998. * * Interactive sound parameter mucker. * */ #include #include #include #include #include #include static struct { const char *label; int value; int supported; int mask; int write_ioctl; int read_ioctl; } sound_params[] = { "volume", 0, 0, SOUND_MASK_VOLUME, SOUND_MIXER_WRITE_VOLUME, SOUND_MIXER_READ_VOLUME, "bass", 0, 0, SOUND_MASK_BASS, SOUND_MIXER_WRITE_BASS, SOUND_MIXER_READ_BASS, "treble", 0, 0, SOUND_MASK_TREBLE, SOUND_MIXER_WRITE_TREBLE, SOUND_MIXER_READ_TREBLE, "synth", 0, 0, SOUND_MASK_SYNTH, SOUND_MIXER_WRITE_SYNTH, SOUND_MIXER_READ_SYNTH, "pcm", 0, 0, SOUND_MASK_PCM, SOUND_MIXER_WRITE_PCM, SOUND_MIXER_READ_PCM, "speaker", 0, 0, SOUND_MASK_SPEAKER, SOUND_MIXER_WRITE_SPEAKER, SOUND_MIXER_READ_SPEAKER, "line", 0, 0, SOUND_MASK_LINE, SOUND_MIXER_WRITE_LINE, SOUND_MIXER_READ_LINE, "mic", 0, 0, SOUND_MASK_MIC, SOUND_MIXER_WRITE_MIC, SOUND_MIXER_READ_MIC, "cd", 0, 0, SOUND_MASK_CD, SOUND_MIXER_WRITE_CD, SOUND_MIXER_READ_CD, "imix", 0, 0, SOUND_MASK_IMIX, SOUND_MIXER_WRITE_IMIX, SOUND_MIXER_READ_IMIX, "altpcm", 0, 0, SOUND_MASK_ALTPCM, SOUND_MIXER_WRITE_ALTPCM, SOUND_MIXER_READ_ALTPCM, "reclev", 0, 0, SOUND_MASK_RECLEV, SOUND_MIXER_WRITE_RECLEV, SOUND_MIXER_READ_RECLEV, "igain", 0, 0, SOUND_MASK_IGAIN, SOUND_MIXER_WRITE_IGAIN, SOUND_MIXER_READ_IGAIN, "ogain", 0, 0, SOUND_MASK_OGAIN, SOUND_MIXER_WRITE_OGAIN, SOUND_MIXER_READ_OGAIN, "line1", 0, 0, SOUND_MASK_LINE1, SOUND_MIXER_WRITE_LINE1, SOUND_MIXER_READ_LINE1, NULL, 0, 0, 0 ,0 }; static void get_supported() { int index; int mixer_fd; int value; mixer_fd = open("/dev/mixer", O_RDWR); if (mixer_fd == -1) { printf("failed to open /dev/mixer\n"); return; } ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &value); close(mixer_fd); index = 0; while (sound_params[index].label != NULL) { if (value & sound_params[index].mask) { sound_params[index].supported = 1; } index++; } } static void get_params() { int index; int mixer_fd; mixer_fd = open("/dev/mixer", O_RDWR); if (mixer_fd == -1) { printf("failed to open /dev/mixer\n"); return; } index = 0; while (sound_params[index].label != NULL) { ioctl(mixer_fd, sound_params[index].read_ioctl, &sound_params[index].value); index++; } close(mixer_fd); } static void show_params() { int index; index = 0; while (sound_params[index].label != NULL) { printf("%8s: left=%03d right=%03d %s\n", sound_params[index].label, sound_params[index].value & 0x7F, (sound_params[index].value >> 8) & 0x7F, (sound_params[index].supported ? "":"(not supported)")); index++; } putchar('\n'); } static int set_param(const char *label, int left, int right) { int index; int done; int mixer_fd; int value; value = (left & 0x7f) + ((right & 0x7F) << 8); index = 0; done = 0; while (!done && (sound_params[index].label != NULL)) { if (strncmp(sound_params[index].label, label, strlen(label)) == 0) { mixer_fd = open("/dev/mixer", O_RDWR); if (mixer_fd == -1) { printf("failed to open /dev/mixer\n"); return -1; } ioctl(mixer_fd, sound_params[index].write_ioctl, &value); close(mixer_fd); done=1; } index++; } if (!done) { return -1; } return 0; } static void main_usage() { printf("\nPlease type: label left right\n"); printf("Example: volume 80 80\n"); printf("Matching suffixes work, such as \"v\" for volume or \"r\" for reclev\n"); printf("cntrl-d (EOF) quits\n\n"); } int main() { char buff[80]; int l, r; char label[80]; #define PROMPT "(ctrl-d:quit ?:help return:show settings)\njmix> " get_supported(); get_params(); show_params(); fputs(PROMPT, stdout); while (fgets(buff, sizeof(buff), stdin)) { if (buff[0] == '\r' || buff[0] == '\n') { show_params(); } else if (sscanf(buff, "%s %d %d", label, &l, &r) != 3) { main_usage(); } else { if (set_param(label, l, r) == 0) { get_params(); show_params(); } else { main_usage(); } } fputs(PROMPT, stdout); } putchar('\n'); return 0; }