[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] switch-on-connect: Do not overwrite user configured default sink/source

PulseAudio Marge Bot (@pulseaudio-merge-bot) gitlab at gitlab.freedesktop.org
Thu Mar 16 20:22:08 UTC 2023



PulseAudio Marge Bot pushed to branch master at PulseAudio / pulseaudio


Commits:
3aaeb511 by Georg Chini at 2023-03-16T20:19:39+00:00
switch-on-connect: Do not overwrite user configured default sink/source

Currently module-switch-on-connect overwrites the default sink or source that
the user has configured. This means that when the overwritten default sink or
source becomes unavailable, the new default will be chosen based on priority
and the default will not return to the originally configured value.
This patch solves the issue by introducing new core variables for the sink
or source chosen by the policy module which have higher priority than the
user configured defaults.

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/784>

- - - - -


3 changed files:

- src/modules/module-switch-on-connect.c
- src/pulsecore/core.c
- src/pulsecore/core.h


Changes:

=====================================
src/modules/module-switch-on-connect.c
=====================================
@@ -100,7 +100,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
 
     /* No default sink, nothing to move away, just set the new default */
     if (!c->default_sink) {
-        pa_core_set_configured_default_sink(c, sink->name);
+        pa_core_set_policy_default_sink(c, sink->name);
         return PA_HOOK_OK;
     }
 
@@ -116,7 +116,7 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
         }
 
     /* Actually do the switch to the new sink */
-    pa_core_set_configured_default_sink(c, sink->name);
+    pa_core_set_policy_default_sink(c, sink->name);
 
     return PA_HOOK_OK;
 }
@@ -160,7 +160,7 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
 
     /* No default source, nothing to move away, just set the new default */
     if (!c->default_source) {
-        pa_core_set_configured_default_source(c, source->name);
+        pa_core_set_policy_default_source(c, source->name);
         return PA_HOOK_OK;
     }
 
@@ -176,7 +176,7 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
         }
 
     /* Actually do the switch to the new source */
-    pa_core_set_configured_default_source(c, source->name);
+    pa_core_set_policy_default_source(c, source->name);
 
     return PA_HOOK_OK;
 }


=====================================
src/pulsecore/core.c
=====================================
@@ -40,6 +40,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/strbuf.h>
+#include <pulsecore/namereg.h>
 
 #include "core.h"
 
@@ -149,6 +150,10 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t
 
     c->default_source = NULL;
     c->default_sink = NULL;
+    c->configured_default_source = NULL;
+    c->configured_default_sink = NULL;
+    c->policy_default_source = NULL;
+    c->policy_default_sink = NULL;
 
     c->default_sample_spec.format = PA_SAMPLE_S16NE;
     c->default_sample_spec.rate = 44100;
@@ -261,6 +266,8 @@ static void core_free(pa_object *o) {
     pa_assert(!c->default_sink);
     pa_xfree(c->configured_default_source);
     pa_xfree(c->configured_default_sink);
+    pa_xfree(c->policy_default_source);
+    pa_xfree(c->policy_default_sink);
 
     pa_silence_cache_done(&c->silence_cache);
     pa_mempool_unref(c->mempool);
@@ -271,6 +278,36 @@ static void core_free(pa_object *o) {
     pa_xfree(c);
 }
 
+static bool is_sink_available(pa_core *core, const char *sink_name) {
+    pa_sink *sink;
+
+    if (!(sink = pa_namereg_get(core, sink_name, PA_NAMEREG_SINK)))
+        return false;
+
+    if (!PA_SINK_IS_LINKED(sink->state))
+        return false;
+
+    if (sink->active_port && sink->active_port->available == PA_AVAILABLE_NO)
+        return false;
+
+    return true;
+}
+
+static bool is_source_available(pa_core *core, const char *source_name) {
+    pa_source *source;
+
+    if (!(source = pa_namereg_get(core, source_name, PA_NAMEREG_SOURCE)))
+        return false;
+
+    if (!PA_SOURCE_IS_LINKED(source->state))
+        return false;
+
+    if (source->active_port && source->active_port->available == PA_AVAILABLE_NO)
+        return false;
+
+    return true;
+}
+
 void pa_core_set_configured_default_sink(pa_core *core, const char *sink) {
     char *old_sink;
 
@@ -278,13 +315,21 @@ void pa_core_set_configured_default_sink(pa_core *core, const char *sink) {
 
     old_sink = pa_xstrdup(core->configured_default_sink);
 
-    if (pa_safe_streq(sink, old_sink))
+    /* The default sink was overwritten by the policy default sink, but the user is
+     * now setting a new default manually. Clear the policy default sink. */
+    if (core->policy_default_sink && is_sink_available(core, core->policy_default_sink)) {
+        pa_xfree(core->policy_default_sink);
+        core->policy_default_sink = NULL;
+
+    } else if (pa_safe_streq(sink, old_sink))
         goto finish;
 
     pa_xfree(core->configured_default_sink);
     core->configured_default_sink = pa_xstrdup(sink);
-    pa_log_info("configured_default_sink: %s -> %s",
-                old_sink ? old_sink : "(unset)", sink ? sink : "(unset)");
+    if (!pa_safe_streq(sink, old_sink)) {
+        pa_log_info("configured_default_sink: %s -> %s",
+                    old_sink ? old_sink : "(unset)", sink ? sink : "(unset)");
+    }
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
 
     pa_core_update_default_sink(core);
@@ -300,12 +345,64 @@ void pa_core_set_configured_default_source(pa_core *core, const char *source) {
 
     old_source = pa_xstrdup(core->configured_default_source);
 
-    if (pa_safe_streq(source, old_source))
+    /* The default source was overwritten by the policy default source, but the user is
+     * now setting a new default manually. Clear the policy default source. */
+    if (core->policy_default_source && is_source_available(core, core->policy_default_source)) {
+        pa_xfree(core->policy_default_source);
+        core->policy_default_source = NULL;
+
+    } else if (pa_safe_streq(source, old_source))
         goto finish;
 
     pa_xfree(core->configured_default_source);
     core->configured_default_source = pa_xstrdup(source);
-    pa_log_info("configured_default_source: %s -> %s",
+    if (!pa_safe_streq(source, old_source)) {
+        pa_log_info("configured_default_source: %s -> %s",
+                    old_source ? old_source : "(unset)", source ? source : "(unset)");
+    }
+    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
+
+    pa_core_update_default_source(core);
+
+finish:
+    pa_xfree(old_source);
+}
+
+void pa_core_set_policy_default_sink(pa_core *core, const char *sink) {
+    char *old_sink;
+
+    pa_assert(core);
+
+    old_sink = pa_xstrdup(core->policy_default_sink);
+
+    if (pa_safe_streq(sink, old_sink))
+        goto finish;
+
+    pa_xfree(core->policy_default_sink);
+    core->policy_default_sink = pa_xstrdup(sink);
+    pa_log_info("policy_default_sink: %s -> %s",
+                old_sink ? old_sink : "(unset)", sink ? sink : "(unset)");
+    pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
+
+    pa_core_update_default_sink(core);
+
+finish:
+    pa_xfree(old_sink);
+}
+
+void pa_core_set_policy_default_source(pa_core *core, const char *source) {
+    char *old_source;
+
+    pa_assert(core);
+
+    old_source = pa_xstrdup(core->policy_default_source);
+
+    if (pa_safe_streq(source, old_source))
+        goto finish;
+
+    pa_xfree(core->policy_default_source);
+    core->policy_default_source = pa_xstrdup(source);
+    pa_log_info("policy_default_source: %s -> %s",
                 old_source ? old_source : "(unset)", source ? source : "(unset)");
     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
 
@@ -331,7 +428,14 @@ static int compare_sinks(pa_sink *a, pa_sink *b) {
             && (!a->active_port || a->active_port->available != PA_AVAILABLE_NO))
         return 1;
 
-    /* The configured default sink is preferred over any other sink. */
+    /* The policy default sink is preferred over any other sink. */
+    if (pa_safe_streq(b->name, core->policy_default_sink))
+        return -1;
+    if (pa_safe_streq(a->name, core->policy_default_sink))
+        return 1;
+
+    /* The configured default sink is preferred over any other sink
+     * except the policy default sink. */
     if (pa_safe_streq(b->name, core->configured_default_sink))
         return -1;
     if (pa_safe_streq(a->name, core->configured_default_sink))
@@ -412,7 +516,14 @@ static int compare_sources(pa_source *a, pa_source *b) {
             && (!a->active_port || a->active_port->available != PA_AVAILABLE_NO))
         return 1;
 
-    /* The configured default source is preferred over any other source. */
+    /* The policy default source is preferred over any other source. */
+    if (pa_safe_streq(b->name, core->policy_default_source))
+        return -1;
+    if (pa_safe_streq(a->name, core->policy_default_source))
+        return 1;
+
+    /* The configured default source is preferred over any other source
+     * except the policy default source. */
     if (pa_safe_streq(b->name, core->configured_default_source))
         return -1;
     if (pa_safe_streq(a->name, core->configured_default_source))


=====================================
src/pulsecore/core.h
=====================================
@@ -176,6 +176,13 @@ struct pa_core {
     char *configured_default_sink;
     char *configured_default_source;
 
+    /* The default sink/source set by some policy module. This will override
+     * the user configured default sink/source, so that the default will
+     * return to the user configured sink/source once the sink/source set by
+     * the policy module is no longer available. */
+    char *policy_default_sink;
+    char *policy_default_source;
+
     /* The effective default sink/source. If no sink or source is explicitly
      * configured as the default, we pick the device that ranks highest
      * according to the compare_sinks() and compare_sources() functions in
@@ -249,6 +256,8 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t
 
 void pa_core_set_configured_default_sink(pa_core *core, const char *sink);
 void pa_core_set_configured_default_source(pa_core *core, const char *source);
+void pa_core_set_policy_default_sink(pa_core *core, const char *sink);
+void pa_core_set_policy_default_source(pa_core *core, const char *source);
 
 /* These should be called whenever something changes that may affect the
  * default sink or source choice.



View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/3aaeb5113d2cec907bd101df22bb28b1a1b8394d

-- 
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/commit/3aaeb5113d2cec907bd101df22bb28b1a1b8394d
You're receiving this email because of your account on gitlab.freedesktop.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/pulseaudio-commits/attachments/20230316/a3d3f750/attachment-0001.htm>


More information about the pulseaudio-commits mailing list