From: Mikel Astiz <mikel.astiz@xxxxxxxxxxxx> Merge hooks into a single callback to avoid duplicated code. --- src/modules/bluetooth/module-bluetooth-policy.c | 103 ++++++++++------------- 1 files changed, 46 insertions(+), 57 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-policy.c b/src/modules/bluetooth/module-bluetooth-policy.c index 03beeb2..c5db1d3 100644 --- a/src/modules/bluetooth/module-bluetooth-policy.c +++ b/src/modules/bluetooth/module-bluetooth-policy.c @@ -56,76 +56,65 @@ struct userdata { pa_hook_slot *sink_put_slot; }; -/* When a source is created, loopback it to default sink */ -static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, void *userdata) { - struct userdata *u = userdata; +static const char *get_bluetooth_protocol(pa_proplist *p) { const char *s; - const char *role; - char *args; - - pa_assert(c); - pa_assert(source); /* Only consider bluetooth sinks and sources */ - s = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_BUS); + s = pa_proplist_gets(p, PA_PROP_DEVICE_BUS); if (!s) - return PA_HOOK_OK; + return NULL; if (!pa_streq(s, "bluetooth")) - return PA_HOOK_OK; - - s = pa_proplist_gets(source->proplist, "bluetooth.protocol"); - if (!s) - return PA_HOOK_OK; - - if (u->enable_a2dp_source && pa_streq(s, "a2dp_source")) /* A2DP profile (we're doing sink role) */ - role = "music"; - else if (u->enable_hfgw && pa_streq(s, "hfgw")) /* HFP profile (we're doing headset role) */ - role = "phone"; - else { - pa_log_debug("Profile %s cannot be selected for loopback", s); - return PA_HOOK_OK; - } - - /* Load module-loopback */ - args = pa_sprintf_malloc("source=\"%s\" source_dont_move=\"true\" sink_input_properties=\"media.role=%s\"", source->name, role); - (void) pa_module_load(c, "module-loopback", args); - pa_xfree(args); + return NULL; - return PA_HOOK_OK; + return pa_proplist_gets(p, "bluetooth.protocol"); } -/* When a sink is created, loopback it to default source */ -static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void *userdata) { - struct userdata *u = userdata; - const char *s; - const char *role; +static pa_hook_result_t device_hook_callback(pa_core *c, pa_object *o, struct userdata *u) { char *args; pa_assert(c); - pa_assert(sink); - - /* Only consider bluetooth sinks and sources */ - s = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_BUS); - if (!s) - return PA_HOOK_OK; - - if (!pa_streq(s, "bluetooth")) - return PA_HOOK_OK; - - s = pa_proplist_gets(sink->proplist, "bluetooth.protocol"); - if (!s) + pa_assert(o); + pa_assert(u); + + if (pa_sink_isinstance(o)) { + pa_sink *sink = PA_SINK(o); + const char *protocol = get_bluetooth_protocol(sink->proplist); + const char *role; + + if (protocol == NULL) + return PA_HOOK_OK; + + if (u->enable_hfgw && pa_streq(protocol, "hfgw")) /* HFP profile (we're doing headset role) */ + role = "phone"; + else { + pa_log_debug("Profile %s cannot be selected for loopback", protocol); + return PA_HOOK_OK; + } + + args = pa_sprintf_malloc("sink=\"%s\" sink_dont_move=\"true\" source_output_properties=\"media.role=%s\"", sink->name, role); + } else if (pa_source_isinstance(o)) { + pa_source *source = PA_SOURCE(o); + const char *protocol = get_bluetooth_protocol(source->proplist); + const char *role; + + if (protocol == NULL) + return PA_HOOK_OK; + + if (u->enable_a2dp_source && pa_streq(protocol, "a2dp_source")) /* A2DP profile (we're doing sink role) */ + role = "music"; + else if (u->enable_hfgw && pa_streq(protocol, "hfgw")) /* HFP profile (we're doing headset role) */ + role = "phone"; + else { + pa_log_debug("Profile %s cannot be selected for loopback", protocol); + return PA_HOOK_OK; + } + + args = pa_sprintf_malloc("source=\"%s\" source_dont_move=\"true\" sink_input_properties=\"media.role=%s\"", source->name, role); + } else return PA_HOOK_OK; - if (u->enable_hfgw && pa_streq(s, "hfgw")) /* HFP profile (we're doing headset role) */ - role = "phone"; - else { - pa_log_debug("Profile %s cannot be selected for loopback", s); - return PA_HOOK_OK; - } - /* Load module-loopback */ - args = pa_sprintf_malloc("sink=\"%s\" sink_dont_move=\"true\" source_output_properties=\"media.role=%s\"", sink->name, role); (void) pa_module_load(c, "module-loopback", args); pa_xfree(args); @@ -157,9 +146,9 @@ int pa__init(pa_module *m) { goto fail; } - u->source_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) source_put_hook_callback, u); + u->source_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) device_hook_callback, u); - u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_put_hook_callback, u); + u->sink_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) device_hook_callback, u); pa_modargs_free(ma); return 0; -- 1.7.7.6