diff options
-rw-r--r-- | cdumb.c | 71 | ||||
-rw-r--r-- | cflac.c | 15 | ||||
-rw-r--r-- | cmp3.c | 95 | ||||
-rw-r--r-- | csid.cpp | 14 |
4 files changed, 185 insertions, 10 deletions
@@ -1,11 +1,14 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <iconv.h> #include "dumb/dumb-kode54/include/dumb.h" +#include "dumb/dumb-kode54/include/internal/it.h" #include "codec.h" #include "cdumb.h" #include "playlist.h" #include "playback.h" +#include "common.h" static int dumb_initialized; static DUH *duh; @@ -656,6 +659,67 @@ static DUH * open_module(const char *fname, const char *ext, int *start_order, i return duh; } +static const char *convstr (const char* str, int sz) { + static char out[2048]; + int i; + for (i = 0; i < sz; i++) { + if (str[i] != ' ') { + break; + } + } + if (i == sz) { + out[0] = 0; + return out; + } + + // check for utf8 (hack) + iconv_t cd; + cd = iconv_open ("utf8", "utf8"); + size_t inbytesleft = sz; + size_t outbytesleft = 2047; + char *pin = (char*)str; + char *pout = out; + memset (out, 0, sizeof (out)); + size_t res = iconv (cd, &pin, &inbytesleft, &pout, &outbytesleft); + iconv_close (cd); + if (res == 0) { + strncpy (out, str, 2047); + out[min (sz, 2047)] = 0; + return out; + } + + const char *enc = "iso8859-1"; + int latin = 0; + int rus = 0; + for (int i = 0; i < sz; i++) { + if ((str[i] >= 'A' && str[i] <= 'Z') + || str[i] >= 'a' && str[i] <= 'z') { + latin++; + } + else if (str[i] < 0) { + rus++; + } + } + if (rus > latin/2) { + // might be russian + enc = "cp1251"; + } + cd = iconv_open ("utf8", enc); + if (!cd) { + // printf ("unknown encoding: %s\n", enc); + return NULL; + } + else { + size_t inbytesleft = sz; + size_t outbytesleft = 2047; + char *pin = (char*)str; + char *pout = out; + memset (out, 0, sizeof (out)); + size_t res = iconv (cd, &pin, &inbytesleft, &pout, &outbytesleft); + iconv_close (cd); + } + return out; +} playItem_t * cdumb_insert (playItem_t *after, const char *fname) { const char *ext = fname + strlen (fname) - 1; @@ -671,7 +735,6 @@ cdumb_insert (playItem_t *after, const char *fname) { if (!duh) { return NULL; } - unload_duh (duh); playItem_t *it = malloc (sizeof (playItem_t)); memset (it, 0, sizeof (playItem_t)); it->codec = &cdumb; @@ -679,7 +742,13 @@ cdumb_insert (playItem_t *after, const char *fname) { it->tracknum = 0; it->timestart = 0; it->timeend = 0; + DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh); + if (itsd->name[0]) + { + ps_add_meta (it, "title", convstr ((char*)&itsd->name, sizeof(itsd->name))); + } after = ps_insert_item (after, it); + unload_duh (duh); return after; } @@ -181,29 +181,34 @@ cflac_init_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__Str it->tracknum = 0; if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { const FLAC__StreamMetadata_VorbisComment *vc = &metadata->data.vorbis_comment; + int title_added = 0; for (int i = 0; i < vc->num_comments; i++) { const FLAC__StreamMetadata_VorbisComment_Entry *c = &vc->comments[i]; if (c->length > 0) { char s[c->length+1]; s[c->length] = 0; memcpy (s, c->entry, c->length); - if (!strncmp (s, "ARTIST=", 7)) { + if (!strncasecmp (s, "ARTIST=", 7)) { ps_add_meta (it, "artist", s + 7); } - else if (!strncmp (s, "TITLE=", 6)) { + else if (!strncasecmp (s, "TITLE=", 6)) { ps_add_meta (it, "title", s + 6); + title_added = 1; } - else if (!strncmp (s, "ALBUM=", 6)) { + else if (!strncasecmp (s, "ALBUM=", 6)) { ps_add_meta (it, "album", s + 6); } - else if (!strncmp (s, "TRACKNUMBER=", 12)) { + else if (!strncasecmp (s, "TRACKNUMBER=", 12)) { ps_add_meta (it, "track", s + 12); } - else if (!strncmp (s, "DATE=", 5)) { + else if (!strncasecmp (s, "DATE=", 5)) { ps_add_meta (it, "date", s + 5); } } } + if (!title_added) { + ps_add_meta (it, "title", NULL); + } // ps_add_meta (it, "artist", performer); // ps_add_meta (it, "album", albumtitle); @@ -583,7 +583,7 @@ static const char *cmp3_genretbl[] = { }; static const char * -convstr (const char* str, int sz) { +convstr_id3v2_2to3 (const char* str, int sz) { static char out[2048]; const char *enc = "iso8859-1"; char *ret = out; @@ -631,8 +631,86 @@ convstr (const char* str, int sz) { return ret; } +static const char * +convstr_id3v2_4 (const char* str, int sz) { + static char out[2048]; + const char *enc = "iso8859-1"; + char *ret = out; + + // hack to add limited cp1251 recoding support + + if (*str == 3) { + // utf8 + strncpy (out, str+1, 2047); + sz--; + out[min (sz, 2047)] = 0; + return out; + } + else if (*str == 0) { + // iso8859-1 + enc = "iso8859-1"; + } + else if (*str == 1) { + enc = "UTF-16"; + } + else if (*str == 2) { + enc = "UTF-16BE"; + } + else { + return ""; + } +#if 0 + else { + int latin = 0; + int rus = 0; + for (int i = 1; i < sz; i++) { + if ((str[i] >= 'A' && str[i] <= 'Z') + || str[i] >= 'a' && str[i] <= 'z') { + latin++; + } + else if (str[i] < 0) { + rus++; + } + } + if (rus > latin/2) { + // might be russian + enc = "cp1251"; + } + } +#endif + str++; + sz--; + iconv_t cd = iconv_open ("utf8", enc); + if (!cd) { + // printf ("unknown encoding: %s\n", enc); + return NULL; + } + else { + size_t inbytesleft = sz; + size_t outbytesleft = 2047; + char *pin = (char*)str; + char *pout = out; + memset (out, 0, sizeof (out)); + size_t res = iconv (cd, &pin, &inbytesleft, &pout, &outbytesleft); + iconv_close (cd); + ret = out; + } + //printf ("decoded %s\n", out+3); + return ret; +} + const char *convstr_id3v1 (const char* str, int sz) { static char out[2048]; + int i; + for (i = 0; i < sz; i++) { + if (str[i] != ' ') { + break; + } + } + if (i == sz) { + out[0] = 0; + return out; + } // check for utf8 (hack) iconv_t cd; @@ -768,7 +846,8 @@ cmp3_read_id3v2 (playItem_t *it, FILE *fp) { } uint8_t version_major = header[3]; uint8_t version_minor = header[4]; - if (version_major > 3 || version_major < 2) { + if (version_major > 4 || version_major < 2) { + printf ("id3v2.%d.%d is unsupported (crap)\n", version_major, version_minor); return -1; // unsupported } uint8_t flags = header[5]; @@ -818,8 +897,15 @@ cmp3_read_id3v2 (playItem_t *it, FILE *fp) { } readptr += 4; // skip crc } + const char * (*convstr)(const char *, int); + if (version_major == 3) { + convstr = convstr_id3v2_2to3; + } + else { + convstr = convstr_id3v2_4; + } while (readptr - tag < size - 4) { - if (version_major == 3) { + if (version_major == 3 || version_major == 4) { char frameid[5]; memcpy (frameid, readptr, 4); frameid[4] = 0; @@ -916,6 +1002,9 @@ cmp3_read_id3v2 (playItem_t *it, FILE *fp) { } readptr += sz; } + else { + printf ("id3v2.%d (unsupported!)\n", version_minor); + } } if (!title_added) { ps_add_meta (it, "title", NULL); @@ -377,8 +377,17 @@ csid_insert (playItem_t *after, const char *fname) { SidTuneInfo sidinfo; tune->getInfo (sidinfo); int i = sidinfo.numberOfInfoStrings; + int title_added = 0; if (i >= 1 && sidinfo.infoString[0] && sidinfo.infoString[0][0]) { - ps_add_meta (it, sidinfo.songs > 1 ? "album" : "title", convstr (sidinfo.infoString[0])); + const char *meta; + if (sidinfo.songs > 1) { + meta = "album"; + } + else { + meta = "title"; + title_added = 1; + } + ps_add_meta (it, meta, convstr (sidinfo.infoString[0])); } if (i >= 2 && sidinfo.infoString[1] && sidinfo.infoString[1][0]) { ps_add_meta (it, "artist", convstr (sidinfo.infoString[1])); @@ -396,6 +405,9 @@ csid_insert (playItem_t *after, const char *fname) { char trk[10]; snprintf (trk, 10, "%d", s+1); ps_add_meta (it, "track", trk); + if (!title_added) { + ps_add_meta (it, "title", NULL); + } after = ps_insert_item (after, it); } } |