+ int fd = *(int *)user_data;
+ return lseek(fd, pos, SEEK_SET);
+}
+
+static uint32_t aac_afh_meta_write_cb(void *user_data, void *dest, uint32_t want)
+{
+ int fd = *(int *)user_data;
+ return write(fd, dest, want);
+}
+
+static uint32_t aac_afh_meta_truncate_cb(void *user_data)
+{
+ int fd = *(int *)user_data;
+ off_t offset = lseek(fd, 0, SEEK_CUR);
+ return ftruncate(fd, offset);
+}
+
+static void replace_tag(mp4ff_tag_t *tag, const char *new_val, bool *found)
+{
+ free(tag->value);
+ tag->value = para_strdup(new_val);
+ *found = true;
+}
+
+static void add_tag(mp4ff_metadata_t *md, const char *item, const char *value)
+{
+ md->tags[md->count].item = para_strdup(item);
+ md->tags[md->count].value = para_strdup(value);
+ md->count++;
+}
+
+static int aac_afh_rewrite_tags(const char *map, size_t mapsize,
+ struct taginfo *tags, int fd, __a_unused const char *filename)
+{
+ int ret, i;
+ int32_t rv;
+ mp4ff_metadata_t metadata;
+ mp4ff_t *mp4ff;
+ mp4ff_callback_t cb = {
+ .read = aac_afh_meta_read_cb,
+ .seek = aac_afh_meta_seek_cb,
+ .write = aac_afh_meta_write_cb,
+ .truncate = aac_afh_meta_truncate_cb,
+ .user_data = &fd
+ };
+ bool found_artist = false, found_title = false, found_album = false,
+ found_year = false, found_comment = false;
+
+ ret = write_all(fd, map, mapsize);
+ if (ret < 0)
+ return ret;
+ lseek(fd, 0, SEEK_SET);
+
+ mp4ff = mp4ff_open_read_metaonly(&cb);
+ if (!mp4ff)
+ return -E_MP4FF_OPEN;
+
+ ret = -E_MP4FF_META_READ;
+ rv = mp4ff_meta_get_num_items(mp4ff);
+ if (rv < 0)
+ goto close;
+ metadata.count = rv;
+ PARA_NOTICE_LOG("%d metadata item(s) found\n", rv);
+
+ metadata.tags = para_malloc((metadata.count + 5) * sizeof(mp4ff_tag_t));
+ for (i = 0; i < metadata.count; i++) {
+ mp4ff_tag_t *tag = metadata.tags + i;
+
+ ret = -E_MP4FF_META_READ;
+ if (mp4ff_meta_get_by_index(mp4ff, i,
+ &tag->item, &tag->value) < 0)
+ goto free_tags;
+ PARA_INFO_LOG("found: %s: %s\n", tag->item, tag->value);
+ if (!strcmp(tag->item, "artist"))
+ replace_tag(tag, tags->artist, &found_artist);
+ else if (!strcmp(tag->item, "title"))
+ replace_tag(tag, tags->title, &found_title);
+ else if (!strcmp(tag->item, "album"))
+ replace_tag(tag, tags->album, &found_album);
+ else if (!strcmp(tag->item, "date"))
+ replace_tag(tag, tags->year, &found_year);
+ else if (!strcmp(tag->item, "comment"))
+ replace_tag(tag, tags->comment, &found_comment);