return render(4);
}
+void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
+{
+ const char *unsupportedFrames[] = {
+ "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG",
+ "TMOO", "TPRO", "TSOA", "TSOT", "TSST", "TSOP", "TIPL",
+ "TMCL", 0
+ };
+ ID3v2::TextIdentificationFrame *frameTDOR = 0;
+ ID3v2::TextIdentificationFrame *frameTDRC = 0;
+ for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
+ ID3v2::Frame *frame = *it;
+ ByteVector frameID = frame->header()->frameID();
+ for(int i = 0; unsupportedFrames[i]; i++) {
+ if(frameID == unsupportedFrames[i]) {
+ debug("A frame that is not supported in ID3v2.3 \'"
+ + String(frameID) + "\' has been discarded");
+ frame = 0;
+ break;
+ }
+ }
+ if(frame && frameID == "TDOR") {
+ frameTDOR = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
+ frame = 0;
+ }
+ if(frame && frameID == "TDRC") {
+ frameTDRC = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
+ frame = 0;
+ }
+ if(frame) {
+ frames->append(frame);
+ }
+ }
+ if(frameTDOR) {
+ String content = frameTDOR->toString();
+ if(content.size() >= 4) {
+ ID3v2::TextIdentificationFrame *frameTORY = new ID3v2::TextIdentificationFrame("TORY", String::Latin1);
+ frameTORY->setText(content.substr(0, 4));
+ frames->append(frameTORY);
+ newFrames->append(frameTORY);
+ }
+ }
+ if(frameTDRC) {
+ // FIXME we can do better here, define also TDAT and TIME
+ String content = frameTDRC->toString();
+ if(content.size() >= 4) {
+ ID3v2::TextIdentificationFrame *frameTYER = new ID3v2::TextIdentificationFrame("TYER", String::Latin1);
+ frameTYER->setText(content.substr(0, 4));
+ frames->append(frameTYER);
+ newFrames->append(frameTYER);
+ }
+ }
+ // FIXME migrate TIPL and TMCL to IPLS
+}
+
+
ByteVector ID3v2::Tag::render(int version) const
{
// We need to render the "tag data" first so that we have to correct size to
// Loop through the frames rendering them and adding them to the tagData.
- for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
+ FrameList newFrames;
+ newFrames.setAutoDelete(true);
+
+ FrameList frameList;
+ if(version == 4) {
+ frameList = d->frameList;
+ }
+ else {
+ downgradeFrames(&frameList, &newFrames);
+ }
+
+ for(FrameList::Iterator it = frameList.begin(); it != frameList.end(); it++) {
(*it)->header()->setVersion(version);
if((*it)->header()->frameID().size() != 4) {
debug("A frame of unsupported or unknown type \'"
CPPUNIT_TEST(testUpdateGenre23_2);
CPPUNIT_TEST(testUpdateGenre24);
CPPUNIT_TEST(testUpdateDate22);
+ CPPUNIT_TEST(testDowngradeTo23);
// CPPUNIT_TEST(testUpdateFullDate22); TODO TYE+TDA should be upgraded to TDRC together
CPPUNIT_TEST(testCompressedFrameWithBrokenLength);
CPPUNIT_TEST_SUITE_END();
CPPUNIT_ASSERT_EQUAL(String("2010-04-03"), f.ID3v2Tag()->frameListMap()["TDRC"].front()->toString());
}
+ void testDowngradeTo23()
+ {
+ ScopedFileCopy copy("xing", ".mp3");
+ string newname = copy.fileName();
+
+ ID3v2::TextIdentificationFrame *tf;
+ MPEG::File foo(newname.c_str());
+ tf = new ID3v2::TextIdentificationFrame("TDOR", String::Latin1);
+ tf->setText("2011-03-16");
+ foo.ID3v2Tag()->addFrame(tf);
+ tf = new ID3v2::TextIdentificationFrame("TDRC", String::Latin1);
+ tf->setText("2012-04-17");
+ foo.ID3v2Tag()->addFrame(tf);
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TDRL", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TDTG", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TMOO", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TPRO", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TSOA", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TSOT", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TSST", String::Latin1));
+ foo.ID3v2Tag()->addFrame(new ID3v2::TextIdentificationFrame("TSOP", String::Latin1));
+ foo.save(MPEG::File::AllTags, true, 3);
+
+ MPEG::File bar(newname.c_str());
+ tf = static_cast<ID3v2::TextIdentificationFrame *>(bar.ID3v2Tag()->frameList("TDOR").front());
+ CPPUNIT_ASSERT(tf);
+ CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), tf->fieldList().size());
+ CPPUNIT_ASSERT_EQUAL(String("2011"), tf->fieldList().front());
+ tf = static_cast<ID3v2::TextIdentificationFrame *>(bar.ID3v2Tag()->frameList("TDRC").front());
+ CPPUNIT_ASSERT(tf);
+ CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), tf->fieldList().size());
+ CPPUNIT_ASSERT_EQUAL(String("2012"), tf->fieldList().front());
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TDRL"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TDTG"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TMOO"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TPRO"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TSOA"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TSOT"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TSST"));
+ CPPUNIT_ASSERT(!bar.ID3v2Tag()->frameListMap().contains("TSOP"));
+ }
+
void testCompressedFrameWithBrokenLength()
{
MPEG::File f("data/compressed_id3_frame.mp3", false);