diff --git a/taglib/mp4/mp4file.cpp b/taglib/mp4/mp4file.cpp index 1fc1524f..566a5e32 100644 --- a/taglib/mp4/mp4file.cpp +++ b/taglib/mp4/mp4file.cpp @@ -34,7 +34,7 @@ using namespace TagLib; namespace { - bool checkValid(const MP4::AtomList &list) + inline bool checkValid(const MP4::AtomList &list) { for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) { @@ -55,7 +55,8 @@ public: FilePrivate() : tag(0), atoms(0), - properties(0) {} + properties(0), + hasMP4Tag(false) {} ~FilePrivate() { @@ -67,6 +68,8 @@ public: MP4::Tag *tag; MP4::Atoms *atoms; MP4::Properties *properties; + + bool hasMP4Tag; }; MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) : @@ -130,12 +133,15 @@ MP4::File::read(bool readProperties) } // must have a moov atom, otherwise consider it invalid - MP4::Atom *moov = d->atoms->find("moov"); - if(!moov) { + if(!d->atoms->find("moov")) { setValid(false); return; } + if(d->atoms->find("moov", "udta", "meta", "ilst")) { + d->hasMP4Tag = true; + } + d->tag = new Tag(this, d->atoms); if(readProperties) { d->properties = new Properties(this, d->atoms); @@ -155,6 +161,16 @@ MP4::File::save() return false; } - return d->tag->save(); + const bool success = d->tag->save(); + if(success) { + d->hasMP4Tag = true; + } + + return success; } +bool +MP4::File::hasMP4Tag() const +{ + return d->hasMP4Tag; +} diff --git a/taglib/mp4/mp4file.h b/taglib/mp4/mp4file.h index 791a0192..40fcde78 100644 --- a/taglib/mp4/mp4file.h +++ b/taglib/mp4/mp4file.h @@ -117,6 +117,12 @@ namespace TagLib { */ bool save(); + /*! + * Returns whether or not the file on disk actually has an MP4 tag, or the + * file has a Metadata Item List (ilst) atom. + */ + bool hasMP4Tag() const; + private: void read(bool readProperties); diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index 6841c43f..c110a612 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -19,6 +19,7 @@ class TestMP4 : public CppUnit::TestFixture CPPUNIT_TEST(testPropertiesALAC); CPPUNIT_TEST(testFreeForm); CPPUNIT_TEST(testCheckValid); + CPPUNIT_TEST(testHasTag); CPPUNIT_TEST(testIsEmpty); CPPUNIT_TEST(testUpdateStco); CPPUNIT_TEST(testSaveExisingWhenIlstIsLast); @@ -67,8 +68,30 @@ public: { MP4::File f(TEST_FILE_PATH_C("empty.aiff")); CPPUNIT_ASSERT(!f.isValid()); - MP4::File f2(TEST_FILE_PATH_C("has-tags.m4a")); - CPPUNIT_ASSERT(f2.isValid()); + } + + void testHasTag() + { + { + MP4::File f(TEST_FILE_PATH_C("has-tags.m4a")); + CPPUNIT_ASSERT(f.isValid()); + CPPUNIT_ASSERT(f.hasMP4Tag()); + } + + ScopedFileCopy copy("no-tags", ".m4a"); + + { + MP4::File f(copy.fileName().c_str()); + CPPUNIT_ASSERT(f.isValid()); + CPPUNIT_ASSERT(!f.hasMP4Tag()); + f.tag()->setTitle("TITLE"); + f.save(); + } + { + MP4::File f(copy.fileName().c_str()); + CPPUNIT_ASSERT(f.isValid()); + CPPUNIT_ASSERT(f.hasMP4Tag()); + } } void testIsEmpty()