diff --git a/taglib/mpeg/id3v2/frames/chapterframe.cpp b/taglib/mpeg/id3v2/frames/chapterframe.cpp index e5f24e85..475a2b8c 100644 --- a/taglib/mpeg/id3v2/frames/chapterframe.cpp +++ b/taglib/mpeg/id3v2/frames/chapterframe.cpp @@ -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); } @@ -228,9 +231,8 @@ void ChapterFrame::parseFields(const ByteVector &data) d->endOffset = data.toUInt32BE(pos); pos += 4; size -= pos; - while(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; @@ -241,7 +243,7 @@ void ChapterFrame::parseFields(const ByteVector &data) return; } - embPos += frame->size() + Frame::headerSize(4); + embPos += frame->size() + header()->size(); addEmbeddedFrame(frame); } } @@ -262,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)); } diff --git a/taglib/mpeg/id3v2/frames/chapterframe.h b/taglib/mpeg/id3v2/frames/chapterframe.h index 96827e1f..05bdd980 100644 --- a/taglib/mpeg/id3v2/frames/chapterframe.h +++ b/taglib/mpeg/id3v2/frames/chapterframe.h @@ -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; }; diff --git a/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp b/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp index 23f7874f..2143b81b 100644 --- a/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp +++ b/taglib/mpeg/id3v2/frames/tableofcontentsframe.cpp @@ -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)); } diff --git a/taglib/mpeg/id3v2/frames/tableofcontentsframe.h b/taglib/mpeg/id3v2/frames/tableofcontentsframe.h index bf578d42..532e1d0e 100644 --- a/taglib/mpeg/id3v2/frames/tableofcontentsframe.h +++ b/taglib/mpeg/id3v2/frames/tableofcontentsframe.h @@ -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; }; diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index 6e305438..2da62bef 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -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); } diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index 610fa328..a0056d94 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -891,6 +891,7 @@ public: void testParseChapterFrame() { ID3v2::ChapterFrame f( + new ID3v2::Header, ByteVector("CHAP" // Frame ID "\x00\x00\x00\x20" // Frame size "\x00\x00" // Frame flags @@ -917,7 +918,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); @@ -946,6 +947,7 @@ public: void testParseTableOfContentsFrame() { ID3v2::TableOfContentsFrame f( + new ID3v2::Header, ByteVector("CTOC" // Frame ID "\x00\x00\x00\x16" // Frame size "\x00\x00" // Frame flags @@ -975,7 +977,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);