diff --git a/ChangeLog b/ChangeLog index 444c24f73a..975e2a5b03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2007-03-06 Tim-Philipp Müller + + * gst/id3demux/id3tags.c: (id3demux_id3v2_frames_to_tag_list): + * gst/id3demux/id3tags.h: + * gst/id3demux/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. + 2007-03-06 Jan Schmidt * ext/gconf/gstswitchsink.c: (gst_switch_sink_dispose), diff --git a/common b/common index 9a56e28fc1..b333511364 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 9a56e28fc15440eb6852411321c46312e1d1bb73 +Subproject commit b333511364c0796d395b4235571db2fc9a8c1e4f diff --git a/gst/id3demux/id3tags.c b/gst/id3demux/id3tags.c index 7e354f2a5f..249acd0a4b 100644 --- a/gst/id3demux/id3tags.c +++ b/gst/id3demux/id3tags.c @@ -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; } diff --git a/gst/id3demux/id3tags.h b/gst/id3demux/id3tags.h index c87c871095..85a17cd4c7 100644 --- a/gst/id3demux/id3tags.h +++ b/gst/id3demux/id3tags.h @@ -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 { diff --git a/gst/id3demux/id3v2frames.c b/gst/id3demux/id3v2frames.c index 459a1ff3fc..f02f1241f5 100644 --- a/gst/id3demux/id3v2frames.c +++ b/gst/id3demux/id3v2frames.c @@ -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)