📄 tag.cpp
字号:
// $Id: tag.cpp,v 1.2 2001/01/16 21:08:01 robert Exp $
// id3lib: a C++ library for creating and manipulating id3v1/v2 tags
// Copyright 1999, 2000 Scott Thomas Haug
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Library General Public License as published by
// the Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// 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 Library General Public
// License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this library; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// The id3lib authors encourage improvements and optimisations to be sent to
// the id3lib coordinator. Please see the README file for details on where to
// send such submissions. See the AUTHORS file for a list of people who have
// contributed to id3lib. See the ChangeLog file for a list of changes to
// id3lib. These files are distributed with id3lib at
// http://download.sourceforge.net/id3lib/
#include "id3config.h"
#include "tag.h"
#include "readers.h"
#include "writers.h"
#include "tag_impl.h"
#include "strings.h"
#include "utils.h"
using namespace dami;
/** \mainpage id3lib Library Documentation
**
** \section tutorial Quick Tutorial
**
** This tutorial will quickly get you up and running with id3lib.
**
** \subsection download Downloading id3lib
**
** First, id3lib must be a part of your development environment. The latest
** files can always be downloaded from the <a href="http://id3lib.sourceforge.net">id3lib homepage</a>.
**
** \subsection include Preparing your source code
**
** To use the basic functionality of id3lib in your C++ code, a single
** \c #include is necessary.
**
** \code
** #include <id3/tag.h>
** \endcode
**
** There are other files that must be included to access more advanced
** functionality, but this will do most of the core functionality.
**
** \subsection creation Creating a tag
**
** Almost all functionality occurs via an ID3_Tag object. An ID3_Tag object
** basically encapsulates two things: a collection of ID3_Frame objects and
** file information. The goal is to populate an ID3_Tag object with ID3_Frame
** objects, and the easiest way to do this is to associate the tag with a
** file. This is done primarily via the ID3_Tag constructor, like so:
**
** \code
** ID3_Tag myTag("song.mp3");
** \endcode
**
** This constructor links, or associates, the object \c tag with the file
** "song.mp3". In doing so, the tagging information from "song.mp3" is parsed
** and added to \c tag. This association can also be accomplished by creating
** an empty tag and making an explicit call to Link().
**
** \code
** ID3_Tag myTag;
** myTag.Link("song.mp3");
** \endcode
**
** The default behavior of Link() is to parse all possible tagging information
** and convert it into ID3v2 frames. The tagging information parsed can be
** limited to a particular type (or types) of tag by passing an ID3_TagType
** (or combination of ID3_TagType's). For example, to read only the ID3v1
** tag, pass in the constant ID3TT_ID3V1.
**
** \code
** myTag.Link("song.mp3", ID3TT_ID3V1);
** \endcode
**
** Another example would be to read in all tags that could possibly appear at
** the end of the file.
**
** \code
** myTag.Link("song.mp3", ID3TT_ID3V1 | ID3TT_LYRICS3V2 | ID3TT_MUSICMATCH);
** \endcode
**
** \section accessing Accessing the Tag Data
**
** After linking with a file, the object \c myTag now contains some or all of
** the tagging information present in the file "song.mp3", represented as
** ID3v2 frames. How can that information be accessed? There a variety of
** ways to do this. One is to iterate through all the frames in the tag.
**
** \code
** // use an std::auto_ptr here to handle object cleanup automatically
** ID3_Tag::Iterator* iter = tag.createIterator();
** ID3_Frame* myFrame = NULL;
** while (NULL != (myFrame = iter->GetNext())
** {
** // do something with myFrame
** }
** delete iter;
** \endcode
**
** Another way to access tagging information is by searching for specific
** frames using the Find() method. For example, the album frame can be found
** in the following manner:
**
** \code
** ID3_Frame* myFrame = myTag.Find(ID3FID_ALBUM);
** if (NULL != myFrame)
** {
** // do something with myFrame
** }
** \endcode
**
** The Find() method can be used to search for frames with specific
** information. For example, the following code can be used to find the frame
** with the title "Nirvana".
**
** \code
** ID3_Frame* myFrame = myTag.Find(ID3FID_TITLE, ID3FN_TEXT, "Nirvana")));
** if (NULL != myFrame)
** {
** // do something with myFrame
** }
** \endcode
**
** As indicated, the Find() method will return a NULL pointer if no such frame
** can be found. If more than one frame meets the search criteria, subsequent
** calls to Find() with the same parameters will return the other matching
** frames. The Find() method is guaranteed to return all matching frames
** before it wraps around to return the first matching frame.
**
** All ID3_Frame objects are comprised of a collection of ID3_Field objects.
** These fields can represent text, numbers, or binary data. As with frames,
** fields can be accessed in a variety of manners. The fields of a frame
** can be iterated over in much the same manner of the frames of a tag.
**
** \code
** // use an std::auto_ptr here to handle object cleanup automatically
** ID3_Frame::Iterator* iter = myFrame->createIterator();
** ID3_Field* myField = NULL;
** while (NULL != (myField = iter->GetNext())
** {
** // do something with myField
** }
** delete iter;
** \endcode
**
** If you know which field type you're looking for, you can access it
** directly.
**
** \code
** ID3_Field* myField = myFrame->GetField(ID3FN_TEXT);
** while (NULL != myField)
** {
** // do something with myField
** }
** \endcode
**
** This documentation currently does not include a list of all possible field
** types, nor does it include all possible frame types and the fields they
** contain. The source code is the best resource for that information.
**
** \todo List all field and frame types.
**
** The ID3_Field represents a single piece of data within an ID3v2 frame. As
** mentioned, an ID3_Field can represent three possible types of
** data: integers, binary data, and test strings. The type of a particular
** field object is immutable; it is determined at the time of its construction
** (almost always when a frame is constructed) and can't be changed. If in
** doubt, the field type can be accessed through its GetType() method.
**
** Having an ID3_Field object isn't much use if you cannot access and/or
** alter its data. Luckily, the id3lib API provides overloaded \c Set and
** \c Get methods for all data types.
**
** If the field is an integer, the following methods can be used to access
** the data.
**
** \code
** uint32 val = myField->Get();
** myField->Set(5);
** (*myField) = 10;
** \endcode
**
** All text data is accessed in a slightly different manner. The following
** code example best illustrates these differences.
**
** \code
** // for ascii strings
** char str1[1024];
** const char* p1 = "My String";
** const char* p2 = "My Other String";
**
** myField->Set(p1);
** (*myField) = p2; // equivalent to Set
**
** myField->Get(str1, 1024); // copies up to 1024 bytes of the field data into str1
** p1 = myField->GetRawText(); // returns a pointer to the internal string
** \endcode
**
** Binary data is similar to text data, except that its base type is a pointer
** to an unsigned, rather than a signed, char.
**
** \code
** // for binary strings
** uchar data[1024];
** const uchar *p1 = getBinaryData(); // not an id3lib function
** size_t size = getBinarySize(); // not an id3lib function
**
** myField->Set(p1, size);
**
** myField->Get(data, 1024); // copies up to 1024 bytes of the field data into str1
** p1 = myField->GetRawBinary(); // returns a pointer to the internal string
** \endcode
**
** \section updating Updating the Tag
**
** When you're ready to save your changes back to the file, a single call to
** Update() is sufficient.
**
** \code
** tag.Update();
** \endcode
**
**/
/** \class ID3_Tag tag.h id3/tag.h
** \brief The representative class of an id3 tag.
**
** The ID3_Tag is, at its simplest, a container for ID3v2 frames. At its
** most complicated, it's a kitchen-sink, monolithic "catch-all" class for
** handling almost every task associated with creating, parsing, rendering,
** and manipulating digital audio data using id3lib.
**
** This simple \c #include does it all. In order to read an existing tag, do
** the following:
**
** \code
** ID3_Tag myTag;
** myTag.Link("something.mp3");
** \endcode
**
** That is all there is to it. Now all you have to do is use the Find()
** method to locate the frames you are interested in is the following:
**
** \code
** ID3_Frame* myFrame = myTag.Find(ID3FID_TITLE);
** if (NULL != myFrame)
** {
** const char* title = myFrame->GetField(ID3FN_TEXT)->GetText();
** cout << "Title: " << title << endl;
** }
** \endcode
**
** This code snippet locates the ID3FID_TITLE frame and displays the
** text field.
**
** When using the ID3_Tag::Link() method, you automatically gain access to any
** ID3v1/1.1, ID3v2, Lyrics3 v2.0, and MusicMatch tags present in the file.
** The class will automaticaly parse and convert any of these foreign tag
** formats into ID3v2 tags. Also, id3lib will correctly parse any correctly
** formatted 'CDM' frames from the unreleased ID3v2 2.01 draft specification.
**
** \author Dirk Mahoney
** \version $Id: tag.cpp,v 1.2 2001/01/16 21:08:01 robert Exp $
** \sa ID3_Frame
** \sa ID3_Field
** \sa ID3_Err
**/
/** Default constructor; it can accept an optional filename as a parameter.
**
** If this file exists, it will be opened and all id3lib-supported tags will
** be parsed and converted to ID3v2 if necessary. After the conversion, the
** file will remain unchanged, and will continue to do so until you use the
** Update() method on the tag (if you choose to Update() at all).
**
** \param name The filename of the mp3 file to link to
**/
ID3_Tag::ID3_Tag(const char *name)
: _impl(new ID3_TagImpl(name))
{
}
/** Standard copy constructor.
**
** \param tag What is copied into this tag
**/
ID3_Tag::ID3_Tag(const ID3_Tag &tag)
: _impl(new ID3_TagImpl(tag))
{
}
ID3_Tag::~ID3_Tag()
{
delete _impl;
}
/** Clears the object and disassociates it from any files.
**
** Frees any resources for which the object is responsible, including all
** frames and files. After a call to Clear(), the object can be used
** again for any new or existing tag.
**/
void ID3_Tag::Clear()
{
_impl->Clear();
}
/** Indicates whether the tag has been altered since the last parse, render,
** or update.
**
** If you have a tag linked to a file, you do not need this method since the
** Update() method will check for changes before writing the tag.
**
** This method is primarily intended as a status indicator for applications
** and for applications that use the Parse() and Render() methods.
**
** Setting a field, changed the ID of an attached frame, setting or grouping
** or encryption IDs, and clearing a frame or field all constitute a change
** to the tag, as do calls to the SetUnsync(), SetExtendedHeader(), and
** SetPadding() methods.
**
** \code
** if (myTag.HasChanged())
** {
** // render and output the tag
** }
** \endcode
**
** \return Whether or not the tag has been altered.
**/
bool ID3_Tag::HasChanged() const
{
return _impl->HasChanged();
}
/** Returns an over estimate of the number of bytes required to store a
** binary version of a tag.
**
** When using Render() to render a binary tag to a
** memory buffer, first use the result of this call to allocate a buffer of
** unsigned chars.
**
** \code
** if (myTag.HasChanged())
** {
** size_t tagSize; = myTag.Size();
** if (tagSize > 0)
** {
** uchar *buffer = new uchar[tagSize];
** if (NULL != buffer)
** {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -