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

Reply via email to