Add MP4::File::strip() to remove meta atom from file

This changes the modifications from the last commit in order to
achieve the following behavior: MP4::File::save() works in the
same way as before, i.e. it will never shrink the file and will
make space from removed items available as padding in the form of
a "free" atom. To completely remove the "meta" atom from the file,
a new method strip() is introduced, which can be used in the same
way as its MPEG::File::strip() counterpart.
This commit is contained in:
Urs Fleisch 2021-12-29 20:54:18 +01:00
parent 2cb7973162
commit c4a0855f42
5 changed files with 65 additions and 14 deletions

View File

@ -175,6 +175,26 @@ MP4::File::save()
return d->tag->save();
}
bool
MP4::File::strip(int tags)
{
if(readOnly()) {
debug("MP4::File::strip() - Cannot strip tags from a read only file.");
return false;
}
if(!isValid()) {
debug("MP4::File::strip() -- Cannot strip tags from an invalid file.");
return false;
}
if(tags & MP4) {
return d->tag->strip();
}
return true;
}
bool
MP4::File::hasMP4Tag() const
{

View File

@ -48,6 +48,19 @@ namespace TagLib {
class TAGLIB_EXPORT File : public TagLib::File
{
public:
/*!
* This set of flags is used for strip() and is suitable for
* being OR-ed together.
*/
enum TagTypes {
//! Empty set. Matches no tag types.
NoTags = 0x0000,
//! Matches MP4 tags.
MP4 = 0x0001,
//! Matches all tag types.
AllTags = 0xffff
};
/*!
* Constructs an MP4 file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
@ -114,6 +127,15 @@ namespace TagLib {
*/
bool save();
/*!
* This will strip the tags that match the OR-ed together TagTypes from the
* file. By default it strips all tags. It returns true if the tags are
* successfully stripped.
*
* \note This will update the file immediately.
*/
bool strip(int tags = AllTags);
/*!
* Returns whether or not the file on disk actually has an MP4 tag, or the
* file has a Metadata Item List (ilst) atom.

View File

@ -528,11 +528,7 @@ MP4::Tag::save()
debug("MP4: Unknown item name \"" + name + "\"");
}
}
// Leave data empty if there are no items. This will ensure that no meta atom
// is saved.
if (!data.isEmpty()) {
data = renderAtom("ilst", data);
}
data = renderAtom("ilst", data);
AtomList path = d->atoms->path("moov", "udta", "meta", "ilst");
if(path.size() == 4) {
@ -545,6 +541,19 @@ MP4::Tag::save()
return true;
}
bool
MP4::Tag::strip()
{
d->items.clear();
AtomList path = d->atoms->path("moov", "udta", "meta", "ilst");
if(path.size() == 4) {
saveExisting(ByteVector(), path);
}
return true;
}
void
MP4::Tag::updateParents(const AtomList &path, long delta, int ignore)
{
@ -647,9 +656,6 @@ 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')) +
@ -724,11 +730,11 @@ MP4::Tag::saveExisting(ByteVector data, const AtomList &path)
}
}
else {
// Strip meta
// Strip meta if data is empty, only the case when called from strip().
MP4::Atom *udta = *(--it);
AtomList &udtaChildren = udta->children;
AtomList::Iterator metaIt = udtaChildren.find(meta);
if (metaIt != udtaChildren.end()) {
if(metaIt != udtaChildren.end()) {
offset = meta->offset;
delta = - meta->length;
udtaChildren.erase(metaIt);

View File

@ -102,6 +102,11 @@ namespace TagLib {
*/
bool contains(const String &key) const;
/*!
* Saves the associated file with the tag stripped.
*/
bool strip();
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
PropertyMap setProperties(const PropertyMap &properties);

View File

@ -673,10 +673,8 @@ public:
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();
CPPUNIT_ASSERT(!f.tag()->isEmpty());
f.strip();
}
{
MP4::File f(copy.fileName().c_str());