diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-01-02 12:45:39 +0100 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-01-02 12:45:39 +0100 |
commit | d90852fcc0ce41ce30d39a7d50e8156863c4a7b9 (patch) | |
tree | 770532f7c0e2f46f4674975db2f0649503a80214 /junklib.c | |
parent | 3d295609190fa94f6a156a6e08aa3d646c628179 (diff) |
extended id3v2 reader to support more frame types; fixed few bugs
Diffstat (limited to 'junklib.c')
-rw-r--r-- | junklib.c | 181 |
1 files changed, 172 insertions, 9 deletions
@@ -24,8 +24,8 @@ #include "utf8.h" #include "plugins.h" -//#define trace(...) { fprintf(stderr, __VA_ARGS__); } -#define trace(fmt,...) +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) @@ -790,7 +790,11 @@ junk_read_id3v2 (playItem_t *it, DB_FILE *fp) { char *band = NULL; char *track = NULL; char *title = NULL; + char *year = NULL; char *vendor = NULL; + char *comment = NULL; + char *copyright = NULL; + char *genre = NULL; int err = 0; while (readptr - tag <= size - 4) { if (version_major == 3 || version_major == 4) { @@ -934,7 +938,64 @@ junk_read_id3v2 (playItem_t *it, DB_FILE *fp) { id3v2_string_read (version_major, &str[0], sz, unsync, readptr); album = convstr (str, sz); } + else if (!strcmp (frameid, "TYER")) { + if (sz > 1000) { + err = 1; + break; // too large + } + char str[sz+2]; + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); + year = convstr (str, sz); + } + else if (!strcmp (frameid, "TCOP")) { + if (sz > 1000) { + err = 1; + break; // too large + } + char str[sz+2]; + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); + copyright = convstr (str, sz); + trace ("TCOP: %s\n", copyright); + } + else if (!strcmp (frameid, "TCON")) { + if (sz > 1000) { + err = 1; + break; // too large + } + char str[sz+2]; + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); + genre = convstr (str, sz); + trace ("TCON: %s\n", genre); + } else if (!strcmp (frameid, "COMM")) { + if (sz < 4) { + trace ("COMM frame is too short, skipped\n"); + readptr += sz; // bad tag + continue; + } + uint8_t enc = readptr[0]; + char lang[4] = {readptr[1], readptr[2], readptr[3], 0}; + if (strcmp (lang, "eng")) { + trace ("non-english comment, skip\n"); + readptr += sz; + continue; + } + trace ("COMM enc is: %d\n", (int)enc); + trace ("COMM language is: %s\n", lang); + char *descr = readptr+4; + trace ("COMM descr: %s\n", descr); + if (!strcmp (descr, "iTunNORM")) { + // ignore itunes normalization metadata + readptr += sz; + continue; + } + int dlen = strlen(descr)+1; + int s = sz - 4 - dlen; + char str[s + 3]; + id3v2_string_read (version_major, &str[1], s, unsync, descr+dlen); + str[0] = enc; + comment = convstr (str, s+1); + trace ("COMM text: %s\n", comment); } else if (!strcmp (frameid, "TXXX")) { if (sz < 2) { @@ -1001,59 +1062,127 @@ junk_read_id3v2 (playItem_t *it, DB_FILE *fp) { // trace ("found id3v2.2 frame: %s, size=%d\n", frameid, sz); if (!strcmp (frameid, "TEN")) { char str[sz+2]; - memcpy (str, readptr, sz); + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); str[sz] = 0; vendor = convstr (str, sz); } else if (!strcmp (frameid, "TT2")) { if (sz > 1000) { + readptr += sz; continue; } char str[sz+2]; - memcpy (str, readptr, sz); + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); str[sz] = 0; title = convstr (str, sz); } else if (!strcmp (frameid, "TAL")) { if (sz > 1000) { + readptr += sz; continue; } char str[sz+2]; - memcpy (str, readptr, sz); + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); str[sz] = 0; album = convstr (str, sz); } else if (!strcmp (frameid, "TP1")) { if (sz > 1000) { + readptr += sz; continue; } char str[sz+2]; - memcpy (str, readptr, sz); + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); str[sz] = 0; artist = convstr (str, sz); } else if (!strcmp (frameid, "TP2")) { if (sz > 1000) { + readptr += sz; continue; } char str[sz+2]; - memcpy (str, readptr, sz); + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); str[sz] = 0; band = convstr (str, sz); } else if (!strcmp (frameid, "TRK")) { if (sz > 1000) { + readptr += sz; continue; } char str[sz+2]; - memcpy (str, readptr, sz); + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); str[sz] = 0; track = convstr (str, sz); } + else if (!strcmp (frameid, "TYE")) { + if (sz > 1000) { + readptr += sz; + continue; + } + char str[sz+2]; + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); + str[sz] = 0; + year = convstr (str, sz); + } + else if (!strcmp (frameid, "TCR")) { + if (sz > 1000) { + readptr += sz; + continue; + } + char str[sz+2]; + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); + str[sz] = 0; + copyright = convstr (str, sz); + } + else if (!strcmp (frameid, "TCO")) { + if (sz > 1000) { + readptr += sz; + continue; + } + char str[sz+2]; + //memcpy (str, readptr, sz); + id3v2_string_read (version_major, &str[0], sz, unsync, readptr); + str[sz] = 0; + genre = convstr (str, sz); + } + else if (!strcmp (frameid, "COM")) { + if (sz > 1000) { + readptr += sz; + continue; + } + uint8_t enc = readptr[0]; + char lang[4] = {readptr[1], readptr[2], readptr[3], 0}; + if (strcmp (lang, "eng")) { + trace ("non-english comment, skip\n"); + readptr += sz; + continue; + } + trace ("COM enc is: %d\n", (int)enc); + trace ("COM language is: %s\n", lang); + char *descr = readptr+4; + trace ("COM descr: %s\n", descr); + int dlen = strlen(descr)+1; + int s = sz - 4 - dlen; + char str[s + 3]; + id3v2_string_read (version_major, &str[1], s, unsync, descr+dlen); + str[0] = enc; + comment = convstr (str, s+1); + trace ("COM text: %s\n", comment); + } readptr += sz; } else { -// trace ("id3v2.%d (unsupported!)\n", version_minor); + trace ("id3v2.%d (unsupported!)\n", version_minor); } } if (!err) { @@ -1077,10 +1206,44 @@ junk_read_id3v2 (playItem_t *it, DB_FILE *fp) { pl_add_meta (it, "title", title); free (title); } + if (genre) { + if (genre[0] == '(') { + const char *v1genre = NULL; + // find matching parenthesis + const char *p = &genre[1]; + while (*p && *p != ')') { + p++; + } + if (p > &genre[1]) { + int g = atoi (&genre[1]); + if (g < 148) { + v1genre = junk_genretbl[g]; + } + } + if (v1genre) { + free (genre); + genre = strdup (v1genre); + } + } + pl_add_meta (it, "genre", genre); + free (genre); + } + if (year) { + pl_add_meta (it, "year", year); + free (year); + } + if (copyright) { + pl_add_meta (it, "copyright", copyright); + free (copyright); + } if (vendor) { pl_add_meta (it, "vendor", vendor); free (vendor); } + if (comment) { + pl_add_meta (it, "comment", comment); + free (comment); + } if (!title) { pl_add_meta (it, "title", NULL); } |