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)
--
[email protected]
SDF Public Access UNIX System - http://sdf.lonestar.org