frame_id.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "nsid3v2.h"
  2. #include "nsid3v2/header.h"
  3. #include "nsid3v2/tag.h"
  4. #include "nsid3v2/frame_utils.h"
  5. #include "nu/ByteReader.h"
  6. #include "nu/ByteWriter.h"
  7. #include "nx/nxstring.h"
  8. struct ParsedID
  9. {
  10. ParsedString owner;
  11. const void *identifier_data;
  12. size_t identifier_byte_length;
  13. };
  14. static int ParseID(const void *data, size_t data_len, ParsedID &parsed)
  15. {
  16. int ret;
  17. if (data_len < 1)
  18. return NErr_Insufficient;
  19. bytereader_value_t byte_reader;
  20. bytereader_init(&byte_reader, data, data_len);
  21. /* owner is always latin-1 */
  22. ret = ParseNullTerminatedString(&byte_reader, 0, parsed.owner);
  23. if (ret != NErr_Success)
  24. return ret;
  25. parsed.identifier_data = bytereader_pointer(&byte_reader);
  26. parsed.identifier_byte_length = bytereader_size(&byte_reader);
  27. return NErr_Success;
  28. }
  29. int NSID3v2_Tag_ID_Find(const nsid3v2_tag_t t, const char *owner, nsid3v2_frame_t *out_frame, int text_flags)
  30. {
  31. const ID3v2::Tag *tag = (const ID3v2::Tag *)t;
  32. if (!tag)
  33. return NErr_Empty;
  34. const ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_ID);
  35. while (frame)
  36. {
  37. const void *data;
  38. size_t data_len;
  39. ParsedID parsed;
  40. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParseID(data, data_len, parsed) == NErr_Success && (!owner || DescriptionMatches(parsed.owner, owner, text_flags)))
  41. {
  42. *out_frame = (nsid3v2_frame_t)frame;
  43. return NErr_Success;
  44. }
  45. frame = tag->FindNextFrame(frame);
  46. }
  47. return NErr_Empty;
  48. }
  49. int NSID3v2_Frame_ID_Get(nsid3v2_frame_t f, nx_string_t *owner, const void **id_data, size_t *length, int text_flags)
  50. {
  51. const ID3v2::Frame *frame = (const ID3v2::Frame *)f;
  52. if (frame)
  53. {
  54. const void *data;
  55. size_t data_len;
  56. ParsedID parsed;
  57. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParseID(data, data_len, parsed) == NErr_Success)
  58. {
  59. if (owner)
  60. {
  61. int ret = NXStringCreateFromParsedString(owner, parsed.owner, text_flags);
  62. if (ret != NErr_Success)
  63. return ret;
  64. }
  65. *id_data = parsed.identifier_data;
  66. *length = parsed.identifier_byte_length;
  67. return NErr_Success;
  68. }
  69. }
  70. return NErr_Empty;
  71. }
  72. int NSID3v2_Tag_ID_Get(const nsid3v2_tag_t t, const char *owner, const void **id_data, size_t *length, int text_flags)
  73. {
  74. const ID3v2::Tag *tag = (const ID3v2::Tag *)t;
  75. if (!tag)
  76. return NErr_Empty;
  77. ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_ID);
  78. while (frame)
  79. {
  80. const void *data;
  81. size_t data_len;
  82. ParsedID parsed;
  83. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParseID(data, data_len, parsed) == NErr_Success && (!owner || DescriptionMatches(parsed.owner, owner, text_flags)))
  84. {
  85. *id_data = parsed.identifier_data;
  86. *length = parsed.identifier_byte_length;
  87. return NErr_Success;
  88. }
  89. frame = tag->FindNextFrame(frame);
  90. }
  91. return NErr_Empty;
  92. }
  93. /* ---------------- Setters ---------------- */
  94. int NSID3v2_Frame_ID_Set(nsid3v2_frame_t f, const char *owner, const void *id_data, size_t length, int text_flags)
  95. {
  96. ID3v2::Frame *frame = (ID3v2::Frame *)f;
  97. if (frame)
  98. {
  99. size_t owner_length=owner?strlen(owner):0;
  100. /* TODO: overflow check */
  101. size_t total_size = owner_length + 1 + length;
  102. void *data;
  103. size_t data_len;
  104. int ret = frame->NewData(total_size, &data, &data_len);
  105. if (ret != NErr_Success)
  106. return ret;
  107. bytewriter_s byte_writer;
  108. bytewriter_init(&byte_writer, data, data_len);
  109. bytewriter_write_n(&byte_writer, owner, owner_length);
  110. bytewriter_write_u8(&byte_writer, 0); // write null terminator separately, in case owner is NULL
  111. bytewriter_write_n(&byte_writer, id_data, length);
  112. return NErr_Success;
  113. }
  114. return NErr_Empty;
  115. }
  116. int NSID3v2_Tag_ID_Set(nsid3v2_tag_t t, const char *owner, const void *id_data, size_t length, int text_flags)
  117. {
  118. ID3v2::Tag *tag = (ID3v2::Tag *)t;
  119. if (!tag)
  120. return NErr_Empty;
  121. ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_ID);
  122. while (frame)
  123. {
  124. const void *data;
  125. size_t data_len;
  126. ParsedID parsed;
  127. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParseID(data, data_len, parsed) == NErr_Success && (!owner || DescriptionMatches(parsed.owner, owner, text_flags)))
  128. {
  129. break;
  130. }
  131. frame = tag->FindNextFrame(frame);
  132. }
  133. if (!frame)
  134. {
  135. frame = tag->NewFrame(NSID3V2_FRAME_ID, 0);
  136. if (!frame)
  137. return NErr_OutOfMemory;
  138. tag->AddFrame(frame);
  139. }
  140. return NSID3v2_Frame_ID_Set((nsid3v2_frame_t)frame, owner, id_data, length, text_flags);
  141. }