From a712cc3a2ed2b407dbec47722e61411ccf94a910 Mon Sep 17 00:00:00 2001 From: Tanu Kaskinen Date: Wed, 20 Apr 2016 15:35:13 +0300 Subject: [PATCH] alsa: ignore jack events when the user is inactive See the big comment in the code for more details. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=93259 --- src/modules/alsa/module-alsa-card.c | 28 ++++++++++++++++++++++++++++ src/pulsecore/card.c | 5 +++++ src/pulsecore/card.h | 2 ++ 3 files changed, 35 insertions(+) diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 286cfc9..b1e3e63 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -369,6 +369,34 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { pa_assert(u); + /* Quick and dirty fix for + * https://bugs.freedesktop.org/show_bug.cgi?id=93259 + * + * Changing the jack state may cause a port change, and a port change will + * make the sink or source change the mixer settings. If there are multiple + * users having pulseaudio running, the mixer changes done by inactive + * users may mess up the volume settings for the active users, because when + * the inactive users change the mixer settings, those changes are picked + * up by the active user's pulseaudio instance and the changes are + * interpreted as if the active user changed the settings manually e.g. + * with alsamixer. Even single-user systems suffer from this, because gdm + * runs its own pulseaudio instance. + * + * Returning early here means that jack state events get ignored while the + * user is inactive. When the user becomes active again, the routing may + * not any more match the real jack state. While this is bad, this should + * nevertheless be better than messing up the volume every time headphones + * are plugged in or out. + * + * It might be better to unload the card altogether when the user becomes + * inactive and udev removes the permission to the card. That requires at + * least improving the default sink handling so that if the unloaded card + * contained the default sink, the default sink should be restored to what + * it was earlier, when the user becomes active and the card becomes + * accessible. */ + if (u->card->suspend_cause & PA_SUSPEND_SESSION) + return 0; + if (mask == SND_CTL_EVENT_MASK_REMOVE) return 0; diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c index b6cbbf7..a86cff4 100644 --- a/src/pulsecore/card.c +++ b/src/pulsecore/card.c @@ -318,6 +318,11 @@ int pa_card_suspend(pa_card *c, bool suspend, pa_suspend_cause_t cause) { pa_assert(c); pa_assert(cause != 0); + if (suspend) + c->suspend_cause |= cause; + else + c->suspend_cause &= ~cause; + PA_IDXSET_FOREACH(sink, c->sinks, idx) { int r; diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h index 30bfc0e..72e7869 100644 --- a/src/pulsecore/card.h +++ b/src/pulsecore/card.h @@ -82,6 +82,8 @@ struct pa_card { bool save_profile:1; + pa_suspend_cause_t suspend_cause; + void *userdata; int (*set_profile)(pa_card *c, pa_card_profile *profile); -- 2.8.1