blob: d28ef30c1a78e340ffa5a2e480deddee1d490ff5 [file] [log] [blame]
// $Id: frame.cpp,v 1.35 2002/08/10 10:42:42 t1mpy Exp $
// id3lib: a C++ library for creating and manipulating id3v1/v2 tags
// Copyright 1999, 2000 Scott Thomas Haug
// Copyright 2002 Thijmen Klok (thijmen@id3lib.org)
// 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/
#if defined HAVE_CONFIG_H
#include <config.h>
#endif
//#include "frame.h"
#include "readers.h"
#include "frame_impl.h"
/** \class ID3_Frame frame.h id3/frame.h
** \brief The representative class of an id3v2 frame.
**
** id3lib defines frames in a funny way. Using some nice c++ conventions,
** ID3_FrameImpl class objects appear to be quite polymorphic; that is, they
** can take on many forms. The same ID3_FrameImpl class provides the
** facilities for the implementation of a complex APIC frame and for a simple
** text frame.
**
** @author Dirk Mahoney
** @version $Id: frame.cpp,v 1.35 2002/08/10 10:42:42 t1mpy Exp $
** @see ID3_Tag
** @see ID3_Field
** @see ID3_Err
**/
/** Default constructor; accepts as a default parameter the type of frame
** to create.
**
** The parameter which will internally set the frame's structure. See
** SetID() for more details.
**
** @param id The type of frame to create
** @see ID3_FrameID
** @see SetID
**/
ID3_Frame::ID3_Frame(ID3_FrameID id)
: _impl(new ID3_FrameImpl(id))
{
}
ID3_Frame::ID3_Frame(const ID3_Frame& frame)
: _impl(new ID3_FrameImpl(frame))
{
}
ID3_Frame::~ID3_Frame()
{
delete _impl;
}
/** Clears the frame of all data and resets the frame such that it can take
** on the form of any id3v2 frame that id3lib supports.
**
** @see ID3_Tag::Clear
**/
void ID3_Frame::Clear()
{
_impl->Clear();
}
/** Returns the type of frame that the object represents.
**
** Useful in conjunction with ID3_Tag::Find() method
**
** @returns The type, or id, of the frame
** @see ID3_Tag::Find
**/
ID3_FrameID ID3_Frame::GetID() const
{
return _impl->GetID();
}
/** Establishes the internal structure of an ID3_FrameImpl object so
** that it represents the id3v2 frame indicated by the parameter
**
** Given an ID3_FrameID (a list of which is found in &lt;id3/field.h&gt;),
** SetID() will structure the object according to the
** frame you wish to implement.
**
** Either using this call or via the constructor, this must be the first
** command performed on an ID3_FrameImpl object.
**
** \code
** myFrame.SetID(ID3FID_TITLE);
** \endcode
**
** @param id The type of frame this frame should be set to
** @see ID3_FrameID
**/
bool ID3_Frame::SetID(ID3_FrameID id)
{
return _impl->SetID(id);
}
bool ID3_Frame::SetSpec(ID3_V2Spec spec)
{
return _impl->SetSpec(spec);
}
ID3_V2Spec ID3_Frame::GetSpec() const
{
return _impl->GetSpec();
}
/** Returns a pointer to the frame's internal field indicated by the
** parameter.
**
** \code
** ID3_TextEnc enc;
** enc = (ID3_TextEnc) myFrame.GetField(ID3FN_TEXTENC)->Get();
** \endcode
**
** @param name The name of the field to be retrieved
** @returns A reference to the desired field
**/
ID3_Field& ID3_Frame::Field(ID3_FieldID fieldName) const
{
return *this->GetField(fieldName);
}
ID3_Field* ID3_Frame::GetField(ID3_FieldID fieldName) const
{
return _impl->GetField(fieldName);
}
size_t ID3_Frame::NumFields() const
{
return _impl->NumFields();
}
/*
ID3_Field* ID3_Frame::GetFieldNum(size_t index) const
{
return _impl->GetFieldNum(index);
}
*/
size_t ID3_Frame::Size()
{
return _impl->Size();
}
bool ID3_Frame::HasChanged() const
{
return _impl->HasChanged();
}
ID3_Frame& ID3_Frame::operator=( const ID3_Frame &rFrame )
{
if (this != &rFrame)
{
*_impl = rFrame;
}
return *this;
}
const char* ID3_Frame::GetDescription(ID3_FrameID id)
{
return ID3_FrameImpl::GetDescription(id);
}
const char* ID3_Frame::GetDescription() const
{
return _impl->GetDescription();
}
const char* ID3_Frame::GetTextID() const
{
return _impl->GetTextID();
}
bool ID3_Frame::Parse(ID3_Reader& reader)
{
try // Klenotic: Catch errors and return false instead of crashing.
{
return _impl->Parse(reader);
}
catch(...)
{
ID3D_WARNING( "ID3_Frame::Parse: call to _impl->Parse() failed");
return false;
}
}
void ID3_Frame::Render(ID3_Writer& writer) const
{
_impl->Render(writer);
}
bool ID3_Frame::Contains(ID3_FieldID id) const
{
return _impl->Contains(id);
}
/** Sets the compression flag within the frame. When the compression flag is
** is set, compression will be attempted. However, the frame might not
** actually be compressed after it is rendered if the "compressed" data is
** no smaller than the "uncompressed" data.
**/
bool ID3_Frame::SetCompression(bool b)
{
return _impl->SetCompression(b);
}
/** Returns whether or not the compression flag is set. After parsing a tag,
** this will indicate whether or not the frame was compressed. After
** rendering a tag, however, it does not actually indicate if the frame is
** compressed rendering. It only indicates whether or not compression was
** attempted. A frame will not be compressed, even whent the compression
** flag is set, if the "compressed" data is no smaller than the
** "uncompressed" data.
**/
bool ID3_Frame::GetCompression() const
{
return _impl->GetCompression();
}
size_t ID3_Frame::GetDataSize() const
{
return _impl->GetDataSize();
}
bool ID3_Frame::SetEncryptionID(uchar id)
{
return _impl->SetEncryptionID(id);
}
uchar ID3_Frame::GetEncryptionID() const
{
return _impl->GetEncryptionID();
}
bool ID3_Frame::SetGroupingID(uchar id)
{
return _impl->SetGroupingID(id);
}
uchar ID3_Frame::GetGroupingID() const
{
return _impl->GetGroupingID();
}
namespace
{
class IteratorImpl : public ID3_Frame::Iterator
{
ID3_FrameImpl::iterator _cur;
ID3_FrameImpl::iterator _end;
public:
IteratorImpl(ID3_FrameImpl& frame)
: _cur(frame.begin()), _end(frame.end())
{
}
ID3_Field* GetNext()
{
ID3_Field* next = NULL;
while (next == NULL && _cur != _end)
{
next = *_cur;
++_cur;
}
return next;
}
};
class ConstIteratorImpl : public ID3_Frame::ConstIterator
{
ID3_FrameImpl::const_iterator _cur;
ID3_FrameImpl::const_iterator _end;
public:
ConstIteratorImpl(ID3_FrameImpl& frame)
: _cur(frame.begin()), _end(frame.end())
{
}
const ID3_Field* GetNext()
{
ID3_Field* next = NULL;
while (next == NULL && _cur != _end)
{
next = *_cur;
++_cur;
}
return next;
}
};
}
ID3_Frame::Iterator*
ID3_Frame::CreateIterator()
{
return new IteratorImpl(*_impl);
}
ID3_Frame::ConstIterator*
ID3_Frame::CreateIterator() const
{
return new ConstIteratorImpl(*_impl);
}