id3_frame.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // The authors have released ID3Lib as Public Domain (PD) and claim no copyright,
  2. // patent or other intellectual property protection in this work. This means that
  3. // it may be modified, redistributed and used in commercial and non-commercial
  4. // software and hardware without restrictions. ID3Lib is distributed on an "AS IS"
  5. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
  6. //
  7. // The ID3Lib authors encourage improvements and optimisations to be sent to the
  8. // ID3Lib coordinator, currently Dirk Mahoney ([email protected]). Approved
  9. // submissions may be altered, and will be included and released under these terms.
  10. //
  11. // Mon Nov 23 18:34:01 1998
  12. // improved/optimized/whatever 10/30/00 JF
  13. #include <string.h>
  14. #include "id3_tag.h"
  15. ID3_Frame::ID3_Frame(ID3_FrameID id)
  16. {
  17. luint lwordsForFields = 0;
  18. version = ID3_TAGVERSION;
  19. revision = ID3_TAGREVISION;
  20. numFields = 0;
  21. fields = NULL;
  22. groupingID[0] = 0;
  23. encryptionID[0] = 0;
  24. compression = false;
  25. lwordsForFields = (((luint) ID3FN_LASTFIELDID) - 1) / (sizeof (luint) * 8);
  26. if ((((luint) ID3FN_LASTFIELDID) - 1) % (sizeof (luint) * 8) != 0)
  27. lwordsForFields++;
  28. if (fieldBits = (bitset)calloc(lwordsForFields, sizeof(*fieldBits)))
  29. {
  30. for (luint i = 0; i < lwordsForFields; i++)
  31. fieldBits[i] = 0;
  32. }
  33. else
  34. ID3_THROW (ID3E_NoMemory);
  35. SetID (id);
  36. }
  37. ID3_Frame::~ID3_Frame (void)
  38. {
  39. Clear();
  40. if (fieldBits)
  41. free(fieldBits);
  42. }
  43. void ID3_Frame::Clear (void)
  44. {
  45. if (numFields && fields)
  46. {
  47. for (luint i = 0; i < numFields; i++)
  48. delete fields[i];
  49. free(fields);
  50. fields = NULL;
  51. numFields = 0;
  52. hasChanged = true;
  53. }
  54. return ;
  55. }
  56. void ID3_Frame::SetID (ID3_FrameID id)
  57. {
  58. ID3_FrameDef *info;
  59. Clear();
  60. if (id != ID3FID_NOFRAME)
  61. {
  62. if (info = ID3_FindFrameDef (id))
  63. {
  64. frameID = id;
  65. numFields = 0;
  66. while (info->fieldDefs[numFields].id != ID3FN_NOFIELD)
  67. numFields++;
  68. if ((fields = (ID3_Field **)calloc(numFields, sizeof(ID3_Field*))) == NULL)
  69. ID3_THROW (ID3E_NoMemory);
  70. else
  71. {
  72. for (luint i = 0; i < numFields; i++)
  73. {
  74. if ((fields[i] = new ID3_Field) == NULL)
  75. ID3_THROW (ID3E_NoMemory);
  76. else
  77. {
  78. fields[i]->name = info->fieldDefs[i].id;
  79. fields[i]->type = info->fieldDefs[i].type;
  80. fields[i]->fixedLength = info->fieldDefs[i].fixedLength;
  81. fields[i]->ioVersion = info->fieldDefs[i].version;
  82. fields[i]->ioRevision = info->fieldDefs[i].revision;
  83. fields[i]->control = info->fieldDefs[i].control;
  84. fields[i]->flags = info->fieldDefs[i].flags;
  85. // tell the frame that this field is present
  86. BS_SET (fieldBits, fields[i]->name);
  87. }
  88. }
  89. hasChanged = true;
  90. }
  91. }
  92. else
  93. ID3_THROW (ID3E_InvalidFrameID);
  94. }
  95. return ;
  96. }
  97. ID3_FrameID ID3_Frame::GetID (void)
  98. {
  99. return frameID;
  100. }
  101. void ID3_Frame::SetVersion (uchar ver, uchar rev)
  102. {
  103. if (version != ver || revision != rev)
  104. hasChanged = true;
  105. version = ver;
  106. revision = rev;
  107. return ;
  108. }
  109. lsint ID3_Frame::FindField (ID3_FieldID fieldName)
  110. {
  111. if (BS_ISSET (fieldBits, fieldName))
  112. {
  113. lsint num = 0;
  114. while (num < (lsint) numFields)
  115. {
  116. if (fields[num]->name == fieldName) return num;
  117. num++;
  118. }
  119. return -1;
  120. }
  121. return 0;
  122. }
  123. ID3_Field& ID3_Frame::Field (ID3_FieldID fieldName)
  124. {
  125. luint fieldNum = FindField (fieldName);
  126. if (fieldNum == -1)
  127. ID3_THROW (ID3E_FieldNotFound);
  128. return *fields[fieldNum];
  129. }
  130. void ID3_Frame::UpdateFieldDeps (void)
  131. {
  132. for (luint i = 0; i < numFields; i++)
  133. {
  134. if (fields[i]->flags & ID3FF_ADJUSTEDBY)
  135. {
  136. switch (fields[i]->type)
  137. {
  138. case ID3FTY_BITFIELD:
  139. {
  140. //luint value = 0;
  141. // now find the field on which this
  142. // field is dependent and get a copy
  143. // of the value of that field.
  144. // then adjust the fixedLength of this
  145. // field to that value / 8.
  146. }
  147. break;
  148. }
  149. }
  150. }
  151. return ;
  152. }
  153. void ID3_Frame::UpdateStringTypes(void)
  154. {
  155. for (luint i = 0; i < numFields; i++)
  156. {
  157. if (fields[i]->flags & ID3FF_ADJUSTENC)
  158. {
  159. ID3_TextEnc enc;
  160. ID3_FieldType newType;
  161. enc = (ID3_TextEnc) Field(ID3FN_TEXTENC).Get();
  162. switch (enc)
  163. {
  164. case ID3TE_ASCII:
  165. newType = ID3FTY_ASCIISTRING;
  166. break;
  167. case ID3TE_UNICODE:
  168. newType = ID3FTY_UNICODESTRING;
  169. break;
  170. case ID3TE_UTF8:
  171. newType = ID3FTY_UTF8STRING;
  172. break;
  173. default:
  174. newType = ID3FTY_ASCIISTRING;
  175. break;
  176. }
  177. fields[i]->type = newType;
  178. }
  179. }
  180. }
  181. luint ID3_Frame::Size(void)
  182. {
  183. luint bytesUsed = 0;
  184. ID3_FrameHeader header;
  185. header.SetVersion (version, revision);
  186. bytesUsed = header.Size();
  187. if (strlen (encryptionID))
  188. bytesUsed++;
  189. if (strlen (groupingID))
  190. bytesUsed++;
  191. // this call is to tell the string fields
  192. // what they should be rendered/parsed as
  193. // (ASCII or Unicode)
  194. UpdateStringTypes();
  195. for (luint i = 0; i < numFields; i++)
  196. {
  197. fields[i]->SetVersion (version, revision);
  198. bytesUsed += fields[i]->BinSize();
  199. }
  200. return bytesUsed;
  201. }
  202. bool ID3_Frame::HasChanged (void)
  203. {
  204. if (hasChanged) return hasChanged;
  205. for (luint i = 0; i < numFields; i++)
  206. {
  207. bool changed = fields[i]->HasChanged();
  208. if (changed) return changed;
  209. }
  210. return 0;
  211. }