diff options
Diffstat (limited to 'Src/id3v2/id3_frame.cpp')
-rw-r--r-- | Src/id3v2/id3_frame.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/Src/id3v2/id3_frame.cpp b/Src/id3v2/id3_frame.cpp new file mode 100644 index 00000000..dd22f43b --- /dev/null +++ b/Src/id3v2/id3_frame.cpp @@ -0,0 +1,273 @@ +// 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; +} |