diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 18b2848b4..94ddac96e 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -2207,8 +2207,11 @@ void pa_sink_set_mute(pa_sink *s, bool mute, bool save) { s->muted = mute; s->save_muted = save; - if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->set_mute) + if (!(s->flags & PA_SINK_DEFERRED_VOLUME) && s->set_mute) { + s->set_mute_in_progress = true; s->set_mute(s); + s->set_mute_in_progress = false; + } if (!PA_SINK_IS_LINKED(s->state)) return; @@ -2252,15 +2255,17 @@ void pa_sink_mute_changed(pa_sink *s, bool new_muted) { pa_assert_ctl_context(); pa_assert(PA_SINK_IS_LINKED(s->state)); - /* The sink implementor may call this if the volume changed to make sure everyone is notified */ - - if (s->muted == new_muted) + if (s->set_mute_in_progress) return; - s->muted = new_muted; - s->save_muted = true; + /* pa_sink_set_mute() does this same check, so this may appear redundant, + * but we must have this here also, because the save parameter of + * pa_sink_set_mute() would otherwise have unintended side effects (saving + * the mute state when it shouldn't be saved). */ + if (new_muted == s->muted) + return; - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + pa_sink_set_mute(s, new_muted, true); } /* Called from main thread */ diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 3c796f060..ff97bda33 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -118,6 +118,8 @@ struct pa_sink { unsigned priority; + bool set_mute_in_progress; + /* Called when the main loop requests a state change. Called from * main loop context. If returns -1 the state change will be * inhibited */ diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index bf7e9776d..041375a4d 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -1800,8 +1800,11 @@ void pa_source_set_mute(pa_source *s, bool mute, bool save) { s->muted = mute; s->save_muted = save; - if (!(s->flags & PA_SOURCE_DEFERRED_VOLUME) && s->set_mute) + if (!(s->flags & PA_SOURCE_DEFERRED_VOLUME) && s->set_mute) { + s->set_mute_in_progress = true; s->set_mute(s); + s->set_mute_in_progress = false; + } if (!PA_SOURCE_IS_LINKED(s->state)) return; @@ -1845,15 +1848,17 @@ void pa_source_mute_changed(pa_source *s, bool new_muted) { pa_assert_ctl_context(); pa_assert(PA_SOURCE_IS_LINKED(s->state)); - /* The source implementor may call this if the mute state changed to make sure everyone is notified */ - - if (s->muted == new_muted) + if (s->set_mute_in_progress) return; - s->muted = new_muted; - s->save_muted = true; + /* pa_source_set_mute() does this same check, so this may appear redundant, + * but we must have this here also, because the save parameter of + * pa_source_set_mute() would otherwise have unintended side effects + * (saving the mute state when it shouldn't be saved). */ + if (new_muted == s->muted) + return; - pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); + pa_source_set_mute(s, new_muted, true); } /* Called from main thread */ diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 63185950d..ca2ed59c6 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -118,6 +118,8 @@ struct pa_source { unsigned priority; + bool set_mute_in_progress; + /* Called when the main loop requests a state change. Called from * main loop context. If returns -1 the state change will be * inhibited */