diff --git a/examples/strip-id3v1.cpp b/examples/strip-id3v1.cpp index ab36d711..f8c88916 100644 --- a/examples/strip-id3v1.cpp +++ b/examples/strip-id3v1.cpp @@ -35,6 +35,6 @@ int main(int argc, char *argv[]) std::cout << "******************** Stripping ID3v1 Tag From: \"" << argv[i] << "\"********************" << std::endl; MPEG::File f(argv[i]); - f.strip(MPEG::File::ID3v1); + f.strip(); } } diff --git a/mpeg/id3v2/frames/commentsframe.cpp b/mpeg/id3v2/frames/commentsframe.cpp index 4a9083f6..99af7a4a 100644 --- a/mpeg/id3v2/frames/commentsframe.cpp +++ b/mpeg/id3v2/frames/commentsframe.cpp @@ -43,14 +43,14 @@ public: CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM") { - d = new CommentsFramePrivate(); + d = new CommentsFramePrivate; d->textEncoding = encoding; } CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data) { - d = new CommentsFramePrivate(); - parseFields(data.mid(Header::size(), size())); + d = new CommentsFramePrivate; + parseFields(data.mid(Header::size(header()->version()), size())); } CommentsFrame::~CommentsFrame() @@ -148,5 +148,5 @@ ByteVector CommentsFrame::renderFields() const CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h) { d = new CommentsFramePrivate(); - parseFields(data.mid(Header::size(), size())); + parseFields(data.mid(Header::size(h->version()), size())); } diff --git a/mpeg/id3v2/frames/textidentificationframe.cpp b/mpeg/id3v2/frames/textidentificationframe.cpp index ae76fb9c..0d696861 100644 --- a/mpeg/id3v2/frames/textidentificationframe.cpp +++ b/mpeg/id3v2/frames/textidentificationframe.cpp @@ -146,5 +146,5 @@ ByteVector TextIdentificationFrame::renderFields() const TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h) { d = new TextIdentificationFramePrivate; - parseFields(data.mid(Header::size(), size())); + parseFields(data.mid(Header::size(h->version()), size())); } diff --git a/mpeg/id3v2/id3v2frame.cpp b/mpeg/id3v2/id3v2frame.cpp index 5f0f894a..2180e6ef 100644 --- a/mpeg/id3v2/id3v2frame.cpp +++ b/mpeg/id3v2/id3v2frame.cpp @@ -50,6 +50,11 @@ TagLib::uint Frame::headerSize() return Header::size(); } +TagLib::uint Frame::headerSize(uint version) +{ + return Header::size(version); +} + ByteVector Frame::textDelimiter(String::Type t) { ByteVector d = char(0); @@ -108,13 +113,13 @@ ByteVector Frame::render() const Frame::Frame(const ByteVector &data) { - d = new FramePrivate(); + d = new FramePrivate; d->header = new Header(data); } Frame::Frame(Header *h) { - d = new FramePrivate(); + d = new FramePrivate; d->header = h; } @@ -139,7 +144,8 @@ void Frame::parse(const ByteVector &data) d->header = new Header(data); // size() is the lenght of the field data - parseFields(data.mid(Header::size(), size())); + + parseFields(data.mid(Header::size(d->header->version()), size())); } //////////////////////////////////////////////////////////////////////////////// @@ -149,11 +155,11 @@ void Frame::parse(const ByteVector &data) class Frame::Header::HeaderPrivate { public: - HeaderPrivate() : frameSize(0) {} + HeaderPrivate() : frameSize(0), version(4) {} ByteVector frameID; uint frameSize; - static const unsigned int size = 10; + uint version; }; //////////////////////////////////////////////////////////////////////////////// @@ -162,7 +168,21 @@ public: TagLib::uint Frame::Header::size() { - return HeaderPrivate::size; + return size(4); +} + +TagLib::uint Frame::Header::size(uint version) +{ + switch(version) { + case 0: + case 1: + case 2: + return 6; + case 3: + case 4: + default: + return 10; + } } //////////////////////////////////////////////////////////////////////////////// @@ -175,6 +195,12 @@ Frame::Header::Header(const ByteVector &data, bool synchSafeInts) setData(data, synchSafeInts); } +Frame::Header::Header(const ByteVector &data, uint version) +{ + d = new HeaderPrivate; + setData(data, version); +} + Frame::Header::~Header() { delete d; @@ -182,33 +208,78 @@ Frame::Header::~Header() void Frame::Header::setData(const ByteVector &data, bool synchSafeInts) { - if(data.size() < 4) { - debug("You must at least specify a frame ID."); - return; + setData(data, uint(synchSafeInts ? 4 : 3)); +} + +void Frame::Header::setData(const ByteVector &data, uint version) +{ + d->version = version; + + switch(version) { + case 0: + case 1: + case 2: + { + + // ID3v2.2 + + if(data.size() < 3) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first three bytes + + d->frameID = data.mid(0, 3); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 6) { + d->frameSize = 0; + return; + } + + d->frameSize = data.mid(3, 3).toUInt(); + + break; } + case 3: + case 4: + default: + { + // ID3v2.3 / ID3v2.4 - // set the frame ID -- the first four bytes + if(data.size() < 4) { + debug("You must at least specify a frame ID."); + return; + } - d->frameID = data.mid(0, 4); + // Set the frame ID -- the first four bytes - // If the full header information was not passed in, do not continue to the - // steps to parse the frame size and flags. + d->frameID = data.mid(0, 4); - if(data.size() < 10) { - d->frameSize = 0; - return; + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 10) { + d->frameSize = 0; + return; + } + + // Set the size -- the frame size is the four bytes starting at byte four in + // the frame header (structure 4) + + if(version >= 4) + d->frameSize = SynchData::toUInt(data.mid(4, 4)); + else + d->frameSize = data.mid(4, 4).toUInt(); + + // TODO: read flags + + break; + } } - - // Set the size -- the frame size is the four bytes starting at byte four in - // the frame header (structure 4) - - if(synchSafeInts) - d->frameSize = SynchData::toUInt(data.mid(4, 4)); - else - d->frameSize = data.mid(4, 4).toUInt(); - - // read flags - // ... } ByteVector Frame::Header::frameID() const @@ -231,6 +302,11 @@ void Frame::Header::setFrameSize(uint size) d->frameSize = size; } +TagLib::uint Frame::Header::version() const +{ + return d->version; +} + ByteVector Frame::Header::render() const { ByteVector flags(2, char(0)); // just blank for the moment diff --git a/mpeg/id3v2/id3v2frame.h b/mpeg/id3v2/id3v2frame.h index b772ea40..920429c6 100644 --- a/mpeg/id3v2/id3v2frame.h +++ b/mpeg/id3v2/id3v2frame.h @@ -65,8 +65,20 @@ namespace TagLib { /*! * Returns the size of the frame header + * + * \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use + * the call below which accepts an ID3v2 version number. In the next + * non-binary compatible release this will be made into a non-static + * member that checks the internal ID3v2 version. */ - static uint headerSize(); + static uint headerSize(); // BIC: remove and make non-static + + /*! + * Returns the size of the frame header for the given ID3v2 version. + * + * \deprecated Please see the explanation above. + */ + static uint headerSize(uint version); // BIC: remove and make non-static /*! * Sets the data that will be used as the frame. Since the length is not @@ -187,8 +199,20 @@ namespace TagLib { * Construct a Frame Header based on \a data. \a data must at least * contain a 4 byte frame ID, and optionally can contain flag data and the * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \deprecated Please use the constructor below that accepts a version + * number. */ - explicit Header(const ByteVector &data, bool synchSafeInts = true); + explicit Header(const ByteVector &data, bool synchSafeInts); + + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \a version should be the ID3v2 version of the tag. + */ + explicit Header(const ByteVector &data, uint version = 4); /*! * Destroys this Header instance. @@ -197,8 +221,17 @@ namespace TagLib { /*! * Sets the data for the Header. + * + * \deprecated Please use the version below that accepts an ID3v2 version + * number. */ - void setData(const ByteVector &data, bool synchSafeInts = true); + void setData(const ByteVector &data, bool synchSafeInts); + + /*! + * Sets the data for the Header. \a version should indicate the ID3v2 + * version number of the tag that this frame is contained in. + */ + void setData(const ByteVector &data, uint version = 4); /*! * Returns the Frame ID (Structure, 4) @@ -228,11 +261,29 @@ namespace TagLib { void setFrameSize(uint size); /*! - * Returns the size of the frame header in bytes. Currently this is - * always 10. + * Returns the ID3v2 version of the header (as passed in from the + * construction of the header). + */ + uint version() const; + + /*! + * Returns the size of the frame header in bytes. + * + * \deprecated Please use the version of this method that accepts a + * version. This is only accurate for ID3v2.3 and ID3v2.4. This will be + * removed in the next binary incompatible release (2.0) and will be + * replaced with a non-static method that checks the frame version. */ static uint size(); + /*! + * Returns the size of the frame header in bytes for the ID3v2 version + * that's given. + * + * \deprecated Please see the explanation in the version above. + */ + static uint size(uint version); + /*! * Render the Header back to binary format in a ByteVector. */ diff --git a/mpeg/id3v2/id3v2framefactory.cpp b/mpeg/id3v2/id3v2framefactory.cpp index 8d4352fa..aa9189ae 100644 --- a/mpeg/id3v2/id3v2framefactory.cpp +++ b/mpeg/id3v2/id3v2framefactory.cpp @@ -56,15 +56,20 @@ FrameFactory *FrameFactory::instance() Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const { - Frame::Header *header = new Frame::Header(data, synchSafeInts); + return createFrame(data, uint(synchSafeInts ? 4 : 3)); +} + +Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const +{ + Frame::Header *header = new Frame::Header(data, version); TagLib::ByteVector frameID = header->frameID(); // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1 // characters. Also make sure that there is data in the frame. - if(!frameID.size() == 4 || header->frameSize() <= 0) - return 0; + if(!frameID.size() == (version < 3 ? 3 : 4) || header->frameSize() <= 0) + return 0; for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) { diff --git a/mpeg/id3v2/id3v2framefactory.h b/mpeg/id3v2/id3v2framefactory.h index f1cefcde..544b0f0e 100644 --- a/mpeg/id3v2/id3v2framefactory.h +++ b/mpeg/id3v2/id3v2framefactory.h @@ -1,4 +1,4 @@ -/*************************************************************************** + /*************************************************************************** copyright : (C) 2002, 2003 by Scott Wheeler email : wheeler@kde.org ***************************************************************************/ @@ -56,8 +56,18 @@ namespace TagLib { * Create a frame based on \a data. \a synchSafeInts should only be set * false if we are parsing an old tag (v2.3 or older) that does not support * synchsafe ints. + * + * \deprecated Please use the method below that accepts an ID3 version + * number in new code. */ - Frame *createFrame(const ByteVector &data, bool synchSafeInts = true) const; + Frame *createFrame(const ByteVector &data, bool synchSafeInts) const; + + /*! + * Create a frame based on \a data. \a version should indicate the ID3v2 + * version of the tag. As ID3v2.4 is the most current version of the + * standard 4 is the default. + */ + Frame *createFrame(const ByteVector &data, uint version = 4) const; /*! * Returns the default text encoding for text frames. If setTextEncoding() diff --git a/mpeg/id3v2/id3v2header.cpp b/mpeg/id3v2/id3v2header.cpp index caa28e2c..4ed09e8a 100644 --- a/mpeg/id3v2/id3v2header.cpp +++ b/mpeg/id3v2/id3v2header.cpp @@ -78,12 +78,12 @@ ByteVector Header::fileIdentifier() Header::Header() { - d = new HeaderPrivate(); + d = new HeaderPrivate; } Header::Header(const ByteVector &data) { - d = new HeaderPrivate(); + d = new HeaderPrivate; parse(data); } diff --git a/mpeg/id3v2/id3v2tag.cpp b/mpeg/id3v2/id3v2tag.cpp index 871cd130..a3a0d60e 100644 --- a/mpeg/id3v2/id3v2tag.cpp +++ b/mpeg/id3v2/id3v2tag.cpp @@ -365,7 +365,7 @@ void ID3v2::Tag::parse(const ByteVector &data) // Make sure that there is at least enough room in the remaining frame data for // a frame header. - while(frameDataPosition < frameDataLength - Frame::headerSize()) { + while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) { // If the next data is position is 0, assume that we've hit the padding // portion of the frame data. @@ -379,10 +379,8 @@ void ID3v2::Tag::parse(const ByteVector &data) return; } - bool synchSafeInts = d->header.majorVersion() >= 4; - Frame *frame = d->factory->createFrame(data.mid(frameDataOffset + frameDataPosition), - synchSafeInts); + d->header.majorVersion()); if(!frame) return; @@ -394,7 +392,7 @@ void ID3v2::Tag::parse(const ByteVector &data) return; } - frameDataPosition += frame->size() + Frame::headerSize(); + frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion()); addFrame(frame); } }