127 lines
3.2 KiB
C
127 lines
3.2 KiB
C
/* vim: tabstop=4 shiftwidth=4 noexpandtab
|
|
* This file is part of ToaruOS and is released under the terms
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
* Copyright (C) 2015 Mike Gerow
|
|
*/
|
|
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
|
|
#include <kernel/mod/sound.h>
|
|
|
|
static char usage[] =
|
|
"%s - Control audio mixer settings.\n"
|
|
"\n"
|
|
"Usage %s [-d device_id] -l\n"
|
|
" %s [-d device_id] [-k knob_id] -r\n"
|
|
" %s [-d device_id] [-k knob_id] -w knob_value\n"
|
|
" %s -h\n"
|
|
"\n"
|
|
" -d: \033[3mDevice id to address. Defaults to the main sound device.\033[0m\n"
|
|
" -l: \033[3mList the knobs on a device.\033[0m\n"
|
|
" -k: \033[3mKnob id to address. Defaults to the device's master knob.\033[0m\n"
|
|
" -r: \033[3mPerform a read on the given device's knob. Defaults to the device's\n"
|
|
" master knob.\033[0m\n"
|
|
" -w: \033[3mPerform a write on the given device's knob. The value should be a\n"
|
|
" float from 0.0 to 1.0.\033[0m\n"
|
|
" -h: \033[3mPrint this help message and exit.\033[0m\n";
|
|
|
|
int main(int argc, char * argv[]) {
|
|
uint32_t device_id = SND_DEVICE_MAIN;
|
|
uint32_t knob_id = SND_KNOB_MASTER;
|
|
uint8_t list_flag = 0;
|
|
uint8_t read_flag = 0;
|
|
uint8_t write_flag = 0;
|
|
double write_value = 0.0;
|
|
|
|
int c;
|
|
|
|
while ((c = getopt(argc, argv, "d:lk:rw:h?")) != -1) {
|
|
switch (c) {
|
|
case 'd':
|
|
device_id = atoi(optarg);
|
|
break;
|
|
case 'l':
|
|
list_flag = 1;
|
|
break;
|
|
case 'k':
|
|
knob_id = atoi(optarg);
|
|
break;
|
|
case 'r':
|
|
read_flag = 1;
|
|
break;
|
|
case 'w':
|
|
write_flag = 1;
|
|
write_value = atof(optarg);
|
|
if (write_value < 0.0 || write_value > 1.0) {
|
|
fprintf(stderr, "argument -w value must be between 0.0 and 1.0\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
break;
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
fprintf(stderr, usage, argv[0], argv[0], argv[0], argv[0], argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
int mixer = open("/dev/mixer", O_RDONLY);
|
|
if (mixer < 1) {
|
|
//perror("open");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (list_flag) {
|
|
snd_knob_list_t list = {0};
|
|
list.device = device_id;
|
|
if (ioctl(mixer, SND_MIXER_GET_KNOBS, &list) < 0) {
|
|
perror("ioctl");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
for (uint32_t i = 0; i < list.num; i++) {
|
|
snd_knob_info_t info = {0};
|
|
info.device = device_id;
|
|
info.id = list.ids[i];
|
|
if (ioctl(mixer, SND_MIXER_GET_KNOB_INFO, &info) < 0) {
|
|
perror("ioctl");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
fprintf(stdout, "%d: %s\n", (unsigned int)info.id, info.name);
|
|
}
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
if (read_flag) {
|
|
snd_knob_value_t value = {0};
|
|
value.device = device_id;
|
|
value.id = knob_id;
|
|
if (ioctl(mixer, SND_MIXER_READ_KNOB, &value) < 0) {
|
|
perror("ioctl");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
double double_val = (double)value.val / SND_KNOB_MAX_VALUE;
|
|
fprintf(stdout, "%f\n", double_val);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (write_flag) {
|
|
snd_knob_value_t value = {0};
|
|
value.device = device_id;
|
|
value.id = knob_id;
|
|
value.val = (uint32_t)(write_value * SND_KNOB_MAX_VALUE);
|
|
if (ioctl(mixer, SND_MIXER_WRITE_KNOB, &value) < 0) {
|
|
perror("ioctl");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
fprintf(stderr, "No operation specified.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|