id3dump.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. id3dump: Print ID3 tags of files, scanned using libmpg123.
  3. copyright 2007 by the mpg123 project - free software under the terms of the LGPL 2.1
  4. see COPYING and AUTHORS files in distribution or http://mpg123.org
  5. initially written by Thomas Orgis
  6. */
  7. #include "mpg123.h"
  8. #include <string.h>
  9. #include "stdio.h"
  10. #include "sys/types.h"
  11. /* Helper for v1 printing, get these strings their zero byte. */
  12. void safe_print(char* name, char *data, size_t size)
  13. {
  14. char safe[31];
  15. if(size>30) return;
  16. memcpy(safe, data, size);
  17. safe[size] = 0;
  18. printf("%s: %s\n", name, safe);
  19. }
  20. /* Print out ID3v1 info. */
  21. void print_v1(mpg123_id3v1 *v1)
  22. {
  23. safe_print("Title", v1->title, sizeof(v1->title));
  24. safe_print("Artist", v1->artist, sizeof(v1->artist));
  25. safe_print("Album", v1->album, sizeof(v1->album));
  26. safe_print("Year", v1->year, sizeof(v1->year));
  27. safe_print("Comment", v1->comment, sizeof(v1->comment));
  28. printf("Genre: %i", v1->genre);
  29. }
  30. /* Split up a number of lines separated by \n, \r, both or just zero byte
  31. and print out each line with specified prefix. */
  32. void print_lines(const char* prefix, mpg123_string *inlines)
  33. {
  34. size_t i;
  35. int hadcr = 0, hadlf = 0;
  36. char *lines = NULL;
  37. char *line = NULL;
  38. size_t len = 0;
  39. if(inlines != NULL && inlines->fill)
  40. {
  41. lines = inlines->p;
  42. len = inlines->fill;
  43. }
  44. else return;
  45. line = lines;
  46. for(i=0; i<len; ++i)
  47. {
  48. if(lines[i] == '\n' || lines[i] == '\r' || lines[i] == 0)
  49. {
  50. char save = lines[i]; /* saving, changing, restoring a byte in the data */
  51. if(save == '\n') ++hadlf;
  52. if(save == '\r') ++hadcr;
  53. if((hadcr || hadlf) && hadlf % 2 == 0 && hadcr % 2 == 0) line = "";
  54. if(line)
  55. {
  56. lines[i] = 0;
  57. printf("%s%s\n", prefix, line);
  58. line = NULL;
  59. lines[i] = save;
  60. }
  61. }
  62. else
  63. {
  64. hadlf = hadcr = 0;
  65. if(line == NULL) line = lines+i;
  66. }
  67. }
  68. }
  69. /* Print out the named ID3v2 fields. */
  70. void print_v2(mpg123_id3v2 *v2)
  71. {
  72. print_lines("Title: ", v2->title);
  73. print_lines("Artist: ", v2->artist);
  74. print_lines("Album: ", v2->album);
  75. print_lines("Year: ", v2->year);
  76. print_lines("Comment: ", v2->comment);
  77. print_lines("Genre: ", v2->genre);
  78. }
  79. /* Print out all stored ID3v2 fields with their 4-character IDs. */
  80. void print_raw_v2(mpg123_id3v2 *v2)
  81. {
  82. size_t i;
  83. for(i=0; i<v2->texts; ++i)
  84. {
  85. char id[5];
  86. char lang[4];
  87. memcpy(id, v2->text[i].id, 4);
  88. id[4] = 0;
  89. memcpy(lang, v2->text[i].lang, 3);
  90. lang[3] = 0;
  91. if(v2->text[i].description.fill)
  92. printf("%s language(%s) description(%s)\n", id, lang, v2->text[i].description.p);
  93. else printf("%s language(%s)\n", id, lang);
  94. print_lines(" ", &v2->text[i].text);
  95. }
  96. for(i=0; i<v2->extras; ++i)
  97. {
  98. char id[5];
  99. memcpy(id, v2->extra[i].id, 4);
  100. id[4] = 0;
  101. printf( "%s description(%s)\n",
  102. id,
  103. v2->extra[i].description.fill ? v2->extra[i].description.p : "" );
  104. print_lines(" ", &v2->extra[i].text);
  105. }
  106. for(i=0; i<v2->comments; ++i)
  107. {
  108. char id[5];
  109. char lang[4];
  110. memcpy(id, v2->comment_list[i].id, 4);
  111. id[4] = 0;
  112. memcpy(lang, v2->comment_list[i].lang, 3);
  113. lang[3] = 0;
  114. printf( "%s description(%s) language(%s): \n",
  115. id,
  116. v2->comment_list[i].description.fill ? v2->comment_list[i].description.p : "",
  117. lang );
  118. print_lines(" ", &v2->comment_list[i].text);
  119. }
  120. }
  121. int main(int argc, char **argv)
  122. {
  123. int i;
  124. mpg123_handle* m;
  125. if(argc < 2)
  126. {
  127. fprintf(stderr, "\nI will print some ID3 tag fields of MPEG audio files.\n");
  128. fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]);
  129. return -1;
  130. }
  131. mpg123_init();
  132. m = mpg123_new(NULL, NULL);
  133. for(i=1; i < argc; ++i)
  134. {
  135. mpg123_id3v1 *v1;
  136. mpg123_id3v2 *v2;
  137. int meta;
  138. if(mpg123_open(m, argv[i]) != MPG123_OK)
  139. {
  140. fprintf(stderr, "Cannot open %s: %s\n", argv[i], mpg123_strerror(m));
  141. continue;
  142. }
  143. mpg123_scan(m);
  144. meta = mpg123_meta_check(m);
  145. if(meta & MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK)
  146. {
  147. printf("Tag data on %s:\n", argv[i]);
  148. printf("\n==== ID3v1 ====\n");
  149. if(v1 != NULL) print_v1(v1);
  150. printf("\n==== ID3v2 ====\n");
  151. if(v2 != NULL) print_v2(v2);
  152. printf("\n==== ID3v2 Raw frames ====\n");
  153. if(v2 != NULL) print_raw_v2(v2);
  154. }
  155. else printf("Nothing found for %s.\n", argv[i]);
  156. mpg123_close(m);
  157. }
  158. mpg123_delete(m);
  159. mpg123_exit();
  160. return 0;
  161. }