[pulseaudio-commits] [Git][pulseaudio/pulseaudio][master] 8 commits: source-output: change bool save_source to char *preferred_source
Tanu Kaskinen
gitlab at gitlab.freedesktop.org
Sat Dec 14 18:49:36 UTC 2019
Tanu Kaskinen pushed to branch master at PulseAudio / pulseaudio
Commits:
5eec504d by Hui Wang at 2019-12-14T18:40:19Z
source-output: change bool save_source to char *preferred_source
The finial objective is to store the preferred source name in the
source-output struct, and use module-stream-restore to save and
restore it.
This patch just replaces the save_source with preferred_source, and
tries to keep the original logic.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
e529db75 by Hui Wang at 2019-12-14T18:40:19Z
source-output: add a new API pa_source_output_set_preferred_source
If the source here is NULL, that means users want to clear the
preferred_source and move the source-output to the default_source,
otherwise set the preferred_source to the source->name and move the
source-output to the source. After that fire the source_output_change
event.
After adding this API, we can use this API to simplify the entry_apply
in the module-stream-restore.c.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
70bbbcdc by Hui Wang at 2019-12-14T18:40:19Z
source-output: clear the preferred_source if it is default_source
When the user moves a stream to the current default source, the
preferred_source should be set to NULL and module-stream-restore
should clear the routing for that stream in the stream database. From
that point on the stream will be always routed to the default source.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
c254f840 by Hui Wang at 2019-12-14T18:40:19Z
core: move source-outputs conditionally when update default_source
When the default source changes, the streams from the old default
source should be moved to the new default source, unless the
preferred_source string is set to the old default source and the
active port of the old default source is not unavailable
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
1cea7ab3 by Hui Wang at 2019-12-14T18:40:19Z
source: move streams to new appeared sources if they prefer these sources
When a new source appears, all streams that have their
preferred_source set to the new source should be moved to the new
source.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
976a366c by Hui Wang at 2019-12-14T18:40:19Z
device-port: moving streams since active_port on source changes status
When the active port of a source becomes unavailable, all streams from
that source should be moved to the default source.
When the active port of a source changes state from unavailable, all
streams that have their preferred_source set to this source should be
moved to this source.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
5e0d5a86 by Hui Wang at 2019-12-14T18:40:19Z
source: move the streams to the default_source when the source unlink
When a source is unlinked, all streams of this source are moved to
default_source, this action is implemented in the core rather than
modules now.
And after this change, the module-rescue-streams is not needed, but
for backward compatibility, we keep it as a dummy module.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
f62a49b8 by Hui Wang at 2019-12-14T18:40:19Z
stream-restore: skip entries set on source from gnome-control-center
When users select an input device from gnome-control-center UI, the
source of this input device will be set to the
configured_default_source and the default_source, these actions are
expected, but after these actions, the gnome-control-center will call
extension_cb() to modify the entries in the database, let all stream
entries to bind the source users select, this is not correct since the
source is default_source now.
This is a temp fix for this issue, after gnome-control-center fixes
this problem, this patch should be reverted.
Signed-off-by: Hui Wang <hui.wang at canonical.com>
- - - - -
16 changed files:
- src/daemon/default.pa.in
- src/daemon/system.pa.in
- src/modules/module-device-manager.c
- src/modules/module-filter-apply.c
- src/modules/module-intended-roles.c
- src/modules/module-rescue-streams.c
- src/modules/module-stream-restore.c
- src/modules/module-switch-on-connect.c
- src/pulsecore/core.c
- src/pulsecore/core.h
- src/pulsecore/device-port.c
- src/pulsecore/device-port.h
- src/pulsecore/source-output.c
- src/pulsecore/source-output.h
- src/pulsecore/source.c
- src/pulsecore/source.h
Changes:
=====================================
src/daemon/default.pa.in
=====================================
@@ -138,10 +138,6 @@ load-module module-gconf
### that look up the default sink/source get the right value
load-module module-default-device-restore
-### Automatically move streams to the default sink if the sink they are
-### connected to dies, similar for sources
-load-module module-rescue-streams
-
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
=====================================
src/daemon/system.pa.in
=====================================
@@ -52,10 +52,6 @@ load-module module-native-protocol-unix
### that look up the default sink/source get the right value
load-module module-default-device-restore
-### Automatically move streams to the default sink if the sink they are
-### connected to dies, similar for sources
-load-module module-rescue-streams
-
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
=====================================
src/modules/module-device-manager.c
=====================================
@@ -728,10 +728,6 @@ static void route_source_output(struct userdata *u, pa_source_output *so) {
pa_assert(u);
pa_assert(u->do_routing);
- /* Don't override user or application routing requests. */
- if (so->save_source || so->source_requested_by_application)
- return;
-
if (so->direct_on_input)
return;
@@ -739,6 +735,10 @@ static void route_source_output(struct userdata *u, pa_source_output *so) {
if (!so->source)
return;
+ /* Don't override user or application routing requests. */
+ if (pa_safe_streq(so->source->name, so->preferred_source) || so->source_requested_by_application)
+ return;
+
auto_filtered_prop = pa_proplist_gets(so->proplist, "module-device-manager.auto_filtered");
if (auto_filtered_prop)
auto_filtered = (pa_parse_boolean(auto_filtered_prop) == 1);
@@ -1596,7 +1596,7 @@ int pa__init(pa_module*m) {
}
if (on_rescue) {
- /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, module-rescue-streams, ... */
+ /* A little bit later than module-stream-restore, a little bit earlier than module-intended-roles, ... */
u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) sink_unlink_hook_callback, u);
u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u);
}
=====================================
src/modules/module-filter-apply.c
=====================================
@@ -687,8 +687,7 @@ static pa_hook_result_t sink_unlink_cb(pa_core *core, pa_sink *sink, struct user
uint32_t idx;
/* Attempt to rescue any streams to the parent sink as this is likely
- * the best course of action (as opposed to a generic rescue via
- * module-rescue-streams */
+ * the best course of action */
if (filter->sink == sink) {
pa_sink_input *i;
@@ -769,8 +768,7 @@ static pa_hook_result_t source_unlink_cb(pa_core *core, pa_source *source, struc
uint32_t idx;
/* Attempt to rescue any streams to the parent source as this is likely
- * the best course of action (as opposed to a generic rescue via
- * module-rescue-streams */
+ * the best course of action */
if (filter->source == source) {
pa_source_output *o;
=====================================
src/modules/module-intended-roles.c
=====================================
@@ -222,9 +222,6 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
if (so->source == source)
continue;
- if (so->save_source)
- continue;
-
if (so->direct_on_input)
continue;
@@ -233,6 +230,9 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
if (!so->source)
continue;
+ if (pa_safe_streq(so->source->name, so->preferred_source))
+ continue;
+
/* It might happen that a stream and a source are set up at the
same time, in which case we want to make sure we don't
interfere with that */
@@ -398,7 +398,7 @@ int pa__init(pa_module*m) {
}
if (on_rescue) {
- /* A little bit later than module-stream-restore, a little bit earlier than module-rescue-streams, ... */
+ /* A little bit later than module-stream-restore, ... */
u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) sink_unlink_hook_callback, u);
u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+10, (pa_hook_cb_t) source_unlink_hook_callback, u);
}
=====================================
src/modules/module-rescue-streams.c
=====================================
@@ -24,200 +24,23 @@
#include <pulse/xmalloc.h>
#include <pulsecore/core.h>
-#include <pulsecore/source-output.h>
-#include <pulsecore/modargs.h>
#include <pulsecore/log.h>
#include <pulsecore/namereg.h>
#include <pulsecore/core-util.h>
PA_MODULE_AUTHOR("Lennart Poettering");
-PA_MODULE_DESCRIPTION("When a source is removed, try to move its streams to the default source");
+PA_MODULE_DESCRIPTION("This module is obsolete, please remove it from your configuration.");
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_LOAD_ONCE(true);
-static const char* const valid_modargs[] = {
- NULL,
-};
-
-struct userdata {
- pa_hook_slot
- *source_unlink_slot,
- *source_output_move_fail_slot;
-};
-
-static pa_source* find_source_from_port(pa_core *c, pa_device_port *port) {
- pa_source *target;
- uint32_t idx;
- void *state;
- pa_device_port *p;
-
- if (!port)
- return NULL;
-
- PA_IDXSET_FOREACH(target, c->sources, idx)
- PA_HASHMAP_FOREACH(p, target->ports, state)
- if (port == p)
- return target;
-
- return NULL;
-}
-
-static void build_group_ports(pa_hashmap *g_ports, pa_hashmap *s_ports) {
- void *state;
- pa_device_port *p;
-
- if (!g_ports || !s_ports)
- return;
-
- PA_HASHMAP_FOREACH(p, s_ports, state)
- pa_hashmap_put(g_ports, p, p);
-}
-
-static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, pa_source *skip) {
- pa_source *target, *fb_source = NULL;
- uint32_t idx;
- pa_hashmap *all_ports;
- pa_device_port *best_port;
-
- pa_assert(c);
- pa_assert(o);
-
- if (c->default_source && c->default_source != skip && pa_source_output_may_move_to(o, c->default_source))
- return c->default_source;
-
- all_ports = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
-
- PA_IDXSET_FOREACH(target, c->sources, idx) {
- if (target == c->default_source)
- continue;
-
- if (target == skip)
- continue;
-
- /* We only move to a monitor source if we're already on one */
- if (skip && !target->monitor_of != !skip->monitor_of)
- continue;
-
- if (!PA_SOURCE_IS_LINKED(target->state))
- continue;
-
- if (!pa_source_output_may_move_to(o, target))
- continue;
-
- if (!fb_source)
- fb_source = target;
-
- build_group_ports(all_ports, target->ports);
- }
-
- best_port = pa_device_port_find_best(all_ports);
-
- pa_hashmap_free(all_ports);
-
- if (best_port)
- target = find_source_from_port(c, best_port);
- else
- target = fb_source;
-
- if (!target)
- pa_log_debug("No evacuation source found.");
-
- return target;
-}
-
-static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, void* userdata) {
- pa_source_output *o;
- uint32_t idx;
-
- pa_assert(c);
- pa_assert(source);
-
- /* There's no point in doing anything if the core is shut down anyway */
- if (c->state == PA_CORE_SHUTDOWN)
- return PA_HOOK_OK;
-
- if (pa_idxset_size(source->outputs) <= 0) {
- pa_log_debug("No source outputs to move away.");
- return PA_HOOK_OK;
- }
-
- PA_IDXSET_FOREACH(o, source->outputs, idx) {
- pa_source *target;
-
- if (!(target = find_evacuation_source(c, o, source)))
- continue;
-
- if (pa_source_output_move_to(o, target, false) < 0)
- pa_log_info("Failed to move source output %u \"%s\" to %s.", o->index,
- pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), target->name);
- else
- pa_log_info("Successfully moved source output %u \"%s\" to %s.", o->index,
- pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), target->name);
- }
-
- return PA_HOOK_OK;
-}
-
-static pa_hook_result_t source_output_move_fail_hook_callback(pa_core *c, pa_source_output *i, void *userdata) {
- pa_source *target;
-
- pa_assert(c);
- pa_assert(i);
-
- /* There's no point in doing anything if the core is shut down anyway */
- if (c->state == PA_CORE_SHUTDOWN)
- return PA_HOOK_OK;
-
- if (!(target = find_evacuation_source(c, i, NULL)))
- return PA_HOOK_OK;
-
- if (pa_source_output_finish_move(i, target, false) < 0) {
- pa_log_info("Failed to move source output %u \"%s\" to %s.", i->index,
- pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name);
- return PA_HOOK_OK;
-
- } else {
- pa_log_info("Successfully moved source output %u \"%s\" to %s.", i->index,
- pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name);
- return PA_HOOK_STOP;
- }
-}
int pa__init(pa_module*m) {
- pa_modargs *ma;
- struct userdata *u;
pa_assert(m);
- if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
- pa_log("Failed to parse module arguments");
- return -1;
- }
-
- m->userdata = u = pa_xnew(struct userdata, 1);
+ pa_log("module-rescue-stream is obsolete and should no longer be loaded. Please remove it from your configuration.");
- /* A little bit later than module-stream-restore, module-intended-roles... */
- u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) source_unlink_hook_callback, u);
+ pa_module_unload_request(m, false);
- u->source_output_move_fail_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FAIL], PA_HOOK_LATE+20, (pa_hook_cb_t) source_output_move_fail_hook_callback, u);
-
- pa_modargs_free(ma);
return 0;
}
-
-void pa__done(pa_module*m) {
- struct userdata *u;
-
- pa_assert(m);
-
- if (!(u = m->userdata))
- return;
-
- if (u->source_unlink_slot)
- pa_hook_slot_free(u->source_unlink_slot);
-
- if (u->source_output_move_fail_slot)
- pa_hook_slot_free(u->source_output_move_fail_slot);
-
- pa_xfree(u);
-}
=====================================
src/modules/module-stream-restore.c
=====================================
@@ -64,8 +64,8 @@ PA_MODULE_USAGE(
"restore_device=<Save/restore sinks/sources?> "
"restore_volume=<Save/restore volumes?> "
"restore_muted=<Save/restore muted states?> "
- "on_hotplug=<When new device becomes available, recheck streams?> "
- "on_rescue=<When device becomes unavailable, recheck streams?> "
+ "on_hotplug=<This argument is obsolete, please remove it from configuration> "
+ "on_rescue=<This argument is obsolete, please remove it from configuration> "
"fallback_table=<filename>");
#define SAVE_INTERVAL (10 * PA_USEC_PER_SEC)
@@ -95,8 +95,6 @@ struct userdata {
*sink_input_fixate_hook_slot,
*source_output_new_hook_slot,
*source_output_fixate_hook_slot,
- *source_put_hook_slot,
- *source_unlink_hook_slot,
*connection_unlink_hook_slot;
pa_time_event *save_time_event;
pa_database* database;
@@ -104,8 +102,6 @@ struct userdata {
bool restore_device:1;
bool restore_volume:1;
bool restore_muted:1;
- bool on_hotplug:1;
- bool on_rescue:1;
pa_native_protocol *protocol;
pa_idxset *subscribed;
@@ -1369,16 +1365,22 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted);
}
- if (source_output->save_source) {
+ if (source_output->preferred_source != NULL || !created_new_entry) {
+ pa_source *s = NULL;
+
pa_xfree(entry->device);
- entry->device = pa_xstrdup(source_output->source->name);
+ entry->device = pa_xstrdup(source_output->preferred_source);
entry->device_valid = true;
- device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry->device, old->device));
+ if (!entry->device)
+ entry->device_valid = false;
- if (source_output->source->card) {
- pa_xfree(entry->card);
- entry->card = pa_xstrdup(source_output->source->card->name);
+ device_updated = !created_new_entry && !pa_safe_streq(entry->device, old->device);
+ pa_xfree(entry->card);
+ entry->card = NULL;
+ entry->card_valid = false;
+ if (entry->device_valid && (s = pa_namereg_get(c, entry->device, PA_NAMEREG_SOURCE)) && s->card) {
+ entry->card = pa_xstrdup(s->card->name);
entry->card_valid = true;
}
}
@@ -1637,110 +1639,6 @@ static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source
return PA_HOOK_OK;
}
-static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
- pa_source_output *so;
- uint32_t idx;
-
- pa_assert(c);
- pa_assert(source);
- pa_assert(u);
- pa_assert(u->on_hotplug && u->restore_device);
-
- PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
- char *name;
- struct entry *e;
-
- if (so->source == source)
- continue;
-
- if (so->save_source)
- continue;
-
- if (so->direct_on_input)
- continue;
-
- /* Skip this if it is already in the process of being moved anyway */
- if (!so->source)
- continue;
-
- /* Skip this source output if it is connecting a filter source to
- * the master */
- if (so->destination_source)
- continue;
-
- /* It might happen that a stream and a source are set up at the
- same time, in which case we want to make sure we don't
- interfere with that */
- if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state))
- continue;
-
- if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
- continue;
-
- if ((e = entry_read(u, name))) {
- if (e->device_valid && pa_streq(e->device, source->name))
- pa_source_output_move_to(so, source, true);
-
- entry_free(e);
- }
-
- pa_xfree(name);
- }
-
- return PA_HOOK_OK;
-}
-
-static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) {
- pa_source_output *so;
- uint32_t idx;
-
- pa_assert(c);
- pa_assert(source);
- pa_assert(u);
- pa_assert(u->on_rescue && u->restore_device);
-
- /* There's no point in doing anything if the core is shut down anyway */
- if (c->state == PA_CORE_SHUTDOWN)
- return PA_HOOK_OK;
-
- PA_IDXSET_FOREACH(so, source->outputs, idx) {
- char *name;
- struct entry *e;
-
- if (so->direct_on_input)
- continue;
-
- if (!so->source)
- continue;
-
- /* Skip this source output if it is connecting a filter source to
- * the master */
- if (so->destination_source)
- continue;
-
- if (!(name = pa_proplist_get_stream_group(so->proplist, "source-output", IDENTIFICATION_PROPERTY)))
- continue;
-
- if ((e = entry_read(u, name))) {
-
- if (e->device_valid) {
- pa_source *d;
-
- if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
- d != source &&
- PA_SOURCE_IS_LINKED(d->state))
- pa_source_output_move_to(so, d, true);
- }
-
- entry_free(e);
- }
-
- pa_xfree(name);
- }
-
- return PA_HOOK_OK;
-}
-
static int fill_db(struct userdata *u, const char *filename) {
FILE *f;
int n = 0;
@@ -1898,21 +1796,16 @@ static void entry_apply(struct userdata *u, const char *name, struct entry *e) {
if (u->restore_device) {
if (!e->device_valid) {
- if (so->save_source) {
+ if (so->preferred_source != NULL) {
pa_log_info("Ensuring device is not saved for stream %s.", name);
/* If the device is not valid we should make sure the
- save flag is cleared as the user may have specifically
+ preferred_source is cleared as the user may have specifically
removed the source element from the rule. */
- so->save_source = false;
- /* This is cheating a bit. The source output itself has not changed
- but the rules governing its routing have, so we fire this event
- such that other routing modules (e.g. module-device-manager)
- will pick up the change and reapply their routing */
- pa_subscription_post(so->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, so->index);
+ pa_source_output_set_preferred_source(so, NULL);
}
} else if ((s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) {
pa_log_info("Restoring device for stream %s.", name);
- pa_source_output_move_to(so, s, true);
+ pa_source_output_set_preferred_source(so, s);
}
}
}
@@ -2094,11 +1987,13 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio
}
/* When users select an output device from gnome-control-center, the gnome-control-center will change all entries
* in the database to bind the sink of this output device, this is not correct since at this moment, the sink is
- * default_sink and we shouldn't bind a stream to default_sink via preferred_sink or database.
+ * default_sink and we shouldn't bind a stream to default_sink via preferred_sink or database. This also applies
+ * to source, default_source and preferred_source.
* After gnome-control-center fix the issue, let us remove this code */
client_name = pa_strnull(pa_proplist_gets(pa_native_connection_get_client(c)->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
if (pa_safe_streq(client_name, "gnome-control-center")) {
- if (entry->device_valid && m->core->default_sink && pa_safe_streq(device, m->core->default_sink->name)) {
+ if (entry->device_valid && ((m->core->default_sink && pa_safe_streq(device, m->core->default_sink->name)) ||
+ (m->core->default_source && pa_safe_streq(device, m->core->default_source->name)))) {
entry_free(entry);
pa_pstream_send_tagstruct(pa_native_connection_get_pstream(c), reply);
return 0;
@@ -2325,7 +2220,8 @@ int pa__init(pa_module*m) {
pa_sink_input *si;
pa_source_output *so;
uint32_t idx;
- bool restore_device = true, restore_volume = true, restore_muted = true, on_hotplug = true, on_rescue = true;
+ bool restore_device = true, restore_volume = true, restore_muted = true;
+
#ifdef HAVE_DBUS
pa_datum key;
bool done;
@@ -2340,13 +2236,15 @@ int pa__init(pa_module*m) {
if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 ||
pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 ||
- pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 ||
- pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 ||
- pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) {
- pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments");
+ pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0) {
+ pa_log("restore_device=, restore_volume= and restore_muted= expect boolean arguments");
goto fail;
}
+ if (pa_modargs_get_value(ma, "on_hotplug", NULL) != NULL ||
+ pa_modargs_get_value(ma, "on_rescue", NULL) != NULL)
+ pa_log("on_hotplug and on_rescue are obsolete arguments, please remove them from your configuration");
+
if (!restore_muted && !restore_volume && !restore_device)
pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!");
@@ -2356,8 +2254,6 @@ int pa__init(pa_module*m) {
u->restore_device = restore_device;
u->restore_volume = restore_volume;
u->restore_muted = restore_muted;
- u->on_hotplug = on_hotplug;
- u->on_rescue = on_rescue;
u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
u->protocol = pa_native_protocol_get(m->core);
@@ -2373,16 +2269,6 @@ int pa__init(pa_module*m) {
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u);
}
- if (restore_device && on_hotplug) {
- /* A little bit earlier than module-intended-roles ... */
- pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u);
- }
-
- if (restore_device && on_rescue) {
- /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */
- pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u);
- }
-
if (restore_volume || restore_muted) {
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u);
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u);
=====================================
src/modules/module-switch-on-connect.c
=====================================
@@ -116,9 +116,6 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
}
static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, void* userdata) {
- pa_source_output *o;
- uint32_t idx;
- pa_source *old_default_source;
const char *s;
struct userdata *u = userdata;
@@ -172,29 +169,9 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
return PA_HOOK_OK;
}
- old_default_source = c->default_source;
-
/* Actually do the switch to the new source */
pa_core_set_configured_default_source(c, source->name);
- /* Now move all old outputs over */
- if (pa_idxset_size(old_default_source->outputs) <= 0) {
- pa_log_debug("No source outputs to move away.");
- return PA_HOOK_OK;
- }
-
- PA_IDXSET_FOREACH(o, old_default_source->outputs, idx) {
- if (o->save_source || !PA_SOURCE_OUTPUT_IS_LINKED(o->state))
- continue;
-
- if (pa_source_output_move_to(o, source, false) < 0)
- pa_log_info("Failed to move source output %u \"%s\" to %s.", o->index,
- pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), source->name);
- else
- pa_log_info("Successfully moved source output %u \"%s\" to %s.", o->index,
- pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), source->name);
- }
-
return PA_HOOK_OK;
}
@@ -211,7 +188,6 @@ int pa__init(pa_module*m) {
m->userdata = u = pa_xnew0(struct userdata, 1);
- /* A little bit later than module-rescue-streams... */
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE+30, (pa_hook_cb_t) sink_put_hook_callback, u);
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE+20, (pa_hook_cb_t) source_put_hook_callback, u);
=====================================
src/pulsecore/core.c
=====================================
@@ -435,6 +435,10 @@ void pa_core_update_default_source(pa_core *core) {
old_default_source ? old_default_source->name : "(unset)", best ? best->name : "(unset)");
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], core->default_source);
+
+ /* try to move the streams from old_default_source to the new default_source conditionally */
+ if (old_default_source)
+ pa_source_move_streams_to_default_source(core, old_default_source, true);
}
void pa_core_set_exit_idle_time(pa_core *core, int time) {
@@ -555,6 +559,41 @@ void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink
}
+void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s) {
+ pa_source_output *so;
+ uint32_t idx;
+
+ pa_assert(c);
+ pa_assert(s);
+
+ PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
+ if (so->source == s)
+ continue;
+
+ if (so->direct_on_input)
+ continue;
+
+ if (!so->source)
+ continue;
+
+ /* Skip this source output if it is connecting a filter source to
+ * the master */
+ if (so->destination_source)
+ continue;
+
+ /* It might happen that a stream and a source are set up at the
+ same time, in which case we want to make sure we don't
+ interfere with that */
+ if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state))
+ continue;
+
+ if (pa_safe_streq(so->preferred_source, s->name))
+ pa_source_output_move_to(so, s, false);
+ }
+
+}
+
+
/* Helper macro to reduce repetition in pa_suspend_cause_to_string().
* Parameters:
* char *p: the current position in the write buffer
=====================================
src/pulsecore/core.h
=====================================
@@ -281,4 +281,6 @@ const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause, char buf[PA_SUS
void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink *s);
+void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s);
+
#endif
=====================================
src/pulsecore/device-port.c
=====================================
@@ -110,6 +110,16 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
else
pa_core_move_streams_to_newly_available_preferred_sink(p->core, sink);
}
+ } else {
+ pa_source *source;
+
+ source = pa_device_port_get_source(p);
+ if (source && p == source->active_port) {
+ if (source->active_port->available == PA_AVAILABLE_NO)
+ pa_source_move_streams_to_default_source(p->core, source, false);
+ else
+ pa_core_move_streams_to_newly_available_preferred_source(p->core, source);
+ }
}
pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index);
@@ -249,3 +259,16 @@ pa_sink *pa_device_port_get_sink(pa_device_port *p) {
}
return rs;
}
+
+pa_source *pa_device_port_get_source(pa_device_port *p) {
+ pa_source *rs = NULL;
+ pa_source *source;
+ uint32_t state;
+
+ PA_IDXSET_FOREACH(source, p->card->sources, state)
+ if (p == pa_hashmap_get(source->ports, p->name)) {
+ rs = source;
+ break;
+ }
+ return rs;
+}
=====================================
src/pulsecore/device-port.h
=====================================
@@ -89,4 +89,6 @@ pa_device_port *pa_device_port_find_best(pa_hashmap *ports);
pa_sink *pa_device_port_get_sink(pa_device_port *p);
+pa_source *pa_device_port_get_source(pa_device_port *p);
+
#endif
=====================================
src/pulsecore/source-output.c
=====================================
@@ -134,7 +134,10 @@ bool pa_source_output_new_data_set_source(pa_source_output_new_data *data, pa_so
if (!data->req_formats) {
/* We're not working with the extended API */
data->source = s;
- data->save_source = save;
+ if (save) {
+ pa_xfree(data->preferred_source);
+ data->preferred_source = pa_xstrdup(s->name);
+ }
data->source_requested_by_application = requested_by_application;
} else {
/* Extended API: let's see if this source supports the formats the client would like */
@@ -143,7 +146,10 @@ bool pa_source_output_new_data_set_source(pa_source_output_new_data *data, pa_so
if (formats && !pa_idxset_isempty(formats)) {
/* Source supports at least one of the requested formats */
data->source = s;
- data->save_source = save;
+ if (save) {
+ pa_xfree(data->preferred_source);
+ data->preferred_source = pa_xstrdup(s->name);
+ }
data->source_requested_by_application = requested_by_application;
if (data->nego_formats)
pa_idxset_free(data->nego_formats, (pa_free_cb_t) pa_format_info_free);
@@ -170,7 +176,7 @@ bool pa_source_output_new_data_set_formats(pa_source_output_new_data *data, pa_i
if (data->source) {
/* Trigger format negotiation */
- return pa_source_output_new_data_set_source(data, data->source, data->save_source,
+ return pa_source_output_new_data_set_source(data, data->source, (data->preferred_source != NULL),
data->source_requested_by_application);
}
@@ -189,6 +195,9 @@ void pa_source_output_new_data_done(pa_source_output_new_data *data) {
if (data->format)
pa_format_info_free(data->format);
+ if (data->preferred_source)
+ pa_xfree(data->preferred_source);
+
pa_proplist_free(data->proplist);
}
@@ -460,7 +469,7 @@ int pa_source_output_new(
pa_cvolume_reset(&o->real_ratio, o->sample_spec.channels);
o->volume_writable = data->volume_writable;
o->save_volume = data->save_volume;
- o->save_source = data->save_source;
+ o->preferred_source = pa_xstrdup(data->preferred_source);
o->save_muted = data->save_muted;
o->muted = data->muted;
@@ -652,6 +661,9 @@ static void source_output_free(pa_object* mo) {
if (o->proplist)
pa_proplist_free(o->proplist);
+ if (o->preferred_source)
+ pa_xfree(o->preferred_source);
+
pa_xfree(o->driver);
pa_xfree(o);
}
@@ -1545,7 +1557,16 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, bool save
o->moving(o, dest);
o->source = dest;
- o->save_source = save;
+ /* save == true, means user is calling the move_to() and want to
+ save the preferred_source */
+ if (save) {
+ pa_xfree(o->preferred_source);
+ if (dest == dest->core->default_source)
+ o->preferred_source = NULL;
+ else
+ o->preferred_source = pa_xstrdup(dest->name);
+ }
+
pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL);
pa_cvolume_remap(&o->volume_factor_source, &o->channel_map, &o->source->channel_map);
@@ -1869,3 +1890,17 @@ void pa_source_output_set_reference_ratio(pa_source_output *o, const pa_cvolume
pa_cvolume_snprint_verbose(old_ratio_str, sizeof(old_ratio_str), &old_ratio, &o->channel_map, true),
pa_cvolume_snprint_verbose(new_ratio_str, sizeof(new_ratio_str), ratio, &o->channel_map, true));
}
+
+/* Called from the main thread. */
+void pa_source_output_set_preferred_source(pa_source_output *o, pa_source *s) {
+ pa_assert(o);
+
+ pa_xfree(o->preferred_source);
+ if (s) {
+ o->preferred_source = pa_xstrdup(s->name);
+ pa_source_output_move_to(o, s, false);
+ } else {
+ o->preferred_source = NULL;
+ pa_source_output_move_to(o, o->core->default_source, false);
+ }
+}
=====================================
src/pulsecore/source-output.h
=====================================
@@ -106,11 +106,15 @@ struct pa_source_output {
bool muted:1;
- /* if true then the source we are connected to and/or the volume
- * set is worth remembering, i.e. was explicitly chosen by the
- * user and not automatically. module-stream-restore looks for
- * this.*/
- bool save_source:1, save_volume:1, save_muted:1;
+ /* if true then the volume and the mute state of this source-output
+ * are worth remembering, module-stream-restore looks for this. */
+ bool save_volume:1, save_muted:1;
+
+ /* if users move the source-output to a source, and the source is not
+ * default_source, the source->name will be saved in preferred_source. And
+ * later if source-output is moved to other sources for some reason, it
+ * still can be restored to the preferred_source at an appropriate time */
+ char *preferred_source;
pa_resample_method_t requested_resample_method, actual_resample_method;
@@ -277,7 +281,8 @@ typedef struct pa_source_output_new_data {
bool volume_writable:1;
- bool save_source:1, save_volume:1, save_muted:1;
+ bool save_volume:1, save_muted:1;
+ char *preferred_source;
} pa_source_output_new_data;
pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data);
@@ -397,6 +402,8 @@ void pa_source_output_set_volume_direct(pa_source_output *o, const pa_cvolume *v
* o->reference_ratio and logs a message if the value changes. */
void pa_source_output_set_reference_ratio(pa_source_output *o, const pa_cvolume *ratio);
+void pa_source_output_set_preferred_source(pa_source_output *o, pa_source *s);
+
#define pa_source_output_assert_io_context(s) \
pa_assert(pa_thread_mq_get() || !PA_SOURCE_OUTPUT_IS_LINKED((s)->state))
=====================================
src/pulsecore/source.c
=====================================
@@ -666,9 +666,13 @@ void pa_source_put(pa_source *s) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
- /* This function must be called after the PA_CORE_HOOK_SOURCE_PUT hook,
- * because module-switch-on-connect needs to know the old default source */
+ /* It's good to fire the SOURCE_PUT hook before updating the default source,
+ * because module-switch-on-connect will set the new source as the default
+ * source, and if we were to call pa_core_update_default_source() before that,
+ * the default source might change twice, causing unnecessary stream moving. */
pa_core_update_default_source(s->core);
+
+ pa_core_move_streams_to_newly_available_preferred_source(s->core, s);
}
/* Called from main context */
@@ -698,6 +702,9 @@ void pa_source_unlink(pa_source *s) {
pa_core_update_default_source(s->core);
+ if (linked)
+ pa_source_move_streams_to_default_source(s->core, s, false);
+
if (s->card)
pa_idxset_remove_by_data(s->card->sources, s, NULL);
@@ -2988,3 +2995,47 @@ void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volum
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_VOLUME_CHANGED], s);
}
+
+void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source, bool default_source_changed) {
+ pa_source_output *o;
+ uint32_t idx;
+ bool old_source_is_unavailable = false;
+
+ pa_assert(core);
+ pa_assert(old_source);
+
+ if (core->state == PA_CORE_SHUTDOWN)
+ return;
+
+ if (core->default_source == NULL || core->default_source->unlink_requested)
+ return;
+
+ if (old_source == core->default_source)
+ return;
+
+ if (old_source->active_port && old_source->active_port->available == PA_AVAILABLE_NO)
+ old_source_is_unavailable = true;
+
+ PA_IDXSET_FOREACH(o, old_source->outputs, idx) {
+ if (!PA_SOURCE_OUTPUT_IS_LINKED(o->state))
+ continue;
+
+ if (!o->source)
+ continue;
+
+ if (pa_safe_streq(old_source->name, o->preferred_source) && !old_source_is_unavailable)
+ continue;
+
+ if (!pa_source_output_may_move_to(o, core->default_source))
+ continue;
+
+ if (default_source_changed)
+ pa_log_info("The source output %u \"%s\" is moving to %s due to change of the default source.",
+ o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name);
+ else
+ pa_log_info("The source output %u \"%s\" is moving to %s due to unlink of a source.",
+ o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_APPLICATION_NAME)), core->default_source->name);
+
+ pa_source_output_move_to(o, core->default_source, false);
+ }
+}
=====================================
src/pulsecore/source.h
=====================================
@@ -479,6 +479,12 @@ int64_t pa_source_get_latency_within_thread(pa_source *s, bool allow_negative);
* sets s->reference_volume and fires change notifications. */
void pa_source_set_reference_volume_direct(pa_source *s, const pa_cvolume *volume);
+/* When the default_source is changed or the active_port of a source is changed to
+ * PA_AVAILABLE_NO, this function is called to move the streams of the old
+ * default_source or the source with active_port equals PA_AVAILABLE_NO to the
+ * current default_source conditionally*/
+void pa_source_move_streams_to_default_source(pa_core *core, pa_source *old_source, bool default_source_changed);
+
#define pa_source_assert_io_context(s) \
pa_assert(pa_thread_mq_get() || !PA_SOURCE_IS_LINKED((s)->state))
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/compare/734a00c849815a45697970d593068c301a04ebbb...f62a49b8cf109c011a9818d2358beb6834e6ec25
--
View it on GitLab: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/compare/734a00c849815a45697970d593068c301a04ebbb...f62a49b8cf109c011a9818d2358beb6834e6ec25
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/20191214/037d5600/attachment-0001.htm>
More information about the pulseaudio-commits
mailing list