attribute.c: Clear attribute bits already at remove time.
authorAndre Noll <maan@systemlinux.org>
Sat, 29 Sep 2007 12:00:14 +0000 (14:00 +0200)
committerAndre Noll <maan@systemlinux.org>
Sat, 29 Sep 2007 12:00:14 +0000 (14:00 +0200)
If an attribute gets removed, the old code deferred clearing the
corresponding attribute bit in the afsi of all audio files until
that bit got reclaimed by add_att.  This is problematic because of
the new no_attribute_set mood method.

So clear the bit already in the rmatt callback.

attribute.c

index b8d4a59..694a962 100644 (file)
@@ -296,7 +296,7 @@ static int com_addatt_callback(const struct osl_object *query,
                __a_unused struct osl_object *result)
 {
        char *p = query->data;
-       uint64_t atts_added = 0;
+       unsigned atts_added = 0;
        int ret;
 
        while (p < (char *)query->data + query->size) {
@@ -330,17 +330,13 @@ static int com_addatt_callback(const struct osl_object *query,
                if (ret < 0)
                        return ret;
                greatest_att_bitnum = PARA_MAX(greatest_att_bitnum, bitnum);
-               atts_added |= 1 << bitnum;
+               atts_added++;
                p += strlen(p) + 1;
        }
        if (!atts_added)
                return 1;
-       atts_added = ~atts_added;
-       ret = audio_file_loop(&atts_added, logical_and_attribute);
-       if (ret < 0)
-               return ret;
        find_greatest_att_bitnum();
-       return reload_current_mood(); /* FIXME: mood_reload() returns an error */
+       return reload_current_mood(); /* FIXME: returns an error */
 }
 
 int com_addatt(__a_unused int fd, int argc, char * const * const argv)
@@ -353,6 +349,7 @@ int com_addatt(__a_unused int fd, int argc, char * const * const argv)
 struct remove_attribute_action_data {
        struct para_buffer pb;
        int num_removed;
+       uint64_t mask_of_removed_atts;
 };
 
 static int remove_attribute(struct osl_table *table, struct osl_row *row,
@@ -360,12 +357,20 @@ static int remove_attribute(struct osl_table *table, struct osl_row *row,
 {
        struct remove_attribute_action_data *raad = data;
        int ret = osl_del_row(table, row);
-       if (ret < 0)
+       unsigned char bitnum;
+
+       if (ret < 0) {
+               para_printf(&raad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
+               return 1;
+       }
+       ret = get_attribute_bitnum_by_name(name, &bitnum);
+       if (ret < 0) {
                para_printf(&raad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
-       else {
-               para_printf(&raad->pb, "removed %s\n", name);
-               raad->num_removed++;
+               return 1;
        }
+       para_printf(&raad->pb, "removed %s\n", name);
+       raad->num_removed++;
+       raad->mask_of_removed_atts |= (1 << bitnum);
        return 1;
 }
 
@@ -386,6 +391,10 @@ static int com_rmatt_callback(const struct osl_object *query,
        if (ret < 0)
                para_printf(&raad.pb, "%s\n", PARA_STRERROR(-ret));
        if (raad.num_removed) {
+               uint64_t and_mask = ~raad.mask_of_removed_atts;
+               ret = audio_file_loop(&and_mask, logical_and_attribute);
+               if (ret < 0)
+                       para_printf(&raad.pb, "%s\n", PARA_STRERROR(-ret));
                find_greatest_att_bitnum();
                ret = reload_current_mood();
                if (ret < 0)