diff --git a/admin-root/config.xml b/admin-root/config.xml index 7e6ca38e..8d617fbf 100644 --- a/admin-root/config.xml +++ b/admin-root/config.xml @@ -116,6 +116,13 @@
+ + MP3 Tag Codepage + + What codepage non-utf mp3 tags should be converted from (default: ISO-8859-1) + + text + Process Playlists @@ -335,4 +342,4 @@ text
- \ No newline at end of file + diff --git a/src/conf.c b/src/conf.c index c568c758..abe53154 100644 --- a/src/conf.c +++ b/src/conf.c @@ -146,6 +146,7 @@ static CONF_ELEMENTS conf_elements[] = { { 0, 0, CONF_T_INT,"scanning","case_sensitive" }, { 0, 0, CONF_T_INT,"scanning","follow_symlinks" }, { 0, 0, CONF_T_INT,"scanning","skip_first" }, + { 0, 0, CONF_T_STRING,"scanning","mp3_tag_codepage" }, { 0, 0, CONF_T_INT,"scan","correct_order" }, /* remapped values */ diff --git a/src/scan-mp3.c b/src/scan-mp3.c index 6636d25d..c9fbaeb5 100644 --- a/src/scan-mp3.c +++ b/src/scan-mp3.c @@ -303,6 +303,7 @@ int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { char *tmp; int got_numeric_genre; int rating; + char *conversion_codepage; pid3file=id3_file_open(file,ID3_FILE_MODE_READONLY); if(!pid3file) { @@ -322,6 +323,9 @@ int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { DPRINTF(E_SPAM,L_SCAN,"Starting mp3 tag scan\n"); + conversion_codepage = conf_alloc_string("scanning","mp3_tag_codepage", + "ISO-8859-1"); + index=0; while((pid3frame=id3_tag_findframe(pid3tag,"",index))) { used=0; @@ -345,20 +349,15 @@ int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { native_text=id3_field_getstrings(&pid3frame->fields[1],0); if(native_text) { - /* FIXME: I didn't understand what was happening here. - * this should really be a switch to evaluate latin1 - * tags as native codepage. Not only is this hackish, - * it's just plain wrong. - */ have_utf8=1; - if(conf_get_int("general","latin1_tags",0)) { - utf8_text=(char *)id3_ucs4_latin1duplicate(native_text); - } else { - utf8_text=(char *)id3_ucs4_utf8duplicate(native_text); - } + utf8_text = util_xtoutf8_alloc(native_text,strlen(native_text), + conversion_codepage); - if(utf8_text) - mem_register(utf8_text,0); + if(!utf8_text) { + utf8_text = (char*)id3_ucs4_latin1duplicate(native_text); + if(utf8_text) + mem_register(utf8_text,0); + } if(!strcmp(pid3frame->id,"TIT2")) { /* Title */ used=1; @@ -509,6 +508,7 @@ int scan_mp3_get_mp3tags(char *file, MP3FILE *pmp3) { index++; } + free(conversion_codepage); id3_file_close(pid3file); DPRINTF(E_DBG,L_SCAN,"Got id3 tag successfully\n"); return TRUE; @@ -766,7 +766,7 @@ void scan_mp3_get_frame_count(IOHANDLE hfile, SCAN_FRAMEINFO *pfi) { DPRINTF(E_SPAM,L_SCAN,"Seeking to %ld\n",pos); io_setpos(hfile,pos,SEEK_SET); - + len = sizeof(frame_buffer); if(!io_read(hfile,frame_buffer,&len) || (len != sizeof(frame_buffer))) { /* check for valid frame */ diff --git a/src/util.c b/src/util.c index 5fc62851..cbaa7319 100644 --- a/src/util.c +++ b/src/util.c @@ -102,19 +102,19 @@ int util_utf16_byte_len(unsigned char *utf16) { unsigned char *util_utf8toutf16_alloc(unsigned char *utf8) { - char *utf16; - + unsigned char *utf16; + utf16 = calloc(1,strlen((char*)utf8) * 4 + 1); if(util_xtoy(utf16,strlen((char*)utf8) * 4 + 1, utf8, strlen((char*)utf8),"UTF-8","UTF-16LE")) { return utf16; } - + free(utf16); return NULL; } unsigned char *util_utf16toutf8_alloc(unsigned char *utf16, int slen) { - char *utf8; + unsigned char *utf8; utf8=calloc(1, slen * 2 + 1); if(util_xtoy(utf8,slen * 2 + 1,utf16,slen,"UTF-16LE","UTF-8")) { @@ -125,17 +125,33 @@ unsigned char *util_utf16toutf8_alloc(unsigned char *utf16, int slen) { return NULL; } +unsigned char *util_xtoutf8_alloc(unsigned char *x, int slen, char *from) { + unsigned char *utf8; + + utf8 = calloc(1, slen * 4 + 1); + if(util_xtoy(utf8,slen * 4 + 1, x, slen, from, "UTF-8")) { + return utf8; + } + free(utf8); + return NULL; +} + int util_xtoy(unsigned char *dbuffer, int dlen, unsigned char *sbuffer, int slen, char *from, char *to) { iconv_t iv; size_t csize; + size_t st_dlen = dlen; + size_t st_slen = slen; + memset(dbuffer,0,dlen); + iv=iconv_open(to,from); if(iv == (iconv_t)-1) { DPRINTF(E_LOG,L_MISC,"iconv error: iconv_open failed with %d\n",errno); } - csize = iconv(iv,&sbuffer,&slen,&dbuffer,&dlen); + csize = iconv(iv,(const char **)&sbuffer,&st_slen, + (char **)&dbuffer,&st_dlen); if(csize == (size_t)-1) { switch(errno) { case EILSEQ: @@ -397,6 +413,7 @@ char *util_vasprintf(char *fmt, va_list ap) { if(!outbuf) DPRINTF(E_FATAL,L_MISC,"Could not allocate buffer in vasprintf\n"); + ap2=ap; /* shut up lint warnings */ VA_COPY(ap2,ap); while(1) { diff --git a/src/util.h b/src/util.h index ff601ac8..8e4317a6 100644 --- a/src/util.h +++ b/src/util.h @@ -46,6 +46,7 @@ extern unsigned char *util_utf16touft8_alloc(unsigned char *utf16, int slen); extern int util_utf8toutf16(unsigned char *utf16, int dlen, unsigned char *utf8, int slen); extern int util_utf16toutf8(unsigned char *utf8, int dlen, unsigned char *utf16, int slen); extern int util_xtoy(unsigned char *dbuffer, int dlen, unsigned char *sbuffer, int slen, char *from, char *to); +extern unsigned char *util_xtoutf8_alloc(unsigned char *x,int slen,char *from); extern int util_utf16_byte_len(unsigned char *utf16); extern void util_hexdump(unsigned char *block, int len);