Enhanced syntax for sset (channels, direction)

This commit is contained in:
Jaroslav Kysela 2001-08-27 09:15:44 +00:00
parent abe718c7cf
commit ea8fe975d9

View file

@ -301,6 +301,36 @@ static int get_volume_simple(char **ptr, int min, int max, int orig)
return tmp1;
}
static int get_bool_simple(char **ptr, char *str, int invert, int orig)
{
if (**ptr == ':')
(*ptr)++;
if (!strncasecmp(*ptr, str, strlen(str))) {
orig = 1 ^ (invert ? 1 : 0);
while (**ptr != '\0' && **ptr != ',' && **ptr != ':')
(*ptr)++;
}
if (**ptr == ',' || **ptr == ':')
(*ptr)++;
return orig;
}
static int simple_skip_word(char **ptr, char *str)
{
char *xptr = *ptr;
if (*xptr == ':')
xptr++;
if (!strncasecmp(xptr, str, strlen(str))) {
while (*xptr != '\0' && *xptr != ',' && *xptr != ':')
xptr++;
if (*xptr == ',' || *xptr == ':')
xptr++;
*ptr = xptr;
return 1;
}
return 0;
}
static void show_control_id(snd_ctl_elem_id_t *id)
{
unsigned int index, device, subdevice;
@ -991,15 +1021,37 @@ static channel_mask_t chanmask[] = {
{NULL, 0}
};
static unsigned int channels_mask(char *arg)
static unsigned int channels_mask(char **arg, unsigned int def)
{
channel_mask_t *c;
for (c = chanmask; c->name; c++) {
if (strncmp(arg, c->name, strlen(c->name)) == 0)
if (strncasecmp(*arg, c->name, strlen(c->name)) == 0) {
while (**arg != '\0' && **arg != ',' && **arg != ' ' && **arg != '\t')
(*arg)++;
if (**arg == ',' || **arg == ' ' || **arg == '\t')
(*arg)++;
return c->mask;
}
return ~0U;
}
return def;
}
static unsigned int dir_mask(char **arg, unsigned int def)
{
int findend = 0;
if (strncasecmp(*arg, "playback", 8) == 0)
def = findend = 1;
else if (strncasecmp(*arg, "capture", 8) == 0)
def = findend = 2;
if (findend) {
while (**arg != '\0' && **arg != ',' && **arg != ' ' && **arg != '\t')
(*arg)++;
if (**arg == ',' || **arg == ' ' || **arg == '\t')
(*arg)++;
}
return def;
}
static int sset(unsigned int argc, char *argv[], int roflag)
@ -1007,8 +1059,9 @@ static int sset(unsigned int argc, char *argv[], int roflag)
int err;
unsigned int idx;
snd_mixer_selem_channel_id_t chn;
unsigned int channels;
long min, max;
unsigned int channels = ~0UL;
unsigned int dir = 3;
long pmin, pmax, cmin, cmax;
snd_mixer_t *handle;
snd_mixer_elem_t *elem;
snd_mixer_selem_id_t *sid;
@ -1052,53 +1105,86 @@ static int sset(unsigned int argc, char *argv[], int roflag)
snd_mixer_close(handle);
return -ENOENT;
}
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
if (roflag)
goto __skip_write;
snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax);
snd_mixer_selem_get_capture_volume_range(elem, &cmin, &cmax);
for (idx = 1; idx < argc; idx++) {
if (!strncmp(argv[idx], "mute", 4) ||
!strncmp(argv[idx], "off", 3)) {
snd_mixer_selem_set_playback_switch_all(elem, 0);
continue;
} else if (!strncmp(argv[idx], "unmute", 6) ||
!strncmp(argv[idx], "on", 2)) {
snd_mixer_selem_set_playback_switch_all(elem, 1);
continue;
} else if (!strncmp(argv[idx], "cap", 3) ||
!strncmp(argv[idx], "rec", 3)) {
snd_mixer_selem_set_capture_switch_all(elem, 1);
continue;
} else if (!strncmp(argv[idx], "nocap", 5) ||
!strncmp(argv[idx], "norec", 5)) {
snd_mixer_selem_set_capture_switch_all(elem, 0);
continue;
}
channels = channels_mask(argv[idx]);
if (isdigit(argv[idx][0]) ||
argv[idx][0] == '+' ||
argv[idx][0] == '-') {
char *ptr;
char *ptr = argv[idx], *optr;
int multi;
multi = (strchr(argv[idx], ',') != NULL);
ptr = argv[idx];
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
long vol;
if (!(channels & (1 << chn)) ||
!snd_mixer_selem_has_playback_channel(elem, chn))
channels = channels_mask(&ptr, channels);
if (*ptr == '\0')
continue;
dir = dir_mask(&ptr, dir);
if (*ptr == '\0')
continue;
multi = (strchr(ptr, ',') != NULL);
optr = ptr;
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
char *sptr = NULL;
int ival;
long lval;
if (! multi)
ptr = argv[idx];
snd_mixer_selem_get_playback_volume(elem, chn, &vol);
snd_mixer_selem_set_playback_volume(elem, chn, get_volume_simple(&ptr, min, max, vol));
}
if (!(channels & (1 << chn)))
continue;
if ((dir & 1) && snd_mixer_selem_has_playback_channel(elem, chn)) {
sptr = ptr;
if (!strncmp(ptr, "mute", 4) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "mute", 0, ival));
} else if (!strncmp(ptr, "off", 3) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "off", 0, ival));
} else if (!strncmp(ptr, "unmute", 6) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "unmute", 1, ival));
} else if (!strncmp(ptr, "on", 2) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "on", 1, ival));
} else if ((isdigit(*ptr) || *ptr == '-' || *ptr == '+') && snd_mixer_selem_has_playback_volume(elem)) {
snd_mixer_selem_get_playback_volume(elem, chn, &lval);
snd_mixer_selem_set_playback_volume(elem, chn, get_volume_simple(&ptr, pmin, pmax, lval));
} else if (simple_skip_word(&ptr, "cap") || simple_skip_word(&ptr, "rec") ||
simple_skip_word(&ptr, "nocap") || simple_skip_word(&ptr, "norec")) {
/* nothing */
} else {
error("Unknown setup '%s'..\n", argv[idx]);
error("Unknown setup '%s'..\n", ptr);
snd_mixer_close(handle);
return err;
}
}
if ((dir & 2) && snd_mixer_selem_has_capture_channel(elem, chn)) {
if (sptr != NULL)
ptr = sptr;
sptr = ptr;
if (!strncmp(ptr, "cap", 3) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "cap", 0, ival));
} else if (!strncmp(ptr, "rec", 3) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "rec", 0, ival));
} else if (!strncmp(ptr, "nocap", 5) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "nocap", 1, ival));
} else if (!strncmp(ptr, "norec", 5) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "norec", 1, ival));
} else if ((isdigit(*ptr) || *ptr == '-' || *ptr == '+') && snd_mixer_selem_has_capture_volume(elem)) {
snd_mixer_selem_get_capture_volume(elem, chn, &lval);
snd_mixer_selem_set_capture_volume(elem, chn, get_volume_simple(&ptr, cmin, cmax, lval));
} else if (simple_skip_word(&ptr, "mute") || simple_skip_word(&ptr, "off") ||
simple_skip_word(&ptr, "unmute") || simple_skip_word(&ptr, "on")) {
/* nothing */
} else {
error("Unknown setup '%s'..\n", ptr);
snd_mixer_close(handle);
return err;
}
}
if (!multi)
ptr = optr;
}
}
__skip_write:
if (!quiet) {
printf("Simple mixer control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));