From b85a0d0710761747946793a4730a10f6b1c85c7c Mon Sep 17 00:00:00 2001 From: Scott Wheeler Date: Thu, 25 Sep 2014 22:19:09 +0200 Subject: [PATCH] Rebuild TRDC from v2.3 fields This fixes an issue that was reported to me via email with the recording date being thrown away from v2.3 tags. --- taglib/mpeg/id3v2/id3v2framefactory.cpp | 22 ++++++++++++++++++++++ taglib/mpeg/id3v2/id3v2framefactory.h | 8 ++++++++ taglib/mpeg/id3v2/id3v2tag.cpp | 4 +++- tests/test_id3v2.cpp | 2 +- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index ee92e4bd..8a4628aa 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -278,6 +278,28 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe return new UnknownFrame(data, header); } +void FrameFactory::rebuildAggregateFrames(Tag *tag) const +{ + if(tag->header()->majorVersion() < 4 && + tag->frameList("TDRC").size() == 1 && + tag->frameList("TDAT").size() == 1) + { + TextIdentificationFrame *trdc = + static_cast(tag->frameList("TDRC").front()); + UnknownFrame *tdat = + static_cast(tag->frameList("TDAT").front()); + + if(trdc->fieldList().size() == 1 && + trdc->fieldList().front().size() == 4 && + tdat->data().size() >= 5) + { + String date(tdat->data().mid(1), String::Type(tdat->data()[0])); + if(date.length() == 4) + trdc->setText(trdc->toString() + '-' + date.substr(2, 2) + '-' + date.substr(0, 2)); + } + } +} + String::Type FrameFactory::defaultTextEncoding() const { return d->defaultEncoding; diff --git a/taglib/mpeg/id3v2/id3v2framefactory.h b/taglib/mpeg/id3v2/id3v2framefactory.h index 94fb144f..8f2f6089 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.h +++ b/taglib/mpeg/id3v2/id3v2framefactory.h @@ -72,6 +72,14 @@ namespace TagLib { */ virtual Frame *createFrame(const ByteVector &data, const Header *tagHeader) const; + /*! + * After a tag has been read, this tries to rebuild some of them + * information, most notably the recording date, from frames that + * have been deprecated and can't be upgraded directly. + */ + // BIC: Make virtual + void rebuildAggregateFrames(Tag *tag) const; + /*! * Returns the default text encoding for text frames. If setTextEncoding() * has not been explicitly called this will only be used for new text diff --git a/taglib/mpeg/id3v2/id3v2tag.cpp b/taglib/mpeg/id3v2/id3v2tag.cpp index 9a5809e3..a83d9c4f 100644 --- a/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/taglib/mpeg/id3v2/id3v2tag.cpp @@ -704,7 +704,7 @@ void ID3v2::Tag::parse(const ByteVector &origData) } d->paddingSize = static_cast(frameDataLength - frameDataPosition); - return; + break; } Frame *frame = d->factory->createFrame(data.mid(frameDataPosition), @@ -723,6 +723,8 @@ void ID3v2::Tag::parse(const ByteVector &origData) frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion()); addFrame(frame); } + + d->factory->rebuildAggregateFrames(this); } void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index 49168597..e368f04f 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -698,7 +698,7 @@ public: tf = static_cast(bar.ID3v2Tag()->frameList("TDRC").front()); CPPUNIT_ASSERT(tf); CPPUNIT_ASSERT_EQUAL(size_t(1), tf->fieldList().size()); - CPPUNIT_ASSERT_EQUAL(String("2012"), tf->fieldList().front()); + CPPUNIT_ASSERT_EQUAL(String("2012-04-17"), tf->fieldList().front()); tf = dynamic_cast(bar.ID3v2Tag()->frameList("TIPL").front()); CPPUNIT_ASSERT(tf); CPPUNIT_ASSERT_EQUAL(size_t(8), tf->fieldList().size());