Page MenuHomeFreeBSD

D31130.id92040.diff
No OneTemporary

D31130.id92040.diff

diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h
--- a/sys/dev/sound/pcm/mixer.h
+++ b/sys/dev/sound/pcm/mixer.h
@@ -60,8 +60,10 @@
void mix_setdevs(struct snd_mixer *m, u_int32_t v);
void mix_setrecdevs(struct snd_mixer *m, u_int32_t v);
+//void 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/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c
--- a/sys/dev/sound/pcm/mixer.c
+++ b/sys/dev/sound/pcm/mixer.c
@@ -58,9 +58,11 @@
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];
@@ -254,7 +256,7 @@
if (m == NULL || dev >= SOUND_MIXER_NRDEVICES ||
(0 == (m->devs & (1 << dev))))
- return -1;
+ return (-1);
l = min((lev & 0x00ff), 100);
r = min(((lev & 0xff00) >> 8), 100);
@@ -262,7 +264,7 @@
d = device_get_softc(m->dev);
if (d == NULL)
- return -1;
+ return (-1);
/* It is safe to drop this mutex due to Giant. */
if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0)
@@ -272,6 +274,13 @@
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 @@
else if (realdev != SOUND_MIXER_NONE &&
MIXER_SET(m, realdev, tl, tr) < 0) {
MIXER_SET_LOCK(m, dropmtx);
- return -1;
+ return (-1);
}
} else if (child != 0) {
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
@@ -305,8 +314,8 @@
realdev = m->realdev[dev];
if (realdev != SOUND_MIXER_NONE &&
MIXER_SET(m, realdev, l, r) < 0) {
- MIXER_SET_LOCK(m, dropmtx);
- return -1;
+ MIXER_SET_LOCK(m, dropmtx);
+ return (-1);
}
} else {
if (dev == SOUND_MIXER_PCM && (d->flags & SD_F_SOFTPCMVOL))
@@ -317,7 +326,7 @@
else if (realdev != SOUND_MIXER_NONE &&
MIXER_SET(m, realdev, l, r) < 0) {
MIXER_SET_LOCK(m, dropmtx);
- return -1;
+ return (-1);
}
}
@@ -326,16 +335,66 @@
m->level[dev] = l | (r << 8);
m->modify_counter++;
- return 0;
+ return (0);
}
static int
mixer_get(struct snd_mixer *mixer, int dev)
{
- if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev)))
- return mixer->level[dev];
+ if ((dev < SOUND_MIXER_NRDEVICES) && (mixer->devs & (1 << dev))) {
+ if (mixer->mutedevs & (1 << dev))
+ return (mixer->level_muted[dev]);
+ else
+ return (mixer->level[dev]);
+ }
else
- return -1;
+ 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 */
+
+ /* Filter out invalid values. */
+ mutedevs &= mixer->devs;
+ 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) {
+ /*
+ * `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;
+ ret += mixer_set(mixer, i, v);
+ }
+ mixer->mutedevs = mutedevs;
+
+ return (ret);
}
static int
@@ -598,6 +657,12 @@
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 +776,7 @@
if (m == NULL)
return (-1);
+ m->mutedevs = 0;
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
v = snd_mixerdefaults[i];
@@ -722,6 +788,11 @@
}
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 +1376,16 @@
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 +1396,9 @@
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;

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 29, 11:33 PM (56 m, 43 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30561260
Default Alt Text
D31130.id92040.diff (5 KB)

Event Timeline