From c4a0855f42c05ad9fab8915f27439c8194b6bb94 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Wed, 29 Dec 2021 20:54:18 +0100 Subject: [PATCH] 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. --- taglib/mp4/mp4file.cpp | 20 ++++++++++++++++++++ taglib/mp4/mp4file.h | 22 ++++++++++++++++++++++ taglib/mp4/mp4tag.cpp | 26 ++++++++++++++++---------- taglib/mp4/mp4tag.h | 5 +++++ tests/test_mp4.cpp | 6 ++---- 5 files changed, 65 insertions(+), 14 deletions(-) diff --git a/taglib/mp4/mp4file.cpp b/taglib/mp4/mp4file.cpp index a7b8eee1..1747d62c 100644 --- a/taglib/mp4/mp4file.cpp +++ b/taglib/mp4/mp4file.cpp @@ -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 { diff --git a/taglib/mp4/mp4file.h b/taglib/mp4/mp4file.h index 8a46d17d..a8bb4880 100644 --- a/taglib/mp4/mp4file.h +++ b/taglib/mp4/mp4file.h @@ -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. diff --git a/taglib/mp4/mp4tag.cpp b/taglib/mp4/mp4tag.cpp index a1e8b5ea..758475b9 100644 --- a/taglib/mp4/mp4tag.cpp +++ b/taglib/mp4/mp4tag.cpp @@ -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); diff --git a/taglib/mp4/mp4tag.h b/taglib/mp4/mp4tag.h index ccee8e06..2f551140 100644 --- a/taglib/mp4/mp4tag.h +++ b/taglib/mp4/mp4tag.h @@ -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); diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index 6e44421a..31f99287 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -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());