]> granicus.if.org Git - taglib/commitdiff
TableOfContents and ChapterFrame can be added to v2.3 or v2.4 tags
authorScott Wheeler <scott@directededge.com>
Thu, 25 Sep 2014 17:32:53 +0000 (19:32 +0200)
committerScott Wheeler <scott@directededge.com>
Thu, 25 Sep 2014 18:01:00 +0000 (20:01 +0200)
taglib/mpeg/id3v2/frames/chapterframe.cpp
taglib/mpeg/id3v2/frames/chapterframe.h
taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp
taglib/mpeg/id3v2/frames/tableofcontentsframe.h
taglib/mpeg/id3v2/id3v2framefactory.cpp
tests/test_id3v2.cpp

index c8650f9df10b063ef75e09c5a3ec5849fba6130c..99bcb3a088bce92611b93bff1422a3d5842358d1 100644 (file)
@@ -36,11 +36,13 @@ using namespace ID3v2;
 class ChapterFrame::ChapterFramePrivate
 {
 public:
-  ChapterFramePrivate()
+  ChapterFramePrivate() :
+    tagHeader(0)
   {
     embeddedFrameList.setAutoDelete(true);
   }
 
+  const ID3v2::Header *tagHeader;
   ByteVector elementID;
   uint startTime;
   uint endTime;
@@ -54,10 +56,11 @@ public:
 // public methods
 ////////////////////////////////////////////////////////////////////////////////
 
-ChapterFrame::ChapterFrame(const ByteVector &data) :
+ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
     ID3v2::Frame(data)
 {
   d = new ChapterFramePrivate;
+  d->tagHeader = tagHeader;
   setData(data);
 }
 
@@ -227,9 +230,9 @@ void ChapterFrame::parseFields(const ByteVector &data)
   d->endOffset = data.mid(pos, 4).toUInt(true);
   pos += 4;
   size -= pos;
-  while((uint)embPos < size - Frame::headerSize(4))
-  {
-    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos));
+
+  while((uint)embPos < size - header()->size()) {
+    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
 
     if(!frame)
       return;
@@ -240,7 +243,7 @@ void ChapterFrame::parseFields(const ByteVector &data)
       return;
     }
 
-    embPos += frame->size() + Frame::headerSize(4);
+    embPos += frame->size() + header()->size();
     addEmbeddedFrame(frame);
   }
 }
@@ -261,9 +264,10 @@ ByteVector ChapterFrame::renderFields() const
   return data;
 }
 
-ChapterFrame::ChapterFrame(const ByteVector &data, Header *h) :
+ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) :
   Frame(h)
 {
   d = new ChapterFramePrivate;
+  d->tagHeader = tagHeader;
   parseFields(fieldData(data));
 }
index 96827e1f16b1426538855aa32578448113e74d98..05bdd980872f9343df792173fc7cfaf641223dc6 100644 (file)
@@ -47,9 +47,10 @@ namespace TagLib {
 
     public:
       /*!
-       * Creates a chapter frame based on \a data.
+       * Creates a chapter frame based on \a data.  \a tagHeader is required as
+       * the internal frames are parsed based on the tag version.
        */
-      ChapterFrame(const ByteVector &data);
+      ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
 
       /*!
        * Creates a chapter frame with the element ID \a eID,
@@ -229,11 +230,10 @@ namespace TagLib {
       virtual ByteVector renderFields() const;
 
     private:
+      ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
       ChapterFrame(const ChapterFrame &);
       ChapterFrame &operator=(const ChapterFrame &);
 
-      ChapterFrame(const ByteVector &data, Header *h);
-
       class ChapterFramePrivate;
       ChapterFramePrivate *d;
     };
index 4698b7ec2fb94d89c74f67ae6d6e11492b955166..6c9dade54e7093b873fd70940cd54ad69abd2fec 100644 (file)
@@ -35,11 +35,13 @@ using namespace ID3v2;
 class TableOfContentsFrame::TableOfContentsFramePrivate
 {
 public:
-  TableOfContentsFramePrivate()
+  TableOfContentsFramePrivate() :
+    tagHeader(0)
   {
     embeddedFrameList.setAutoDelete(true);
   }
 
+  const ID3v2::Header *tagHeader;
   ByteVector elementID;
   bool isTopLevel;
   bool isOrdered;
@@ -52,7 +54,7 @@ public:
 // public methods
 ////////////////////////////////////////////////////////////////////////////////
 
-TableOfContentsFrame::TableOfContentsFrame(const ByteVector &data) :
+TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
     ID3v2::Frame(data)
 {
   d = new TableOfContentsFramePrivate;
@@ -248,9 +250,8 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
   }
 
   size -= pos;
-  while((uint)embPos < size - Frame::headerSize(4))
-  {
-    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos));
+  while(embPos < size - header()->size()) {
+    Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
 
     if(!frame)
       return;
@@ -261,7 +262,7 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
       return;
     }
 
-    embPos += frame->size() + Frame::headerSize(4);
+    embPos += frame->size() + header()->size();
     addEmbeddedFrame(frame);
   }
 }
@@ -290,9 +291,11 @@ ByteVector TableOfContentsFrame::renderFields() const
   return data;
 }
 
-TableOfContentsFrame::TableOfContentsFrame(const ByteVector &data, Header *h) :
+TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader,
+                                           const ByteVector &data, Header *h) :
   Frame(h)
 {
   d = new TableOfContentsFramePrivate;
+  d->tagHeader = tagHeader;
   parseFields(fieldData(data));
 }
index bf578d42a49d548e39f7aea6780b0ee2e77437a6..532e1d0e62e6c0a4ccd8893e9cb5ef19cf51b3c1 100644 (file)
@@ -46,9 +46,10 @@ namespace TagLib {
 
     public:
       /*!
-       * Creates a table of contents frame based on \a data.
+       * Creates a table of contents frame based on \a data.  \a tagHeader is
+       * required as the internal frames are parsed based on the tag version.
        */
-      TableOfContentsFrame(const ByteVector &data);
+      TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
 
       /*!
        * Creates a table of contents frame with the element ID \a eID,
@@ -60,39 +61,39 @@ namespace TagLib {
        * Destroys the frame.
        */
       ~TableOfContentsFrame();
-      
+
       /*!
        * Returns the elementID of the frame. Element ID
        * is a null terminated string, however it's not human-readable.
-       * 
+       *
        * \see setElementID()
        */
       ByteVector elementID() const;
-      
+
       /*!
        * Returns true, if the frame is top-level (doen't have
        * any parent CTOC frame).
-       * 
+       *
        * \see setIsTopLevel()
        */
       bool isTopLevel() const;
-      
+
       /*!
        * Returns true, if the child elements list entries
        * are ordered.
-       * 
+       *
        * \see setIsOrdered()
        */
       bool isOrdered() const;
-      
+
       /*!
        * Returns count of child elements of the frame. It allways
        * corresponds to size of child elements list.
-       * 
+       *
        * \see childElements()
        */
       uint entryCount() const;
-      
+
       /*!
        * Returns list of child elements of the frame.
        *
@@ -103,55 +104,55 @@ namespace TagLib {
       /*!
        * Sets the elementID of the frame to \a eID. If \a eID isn't
        * null terminated, a null char is appended automatically.
-       * 
+       *
        * \see elementID()
        */
       void setElementID(const ByteVector &eID);
-      
+
       /*!
        * Sets, if the frame is top-level (doen't have
        * any parent CTOC frame).
-       * 
+       *
        * \see isTopLevel()
        */
       void setIsTopLevel(const bool &t);
-      
+
       /*!
        * Sets, if the child elements list entries
        * are ordered.
-       * 
+       *
        * \see isOrdered()
        */
       void setIsOrdered(const bool &o);
-      
+
       /*!
        * Sets list of child elements of the frame to \a l.
        *
        * \see childElements()
        */
       void setChildElements(const ByteVectorList &l);
-      
+
       /*!
        * Adds \a cE to list of child elements of the frame.
        *
        * \see childElements()
        */
       void addChildElement(const ByteVector &cE);
-      
+
       /*!
        * Removes \a cE to list of child elements of the frame.
        *
        * \see childElements()
        */
       void removeChildElement(const ByteVector &cE);
-      
+
       /*!
        * Returns a reference to the frame list map.  This is an FrameListMap of
        * all of the frames embedded in the CTOC frame.
        *
-       * This is the most convenient structure for accessing the CTOC frame's 
-       * embedded frames. Many frame types allow multiple instances of the same 
-       * frame type so this is a map of lists. In most cases however there will 
+       * This is the most convenient structure for accessing the CTOC frame's
+       * embedded frames. Many frame types allow multiple instances of the same
+       * frame type so this is a map of lists. In most cases however there will
        * only be a single frame of a certain type.
        *
        * \warning You should not modify this data structure directly, instead
@@ -160,13 +161,13 @@ namespace TagLib {
        * \see embeddedFrameList()
        */
       const FrameListMap &embeddedFrameListMap() const;
-      
+
       /*!
-       * Returns a reference to the embedded frame list.  This is an FrameList 
+       * Returns a reference to the embedded frame list.  This is an FrameList
        * of all of the frames embedded in the CTOC frame in the order that they
        * were parsed.
        *
-       * This can be useful if for example you want iterate over the CTOC frame's 
+       * This can be useful if for example you want iterate over the CTOC frame's
        * embedded frames in the order that they occur in the CTOC frame.
        *
        * \warning You should not modify this data structure directly, instead
@@ -175,7 +176,7 @@ namespace TagLib {
       const FrameList &embeddedFrameList() const;
 
       /*!
-       * Returns the embedded frame list for frames with the id \a frameID 
+       * Returns the embedded frame list for frames with the id \a frameID
        * or an empty list if there are no embedded frames of that type.  This
        * is just a convenience and is equivalent to:
        *
@@ -188,7 +189,7 @@ namespace TagLib {
       const FrameList &embeddedFrameList(const ByteVector &frameID) const;
 
       /*!
-       * Add an embedded frame to the CTOC frame.  At this point the CTOC frame 
+       * Add an embedded frame to the CTOC frame.  At this point the CTOC frame
        * takes ownership of the embedded frame and will handle freeing its memory.
        *
        * \note Using this method will invalidate any pointers on the list
@@ -197,7 +198,7 @@ namespace TagLib {
       void addEmbeddedFrame(Frame *frame);
 
       /*!
-       * Remove an embedded frame from the CTOC frame.  If \a del is true the frame's 
+       * Remove an embedded frame from the CTOC frame.  If \a del is true the frame's
        * memory will be freed; if it is false, it must be deleted by the user.
        *
        * \note Using this method will invalidate any pointers on the list
@@ -206,7 +207,7 @@ namespace TagLib {
       void removeEmbeddedFrame(Frame *frame, bool del = true);
 
       /*!
-       * Remove all embedded frames of type \a id from the CTOC frame and free their 
+       * Remove all embedded frames of type \a id from the CTOC frame and free their
        * memory.
        *
        * \note Using this method will invalidate any pointers on the list
@@ -220,16 +221,16 @@ namespace TagLib {
 
       /*!
        * CTOC frames each have a unique element ID. This searches for a CTOC
-       * frame with the element ID \a eID and returns a pointer to it. This 
+       * frame with the element ID \a eID and returns a pointer to it. This
        * can be used to link together parent and child CTOC frames.
        *
        * \see elementID()
        */
       static TableOfContentsFrame *findByElementID(const Tag *tag, const ByteVector &eID);
-      
+
       /*!
        * CTOC frames each contain a flag that indicates, if CTOC frame is top-level (there isn't
-       * any frame, which contains this frame in its child elements list). Only a single frame 
+       * any frame, which contains this frame in its child elements list). Only a single frame
        * within tag can be top-level. This searches for a top-level CTOC frame.
        *
        * \see isTopLevel()
@@ -241,11 +242,10 @@ namespace TagLib {
       virtual ByteVector renderFields() const;
 
     private:
+      TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
       TableOfContentsFrame(const TableOfContentsFrame &);
       TableOfContentsFrame &operator=(const TableOfContentsFrame &);
 
-      TableOfContentsFrame(const ByteVector &data, Header *h);
-
       class TableOfContentsFramePrivate;
       TableOfContentsFramePrivate *d;
     };
index e2b1d0de96afb38f0162c7ec5693b310217d82a5..fbf38adbd9d008894343b180ba76ef0c1fe4037b 100644 (file)
@@ -280,12 +280,12 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
   // Chapter (ID3v2 chapters 1.0)
 
   if(frameID == "CHAP")
-    return new ChapterFrame(data, header);
+    return new ChapterFrame(tagHeader, data, header);
 
   // Table of contents (ID3v2 chapters 1.0)
 
   if(frameID == "CTOC")
-    return new TableOfContentsFrame(data, header);
+    return new TableOfContentsFrame(tagHeader, data, header);
 
   return new UnknownFrame(data, header);
 }
index 42bfaa382198fbc19d18ee38b253f795af4487a0..fde7c4d25ab886d007a5af599e088abbbffcf8ab 100644 (file)
@@ -889,6 +889,7 @@ public:
   void testParseChapterFrame()
   {
     ID3v2::ChapterFrame f(
+      new ID3v2::Header,
       ByteVector("CHAP"                     // Frame ID
                  "\x00\x00\x00\x20"         // Frame size
                  "\x00\x00"                 // Frame flags
@@ -915,7 +916,7 @@ public:
 
   void testRenderChapterFrame()
   {
-    ID3v2::ChapterFrame f("CHAP");
+    ID3v2::ChapterFrame f(new ID3v2::Header, "CHAP");
     f.setElementID(ByteVector("\x43\x00", 2));
     f.setStartTime(3);
     f.setEndTime(5);
@@ -944,6 +945,7 @@ public:
   void testParseTableOfContentsFrame()
   {
     ID3v2::TableOfContentsFrame f(
+      new ID3v2::Header,
       ByteVector("CTOC"                     // Frame ID
                  "\x00\x00\x00\x16"         // Frame size
                  "\x00\x00"                 // Frame flags
@@ -973,7 +975,7 @@ public:
 
   void testRenderTableOfContentsFrame()
   {
-    ID3v2::TableOfContentsFrame f("CTOC");
+    ID3v2::TableOfContentsFrame f(new ID3v2::Header, "CTOC");
     f.setElementID(ByteVector("\x54\x00", 2));
     f.setIsTopLevel(false);
     f.setIsOrdered(true);