diff options
Diffstat (limited to 'src/modules/module-filter-heuristics.c')
-rw-r--r-- | src/modules/module-filter-heuristics.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/src/modules/module-filter-heuristics.c b/src/modules/module-filter-heuristics.c index a385ff24..20a48355 100644 --- a/src/modules/module-filter-heuristics.c +++ b/src/modules/module-filter-heuristics.c @@ -33,6 +33,8 @@ #include "module-filter-heuristics-symdef.h" +#define PA_PROP_FILTER_APPLY_MOVING "filter.apply.moving" +#define PA_PROP_FILTER_HEURISTICS "filter.heuristics" PA_MODULE_AUTHOR("Colin Guthrie"); PA_MODULE_DESCRIPTION("Detect when various filters are desirable"); @@ -46,27 +48,63 @@ static const char* const valid_modargs[] = { struct userdata { pa_core *core; pa_hook_slot - *sink_input_put_slot; + *sink_input_put_slot, + *sink_input_move_finish_slot; }; -static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, struct userdata *u) { - const char *sink_role, *si_role; +static pa_hook_result_t process(struct userdata *u, pa_sink_input *i) { + const char *want, *sink_role, *si_role; + + /* 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)) + 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 (apply && pa_streq(apply, "echo-cancel")) { + pa_proplist_unset(i->proplist, PA_PROP_FILTER_APPLY); + pa_proplist_unset(i->proplist, PA_PROP_FILTER_HEURISTICS); + } + + return PA_HOOK_OK; + } + + 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"); + } + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, struct userdata *u) { pa_core_assert_ref(core); pa_sink_input_assert_ref(i); pa_assert(u); - /* If the stream already specifies what it wants, then let it be. */ - if (pa_proplist_gets(i->proplist, PA_PROP_FILTER_WANT)) - return PA_HOOK_OK; + return process(u, i); +} - if ((sink_role = pa_proplist_gets(i->sink->proplist, PA_PROP_DEVICE_INTENDED_ROLES)) && strstr(sink_role, "phone")) - return PA_HOOK_OK; +static pa_hook_result_t sink_input_move_finish_cb(pa_core *core, pa_sink_input *i, struct userdata *u) { + pa_core_assert_ref(core); + pa_sink_input_assert_ref(i); + pa_assert(u); - if ((si_role = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE)) && pa_streq(si_role, "phone")) - pa_proplist_sets(i->proplist, PA_PROP_FILTER_WANT, "echo-cancel"); + /* module-filter-apply triggered this move, ignore */ + if (pa_proplist_gets(i->proplist, PA_PROP_FILTER_APPLY_MOVING)) + return PA_HOOK_OK; - return PA_HOOK_OK; + return process(u, i); } int pa__init(pa_module *m) { @@ -85,6 +123,7 @@ int pa__init(pa_module *m) { u->core = m->core; 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); pa_modargs_free(ma); @@ -111,6 +150,8 @@ void pa__done(pa_module *m) { if (u->sink_input_put_slot) 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); pa_xfree(u); |