This makes sure that when a new Bluetooth device turns up, we set it to the appropriate profile depending on the current list of streams. --- src/modules/module-profile-switcher.c | 48 ++++++++++++++++++++++++++++++++- 1 files changed, 47 insertions(+), 1 deletions(-) diff --git a/src/modules/module-profile-switcher.c b/src/modules/module-profile-switcher.c index 4607ac6..56bc2c1 100644 --- a/src/modules/module-profile-switcher.c +++ b/src/modules/module-profile-switcher.c @@ -32,6 +32,7 @@ #include <pulsecore/sink.h> #include <pulsecore/sink-input.h> #include <pulsecore/source-output.h> +#include <pulsecore/card.h> #include <pulsecore/modargs.h> #include <pulsecore/log.h> @@ -50,7 +51,8 @@ struct userdata { pa_hook_slot *sink_input_put_slot, *sink_input_unlink_post_slot, - *source_output_unlink_post_slot; + *source_output_unlink_post_slot, + *card_new_slot; }; #define GET_ROLE(i) \ @@ -189,6 +191,47 @@ static pa_hook_result_t source_output_unlink_post_cb(pa_core *c, pa_source_outpu return PA_HOOK_OK; } +/* Set the inital profile for the card based on currently available + * sink-inputs and source-outputs. */ +static pa_hook_result_t card_new_cb(pa_core *c, pa_card_new_data *data, void *userdata) { + const char *device_api; + pa_sink_input *input; + pa_source_output *output; + pa_bool_t use_a2dp = TRUE; + uint32_t idx; + + device_api = pa_proplist_gets(data->proplist, PA_PROP_DEVICE_API); + if (!device_api || !pa_streq(device_api, "bluez")) + return PA_HOOK_OK; + + PA_IDXSET_FOREACH(input, c->sink_inputs, idx) { + if (pa_streq(GET_ROLE(input), "phone")) { + use_a2dp = FALSE; + goto done; + } + } + + PA_IDXSET_FOREACH(output, c->source_outputs, idx) { + if (pa_streq(GET_ROLE(output), "phone")) { + use_a2dp = FALSE; + break; + } + } + +done: + if (use_a2dp) { + pa_log_info("No phone streams, switching card '%s' to A2DP profile", data->name); + pa_card_new_data_set_profile(data, "a2dp"); + data->save_profile = FALSE; + } else { + pa_log_info("Have a phone stream, switching card '%s' to HSP/HFP profile", data->name); + pa_card_new_data_set_profile(data, "hsp"); + data->save_profile = FALSE; + } + + return PA_HOOK_OK; +} + int pa__init(pa_module*m) { pa_modargs *ma; struct userdata *u; @@ -206,6 +249,7 @@ 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_EARLY, (pa_hook_cb_t) sink_input_put_cb, u); u->sink_input_unlink_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_unlink_post_cb, u); u->source_output_unlink_post_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_unlink_post_cb, u); + u->card_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) card_new_cb, u); pa_modargs_free(ma); return 0; @@ -225,6 +269,8 @@ void pa__done(pa_module*m) { pa_hook_slot_free(u->sink_input_unlink_post_slot); if (u->source_output_unlink_post_slot) pa_hook_slot_free(u->source_output_unlink_post_slot); + if (u->card_new_slot) + pa_hook_slot_free(u->card_new_slot); pa_xfree(u); } -- 1.7.8.4