X-Git-Url: https://code.delx.au/pulseaudio/blobdiff_plain/ceca42f706c7d193cbda4e201d84f62790f0a465..a67318f8affc4973507811946708bc17e63f1ec7:/src/modules/module-filter-heuristics.c?ds=sidebyside diff --git a/src/modules/module-filter-heuristics.c b/src/modules/module-filter-heuristics.c index 20a48355..885b02ee 100644 --- a/src/modules/module-filter-heuristics.c +++ b/src/modules/module-filter-heuristics.c @@ -23,8 +23,9 @@ #include #endif +#include + #include -#include #include #include #include @@ -39,7 +40,7 @@ PA_MODULE_AUTHOR("Colin Guthrie"); PA_MODULE_DESCRIPTION("Detect when various filters are desirable"); PA_MODULE_VERSION(PACKAGE_VERSION); -PA_MODULE_LOAD_ONCE(TRUE); +PA_MODULE_LOAD_ONCE(true); static const char* const valid_modargs[] = { NULL @@ -49,39 +50,45 @@ struct userdata { pa_core *core; pa_hook_slot *sink_input_put_slot, - *sink_input_move_finish_slot; + *sink_input_move_finish_slot, + *source_output_put_slot, + *source_output_move_finish_slot; }; -static pa_hook_result_t process(struct userdata *u, pa_sink_input *i) { - const char *want, *sink_role, *si_role; +static pa_hook_result_t process(struct userdata *u, pa_object *o, bool is_sink_input) { + const char *want; + pa_proplist *pl, *parent_pl; + + if (is_sink_input) { + pl = PA_SINK_INPUT(o)->proplist; + parent_pl = PA_SINK_INPUT(o)->sink->proplist; + } else { + pl = PA_SOURCE_OUTPUT(o)->proplist; + parent_pl = PA_SOURCE_OUTPUT(o)->source->proplist; + } /* If the stream already specifies what it must have, then let it be. */ - if (!pa_proplist_gets(i->proplist, PA_PROP_FILTER_HEURISTICS) && pa_proplist_gets(i->proplist, PA_PROP_FILTER_APPLY)) + if (!pa_proplist_gets(pl, PA_PROP_FILTER_HEURISTICS) && pa_proplist_gets(pl, PA_PROP_FILTER_APPLY)) return PA_HOOK_OK; - want = pa_proplist_gets(i->proplist, PA_PROP_FILTER_WANT); - if (!want) { - /* This is a phone stream, maybe we want echo cancellation */ - if ((si_role = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE)) && pa_streq(si_role, "phone")) - want = "echo-cancel"; - } - /* On phone sinks, make sure we're not applying echo cancellation */ - if ((sink_role = pa_proplist_gets(i->sink->proplist, PA_PROP_DEVICE_INTENDED_ROLES)) && strstr(sink_role, "phone")) { - const char *apply = pa_proplist_gets(i->proplist, PA_PROP_FILTER_APPLY); + if (pa_str_in_list_spaces(pa_proplist_gets(parent_pl, PA_PROP_DEVICE_INTENDED_ROLES), "phone")) { + const char *apply = pa_proplist_gets(pl, PA_PROP_FILTER_APPLY); if (apply && pa_streq(apply, "echo-cancel")) { - pa_proplist_unset(i->proplist, PA_PROP_FILTER_APPLY); - pa_proplist_unset(i->proplist, PA_PROP_FILTER_HEURISTICS); + pa_proplist_unset(pl, PA_PROP_FILTER_APPLY); + pa_proplist_unset(pl, PA_PROP_FILTER_HEURISTICS); } return PA_HOOK_OK; } + want = pa_proplist_gets(pl, PA_PROP_FILTER_WANT); + if (want) { /* There's a filter that we want, ask module-filter-apply to apply it, and remember that we're managing filter.apply */ - pa_proplist_sets(i->proplist, PA_PROP_FILTER_APPLY, want); - pa_proplist_sets(i->proplist, PA_PROP_FILTER_HEURISTICS, "1"); + pa_proplist_sets(pl, PA_PROP_FILTER_APPLY, want); + pa_proplist_sets(pl, PA_PROP_FILTER_HEURISTICS, "1"); } return PA_HOOK_OK; @@ -92,7 +99,7 @@ static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, struc pa_sink_input_assert_ref(i); pa_assert(u); - return process(u, i); + return process(u, PA_OBJECT(i), true); } static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input *i, struct userdata *u) { @@ -104,7 +111,27 @@ static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input * if (pa_proplist_gets(i->proplist, PA_PROP_FILTER_APPLY_MOVING)) return PA_HOOK_OK; - return process(u, i); + return process(u, PA_OBJECT(i), true); +} + +static pa_hook_result_t source_output_put_cb(pa_core *core, pa_source_output *i, struct userdata *u) { + pa_core_assert_ref(core); + pa_source_output_assert_ref(i); + pa_assert(u); + + return process(u, PA_OBJECT(i), false); +} + +static pa_hook_result_t source_output_move_finish_cb(pa_core *core, pa_source_output *i, struct userdata *u) { + pa_core_assert_ref(core); + pa_source_output_assert_ref(i); + pa_assert(u); + + /* module-filter-apply triggered this move, ignore */ + if (pa_proplist_gets(i->proplist, PA_PROP_FILTER_APPLY_MOVING)) + return PA_HOOK_OK; + + return process(u, PA_OBJECT(i), false); } int pa__init(pa_module *m) { @@ -124,6 +151,8 @@ int pa__init(pa_module *m) { u->sink_input_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE-1, (pa_hook_cb_t) sink_input_put_cb, u); u->sink_input_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_LATE-1, (pa_hook_cb_t) sink_input_move_finish_cb, u); + u->source_output_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_LATE-1, (pa_hook_cb_t) source_output_put_cb, u); + u->source_output_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], PA_HOOK_LATE-1, (pa_hook_cb_t) source_output_move_finish_cb, u); pa_modargs_free(ma); @@ -137,7 +166,6 @@ fail: return -1; - } void pa__done(pa_module *m) { @@ -152,6 +180,10 @@ void pa__done(pa_module *m) { pa_hook_slot_free(u->sink_input_put_slot); if (u->sink_input_move_finish_slot) pa_hook_slot_free(u->sink_input_move_finish_slot); + if (u->source_output_put_slot) + pa_hook_slot_free(u->source_output_put_slot); + if (u->source_output_move_finish_slot) + pa_hook_slot_free(u->source_output_move_finish_slot); pa_xfree(u);