+static pa_bool_t entry_write(struct userdata *u, const char *name, const struct entry *e) {
+ pa_tagstruct *t;
+ pa_datum key, data;
+ pa_bool_t r;
+ uint32_t i;
+ pa_format_info *f;
+ uint8_t n_formats;
+
+ pa_assert(u);
+ pa_assert(name);
+ pa_assert(e);
+
+ n_formats = pa_idxset_size(e->formats);
+ pa_assert(n_formats > 0);
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu8(t, e->version);
+ pa_tagstruct_put_boolean(t, e->volume_valid);
+ pa_tagstruct_put_channel_map(t, &e->channel_map);
+ pa_tagstruct_put_cvolume(t, &e->volume);
+ pa_tagstruct_put_boolean(t, e->muted_valid);
+ pa_tagstruct_put_boolean(t, e->muted);
+ pa_tagstruct_put_boolean(t, e->port_valid);
+ pa_tagstruct_puts(t, e->port);
+ pa_tagstruct_putu8(t, n_formats);
+
+ PA_IDXSET_FOREACH(f, e->formats, i) {
+ pa_tagstruct_put_format_info(t, f);
+ }
+
+ key.data = (char *) name;
+ key.size = strlen(name);
+
+ data.data = (void*)pa_tagstruct_data(t, &data.size);
+
+ r = (pa_database_set(u->database, &key, &data, TRUE) == 0);
+
+ pa_tagstruct_free(t);
+
+ return r;
+}
+
+#ifdef ENABLE_LEGACY_DATABASE_ENTRY_FORMAT
+
+#define LEGACY_ENTRY_VERSION 2
+static struct entry* legacy_entry_read(struct userdata *u, pa_datum *data) {
+ struct legacy_entry {
+ uint8_t version;
+ pa_bool_t muted_valid:1, volume_valid:1, port_valid:1;
+ pa_bool_t muted:1;
+ pa_channel_map channel_map;
+ pa_cvolume volume;
+ char port[PA_NAME_MAX];
+ } PA_GCC_PACKED;
+ struct legacy_entry *le;
+ struct entry *e;
+
+ pa_assert(u);
+ pa_assert(data);
+
+ if (data->size != sizeof(struct legacy_entry)) {
+ pa_log_debug("Size does not match.");
+ return NULL;
+ }
+
+ le = (struct legacy_entry*)data->data;
+
+ if (le->version != LEGACY_ENTRY_VERSION) {
+ pa_log_debug("Version mismatch.");
+ return NULL;
+ }
+
+ if (!memchr(le->port, 0, sizeof(le->port))) {
+ pa_log_warn("Port has missing NUL byte.");
+ return NULL;
+ }
+
+ if (le->volume_valid && !pa_channel_map_valid(&le->channel_map)) {
+ pa_log_warn("Invalid channel map.");
+ return NULL;
+ }
+
+ if (le->volume_valid && (!pa_cvolume_valid(&le->volume) || !pa_cvolume_compatible_with_channel_map(&le->volume, &le->channel_map))) {
+ pa_log_warn("Volume and channel map don't match.");
+ return NULL;
+ }
+
+ e = entry_new(TRUE);
+ e->muted_valid = le->muted_valid;
+ e->volume_valid = le->volume_valid;
+ e->port_valid = le->port_valid;
+ e->muted = le->muted;
+ e->channel_map = le->channel_map;
+ e->volume = le->volume;
+ e->port = pa_xstrdup(le->port);
+ return e;
+}
+#endif
+