/* id3dump: Print ID3 tags of files, scanned using libmpg123. This is example code only sensible to be considered in the public domain. Initially written by Thomas Orgis. */ #include "mpg123.h" #include #include "stdio.h" #include "sys/types.h" /** Helper for v1 printing, get these strings their zero byte. */ void safe_print(char* name, char *data, size_t size) { char safe[31]; if(size>30) return; memcpy(safe, data, size); safe[size] = 0; printf("%s: %s\n", name, safe); } /** Print out ID3v1 info. */ void print_v1(mpg123_id3v1 *v1) { safe_print("Title", v1->title, sizeof(v1->title)); safe_print("Artist", v1->artist, sizeof(v1->artist)); safe_print("Album", v1->album, sizeof(v1->album)); safe_print("Year", v1->year, sizeof(v1->year)); safe_print("Comment", v1->comment, sizeof(v1->comment)); printf("Genre: %i", v1->genre); } /** Split up a number of lines separated by \\n, \\r, both or just zero byte and print out each line with specified prefix. */ void print_lines(const char* prefix, mpg123_string *inlines) { size_t i; int hadcr = 0, hadlf = 0; char *lines = NULL; char *line = NULL; size_t len = 0; if(inlines != NULL && inlines->fill) { lines = inlines->p; len = inlines->fill; } else return; line = lines; for(i=0; ititle); print_lines("Artist: ", v2->artist); print_lines("Album: ", v2->album); print_lines("Year: ", v2->year); print_lines("Comment: ", v2->comment); print_lines("Genre: ", v2->genre); } /** Print out all stored ID3v2 fields with their 4-character IDs. */ void print_raw_v2(mpg123_id3v2 *v2) { size_t i; for(i=0; itexts; ++i) { char id[5]; char lang[4]; memcpy(id, v2->text[i].id, 4); id[4] = 0; memcpy(lang, v2->text[i].lang, 3); lang[3] = 0; if(v2->text[i].description.fill) printf("%s language(%s) description(%s)\n", id, lang, v2->text[i].description.p); else printf("%s language(%s)\n", id, lang); print_lines(" ", &v2->text[i].text); } for(i=0; iextras; ++i) { char id[5]; memcpy(id, v2->extra[i].id, 4); id[4] = 0; printf( "%s description(%s)\n", id, v2->extra[i].description.fill ? v2->extra[i].description.p : "" ); print_lines(" ", &v2->extra[i].text); } for(i=0; icomments; ++i) { char id[5]; char lang[4]; memcpy(id, v2->comment_list[i].id, 4); id[4] = 0; memcpy(lang, v2->comment_list[i].lang, 3); lang[3] = 0; printf( "%s description(%s) language(%s): \n", id, v2->comment_list[i].description.fill ? v2->comment_list[i].description.p : "", lang ); print_lines(" ", &v2->comment_list[i].text); } } /** The whole operation. */ int main(int argc, char **argv) { int i; mpg123_handle* m; if(argc < 2) { fprintf(stderr, "\nI will print some ID3 tag fields of MPEG audio files.\n"); fprintf(stderr, "\nUsage: %s \n\n", argv[0]); return -1; } #if MPG123_API_VERSION < 46 // Newer versions of the library don't need that anymore, but it is safe // to have the no-op call present for compatibility with old versions. mpg123_init(); #endif m = mpg123_new(NULL, NULL); for(i=1; i < argc; ++i) { mpg123_id3v1 *v1; mpg123_id3v2 *v2; int meta; if(mpg123_open(m, argv[i]) != MPG123_OK) { fprintf(stderr, "Cannot open %s: %s\n", argv[i], mpg123_strerror(m)); continue; } mpg123_scan(m); meta = mpg123_meta_check(m); if(meta & MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK) { printf("Tag data on %s:\n", argv[i]); printf("\n==== ID3v1 ====\n"); if(v1 != NULL) print_v1(v1); printf("\n==== ID3v2 ====\n"); if(v2 != NULL) print_v2(v2); printf("\n==== ID3v2 Raw frames ====\n"); if(v2 != NULL) print_raw_v2(v2); } else printf("Nothing found for %s.\n", argv[i]); mpg123_close(m); } mpg123_delete(m); return 0; }