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

commit 2a4476d554b6cf244c3c5019968640bea28e94ee
parent 08cd797e4e6cc44c08c1b83ab41063814ac9f537
Author: Christos Margiolis <christos@margiolis.net>
Date:   Sat, 10 Jul 2021 13:37:02 +0300

kernel: allow volume to be changed while muted

Diffstat:
Mdiff/mixer_kern.diff | 45+++++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)

diff --git a/diff/mixer_kern.diff b/diff/mixer_kern.diff @@ -1,5 +1,5 @@ diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c -index 92c5f3d613e..d85dff6eee7 100644 +index 92c5f3d613e..55f69c4b242 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -58,9 +58,11 @@ struct snd_mixer { @@ -32,7 +32,21 @@ index 92c5f3d613e..d85dff6eee7 100644 /* It is safe to drop this mutex due to Giant. */ if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0) -@@ -287,7 +289,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) +@@ -272,6 +274,13 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) + + MIXER_SET_UNLOCK(m, dropmtx); + ++ /* Allow the volume to be "changed" while muted. */ ++ if (m->mutedevs & (1 << dev)) { ++ m->level_muted[dev] = l | (r << 8); ++ MIXER_SET_LOCK(m, dropmtx); ++ return (0); ++ } ++ + /* TODO: recursive handling */ + parent = m->parent[dev]; + if (parent >= SOUND_MIXER_NRDEVICES) +@@ -287,7 +296,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) else if (realdev != SOUND_MIXER_NONE && MIXER_SET(m, realdev, tl, tr) < 0) { MIXER_SET_LOCK(m, dropmtx); @@ -41,7 +55,7 @@ index 92c5f3d613e..d85dff6eee7 100644 } } else if (child != 0) { for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { -@@ -305,8 +307,8 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) +@@ -305,8 +314,8 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) realdev = m->realdev[dev]; if (realdev != SOUND_MIXER_NONE && MIXER_SET(m, realdev, l, r) < 0) { @@ -52,7 +66,7 @@ index 92c5f3d613e..d85dff6eee7 100644 } } else { if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL)) -@@ -317,7 +319,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) +@@ -317,7 +326,7 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) else if (realdev != SOUND_MIXER_NONE && MIXER_SET(m, realdev, l, r) < 0) { MIXER_SET_LOCK(m, dropmtx); @@ -61,7 +75,7 @@ index 92c5f3d613e..d85dff6eee7 100644 } } -@@ -326,16 +328,55 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) +@@ -326,16 +335,66 @@ mixer_set(struct snd_mixer *m, u_int dev, u_int lev) m->level[dev] = l | (r << 8); m->modify_counter++; @@ -110,6 +124,17 @@ index 92c5f3d613e..d85dff6eee7 100644 + mixer->level_muted[i] = mixer->level[i]; + v = 0; + } else if (!(mutedevs & (1 << i)) && mixer->level[i] == 0) { ++ /* ++ * `mixer_set` checks if the device is muted and, if ++ * yes, assigns the volume to `level_muted` and returns. ++ * In case of an unmute, we'll first UNSET the mute bit ++ * so that we bypass this check. ++ * ++ * This is probably a dirty hack, but assigning the ++ * flags before the loop would cause the same effect, ++ * this time when muting. ++ */ ++ mixer->mutedevs &= ~(1 << i); + v = mixer->level_muted[i]; + } else + continue; @@ -121,7 +146,7 @@ index 92c5f3d613e..d85dff6eee7 100644 } static int -@@ -598,6 +639,12 @@ mix_getdevs(struct snd_mixer *m) +@@ -598,6 +657,12 @@ mix_getdevs(struct snd_mixer *m) return m->devs; } @@ -134,7 +159,7 @@ index 92c5f3d613e..d85dff6eee7 100644 u_int32_t mix_getrecdevs(struct snd_mixer *m) { -@@ -711,6 +758,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) +@@ -711,6 +776,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) if (m == NULL) return (-1); @@ -142,7 +167,7 @@ index 92c5f3d613e..d85dff6eee7 100644 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { v = snd_mixerdefaults[i]; -@@ -722,6 +770,11 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) +@@ -722,6 +788,11 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo) } mixer_set(m, i, v | (v << 8)); @@ -154,7 +179,7 @@ index 92c5f3d613e..d85dff6eee7 100644 } mixer_setrecsrc(m, 0); /* Set default input. */ -@@ -1305,10 +1358,16 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, +@@ -1305,10 +1376,16 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, goto done; } if ((cmd & ~0xff) == MIXER_WRITE(0)) { @@ -173,7 +198,7 @@ index 92c5f3d613e..d85dff6eee7 100644 snd_mtxunlock(m->lock); return ((ret == 0) ? 0 : ENXIO); } -@@ -1319,6 +1378,9 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, +@@ -1319,6 +1396,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;