commit 4476aa86fe55ccbf2b34c84a194dbeb82331ac03
parent b47986a3584d1e38c6c8ff8a5ff47fbd580308bc
Author: Christos Margiolis <christos@margiolis.net>
Date: Sat, 3 Jul 2021 00:41:13 +0300
implemented mute ioctl in the kernel
Diffstat:
7 files changed, 195 insertions(+), 220 deletions(-)
diff --git a/diff/mixer_kern.diff b/diff/mixer_kern.diff
@@ -0,0 +1,134 @@
+diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
+index 92c5f3d613e..a15b59eb47f 100644
+--- a/sys/dev/sound/pcm/mixer.c
++++ b/sys/dev/sound/pcm/mixer.c
+@@ -58,9 +58,11 @@ struct snd_mixer {
+ device_t dev;
+ u_int32_t hwvol_mute_level;
+ u_int32_t devs;
++ u_int32_t mutedevs;
+ u_int32_t recdevs;
+ u_int32_t recsrc;
+ u_int16_t level[32];
++ u_int16_t level_muted[32];
+ u_int8_t parent[32];
+ u_int32_t child[32];
+ u_int8_t realdev[32];
+@@ -338,6 +340,40 @@ mixer_get(struct snd_mixer *mixer, int dev)
+ return -1;
+ }
+
++static int
++mixer_setmute(struct snd_mixer *mixer, u_int32_t mutedevs)
++{
++ struct snddev_info *d;
++ int dropmtx, i, ret = 0, v;
++
++ d = device_get_softc(mixer->dev);
++ if (d == NULL)
++ return (-1);
++ if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0)
++ dropmtx = 1;
++ else
++ dropmtx = 0;
++
++ /* FIXME: lock/unlock */
++
++ mutedevs &= mixer->devs; /* Filter out invalid values. */
++ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
++ if (!(mixer->devs & (1 << i)))
++ continue;
++ if ((mutedevs & (1 << i)) && mixer->level[i] != 0) {
++ mixer->level_muted[i] = mixer->level[i];
++ v = 0;
++ } else if (!(mutedevs & (1 << i)) && mixer->level[i] == 0)
++ v = mixer->level_muted[i];
++ else
++ continue;
++ ret += mixer_set(mixer, i, v);
++ }
++ mixer->mutedevs = mutedevs;
++
++ return (ret);
++}
++
+ static int
+ mixer_setrecsrc(struct snd_mixer *mixer, u_int32_t src)
+ {
+@@ -598,6 +634,12 @@ mix_getdevs(struct snd_mixer *m)
+ return m->devs;
+ }
+
++u_int32_t
++mix_getmutedevs(struct snd_mixer *m)
++{
++ return m->mutedevs;
++}
++
+ u_int32_t
+ mix_getrecdevs(struct snd_mixer *m)
+ {
+@@ -711,6 +753,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
+ if (m == NULL)
+ return (-1);
+
++ m->mutedevs = 0;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ v = snd_mixerdefaults[i];
+
+@@ -722,6 +765,11 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
+ }
+
+ mixer_set(m, i, v | (v << 8));
++ /*
++ * Make sure we don't use an uninitialized value in
++ * `mixer_setmute`.
++ */
++ m->level_muted[i] = 0;
+ }
+
+ mixer_setrecsrc(m, 0); /* Set default input. */
+@@ -1305,10 +1353,16 @@ mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
+ goto done;
+ }
+ if ((cmd & ~0xff) == MIXER_WRITE(0)) {
+- if (j == SOUND_MIXER_RECSRC)
++ switch (j) {
++ case SOUND_MIXER_RECSRC:
+ ret = mixer_setrecsrc(m, *arg_i);
+- else
++ break;
++ case SOUND_MIXER_MUTE:
++ ret = mixer_setmute(m, *arg_i);
++ break;
++ default:
+ ret = mixer_set(m, j, *arg_i);
++ }
+ snd_mtxunlock(m->lock);
+ return ((ret == 0) ? 0 : ENXIO);
+ }
+@@ -1319,6 +1373,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;
++ case SOUND_MIXER_MUTE:
++ v = mix_getmutedevs(m);
++ break;
+ case SOUND_MIXER_RECMASK:
+ v = mix_getrecdevs(m);
+ break;
+diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
+index 8e11d553a3e..6d7d861e8a6 100644
+--- a/sys/dev/sound/pcm/mixer.h
++++ b/sys/dev/sound/pcm/mixer.h
+@@ -60,8 +60,10 @@ device_t mix_get_dev(struct snd_mixer *m);
+
+ void mix_setdevs(struct snd_mixer *m, u_int32_t v);
+ void mix_setrecdevs(struct snd_mixer *m, u_int32_t v);
++// XXX: int mix_setmutedevs(struct snd_mixer *m, u_int32_t mutedevs);
+ u_int32_t mix_getdevs(struct snd_mixer *m);
+ u_int32_t mix_getrecdevs(struct snd_mixer *m);
++u_int32_t mix_getmutedevs(struct snd_mixer *m);
+ void mix_setparentchild(struct snd_mixer *m, u_int32_t parent, u_int32_t childs);
+ 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/diff/mixer_rc.diff b/diff/mixer_rc.diff
@@ -0,0 +1,8 @@
+61c61
+< /usr/sbin/mixer_prog -f ${dev} -o > /var/db/${1}-state 2>/dev/null
+---
+> /usr/sbin/mixer -f ${dev} -s > /var/db/${1}-state 2>/dev/null
+75c75
+< /usr/sbin/mixer_prog -f ${dev} `cat ${file}` > /dev/null
+---
+> /usr/sbin/mixer -f ${dev} `cat ${file}` > /dev/null
diff --git a/mixer_lib/mixer.c b/mixer_lib/mixer.c
@@ -87,6 +87,7 @@ dunit:
if (ioctl(m->fd, SNDCTL_MIXERINFO, &m->mi) < 0 ||
ioctl(m->fd, SNDCTL_CARDINFO, &m->ci) < 0 ||
ioctl(m->fd, SOUND_MIXER_READ_DEVMASK, &m->devmask) < 0 ||
+ ioctl(m->fd, SOUND_MIXER_READ_MUTE, &m->mutemask) < 0 ||
ioctl(m->fd, SOUND_MIXER_READ_RECMASK, &m->recmask) < 0 ||
ioctl(m->fd, SOUND_MIXER_READ_RECSRC, &m->recsrc) < 0)
goto fail;
@@ -100,23 +101,21 @@ dunit:
if ((dp = calloc(1, sizeof(struct mix_dev))) == NULL)
goto fail;
dp->devno = i;
+
+ /* XXX: Make this a seperate function? */
dp->lvol = M_VOLNORM(v & 0x7f);
dp->rvol = M_VOLNORM((v >> 8) & 0x7f);
dp->pan = dp->rvol - dp->lvol;
- /*
- * TODO: find a way to know if it's already muted
- * or not, this doesn't make sense
- */
- 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);
+
+ dp->f_mut = M_ISMUTE(m, i) ? 1 : 0;
+ dp->f_pbk = !M_ISREC(m, i) ? 1 : 0;
+ dp->f_rec = M_ISREC(m, i) ? 1 : 0;
+ dp->f_src = M_ISRECSRC(m, i) ? 1 : 0;
(void)strlcpy(dp->name, names[i], sizeof(dp->name));
TAILQ_INSERT_TAIL(&m->devs, dp, devs);
ndev++;
}
+
/* The default device is always "vol". */
m->dev = TAILQ_FIRST(&m->devs);
@@ -226,6 +225,37 @@ mixer_setpan(struct mixer *m, float pan)
return (mixer_setvol(m, l, r));
}
+int
+mixer_setmute(struct mixer *m, int opt)
+{
+ int v;
+
+ switch (opt) {
+ case M_MUTE:
+ m->mutemask |= (1 << m->dev->devno);
+ break;
+ case M_UNMUTE:
+ m->mutemask &= ~(1 << m->dev->devno);
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ if (ioctl(m->fd, SOUND_MIXER_WRITE_MUTE, &m->mutemask) < 0)
+ return (-1);
+ if (ioctl(m->fd, SOUND_MIXER_READ_MUTE, &m->mutemask) < 0)
+ return (-1);
+ /* Update the volume. */
+ if (ioctl(m->fd, MIXER_READ(m->dev->devno), &v) < 0)
+ return (-1);
+ m->dev->lvol = M_VOLNORM(v & 0x7f);
+ m->dev->rvol = M_VOLNORM((v >> 8) & 0x7f);
+ m->dev->pan = m->dev->rvol - m->dev->lvol;
+ m->dev->f_mut = M_ISMUTE(m, m->dev->devno);
+
+ return 0;
+}
+
/*
* Modify the mixer's selected device flags. The `recsrc` flag tells
* us if a device is a recording source.
diff --git a/mixer_lib/mixer.h b/mixer_lib/mixer.h
@@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$");
#define M_SETRECDEV 0x04
#define M_TOGGLERECDEV 0x08
+#define M_MUTE 0x01
+#define M_UNMUTE 0x02
+
#define M_VOLMIN 0.0f
#define M_VOLMAX 1.0f
#define M_VOLNORM(v) ((v) / 100.0f)
@@ -49,6 +52,7 @@ __FBSDID("$FreeBSD$");
#define M_ISSET(n, f) ((1 << (n)) & (f))
#define M_ISDEV(m, n) M_ISSET(n, (m)->devmask)
+#define M_ISMUTE(m, n) M_ISSET(n, (m)->mutemask)
#define M_ISREC(m, n) M_ISSET(n, (m)->recmask)
#define M_ISRECSRC(m, n) M_ISSET(n, (m)->recsrc)
@@ -58,10 +62,9 @@ struct mix_dev {
float lvol;
float rvol;
float pan;
- int lmute;
- int rmute;
//int rate;
//int samples;
+ int f_mut;
int f_pbk;
int f_rec;
int f_src;
@@ -77,17 +80,21 @@ struct mixer {
int fd;
int unit;
int devmask;
+ int mutemask;
int recmask;
int recsrc;
int f_default;
};
+/* XXX: move control handling here? */
+
struct mixer *mixer_open(const char *);
int mixer_close(struct mixer *);
struct mix_dev *mixer_getdev(struct mixer *, int);
struct mix_dev *mixer_getdevbyname(struct mixer *, const char *);
int mixer_setvol(struct mixer *, float, float);
int mixer_setpan(struct mixer *, float);
+int mixer_setmute(struct mixer *, int);
int mixer_modrecsrc(struct mixer *, int);
int mixer_getdunit(void);
int mixer_setdunit(struct mixer *, int);
diff --git a/mixer_prog/mixer_prog.c b/mixer_prog/mixer_prog.c
@@ -33,6 +33,7 @@
#define CTRL_VOL 0
#define CTRL_SRC 1
+#define CTRL_MUT 2
struct ctrl {
char name[NAME_MAX];
@@ -55,6 +56,7 @@ static void usage(void) __dead2;
static const struct ctrl ctrls[] = {
[CTRL_VOL] = { "volume", modvol, printvol },
[CTRL_SRC] = { "recsrc", modrecsrc, printrec },
+ /*[CTRL_MUT] = { "mute", modmute, printmute },*/
};
static void
@@ -91,6 +93,8 @@ printdev(struct mix_dev *d, int oflag)
printf(" rec");
if (d->f_src)
printf(" src");
+ if (d->f_mut)
+ printf(" mute");
printf("\n");
} else {
printf("%s.%s=%.2f:%.2f\n",
diff --git a/rc.d/mixer b/rc.d/mixer
@@ -1,104 +0,0 @@
-#!/bin/sh -
-#
-# Copyright (c) 2004 The FreeBSD Project
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD: releng/12.2/libexec/rc/rc.d/mixer 298514 2016-04-23 16:10:54Z lme $
-#
-
-# PROVIDE: mixer
-# REQUIRE: FILESYSTEMS
-# KEYWORD: nojail shutdown
-
-. /etc/rc.subr
-
-name="mixer"
-desc="Save and restore soundcard mixer values"
-rcvar="mixer_enable"
-stop_cmd="mixer_stop"
-start_cmd="mixer_start"
-reload_cmd="mixer_start"
-extra_commands="reload"
-
-#
-# List current mixer devices to stdout.
-#
-list_mixers()
-{
- ( cd /dev ; ls mixer* 2>/dev/null )
-}
-
-#
-# Save state of an individual mixer specified as $1
-#
-mixer_save()
-{
- local dev
-
- dev="/dev/${1}"
- if [ -r ${dev} ]; then
- /usr/sbin/mixer_prog -f ${dev} -o > /var/db/${1}-state 2>/dev/null
- fi
-}
-
-#
-# Restore the state of an individual mixer specified as $1
-#
-mixer_restore()
-{
- local file dev
-
- dev="/dev/${1}"
- file="/var/db/${1}-state"
- if [ -r ${dev} -a -r ${file} ]; then
- /usr/sbin/mixer_prog -f ${dev} `cat ${file}` > /dev/null
- fi
-}
-
-#
-# Restore state of all mixers
-#
-mixer_start()
-{
- local mixer
-
- for mixer in `list_mixers`; do
- mixer_restore ${mixer}
- done
-}
-
-#
-# Save the state of all mixers
-#
-mixer_stop()
-{
- local mixer
-
- for mixer in `list_mixers`; do
- mixer_save ${mixer}
- done
-}
-
-load_rc_config $name
-run_rc_command "$1"
diff --git a/rc.d/mixer.old b/rc.d/mixer.old
@@ -1,104 +0,0 @@
-#!/bin/sh -
-#
-# Copyright (c) 2004 The FreeBSD Project
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# $FreeBSD$
-#
-
-# PROVIDE: mixer
-# REQUIRE: FILESYSTEMS
-# KEYWORD: nojail shutdown
-
-. /etc/rc.subr
-
-name="mixer"
-desc="Save and restore soundcard mixer values"
-rcvar="mixer_enable"
-stop_cmd="mixer_stop"
-start_cmd="mixer_start"
-reload_cmd="mixer_start"
-extra_commands="reload"
-
-#
-# List current mixer devices to stdout.
-#
-list_mixers()
-{
- ( cd /dev ; ls mixer* 2>/dev/null )
-}
-
-#
-# Save state of an individual mixer specified as $1
-#
-mixer_save()
-{
- local dev
-
- dev="/dev/${1}"
- if [ -r ${dev} ]; then
- /usr/sbin/mixer -f ${dev} -s > /var/db/${1}-state 2>/dev/null
- fi
-}
-
-#
-# Restore the state of an individual mixer specified as $1
-#
-mixer_restore()
-{
- local file dev
-
- dev="/dev/${1}"
- file="/var/db/${1}-state"
- if [ -r ${dev} -a -r ${file} ]; then
- /usr/sbin/mixer -f ${dev} `cat ${file}` > /dev/null
- fi
-}
-
-#
-# Restore state of all mixers
-#
-mixer_start()
-{
- local mixer
-
- for mixer in `list_mixers`; do
- mixer_restore ${mixer}
- done
-}
-
-#
-# Save the state of all mixers
-#
-mixer_stop()
-{
- local mixer
-
- for mixer in `list_mixers`; do
- mixer_save ${mixer}
- done
-}
-
-load_rc_config $name
-run_rc_command "$1"