[pulseaudio-discuss] [PATCH 2/2] card-restore: Add the ability to save and restore the latency offset.
Tanu Kaskinen
tanuk at iki.fi
Sat Jun 30 03:47:58 PDT 2012
On Thu, 2012-06-28 at 13:17 +0200, poljar (Damir Jelić) wrote:
> From: "poljar (Damir Jelić)" <poljarinho at gmail.com>
>
> 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 | 90 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 88 insertions(+), 2 deletions(-)
>
> diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
> index e90e610..55589c8 100644
> --- a/src/modules/module-card-restore.c
> +++ b/src/modules/module-card-restore.c
> @@ -68,11 +68,14 @@ struct userdata {
> pa_database *database;
> };
>
> -#define ENTRY_VERSION 1
> +#define ENTRY_VERSION 2
>
> struct entry {
> uint8_t version;
> char *profile;
> + uint8_t port_count;
I'd go with uint32_t. It's unlikely that 8 bits wouldn't be enough, but
I think it's still somewhat possible that some card would some day have
more than 255 ports.
> + char **port_names;
> + int64_t *port_offsets;
I'd prefer one array of structs containing the port info, instead of
multiple arrays where each item contains one field of the port info.
> };
>
> static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
> @@ -99,14 +102,31 @@ static void trigger_save(struct userdata *u) {
>
> static struct entry* entry_new(void) {
> struct entry *r = pa_xnew0(struct entry, 1);
> +
> r->version = ENTRY_VERSION;
> + r->port_count = 0;
> + r->port_names = NULL;
> + r->port_offsets = NULL;
> +
These changes can be dropped, because the entry is already zeroed.
> return r;
> }
>
> static void entry_free(struct entry* e) {
> + int i;
I'd prefer unsigned for variables that are inherently unsigned in
nature, like array indexes. This is such a minor thing that if you are
at all against the change, don't do it.
> +
> pa_assert(e);
>
> pa_xfree(e->profile);
> +
> + if (e->port_count > 0)
> + for (i = 0; i < e->port_count; i++)
> + pa_xfree(e->port_names[i]);
> +
> + if (e->port_names)
> + pa_xfree(e->port_names);
> + if (e->port_offsets)
> + pa_xfree(e->port_offsets);
> +
> pa_xfree(e);
> }
>
> @@ -114,6 +134,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;
> + int i;
"int" -> "unsigned"
>
> pa_assert(u);
> pa_assert(name);
> @@ -122,6 +143,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_putu8(t, e->port_count);
> +
> + for (i = 0; i < e->port_count; i++) {
> + pa_tagstruct_puts(t, e->port_names[i]);
> + pa_tagstruct_puts64(t, e->port_offsets[i]);
> + }
>
> key.data = (char *) name;
> key.size = strlen(name);
> @@ -177,6 +204,8 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
> struct entry *e = NULL;
> pa_tagstruct *t = NULL;
> const char* profile;
> + const char *port_name = NULL;
> + int64_t port_offset = 0;
These could be declared later, because they are not needed at this
scope.
>
> pa_assert(u);
> pa_assert(name);
> @@ -201,6 +230,28 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
>
> e->profile = pa_xstrdup(profile);
>
> + if (e->version >= 2) {
> + int i;
"int" -> "unsigned"
> +
> + pa_tagstruct_getu8(t, &e->port_count);
The return value must be checked.
> +
> + if (e->port_count > 0) {
> + e->port_names = pa_xnew(char*, e->port_count);
> + e->port_offsets = pa_xnew(int64_t, 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_names[i] = pa_xstrdup(port_name);
> + e->port_offsets[i] = port_offset;
> + }
> + }
> + }
> +
> if (!pa_tagstruct_eof(t))
> goto fail;
>
> @@ -237,6 +288,10 @@ fail:
> static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
> struct userdata *u = userdata;
> struct entry *entry, *old;
> + void *state;
Can be declared later.
> + int i = 0;
"int" -> "unsigned"
> + pa_bool_t dirty = false;
> + pa_device_port *p;
These can be declared later. Also, you should use "FALSE" instead of
"false". (We could start a discussion about deprecating pa_bool_t and
starting to use plain bool, though, since we are using other C99
features anyway, so it shouldn't be a compatibility issue. I'll do
that.)
> pa_card *card;
>
> pa_assert(c);
> @@ -255,9 +310,29 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
> entry = entry_new();
> entry->profile = pa_xstrdup(card->active_profile ? card->active_profile->name : "");
Before these lines there's this:
if (!card->save_profile)
return;
You need to do something about that. If save_profile is FALSE, you will
still want to update the database if the latency offsets change.
>
> + entry->port_count = pa_hashmap_size(card->ports);
> + if (entry->port_count > 0) {
> + entry->port_names = pa_xnew(char*, entry->port_count);
> + entry->port_offsets = pa_xnew(int64_t, entry->port_count);
> +
> + PA_HASHMAP_FOREACH(p, card->ports, state) {
> + entry->port_names[i] = pa_xstrdup(p->name);
> + entry->port_offsets[i] = p->latency_offset;
> + i++;
> + }
> + }
> +
> if ((old = entry_read(u, card->name))) {
>
> - if (pa_streq(old->profile, entry->profile)) {
> + if (pa_streq(old->profile, entry->profile) &&
> + old->port_count == entry->port_count)
> + for (i = 0; i < old->port_count; i++) {
> + if (!pa_streq(old->port_names[i], entry->port_names[i]) ||
> + old->port_offsets[i] != entry->port_offsets[i])
> + dirty = true;
> + }
This isn't right. dirty must be set to TRUE if the profile has changed
(and save_profile is TRUE) *or* if the offsets have changed. This code
doesn't do that.
> +
> + if(!dirty) {
Missing space after "if".
> entry_free(old);
> entry_free(entry);
> return;
Later in this function there's this:
pa_log_info("Storing profile for card %s.", card->name);
That's not accurate anymore after your changes.
> @@ -276,6 +351,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
>
> static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new_data, struct userdata *u) {
> struct entry *e;
> + int i;
> + pa_device_port *p;
Can be declared later.
>
> pa_assert(new_data);
>
> @@ -285,9 +362,18 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
> 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);
>
> + /* Always restore the latency offsets because their
> + * initial value is always 0 */
The if condition is:
if ((e = entry_read(u, new_data->name)) && e->profile[0]) {
If the e->profile[0] check fails, then the offsets won't get restored.
> + for (i = 0; i < e->port_count; i++) {
> + p = pa_hashmap_get(new_data->ports, e->port_names[i]);
> + if(p)
Missing space after "if".
--
Tanu
More information about the pulseaudio-discuss
mailing list