[pulseaudio-discuss] [PATCH] card-restore: Fix profile restoring with bluetooth

Tanu Kaskinen tanu.kaskinen at linux.intel.com
Tue Dec 16 03:14:41 PST 2014

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
+    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->profile_available_changed_hook_slot);

More information about the pulseaudio-discuss mailing list