On Mon, May 09, 2011 at 01:32:49AM +0300, Sviatoslav Chagaev wrote: > * sorted output looks cleaner, prettier; > * it's easier to find the variable you're looking for in a sorted > output; > * hierarchical variable names yet unordered? doesn't make sense; > * this way mixerctl's behaviour will be closer to other *ctl programs > which output variables in an ordered fashion (audioctl, sysctl, > wsconsctl).
these are all matters of opinion, except for "hierarchical variable names" which is not technically the case here. > Before: note how the controls are grouped (mostly) by "widget". please read azalia(4). > s@d630:0:/usr/src/usr.bin/mixerctl$ mixerctl > outputs.hp_source=dac-0:1 > outputs.hp_dir=output > outputs.hp_boost=off > outputs.line-in_source=dac-2:3 > outputs.line-in_dir=input > outputs.mic_dir=input-vr80 > outputs.spkr_source=dac-2:3 > outputs.spkr_dir=none > outputs.spkr_boost=off > inputs.dac-2:3_mute=off > inputs.dac-2:3=152,152 > inputs.dac-0:1_mute=off > inputs.dac-0:1=152,152 > inputs.sel_source=mic > outputs.sel=126,126 > inputs.sel2_source=line-in > outputs.sel2=126,126 > inputs.sel3_source=sel > inputs.sel3_sel=119,119 > inputs.sel4_source=sel2 > inputs.sel4_sel2=119,119 > record.adc-0:1_source=sel3 > record.adc-0:1_mute=off > record.adc-2:3_source=sel4 > record.adc-2:3_mute=off > inputs.beep=85 and at the end are the "pseudo" controls. the ones most people are most interested in. so even if the rest of the controls scroll by when you do a simple "mixerctl", you see these controls. > outputs.hp_sense=plugged > outputs.line-in_sense=unplugged > outputs.spkr_muters=hp,line-in > outputs.master=153,153 > outputs.master.mute=off > outputs.master.slaves=dac-2:3,dac-0:1 > record.volume=0,0 > record.volume.mute=off > record.volume.slaves=adc-0:1,adc-2:3 > > After: > s@d630:0:/usr/src/usr.bin/mixerctl$ ./mixerctl > inputs.beep=85 > inputs.dac-0:1=152,152 > inputs.dac-0:1_mute=off > inputs.dac-2:3=152,152 > inputs.dac-2:3_mute=off > inputs.sel2_source=line-in > inputs.sel3_sel=119,119 > inputs.sel3_source=sel > inputs.sel4_sel2=119,119 > inputs.sel4_source=sel2 > inputs.sel_source=mic > outputs.hp_boost=off > outputs.hp_dir=output > outputs.hp_sense=plugged > outputs.hp_source=dac-0:1 > outputs.line-in_dir=input > outputs.line-in_sense=unplugged > outputs.line-in_source=dac-2:3 > outputs.master=153,153 > outputs.master.mute=off > outputs.master.slaves=dac-2:3,dac-0:1 > outputs.mic_dir=input-vr80 > outputs.sel=126,126 > outputs.sel2=126,126 > outputs.spkr_boost=off > outputs.spkr_dir=none > outputs.spkr_muters=hp,line-in > outputs.spkr_source=dac-2:3 > record.adc-0:1_mute=off > record.adc-0:1_source=sel3 > record.adc-2:3_mute=off > record.adc-2:3_source=sel4 > record.volume=0,0 > record.volume.mute=off > record.volume.slaves=adc-0:1,adc-2:3 I do not find this more useful. prettier, perhaps, but not more useful. in particular, this (further) breaks the widget-wise grouping on some devices. please read azalia(4), "inputs" and "outputs" is really just a hint, and making it more precise is much more difficult than adding sorting to mixerctl ... > > > Index: mixerctl.c > =================================================================== > RCS file: /OpenBSD/src/usr.bin/mixerctl/mixerctl.c,v > retrieving revision 1.29 > diff -u -r1.29 mixerctl.c > --- mixerctl.c 12 Nov 2009 07:27:31 -0000 1.29 > +++ mixerctl.c 8 May 2011 22:25:03 -0000 > @@ -46,23 +46,21 @@ > #include <string.h> > #include <unistd.h> > > -struct field *findfield(char *); > -void adjlevel(char **, u_char *, int); > -void catstr(char *, char *, char *); > -void prfield(struct field *, char *, int, mixer_ctrl_t *); > -void rdfield(int, struct field *, char *, int, char *); > -__dead void usage(void); > - > #define FIELD_NAME_MAX 64 > > struct field { > char name[FIELD_NAME_MAX]; > mixer_ctrl_t *valp; > mixer_devinfo_t *infp; > -} *fields, *rfields; > +}; > > -mixer_ctrl_t *values; > -mixer_devinfo_t *infos; > +int fieldcmp(const void *, const void *); > +int fieldnamecmp(const void *, const void *); > +void adjlevel(char **, u_char *, int); > +void catstr(char *, char *, char *); > +void prfield(struct field *, char *, int, mixer_ctrl_t *); > +void rdfield(int, struct field *, char *, int, char *); > +__dead void usage(void); > > void > catstr(char *p, char *q, char *out) > @@ -73,14 +71,19 @@ > strlcpy(out, tmp, FIELD_NAME_MAX); > } > > -struct field * > -findfield(char *name) > +int > +fieldcmp(const void *pa, const void *pb) > { > - int i; > - for (i = 0; fields[i].name[0] != '\0'; i++) > - if (strcmp(fields[i].name, name) == 0) > - return &fields[i]; > - return (0); > + const struct field *a = pa, *b = pb; > + return strcmp(a->name, b->name); > +} > + > +int > +fieldnamecmp(const void *pa, const void *pb) > +{ > + const char *name = pa; > + const struct field *f = pb; > + return strcmp(name, f->name); > } > > #define e_member_name un.e.member[i].label.name > @@ -241,12 +244,15 @@ > int > main(int argc, char **argv) > { > - int fd, i, j, ch, pos; > + int fd, i, ch, pos; > int aflag = 0, qflag = 0, vflag = 0, tflag = 0; > char *file; > char *sep = "="; > - mixer_devinfo_t dinfo; > + mixer_devinfo_t dinfo, *infos; > + mixer_ctrl_t *values; > int ndev; > + struct field *fields, *rfields; > + int nfields; > > if ((file = getenv("MIXERDEVICE")) == 0 || *file == '\0') > file = "/dev/mixer"; > @@ -331,29 +337,31 @@ > } > } > > - for (j = i = 0; i < ndev; i++) { > + for (nfields = i = 0; i < ndev; i++) { > if (infos[i].type != AUDIO_MIXER_CLASS && > infos[i].prev == AUDIO_MIXER_LAST) { > - fields[j++] = rfields[i]; > + fields[nfields++] = rfields[i]; > for (pos = infos[i].next; pos != AUDIO_MIXER_LAST; > pos = infos[pos].next) { > - fields[j] = rfields[pos]; > + fields[nfields] = rfields[pos]; > catstr(rfields[i].name, infos[pos].label.name, > - fields[j].name); > - j++; > + fields[nfields].name); > + nfields++; > } > } > } > > - for (i = 0; i < j; i++) { > + for (i = 0; i < nfields; i++) { > int cls = fields[i].infp->mixer_class; > if (cls >= 0 && cls < ndev) > catstr(infos[cls].label.name, fields[i].name, > fields[i].name); > } > > + qsort(fields, nfields, sizeof *fields, fieldcmp); > + > if (!argc && aflag) { > - for (i = 0; fields[i].name[0] != '\0'; i++) { > + for (i = 0; i < nfields; i++) { > prfield(&fields[i], sep, vflag, fields[i].valp); > printf("\n"); > } > @@ -369,7 +377,9 @@ > ch = 1; > } > > - if ((p = findfield(*argv)) == NULL) { > + p = bsearch(*argv, fields, nfields, sizeof *fields, > + fieldnamecmp); > + if (p == NULL) { > warnx("field %s does not exist", *argv); > } else if (ch || tflag) { > if (tflag && q == NULL) -- jake...@sdf.lonestar.org SDF Public Access UNIX System - http://sdf.lonestar.org