diff -uNr mt-daapd-0.2.4.orig/src/db-gdbm.c mt-daapd-0.2.4.work/src/db-gdbm.c --- mt-daapd-0.2.4.orig/src/db-gdbm.c 2005-01-17 14:20:13.000000000 +0900 +++ mt-daapd-0.2.4.work/src/db-gdbm.c 2006-03-04 12:06:22.000000000 +0900 @@ -19,6 +19,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define USE_CP932 + +#ifdef USE_CP932 + #define UNKNOWN_STR "UNKNOWN" + #ifndef FILESYSTEM_CES + #define FILESYSTEM_CES "CP932" +/* + #define FILESYSTEM_CES "UTF-8" + #define FILESYSTEM_CES "EUC-JP" +*/ + #endif +#endif + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -34,6 +47,9 @@ #include #include +#ifdef USE_CP932 + #include +#endif #include "err.h" #include "mp3-scanner.h" @@ -577,6 +593,43 @@ return !db_song_count; } +#ifdef USE_CP932 +#define MAX_ICONV_BUF 1024 + +typedef enum { + ICONV_OK, + ICONV_TRYNEXT, + ICONV_FATAL +} iconv_result; + +static iconv_result do_convert(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; +} + +#endif /** * Get the pointer to a specific playlist. MUST HAVE A @@ -686,7 +739,26 @@ if(!pnew) return -1; +#ifdef USE_CP932 + if (!strcasecmp(FILESYSTEM_CES, "UTF-8")) { pnew->name=strdup(name); + } else { + char* iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char)); + if (iconv_buf) { + iconv_result rc = do_convert("UTF-8", FILESYSTEM_CES, name, strlen(name), + iconv_buf, MAX_ICONV_BUF); + if(rc == ICONV_OK) { + pnew->name = iconv_buf; + } else { + pnew->name = strdup(UNKNOWN_STR); + free(iconv_buf); + } + } + } // if utf-8 +#else + pnew->name=strdup(name); +#endif + pnew->id=playlistid; pnew->nodes=NULL; pnew->last_node=NULL; diff -uNr mt-daapd-0.2.4.orig/src/mp3-scanner.c mt-daapd-0.2.4.work/src/mp3-scanner.c --- mt-daapd-0.2.4.orig/src/mp3-scanner.c 2005-02-06 06:22:47.000000000 +0900 +++ mt-daapd-0.2.4.work/src/mp3-scanner.c 2006-03-04 12:06:01.000000000 +0900 @@ -26,6 +26,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define USE_CP932 + +#ifdef USE_CP932 + #define UNKNOWN_STR "UNKNOWN" + #ifndef FILESYSTEM_CES + #define FILESYSTEM_CES "CP932" +/* + #define FILESYSTEM_CES "UTF-8" + #define FILESYSTEM_CES "EUC-JP" +*/ + #endif +#endif + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -45,6 +58,10 @@ #include #include /* why here? For osx 10.2, of course! */ +#ifdef USE_CP932 + #include +#endif + #include "daapd.h" #include "db-memory.h" #include "err.h" @@ -739,6 +756,97 @@ return 0; } +#ifdef USE_CP932 +#define MAX_ICONV_BUF 1024 + +typedef enum { + ICONV_OK, + ICONV_TRYNEXT, + ICONV_FATAL +} iconv_result; + +static iconv_result do_convert(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; +} + +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; + + 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; + } + + /* (1) try utf8 -> cp932 */ + rc = do_convert("CP932", "UTF-8", in8, strlen(in8), iconv_buf, MAX_ICONV_BUF); + if (rc == ICONV_OK) { + utf8_text = in8; + free(iconv_buf); + } else if (rc == ICONV_TRYNEXT) { + /* (2) try cp932 -> utf8 */ + rc = do_convert("UTF-8", "CP932", in, strlen(in), iconv_buf, MAX_ICONV_BUF); + if (rc == ICONV_OK) { + utf8_text = iconv_buf; + } else if (rc == ICONV_TRYNEXT) { + /* (3) try euc-jp -> utf8 */ + rc = do_convert("UTF-8", "EUC-JP", in, strlen(in), iconv_buf, MAX_ICONV_BUF); + if (rc == ICONV_OK) { + utf8_text = iconv_buf; + } else if (rc == ICONV_TRYNEXT) { + /* utf-8 including non-japanese char? fallback. */ + utf8_text = (char*)id3_ucs4_utf8duplicate(native_text); + free(iconv_buf); + } + } + free(in8); + } + free(in); + + out: + if(!utf8_text) { + utf8_text = strdup(UNKNOWN_STR); + } + + return utf8_text; +} +#endif int scan_get_mp3tags(char *file, MP3FILE *pmp3) { struct id3_file *pid3file; @@ -796,7 +904,11 @@ if(native_text) { have_utf8=1; +#ifdef USE_CP932 + utf8_text = get_utf8_text(native_text); +#else utf8_text=id3_ucs4_utf8duplicate(native_text); +#endif MEMNOTIFY(utf8_text); if(!strcmp(pid3frame->id,"TIT2")) { /* Title */ @@ -1762,8 +1874,28 @@ song->data_kind=0; } - if(!song->title) + if(!song->title) { +#ifdef USE_CP932 + if (!strcasecmp(FILESYSTEM_CES, "UTF-8")) { song->title = strdup(song->fname); + } else { + char* iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char)); + if (iconv_buf) { + iconv_result rc = do_convert("UTF-8", FILESYSTEM_CES, + song->fname, strlen(song->fname), + iconv_buf, MAX_ICONV_BUF); + if(rc == ICONV_OK) { + song->title = iconv_buf; + } else { + song->title = strdup(UNKNOWN_STR); + free(iconv_buf); + } + } + } // if utf-8 +#else + song->title = strdup(song->fname); +#endif + } /* Ogg used to be set as an item_kind of 4. Dunno why */ song->item_kind = 2; diff -uNr mt-daapd-0.2.4.orig/src/parser.c mt-daapd-0.2.4.work/src/parser.c --- mt-daapd-0.2.4.orig/src/parser.c 2005-09-12 04:19:11.000000000 +0900 +++ mt-daapd-0.2.4.work/src/parser.c 2006-03-04 12:06:10.000000000 +0900 @@ -36,6 +36,19 @@ #define AGO 286 #define INTERVAL 287 +#define USE_CP932 + +#ifdef USE_CP932 + #define UNKNOWN_STR "UNKNOWN" + #ifndef FILESYSTEM_CES + #define FILESYSTEM_CES "CP932" +/* + #define FILESYSTEM_CES "UTF-8" + #define FILESYSTEM_CES "EUC-JP" +*/ + #endif +#endif + #line 1 "parser.y" @@ -67,6 +80,11 @@ #include #include "playlist.h" +#ifdef USE_CP932 + #include + #include +#endif + #define YYERROR_VERBOSE 1 extern int yyerror(char *msg); @@ -1131,6 +1149,43 @@ return 1; } #line 174 "parser.y" +#ifdef USE_CP932 +#define MAX_ICONV_BUF 1024 + +typedef enum { + ICONV_OK, + ICONV_TRYNEXT, + ICONV_FATAL +} iconv_result; + +static iconv_result do_convert(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; +} +#endif + PL_NODE *pl_newintpredicate(int tag, int op, int value) { PL_NODE *pnew; @@ -1170,7 +1225,25 @@ pnew->op=op; pnew->type=T_STR; pnew->arg1.ival=tag; +#ifdef USE_CP932 + if (!strcasecmp(FILESYSTEM_CES, "UTF-8")) { pnew->arg2.cval=value; + } else { + char* iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char)); + if (iconv_buf) { + iconv_result rc = do_convert("UTF-8", FILESYSTEM_CES, value, strlen(value), + iconv_buf, MAX_ICONV_BUF); + if(rc == ICONV_OK) { + pnew->arg2.cval = iconv_buf; + } else { + pnew->arg2.cval = strdup(UNKNOWN_STR); + free(iconv_buf); + } + } + } // if utf-8 +#else + pnew->arg2.cval=value; +#endif return pnew; }