aboutsummaryrefslogtreecommitdiff
path: root/Src/id3v2/id3_frame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/id3v2/id3_frame.cpp')
-rw-r--r--Src/id3v2/id3_frame.cpp273
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;
+}