mixer

FreeBSD OSS mixer library implementation and a complete rewrite of mixer(8)
git clone git://git.margiolis.net/mixer.git
Log | Files | Refs | README | LICENSE

commit 8b62568de30fb40da917397286e55f03037700bd
parent fc1248a5e65159c108214197dfb13a15a7988b9b
Author: Christos Margiolis <christos@margiolis.net>
Date:   Fri, 15 Oct 2021 03:08:09 +0300

update kernel patches, minor library and prog updates

Diffstat:
Mdiff/mixer_kern.diff | 81++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mlib/libmixer/mixer.c | 24+++++++++++++++---------
Musr.sbin/mixer/mixer.c | 36+++++++++++++++++++++---------------
3 files changed, 81 insertions(+), 60 deletions(-)

diff --git a/diff/mixer_kern.diff b/diff/mixer_kern.diff @@ -1,8 +1,8 @@ diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c -index ecf89df4c9a..234a0cb2435 100644 +index 38c578ba828..4d56eee6847 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c -@@ -1218,6 +1218,8 @@ chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction) +@@ -1223,6 +1223,8 @@ chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction) c->volume[SND_VOL_C_MASTER][SND_CHN_T_VOL_0DB] = SND_VOL_0DB_MASTER; c->volume[SND_VOL_C_PCM][SND_CHN_T_VOL_0DB] = chn_vol_0db_pcm; @@ -11,7 +11,7 @@ index ecf89df4c9a..234a0cb2435 100644 chn_vpc_reset(c, SND_VOL_C_PCM, 1); ret = ENODEV; -@@ -1389,6 +1391,75 @@ chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt) +@@ -1394,6 +1396,75 @@ chn_getvolume_matrix(struct pcm_channel *c, int vc, int vt) return (c->volume[vc][vt]); } @@ -88,7 +88,7 @@ index ecf89df4c9a..234a0cb2435 100644 chn_getmatrix(struct pcm_channel *c) { diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h -index 969b8dba27d..45b517f22ce 100644 +index 34d62f4e15c..60b7b3416cc 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -166,7 +166,8 @@ struct pcm_channel { @@ -121,10 +121,10 @@ index 969b8dba27d..45b517f22ce 100644 int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak); #endif diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c -index 9dfc47d60fb..0c5c8af341d 100644 +index 0593a585b0f..15f437b8627 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c -@@ -964,6 +964,7 @@ dsp_ioctl_channel(struct cdev *dev, struct pcm_channel *volch, u_long cmd, +@@ -965,6 +965,7 @@ dsp_ioctl_channel(struct cdev *dev, struct pcm_channel *volch, u_long cmd, struct snddev_info *d; struct pcm_channel *rdch, *wrch; int j, devtype, ret; @@ -132,7 +132,7 @@ index 9dfc47d60fb..0c5c8af341d 100644 d = dsp_get_info(dev); if (!PCM_REGISTERED(d) || !(dsp_get_flags(dev) & SD_F_VPC)) -@@ -1002,67 +1003,95 @@ dsp_ioctl_channel(struct cdev *dev, struct pcm_channel *volch, u_long cmd, +@@ -1003,67 +1004,95 @@ dsp_ioctl_channel(struct cdev *dev, struct pcm_channel *volch, u_long cmd, } /* Final validation */ @@ -274,6 +274,16 @@ index 9dfc47d60fb..0c5c8af341d 100644 } static int +@@ -2294,8 +2323,7 @@ dsp_stdclone(char *name, char *namep, char *sep, int use_sep, int *u, int *c) + size_t len; + + len = strlen(namep); +- +- if (bcmp(name, namep, len) != 0) ++ if (strncmp(name, namep, len) != 0) + return (ENODEV); + + name += len; diff --git a/sys/dev/sound/pcm/feeder_volume.c b/sys/dev/sound/pcm/feeder_volume.c index 322d7f6b2c8..2312bd89c9d 100644 --- a/sys/dev/sound/pcm/feeder_volume.c @@ -337,7 +347,7 @@ index 322d7f6b2c8..2312bd89c9d 100644 j *= align; dst += j; diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c -index 92c5f3d613e..8275d1a2684 100644 +index 09b0bb8ab14..89e78b036e9 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -51,16 +51,16 @@ struct snd_mixer { @@ -427,7 +437,7 @@ index 92c5f3d613e..8275d1a2684 100644 } } -@@ -326,16 +331,43 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) +@@ -326,16 +331,42 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) m->level[dev] = l | (r << 8); m->modify_counter++; @@ -455,7 +465,6 @@ index 92c5f3d613e..8275d1a2684 100644 +void +mix_setmutedevs(struct snd_mixer *mixer, u_int32_t mutedevs) +{ -+ int i; + u_int32_t delta; + + /* Filter out invalid values. */ @@ -463,7 +472,7 @@ index 92c5f3d613e..8275d1a2684 100644 + delta = (mixer->mutedevs ^ mutedevs) & mixer->devs; + mixer->mutedevs = mutedevs; + -+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { ++ for (int i = 0; i < SOUND_MIXER_NRDEVICES; i++) { + if (!(delta & (1 << i))) + continue; + if (mutedevs & (1 << i)) { @@ -476,7 +485,7 @@ index 92c5f3d613e..8275d1a2684 100644 } static int -@@ -598,6 +630,12 @@ mix_getdevs(struct snd_mixer *m) +@@ -598,6 +629,12 @@ mix_getdevs(struct snd_mixer *m) return m->devs; } @@ -489,7 +498,7 @@ index 92c5f3d613e..8275d1a2684 100644 u_int32_t mix_getrecdevs(struct snd_mixer *m) { -@@ -721,7 +759,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) +@@ -721,7 +758,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) } } @@ -498,7 +507,7 @@ index 92c5f3d613e..8275d1a2684 100644 } mixer_setrecsrc(m, 0); /* Set default input. */ -@@ -799,7 +837,7 @@ mixer_uninit(device_t dev) +@@ -799,7 +836,7 @@ mixer_uninit(device_t dev) snd_mtxlock(m->lock); for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) @@ -507,7 +516,7 @@ index 92c5f3d613e..8275d1a2684 100644 mixer_setrecsrc(m, SOUND_MASK_MIC); -@@ -836,8 +874,12 @@ mixer_reinit(device_t dev) +@@ -836,8 +873,12 @@ mixer_reinit(device_t dev) return i; } @@ -522,7 +531,7 @@ index 92c5f3d613e..8275d1a2684 100644 mixer_setrecsrc(m, m->recsrc); snd_mtxunlock(m->lock); -@@ -863,10 +905,8 @@ sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) +@@ -863,10 +904,8 @@ sysctl_hw_snd_hwvol_mixer(SYSCTL_HANDLER_ARGS) if (dev == -1) { snd_mtxunlock(m->lock); return EINVAL; @@ -534,7 +543,7 @@ index 92c5f3d613e..8275d1a2684 100644 } } snd_mtxunlock(m->lock); -@@ -897,14 +937,7 @@ mixer_hwvol_init(device_t dev) +@@ -897,14 +936,7 @@ mixer_hwvol_init(device_t dev) void mixer_hwvol_mute_locked(struct snd_mixer *m) { @@ -550,7 +559,7 @@ index 92c5f3d613e..8275d1a2684 100644 } void -@@ -925,11 +958,8 @@ mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) +@@ -925,11 +957,8 @@ mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) { int level, left, right; @@ -564,7 +573,7 @@ index 92c5f3d613e..8275d1a2684 100644 if (level != -1) { left = level & 0xff; right = (level >> 8) & 0xff; -@@ -943,7 +973,8 @@ mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) +@@ -943,7 +972,8 @@ mixer_hwvol_step_locked(struct snd_mixer *m, int left_step, int right_step) right = 0; else if (right > 100) right = 100; @@ -574,7 +583,7 @@ index 92c5f3d613e..8275d1a2684 100644 } } -@@ -976,7 +1007,7 @@ mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right) +@@ -976,7 +1006,7 @@ mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right) KASSERT(m != NULL, ("NULL snd_mixer")); snd_mtxlock(m->lock); @@ -583,7 +592,7 @@ index 92c5f3d613e..8275d1a2684 100644 snd_mtxunlock(m->lock); return ((ret != 0) ? ENXIO : 0); -@@ -1305,10 +1336,18 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, +@@ -1304,10 +1334,18 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, goto done; } if ((cmd & ~0xff) == MIXER_WRITE(0)) { @@ -605,7 +614,7 @@ index 92c5f3d613e..8275d1a2684 100644 snd_mtxunlock(m->lock); return ((ret == 0) ? 0 : ENXIO); } -@@ -1319,6 +1358,9 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, +@@ -1318,6 +1356,9 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, case SOUND_MIXER_STEREODEVS: v = mix_getdevs(m); break; @@ -615,7 +624,7 @@ index 92c5f3d613e..8275d1a2684 100644 case SOUND_MIXER_RECMASK: v = mix_getrecdevs(m); break; -@@ -1327,6 +1369,7 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, +@@ -1326,6 +1367,7 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, break; default: v = mixer_get(m, j); @@ -623,7 +632,7 @@ index 92c5f3d613e..8275d1a2684 100644 } *arg_i = v; snd_mtxunlock(m->lock); -@@ -1555,5 +1598,5 @@ mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right) +@@ -1554,5 +1596,5 @@ mix_set_locked(struct snd_mixer *m, u_int dev, int left, int right) level = (left & 0xFF) | ((right & 0xFF) << 8); @@ -646,10 +655,10 @@ index 8e11d553a3e..7857609b289 100644 void mix_setrealdev(struct snd_mixer *m, u_int32_t dev, u_int32_t realdev); u_int32_t mix_getparent(struct snd_mixer *m, u_int32_t dev); diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c -index b4be28aeff8..6b1b8bcbc93 100644 +index 299e4937f8e..663ec84f93b 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c -@@ -1012,12 +1012,30 @@ SYSCTL_PROC(_hw_snd, OID_AUTO, clone_gc, CTLTYPE_INT | CTLFLAG_RWTUN, +@@ -1015,12 +1015,30 @@ SYSCTL_PROC(_hw_snd, OID_AUTO, clone_gc, "global clone garbage collector"); #endif @@ -681,9 +690,9 @@ index b4be28aeff8..6b1b8bcbc93 100644 sysadmin then needs min+max sysctls for this */ SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), -@@ -1027,6 +1045,11 @@ pcm_sysinit(device_t dev) - "bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN, d, sizeof(d), - sysctl_dev_pcm_bitperfect, "I", +@@ -1030,6 +1048,11 @@ pcm_sysinit(device_t dev) + "bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, d, + sizeof(d), sysctl_dev_pcm_bitperfect, "I", "bit-perfect playback/recording (0=disable, 1=enable)"); + SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), @@ -693,26 +702,26 @@ index b4be28aeff8..6b1b8bcbc93 100644 #ifdef SND_DEBUG SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, -@@ -1130,7 +1153,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) +@@ -1133,7 +1156,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) sysctl_ctx_init(&d->rec_sysctl_ctx); d->rec_sysctl_tree = SYSCTL_ADD_NODE(&d->rec_sysctl_ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec", -- CTLFLAG_RD, 0, "record channels node"); -+ CTLFLAG_RD, 0, "recording channels node"); +- CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "record channels node"); ++ CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "recording channels node"); if (numplay > 0 || numrec > 0) d->flags |= SD_F_AUTOVCHAN; diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h -index d4b3a23e8eb..e9979cf426c 100644 +index cdae5e837cd..62787a3e689 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -411,6 +411,10 @@ struct snddev_info { void sound_oss_sysinfo(oss_sysinfo *); int sound_oss_card_info(oss_card_info *); -+#define PCM_MODE_MIXER 0x01 -+#define PCM_MODE_PLAY 0x02 -+#define PCM_MODE_REC 0x04 ++#define PCM_MODE_MIXER 0x01 ++#define PCM_MODE_PLAY 0x02 ++#define PCM_MODE_REC 0x04 + #define PCM_LOCKOWNED(d) mtx_owned((d)->lock) #define PCM_LOCK(d) mtx_lock((d)->lock) diff --git a/lib/libmixer/mixer.c b/lib/libmixer/mixer.c @@ -28,7 +28,6 @@ #include <errno.h> #include <fcntl.h> -#include <libgen.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -36,6 +35,8 @@ #include "mixer.h" +#define BASEPATH "/dev/mixer" + static int _mixer_readvol(struct mixer *, struct mix_dev *); /* @@ -68,17 +69,21 @@ mixer_open(const char *name) struct mixer *m = NULL; struct mix_dev *dp; const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; - char *p; int i; if ((m = calloc(1, sizeof(struct mixer))) == NULL) goto fail; if (name != NULL) { - p = basename((char *)name); - if (strncmp(p, "mixer", 5) == 0 && p[5] == '\0') - goto dunit; - (void)sscanf(p, "%*[^0123456789]%d", &m->unit); + /* `name` does not start with "/dev/mixer". */ + if (strncmp(name, BASEPATH, strlen(BASEPATH)) != 0) { + m->unit = -1; + } else { + /* `name` is "/dev/mixer" so, we'll use the default unit. */ + if (strncmp(name, BASEPATH, strlen(name)) == 0) + goto dunit; + m->unit = strtol(name + strlen(BASEPATH), NULL, 10); + } (void)strlcpy(m->name, name, sizeof(m->name)); } else { dunit: @@ -124,13 +129,14 @@ dunit: TAILQ_INSERT_TAIL(&m->devs, dp, devs); m->ndev++; } + + /* The default device is always "vol". */ m->dev = TAILQ_FIRST(&m->devs); return (m); fail: - /* XXX: do we need this? */ - /*if (m != NULL)*/ - /*(void)mixer_close(m);*/ + if (m != NULL) + (void)mixer_close(m); return (NULL); } diff --git a/usr.sbin/mixer/mixer.c b/usr.sbin/mixer/mixer.c @@ -24,13 +24,12 @@ #include <err.h> #include <errno.h> +#include <mixer.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <mixer.h> - static void usage(void) __dead2; static void initctls(struct mixer *); static void printall(struct mixer *, int); @@ -49,7 +48,7 @@ static int print_recsrc(struct mix_dev *, void *); static const mix_ctl_t ctl_dunit = { .parent_dev = NULL, .id = -1, - .name = "dunit", + .name = "default_unit", .mod = mod_dunit, .print = NULL }; @@ -61,7 +60,7 @@ main(int argc, char *argv[]) mix_ctl_t *cp; char *name = NULL, buf[NAME_MAX]; char *p, *bufp, *devstr, *ctlstr, *valstr = NULL; - int du, i, n, pall = 1; + int dunit, i, n, pall = 1; int aflag = 0, dflag = 0, oflag = 0, sflag = 0; int ch; @@ -71,7 +70,7 @@ main(int argc, char *argv[]) aflag = 1; break; case 'd': - du = strtol(optarg, NULL, 10); + dunit = strtol(optarg, NULL, 10); if (errno == EINVAL || errno == ERANGE) err(1, "strtol"); dflag = 1; @@ -119,7 +118,7 @@ main(int argc, char *argv[]) initctls(m); - if (dflag && ctl_dunit.mod(m->dev, &du) < 0) + if (dflag && ctl_dunit.mod(m->dev, &dunit) < 0) goto parse; if (sflag) { printrecsrc(m, oflag); @@ -219,15 +218,23 @@ printminfo(struct mixer *m, int oflag) if (oflag) return; - printf("%s: <%s> %s", m->mi.name, m->ci.longname, m->ci.hw_info); - printf(" ("); + printf("%s:", m->mi.name); + if (*m->ci.longname != '\0') + printf(" <%s>", m->ci.longname); + if (*m->ci.hw_info != '\0') + printf(" %s", m->ci.hw_info); + + if (m->mode != 0) + printf(" ("); if (m->mode & MIX_MODE_PLAY) printf("play"); if ((m->mode & playrec) == playrec) printf("/"); if (m->mode & MIX_MODE_REC) printf("rec"); - printf(")"); + if (m->mode != 0) + printf(")"); + if (m->f_default) printf(" (default)"); printf("\n"); @@ -279,8 +286,7 @@ printrecsrc(struct mixer *m, int oflag) printf("%s", dp->name); if (oflag) printf(".%s=+%s", - mixer_get_ctl(dp, C_SRC)->name, - n ? " " : ""); + mixer_get_ctl(dp, C_SRC)->name, n ? " " : ""); } } printf("\n"); @@ -289,18 +295,18 @@ printrecsrc(struct mixer *m, int oflag) static int mod_dunit(struct mix_dev *d, void *p) { - int du = *((int *)p); + int dunit = *((int *)p); int n; if ((n = mixer_get_dunit()) < 0) { warn("cannot get default unit"); return (-1); } - if (mixer_set_dunit(d->parent_mixer, du) < 0) { - warn("cannot set default unit to: %d", du); + if (mixer_set_dunit(d->parent_mixer, dunit) < 0) { + warn("cannot set default unit to: %d", dunit); return (-1); } - printf("%s: %d -> %d\n", ctl_dunit.name, n, du); + printf("%s: %d -> %d\n", ctl_dunit.name, n, dunit); return (0); }