From: "poljar (Damir Jeli?)" <poljarinho@xxxxxxxxx> module-card-restore now saves the latency offsets. This change includes a entry version bump. The entry now consists of a port count and a port name and offset for every port that belongs to the relevant card. --- src/modules/module-card-restore.c | 122 ++++++++++++++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 13 deletions(-) diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c index 1079a72..b21aaae 100644 --- a/src/modules/module-card-restore.c +++ b/src/modules/module-card-restore.c @@ -68,11 +68,18 @@ struct userdata { pa_database *database; }; -#define ENTRY_VERSION 1 +#define ENTRY_VERSION 2 + +struct port_info { + char *name; + int64_t offset; +}; struct entry { uint8_t version; char *profile; + uint32_t port_count; + struct port_info *port_info; }; static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { @@ -107,6 +114,16 @@ static void entry_free(struct entry* e) { pa_assert(e); pa_xfree(e->profile); + + if (e->port_count > 0) { + unsigned i; + for (i = 0; i < e->port_count; i++) + pa_xfree(e->port_info[i].name); + } + + if (e->port_info) + pa_xfree(e->port_info); + pa_xfree(e); } @@ -114,6 +131,7 @@ static pa_bool_t entry_write(struct userdata *u, const char *name, const struct pa_tagstruct *t; pa_datum key, data; pa_bool_t r; + unsigned i; pa_assert(u); pa_assert(name); @@ -122,6 +140,12 @@ static pa_bool_t entry_write(struct userdata *u, const char *name, const struct t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu8(t, e->version); pa_tagstruct_puts(t, e->profile); + pa_tagstruct_putu32(t, e->port_count); + + for (i = 0; i < e->port_count; i++) { + pa_tagstruct_puts(t, e->port_info[i].name); + pa_tagstruct_puts64(t, e->port_info[i].offset); + } key.data = (char *) name; key.size = strlen(name); @@ -201,6 +225,30 @@ static struct entry* entry_read(struct userdata *u, const char *name) { e->profile = pa_xstrdup(profile); + if (e->version >= 2) { + const char *port_name = NULL; + int64_t port_offset = 0; + unsigned i; + + if (pa_tagstruct_getu32(t, &e->port_count) < 0) + goto fail; + + if (e->port_count > 0) { + e->port_info = pa_xnew(struct port_info, e->port_count); + + for (i = 0; i < e->port_count; i++) { + if (pa_tagstruct_gets(t, &port_name) < 0 || + pa_tagstruct_gets64(t, &port_offset) < 0) { + e->port_count = i; + goto fail; + } + + e->port_info[i].name = pa_xstrdup(port_name); + e->port_info[i].offset = port_offset; + } + } + } + if (!pa_tagstruct_eof(t)) goto fail; @@ -238,6 +286,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 struct userdata *u = userdata; struct entry *entry, *old; pa_card *card; + unsigned i = 0; pa_assert(c); pa_assert(u); @@ -249,15 +298,44 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(card = pa_idxset_get_by_index(c->cards, idx))) return; + entry = entry_new(); + if (!card->save_profile) - return; + entry->profile = pa_xstrdup(""); + else + entry->profile = pa_xstrdup(card->active_profile->name); - entry = entry_new(); - entry->profile = pa_xstrdup(card->active_profile->name); + entry->port_count = pa_hashmap_size(card->ports); + + if (entry->port_count > 0) { + void *state; + pa_device_port *p; + + entry->port_info = pa_xnew(struct port_info, entry->port_count); + + PA_HASHMAP_FOREACH(p, card->ports, state) { + entry->port_info[i].name = pa_xstrdup(p->name); + entry->port_info[i].offset = p->latency_offset; + i++; + } + } if ((old = entry_read(u, card->name))) { + bool dirty = false; - if (pa_streq(old->profile, entry->profile)) { + if (!pa_streq(old->profile, entry->profile) && + card->save_profile) + dirty = true; + + else + for (i = 0; i < old->port_count; i++) + if (!pa_streq(old->port_info[i].name, entry->port_info[i].name) || + old->port_info[i].offset != entry->port_info[i].offset) { + dirty = true; + break; + } + + if (!dirty) { entry_free(old); entry_free(entry); return; @@ -266,7 +344,10 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 entry_free(old); } - pa_log_info("Storing profile for card %s.", card->name); + if (!card->save_profile) + pa_log_info("Storing profile and port latency offsets for card %s.", card->name); + else + pa_log_info("Port latency offsets for card %s.", card->name); if (entry_write(u, card->name, entry)) trigger_save(u); @@ -279,14 +360,29 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new pa_assert(new_data); - if ((e = entry_read(u, new_data->name)) && e->profile[0]) { + if ((e = entry_read(u, new_data->name))) { + unsigned i; + pa_device_port *p; + + if (e->profile[0]) { + if (!new_data->active_profile) { + pa_log_info("Restoring profile for card %s.", new_data->name); + pa_card_new_data_set_profile(new_data, e->profile); + new_data->save_profile = TRUE; - if (!new_data->active_profile) { - pa_log_info("Restoring profile for card %s.", new_data->name); - pa_card_new_data_set_profile(new_data, e->profile); - new_data->save_profile = TRUE; - } else - pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name); + } else + pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name); + } + + /* Always restore the latency offsets because their + * initial value is always 0 */ + + pa_log_info("Restoring port latency offsets for card %s.", new_data->name); + for (i = 0; i < e->port_count; i++) { + p = pa_hashmap_get(new_data->ports, e->port_info[i].name); + if (p) + p->latency_offset = e->port_info[i].offset; + } entry_free(e); } -- 1.7.11.1