From 5795be1f8dc72307c40bdfe6cd09665e90c34bfe Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Sat, 24 Jan 2009 20:07:23 +0100
Subject: tag_id3: added MusicBrainz tag support

Added support for the MusicBrainz TXXX tags, documented on:

  http://musicbrainz.org/doc/MusicBrainzTag
---
 src/tag_id3.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/src/tag_id3.c b/src/tag_id3.c
index 62a14060a..f919111d5 100644
--- a/src/tag_id3.c
+++ b/src/tag_id3.c
@@ -24,6 +24,7 @@
 #include <id3tag.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 
@@ -49,6 +50,23 @@
 #define ID3_FRAME_ALBUM_ARTIST "TPE2"
 #endif
 
+static id3_utf8_t *
+tag_id3_getstring(const struct id3_frame *frame, unsigned i)
+{
+	union id3_field *field;
+	const id3_ucs4_t *ucs4;
+
+	field = id3_frame_field(frame, i);
+	if (field == NULL)
+		return NULL;
+
+	ucs4 = id3_field_getstring(field);
+	if (ucs4 == NULL)
+		return NULL;
+
+	return id3_ucs4_utf8duplicate(ucs4);
+}
+
 /* This will try to convert a string to utf-8,
  */
 static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4, int type)
@@ -205,6 +223,65 @@ getID3Info(struct id3_tag *tag, const char *id, int type, struct tag *mpdTag)
 		g_debug("Unsupported tag type requrested");
 }
 
+/**
+ * Parse a TXXX name, and convert it to a tag_type enum value.
+ * Returns TAG_NUM_OF_ITEM_TYPES if the TXXX name is not understood.
+ */
+static enum tag_type
+tag_id3_parse_txxx_name(const char *name)
+{
+	static const struct {
+		enum tag_type type;
+		const char *name;
+	} musicbrainz_txxx[] = {
+		{ TAG_MUSICBRAINZ_ARTISTID, "MusicBrainz Artist Id" },
+		{ TAG_MUSICBRAINZ_ALBUMID, "MusicBrainz Album Id" },
+		{ TAG_MUSICBRAINZ_ALBUMARTISTID,
+		  "MusicBrainz Album Artist Id" },
+		{ TAG_MUSICBRAINZ_TRACKID, "MusicBrainz Track Id" },
+	};
+
+	for (unsigned i = 0; i < G_N_ELEMENTS(musicbrainz_txxx); ++i)
+		if (strcmp(name, musicbrainz_txxx[i].name) == 0)
+			return musicbrainz_txxx[i].type;
+
+	return TAG_NUM_OF_ITEM_TYPES;
+}
+
+/**
+ * Import all known MusicBrainz tags from TXXX frames.
+ */
+static void
+tag_id3_import_musicbrainz(struct tag *mpd_tag, struct id3_tag *id3_tag)
+{
+	for (unsigned i = 0;; ++i) {
+		const struct id3_frame *frame;
+		id3_utf8_t *name, *value;
+		enum tag_type type;
+
+		frame = id3_tag_findframe(id3_tag, "TXXX", i);
+		if (frame == NULL)
+			break;
+
+		name = tag_id3_getstring(frame, 1);
+		if (name == NULL)
+			continue;
+
+		type = tag_id3_parse_txxx_name((const char*)name);
+		free(name);
+
+		if (type == TAG_NUM_OF_ITEM_TYPES)
+			continue;
+
+		value = tag_id3_getstring(frame, 2);
+		if (value == NULL)
+			continue;
+
+		tag_add_item(mpd_tag, type, (const char*)value);
+		free(value);
+	}
+}
+
 struct tag *tag_id3_import(struct id3_tag * tag)
 {
 	struct tag *ret = tag_new();
@@ -224,6 +301,8 @@ struct tag *tag_id3_import(struct id3_tag * tag)
 	getID3Info(tag, ID3_FRAME_COMMENT, TAG_ITEM_COMMENT, ret);
 	getID3Info(tag, ID3_FRAME_DISC, TAG_ITEM_DISC, ret);
 
+	tag_id3_import_musicbrainz(ret, tag);
+
 	if (tag_is_empty(ret)) {
 		tag_free(ret);
 		ret = NULL;
-- 
cgit v1.2.3