* Use internal music metadata functions intead of taglib.
1) Taglib does not support MP4 or WMA/ASF without hacking it in there. 2) Taglib is C++, so it's nice to remove that dependency. * Use embedded album art where available.
This commit is contained in:
262
tagutils/tagutils-misc.c
Normal file
262
tagutils/tagutils-misc.c
Normal file
@ -0,0 +1,262 @@
|
||||
//=========================================================================
|
||||
// FILENAME : tagutils-misc.c
|
||||
// DESCRIPTION : Misc routines for supporting tagutils
|
||||
//=========================================================================
|
||||
// Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
|
||||
//=========================================================================
|
||||
|
||||
/* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* Language
|
||||
**************************************************************************/
|
||||
|
||||
#define MAX_ICONV_BUF 1024
|
||||
|
||||
typedef enum {
|
||||
ICONV_OK,
|
||||
ICONV_TRYNEXT,
|
||||
ICONV_FATAL
|
||||
} iconv_result;
|
||||
|
||||
static iconv_result
|
||||
do_iconv(const char* to_ces, const char* from_ces,
|
||||
char *inbuf, size_t inbytesleft,
|
||||
char *outbuf_orig, size_t outbytesleft_orig)
|
||||
{
|
||||
size_t rc;
|
||||
iconv_result ret = ICONV_OK;
|
||||
|
||||
size_t outbytesleft = outbytesleft_orig - 1;
|
||||
char* outbuf = outbuf_orig;
|
||||
|
||||
iconv_t cd = iconv_open(to_ces, from_ces);
|
||||
|
||||
if(cd == (iconv_t)-1)
|
||||
{
|
||||
return ICONV_FATAL;
|
||||
}
|
||||
rc = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
|
||||
if(rc == (size_t)-1)
|
||||
{
|
||||
if(errno == E2BIG)
|
||||
{
|
||||
ret = ICONV_FATAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ICONV_TRYNEXT;
|
||||
memset(outbuf_orig, '\0', outbytesleft_orig);
|
||||
}
|
||||
}
|
||||
iconv_close(cd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define N_LANG_ALT 8
|
||||
struct {
|
||||
char *lang;
|
||||
char *cpnames[N_LANG_ALT];
|
||||
} iconv_map[] = {
|
||||
{ "JA", { "ISO-8859-1", "CP932", "ISO8859-1", "CP950", "CP936", 0 } },
|
||||
{ "ZH_CN", { "ISO-8859-1", "CP936", "CP950", "CP932", 0 } },
|
||||
{ "ZH_TW", { "ISO-8859-1", "CP950", "CP936", "CP932", 0 } },
|
||||
{ 0, { 0 } }
|
||||
};
|
||||
static int lang_index = -1;
|
||||
|
||||
static int
|
||||
_lang2cp(char *lang)
|
||||
{
|
||||
int cp;
|
||||
|
||||
if(!lang || lang[0] == '\0')
|
||||
return -1;
|
||||
for(cp = 0; iconv_map[cp].lang; cp++)
|
||||
{
|
||||
if(!strcasecmp(iconv_map[cp].lang, lang))
|
||||
return cp;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static unsigned char*
|
||||
_get_utf8_text(const id3_ucs4_t* native_text)
|
||||
{
|
||||
unsigned char *utf8_text = NULL;
|
||||
char *in, *in8, *iconv_buf;
|
||||
iconv_result rc;
|
||||
int i, n;
|
||||
|
||||
in = (char*)id3_ucs4_latin1duplicate(native_text);
|
||||
if(!in)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
in8 = (char*)id3_ucs4_utf8duplicate(native_text);
|
||||
if(!in8)
|
||||
{
|
||||
free(in);
|
||||
goto out;
|
||||
}
|
||||
|
||||
iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char));
|
||||
if(!iconv_buf)
|
||||
{
|
||||
free(in); free(in8);
|
||||
goto out;
|
||||
}
|
||||
|
||||
i = lang_index;
|
||||
// (1) try utf8 -> default
|
||||
rc = do_iconv(iconv_map[i].cpnames[0], "UTF-8", in8, strlen(in8), iconv_buf, MAX_ICONV_BUF);
|
||||
if(rc == ICONV_OK)
|
||||
{
|
||||
utf8_text = (unsigned char*)in8;
|
||||
free(iconv_buf);
|
||||
}
|
||||
else if(rc == ICONV_TRYNEXT)
|
||||
{
|
||||
// (2) try default -> utf8
|
||||
rc = do_iconv("UTF-8", iconv_map[i].cpnames[0], in, strlen(in), iconv_buf, MAX_ICONV_BUF);
|
||||
if(rc == ICONV_OK)
|
||||
{
|
||||
utf8_text = (unsigned char*)iconv_buf;
|
||||
}
|
||||
else if(rc == ICONV_TRYNEXT)
|
||||
{
|
||||
// (3) try other encodes
|
||||
for(n = 1; n < N_LANG_ALT && iconv_map[i].cpnames[n]; n++)
|
||||
{
|
||||
rc = do_iconv("UTF-8", iconv_map[i].cpnames[n], in, strlen(in), iconv_buf, MAX_ICONV_BUF);
|
||||
if(rc == ICONV_OK)
|
||||
{
|
||||
utf8_text = (unsigned char*)iconv_buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!utf8_text)
|
||||
{
|
||||
// cannot iconv
|
||||
utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
|
||||
free(iconv_buf);
|
||||
}
|
||||
}
|
||||
free(in8);
|
||||
}
|
||||
free(in);
|
||||
|
||||
out:
|
||||
if(!utf8_text)
|
||||
{
|
||||
utf8_text = (unsigned char*)strdup("UNKNOWN");
|
||||
}
|
||||
|
||||
return utf8_text;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vc_scan(struct song_metadata *psong, const char *comment, const size_t length)
|
||||
{
|
||||
char strbuf[1024];
|
||||
|
||||
if(length > (sizeof(strbuf) - 1))
|
||||
{
|
||||
DPRINTF(E_ERROR, L_SCANNER, "Vorbis Comment too long\n");
|
||||
return;
|
||||
}
|
||||
strncpy(strbuf, comment, length);
|
||||
strbuf[length] = '\0';
|
||||
|
||||
// ALBUM, ARTIST, PUBLISHER, COPYRIGHT, DISCNUMBER, ISRC, EAN/UPN, LABEL, LABELNO,
|
||||
// LICENSE, OPUS, SOURCEMEDIA, TITLE, TRACKNUMBER, VERSION, ENCODED-BY, ENCODING,
|
||||
// -- foollowing tags are muliples
|
||||
// COMPOSER, ARRANGER, LYRICIST, AUTHOR, CONDUCTOR, PERFORMER, ENSEMBLE, PART
|
||||
// PARTNUMBER, GENRE, DATE, LOCATION, COMMENT
|
||||
if(!strncasecmp(strbuf, "ALBUM=", 6))
|
||||
{
|
||||
psong->album = strdup(strbuf + 6);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "ARTIST=", 7))
|
||||
{
|
||||
psong->contributor[ROLE_ARTIST] = strdup(strbuf + 7);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "ARTISTSORT=", 11))
|
||||
{
|
||||
psong->contributor_sort[ROLE_ARTIST] = strdup(strbuf + 11);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "TITLE=", 6))
|
||||
{
|
||||
psong->title = strdup(strbuf + 6);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "TRACKNUMBER=", 12))
|
||||
{
|
||||
psong->track = atoi(strbuf + 12);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "DISCNUMBER=", 11))
|
||||
{
|
||||
psong->disc = atoi(strbuf + 11);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "GENRE=", 6))
|
||||
{
|
||||
psong->genre = strdup(strbuf + 6);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "DATE=", 5))
|
||||
{
|
||||
if(length >= (5 + 10) &&
|
||||
isdigit(strbuf[5 + 0]) && isdigit(strbuf[5 + 1]) && ispunct(strbuf[5 + 2]) &&
|
||||
isdigit(strbuf[5 + 3]) && isdigit(strbuf[5 + 4]) && ispunct(strbuf[5 + 5]) &&
|
||||
isdigit(strbuf[5 + 6]) && isdigit(strbuf[5 + 7]) && isdigit(strbuf[5 + 8]) && isdigit(strbuf[5 + 9]))
|
||||
{
|
||||
// nn-nn-yyyy
|
||||
strbuf[5 + 10] = '\0';
|
||||
psong->year = atoi(strbuf + 5 + 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
// year first. year is at most 4 digit.
|
||||
strbuf[5 + 4] = '\0';
|
||||
psong->year = atoi(strbuf + 5);
|
||||
}
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "COMMENT=", 8))
|
||||
{
|
||||
psong->comment = strdup(strbuf + 8);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "MUSICBRAINZ_ALBUMID=", 20))
|
||||
{
|
||||
psong->musicbrainz_albumid = strdup(strbuf + 20);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "MUSICBRAINZ_TRACKID=", 20))
|
||||
{
|
||||
psong->musicbrainz_trackid = strdup(strbuf + 20);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "MUSICBRAINZ_TRACKID=", 20))
|
||||
{
|
||||
psong->musicbrainz_trackid = strdup(strbuf + 20);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "MUSICBRAINZ_ARTISTID=", 21))
|
||||
{
|
||||
psong->musicbrainz_artistid = strdup(strbuf + 21);
|
||||
}
|
||||
else if(!strncasecmp(strbuf, "MUSICBRAINZ_ALBUMARTISTID=", 26))
|
||||
{
|
||||
psong->musicbrainz_albumartistid = strdup(strbuf + 26);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user