mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
273 lines
5 KiB
C++
273 lines
5 KiB
C++
// The authors have released ID3Lib as Public Domain (PD) and claim no copyright,
|
|
// patent or other intellectual property protection in this work. This means that
|
|
// it may be modified, redistributed and used in commercial and non-commercial
|
|
// software and hardware without restrictions. ID3Lib is distributed on an "AS IS"
|
|
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
|
//
|
|
// The ID3Lib authors encourage improvements and optimisations to be sent to the
|
|
// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved
|
|
// submissions may be altered, and will be included and released under these terms.
|
|
//
|
|
// Mon Nov 23 18:34:01 1998
|
|
// improved/optimized/whatever 10/30/00 JF
|
|
|
|
|
|
#include <string.h>
|
|
#include "id3_tag.h"
|
|
|
|
|
|
ID3_Frame::ID3_Frame(ID3_FrameID id)
|
|
{
|
|
luint lwordsForFields = 0;
|
|
|
|
version = ID3_TAGVERSION;
|
|
revision = ID3_TAGREVISION;
|
|
numFields = 0;
|
|
fields = NULL;
|
|
groupingID[0] = 0;
|
|
encryptionID[0] = 0;
|
|
compression = false;
|
|
|
|
lwordsForFields = (((luint) ID3FN_LASTFIELDID) - 1) / (sizeof (luint) * 8);
|
|
|
|
if ((((luint) ID3FN_LASTFIELDID) - 1) % (sizeof (luint) * 8) != 0)
|
|
lwordsForFields++;
|
|
|
|
if (fieldBits = (bitset)calloc(lwordsForFields, sizeof(*fieldBits)))
|
|
{
|
|
for (luint i = 0; i < lwordsForFields; i++)
|
|
fieldBits[i] = 0;
|
|
}
|
|
else
|
|
ID3_THROW (ID3E_NoMemory);
|
|
|
|
SetID (id);
|
|
}
|
|
|
|
|
|
ID3_Frame::~ID3_Frame (void)
|
|
{
|
|
Clear();
|
|
|
|
if (fieldBits)
|
|
free(fieldBits);
|
|
}
|
|
|
|
|
|
void ID3_Frame::Clear (void)
|
|
{
|
|
if (numFields && fields)
|
|
{
|
|
for (luint i = 0; i < numFields; i++)
|
|
delete fields[i];
|
|
|
|
free(fields);
|
|
|
|
fields = NULL;
|
|
numFields = 0;
|
|
hasChanged = true;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
void ID3_Frame::SetID (ID3_FrameID id)
|
|
{
|
|
ID3_FrameDef *info;
|
|
|
|
Clear();
|
|
|
|
if (id != ID3FID_NOFRAME)
|
|
{
|
|
if (info = ID3_FindFrameDef (id))
|
|
{
|
|
frameID = id;
|
|
|
|
numFields = 0;
|
|
|
|
while (info->fieldDefs[numFields].id != ID3FN_NOFIELD)
|
|
numFields++;
|
|
|
|
if ((fields = (ID3_Field **)calloc(numFields, sizeof(ID3_Field*))) == NULL)
|
|
ID3_THROW (ID3E_NoMemory);
|
|
else
|
|
{
|
|
for (luint i = 0; i < numFields; i++)
|
|
{
|
|
if ((fields[i] = new ID3_Field) == NULL)
|
|
ID3_THROW (ID3E_NoMemory);
|
|
else
|
|
{
|
|
fields[i]->name = info->fieldDefs[i].id;
|
|
fields[i]->type = info->fieldDefs[i].type;
|
|
fields[i]->fixedLength = info->fieldDefs[i].fixedLength;
|
|
fields[i]->ioVersion = info->fieldDefs[i].version;
|
|
fields[i]->ioRevision = info->fieldDefs[i].revision;
|
|
fields[i]->control = info->fieldDefs[i].control;
|
|
fields[i]->flags = info->fieldDefs[i].flags;
|
|
|
|
// tell the frame that this field is present
|
|
BS_SET (fieldBits, fields[i]->name);
|
|
}
|
|
}
|
|
|
|
hasChanged = true;
|
|
}
|
|
}
|
|
else
|
|
ID3_THROW (ID3E_InvalidFrameID);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
ID3_FrameID ID3_Frame::GetID (void)
|
|
{
|
|
return frameID;
|
|
}
|
|
|
|
|
|
void ID3_Frame::SetVersion (uchar ver, uchar rev)
|
|
{
|
|
if (version != ver || revision != rev)
|
|
hasChanged = true;
|
|
|
|
version = ver;
|
|
revision = rev;
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
lsint ID3_Frame::FindField (ID3_FieldID fieldName)
|
|
{
|
|
if (BS_ISSET (fieldBits, fieldName))
|
|
{
|
|
lsint num = 0;
|
|
while (num < (lsint) numFields)
|
|
{
|
|
if (fields[num]->name == fieldName) return num;
|
|
num++;
|
|
}
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
ID3_Field& ID3_Frame::Field (ID3_FieldID fieldName)
|
|
{
|
|
luint fieldNum = FindField (fieldName);
|
|
|
|
if (fieldNum == -1)
|
|
ID3_THROW (ID3E_FieldNotFound);
|
|
|
|
return *fields[fieldNum];
|
|
}
|
|
|
|
|
|
void ID3_Frame::UpdateFieldDeps (void)
|
|
{
|
|
for (luint i = 0; i < numFields; i++)
|
|
{
|
|
if (fields[i]->flags & ID3FF_ADJUSTEDBY)
|
|
{
|
|
switch (fields[i]->type)
|
|
{
|
|
case ID3FTY_BITFIELD:
|
|
{
|
|
//luint value = 0;
|
|
|
|
// now find the field on which this
|
|
// field is dependent and get a copy
|
|
// of the value of that field.
|
|
// then adjust the fixedLength of this
|
|
// field to that value / 8.
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
void ID3_Frame::UpdateStringTypes(void)
|
|
{
|
|
for (luint i = 0; i < numFields; i++)
|
|
{
|
|
if (fields[i]->flags & ID3FF_ADJUSTENC)
|
|
{
|
|
ID3_TextEnc enc;
|
|
ID3_FieldType newType;
|
|
|
|
enc = (ID3_TextEnc) Field(ID3FN_TEXTENC).Get();
|
|
|
|
switch (enc)
|
|
{
|
|
case ID3TE_ASCII:
|
|
newType = ID3FTY_ASCIISTRING;
|
|
break;
|
|
|
|
case ID3TE_UNICODE:
|
|
newType = ID3FTY_UNICODESTRING;
|
|
break;
|
|
|
|
case ID3TE_UTF8:
|
|
newType = ID3FTY_UTF8STRING;
|
|
break;
|
|
|
|
default:
|
|
newType = ID3FTY_ASCIISTRING;
|
|
break;
|
|
}
|
|
|
|
fields[i]->type = newType;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
luint ID3_Frame::Size(void)
|
|
{
|
|
luint bytesUsed = 0;
|
|
ID3_FrameHeader header;
|
|
|
|
header.SetVersion (version, revision);
|
|
bytesUsed = header.Size();
|
|
|
|
if (strlen (encryptionID))
|
|
bytesUsed++;
|
|
|
|
if (strlen (groupingID))
|
|
bytesUsed++;
|
|
|
|
// this call is to tell the string fields
|
|
// what they should be rendered/parsed as
|
|
// (ASCII or Unicode)
|
|
UpdateStringTypes();
|
|
|
|
for (luint i = 0; i < numFields; i++)
|
|
{
|
|
fields[i]->SetVersion (version, revision);
|
|
bytesUsed += fields[i]->BinSize();
|
|
}
|
|
|
|
return bytesUsed;
|
|
}
|
|
|
|
|
|
bool ID3_Frame::HasChanged (void)
|
|
{
|
|
if (hasChanged) return hasChanged;
|
|
|
|
for (luint i = 0; i < numFields; i++)
|
|
{
|
|
bool changed = fields[i]->HasChanged();
|
|
if (changed) return changed;
|
|
}
|
|
return 0;
|
|
}
|