Merge pull request #643 from TsudaKageyu/save-asf

Avoid writing duplicate tags when saving ASF files.
This commit is contained in:
Tsuda Kageyu 2015-11-20 13:52:33 +09:00
commit 224f133d65
4 changed files with 32 additions and 8 deletions

1
NEWS
View File

@ -5,6 +5,7 @@
* Better handling of duplicate ID3v2 tags in all kinds of files.
* Better handling of duplicate tags in WAV files.
* Fixed crash when calling File::properties() after strip().
* Fixed possible file corruptions when saving ASF files.
* Marked ByteVector::null and ByteVector::isNull() deprecated.
* Marked String::null and ByteVector::isNull() deprecated.
* Many smaller bug fixes and performance improvements.

View File

@ -50,7 +50,7 @@ public:
class MetadataLibraryObject;
FilePrivate():
size(0),
headerSize(0),
tag(0),
properties(0),
contentDescriptionObject(0),
@ -68,7 +68,7 @@ public:
delete properties;
}
unsigned long long size;
unsigned long long headerSize;
ASF::Tag *tag;
ASF::Properties *properties;
@ -556,6 +556,10 @@ bool ASF::File::save()
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
}
d->extendedContentDescriptionObject->attributeData.clear();
d->metadataObject->attributeData.clear();
d->metadataLibraryObject->attributeData.clear();
const AttributeListMap allAttributes = d->tag->attributeListMap();
for(AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) {
@ -591,8 +595,14 @@ bool ASF::File::save()
data.append((*it)->render(this));
}
data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data;
insert(data, 0, (TagLib::ulong)d->size);
seek(16);
writeBlock(ByteVector::fromLongLong(data.size() + 30, false));
writeBlock(ByteVector::fromUInt(d->objects.size(), false));
writeBlock(ByteVector("\x01\x02", 2));
insert(data, 30, static_cast<ulong>(d->headerSize - 30));
d->headerSize = data.size() + 30;
return true;
}
@ -617,7 +627,7 @@ void ASF::File::read()
d->properties = new ASF::Properties();
bool ok;
d->size = readQWORD(this, &ok);
d->headerSize = readQWORD(this, &ok);
if(!ok) {
setValid(false);
return;

View File

@ -112,9 +112,6 @@ namespace TagLib {
* Save the file.
*
* This returns true if the save was successful.
*
* \warning In the current implementation, it's dangerous to call save()
* repeatedly. At worst it will corrupt the file.
*/
virtual bool save();

View File

@ -25,6 +25,7 @@ class TestASF : public CppUnit::TestFixture
CPPUNIT_TEST(testSavePicture);
CPPUNIT_TEST(testSaveMultiplePictures);
CPPUNIT_TEST(testProperties);
CPPUNIT_TEST(testRepeatedSave);
CPPUNIT_TEST_SUITE_END();
public:
@ -270,6 +271,21 @@ public:
CPPUNIT_ASSERT_EQUAL(StringList("3"), tags["DISCNUMBER"]);
}
void testRepeatedSave()
{
ScopedFileCopy copy("silence-1", ".wma");
{
ASF::File f(copy.fileName().c_str());
f.tag()->setTitle(std::string(128 * 1024, 'X').c_str());
f.save();
CPPUNIT_ASSERT_EQUAL(297578L, f.length());
f.tag()->setTitle(std::string(16 * 1024, 'X').c_str());
f.save();
CPPUNIT_ASSERT_EQUAL(68202L, f.length());
}
}
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestASF);