/* * Solaris Audio Mixer thingy :( * * $Id: solaudio.c,v 1.3 2004/08/17 19:39:56 psionic Exp $ */ #include #include #include #include #include #include struct options { uint_t volume; /* Master output volume */ uchar_t muted; /* Muted? */ uint_t port; /* Where is audio going? (headphones, etc) */ }; typedef struct options options_t; void print_status(); void print_info(audio_info_t *info, audio_channel_t *ch); void parse_args(int argc, char **argv); void set_info(options_t *foo, audio_info_t *info, audio_channel_t *chan); void usage(const char *err); /* I'm lazy... */ static char *me; static audio_channel_t ch; static am_control_t *ctl; static int num, audio_fd; int main(int argc, char **argv) { audio_info_t info; int i; audio_fd = open("/dev/audioctl", O_RDWR); me = *argv; if (audio_fd == -1) { printf("Error [/dev/audioctl]: %s\n", strerror(errno)); exit(1); } if (ioctl(audio_fd, AUDIO_GET_NUM_CHS, &num) < 0) { printf("AUDIO_GET_NUM_CHS: %s\n", strerror(errno)); exit(1); } ctl = (am_control_t *)malloc(AUDIO_MIXER_CTL_STRUCT_SIZE(num)); if (ioctl(audio_fd, AUDIO_MIXERCTL_GETINFO, ctl) < 0) { printf("AUDIO_MIXERCTL_GETINFO: %s\n", strerror(errno)); exit(1); } ch.info = &info; ch.info_size = sizeof (audio_info_t); if (argc == 1) { print_status(); } else { parse_args(argc, argv); print_status(); } free(ctl); } void print_status() { int i; audio_info_t maininfo; if (ioctl(audio_fd, AUDIO_GETINFO, &maininfo) >= 0) { print_info(&maininfo, NULL); } for (i = 0; i < num; i++) { if (ctl->ch_open[i] != 0) { ch.ch_number = i; if (ioctl(audio_fd, AUDIO_MIXERCTL_GET_CHINFO, &ch) < 0) { printf("Channel # %d isn't an audio/audioctl device\n", i); } else { audio_info_t *info = (audio_info_t *)ch.info; print_info(info, &ch); } } } } void print_info(audio_info_t *info, audio_channel_t *ch) { float vol = (float)(info->play.gain); if (ch == NULL) printf("Ch# Master"); else printf("Ch# %d, PID = %d, Type = %d", ch->ch_number, ch->pid, ch->dev_type); if (info->output_muted) printf(" [MUTED]\n"); else printf("\n"); printf("\tVolume: %.0f%%\n", (vol / AUDIO_MAX_GAIN) * 100.0); } void parse_args(int argc, char **argv) { audio_info_t maininfo; char **p = argv; int gain; char *param; char done; int i; options_t foo; foo.muted = 0; foo.volume = 0; foo.port = 0; while (*++p != NULL && **p == '-') { done = 0; while (!done && *++*p != '\0') { /* printf("Flag: %c\n", **p); */ switch (**p) { case 'h': usage(NULL); break; case 'm': printf("Toggling mute\n"); foo.muted = 1; break; case 'p': printf("Toggling Headphones\n"); foo.port |= AUDIO_HEADPHONE; break; case 'l': printf("Toggling Line Out\n"); foo.port |= AUDIO_LINE_OUT; break; case 's': printf("Toggling Internal Speaker\n"); foo.port |= AUDIO_SPEAKER; break; case 'v': //printf("---> %c\n", if (*(*p + 1) == NULL) if (*(p + 1) == NULL) usage("-v requires a value (0-100)"); else { param = *(p + 1); /* Move to next word */ p++; } else { param = *p + 1; } /* Move to the next word... */ p++; printf("Word: %s\n", param); gain = atoi(param); if (gain < 0 || gain > 100) usage("Volume values are range 0-100 inclusive."); foo.volume = (int)((gain / 100.0) * 255.0); done = 1; break; default: /* Call usage() instead? */ printf("Invalid argument: %c\n", **p); break; } for (i = 0; i < num; i++) { if (ctl->ch_open[i] != 0) { ch.ch_number = i; if (ioctl(audio_fd, AUDIO_MIXERCTL_GET_CHINFO, &ch) < 0) { printf("Channel # %d isn't an audio/audioctl device\n", i); } else { audio_info_t *info = (audio_info_t *)ch.info; set_info(&foo, info, &ch); } } } if (ioctl(audio_fd, AUDIO_GETINFO, &maininfo) >= 0) { set_info(&foo, &maininfo, NULL); } } } } void set_info(options_t *foo, audio_info_t *info, audio_channel_t *chan) { char chname[10] = "main"; if (chan != NULL) sprintf(chname, "%d", chan->ch_number); else { if (foo->muted) { /* printf("Muting channel %s / %d / %d\n", chname, info->output_muted, foo->muted); */ info->output_muted ^= foo->muted; } } if (foo->volume) info->play.gain = foo->volume; if (foo->port) info->play.port ^= foo->port; if (ioctl(audio_fd, AUDIO_SETINFO, info) < 0) { printf("Warning: Failed setting audio channel info for channel %s", chname); if (chan != NULL) printf("[PID: %d].\n", chan->pid); } } void usage(const char *err) { if (err != NULL) printf("Error: %s\n", err); printf("Usage: %s [ -mslp -v <0-100> ]\n", me); printf("\t-m toggle mute\n"); printf("\t-l toggle line-out\n"); printf("\t-p toggle headphones\n"); printf("\t-s toggle internal speaker\n"); printf("\t-v <0-100> set volume percentage level\n"); exit(1); }