/*************************************************************************** copyright : (C) 2002 - 2008 by Scott Wheeler email : wheeler@kde.org ***************************************************************************/ /*************************************************************************** * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License version * * 2.1 as published by the Free Software Foundation. * * * * This library is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * * 02110-1301 USA * * * * Alternatively, this file is available under the Mozilla Public * * License Version 1.1. You may obtain a copy of the License at * * http://www.mozilla.org/MPL/ * ***************************************************************************/ #ifndef TAGLIB_ID3V2FRAME_H #define TAGLIB_ID3V2FRAME_H #include "tstring.h" #include "tbytevector.h" #include "taglib_export.h" namespace TagLib { class StringList; class PropertyMap; namespace ID3v2 { class Tag; class FrameFactory; //! ID3v2 frame implementation /*! * This class is the main ID3v2 frame implementation. In ID3v2, a tag is * split between a collection of frames (which are in turn split into fields * (Structure, 4) * (Frames). This class provides an API for * gathering information about and modifying ID3v2 frames. Funtionallity * specific to a given frame type is handed in one of the many subclasses. */ class TAGLIB_EXPORT Frame { friend class Tag; friend class FrameFactory; public: /*! * Creates a textual frame which corresponds to a single key in the PropertyMap * interface. These are all (User)TextIdentificationFrames except TIPL and TMCL, * all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame. */ static Frame *createTextualFrame(const String &key, const StringList &values); /*! * Destroys this Frame instance. */ virtual ~Frame(); /*! * Returns the Frame ID (Structure, 4) * (Frames, 4) */ ByteVector frameID() const; /*! * Returns the size of the frame. */ unsigned int size() const; /*! * 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 unsigned int 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 unsigned int headerSize(unsigned int version); // BIC: remove and make non-static /*! * Sets the data that will be used as the frame. Since the length is not * known before the frame has been parsed, this should just be a pointer to * the first byte of the frame. It will determine the length internally * and make that available through size(). */ void setData(const ByteVector &data); /*! * Set the text of frame in the sanest way possible. This should only be * reimplemented in frames where there is some logical mapping to text. * * \note If the frame type supports multiple text encodings, this will not * change the text encoding of the frame; the string will be converted to * that frame's encoding. Please use the specific APIs of the frame types * to set the encoding if that is desired. */ virtual void setText(const String &text); /*! * This returns the textual representation of the data in the frame. * Subclasses must reimplement this method to provide a string * representation of the frame's data. */ virtual String toString() const = 0; /*! * Render the frame back to its binary format in a ByteVector. */ ByteVector render() const; /*! * Returns the text delimiter that is used between fields for the string * type \a t. */ static ByteVector textDelimiter(String::Type t); /*! * The string with which an instrument name is prefixed to build a key in a PropertyMap; * used to translate PropertyMaps to TMCL frames. In the current implementation, this * is "PERFORMER:". */ static const String instrumentPrefix; /*! * The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX * frame for a non-standard key. In the current implementation, this is "COMMENT:". */ static const String commentPrefix; /*! * The PropertyMap key prefix which triggers the use of a USLT frame instead of a TXXX * frame for a non-standard key. In the current implementation, this is "LYRICS:". */ static const String lyricsPrefix; /*! * The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX * frame for a non-standard key. In the current implementation, this is "URL:". */ static const String urlPrefix; protected: class Header; /*! * Constructs an ID3v2 frame using \a data to read the header information. * All other processing of \a data should be handled in a subclass. * * \note This need not contain anything more than a frame ID, but * \e must contain at least that. */ explicit Frame(const ByteVector &data); /*! * This creates an Frame using the header \a h. * * The ownership of this header will be assigned to the frame and the * header will be deleted when the frame is destroyed. */ Frame(Header *h); /*! * Returns a pointer to the frame header. */ Header *header() const; /*! * Sets the header to \a h. If \a deleteCurrent is true, this will free * the memory of the current header. * * The ownership of this header will be assigned to the frame and the * header will be deleted when the frame is destroyed. */ void setHeader(Header *h, bool deleteCurrent = true); /*! * Called by setData() to parse the frame data. It makes this information * available through the public API. */ void parse(const ByteVector &data); /*! * Called by parse() to parse the field data. It makes this information * available through the public API. This must be overridden by the * subclasses. */ virtual void parseFields(const ByteVector &data) = 0; /*! * Render the field data back to a binary format in a ByteVector. This * must be overridden by subclasses. */ virtual ByteVector renderFields() const = 0; /*! * Returns a ByteVector containing the field data given the frame data. * This correctly adjusts for the header size plus any additional frame * data that's specified in the frame header flags. */ ByteVector fieldData(const ByteVector &frameData) const; /*! * Reads a String of type \a encoding from the ByteVector \a data. If \a * position is passed in it is used both as the starting point and is * updated to return the position just after the string that has been read. * This is useful for reading strings sequentially. */ String readStringField(const ByteVector &data, String::Type encoding, int *positon = 0); /*! * Checks a the list of string values to see if they can be used with the * specified encoding and returns the recommended encoding. */ // BIC: remove and make non-static static String::Type checkEncoding(const StringList &fields, String::Type encoding); /*! * Checks a the list of string values to see if they can be used with the * specified encoding and returns the recommended encoding. This method * also checks the ID3v2 version and makes sure the encoding can be used * in the specified version. */ // BIC: remove and make non-static static String::Type checkEncoding(const StringList &fields, String::Type encoding, unsigned int version); /*! * Checks a the list of string values to see if they can be used with the * specified encoding and returns the recommended encoding. This method * also checks the ID3v2 version and makes sure the encoding can be used * in the version specified by the frame's header. */ String::Type checkTextEncoding(const StringList &fields, String::Type encoding) const; /*! * Parses the contents of this frame as PropertyMap. If that fails, the returend * PropertyMap will be empty, and its unsupportedData() will contain this frame's * ID. * BIC: Will be a virtual function in future releases. */ PropertyMap asProperties() const; /*! * Returns an appropriate ID3 frame ID for the given free-form tag key. This method * will return an empty ByteVector if no specialized translation is found. */ static ByteVector keyToFrameID(const String &); /*! * Returns a free-form tag name for the given ID3 frame ID. Note that this does not work * for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned. */ static String frameIDToKey(const ByteVector &); /*! * Returns an appropriate TXXX frame description for the given free-form tag key. */ static String keyToTXXX(const String &); /*! * Returns a free-form tag name for the given ID3 frame description. */ static String txxxToKey(const String &); /*! * This helper function splits the PropertyMap \a original into three ProperytMaps * \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that: * - \a singleFrameProperties contains only of keys which can be represented with * exactly one ID3 frame per key. In the current implementation * this is everything except for the fixed "involved people" keys and keys of the * form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are * mapped to a TMCL frame. * - \a tiplProperties will consist of those keys that are present in * TextIdentificationFrame::involvedPeopleMap() * - \a tmclProperties contains the "musician credits" keys which should be mapped * to a TMCL frame */ static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, PropertyMap &tiplProperties, PropertyMap &tmclProperties); private: Frame(const Frame &); Frame &operator=(const Frame &); class FramePrivate; friend class FramePrivate; FramePrivate *d; }; //! ID3v2 frame header implementation /*! * The ID3v2 Frame Header (Structure, 4) * * Every ID3v2::Frame has an associated header that gives some general * properties of the frame and also makes it possible to identify the frame * type. * * As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the * frame headers and then creates the appropriate Frame subclass based on * the type and attaches the header. */ class TAGLIB_EXPORT Frame::Header { public: /*! * 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. */ 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, unsigned int version = 4); /*! * Destroys this Header instance. */ virtual ~Header(); /*! * 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); /*! * 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, unsigned int version = 4); /*! * Returns the Frame ID (Structure, 4) * (Frames, 4) */ ByteVector frameID() const; /*! * Sets the frame's ID to \a id. Only the first four bytes of \a id will * be used. * * \warning This method should in general be avoided. It exists simply to * provide a mechanism for transforming frames from a deprecated frame type * to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4. */ void setFrameID(const ByteVector &id); /*! * Returns the size of the frame data portion, as set when setData() was * called or set explicitly via setFrameSize(). */ unsigned int frameSize() const; /*! * Sets the size of the frame data portion. */ void setFrameSize(unsigned int size); /*! * Returns the ID3v2 version of the header, as passed in from the * construction of the header or set via setVersion(). */ unsigned int version() const; /*! * Sets the ID3v2 version of the header, changing has impact on the * correct parsing/rendering of frame data. */ void setVersion(unsigned int version); /*! * 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 unsigned int 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 unsigned int size(unsigned int version); /*! * Returns true if the flag for tag alter preservation is set. * * The semantics are a little backwards from what would seem natural * (setting the preservation flag to throw away the frame), but this * follows the ID3v2 standard. * * \see setTagAlterPreservation() */ bool tagAlterPreservation() const; /*! * Sets the flag for preservation of this frame if the tag is set. If * this is set to true the frame will not be written when the tag is * saved. * * The semantics are a little backwards from what would seem natural * (setting the preservation flag to throw away the frame), but this * follows the ID3v2 standard. * * \see tagAlterPreservation() */ void setTagAlterPreservation(bool discard); /*! * Returns true if the flag for file alter preservation is set. * * \note This flag is currently ignored internally in TagLib. */ bool fileAlterPreservation() const; /*! * Returns true if the frame is meant to be read only. * * \note This flag is currently ignored internally in TagLib. */ bool readOnly() const; /*! * Returns true if the flag for the grouping identity is set. * * \note This flag is currently ignored internally in TagLib. */ bool groupingIdentity() const; /*! * Returns true if compression is enabled for this frame. * * \note This flag is currently ignored internally in TagLib. */ bool compression() const; /*! * Returns true if encryption is enabled for this frame. * * \note This flag is currently ignored internally in TagLib. */ bool encryption() const; #ifndef DO_NOT_DOCUMENT bool unsycronisation() const; #endif /*! * Returns true if unsynchronisation is enabled for this frame. */ bool unsynchronisation() const; /*! * Returns true if the flag for a data length indicator is set. */ bool dataLengthIndicator() const; /*! * Render the Header back to binary format in a ByteVector. */ ByteVector render() const; /*! * \deprecated */ bool frameAlterPreservation() const; private: Header(const Header &); Header &operator=(const Header &); class HeaderPrivate; HeaderPrivate *d; }; } } #endif