[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