commit c587058824743fe5faf3ec5b07ca9c89e2459113
parent 0a2cf822789f7543fa5d2329a9f947c1cdca418d
Author: Christos Margiolis <christos@margiolis.net>
Date: Fri, 18 Jun 2021 19:27:15 +0300
mixer_lib: added `mixer_get_nmixers`
mixer_prog: major refactoring, added -a, -d, -s and -r options.
Diffstat:
3 files changed, 202 insertions(+), 173 deletions(-)
diff --git a/mixer_lib/mixer.c b/mixer_lib/mixer.c
@@ -106,8 +106,10 @@ default_unit:
*/
dp->lmute = 0;
dp->rmute = 0;
+ /* XXX: is this correct? */
dp->f_pbk = !M_ISREC(m, i);
dp->f_rec = M_ISREC(m, i);
+ dp->f_src = M_ISRECSRC(m, i);
(void)strlcpy(dp->name, names[i], sizeof(dp->name));
TAILQ_INSERT_TAIL(&m->devs, dp, devs);
}
@@ -145,8 +147,8 @@ mixer_seldevbyname(struct mixer *m, const char *name, int flags)
struct mix_dev *dp;
TAILQ_FOREACH(dp, &m->devs, devs) {
- if (M_ISSET(dp->devno, flags)
- && !strncmp(dp->name, name, sizeof(dp->name)))
+ if (M_ISSET(dp->devno, flags) &&
+ !strncmp(dp->name, name, sizeof(dp->name)))
return (dp);
}
errno = EINVAL;
@@ -228,6 +230,7 @@ mixer_modrecsrc(struct mixer *m, int opt)
errno = EINVAL;
return (-1);
}
+ m->dev->f_src = M_ISRECSRC(m, m->dev->devno);
if (ioctl(m->fd, SOUND_MIXER_WRITE_RECSRC, &m->recsrc) < 0)
return (-1);
if (ioctl(m->fd, SOUND_MIXER_READ_RECSRC, &m->recsrc) < 0)
@@ -274,6 +277,26 @@ mixer_set_default_unit(struct mixer *m, int unit)
}
/*
+ * Get the total number of mixers in the system.
+ */
+int
+mixer_get_nmixers(void)
+{
+ struct mixer *m;
+ oss_sysinfo si;
+
+ if ((m = mixer_open(NULL)) == NULL)
+ return (-1);
+ if (ioctl(m->fd, OSS_SYSINFO, &si) < 0) {
+ (void)mixer_close(m);
+ return (-1);
+ }
+ (void)mixer_close(m);
+
+ return (si.nummixers);
+}
+
+/*
* Free resources and close the mixer.
*/
static int
diff --git a/mixer_lib/mixer.h b/mixer_lib/mixer.h
@@ -23,6 +23,8 @@
#ifndef _MIXER_H_
#define _MIXER_H_
+__BEGIN_DECLS
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -61,6 +63,7 @@ struct mix_dev {
//int samples;
int f_pbk;
int f_rec;
+ int f_src;
TAILQ_ENTRY(mix_dev) devs;
};
@@ -87,5 +90,9 @@ int mixer_chpan(struct mixer *, float);
int mixer_modrecsrc(struct mixer *, int);
int mixer_get_default_unit(void);
int mixer_set_default_unit(struct mixer *, int);
+int mixer_get_nmixers(void);
+/* TODO: get mixer/card total number */
+
+__END_DECLS
#endif /* _MIXER_H_ */
diff --git a/mixer_prog/mixer_prog.c b/mixer_prog/mixer_prog.c
@@ -29,70 +29,53 @@
#include <mixer.h>
static void usage(struct mixer *) __dead2;
-static void printrecsrc(struct mixer *, int);
+static void printall(struct mixer *);
+static void printmixer(struct mixer *);
+static void printdev(struct mix_dev *);
static void __dead2
usage(struct mixer *m)
{
- struct mix_dev *dp;
- int n;
-
- printf("usage: %1$s [-f device] [-s | -S] [dev [+|-][voll[:[+|-]volr]] ...\n"
- " %1$s [-f device] [-s | -S] recsrc ...\n"
- " %1$s [-f device] [-s | -S] {^|+|-|=}rec rdev ...\n",
+ printf("usage: %1$s [-f device] [-d unit] [dev [+|-][lvol[:[+|-]rvol]] ...\n"
+ " %1$s [-f device] [-d unit] -s ...\n"
+ " %1$s [-f device] [-d unit] -r {^|+|-|=}rdev ...\n"
+ " %1$s -a\n",
getprogname());
- if (m->devmask) {
- printf(" devices: ");
- n = 0;
- TAILQ_FOREACH(dp, &m->devs, devs) {
- if (M_ISDEV(m, dp->devno)) {
- if (n)
- printf(", ");
- printf("%s", dp->name);
- n++;
- }
- }
- }
- if (m->recmask) {
- printf("\n rec devices: ");
- n = 0;
- TAILQ_FOREACH(dp, &m->devs, devs) {
- if (M_ISREC(m, dp->devno)) {
- if (n)
- printf(", ");
- printf("%s", dp->name);
- n++;
- }
- }
- }
- printf("\n");
(void)mixer_close(m);
exit(1);
}
static void
-printrecsrc(struct mixer *m, int sflag)
+printall(struct mixer *m)
{
struct mix_dev *dp;
- int n;
- if (!m->recmask)
- return;
- if (!sflag)
- printf("Recording source: ");
- n = 0;
+ printmixer(m);
TAILQ_FOREACH(dp, &m->devs, devs) {
- if (M_ISRECSRC(m, dp->devno)) {
- if (sflag)
- printf("%srec ", n ? " +" : "=");
- else if (n)
- printf(", ");
- printf("%s", dp->name);
- n++;
- }
+ printdev(dp);
}
- if (!sflag)
- printf("\n");
+}
+
+static void
+printmixer(struct mixer *m)
+{
+ printf("%s: <%s> %s", m->mi.name, m->ci.longname, m->ci.hw_info);
+ if (m->f_default)
+ printf(" (default)");
+ printf("\n");
+}
+
+static void
+printdev(struct mix_dev *d)
+{
+ printf(" %-10s%.2f:%.2f", d->name, d->lvol, d->rvol);
+ if (d->f_pbk)
+ printf("\t(playback)");
+ if (d->f_rec)
+ printf("\t(rec)");
+ if (d->f_src)
+ printf("\t(src)");
+ printf("\n");
}
int
@@ -100,23 +83,32 @@ main(int argc, char *argv[])
{
struct mixer *m;
struct mix_dev *dp;
- char lstr[8], rstr[8], *name = NULL;
+ char lstr[8], rstr[8], *recstr, *name = NULL, buf[NAME_MAX];
float l, r, lrel, rrel;
- int dusage = 0, drecsrc = 0, sflag = 0, Sflag = 0;
- char ch, n, t, k, opt = 0;
+ int dusage = 0, opt = 0, dunit;
+ int aflag = 0, dflag = 0, rflag = 0, sflag = 0;
+ int i, rc = 0;
+ char ch, t, k, n;
- /* FIXME: problems with -rec */
- while ((ch = getopt(argc, argv, "f:sS")) != -1) {
+ while ((ch = getopt(argc, argv, "ad:f:r:s")) != -1) {
switch (ch) {
+ case 'a':
+ aflag = 1;
+ break;
+ case 'd':
+ dunit = strtol(optarg, NULL, 10);
+ dflag = 1;
+ break;
case 'f':
name = optarg;
break;
+ case 'r':
+ recstr = optarg;
+ rflag = 1;
+ break;
case 's':
sflag = 1;
break;
- case 'S':
- Sflag = 1;
- break;
case '?':
default:
dusage = 1;
@@ -126,58 +118,43 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (sflag && Sflag)
- dusage = 1;
+ if (aflag) {
+ if ((n = mixer_get_nmixers()) < 0)
+ err(1, "mixer_get_nmixers");
+ for (i = 0; i < n; i++) {
+ (void)snprintf(buf, sizeof(buf), "/dev/mixer%d", i);
+ if ((m = mixer_open(buf)) == NULL)
+ err(1, "mixer_open: %s", buf);
+ printall(m);
+ (void)mixer_close(m);
+ }
+ return (0);
+ }
if ((m = mixer_open(name)) == NULL)
err(1, "mixer_open: %s", name);
- if (!argc && !dusage) {
- n = 0;
- TAILQ_FOREACH(dp, &m->devs, devs) {
- if (sflag || Sflag) {
- printf("%s%s%c%.2f:%.2f", n ? " " : "",
- dp->name, Sflag ? ':' : ' ',
- dp->lvol, dp->rvol);
- n++;
- } else
- printf("Mixer %-8s is currently set to %.2f:%.2f\n",
- dp->name, dp->lvol, dp->rvol);
- }
- if (n && m->recmask)
- printf(" ");
- printrecsrc(m, sflag || Sflag);
- (void)mixer_close(m);
- return 0;
- }
-
- n = 0;
- while (argc > 0 && !dusage) {
- if (strcmp("recsrc", *argv) == 0) {
- drecsrc = 1;
- argc--;
- argv++;
- continue;
- } else if (strcmp("rec", *argv + 1) == 0) {
- if (**argv != '+' && **argv != '-'
- && **argv != '=' && **argv != '^') {
- warnx("unkown modifier: %c", **argv);
- dusage = 1;
- break;
+ while (!dusage) {
+ if (dflag) {
+ if (mixer_set_default_unit(m, dunit) < 0) {
+ warn("cannot set default unit to %d", dunit);
+ rc = 1;
+ goto done;
}
- if (argc <= 1) {
- warnx("no recording device specified");
- dusage = 1;
- break;
- }
- if ((m->dev = mixer_seldevbyname(m, argv[1],
- m->recmask)) == NULL) {
- warnx("unkown recording revice: %s", argv[1]);
+ /* Reopen the mixer, but use the default path. */
+ (void)mixer_close(m);
+ if ((m = mixer_open(NULL)) == NULL)
+ err(1, "mixer_open");
+ printf("changed default unit to: %d\n", dunit);
+ dflag = 0;
+ } else if (rflag) {
+ if (*recstr != '+' && *recstr != '-' &&
+ *recstr != '=' && *recstr != '^') {
+ warnx("unkown modifier: %c", *recstr);
dusage = 1;
break;
}
-
- switch (**argv) {
+ switch (*recstr) {
case '+':
opt = M_ADDRECDEV;
break;
@@ -191,86 +168,108 @@ main(int argc, char *argv[])
opt = M_TOGGLERECDEV;
break;
}
- if (mixer_modrecsrc(m, opt) < 0) {
- warnx("cannot modify device");
- break;
- }
- drecsrc = 1;
- argc -= 2;
- argv += 2;
- continue;
- }
-
- if ((t = sscanf(*argv, "%f:%f", &l, &r)) > 0)
- ; /* nothing */
- else if ((m->dev = mixer_seldevbyname(m, *argv,
- m->devmask)) == NULL) {
- warnx("unkown device: %s", *argv);
- dusage = 1;
- break;
- }
-
- lrel = rrel = 0;
- if (argc > 1) {
- k = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr);
- if (k == EOF) {
- warnx("invalid value: %s", argv[1]);
+ if (*(++recstr) == '\0') {
+ warnx("no recording device specified");
dusage = 1;
break;
}
- if (k > 0) {
- if (*lstr == '+' || *lstr == '-')
- lrel = rrel = 1;
- l = strtof(lstr, NULL);
+ if ((m->dev = mixer_seldevbyname(m, recstr,
+ m->recmask)) == NULL) {
+ warn("unkown recording revice: %s", recstr);
+ rc = 1;
+ goto done;
}
- if (k > 1) {
- if (*rstr == '+' || *rstr == '-')
- rrel = 1;
- r = strtof(rstr, NULL);
+ if (mixer_modrecsrc(m, opt) < 0) {
+ warn("cannot modify device");
+ rc = 1;
+ goto done;
+ }
+ /* We don't want to end up here again. */
+ rflag = 0;
+ } else if (sflag) {
+ if (!m->recmask)
+ goto done;
+ n = 0;
+ printmixer(m);
+ printf(" recording source: ");
+ TAILQ_FOREACH(dp, &m->devs, devs) {
+ if (M_ISRECSRC(m, dp->devno)) {
+ if (n)
+ printf(", ");
+ printf("%s", dp->name);
+ n++;
+ }
+ }
+ printf("\n");
+ goto done;
+ } else if (argc > 0) {
+ if ((t = sscanf(*argv, "%f:%f", &l, &r)) > 0)
+ ; /* nothing */
+ else if ((m->dev = mixer_seldevbyname(m, *argv,
+ m->devmask)) == NULL) {
+ warn("unkown device: %s", *argv);
+ rc = 1;
+ goto done;
}
- }
-
- switch (argc > 1 ? k : t) {
- case 0:
- printf("Mixer %-8s is currently set to %.2f:%.2f\n",
- m->dev->name, m->dev->lvol, m->dev->rvol);
- argc--;
- argv++;
- continue;
- case 1:
- r = l; /* FALLTHROUGH */
- case 2:
- if (lrel)
- l += m->dev->lvol;
- if (rrel)
- r += m->dev->rvol;
- if (l < M_VOLMIN)
- l = M_VOLMIN;
- else if (l > M_VOLMAX)
- l = M_VOLMAX;
- if (r < M_VOLMIN)
- r = M_VOLMIN;
- else if (r > M_VOLMAX)
- r = M_VOLMAX;
- if (mixer_chvol(m, l, r) < 0) {
- warnx("cannot change volume");
- break;
+ lrel = rrel = 0;
+ if (argc > 1) {
+ k = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr);
+ if (k == EOF) {
+ warnx("invalid value: %s", argv[1]);
+ dusage = 1;
+ break;
+ }
+ if (k > 0) {
+ if (*lstr == '+' || *lstr == '-')
+ lrel = rrel = 1;
+ l = strtof(lstr, NULL);
+ }
+ if (k > 1) {
+ if (*rstr == '+' || *rstr == '-')
+ rrel = 1;
+ r = strtof(rstr, NULL);
+ }
}
- if (!Sflag)
- printf("Setting the mixer %s from %.2f:%.2f "
- "to %.2f:%.2f\n",
+
+ switch (argc > 1 ? k : t) {
+ case 0:
+ printmixer(m);
+ printdev(m->dev);
+ goto done;
+ case 1:
+ r = l; /* FALLTHROUGH */
+ case 2:
+ if (lrel)
+ l += m->dev->lvol;
+ if (rrel)
+ r += m->dev->rvol;
+
+ if (l < M_VOLMIN)
+ l = M_VOLMIN;
+ else if (l > M_VOLMAX)
+ l = M_VOLMAX;
+ if (r < M_VOLMIN)
+ r = M_VOLMIN;
+ else if (r > M_VOLMAX)
+ r = M_VOLMAX;
+
+ printf("Mixer %s: %.2f:%.2f -> %.2f:%.2f\n",
m->dev->name, m->dev->lvol, m->dev->rvol, l, r);
- argc -= 2;
- argv += 2;
- }
+
+ if (mixer_chvol(m, l, r) < 0) {
+ warnx("cannot change volume");
+ rc = 1;
+ }
+ goto done;
+ }
+ } else
+ break;
}
- if (dusage)
- usage(m);
- if (drecsrc)
- printrecsrc(m, sflag || Sflag);
+ dusage ? usage(m) : printall(m);
+done:
(void)mixer_close(m);
- return 0;
+ return (rc);
}