/***************************************************************************
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_ID3V2FRAMEFACTORY_H
#define TAGLIB_ID3V2FRAMEFACTORY_H
#include "tbytevector.h"
#include "taglib_export.h"
#include "id3v2frame.h"
#include "id3v2header.h"
namespace TagLib {
namespace ID3v2 {
class TextIdentificationFrame;
//! A factory for creating ID3v2 frames during parsing
/*!
* This factory abstracts away the frame creation process and instantiates
* the appropriate ID3v2::Frame subclasses based on the contents of the
* data.
*
* Reimplementing this factory is the key to adding support for frame types
* not directly supported by TagLib to your application. To do so you would
* subclass this factory and reimplement createFrame(). Then by setting your
* factory to be the default factory in ID3v2::Tag constructor you can
* implement behavior that will allow for new ID3v2::Frame subclasses (also
* provided by you) to be used.
* See
* tests/test_id3v2framefactory.cpp for an example.
*
* This implements both abstract factory and singleton patterns
* of which more information is available on the web and in software design
* textbooks (notably Design Patterns).
*
* \note You do not need to use this factory to create new frames to add to
* an ID3v2::Tag. You can instantiate frame subclasses directly (with \c new)
* and add them to a tag using ID3v2::Tag::addFrame()
*
* \see ID3v2::Tag::addFrame()
*/
class TAGLIB_EXPORT FrameFactory
{
public:
FrameFactory(const FrameFactory &) = delete;
FrameFactory &operator=(const FrameFactory &) = delete;
static FrameFactory *instance();
/*!
* Create a frame based on \a origData. \a tagHeader should be a valid
* ID3v2::Header instance.
*/
virtual Frame *createFrame(const ByteVector &origData, const Header *tagHeader) const;
/*!
* Creates a textual frame which corresponds to a single key in the
* PropertyMap interface. TIPL and TMCL do not belong to this category
* and are thus handled explicitly in the Frame class.
*/
virtual Frame *createFrameForProperty(
const String &key, const StringList &values) const;
/*!
* After a tag has been read, this tries to rebuild some of them
* information, most notably the recording date, from frames that
* have been deprecated and can't be upgraded directly.
*/
virtual void rebuildAggregateFrames(ID3v2::Tag *tag) const;
/*!
* Returns the default text encoding for text frames. If setTextEncoding()
* has not been explicitly called this will only be used for new text
* frames. However, if this value has been set explicitly all frames will be
* converted to this type (unless it's explicitly set differently for the
* individual frame) when being rendered.
*
* \see setDefaultTextEncoding()
*/
String::Type defaultTextEncoding() const;
/*!
* Set the default text encoding for all text frames that are created to
* \a encoding. If no value is set the frames with either default to the
* encoding type that was parsed and new frames default to Latin1.
*
* Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE.
*
* \see defaultTextEncoding()
*/
void setDefaultTextEncoding(String::Type encoding);
/*!
* Returns \c true if defaultTextEncoding() is used.
* The default text encoding is used when setDefaultTextEncoding() has
* been called. In this case, reimplementations of FrameFactory should
* use defaultTextEncoding() on the frames (having a text encoding field)
* they create.
*
* \see defaultTextEncoding()
* \see setDefaultTextEncoding()
*/
bool isUsingDefaultTextEncoding() const;
protected:
/*!
* Constructs a frame factory. Because this is a singleton this method is
* protected, but may be used for subclasses.
*/
FrameFactory();
/*!
* Destroys the frame factory.
*/
~FrameFactory();
/*!
* This method checks for compliance to the current ID3v2 standard (2.4)
* and does nothing in the common case. However if a frame is found that
* is not compatible with the current standard, this method either updates
* the frame or indicates that it should be discarded.
*
* This method with return \c true (with or without changes to the frame) if
* this frame should be kept or \c false if it should be discarded.
*
* See the id3v2.4.0-changes.txt document for further information.
*/
virtual bool updateFrame(Frame::Header *header) const;
/*!
* Creates and prepares the frame header for createFrame().
*
* \param data data of the frame (might be modified)
* \param tagHeader the tag header
* \return {header, ok}: header is a created frame header or nullptr
* if the frame is invalid; ok is \c true if the frame is supported.
*/
std::pair prepareFrameHeader(
ByteVector &data, const Header *tagHeader) const;
/*!
* Create a frame based on \a data. \a header should be a valid frame
* header and \a tagHeader a valid ID3v2::Header instance.
*
* This method is called by the public overloaded method
* createFrame(const ByteVector &, const Header *) after creating
* \a header from verified \a data using prepareFrameHeader(), so
* this method is provided to be reimplemented in derived classes.
*/
virtual Frame *createFrame(const ByteVector &data, Frame::Header *header,
const Header *tagHeader) const;
private:
static FrameFactory factory;
class FrameFactoryPrivate;
TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE
std::unique_ptr d;
};
} // namespace ID3v2
} // namespace TagLib
#endif