tag.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "tag.h"
  2. #include <string.h> // for strnlen
  3. #include "nsid3v1.h"
  4. #include "foundation/error.h"
  5. #include "nu/ByteReader.h"
  6. #include "nu/ByteWriter.h"
  7. #ifdef __APPLE__
  8. inline static size_t id3v1_strnlen(const char *s, size_t n)
  9. {
  10. const char *p=(const char *)memchr(s, 0, n);
  11. return p?p-s:n;
  12. }
  13. #else // __APPLE__
  14. inline static size_t id3v1_strnlen(const char *s, size_t n)
  15. {
  16. return strnlen(s, n);
  17. }
  18. #endif
  19. ID3v1::Tag::Tag()
  20. {
  21. }
  22. void ID3v1::Tag::New()
  23. {
  24. header[0]='T';
  25. header[1]='A';
  26. header[2]='G';
  27. memset(title, 0, 30);
  28. memset(artist, 0, 30);
  29. memset(album, 0, 30);
  30. memset(year, 0, 30);
  31. memset(comment, 0, 30);
  32. track=0;
  33. genre=0;
  34. }
  35. // Deprecated, bytereader class can now handle n-number of bytes
  36. static void GetAndFillNumberOfBytes(bytereader_value_t byte_reader, int bytes, const void *data, char *destination)
  37. {
  38. for (int i = 0; i < bytes; i++)
  39. {
  40. destination[i] = bytereader_read_u8(&byte_reader);
  41. }
  42. }
  43. const char *ID3v1::Tag::GetHeader(void) const { return header; }
  44. const char *ID3v1::Tag::GetTitle(void) const { return title; }
  45. const char *ID3v1::Tag::GetArtist(void) const { return artist; }
  46. const char *ID3v1::Tag::GetAlbum(void) const { return album; }
  47. const char *ID3v1::Tag::GetYear(void) const { return year; }
  48. const char *ID3v1::Tag::GetComment(void) const { return comment; }
  49. uint8_t ID3v1::Tag::GetTrack(void) const { return track; }
  50. uint8_t ID3v1::Tag::GetGenre(void) const { return genre; }
  51. //unsigned int ID3v1::Tag::GetTitleLength(void) { return ( strlen(title) <= 30 ) ? strlen(title) : 30; }
  52. size_t ID3v1::Tag::GetHeaderLength(void) const { return id3v1_strnlen(header, 3); }
  53. size_t ID3v1::Tag::GetTitleLength(void) const { return id3v1_strnlen(title, 30); }
  54. size_t ID3v1::Tag::GetArtistLength(void) const { return id3v1_strnlen(artist, 30); }
  55. size_t ID3v1::Tag::GetAlbumLength(void) const { return id3v1_strnlen(album, 30); }
  56. size_t ID3v1::Tag::GetYearLength(void) const { return id3v1_strnlen(year, 4); }
  57. size_t ID3v1::Tag::GetCommentLength(void) const { return id3v1_strnlen(comment, 30); }
  58. int ID3v1::Tag::Parse(const void *data, size_t len)
  59. {
  60. if (len < 128)
  61. return NErr_NeedMoreData;
  62. bytereader_value_t byte_reader;
  63. bytereader_init(&byte_reader, data, len);
  64. // Get header
  65. bytereader_read_n(&byte_reader, header, 3);
  66. // Get title
  67. bytereader_read_n(&byte_reader, title, 30);
  68. // Get artist
  69. bytereader_read_n(&byte_reader, artist, 30);
  70. // Get album
  71. bytereader_read_n(&byte_reader, album, 30);
  72. // Get year
  73. bytereader_read_n(&byte_reader, year, 4);
  74. // Get comments
  75. bytereader_read_n(&byte_reader, comment, 30);
  76. // Get genre
  77. genre = bytereader_read_u8(&byte_reader);
  78. // Check for the presence of track # inside of the comments field at offset position 29 & 30
  79. if (comment[28] == 0 && comment[29] != 0)
  80. {
  81. track = comment[29];
  82. }
  83. else
  84. track = 0;
  85. return NErr_Success;
  86. }
  87. /* copies source_bytes characters to destination, and fills up the remaining (up to destination_length) with null */
  88. static void id3v1_strncpyn(char *destination, size_t destination_length, const char *source, size_t source_bytes)
  89. {
  90. // make sure we don't write too much
  91. if (source_bytes > destination_length)
  92. source_bytes = destination_length;
  93. memcpy(destination, source, source_bytes);
  94. memset(destination+source_bytes, 0, destination_length-source_bytes); // zero remainder of string
  95. }
  96. void ID3v1::Tag::SetTitle(const char *new_title, size_t length)
  97. {
  98. id3v1_strncpyn(title, 30, new_title, length);
  99. }
  100. void ID3v1::Tag::SetArtist(const char *new_artist, size_t length)
  101. {
  102. id3v1_strncpyn(artist, 30, new_artist, length);
  103. }
  104. void ID3v1::Tag::SetAlbum(const char *new_album, size_t length)
  105. {
  106. id3v1_strncpyn(album, 30, new_album, length);
  107. }
  108. void ID3v1::Tag::SetYear(const char *new_year, size_t length)
  109. {
  110. id3v1_strncpyn(year, 4, new_year, length);
  111. }
  112. void ID3v1::Tag::SetComment(const char *new_comment, size_t length)
  113. {
  114. id3v1_strncpyn(comment, 28, new_comment, length);
  115. }
  116. void ID3v1::Tag::SetTrack(uint8_t new_track)
  117. {
  118. track = new_track;
  119. }
  120. void ID3v1::Tag::SetGenre(uint8_t new_genre)
  121. {
  122. genre = new_genre;
  123. }
  124. int ID3v1::Tag::Serialize(void *data, size_t len)
  125. {
  126. if (len < 128)
  127. return NErr_Insufficient;
  128. bytewriter_s byte_writer;
  129. bytewriter_init(&byte_writer, data, len);
  130. bytewriter_write_n(&byte_writer, header, 3);
  131. bytewriter_write_n(&byte_writer, title, 30);
  132. bytewriter_write_n(&byte_writer, artist, 30);
  133. bytewriter_write_n(&byte_writer, album, 30);
  134. bytewriter_write_n(&byte_writer, year, 4);
  135. bytewriter_write_n(&byte_writer, comment, 28);
  136. bytewriter_write_u8(&byte_writer, 0);
  137. bytewriter_write_u8(&byte_writer, track);
  138. bytewriter_write_u8(&byte_writer, genre);
  139. return NErr_Success;
  140. }