diff --git a/libsndio/sioctl_open.3 b/libsndio/sioctl_open.3 index 5e733c1..2909b70 100644 --- a/libsndio/sioctl_open.3 +++ b/libsndio/sioctl_open.3 @@ -127,6 +127,7 @@ struct sioctl_desc { #define SIOCTL_SW 3 /* on/off switch (0 or 1) */ #define SIOCTL_VEC 4 /* number, element of vector */ #define SIOCTL_LIST 5 /* switch, element of a list */ +#define SIOCTL_SEL 6 /* element of a selector */ unsigned int type; /* one of above */ char func[SIOCTL_NAMEMAX]; /* function name, ex. "level" */ char group[SIOCTL_NAMEMAX]; /* group this control belongs to */ @@ -167,6 +168,10 @@ from the line input to the speaker. An element of an array of on/off switches. For instance the line-in position of the speaker source selector. +.It SIOCTL_SEL +Same as +.Va SIOCTL_LIST +but exactly one element is selected at a time. .El .Pp The @@ -182,9 +187,10 @@ attributes indicate the names of the controlled nodes, typically channels of audio streams. .Va node1 is meaningful for -.Va SIOCTL_VEC +.Va SIOCTL_VEC , +.Va SIOCTL_LIST , and -.Va SIOCTL_LIST +.Va SIOCTL_SEL only. .Pp Names in the diff --git a/libsndio/sndio.h b/libsndio/sndio.h index 292227c..19ad612 100644 --- a/libsndio/sndio.h +++ b/libsndio/sndio.h @@ -108,6 +108,7 @@ struct sioctl_desc { #define SIOCTL_SW 3 /* on/off switch (0 or 1) */ #define SIOCTL_VEC 4 /* number, element of vector */ #define SIOCTL_LIST 5 /* switch, element of a list */ +#define SIOCTL_SEL 6 /* element of a selector */ unsigned int type; /* one of above */ char func[SIOCTL_NAMEMAX]; /* function name, ex. "level" */ char group[SIOCTL_NAMEMAX]; /* group this control belongs to */ diff --git a/sndioctl/sndioctl.c b/sndioctl/sndioctl.c index 56d7211..37b61ea 100644 --- a/sndioctl/sndioctl.c +++ b/sndioctl/sndioctl.c @@ -107,7 +107,8 @@ cmpdesc(struct sioctl_desc *d1, struct sioctl_desc *d2) if (res != 0) return res; res = d1->node0.unit - d2->node0.unit; - if (d1->type == SIOCTL_VEC || + if (d1->type == SIOCTL_SEL || + d1->type == SIOCTL_VEC || d1->type == SIOCTL_LIST) { if (res != 0) return res; @@ -297,6 +298,7 @@ ismono(struct info *g) return 0; } break; + case SIOCTL_SEL: case SIOCTL_VEC: case SIOCTL_LIST: for (p2 = g; p2 != NULL; p2 = nextpar(p2)) { @@ -345,6 +347,7 @@ print_desc(struct info *p, int mono) case SIOCTL_SW: printf("*"); break; + case SIOCTL_SEL: case SIOCTL_VEC: case SIOCTL_LIST: more = 0; @@ -358,7 +361,8 @@ print_desc(struct info *p, int mono) if (more) printf(","); print_node(&e->desc.node1, mono); - printf(":*"); + if (p->desc.type != SIOCTL_SEL) + printf(":*"); more = 1; } } @@ -394,6 +398,7 @@ print_ent(struct info *e, char *comment) case SIOCTL_NONE: printf("\n"); break; + case SIOCTL_SEL: case SIOCTL_VEC: case SIOCTL_LIST: print_node(&e->desc.node1, 0); @@ -422,6 +427,7 @@ print_val(struct info *p, int mono) case SIOCTL_SW: print_num(p); break; + case SIOCTL_SEL: case SIOCTL_VEC: case SIOCTL_LIST: more = 0; @@ -621,6 +627,9 @@ dump(void) case SIOCTL_SW: printf("0..%d (%u)", i->desc.maxval, i->curval); break; + case SIOCTL_SEL: + print_node(&i->desc.node1, 0); + break; case SIOCTL_VEC: case SIOCTL_LIST: print_node(&i->desc.node1, 0); @@ -700,6 +709,7 @@ cmd(char *line) npar++; } break; + case SIOCTL_SEL: case SIOCTL_VEC: case SIOCTL_LIST: for (i = g; i != NULL; i = nextpar(i)) { @@ -889,17 +899,36 @@ ondesc(void *arg, struct sioctl_desc *d, int curval) void onctl(void *arg, unsigned addr, unsigned val) { - struct info *i; + struct info *i, *j; - for (i = infolist; i != NULL; i = i->next) { - if (i->ctladdr != addr) - continue; - if (i->curval != val) { - i->curval = val; - if (m_flag) - print_ent(i, "changed"); - } + i = infolist; + for (;;) { + if (i == NULL) + return; + if (i->ctladdr == addr) + break; + i = i->next; } + + if (i->curval == val) { + print_ent(i, "eq"); + return; + } + + if (i->desc.type == SIOCTL_SEL) { + for (j = infolist; j != NULL; j = j->next) { + if (strcmp(i->desc.group, j->desc.group) != 0 || + strcmp(i->desc.node0.name, j->desc.node0.name) != 0 || + strcmp(i->desc.func, j->desc.func) != 0 || + i->desc.node0.unit != j->desc.node0.unit) + continue; + j->curval = (i->ctladdr == j->ctladdr); + } + } else + i->curval = val; + + if (m_flag) + print_ent(i, "changed"); } int diff --git a/sndiod/dev.c b/sndiod/dev.c index f46723d..3c4b8d3 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -2297,6 +2297,7 @@ ctl_log(struct ctl *c) break; case CTL_VEC: case CTL_LIST: + case CTL_SEL: ctl_node_log(&c->node1); log_puts(":"); log_putu(c->curval); @@ -2321,7 +2322,7 @@ dev_addctl(struct dev *d, char *gstr, int type, int addr, strlcpy(c->group, gstr, CTL_NAMEMAX); strlcpy(c->node0.name, str0, CTL_NAMEMAX); c->node0.unit = unit0; - if (c->type == CTL_VEC || c->type == CTL_LIST) { + if (c->type == CTL_VEC || c->type == CTL_LIST || c->type == CTL_SEL) { strlcpy(c->node1.name, str1, CTL_NAMEMAX); c->node1.unit = unit1; } else diff --git a/sndiod/dev.h b/sndiod/dev.h index fb4dfbc..cbca055 100644 --- a/sndiod/dev.h +++ b/sndiod/dev.h @@ -126,6 +126,7 @@ struct ctl { #define CTL_SW 3 /* on/off switch, only bit 7 counts */ #define CTL_VEC 4 /* number, element of vector */ #define CTL_LIST 5 /* switch, element of a list */ +#define CTL_SEL 6 /* element of a selector */ unsigned int type; /* one of above */ unsigned int addr; /* control address */ #define CTL_NAMEMAX 16 /* max name lenght */