Skip to content

Instantly share code, notes, and snippets.

@ousttrue
Created November 29, 2012 22:35
Show Gist options
  • Save ousttrue/4172369 to your computer and use it in GitHub Desktop.
Save ousttrue/4172369 to your computer and use it in GitHub Desktop.
id3v2 character encoding patch for mpd
--- src/tag_id3.c.orig 2012-11-28 09:27:00.009431866 +0900
+++ src/tag_id3.c 2012-11-28 10:16:23.205446028 +0900
@@ -78,38 +78,72 @@
}
/* This will try to convert a string to utf-8,
- */
+*/
static id3_utf8_t *
-import_id3_string(bool is_id3v1, const id3_ucs4_t *ucs4)
+import_id3_string(enum id3_field_textencoding text_encoding, const id3_ucs4_t *ucs4)
{
id3_utf8_t *utf8, *utf8_stripped;
id3_latin1_t *isostr;
const char *encoding;
- /* use encoding field here? */
- if (is_id3v1 &&
- (encoding = config_get_string(CONF_ID3V1_ENCODING, NULL)) != NULL) {
- isostr = id3_ucs4_latin1duplicate(ucs4);
- if (G_UNLIKELY(!isostr)) {
- return NULL;
- }
-
- utf8 = (id3_utf8_t *)
- g_convert_with_fallback((const char*)isostr, -1,
- "utf-8", encoding,
- NULL, NULL, NULL, NULL);
- if (utf8 == NULL) {
- g_debug("Unable to convert %s string to UTF-8: '%s'",
- encoding, isostr);
- g_free(isostr);
- return NULL;
- }
- g_free(isostr);
- } else {
- utf8 = id3_ucs4_utf8duplicate(ucs4);
- if (G_UNLIKELY(!utf8)) {
- return NULL;
- }
+ if(ucs4==NULL){
+ return NULL;
+ }
+
+ /*
+ * check text encoding
+ * refer http://www.id3.org/id3v2.4.0-structure
+ */
+ switch(text_encoding)
+ {
+ case ID3_FIELD_TEXTENCODING_ISO_8859_1: /* ISO-8859-1 */
+ /**
+ * process as none unicode string
+ * include isId3v1(tag)
+ */
+ isostr = id3_ucs4_latin1duplicate(ucs4);
+ if (G_UNLIKELY(!isostr)) {
+ g_debug("fail to id3_ucs4_latin1duplicate\n");
+ return NULL;
+ }
+
+ /* determine text encoding */
+ encoding = config_get_string(CONF_ID3V1_ENCODING, NULL);
+ if(!encoding)
+ encoding="ISO-8859-1";
+
+ /* convert to UTF-8 */
+ {
+ GError *error = NULL;
+ utf8 = (id3_utf8_t *)
+ g_convert_with_fallback((const char*)isostr, -1,
+ "utf-8", encoding,
+ NULL, NULL, NULL, &error);
+
+ if (utf8 == NULL) {
+ g_debug("Unable to convert %s(%d) string to UTF-8: "
+ "'%s'\n", encoding, text_encoding, isostr);
+ g_error_free(error);
+ free(isostr);
+ return NULL;
+ }
+ free(isostr);
+ }
+ break;
+
+ case ID3_FIELD_TEXTENCODING_UTF_16: /* UTF-16 with BOM */
+ case ID3_FIELD_TEXTENCODING_UTF_16BE: /* UTF-16BE withouot BOM */
+ case ID3_FIELD_TEXTENCODING_UTF_8: /* UTF-8 */
+ default:
+ /**
+ * unicode string
+ */
+ utf8=id3_ucs4_utf8duplicate(ucs4);
+ if (utf8 == NULL) {
+ g_debug("fail to id3_ucs4_utf8duplicate\n");
+ return NULL;
+ }
+ break;
}
utf8_stripped = (id3_utf8_t *)g_strdup(g_strstrip((gchar *)utf8));
@@ -127,12 +161,13 @@
*/
static void
tag_id3_import_text_frame(struct tag *dest, struct id3_tag *tag,
- const struct id3_frame *frame,
- enum tag_type type)
+ const struct id3_frame *frame,
+ enum tag_type type)
{
id3_ucs4_t const *ucs4;
id3_utf8_t *utf8;
- union id3_field const *field;
+ union id3_field const *field0;
+ union id3_field const *field1;
unsigned int nstrings, i;
if (frame->nfields != 2)
@@ -140,27 +175,27 @@
/* check the encoding field */
- field = id3_frame_field(frame, 0);
- if (field == NULL || field->type != ID3_FIELD_TYPE_TEXTENCODING)
+ field0 = id3_frame_field(frame, 0);
+ if (field0 == NULL || field0->type != ID3_FIELD_TYPE_TEXTENCODING)
return;
/* process the value(s) */
- field = id3_frame_field(frame, 1);
- if (field == NULL || field->type != ID3_FIELD_TYPE_STRINGLIST)
+ field1 = id3_frame_field(frame, 1);
+ if (field1 == NULL || field1->type != ID3_FIELD_TYPE_STRINGLIST)
return;
/* Get the number of strings available */
- nstrings = id3_field_getnstrings(field);
+ nstrings = id3_field_getnstrings(field1);
for (i = 0; i < nstrings; i++) {
- ucs4 = id3_field_getstrings(field, i);
+ ucs4 = id3_field_getstrings(field1, i);
if (ucs4 == NULL)
continue;
if (type == TAG_GENRE)
ucs4 = id3_genre_name(ucs4);
- utf8 = import_id3_string(tag_is_id3v1(tag), ucs4);
+ utf8 = import_id3_string(id3_field_gettextencoding(field0), ucs4);
if (utf8 == NULL)
continue;
@@ -175,11 +210,11 @@
*/
static void
tag_id3_import_text(struct tag *dest, struct id3_tag *tag, const char *id,
- enum tag_type type)
+ enum tag_type type)
{
const struct id3_frame *frame;
for (unsigned i = 0;
- (frame = id3_tag_findframe(tag, id, i)) != NULL; ++i)
+ (frame = id3_tag_findframe(tag, id, i)) != NULL; ++i)
tag_id3_import_text_frame(dest, tag, frame, type);
}
@@ -194,26 +229,31 @@
*/
static void
tag_id3_import_comment_frame(struct tag *dest, struct id3_tag *tag,
- const struct id3_frame *frame,
- enum tag_type type)
+ const struct id3_frame *frame,
+ enum tag_type type)
{
id3_ucs4_t const *ucs4;
id3_utf8_t *utf8;
- union id3_field const *field;
+ union id3_field const *field0;
+ union id3_field const *field3;
if (frame->nfields != 4)
return;
+ field0 = id3_frame_field(frame, 0);
+ if (field0 == NULL)
+ return;
+
/* for now I only read the 4th field, with the fullstring */
- field = id3_frame_field(frame, 3);
- if (field == NULL)
+ field3 = id3_frame_field(frame, 3);
+ if (field3 == NULL)
return;
- ucs4 = id3_field_getfullstring(field);
+ ucs4 = id3_field_getfullstring(field3);
if (ucs4 == NULL)
return;
- utf8 = import_id3_string(tag_is_id3v1(tag), ucs4);
+ utf8 = import_id3_string(id3_field_gettextencoding(field0), ucs4);
if (utf8 == NULL)
return;
@@ -227,11 +267,11 @@
*/
static void
tag_id3_import_comment(struct tag *dest, struct id3_tag *tag, const char *id,
- enum tag_type type)
+ enum tag_type type)
{
const struct id3_frame *frame;
for (unsigned i = 0;
- (frame = id3_tag_findframe(tag, id, i)) != NULL; ++i)
+ (frame = id3_tag_findframe(tag, id, i)) != NULL; ++i)
tag_id3_import_comment_frame(dest, tag, frame, type);
}
@@ -250,7 +290,7 @@
{ TAG_MUSICBRAINZ_ARTISTID, "MusicBrainz Artist Id" },
{ TAG_MUSICBRAINZ_ALBUMID, "MusicBrainz Album Id" },
{ TAG_MUSICBRAINZ_ALBUMARTISTID,
- "MusicBrainz Album Artist Id" },
+ "MusicBrainz Album Artist Id" },
{ TAG_MUSICBRAINZ_TRACKID, "MusicBrainz Track Id" },
};
@@ -318,7 +358,7 @@
name = id3_field_getlatin1(field);
if (name == NULL ||
- strcmp((const char *)name, "http://musicbrainz.org") != 0)
+ strcmp((const char *)name, "http://musicbrainz.org") != 0)
continue;
field = id3_frame_field(frame, 1);
@@ -330,7 +370,7 @@
continue;
tag_add_item_n(mpd_tag, TAG_MUSICBRAINZ_TRACKID,
- (const char*)value, length);
+ (const char*)value, length);
}
}
@@ -340,11 +380,11 @@
tag_id3_import_text(ret, tag, ID3_FRAME_ARTIST, TAG_ARTIST);
tag_id3_import_text(ret, tag, ID3_FRAME_ALBUM_ARTIST,
- TAG_ALBUM_ARTIST);
+ TAG_ALBUM_ARTIST);
tag_id3_import_text(ret, tag, ID3_FRAME_ARTIST_SORT,
- TAG_ARTIST_SORT);
+ TAG_ARTIST_SORT);
tag_id3_import_text(ret, tag, ID3_FRAME_ALBUM_ARTIST_SORT,
- TAG_ALBUM_ARTIST_SORT);
+ TAG_ALBUM_ARTIST_SORT);
tag_id3_import_text(ret, tag, ID3_FRAME_TITLE, TAG_TITLE);
tag_id3_import_text(ret, tag, ID3_FRAME_ALBUM, TAG_ALBUM);
tag_id3_import_text(ret, tag, ID3_FRAME_TRACK, TAG_TRACK);
@@ -397,7 +437,7 @@
/* It's ok if we get less than we asked for */
query_buffer_size = fill_buffer(query_buffer, ID3_TAG_QUERYSIZE,
- stream, offset, whence);
+ stream, offset, whence);
if (query_buffer_size <= 0) return NULL;
/* Look for a tag header */
@@ -524,7 +564,7 @@
stream = fopen(file, "rb");
if (!stream) {
g_debug("tag_id3_load: Failed to open file: '%s', %s",
- file, strerror(errno));
+ file, strerror(errno));
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment