summaryrefslogtreecommitdiff
path: root/src/pulsecore/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore/core.c')
-rw-r--r--src/pulsecore/core.c125
1 files changed, 118 insertions, 7 deletions
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 132f08bbb..df7b72461 100644
--- a/src/pulsecore/core.c
+++ b/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))