[easytag/wip/core-refactoring] Avoid locale-sensitive field name reading for FLAC
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag/wip/core-refactoring] Avoid locale-sensitive field name reading for FLAC
- Date: Sun, 14 Feb 2016 11:23:01 +0000 (UTC)
commit 845edcd8e03c2d9f1661c3f21f8a286cc8de1977
Author: David King <amigadave amigadave com>
Date: Fri Feb 12 21:21:43 2016 +0000
Avoid locale-sensitive field name reading for FLAC
Avoid calling strncasecmp() when searching for tag field names in Vorbis
comments while reading FLAC files. The same function is called internally by
libFLAC when searching for tags, and it is dependent on the current locale, so
it fails with Turkish and the lower-case 'i' being transformed to the dotted
upper-case version. As Vorbis comment field neames are only permitted to be
ASCII, (with some further restrictions), use g_ascii_strup() to convert them
all to upper-case before comparing them.
As an additional optimization, insert the tag key/value pairs in a hash table
during reading. This avoids the behaviour of searching through all the comments
in the file when loading data for each UI field (as well as a second time, when
populating the list of unsupported fields). Instead, only a single lookup per
tag is required.
https://sourceforge.net/p/flac/bugs/417/
src/tags/flac_tag.c | 770 ++++++++++++++++++++-------------------------------
1 files changed, 306 insertions(+), 464 deletions(-)
---
diff --git a/src/tags/flac_tag.c b/src/tags/flac_tag.c
index 6656912..3906600 100644
--- a/src/tags/flac_tag.c
+++ b/src/tags/flac_tag.c
@@ -98,17 +98,87 @@ set_or_append_field (gchar **field,
}
/*
- * @field: a tag field to search
- * @str: a search term to compare against @field
+ * populate_tag_hash_table:
+ * @vc: a Vorbis comment block from which to read fields
*
- * Call strncasecmp() on @str as well as the string in field, comparing only up
- * to the length of the field.
+ * Add comments from the supplied @vc block to a newly-allocated hash table.
+ * Normalise the field names to upper-case ASCII, taking care to ignore the
+ * current locale. Validate the field values are UTF-8 before inserting them in
+ * the hash table. Add the values as strings in a GSList.
+ *
+ * Returns: (transfer full): a newly-allocated hash table of tags
+ */
+static GHashTable *
+populate_tag_hash_table (const FLAC__StreamMetadata_VorbisComment *vc)
+{
+ GHashTable *ret;
+ guint32 i;
+
+ /* Free the string lists manually, to avoid having to duplicate them each
+ * time that an existing key is inserted. */
+ ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ for (i = 0; i < vc->num_comments; i++)
+ {
+ const FLAC__StreamMetadata_VorbisComment_Entry comment = vc->comments[i];
+ const gchar *separator;
+ gchar *field;
+ gchar *field_up;
+ gchar *value;
+ /* TODO: Use a GPtrArray instead? */
+ GSList *l;
+
+ separator = memchr (comment.entry, '=', comment.length);
+
+ if (!separator)
+ {
+ g_warning ("Field separator not found when reading FLAC tag: %s",
+ vc->comments[i].entry);
+ continue;
+ }
+
+ field = g_strndup ((const gchar *)comment.entry,
+ separator - (const gchar *)comment.entry);
+ field_up = g_ascii_strup (field, -1);
+ g_free (field);
+
+ l = g_hash_table_lookup (ret, field_up);
+
+ /* If the lookup failed, a new list is created. The list takes
+ * ownership of the field value. */
+ value = validate_field_utf8 (separator + 1,
+ comment.length - ((separator + 1)
+ - (const gchar *)comment.entry));
+
+ /* Appending is slower, but much easier here (and the lists should be
+ * short). */
+ l = g_slist_append (l, value);
+
+ g_hash_table_insert (ret, field_up, l);
+ }
+
+ return ret;
+}
+
+/*
+ * values_list_foreach:
+ * @data: (transfer full): the tag value
+ * @user_data: (inout): a tag location to fill
+ *
+ * Called on each element in a GSList of tag values, to set or append the
+ * string to the tag.
*/
-static gint
-field_strncasecmp (FLAC__StreamMetadata_VorbisComment_Entry *field,
- const gchar *str)
+static void
+values_list_foreach (gpointer data,
+ gpointer user_data)
{
- return strncasecmp ((gchar *)field->entry, str, strlen (str));
+ gchar *value = (gchar *)data;
+ gchar **tag = (gchar **)user_data;
+
+ if (!et_str_empty (value))
+ {
+ set_or_append_field (tag, value);
+ }
}
/*
@@ -130,10 +200,7 @@ flac_tag_read_file_tag (GFile *file,
et_flac_read_close_func };
FLAC__Metadata_Iterator *iter;
- gchar *string = NULL;
- guint i;
EtPicture *prev_pic = NULL;
- //gint j = 1;
g_return_val_if_fail (file != NULL && FileTag != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
@@ -181,499 +248,274 @@ flac_tag_read_file_tag (GFile *file,
if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
{
- FLAC__StreamMetadata_VorbisComment *vc;
- FLAC__StreamMetadata_VorbisComment_Entry *field;
- gint field_num;
- guint32 field_len;
- gchar *field_value;
-
- // Get comments from block
- vc = &block->data.vorbis_comment;
-
- /*********
- * Title *
- *********/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_TITLE)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
+ const FLAC__StreamMetadata_VorbisComment *vc;
+ GHashTable *tags;
+ GSList *strings;
+ GHashTableIter tags_iter;
+ gchar *key;
+
+ /* Get comments from block. */
+ vc = &block->data.vorbis_comment;
+ tags = populate_tag_hash_table (vc);
+
+ /* Title */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_TITLE)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->title);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_TITLE);
+ }
- if (field_value)
- {
- field_value++;
+ /* Artist */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_ARTIST)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->artist);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_ARTIST);
+ }
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
+ /* Album artist. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_ALBUM_ARTIST)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->album_artist);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_ALBUM_ARTIST);
+ }
- set_or_append_field (&FileTag->title, field_value);
- }
- }
- }
+ /* Album. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_ALBUM)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->album);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_ALBUM);
+ }
- /**********
- * Artist *
- **********/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_ARTIST)) >= 0)
+ /* Disc number and total discs. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_DISC_TOTAL)))
+ {
+ /* Only take values from the first total discs field. */
+ if (!et_str_empty (strings->data))
{
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
-
- set_or_append_field (&FileTag->artist,
- field_value);
- }
- }
+ FileTag->disc_total = et_disc_number_to_string (atoi (strings->data));
}
- /****************
- * Album Artist *
- ****************/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_ALBUM_ARTIST)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
-
- set_or_append_field (&FileTag->album_artist,
- field_value);
- }
- }
- }
+ g_slist_free_full (strings, g_free);
+ g_hash_table_remove (tags,
+ ET_VORBIS_COMMENT_FIELD_DISC_TOTAL);
+ }
- /*********
- * Album *
- *********/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_ALBUM)) >= 0)
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_DISC_NUMBER)))
+ {
+ /* Only take values from the first disc number field. */
+ if (!et_str_empty (strings->data))
{
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
+ gchar *separator;
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
-
- set_or_append_field (&FileTag->album, field_value);
- }
- }
- }
+ separator = strchr (strings->data, '/');
- /******************************
- * Disc Number and Disc Total *
- ******************************/
- if ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, 0,
ET_VORBIS_COMMENT_FIELD_DISC_TOTAL)) >= 0)
- {
- /* Extract field value. */
- field = &vc->comments[field_num];
- field_value = memchr (field->entry, '=', field->length);
-
- if (field_value)
+ if (separator && !FileTag->disc_total)
{
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
- FileTag->disc_total = et_disc_number_to_string (atoi (field_value));
- g_free (field_value);
- }
+ FileTag->disc_total = et_disc_number_to_string (atoi (separator + 1));
+ *separator = '\0';
}
- /* Discs is also filled below, if not done here. */
- }
-
- if ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, 0,
ET_VORBIS_COMMENT_FIELD_DISC_NUMBER)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
- string = strchr (field_value, '/');
-
- if (string && !FileTag->disc_total)
- {
- FileTag->disc_total = et_disc_number_to_string (atoi (string + 1));
- *string = '\0';
- }
- FileTag->disc_number = et_disc_number_to_string (atoi (field_value));
-
- g_free (field_value);
- }
- }
+ FileTag->disc_number = et_disc_number_to_string (atoi (strings->data));
}
- /********
- * Year *
- ********/
- if ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, 0,
ET_VORBIS_COMMENT_FIELD_DATE)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
- FileTag->year = field_value;
- }
- }
- }
+ g_slist_free_full (strings, g_free);
+ g_hash_table_remove (tags,
+ ET_VORBIS_COMMENT_FIELD_DISC_NUMBER);
+ }
- /*************************
- * Track and Total Track *
- *************************/
- if ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, 0,
ET_VORBIS_COMMENT_FIELD_TRACK_TOTAL)) >= 0)
+ /* Track number and total tracks. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_TRACK_TOTAL)))
+ {
+ /* Only take values from the first total tracks field. */
+ if (!et_str_empty (strings->data))
{
- /* Extract field value */
- field = &vc->comments[field_num];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
- FileTag->track_total = et_track_number_to_string (atoi (field_value));
- g_free (field_value);
- }
- }
- // Below is also filled track_total if not done here
+ FileTag->track_total = et_track_number_to_string (atoi (strings->data));
}
- if ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, 0,
ET_VORBIS_COMMENT_FIELD_TRACK_NUMBER)) >= 0)
+ g_slist_free_full (strings, g_free);
+ g_hash_table_remove (tags,
+ ET_VORBIS_COMMENT_FIELD_TRACK_TOTAL);
+ }
+
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_TRACK_NUMBER)))
+ {
+ /* Only take values from the first track number field. */
+ if (!et_str_empty (strings->data))
{
- /* Extract field value */
- field = &vc->comments[field_num];
- field_value = memchr(field->entry, '=', field->length);
+ gchar *separator;
+
+ separator = strchr (strings->data, '/');
- if (field_value)
+ if (separator && !FileTag->track_total)
{
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
- string = strchr (field_value, '/');
-
- if (string && !FileTag->track_total)
- {
- FileTag->track_total = et_track_number_to_string (atoi (string + 1));
- *string = '\0';
- }
- FileTag->track = et_track_number_to_string (atoi (field_value));
-
- g_free (field_value);
- }
+ FileTag->track_total = et_track_number_to_string (atoi (separator + 1));
+ *separator = '\0';
}
- }
- /*********
- * Genre *
- *********/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_GENRE)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
+ FileTag->track = et_track_number_to_string (atoi (strings->data));
+ }
- if (field_value)
- {
- field_value++;
+ g_slist_free_full (strings, g_free);
+ g_hash_table_remove (tags,
+ ET_VORBIS_COMMENT_FIELD_TRACK_NUMBER);
+ }
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
+ /* Year. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_DATE)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->year);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_DATE);
+ }
- set_or_append_field (&FileTag->genre, field_value);
- }
- }
- }
+ /* Genre. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_GENRE)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->genre);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_GENRE);
+ }
- /***********
- * Comment *
- ***********/
- field_num = 0;
- while ( 1 )
- {
- gint field_num1, field_num2;
-
- // The comment field can take two forms...
- field_num1 = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_DESCRIPTION);
- field_num2 = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_COMMENT);
-
- if (field_num1 >= 0 && field_num2 >= 0)
- // Note : We set field_num to the last "comment" field to avoid to concatenate
- // the DESCRIPTION and COMMENT field if there are both present (EasyTAG writes the
both...)
- if (field_num1 < field_num2)
- field_num = field_num2;
- else
- field_num = field_num1;
- else if (field_num1 >= 0)
- field_num = field_num1;
- else if (field_num2 >= 0)
- field_num = field_num2;
- else
- break;
-
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
+ /* Comment. */
+ {
+ GSList *descs;
+ GSList *comments;
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
+ descs = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_DESCRIPTION);
+ comments = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_COMMENT);
- set_or_append_field (&FileTag->comment,
- field_value);
- }
- }
+ /* Prefer DESCRIPTION, as it is part of the spec. */
+ if (descs && !comments)
+ {
+ g_slist_foreach (descs, values_list_foreach,
+ &FileTag->comment);
}
-
- /************
- * Composer *
- ************/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_COMPOSER)) >= 0)
+ else if (descs && comments)
{
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
-
- set_or_append_field (&FileTag->composer,
- field_value);
- }
- }
+ g_slist_foreach (descs, values_list_foreach,
+ &FileTag->comment);
+ g_slist_foreach (comments, values_list_foreach,
+ &FileTag->comment);
}
-
- /*******************
- * Original artist *
- *******************/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_PERFORMER)) >= 0)
+ else if (comments)
{
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
-
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
-
- set_or_append_field (&FileTag->orig_artist,
- field_value);
- }
- }
+ g_slist_foreach (comments, values_list_foreach,
+ &FileTag->comment);
}
- /*************
- * Copyright *
- *************/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_COPYRIGHT)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
+ g_slist_free (descs);
+ g_slist_free (comments);
+ g_hash_table_remove (tags,
+ ET_VORBIS_COMMENT_FIELD_DESCRIPTION);
+ g_hash_table_remove (tags,
+ ET_VORBIS_COMMENT_FIELD_COMMENT);
+ }
- if (field_value)
- {
- field_value++;
+ /* Composer. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_COMPOSER)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->composer);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_COMPOSER);
+ }
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
+ /* Original artist. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_PERFORMER)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->orig_artist);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_PERFORMER);
+ }
- set_or_append_field (&FileTag->copyright,
- field_value);
- }
- }
- }
+ /* Copyright. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_COPYRIGHT)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->copyright);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_COPYRIGHT);
+ }
- /*******
- * URL *
- *******/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_CONTACT)) >= 0)
- {
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
+ /* URL. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_CONTACT)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->url);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_CONTACT);
+ }
- if (field_value)
- {
- field_value++;
+ /* Encoded by. */
+ if ((strings = g_hash_table_lookup (tags,
+ ET_VORBIS_COMMENT_FIELD_ENCODED_BY)))
+ {
+ g_slist_foreach (strings, values_list_foreach,
+ &FileTag->encoded_by);
+ g_slist_free (strings);
+ g_hash_table_remove (tags, ET_VORBIS_COMMENT_FIELD_ENCODED_BY);
+ }
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
+ /* Save unsupported fields. */
+ g_hash_table_iter_init (&tags_iter, tags);
- set_or_append_field (&FileTag->url, field_value);
- }
- }
- }
+ while (g_hash_table_iter_next (&tags_iter, (gpointer *)&key,
+ (gpointer *)&strings))
+ {
+ GSList *l;
- /**************
- * Encoded by *
- **************/
- field_num = 0;
- while ((field_num = FLAC__metadata_object_vorbiscomment_find_entry_from (block, field_num,
ET_VORBIS_COMMENT_FIELD_ENCODED_BY)) >= 0)
+ for (l = strings; l != NULL; l = g_slist_next (l))
{
- /* Extract field value */
- field = &vc->comments[field_num++];
- field_value = memchr(field->entry, '=', field->length);
-
- if (field_value)
- {
- field_value++;
+ FileTag->other = g_list_prepend (FileTag->other,
+ g_strconcat (key,
+ "=",
+ l->data,
+ NULL));
+ }
- if (!et_str_empty (field_value))
- {
- field_len = field->length - (field_value - (gchar*) field->entry);
- field_value = validate_field_utf8 (field_value,
- field_len);
+ g_slist_free_full (strings, g_free);
+ g_hash_table_iter_remove (&tags_iter);
+ }
- set_or_append_field (&FileTag->encoded_by,
- field_value);
- }
- }
- }
+ if (FileTag->other)
+ {
+ FileTag->other = g_list_reverse (FileTag->other);
+ }
- /***************************
- * Save unsupported fields *
- ***************************/
- for (i=0;i<(guint)vc->num_comments;i++)
- {
- field = &vc->comments[i];
- if (field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_TITLE "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_ARTIST "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_ALBUM_ARTIST "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_ALBUM "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_DISC_NUMBER "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_DISC_TOTAL "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_DATE "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_TRACK_NUMBER "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_TRACK_TOTAL "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_GENRE "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_DESCRIPTION "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_COMMENT "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_COMPOSER "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_PERFORMER "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_COPYRIGHT "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_CONTACT "=") != 0
- && field_strncasecmp (field,
- ET_VORBIS_COMMENT_FIELD_ENCODED_BY "=") != 0)
- {
- //g_print("custom %*s\n", field->length, field->entry);
- FileTag->other = g_list_append(FileTag->other,g_strndup((const gchar *)field->entry,
field->length));
- }
- }
+ /* The hash table should now only contain keys. */
+ g_hash_table_unref (tags);
}
else if (block->type == FLAC__METADATA_TYPE_PICTURE)
{
/* Picture. */
- FLAC__StreamMetadata_Picture *p;
+ const FLAC__StreamMetadata_Picture *p;
GBytes *bytes;
EtPicture *pic;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]