tag: id3v2: Do not convert obsolete TDA/TDAT frames to TDRC frames, otherwise the...
authorTim-Philipp Müller <tim@centricular.net>
Tue, 6 Mar 2007 18:16:49 +0000 (18:16 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Sun, 14 Aug 2011 23:10:30 +0000 (00:10 +0100)
Original commit message from CVS:
* gst-libs/gst/tag/id3v2.c: (id3demux_id3v2_frames_to_tag_list):
* gst-libs/gst/tag/id3v2.h:
* gst-libs/gst/tag/id3v2frames.c: (id3demux_id3v2_parse_frame),
(parse_obsolete_tdat_frame):
Do not convert obsolete TDA/TDAT frames to TDRC frames, otherwise
the four-digit number will be interpreted as a year, whereas it is
month and day in DDMM format. Instead, parse TDAT frames and fix up
the date in the GST_TAG_DATE tag later if we also extracted a year.
Fixes #407349.

gst-libs/gst/tag/id3v2.c
gst-libs/gst/tag/id3v2.h
gst-libs/gst/tag/id3v2frames.c

index 7e354f2..249acd0 100644 (file)
@@ -242,7 +242,6 @@ const struct ID3v2FrameIDConvert
 } frame_id_conversions[] = {
   /* 2.3.x frames */
   {
-  "TDAT", "TDRC"}, {
   "TORY", "TDOR"}, {
   "TYER", "TDRC"},
       /* 2.2.x frames */
@@ -266,7 +265,7 @@ const struct ID3v2FrameIDConvert
   "TCM", "TCOM"}, {
   "TCO", "TCON"}, {
   "TCR", "TCOP"}, {
-  "TDA", "TDRC"}, {
+  "TDA", "TDAT"}, {             /* obsolete, but we need to parse it anyway */
   "TDY", "TDLY"}, {
   "TEN", "TENC"}, {
   "TFT", "TFLT"}, {
@@ -500,5 +499,18 @@ id3demux_id3v2_frames_to_tag_list (ID3TagsWorking * work, guint size)
     return ID3TAGS_BROKEN_TAG;
   }
 
+  /* Set day/month now if they were in a separate (obsolete) TDAT frame */
+  if (work->pending_day != 0 && work->pending_month != 0) {
+    GDate *date = NULL;
+
+    if (gst_tag_list_get_date (work->tags, GST_TAG_DATE, &date)) {
+      g_date_set_day (date, work->pending_day);
+      g_date_set_month (date, work->pending_month);
+      gst_tag_list_add (work->tags, GST_TAG_MERGE_REPLACE, GST_TAG_DATE,
+          date, NULL);
+      g_date_free (date);
+    }
+  }
+
   return ID3TAGS_READ_TAG;
 }
index c87c871..85a17cd 100644 (file)
@@ -78,6 +78,10 @@ typedef struct {
   
   /* Previous genre string, for simple duplicate removal */
   gchar *prev_genre;
+
+  /* To collect day/month from obsolete TDAT frame if it exists */
+  guint pending_month;
+  guint pending_day;
 } ID3TagsWorking;
 
 enum {
index 459a1ff..f02f124 100644 (file)
@@ -44,6 +44,7 @@ static gchar *parse_user_text_identification_frame (ID3TagsWorking * work,
 static gchar *parse_unique_file_identifier (ID3TagsWorking * work,
     const gchar ** tag_name);
 static gboolean parse_relative_volume_adjustment_two (ID3TagsWorking * work);
+static void parse_obsolete_tdat_frame (ID3TagsWorking * work);
 static gboolean id3v2_tag_to_taglist (ID3TagsWorking * work,
     const gchar * tag_name, const gchar * tag_str);
 /* Parse a single string into an array of gchar* */
@@ -100,6 +101,7 @@ id3demux_id3v2_parse_frame (ID3TagsWorking * work)
   if (tag_name == NULL &&
       strncmp (work->frame_id, "RVA2", 4) != 0 &&
       strncmp (work->frame_id, "TXXX", 4) != 0 &&
+      strncmp (work->frame_id, "TDAT", 4) != 0 &&
       strncmp (work->frame_id, "UFID", 4) != 0) {
     return FALSE;
   }
@@ -152,12 +154,15 @@ id3demux_id3v2_parse_frame (ID3TagsWorking * work)
   }
 
   if (work->frame_id[0] == 'T') {
-    if (strcmp (work->frame_id, "TXXX") != 0) {
-      /* Text identification frame */
-      tag_fields = parse_text_identification_frame (work);
-    } else {
+    if (strcmp (work->frame_id, "TDAT") == 0) {
+      parse_obsolete_tdat_frame (work);
+      result = TRUE;
+    } else if (strcmp (work->frame_id, "TXXX") == 0) {
       /* Handle user text frame */
       tag_str = parse_user_text_identification_frame (work, &tag_name);
+    } else {
+      /* Text identification frame */
+      tag_fields = parse_text_identification_frame (work);
     }
   } else if (!strcmp (work->frame_id, "COMM")) {
     /* Comment */
@@ -635,6 +640,23 @@ parse_relative_volume_adjustment_two (ID3TagsWorking * work)
   return (gain_tag_name != NULL || peak_tag_name != NULL);
 }
 
+static void
+parse_obsolete_tdat_frame (ID3TagsWorking * work)
+{
+  if (work->parse_size >= 5 &&
+      work->parse_data[0] == ID3V2_ENCODING_ISO8859 &&
+      g_ascii_isdigit (work->parse_data[1]) &&
+      g_ascii_isdigit (work->parse_data[2]) &&
+      g_ascii_isdigit (work->parse_data[3]) &&
+      g_ascii_isdigit (work->parse_data[4])) {
+    work->pending_day = (10 * g_ascii_digit_value (work->parse_data[1])) +
+        g_ascii_digit_value (work->parse_data[2]);
+    work->pending_month = (10 * g_ascii_digit_value (work->parse_data[3])) +
+        g_ascii_digit_value (work->parse_data[4]);
+    GST_LOG ("date (dd/mm) %02u/%02u", work->pending_day, work->pending_month);
+  }
+}
+
 static gboolean
 id3v2_tag_to_taglist (ID3TagsWorking * work, const gchar * tag_name,
     const gchar * tag_str)