mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 21:20:26 -04:00
Remove MP4 meta atom when empty tag is saved
Currently, MP4 tags can only grow. If items are removed, they are just replaced by padding in the form of "free" atoms. This change will remove the whole "meta" atom when an MP4 tag without items is saved. This will make it possible, to bring the file back to its pristine state without metadata.
This commit is contained in:
parent
ff8a9ea831
commit
2cb7973162
@ -528,7 +528,11 @@ MP4::Tag::save()
|
||||
debug("MP4: Unknown item name \"" + name + "\"");
|
||||
}
|
||||
}
|
||||
data = renderAtom("ilst", data);
|
||||
// Leave data empty if there are no items. This will ensure that no meta atom
|
||||
// is saved.
|
||||
if (!data.isEmpty()) {
|
||||
data = renderAtom("ilst", data);
|
||||
}
|
||||
|
||||
AtomList path = d->atoms->path("moov", "udta", "meta", "ilst");
|
||||
if(path.size() == 4) {
|
||||
@ -643,6 +647,9 @@ MP4::Tag::updateOffsets(long delta, long offset)
|
||||
void
|
||||
MP4::Tag::saveNew(ByteVector data)
|
||||
{
|
||||
if(data.isEmpty())
|
||||
return;
|
||||
|
||||
data = renderAtom("meta", ByteVector(4, '\0') +
|
||||
renderAtom("hdlr", ByteVector(8, '\0') + ByteVector("mdirappl") +
|
||||
ByteVector(9, '\0')) +
|
||||
@ -699,20 +706,40 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
|
||||
}
|
||||
|
||||
long delta = data.size() - length;
|
||||
if(delta > 0 || (delta < 0 && delta > -8)) {
|
||||
data.append(padIlst(data));
|
||||
delta = data.size() - length;
|
||||
}
|
||||
else if(delta < 0) {
|
||||
data.append(padIlst(data, -delta - 8));
|
||||
delta = 0;
|
||||
}
|
||||
if(!data.isEmpty()) {
|
||||
if(delta > 0 || (delta < 0 && delta > -8)) {
|
||||
data.append(padIlst(data));
|
||||
delta = data.size() - length;
|
||||
}
|
||||
else if(delta < 0) {
|
||||
data.append(padIlst(data, -delta - 8));
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
d->file->insert(data, offset, length);
|
||||
d->file->insert(data, offset, length);
|
||||
|
||||
if(delta) {
|
||||
updateParents(path, delta, 1);
|
||||
updateOffsets(delta, offset);
|
||||
if(delta) {
|
||||
updateParents(path, delta, 1);
|
||||
updateOffsets(delta, offset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Strip meta
|
||||
MP4::Atom *udta = *(--it);
|
||||
AtomList &udtaChildren = udta->children;
|
||||
AtomList::Iterator metaIt = udtaChildren.find(meta);
|
||||
if (metaIt != udtaChildren.end()) {
|
||||
offset = meta->offset;
|
||||
delta = - meta->length;
|
||||
udtaChildren.erase(metaIt);
|
||||
d->file->removeBlock(meta->offset, meta->length);
|
||||
delete meta;
|
||||
|
||||
if(delta) {
|
||||
updateParents(path, delta, 2);
|
||||
updateOffsets(delta, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ class TestMP4 : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testRepeatedSave);
|
||||
CPPUNIT_TEST(testWithZeroLengthAtom);
|
||||
CPPUNIT_TEST(testEmptyValuesRemoveItems);
|
||||
CPPUNIT_TEST(testRemoveMetadata);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@ -654,6 +655,39 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(zeroUInt, tag->track());
|
||||
CPPUNIT_ASSERT(!tag->contains("trkn"));
|
||||
}
|
||||
|
||||
void testRemoveMetadata()
|
||||
{
|
||||
ScopedFileCopy copy("no-tags", ".m4a");
|
||||
|
||||
{
|
||||
MP4::File f(copy.fileName().c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
CPPUNIT_ASSERT(!f.hasMP4Tag());
|
||||
MP4::Tag *tag = f.tag();
|
||||
CPPUNIT_ASSERT(tag->isEmpty());
|
||||
tag->setTitle("TITLE");
|
||||
f.save();
|
||||
}
|
||||
{
|
||||
MP4::File f(copy.fileName().c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
CPPUNIT_ASSERT(f.hasMP4Tag());
|
||||
MP4::Tag *tag = f.tag();
|
||||
CPPUNIT_ASSERT(!tag->isEmpty());
|
||||
tag->setTitle("");
|
||||
f.save();
|
||||
}
|
||||
{
|
||||
MP4::File f(copy.fileName().c_str());
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
CPPUNIT_ASSERT(!f.hasMP4Tag());
|
||||
CPPUNIT_ASSERT(f.tag()->isEmpty());
|
||||
CPPUNIT_ASSERT(fileEqual(
|
||||
copy.fileName(),
|
||||
TEST_FILE_PATH_C("no-tags.m4a")));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestMP4);
|
||||
|
Loading…
Reference in New Issue
Block a user