Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131863903
D31130.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D31130.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 v);
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
@@ -51,16 +51,16 @@
KOBJ_FIELDS;
void *devinfo;
int busy;
- int hwvol_muted;
int hwvol_mixer;
int hwvol_step;
int type;
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];
@@ -244,7 +244,7 @@
}
static int
-mixer_set(struct snd_mixer *m, u_int dev, u_int lev)
+mixer_set(struct snd_mixer *m, u_int dev, u_int32_t muted, u_int lev)
{
struct snddev_info *d;
u_int l, r, tl, tr;
@@ -254,7 +254,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 +262,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)
@@ -270,6 +270,11 @@
else
dropmtx = 0;
+ /* Allow the volume to be "changed" while muted. */
+ if (muted & (1 << dev)) {
+ m->level_muted[dev] = l | (r << 8);
+ return (0);
+ }
MIXER_SET_UNLOCK(m, dropmtx);
/* TODO: recursive handling */
@@ -287,7 +292,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 +310,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 +322,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 +331,42 @@
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];
- else
- return -1;
+ 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);
+ }
+}
+
+void
+mix_setmutedevs(struct snd_mixer *mixer, u_int32_t mutedevs)
+{
+ u_int32_t delta;
+
+ /* Filter out invalid values. */
+ mutedevs &= mixer->devs;
+ delta = (mixer->mutedevs ^ mutedevs) & mixer->devs;
+ mixer->mutedevs = mutedevs;
+
+ for (int i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (!(delta & (1 << i)))
+ continue;
+ if (mutedevs & (1 << i)) {
+ mixer->level_muted[i] = mixer->level[i];
+ mixer_set(mixer, i, 0, 0);
+ } else {
+ mixer_set(mixer, i, 0, mixer->level_muted[i]);
+ }
+ }
}
static int
@@ -598,6 +629,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)
{
@@ -721,7 +758,7 @@
}
}
- mixer_set(m, i, v | (v << 8));
+ mixer_set(m, i, 0, v | (v << 8));
}
mixer_setrecsrc(m, 0); /* Set default input. */
@@ -799,7 +836,7 @@
snd_mtxlock(m->lock);
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- mixer_set(m, i, 0);
+ mixer_set(m, i, 0, 0);
mixer_setrecsrc(m, SOUND_MASK_MIC);
@@ -836,8 +873,12 @@
return i;
}
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- mixer_set(m, i, m->level[i]);
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (m->mutedevs & (1 << i))
+ mixer_set(m, i, 0, 0);
+ else
+ mixer_set(m, i, 0, m->level[i]);
+ }
mixer_setrecsrc(m, m->recsrc);
snd_mtxunlock(m->lock);
@@ -863,10 +904,8 @@
if (dev == -1) {
snd_mtxunlock(m->lock);
return EINVAL;
- }
- else if (dev != m->hwvol_mixer) {
+ } else {
m->hwvol_mixer = dev;
- m->hwvol_muted = 0;
}
}
snd_mtxunlock(m->lock);
@@ -897,14 +936,7 @@
void
mixer_hwvol_mute_locked(struct snd_mixer *m)
{
- if (m->hwvol_muted) {
- m->hwvol_muted = 0;
- mixer_set(m, m->hwvol_mixer, m->hwvol_mute_level);
- } else {
- m->hwvol_muted++;
- m->hwvol_mute_level = mixer_get(m, m->hwvol_mixer);
- mixer_set(m, m->hwvol_mixer, 0);
- }
+ mix_setmutedevs(m, m->mutedevs ^ (1 << m->hwvol_mixer));
}
void
@@ -925,11 +957,8 @@
{
int level, left, right;
- if (m->hwvol_muted) {
- m->hwvol_muted = 0;
- level = m->hwvol_mute_level;
- } else
- level = mixer_get(m, m->hwvol_mixer);
+ level = mixer_get(m, m->hwvol_mixer);
+
if (level != -1) {
left = level & 0xff;
right = (level >> 8) & 0xff;
@@ -943,7 +972,8 @@
right = 0;
else if (right > 100)
right = 100;
- mixer_set(m, m->hwvol_mixer, left | right << 8);
+
+ mixer_set(m, m->hwvol_mixer, m->mutedevs, left | right << 8);
}
}
@@ -976,7 +1006,7 @@
KASSERT(m != NULL, ("NULL snd_mixer"));
snd_mtxlock(m->lock);
- ret = mixer_set(m, dev, left | (right << 8));
+ ret = mixer_set(m, dev, m->mutedevs, left | (right << 8));
snd_mtxunlock(m->lock);
return ((ret != 0) ? ENXIO : 0);
@@ -1304,10 +1334,18 @@
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
- ret = mixer_set(m, j, *arg_i);
+ break;
+ case SOUND_MIXER_MUTE:
+ mix_setmutedevs(m, *arg_i);
+ ret = 0;
+ break;
+ default:
+ ret = mixer_set(m, j, m->mutedevs, *arg_i);
+ break;
+ }
snd_mtxunlock(m->lock);
return ((ret == 0) ? 0 : ENXIO);
}
@@ -1318,6 +1356,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;
@@ -1326,6 +1367,7 @@
break;
default:
v = mixer_get(m, j);
+ break;
}
*arg_i = v;
snd_mtxunlock(m->lock);
@@ -1554,5 +1596,5 @@
level = (left & 0xFF) | ((right & 0xFF) << 8);
- return (mixer_set(m, dev, level));
+ return (mixer_set(m, dev, m->mutedevs, level));
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 12, 7:23 PM (5 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23637549
Default Alt Text
D31130.diff (6 KB)
Attached To
Mode
D31130: sound(4): mixer: implement (un)muting
Attached
Detach File
Event Timeline
Log In to Comment