When I test this patch, I get bitten by the same thing I got when I developed my version of the patch: The "remote end hung up" problem which causes the sink to be constantly suspended. I worked around this myself by disabling this code: - release = (t->state != PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile); + release = (false && t->state != PA_BLUETOOTH_TRANSPORT_STATE_PLAYING && u->profile == t->profile); ...but that's obviously wrong. On 2014-12-16 12:14, Tanu Kaskinen wrote: > The bluetooth card is created when the first profile becomes > available, which means that the card may have profiles that are not > available when the card is initialized. If module-card-restore tries > to restore such profile, that will fail, and the card will be > initialized with the "off" profile active. > > This patch modifies module-card-restore so that if follows the profile > availability status, and when the saved profile becomes available, it > is activated. Additionally, module-card-restore is modified so that it > doesn't even try to restore unavailable profiles, when the necessary > information is available. In practice there are two existing places > where the profile is restored, and only one of those contexts has the > necessary information available. Unfortunately, it's the more > important context (card creation) where the information is not > available. This means that module-card-restore will set the initial > profile of a new card even if the profile is unavailable, and this > will cause an ugly warning in the log, even though there's nothing > abnormal happening. > > BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=87081 > --- > src/modules/module-card-restore.c | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c > index 681acca..beb748e 100644 > --- a/src/modules/module-card-restore.c > +++ b/src/modules/module-card-restore.c > @@ -66,6 +66,7 @@ struct userdata { > pa_hook_slot *card_put_hook_slot; > pa_hook_slot *card_profile_changed_hook_slot; > pa_hook_slot *card_profile_added_hook_slot; > + pa_hook_slot *profile_available_changed_hook_slot; > pa_hook_slot *port_offset_hook_slot; > pa_time_event *save_time_event; > pa_database *database; > @@ -412,6 +413,9 @@ static pa_hook_result_t card_profile_added_callback(pa_core *c, pa_card_profile > > pa_assert(profile); > > + if (profile->available == PA_AVAILABLE_NO) > + return PA_HOOK_OK; > + > if (!(entry = entry_read(u, profile->card->name))) > return PA_HOOK_OK; > > @@ -425,6 +429,33 @@ static pa_hook_result_t card_profile_added_callback(pa_core *c, pa_card_profile > return PA_HOOK_OK; > } > > +static pa_hook_result_t profile_available_changed_callback(void *hook_data, void *call_data, void *userdata) { > + pa_card_profile *profile = call_data; > + pa_card *card; > + struct userdata *u = userdata; > + struct entry *entry; > + > + pa_assert(profile); > + pa_assert(u); > + > + card = profile->card; > + > + if (profile->available == PA_AVAILABLE_NO) > + return PA_HOOK_OK; > + > + entry = entry_read(u, card->name); > + if (!entry) > + return PA_HOOK_OK; > + > + if (!pa_streq(profile->name, entry->profile)) > + return PA_HOOK_OK; > + > + pa_log_info("Card %s profile %s became available, activating.", card->name, profile->name); > + pa_card_set_profile(profile->card, profile, true); > + > + return PA_HOOK_OK; > +} > + > static pa_hook_result_t port_offset_change_callback(pa_core *c, pa_device_port *port, struct userdata *u) { > struct entry *entry; > pa_card *card; > @@ -511,6 +542,8 @@ int pa__init(pa_module*m) { > u->card_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) card_put_hook_callback, u); > u->card_profile_changed_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_changed_callback, u); > u->card_profile_added_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_added_callback, u); > + u->profile_available_changed_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED], > + PA_HOOK_NORMAL, profile_available_changed_callback, u); > u->port_offset_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_offset_change_callback, u); > u->hooks_connected = true; > > @@ -551,6 +584,7 @@ void pa__done(pa_module*m) { > pa_hook_slot_free(u->card_put_hook_slot); > pa_hook_slot_free(u->card_profile_changed_hook_slot); > pa_hook_slot_free(u->card_profile_added_hook_slot); > + pa_hook_slot_free(u->profile_available_changed_hook_slot); > pa_hook_slot_free(u->port_offset_hook_slot); > } > > -- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic