The card-restore module now saves and restores the volume per port. This change includes a entry version bump. BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=55262 --- src/modules/module-card-restore.c | 68 +++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c index 3b061b6..b7ff7bc 100644 --- a/src/modules/module-card-restore.c +++ b/src/modules/module-card-restore.c @@ -67,16 +67,18 @@ struct userdata { pa_hook_slot *card_profile_hook_slot; pa_hook_slot *port_new_hook_slot; pa_hook_slot *port_offset_hook_slot; + pa_hook_slot *port_volume_hook_slot; pa_time_event *save_time_event; pa_database *database; bool hooks_connected; }; -#define ENTRY_VERSION 2 +#define ENTRY_VERSION 3 struct port_info { char *name; int64_t offset; + pa_cvolume volume; }; struct entry { @@ -121,6 +123,7 @@ static struct port_info *port_info_new(pa_device_port *port) { p_info = pa_xnew(struct port_info, 1); p_info->name = pa_xstrdup(port->name); p_info->offset = port->latency_offset; + p_info->volume = port->volume; } else p_info = pa_xnew0(struct port_info, 1); @@ -134,6 +137,7 @@ static void port_info_update(struct port_info *p_info, pa_device_port *port) { pa_xfree(p_info->name); p_info->name = pa_xstrdup(port->name); p_info->offset = port->latency_offset; + p_info->volume = port->volume; } static void port_info_free(struct port_info *p_info) { @@ -185,7 +189,10 @@ static bool entrys_equal(struct entry *a, struct entry *b) { PA_HASHMAP_FOREACH(Ap_info, a->ports, state) { if ((Bp_info = pa_hashmap_get(b->ports, Ap_info->name))) { - if (Ap_info->offset != Bp_info->offset) + if (Ap_info->offset != Bp_info->offset || + !pa_cvolume_valid(&Ap_info->volume) || + !pa_cvolume_valid(&Bp_info->volume) || + !pa_cvolume_equal(&Ap_info->volume, &Bp_info->volume)) return false; } else return false; @@ -213,6 +220,7 @@ static pa_bool_t entry_write(struct userdata *u, const char *name, const struct PA_HASHMAP_FOREACH(p_info, e->ports, state) { pa_tagstruct_puts(t, p_info->name); pa_tagstruct_puts64(t, p_info->offset); + pa_tagstruct_put_cvolume(t, &p_info->volume); } key.data = (char *) name; @@ -300,22 +308,26 @@ static struct entry* entry_read(struct userdata *u, const char *name) { uint32_t port_count = 0; const char *port_name = NULL; int64_t port_offset = 0; + pa_cvolume port_volume; struct port_info *p_info; unsigned i; if (pa_tagstruct_getu32(t, &port_count) < 0) goto fail; + pa_cvolume_init(&port_volume); for (i = 0; i < port_count; i++) { if (pa_tagstruct_gets(t, &port_name) < 0 || !port_name || pa_hashmap_get(e->ports, port_name) || - pa_tagstruct_gets64(t, &port_offset) < 0) + pa_tagstruct_gets64(t, &port_offset) < 0 || + (e->version >= 3 && pa_tagstruct_get_cvolume(t, &port_volume) < 0)) goto fail; p_info = port_info_new(NULL); p_info->name = pa_xstrdup(port_name); p_info->offset = port_offset; + p_info->volume = port_volume; pa_assert_se(pa_hashmap_put(e->ports, p_info->name, p_info) >= 0); } @@ -358,9 +370,9 @@ static void show_full_info(pa_card *card) { pa_assert(card); if (card->save_profile) - pa_log_info("Storing profile and port latency offsets for card %s.", card->name); + pa_log_info("Storing profile, port volumes and latency offsets for card %s.", card->name); else - pa_log_info("Storing port latency offsets for card %s.", card->name); + pa_log_info("Storing port volumes and latency offsets for card %s.", card->name); } static pa_hook_result_t card_put_hook_callback(pa_core *c, pa_card *card, struct userdata *u) { @@ -475,6 +487,37 @@ static pa_hook_result_t port_offset_change_callback(pa_core *c, pa_device_port * return PA_HOOK_OK; } +static pa_hook_result_t port_volume_change_callback(pa_core *c, pa_device_port *port, struct userdata *u) { + struct entry *entry; + pa_card *card; + + pa_assert(port); + card = port->card; + + if ((entry = entry_read(u, card->name))) { + struct port_info *p_info; + + if ((p_info = pa_hashmap_get(entry->ports, port->name))) + p_info->volume = port->volume; + else { + p_info = port_info_new(port); + pa_assert_se(pa_hashmap_put(entry->ports, p_info->name, p_info) >= 0); + } + + pa_log_info("Storing volumes for port %s on card %s.", port->name, card->name); + + } else { + entry_from_card(card); + show_full_info(card); + } + + if (entry_write(u, card->name, entry)) + trigger_save(u); + + entry_free(entry); + return PA_HOOK_OK; +} + static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new_data, struct userdata *u) { struct entry *e; void *state; @@ -496,14 +539,19 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new 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 */ + /* Always restore the latency offsets and volumes because their + * initial values are always 0 and PA_VOLUME_INVALID */ - pa_log_info("Restoring port latency offsets for card %s.", new_data->name); + pa_log_info("Restoring port volumes and latency offsets for card %s.", new_data->name); PA_HASHMAP_FOREACH(p_info, e->ports, state) - if ((p = pa_hashmap_get(new_data->ports, p_info->name))) + if ((p = pa_hashmap_get(new_data->ports, p_info->name))) { + char buf[PA_CVOLUME_SNPRINT_MAX]; + p->latency_offset = p_info->offset; + p->volume = p_info->volume; + pa_log_info("Restored volumes for port: %s - %s", p->name, pa_cvolume_snprint(buf, PA_CVOLUME_SNPRINT_MAX, &p_info->volume)); + } entry_free(e); @@ -531,6 +579,7 @@ int pa__init(pa_module*m) { u->card_profile_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_change_callback, u); u->port_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_PORT_ADDED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_port_add_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->port_volume_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_PORT_VOLUME_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_volume_change_callback, u); u->hooks_connected = true; if (!(fname = pa_state_path("card-database", TRUE))) @@ -571,6 +620,7 @@ void pa__done(pa_module*m) { pa_hook_slot_free(u->card_profile_hook_slot); pa_hook_slot_free(u->port_new_hook_slot); pa_hook_slot_free(u->port_offset_hook_slot); + pa_hook_slot_free(u->port_volume_hook_slot); } if (u->save_time_event) -- 1.8.2