Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150137317
D31130.id92043.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D31130.id92043.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 30, 5:10 PM (18 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30561260
Default Alt Text
D31130.id92043.diff (5 KB)
Attached To
Mode
D31130: sound(4): mixer: implement (un)muting
Attached
Detach File
Event Timeline
Log In to Comment