+/*
+ * FLAC__metadata_object_vorbiscomment_replace_comment() is buggy in some
+ * libFLAC versions (see commit e95399c1 in the flac git repository). Hence we
+ * use delete and add as a workaround.
+ */
+static int flac_replace_vorbis_comment(FLAC__StreamMetadata *b,
+ const char *tag, const char* val)
+{
+ FLAC__bool ok;
+ FLAC__StreamMetadata_VorbisComment_Entry entry;
+ int ret;
+
+ PARA_INFO_LOG("replacing %s\n", tag);
+ ret = FLAC__metadata_object_vorbiscomment_remove_entries_matching(
+ b, tag);
+ if (ret < 0)
+ return -E_FLAC_REPLACE_COMMENT;
+ ok = FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(
+ &entry, tag, val? val : "");
+ if (!ok)
+ return -E_FLAC_REPLACE_COMMENT;
+ ok = FLAC__metadata_object_vorbiscomment_append_comment(b, entry,
+ false /* no copy */);
+ if (!ok) {
+ free(entry.entry);
+ return -E_FLAC_REPLACE_COMMENT;
+ }
+ return 1;
+}
+
+static int flac_replace_vorbis_comments(FLAC__Metadata_Chain *chain,
+ FLAC__StreamMetadata *b, struct taginfo *tags)
+{
+ FLAC__bool ok;
+ int ret;
+
+ ret = flac_replace_vorbis_comment(b, "artist", tags->artist);
+ if (ret < 0)
+ return ret;
+ ret = flac_replace_vorbis_comment(b, "title", tags->title);
+ if (ret < 0)
+ return ret;
+ ret = flac_replace_vorbis_comment(b, "album", tags->album);
+ if (ret < 0)
+ return ret;
+ ret = flac_replace_vorbis_comment(b, "year", tags->year);
+ if (ret < 0)
+ return ret;
+ ret = flac_replace_vorbis_comment(b, "comment", tags->comment);
+ if (ret < 0)
+ return ret;
+ /*
+ * Even if padding is disabled, libflac will try to modify the original
+ * file inplace if the metadata size has not changed. This won't work
+ * here though, because the original file is mapped read-only. Since
+ * there is no option to force the use of a temp file we work around
+ * this shortcoming by adding a dummy entry which increases the size of
+ * the meta data. If the entry already exists, we simply remove it.
+ */
+ ok = FLAC__metadata_chain_check_if_tempfile_needed(chain,
+ false /* no padding */);
+ if (!ok) {
+ PARA_INFO_LOG("adding/removing dummy comment\n");
+ ret = FLAC__metadata_object_vorbiscomment_remove_entries_matching(
+ b, "comment2");
+ if (ret < 0)
+ return -E_FLAC_REPLACE_COMMENT;
+ if (ret == 0) { /* nothing was removed */
+ ret = flac_replace_vorbis_comment(b, "comment2",
+ "avoid inplace write");
+ if (ret < 0)
+ return ret;
+ }
+ assert(FLAC__metadata_chain_check_if_tempfile_needed(chain,
+ false /* no padding */));
+ }
+ return 1;
+}
+
+static int flac_init_meta(struct private_flac_afh_data *pfad,
+ FLAC__Metadata_Chain **chainp, FLAC__Metadata_Iterator **iterp)