frame_apic.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include "nsid3v2.h"
  2. #include "nsid3v2/header.h"
  3. #include "nsid3v2/tag.h"
  4. #include "nsid3v2/frame_utils.h"
  5. #include <api/memmgr/api_memmgr.h>
  6. #include <strsafe.h>
  7. struct ParsedPicture
  8. {
  9. uint8_t encoding; // 0 - iso-8859-1, 1 - UTF16LE, 2 - UTF16BE, 3 - UTF8
  10. const char *mime_type;
  11. size_t mime_cch;
  12. uint8_t picture_type;
  13. union
  14. {
  15. const char *as8;
  16. const wchar_t *as16;
  17. } description_data;
  18. size_t description_cch;
  19. const void *picture_data;
  20. size_t picture_bytes;
  21. };
  22. static int ParsePicture(const void *data, size_t data_len, ParsedPicture &parsed)
  23. {
  24. const uint8_t *data8 = (const uint8_t *)data;
  25. parsed.encoding = data8[0];
  26. parsed.mime_type = (const char *)&data8[1];
  27. data_len--;
  28. ParseDescription(parsed.mime_type, data_len, parsed.mime_cch);
  29. parsed.picture_type = data8[2+parsed.mime_cch];
  30. data_len--;
  31. switch(parsed.encoding)
  32. {
  33. case 0: // ISO-8859-1
  34. ParseDescription(parsed.description_data.as8, parsed.description_cch, data_len);
  35. parsed.picture_data = parsed.description_data.as8 + parsed.description_cch + 1;
  36. parsed.picture_bytes = data_len;
  37. return NErr_Success;
  38. case 1: // UTF-16
  39. ParseDescription(parsed.description_data.as16, parsed.description_cch, data_len, parsed.encoding);
  40. parsed.picture_data = parsed.description_data.as8 + parsed.description_cch + 1;
  41. parsed.picture_bytes = data_len;
  42. return NErr_Success;
  43. case 2: // UTF-16 BE
  44. ParseDescription(parsed.description_data.as16, parsed.description_cch, data_len, parsed.encoding);
  45. parsed.picture_data = parsed.description_data.as8 + parsed.description_cch + 1;
  46. parsed.picture_bytes = data_len;
  47. return NErr_Success;
  48. case 3: // UTF-8
  49. ParseDescription(parsed.description_data.as8, parsed.description_cch, data_len);
  50. parsed.picture_data = parsed.description_data.as8 + parsed.description_cch + 1;
  51. parsed.picture_bytes = data_len;
  52. return NErr_Success;
  53. }
  54. return NErr_NotImplemented;
  55. }
  56. int NSID3v2_Tag_APIC_GetPicture(const nsid3v2_tag_t t, uint8_t picture_type, void *_memmgr, wchar_t **mime_type, void **picture_data, size_t *picture_bytes)
  57. {
  58. api_memmgr *memmgr = (api_memmgr *)_memmgr;
  59. const ID3v2::Tag *tag = (const ID3v2::Tag *)t;
  60. const ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_PICTURE);
  61. while (frame)
  62. {
  63. const void *data;
  64. size_t data_len;
  65. ParsedPicture parsed;
  66. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParsePicture(data, data_len, parsed) == NErr_Success && parsed.picture_type == picture_type)
  67. {
  68. const char *type = strchr(parsed.mime_type, '/');
  69. if (type && *type)
  70. {
  71. type++;
  72. int typelen = MultiByteToWideChar(CP_ACP, 0, type, -1, 0, 0);
  73. *mime_type = (wchar_t *)memmgr->sysMalloc(typelen * sizeof(wchar_t));
  74. MultiByteToWideChar(CP_ACP, 0, type, -1, *mime_type, typelen);
  75. }
  76. else
  77. *mime_type = 0; // unknown!
  78. *picture_bytes = parsed.picture_bytes;
  79. *picture_data = memmgr->sysMalloc(parsed.picture_bytes);
  80. memcpy(*picture_data, parsed.picture_data, parsed.picture_bytes);
  81. return NErr_Success;
  82. }
  83. frame = tag->FindNextFrame(frame);
  84. }
  85. return NErr_Error;
  86. }
  87. int NSID3v2_Tag_APIC_GetFirstPicture(const nsid3v2_tag_t t, void *_memmgr, wchar_t **mime_type, void **picture_data, size_t *picture_bytes)
  88. {
  89. api_memmgr *memmgr = (api_memmgr *)_memmgr;
  90. const ID3v2::Tag *tag = (const ID3v2::Tag *)t;
  91. const ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_PICTURE);
  92. while (frame)
  93. {
  94. const void *data;
  95. size_t data_len;
  96. ParsedPicture parsed;
  97. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParsePicture(data, data_len, parsed) == NErr_Success)
  98. {
  99. const char *type = strchr(parsed.mime_type, '/');
  100. if (type && *type)
  101. {
  102. type++;
  103. int typelen = MultiByteToWideChar(CP_ACP, 0, type, -1, 0, 0);
  104. *mime_type = (wchar_t *)memmgr->sysMalloc(typelen * sizeof(wchar_t));
  105. MultiByteToWideChar(CP_ACP, 0, type, -1, *mime_type, typelen);
  106. }
  107. else
  108. *mime_type = 0; // unknown!
  109. *picture_bytes = parsed.picture_bytes;
  110. *picture_data = memmgr->sysMalloc(parsed.picture_bytes);
  111. memcpy(*picture_data, parsed.picture_data, parsed.picture_bytes);
  112. return NErr_Success;
  113. }
  114. frame = tag->FindNextFrame(frame);
  115. }
  116. return NErr_Error;
  117. }
  118. int NSID3v2_Tag_APIC_GetFrame(const nsid3v2_tag_t t, uint8_t picture_type, nsid3v2_frame_t *f)
  119. {
  120. const ID3v2::Tag *tag = (const ID3v2::Tag *)t;
  121. const ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_PICTURE);
  122. while (frame)
  123. {
  124. const void *data;
  125. size_t data_len;
  126. ParsedPicture parsed;
  127. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParsePicture(data, data_len, parsed) == NErr_Success && parsed.picture_type == picture_type)
  128. {
  129. *f = (nsid3v2_frame_t)frame;
  130. return NErr_Success;
  131. }
  132. frame = tag->FindNextFrame(frame);
  133. }
  134. return NErr_Error;
  135. }
  136. int NSID3v2_Tag_APIC_GetFirstFrame(const nsid3v2_tag_t t, nsid3v2_frame_t *f)
  137. {
  138. const ID3v2::Tag *tag = (const ID3v2::Tag *)t;
  139. const ID3v2::Frame *frame = tag->FindFirstFrame(NSID3V2_FRAME_PICTURE);
  140. while (frame)
  141. {
  142. const void *data;
  143. size_t data_len;
  144. ParsedPicture parsed;
  145. if (frame->GetData(&data, &data_len) == NErr_Success && data_len > 0 && ParsePicture(data, data_len, parsed) == NErr_Success)
  146. {
  147. *f = (nsid3v2_frame_t)frame;
  148. return NErr_Success;
  149. }
  150. frame = tag->FindNextFrame(frame);
  151. }
  152. return NErr_Error;
  153. }