diff options
author | Tanu Kaskinen <tanuk@iki.fi> | 2009-08-16 21:25:48 +0300 |
---|---|---|
committer | Tanu Kaskinen <tanuk@iki.fi> | 2009-08-16 21:25:48 +0300 |
commit | bcaba0b1b43d6a1b32aadfa98860f40b2c93e136 (patch) | |
tree | 6bd0d60a8fa822bfd688b90d062d0f73eee2e47e /src/modules/module-rescue-streams.c | |
parent | 2bb3eef414f80189cf6af6cd66c519630e4c0a43 (diff) | |
parent | 01e4b61a910afdd21f860fadbe98075735c2bf51 (diff) |
Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work
Conflicts:
src/Makefile.am
src/daemon/daemon-conf.c
src/daemon/daemon.conf.in
src/modules/module-stream-restore.c
src/pulse/client-conf.c
src/pulsecore/namereg.c
Diffstat (limited to 'src/modules/module-rescue-streams.c')
-rw-r--r-- | src/modules/module-rescue-streams.c | 179 |
1 files changed, 142 insertions, 37 deletions
diff --git a/src/modules/module-rescue-streams.c b/src/modules/module-rescue-streams.c index c23feceb..722d84b2 100644 --- a/src/modules/module-rescue-streams.c +++ b/src/modules/module-rescue-streams.c @@ -45,13 +45,46 @@ static const char* const valid_modargs[] = { }; struct userdata { - pa_hook_slot *sink_slot, *source_slot; + pa_hook_slot + *sink_unlink_slot, + *source_unlink_slot, + *sink_input_move_fail_slot, + *source_output_move_fail_slot; }; -static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { +static pa_sink* find_evacuation_sink(pa_core *c, pa_sink_input *i, pa_sink *skip) { + pa_sink *target, *def; + uint32_t idx; + + pa_assert(c); + pa_assert(i); + + def = pa_namereg_get_default_sink(c); + + if (def && def != skip && pa_sink_input_may_move_to(i, def)) + return def; + + PA_IDXSET_FOREACH(target, c->sinks, idx) { + if (target == def) + continue; + + if (target == skip) + continue; + + if (!PA_SINK_IS_LINKED(pa_sink_get_state(target))) + continue; + + if (pa_sink_input_may_move_to(i, target)) + return target; + } + + pa_log_debug("No evacuation sink found."); + return NULL; +} + +static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { pa_sink_input *i; uint32_t idx; - pa_sink *target; pa_assert(c); pa_assert(sink); @@ -65,21 +98,12 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user return PA_HOOK_OK; } - if (!(target = pa_namereg_get_default_sink(c)) || target == sink) { - - PA_IDXSET_FOREACH(target, c->sinks, idx) - if (target != sink) - break; - - if (!target) { - pa_log_debug("No evacuation sink found."); - return PA_HOOK_OK; - } - } + PA_IDXSET_FOREACH(i, sink->inputs, idx) { + pa_sink *target; - pa_assert(target != sink); + if (!(target = find_evacuation_sink(c, i, sink))) + continue; - PA_IDXSET_FOREACH(i, sink->inputs, idx) { if (pa_sink_input_move_to(i, target, FALSE) < 0) pa_log_info("Failed to move sink input %u \"%s\" to %s.", i->index, pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); @@ -91,9 +115,66 @@ static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* user return PA_HOOK_OK; } -static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void* userdata) { +static pa_hook_result_t sink_input_move_fail_hook_callback(pa_core *c, pa_sink_input *i, void *userdata) { + pa_sink *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_sink(c, i, NULL))) + return PA_HOOK_OK; + + if (pa_sink_input_finish_move(i, target, FALSE) < 0) { + pa_log_info("Failed to move sink input %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("Sucessfully moved sink input %u \"%s\" to %s.", i->index, + pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), target->name); + return PA_HOOK_STOP; + } +} + +static pa_source* find_evacuation_source(pa_core *c, pa_source_output *o, pa_source *skip) { + pa_source *target, *def; + uint32_t idx; + + pa_assert(c); + pa_assert(o); + + def = pa_namereg_get_default_source(c); + + if (def && def != skip && pa_source_output_may_move_to(o, def)) + return def; + + PA_IDXSET_FOREACH(target, c->sources, idx) { + if (target == def) + continue; + + if (target == skip) + continue; + + if (!target->monitor_of != !skip->monitor_of) + continue; + + if (!PA_SOURCE_IS_LINKED(pa_source_get_state(target))) + continue; + + if (pa_source_output_may_move_to(o, target)) + return target; + } + + pa_log_debug("No evacuation source found."); + return NULL; +} + +static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, void* userdata) { pa_source_output *o; - pa_source *target; uint32_t idx; pa_assert(c); @@ -108,21 +189,12 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void return PA_HOOK_OK; } - if (!(target = pa_namereg_get_default_source(c)) || target == source) { - - PA_IDXSET_FOREACH(target, c->sources, idx) - if (target != source && !target->monitor_of == !source->monitor_of) - break; - - if (!target) { - pa_log_info("No evacuation source found."); - return PA_HOOK_OK; - } - } + PA_IDXSET_FOREACH(o, source->outputs, idx) { + pa_source *target; - pa_assert(target != source); + if (!(target = find_evacuation_source(c, o, source))) + continue; - PA_IDXSET_FOREACH(o, source->outputs, idx) { 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); @@ -134,6 +206,31 @@ static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void 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 input %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("Sucessfully moved source input %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; @@ -148,8 +245,11 @@ int pa__init(pa_module*m) { m->userdata = u = pa_xnew(struct userdata, 1); /* A little bit later than module-stream-restore, module-intended-roles... */ - u->sink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) sink_hook_callback, u); - u->source_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) source_hook_callback, u); + u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE+20, (pa_hook_cb_t) sink_unlink_hook_callback, u); + 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); + + u->sink_input_move_fail_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FAIL], PA_HOOK_LATE+20, (pa_hook_cb_t) sink_input_move_fail_hook_callback, u); + 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; @@ -163,10 +263,15 @@ void pa__done(pa_module*m) { if (!(u = m->userdata)) return; - if (u->sink_slot) - pa_hook_slot_free(u->sink_slot); - if (u->source_slot) - pa_hook_slot_free(u->source_slot); + if (u->sink_unlink_slot) + pa_hook_slot_free(u->sink_unlink_slot); + if (u->source_unlink_slot) + pa_hook_slot_free(u->source_unlink_slot); + + if (u->sink_input_move_fail_slot) + pa_hook_slot_free(u->sink_input_move_fail_slot); + if (u->source_output_move_fail_slot) + pa_hook_slot_free(u->source_output_move_fail_slot); pa_xfree(u); } |