+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("Successfully 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 (skip && !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) {