]> granicus.if.org Git - taglib/commitdiff
Fix saving MP4 files.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Tue, 24 Nov 2015 14:41:10 +0000 (23:41 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Tue, 24 Nov 2015 14:41:10 +0000 (23:41 +0900)
This fixes the issue reported at #619.

taglib/mp4/mp4file.cpp
taglib/mp4/mp4file.h
taglib/mp4/mp4tag.cpp
tests/test_mp4.cpp

index 566a5e32b98fb47724f602ec730dfb2c252d0569..d0a6c4c66e561358083674a7d19975c401ba5324 100644 (file)
@@ -55,8 +55,7 @@ public:
   FilePrivate() :
     tag(0),
     atoms(0),
-    properties(0),
-    hasMP4Tag(false) {}
+    properties(0) {}
 
   ~FilePrivate()
   {
@@ -68,8 +67,6 @@ public:
   MP4::Tag        *tag;
   MP4::Atoms      *atoms;
   MP4::Properties *properties;
-
-  bool hasMP4Tag;
 };
 
 MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
@@ -138,10 +135,6 @@ MP4::File::read(bool readProperties)
     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);
@@ -161,16 +154,11 @@ MP4::File::save()
     return false;
   }
 
-  const bool success = d->tag->save();
-  if(success) {
-    d->hasMP4Tag = true;
-  }
-
-  return success;
+  return d->tag->save();
 }
 
 bool
 MP4::File::hasMP4Tag() const
 {
-  return d->hasMP4Tag;
+  return (d->atoms->find("moov", "udta", "meta", "ilst") != 0);
 }
index 40fcde78cb52008796d3e948b763fa2b4864f945..3840bd0220f9fac83762602679d2d3f14a475e53 100644 (file)
@@ -111,9 +111,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.
        */
       bool save();
 
index 842191969822aa3804a2ca9788274cddba91c37f..384a45485727f4a63caa5777dd01511496390449 100644 (file)
@@ -629,6 +629,11 @@ MP4::Tag::saveNew(ByteVector data)
 
   updateParents(path, data.size());
   updateOffsets(data.size(), offset);
+
+  // Insert the newly created atoms into the tree to keep it up-to-date.
+
+  d->file->seek(offset);
+  path.back()->children.prepend(new Atom(d->file));
 }
 
 void
index 58dbae42325225aceb8d0d670dc7b33477f5ac29..10b1e1fc6578c83434cbe5e77467843b2e440fea 100644 (file)
@@ -30,6 +30,7 @@ class TestMP4 : public CppUnit::TestFixture
   CPPUNIT_TEST(testCovrRead2);
   CPPUNIT_TEST(testProperties);
   CPPUNIT_TEST(testFuzzedFile);
+  CPPUNIT_TEST(testRepeatedSave);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -344,6 +345,17 @@ public:
     CPPUNIT_ASSERT(f.isValid());
   }
 
+  void testRepeatedSave()
+  {
+    ScopedFileCopy copy("no-tags", ".m4a");
+
+    MP4::File f(copy.fileName().c_str());
+    f.tag()->setTitle("0123456789");
+    f.save();
+    f.save();
+    CPPUNIT_ASSERT_EQUAL(2862L, f.find("0123456789"));
+    CPPUNIT_ASSERT_EQUAL(-1L, f.find("0123456789", 2863));
+  }
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestMP4);