use strings rather than channel numbers

This commit is contained in:
Alexandre Ratchov 2015-03-05 10:12:34 +01:00
parent dfa1d3dd8c
commit 905c319315
11 changed files with 169 additions and 170 deletions

View File

@ -29,7 +29,7 @@
/* /*
* limits * limits
*/ */
#define AMSG_MIX_NAMEMAX 12 /* max name length */ #define AMSG_MIX_NAMEMAX 16 /* max name length */
#define AMSG_MIX_INTMAX 127 /* max channel number */ #define AMSG_MIX_INTMAX 127 /* max channel number */
#define AMSG_MIX_HALF 64 /* also bool threshold */ #define AMSG_MIX_HALF 64 /* also bool threshold */
@ -115,8 +115,7 @@ struct amsg {
*/ */
struct amsg_mix_chan { struct amsg_mix_chan {
char str[AMSG_MIX_NAMEMAX]; /* stream name */ char str[AMSG_MIX_NAMEMAX]; /* stream name */
uint8_t min; /* first channel */ char opt[AMSG_MIX_NAMEMAX]; /* stream name */
uint8_t num; /* number of channels */
}; };
/* /*
@ -125,9 +124,9 @@ struct amsg_mix_chan {
struct amsg_mix_desc { struct amsg_mix_desc {
struct amsg_mix_chan chan0; /* affected channels */ struct amsg_mix_chan chan0; /* affected channels */
struct amsg_mix_chan chan1; /* dito for AMSG_MIX_{SEL,VEC,LIST} */ struct amsg_mix_chan chan1; /* dito for AMSG_MIX_{SEL,VEC,LIST} */
char grp[AMSG_MIX_NAMEMAX]; /* parameter group name */
uint8_t type; /* see siomix_desc structure */ uint8_t type; /* see siomix_desc structure */
uint8_t __pad[1]; uint8_t __pad[1];
char grp[AMSG_MIX_NAMEMAX]; /* parameter group name */
uint16_t addr; /* control address */ uint16_t addr; /* control address */
uint16_t __pad2[1]; uint16_t __pad2[1];
uint16_t curval; uint16_t curval;

View File

@ -172,11 +172,11 @@ _siomix_ondesc_cb(struct siomix_hdl *hdl,
struct siomix_desc *desc, unsigned int val) struct siomix_desc *desc, unsigned int val)
{ {
if (desc) { if (desc) {
DPRINTF("%u -> %s[%u/%u].%s=%s[%u/%u]\n", DPRINTF("%u -> %s[%s].%s=%s[%s]\n",
desc->addr, desc->addr,
desc->chan0.str, desc->chan0.min, desc->chan0.num, desc->chan0.str, desc->chan0.opt,
desc->grp, desc->grp,
desc->chan1.str, desc->chan1.min, desc->chan1.num); desc->chan1.str, desc->chan1.opt);
} }
if (hdl->desc_cb) if (hdl->desc_cb)
hdl->desc_cb(hdl->desc_arg, desc, val); hdl->desc_cb(hdl->desc_arg, desc, val);

View File

@ -75,13 +75,11 @@ siomix_aucat_rdata(struct siomix_aucat_hdl *hdl)
c = hdl->tmp; c = hdl->tmp;
while (size >= sizeof(struct amsg_mix_desc)) { while (size >= sizeof(struct amsg_mix_desc)) {
strlcpy(desc.chan0.str, c->chan0.str, SIOMIX_NAMEMAX); strlcpy(desc.chan0.str, c->chan0.str, SIOMIX_NAMEMAX);
desc.chan0.min = c->chan0.min; strlcpy(desc.chan0.opt, c->chan0.opt, SIOMIX_NAMEMAX);
desc.chan0.num = c->chan0.num;
strlcpy(desc.chan1.str, c->chan1.str, SIOMIX_NAMEMAX); strlcpy(desc.chan1.str, c->chan1.str, SIOMIX_NAMEMAX);
desc.chan1.min = c->chan1.min; strlcpy(desc.chan1.opt, c->chan1.opt, SIOMIX_NAMEMAX);
desc.chan1.num = c->chan1.num;
desc.type = c->type;
strlcpy(desc.grp, c->grp, SIOMIX_NAMEMAX); strlcpy(desc.grp, c->grp, SIOMIX_NAMEMAX);
desc.type = c->type;
desc.addr = ntohs(c->addr); desc.addr = ntohs(c->addr);
_siomix_ondesc_cb(&hdl->siomix, &desc, ntohs(c->curval)); _siomix_ondesc_cb(&hdl->siomix, &desc, ntohs(c->curval));
size -= sizeof(struct amsg_mix_desc); size -= sizeof(struct amsg_mix_desc);

View File

@ -118,8 +118,7 @@ stucture as follows:
.Bd -literal .Bd -literal
struct siomix_chan { struct siomix_chan {
char str[SIOMIX_NAMEMAX]; /* stream name */ char str[SIOMIX_NAMEMAX]; /* stream name */
unsigned int min; /* first channel */ char opt[SIOMIX_NAMEMAX]; /* optionnal channel */
unsigned int num; /* number of channels */
}; };
struct siomix_desc { struct siomix_desc {
@ -184,9 +183,8 @@ The
.Va chan0 .Va chan0
and and
.Va chan1 .Va chan1
attributes indicate the names of the affected streams, the first attributes indicate the names of the affected streams, and
channels and the number of channels affected; zero an optional channel sub-set.
indicates that no channel information is exposed.
.Va chan1 .Va chan1
is meaningful for is meaningful for
.Va SIOMIX_VEC .Va SIOMIX_VEC

View File

@ -149,15 +149,17 @@ siomix_sun_close(struct siomix_hdl *addr)
free(hdl); free(hdl);
} }
/*
* parse foo-4:5 and convert it to "foo", 4, 2
*/
static int static int
copy_ch(struct siomix_sun_hdl *hdl, struct siomix_chan *c, char *istr, int cls) copy_ch(struct siomix_sun_hdl *hdl,
int icls, char *istr, char *ostr, int *rmin, int *rnum)
{ {
size_t len; size_t len;
char *sep, *ostr, *endp; char *sep, *endp;
long min, max; long cmin, cmax;
c->min = c->num = 0;
ostr = c->str;
ostr[0] = 0; ostr[0] = 0;
sep = strchr(istr, '-'); sep = strchr(istr, '-');
@ -169,59 +171,86 @@ copy_ch(struct siomix_sun_hdl *hdl, struct siomix_chan *c, char *istr, int cls)
ostr[len] = 0; ostr[len] = 0;
istr = sep + 1; istr = sep + 1;
min = strtol(istr, &endp, 10); cmin = strtol(istr, &endp, 10);
if (endp != istr) { if (endp != istr) {
/* /*
* this a "foo-0:3" style range * this a "foo-0:3" style range
*/ */
istr = endp; istr = endp;
c->min = min;
c->num = 1;
if (*endp == ':') { if (*endp == ':') {
istr++; istr++;
max = strtol(istr, &endp, 10); cmax = strtol(istr, &endp, 10);
if (endp == istr) { if (endp == istr) {
DPRINTF("bad range\n"); DPRINTF("bad range\n");
return 0; return 0;
} }
istr = endp; istr = endp;
c->num = max - min + 1; } else if (*endp == 0) {
cmax = cmin;
} else {
DPRINTF("unknown range\n");
return 0;
} }
*rmin = cmin;
*rnum = cmax - cmin + 1;
} else { } else {
if (strcmp(ostr, "line") == 0) if (strcmp(ostr, "line") == 0) {
/* rename make "line-foo" to "foo" */
ostr[0] = 0; ostr[0] = 0;
else } else {
/* append unknown suffix with '_' */
strlcat(ostr, "_", SIOMIX_NAMEMAX); strlcat(ostr, "_", SIOMIX_NAMEMAX);
}
strlcat(ostr, istr, SIOMIX_NAMEMAX); strlcat(ostr, istr, SIOMIX_NAMEMAX);
*rmin = 0;
*rnum = 0;
} }
} else { } else {
*rmin = 0;
*rnum = 0;
strlcpy(ostr, istr, SIOMIX_NAMEMAX); strlcpy(ostr, istr, SIOMIX_NAMEMAX);
} }
if (cls == -1) if (icls == -1)
return 1; return 1;
if (strcmp(ostr, "line") == 0) { if (strcmp(ostr, "line") == 0) {
if (cls == hdl->iclass) if (icls == hdl->iclass)
strlcpy(ostr, "in", SIOMIX_NAMEMAX); strlcpy(ostr, "in", SIOMIX_NAMEMAX);
if (cls == hdl->oclass) if (icls == hdl->oclass)
strlcpy(ostr, "out", SIOMIX_NAMEMAX); strlcpy(ostr, "out", SIOMIX_NAMEMAX);
} }
if (strcmp(ostr, "volume") == 0) { if (strcmp(ostr, "volume") == 0) {
if (cls == hdl->rclass) if (icls == hdl->rclass)
strlcpy(ostr, "rec", SIOMIX_NAMEMAX); strlcpy(ostr, "rec", SIOMIX_NAMEMAX);
} }
return 1; return 1;
} }
static void
make_opt(char *opt, int min, int num)
{
switch (num) {
case 0:
opt[0] = 0;
break;
case 1:
snprintf(opt, SIOMIX_NAMEMAX, "%u", min);
break;
default:
snprintf(opt, SIOMIX_NAMEMAX, "%u-%u", min, min + num - 1);
break;
}
}
static int static int
copyname_num(struct siomix_sun_hdl *hdl, copyname_num(struct siomix_sun_hdl *hdl,
struct siomix_desc *desc, struct mixer_devinfo *info) struct mixer_devinfo *info, struct siomix_desc *desc, int *rmin, int *rnum)
{ {
size_t len; size_t len;
char *sep, *istr; char *sep, *istr;
sep = strchr(info->label.name, '_'); sep = strchr(info->label.name, '_');
if (sep) { if (sep) {
strlcpy(desc->grp, "levels", SIOMIX_NAMEMAX); strlcpy(desc->grp, "mix", SIOMIX_NAMEMAX);
desc->type = SIOMIX_VEC; desc->type = SIOMIX_VEC;
len = sep - info->label.name; len = sep - info->label.name;
if (len >= SIOMIX_NAMEMAX - 1) if (len >= SIOMIX_NAMEMAX - 1)
@ -229,29 +258,27 @@ copyname_num(struct siomix_sun_hdl *hdl,
memcpy(desc->chan0.str, info->label.name, len); memcpy(desc->chan0.str, info->label.name, len);
desc->chan0.str[len] = 0; desc->chan0.str[len] = 0;
istr = sep + 1; istr = sep + 1;
if (!copy_ch(hdl, &desc->chan1, istr, info->mixer_class)) if (!copy_ch(hdl, info->mixer_class, istr,
desc->chan1.str, rmin, rnum))
return 0; return 0;
desc->chan0.min = desc->chan1.min;
desc->chan0.num = desc->chan1.num;
} else { } else {
strlcpy(desc->grp, "level", SIOMIX_NAMEMAX); strlcpy(desc->grp, "level", SIOMIX_NAMEMAX);
desc->type = SIOMIX_NUM; desc->type = SIOMIX_NUM;
istr = info->label.name; istr = info->label.name;
if (!copy_ch(hdl, &desc->chan0, istr, info->mixer_class)) if (!copy_ch(hdl, info->mixer_class, istr,
desc->chan0.str, rmin, rnum))
return 0; return 0;
desc->chan1.str[0] = '\0'; desc->chan1.str[0] = '\0';
desc->chan1.min = 0;
desc->chan1.num = 0;
} }
return 1; return 1;
} }
static int static int
copyname_enum(struct siomix_sun_hdl *hdl, copyname_enum(struct siomix_sun_hdl *hdl,
struct siomix_desc *desc, struct mixer_devinfo *info) struct mixer_devinfo *info, struct siomix_desc *desc, int *rmin, int *rnum)
{ {
char istr[SIOMIX_NAMEMAX], *sep; char istr[SIOMIX_NAMEMAX], *sep;
size_t len; size_t len;
sep = strrchr(info->label.name, '.'); sep = strrchr(info->label.name, '.');
if (sep == NULL) if (sep == NULL)
@ -264,9 +291,10 @@ copyname_enum(struct siomix_sun_hdl *hdl,
strlcpy(desc->grp, info->label.name, SIOMIX_NAMEMAX); strlcpy(desc->grp, info->label.name, SIOMIX_NAMEMAX);
while (info->prev >= 0) while (info->prev >= 0)
info = hdl->info + info->prev; info = hdl->info + info->prev;
if (!copy_ch(hdl, &desc->chan0, if (!copy_ch(hdl, info->mixer_class, info->label.name,
info->label.name, info->mixer_class)) desc->chan0.str, rmin, rnum))
return 0; return 0;
desc->chan1.str[0] = 0;
} else { } else {
strlcpy(desc->grp, sep + 1, SIOMIX_NAMEMAX); strlcpy(desc->grp, sep + 1, SIOMIX_NAMEMAX);
len = sep - info->label.name; len = sep - info->label.name;
@ -274,9 +302,10 @@ copyname_enum(struct siomix_sun_hdl *hdl,
return 0; return 0;
memcpy(istr, info->label.name, len); memcpy(istr, info->label.name, len);
istr[len] = '\0'; istr[len] = '\0';
if (!copy_ch(hdl, &desc->chan0, istr, if (!copy_ch(hdl, info->mixer_class, istr,
info->mixer_class)) desc->chan0.str, rmin, rnum))
return 0; return 0;
desc->chan1.str[0] = 0;
} }
/* /*
* certain cards expose adc[0-1].source and adc[2-3].source * certain cards expose adc[0-1].source and adc[2-3].source
@ -324,19 +353,20 @@ enum_to_sw(struct mixer_devinfo *info, struct siomix_desc *desc)
return 0; return 0;
v0 = info->un.e.member[ord_to_num(info, 0)].label.name; v0 = info->un.e.member[ord_to_num(info, 0)].label.name;
v1 = info->un.e.member[ord_to_num(info, 1)].label.name; v1 = info->un.e.member[ord_to_num(info, 1)].label.name;
desc->chan1.str[0] = 0;
desc->chan1.min = 0;
desc->chan1.num = 0;
desc->type = SIOMIX_SW;
if (strcmp(v0, "off") == 0 && strcmp(v1, "on") == 0) if (strcmp(v0, "off") == 0 && strcmp(v1, "on") == 0)
return 1; goto make_sw;
if (strcmp(v0, "unplugged") == 0 && strcmp(v1, "plugged") == 0) { if (strcmp(v0, "unplugged") == 0 && strcmp(v1, "plugged") == 0) {
strlcpy(desc->grp, strlcpy(desc->grp,
info->un.e.member[1].label.name, info->un.e.member[1].label.name,
SIOMIX_NAMEMAX); SIOMIX_NAMEMAX);
return 1; goto make_sw;
} }
return 0; return 0;
make_sw:
desc->chan1.str[0] = 0;
desc->chan1.opt[0] = 0;
desc->type = SIOMIX_SW;
return 1;
} }
static int static int
@ -346,7 +376,8 @@ siomix_sun_ondesc(struct siomix_hdl *addr)
struct mixer_devinfo *info; struct mixer_devinfo *info;
struct mixer_ctrl *ctrl; struct mixer_ctrl *ctrl;
struct siomix_desc desc; struct siomix_desc desc;
int i, j, v; char *ostr;
int i, j, v, cmin, cnum;
for (i = 0; i < hdl->ninfo; i++) { for (i = 0; i < hdl->ninfo; i++) {
info = hdl->info + i; info = hdl->info + i;
@ -373,19 +404,25 @@ siomix_sun_ondesc(struct siomix_hdl *addr)
info = hdl->info; info = hdl->info;
for (i = 0; i < hdl->ninfo; i++) { for (i = 0; i < hdl->ninfo; i++) {
DPRINTF("parsing \"%s\"\n", info->label.name); DPRINTF("psarsing \"%s\"\n", info->label.name);
switch (info->type) { switch (info->type) {
case AUDIO_MIXER_VALUE: case AUDIO_MIXER_VALUE:
desc.addr = i * 32; desc.addr = i * 32;
if (!copyname_num(hdl, &desc, info)) if (!copyname_num(hdl, info, &desc, &cmin, &cnum))
return 0; return 0;
if (info->un.v.num_channels > 1) make_opt(desc.chan0.opt, cmin, cnum);
desc.chan0.num = 1; desc.chan1.opt[0] = 0;
for (j = 0; j < info->un.v.num_channels; j++) { for (j = 0; j < info->un.v.num_channels; j++) {
v = hdl->curval[i].un.value.level[j] * v = hdl->curval[i].un.value.level[j] *
127 / 255; 127 / 255;
ostr = desc.type == SIOMIX_NUM ?
desc.chan0.opt : desc.chan1.opt;
if (info->un.v.num_channels > 1) {
make_opt(ostr, cmin + j, 1);
} else {
make_opt(ostr, cmin, cnum);
}
_siomix_ondesc_cb(&hdl->siomix, &desc, v); _siomix_ondesc_cb(&hdl->siomix, &desc, v);
desc.chan0.min++;
desc.addr++; desc.addr++;
} }
break; break;
@ -393,20 +430,24 @@ siomix_sun_ondesc(struct siomix_hdl *addr)
desc.addr = i * 32; desc.addr = i * 32;
if (info->un.e.num_mem <= 1) if (info->un.e.num_mem <= 1)
break; break;
if (!copyname_enum(hdl, &desc, info)) if (!copyname_enum(hdl, info, &desc, &cmin, &cnum))
return 0; return 0;
if (enum_to_sw(info, &desc)) { if (enum_to_sw(info, &desc)) {
make_opt(desc.chan0.opt, cmin, cnum);
_siomix_ondesc_cb(&hdl->siomix, &desc, _siomix_ondesc_cb(&hdl->siomix, &desc,
ord_to_num(info, hdl->curval[i].un.ord)); ord_to_num(info, hdl->curval[i].un.ord));
break; break;
} }
for (j = 0; j < info->un.e.num_mem; j++) { for (j = 0; j < info->un.e.num_mem; j++) {
if (!copyname_enum(hdl, &desc, info)) if (!copyname_enum(hdl, info,
&desc, &cmin, &cnum))
return 0; return 0;
copy_ch(hdl, &desc.chan1, make_opt(desc.chan0.opt, cmin, cnum);
info->un.e.member[j].label.name, if (!copy_ch(hdl, info->mixer_class,
info->mixer_class); info->un.e.member[j].label.name,
desc.chan1.str, &cmin, &cnum))
return 0;
make_opt(desc.chan1.opt, cmin, cnum);
desc.type = SIOMIX_LIST; desc.type = SIOMIX_LIST;
v = (j == ord_to_num(info, v = (j == ord_to_num(info,
hdl->curval[i].un.ord)) ? 1 : 0; hdl->curval[i].un.ord)) ? 1 : 0;
@ -418,14 +459,16 @@ siomix_sun_ondesc(struct siomix_hdl *addr)
desc.addr = i * 32; desc.addr = i * 32;
if (info->un.s.num_mem == 0) if (info->un.s.num_mem == 0)
break; break;
if (!copyname_enum(hdl, &desc, info)) if (!copyname_enum(hdl, info, &desc, &cmin, &cnum))
return 0; return 0;
make_opt(desc.chan0.opt, cmin, cnum);
desc.type = SIOMIX_LIST; desc.type = SIOMIX_LIST;
for (j = 0; j < info->un.s.num_mem; j++) { for (j = 0; j < info->un.s.num_mem; j++) {
if (!copy_ch(hdl, &desc.chan1, if (!copy_ch(hdl, info->mixer_class,
info->un.s.member[j].label.name, info->un.s.member[j].label.name,
info->mixer_class)) desc.chan1.str, &cmin, &cnum))
return 0; return 0;
make_opt(desc.chan1.opt, cmin, cnum);
_siomix_ondesc_cb(&hdl->siomix, &desc, _siomix_ondesc_cb(&hdl->siomix, &desc,
mask_to_bit(info, j, mask_to_bit(info, j,
hdl->curval[i].un.mask)); hdl->curval[i].un.mask));

View File

@ -98,8 +98,7 @@ struct sio_cap {
*/ */
struct siomix_chan { struct siomix_chan {
char str[SIOMIX_NAMEMAX]; /* stream name */ char str[SIOMIX_NAMEMAX]; /* stream name */
unsigned int min; /* first channel */ char opt[SIOMIX_NAMEMAX]; /* optional (sub-)stream name */
unsigned int num; /* number of channels */
}; };
/* /*

View File

@ -44,13 +44,13 @@ struct info {
int cmpdesc(struct siomix_desc *, struct siomix_desc *); int cmpdesc(struct siomix_desc *, struct siomix_desc *);
int isdiag(struct info *); int isdiag(struct info *);
struct info *selpos(struct info *); struct info *selpos(struct info *);
struct info *vecent(struct info *, char *, unsigned, unsigned); struct info *vecent(struct info *, char *, char *);
struct info *nextgrp(struct info *); struct info *nextgrp(struct info *);
struct info *nextpar(struct info *); struct info *nextpar(struct info *);
struct info *firstent(struct info *, char *); struct info *firstent(struct info *, char *);
struct info *nextent(struct info *, int); struct info *nextent(struct info *, int);
int matchpar(struct info *, char *, unsigned, unsigned); int matchpar(struct info *, char *, char *);
int matchent(struct info *, char *, unsigned, unsigned); int matchent(struct info *, char *, char *);
int ismono(struct info *); int ismono(struct info *);
void print_chan(struct siomix_chan *, int); void print_chan(struct siomix_chan *, int);
void print_desc(struct info *, int); void print_desc(struct info *, int);
@ -58,7 +58,7 @@ void print_val(struct info *, int);
void print_par(struct info *, int); void print_par(struct info *, int);
int parse_name(char **, char *); int parse_name(char **, char *);
int parse_dec(char **, unsigned *); int parse_dec(char **, unsigned *);
int parse_chan(char **, char *, unsigned *, unsigned *); int parse_chan(char **, char *, char *);
int parse_modeval(char **, int *, unsigned *); int parse_modeval(char **, int *, unsigned *);
void dump(void); void dump(void);
int cmd(char *); int cmd(char *);
@ -90,7 +90,7 @@ cmpdesc(struct siomix_desc *d1, struct siomix_desc *d2)
res = strcmp(d1->grp, d2->grp); res = strcmp(d1->grp, d2->grp);
if (res != 0) if (res != 0)
return res; return res;
res = d1->chan0.min - d2->chan0.min; res = strcmp(d1->chan0.opt, d2->chan0.opt);
if (d1->type == SIOMIX_VEC || if (d1->type == SIOMIX_VEC ||
d1->type == SIOMIX_LIST) { d1->type == SIOMIX_LIST) {
if (res != 0) if (res != 0)
@ -98,7 +98,7 @@ cmpdesc(struct siomix_desc *d1, struct siomix_desc *d2)
res = strcmp(d1->chan1.str, d2->chan1.str); res = strcmp(d1->chan1.str, d2->chan1.str);
if (res != 0) if (res != 0)
return res; return res;
res = d1->chan1.min - d2->chan1.min; res = strcmp(d1->chan1.opt, d2->chan0.opt);
} }
return res; return res;
} }
@ -109,12 +109,10 @@ cmpdesc(struct siomix_desc *d1, struct siomix_desc *d2)
int int
isdiag(struct info *e) isdiag(struct info *e)
{ {
if (e->desc.chan0.num == 0 || if (strlen(e->desc.chan0.opt) == 0 ||
e->desc.chan1.num == 0) strlen(e->desc.chan1.opt) == 0)
return 1; return 1;
return return strcmp(e->desc.chan1.opt, e->desc.chan0.opt) == 0;
e->desc.chan1.min == e->desc.chan0.min &&
e->desc.chan1.num == e->desc.chan0.num;
} }
/* /*
@ -136,12 +134,11 @@ selpos(struct info *i)
* find the selector or vector entry with the given name and channels * find the selector or vector entry with the given name and channels
*/ */
struct info * struct info *
vecent(struct info *i, char *vstr, unsigned vmin, unsigned vnum) vecent(struct info *i, char *vstr, char *vopt)
{ {
while (i != NULL) { while (i != NULL) {
if (strcmp(i->desc.chan1.str, vstr) == 0 && if ((strcmp(i->desc.chan1.str, vstr) == 0) &&
i->desc.chan1.num == vnum && (strlen(vopt) == 0 || strcmp(i->desc.chan1.opt, vopt) == 0))
i->desc.chan1.min == vmin)
break; break;
i = i->next; i = i->next;
} }
@ -172,19 +169,16 @@ nextgrp(struct info *i)
struct info * struct info *
nextpar(struct info *i) nextpar(struct info *i)
{ {
char *str, *grp; char *str, *opt, *grp;
unsigned min, num;
grp = i->desc.grp; grp = i->desc.grp;
str = i->desc.chan0.str; str = i->desc.chan0.str;
min = i->desc.chan0.min; opt = i->desc.chan0.opt;
num = i->desc.chan0.num;
for (i = i->next; i != NULL; i = i->next) { for (i = i->next; i != NULL; i = i->next) {
if (strcmp(i->desc.chan0.str, str) != 0 || if (strcmp(i->desc.chan0.str, str) != 0 ||
strcmp(i->desc.grp, grp) != 0) strcmp(i->desc.grp, grp) != 0)
break; break;
if (i->desc.chan0.min != min || if (strcmp(i->desc.chan0.opt, opt) != 0)
i->desc.chan0.num != num)
return i; return i;
} }
return NULL; return NULL;
@ -221,21 +215,18 @@ firstent(struct info *g, char *vstr)
struct info * struct info *
nextent(struct info *i, int mono) nextent(struct info *i, int mono)
{ {
char *str, *grp; char *str, *opt, *grp;
unsigned min, num;
grp = i->desc.grp; grp = i->desc.grp;
str = i->desc.chan0.str; str = i->desc.chan0.str;
min = i->desc.chan0.min; opt = i->desc.chan0.opt;
num = i->desc.chan0.num;
for (i = i->next; i != NULL; i = i->next) { for (i = i->next; i != NULL; i = i->next) {
if (strcmp(i->desc.chan0.str, str) != 0 || if (strcmp(i->desc.chan0.str, str) != 0 ||
strcmp(i->desc.grp, grp) != 0) strcmp(i->desc.grp, grp) != 0)
return NULL; return NULL;
if (mono) if (mono)
return i; return i;
if (i->desc.chan0.min == min && if (strcmp(i->desc.chan0.opt, opt) != 0)
i->desc.chan0.num == num)
return i; return i;
} }
return NULL; return NULL;
@ -245,19 +236,17 @@ nextent(struct info *i, int mono)
* return true if parameter matches the given name and channel range * return true if parameter matches the given name and channel range
*/ */
int int
matchpar(struct info *i, char *astr, unsigned amin, unsigned anum) matchpar(struct info *i, char *astr, char *aopt)
{ {
if (strcmp(i->desc.chan0.str, astr) != 0) if (strcmp(i->desc.chan0.str, astr) != 0)
return 0; return 0;
if (anum == 0) if (strlen(aopt) == 0)
return 1; return 1;
else if (i->desc.chan0.num == 0) { else if (strlen(i->desc.chan0.opt) == 0) {
fprintf(stderr, "range used for parameter with no range\n"); fprintf(stderr, "opt used for parameter with no opt\n");
exit(1); exit(1);
} }
return return strcmp(i->desc.chan0.opt, aopt) == 0;
i->desc.chan0.min >= amin &&
i->desc.chan0.min + i->desc.chan0.num <= amin + anum;
} }
/* /*
@ -265,19 +254,17 @@ matchpar(struct info *i, char *astr, unsigned amin, unsigned anum)
* channel range * channel range
*/ */
int int
matchent(struct info *i, char *vstr, unsigned vmin, unsigned vnum) matchent(struct info *i, char *vstr, char *vopt)
{ {
if (strcmp(i->desc.chan1.str, vstr) != 0) if (strcmp(i->desc.chan1.str, vstr) != 0)
return 0; return 0;
if (vnum == 0) { if (strlen(vopt) == 0)
return 1; return 1;
} else { else if (strlen(i->desc.chan1.opt) == 0) {
if (i->desc.chan1.num == 0) { fprintf(stderr, "opt used for parameter with no opt\n");
fprintf(stderr, "range not allowed\n"); exit(1);
exit(1);
}
} }
return i->desc.chan1.min == vmin && i->desc.chan1.num == vnum; return strcmp(i->desc.chan1.opt, vopt) == 0;
} }
/* /*
@ -311,8 +298,7 @@ ismono(struct info *g)
} else { } else {
e1 = vecent(p1, e1 = vecent(p1,
e2->desc.chan1.str, e2->desc.chan1.str,
p1->desc.chan0.min, p1->desc.chan0.opt);
p1->desc.chan0.num);
if (e1 == NULL) if (e1 == NULL)
continue; continue;
if (e1->curval != e2->curval) if (e1->curval != e2->curval)
@ -332,11 +318,8 @@ void
print_chan(struct siomix_chan *c, int mono) print_chan(struct siomix_chan *c, int mono)
{ {
printf("%s", c->str); printf("%s", c->str);
if (!mono && c->num > 0) { if (!mono && strlen(c->opt) > 0) {
printf("[%u", c->min); printf("[%s]", c->opt);
if (c->num > 1)
printf("-%u", c->min + c->num - 1);
printf("]");
} }
} }
@ -441,7 +424,7 @@ print_par(struct info *p, int mono)
if (i->desc.type != SIOMIX_LABEL) if (i->desc.type != SIOMIX_LABEL)
continue; continue;
if (strcmp(i->desc.chan0.str, p->desc.chan0.str) == 0 && if (strcmp(i->desc.chan0.str, p->desc.chan0.str) == 0 &&
i->desc.chan0.min == p->desc.chan0.min && strcmp(i->desc.chan0.opt, p->desc.chan0.opt) == 0 &&
strlen(i->desc.grp) > 0) { strlen(i->desc.grp) > 0) {
printf("\t# %s", i->desc.grp); printf("\t# %s", i->desc.grp);
} }
@ -507,39 +490,25 @@ parse_dec(char **line, unsigned *num)
* parse a sub-stream, eg. "spkr[4-7]" * parse a sub-stream, eg. "spkr[4-7]"
*/ */
int int
parse_chan(char **line, char *str, unsigned *rmin, unsigned *rnum) parse_chan(char **line, char *str, char *opt)
{ {
char *p = *line; char *p = *line;
unsigned min, max;
if (!parse_name(&p, str)) if (!parse_name(&p, str))
return 0; return 0;
if (*p != '[') { if (*p != '[') {
*rmin = 0; *opt = 0;
*rnum = 0;
*line = p; *line = p;
return 1; return 1;
} }
p++; p++;
if (!parse_dec(&p, &min)) if (!parse_name(&p, opt))
return 0; return 0;
if (*p == '-') {
p++;
if (!parse_dec(&p, &max))
return 0;
if (max < min) {
fprintf(stderr, "%u-%u: bad range\n", min, max);
return 0;
}
} else
max = min;
if (*p != ']') { if (*p != ']') {
fprintf(stderr, "']' expected near '%s'\n", p); fprintf(stderr, "']' expected near '%s'\n", p);
return 0; return 0;
} }
p++; p++;
*rmin = min;
*rnum = max - min + 1;
*line = p; *line = p;
return 1; return 1;
} }
@ -621,11 +590,12 @@ cmd(char *line)
char *pos = line; char *pos = line;
struct info *i, *e, *g; struct info *i, *e, *g;
char grp[SIOMIX_NAMEMAX], astr[SIOMIX_NAMEMAX], vstr[SIOMIX_NAMEMAX]; char grp[SIOMIX_NAMEMAX], astr[SIOMIX_NAMEMAX], vstr[SIOMIX_NAMEMAX];
char aopt[SIOMIX_NAMEMAX], vopt[SIOMIX_NAMEMAX];
unsigned amin, anum, vmin, vnum, val; unsigned amin, anum, vmin, vnum, val;
unsigned npar = 0, nent = 0; unsigned npar = 0, nent = 0;
int comma, mode; int comma, mode;
if (!parse_chan(&pos, astr, &amin, &anum)) if (!parse_chan(&pos, astr, aopt))
return 0; return 0;
if (*pos != '.') { if (*pos != '.') {
fprintf(stderr, "'.' expected near '%s'\n", pos); fprintf(stderr, "'.' expected near '%s'\n", pos);
@ -663,7 +633,7 @@ cmd(char *line)
if (!parse_modeval(&pos, &mode, &val)) if (!parse_modeval(&pos, &mode, &val))
return 0; return 0;
for (i = g; i != NULL; i = nextpar(i)) { for (i = g; i != NULL; i = nextpar(i)) {
if (!matchpar(i, astr, amin, anum)) if (!matchpar(i, astr, aopt))
continue; continue;
i->mode = mode; i->mode = mode;
i->newval = val; i->newval = val;
@ -673,7 +643,7 @@ cmd(char *line)
case SIOMIX_VEC: case SIOMIX_VEC:
case SIOMIX_LIST: case SIOMIX_LIST:
for (i = g; i != NULL; i = nextpar(i)) { for (i = g; i != NULL; i = nextpar(i)) {
if (!matchpar(i, astr, amin, anum)) if (!matchpar(i, astr, aopt))
continue; continue;
for (e = i; e != NULL; e = nextent(e, 0)) { for (e = i; e != NULL; e = nextent(e, 0)) {
e->newval = 0; e->newval = 0;
@ -690,7 +660,7 @@ cmd(char *line)
break; break;
pos++; pos++;
} }
if (!parse_chan(&pos, vstr, &vmin, &vnum)) if (!parse_chan(&pos, vstr, vopt))
return 0; return 0;
if (*pos == ':') { if (*pos == ':') {
pos++; pos++;
@ -702,10 +672,10 @@ cmd(char *line)
} }
nent = 0; nent = 0;
for (i = g; i != NULL; i = nextpar(i)) { for (i = g; i != NULL; i = nextpar(i)) {
if (!matchpar(i, astr, amin, anum)) if (!matchpar(i, astr, aopt))
continue; continue;
for (e = i; e != NULL; e = nextent(e, 0)) { for (e = i; e != NULL; e = nextent(e, 0)) {
if (matchent(e, vstr, vmin, vnum)) { if (matchent(e, vstr, vopt)) {
e->newval = val; e->newval = val;
e->mode = mode; e->mode = mode;
nent++; nent++;
@ -713,7 +683,7 @@ cmd(char *line)
} }
} }
if (nent == 0) { if (nent == 0) {
fprintf(stderr, "%s[%d/%d]: invalid value\n", vstr, vmin, vnum); fprintf(stderr, "%s[%s]: invalid value\n", vstr, vopt);
print_par(g, 0); print_par(g, 0);
exit(1); exit(1);
} }

View File

@ -1148,16 +1148,16 @@ dev_open(struct dev *d)
dev_uniqname(d, "slot", ctlname); dev_uniqname(d, "slot", ctlname);
c = dev_addctl(d, CTL_NUM, c = dev_addctl(d, CTL_NUM,
d->ctl_addr + CTLADDR_SLOT_LEVEL(i), d->ctl_addr + CTLADDR_SLOT_LEVEL(i),
ctlname, 0, 0, "softvol", NULL, 0, 0); ctlname, "", "softvol", NULL, NULL);
c->curval = d->slot[i].vol; c->curval = d->slot[i].vol;
dev_addctl(d, CTL_LABEL, dev_addctl(d, CTL_LABEL,
d->ctl_addr + CTLADDR_SLOT_LABEL(i), d->ctl_addr + CTLADDR_SLOT_LABEL(i),
ctlname, 0, 0, d->slot[i].name, NULL, 0, 0); ctlname, "", d->slot[i].name, NULL, NULL);
} }
dev_uniqname(d, "master", ctlname); dev_uniqname(d, "master", ctlname);
c = dev_addctl(d, CTL_NUM, c = dev_addctl(d, CTL_NUM,
d->ctl_addr + CTLADDR_MASTER, d->ctl_addr + CTLADDR_MASTER,
ctlname, 0, 0, "softvol", NULL, 0, 0); ctlname, "", "softvol", NULL, NULL);
c->curval = d->master; c->curval = d->master;
return 1; return 1;
} }
@ -2030,13 +2030,9 @@ void
ctl_chan_log(struct ctl_chan *c) ctl_chan_log(struct ctl_chan *c)
{ {
log_puts(c->str); log_puts(c->str);
if (c->num > 0) { if (strlen(c->opt) > 0) {
log_puts("["); log_puts("[");
log_putu(c->min); log_puts(c->opt);
if (c->num > 1) {
log_puts("-");
log_putu(c->min + c->num - 1);
}
log_puts("]"); log_puts("]");
} }
} }
@ -2093,8 +2089,7 @@ dev_uniqname(struct dev *d, char *templ, char *name)
*/ */
struct ctl * struct ctl *
dev_addctl(struct dev *d, int type, int addr, dev_addctl(struct dev *d, int type, int addr,
char *str0, int cmin0, int cnum0, char *grp, char *str0, char *opt0, char *grp, char *str1, char *opt1)
char *str1, int cmin1, int cnum1)
{ {
struct ctl *c; struct ctl *c;
@ -2102,13 +2097,11 @@ dev_addctl(struct dev *d, int type, int addr,
c->type = type; c->type = type;
strlcpy(c->grp, grp, CTL_NAMEMAX); strlcpy(c->grp, grp, CTL_NAMEMAX);
strlcpy(c->chan0.str, str0, CTL_NAMEMAX); strlcpy(c->chan0.str, str0, CTL_NAMEMAX);
c->chan0.min = cmin0; strlcpy(c->chan0.opt, opt0, CTL_NAMEMAX);
c->chan0.num = cnum0;
if (c->type == CTL_VEC || if (c->type == CTL_VEC ||
c->type == CTL_LIST) { c->type == CTL_LIST) {
strlcpy(c->chan1.str, str1, CTL_NAMEMAX); strlcpy(c->chan1.str, str1, CTL_NAMEMAX);
c->chan1.min = cmin1; strlcpy(c->chan1.opt, opt1, CTL_NAMEMAX);
c->chan1.num = cnum1;
} else } else
memset(&c->chan1, 0, sizeof(struct ctl_chan)); memset(&c->chan1, 0, sizeof(struct ctl_chan));
c->addr = addr; c->addr = addr;

View File

@ -113,12 +113,11 @@ struct ctl {
#define CTL_LABEL 6 /* attach string to stream */ #define CTL_LABEL 6 /* attach string to stream */
unsigned int type; /* one of above */ unsigned int type; /* one of above */
unsigned int addr; /* control address */ unsigned int addr; /* control address */
#define CTL_NAMEMAX 12 /* max name lenght */ #define CTL_NAMEMAX 16 /* max name lenght */
char grp[CTL_NAMEMAX]; /* parameter group name */ char grp[CTL_NAMEMAX]; /* parameter group name */
struct ctl_chan { struct ctl_chan {
char str[CTL_NAMEMAX]; /* stream name */ char str[CTL_NAMEMAX]; /* stream name */
unsigned int min; /* first channel */ char opt[CTL_NAMEMAX];
unsigned int num; /* number of channels */
} chan0, chan1; /* affected channels */ } chan0, chan1; /* affected channels */
unsigned int val_mask; unsigned int val_mask;
unsigned int desc_mask; unsigned int desc_mask;
@ -290,6 +289,6 @@ int dev_onctl(struct dev *, int, int);
int dev_nctl(struct dev *); int dev_nctl(struct dev *);
void dev_label(struct dev *, int); void dev_label(struct dev *, int);
struct ctl *dev_addctl(struct dev *, int, int, struct ctl *dev_addctl(struct dev *, int, int,
char *, int, int, char *, char *, int, int); char *, char *, char *, char *, char *);
#endif /* !defined(DEV_H) */ #endif /* !defined(DEV_H) */

View File

@ -71,8 +71,8 @@ dev_siomix_ondesc(void *arg, struct siomix_desc *desc, int val)
return; return;
} }
c = dev_addctl(d, desc->type, desc->addr, c = dev_addctl(d, desc->type, desc->addr,
desc->chan0.str, desc->chan0.min, desc->chan0.num, desc->grp, desc->chan0.str, desc->chan0.opt, desc->grp,
desc->chan1.str, desc->chan1.min, desc->chan1.num); desc->chan1.str, desc->chan1.opt);
c->curval = val; c->curval = val;
#ifdef DEBUG #ifdef DEBUG
if (log_level >= 3) { if (log_level >= 3) {

View File

@ -1553,12 +1553,12 @@ sock_buildmsg(struct sock *f)
c->val_mask &= ~mask; c->val_mask &= ~mask;
strlcpy(desc->chan0.str, c->chan0.str, strlcpy(desc->chan0.str, c->chan0.str,
AMSG_MIX_NAMEMAX); AMSG_MIX_NAMEMAX);
desc->chan0.min = c->chan0.min; strlcpy(desc->chan0.opt, c->chan0.opt,
desc->chan0.num = c->chan0.num; AMSG_MIX_NAMEMAX);
strlcpy(desc->chan1.str, c->chan1.str, strlcpy(desc->chan1.str, c->chan1.str,
AMSG_MIX_NAMEMAX); AMSG_MIX_NAMEMAX);
desc->chan1.min = c->chan1.min; strlcpy(desc->chan1.opt, c->chan1.opt,
desc->chan1.num = c->chan1.num; AMSG_MIX_NAMEMAX);
desc->type = c->type; desc->type = c->type;
strlcpy(desc->grp, c->grp, AMSG_MIX_NAMEMAX); strlcpy(desc->grp, c->grp, AMSG_MIX_NAMEMAX);
desc->addr = htons(c->addr); desc->addr = htons(c->addr);