sound: enforce MASTER volume mute during playback

MASTER mute (vol.mute) works while audio is playing. However, if a
stream is stopped and restarted (PCMTRIG_STOP -> PCMTRIG_START), the
audio will resume even though the mixer shows the MASTER volume as
muted. Other streams that are already playing remain silent. New streams
may also start playing audio regardless of the MASTER mute state.

The volume feeder now considers the MASTER mute when determining whether
a channel should be muted. This ensures MASTER mute is consistently
enforced for all streams and removes the dependency on trigger-driven
state propagation.

Tested with Creative Labs CA0132 card.

MFC after:	1 week
Reviewed by:	christos
Differential Revision:	https://reviews.freebsd.org/D55605
This commit is contained in:
Sean Farley
2026-03-12 19:22:02 +01:00
committed by Christos Margiolis
parent 815ef05284
commit ac5ff28130
+10 -1
View File
@@ -242,11 +242,14 @@ feed_volume_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
{
int temp_vol[SND_CHN_T_VOL_MAX];
struct feed_volume_info *info;
struct snd_mixer *m;
struct snddev_info *d;
uint32_t j, align;
int i, *matrix;
uint8_t *dst;
const int16_t *vol;
const int8_t *muted;
bool master_muted = false;
/*
* Fetch filter data operation.
@@ -278,8 +281,14 @@ feed_volume_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b,
return (FEEDER_FEED(f->source, c, b, count, source));
/* Check if any controls are muted. */
d = (c != NULL) ? c->parentsnddev : NULL;
m = (d != NULL && d->mixer_dev != NULL) ? d->mixer_dev->si_drv1 : NULL;
if (m != NULL)
master_muted = (mix_getmutedevs(m) & (1 << SND_VOL_C_MASTER));
for (j = 0; j != SND_CHN_T_VOL_MAX; j++)
temp_vol[j] = muted[j] ? 0 : vol[j];
temp_vol[j] = (muted[j] || master_muted) ? 0 : vol[j];
dst = b;
align = info->bps * info->channels;