source: titan/minidlna-1.0.22/tagutils/tagutils-misc.c @ 13567

Last change on this file since 13567 was 13567, checked in by obi, 11 years ago

[titan] add minidlna-1.0.22 first step

File size: 6.7 KB
Line 
1//=========================================================================
2// FILENAME     : tagutils-misc.c
3// DESCRIPTION  : Misc routines for supporting tagutils
4//=========================================================================
5// Copyright (c) 2008- NETGEAR, Inc. All Rights Reserved.
6//=========================================================================
7
8/* This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22/**************************************************************************
23* Language
24**************************************************************************/
25
26#define MAX_ICONV_BUF 1024
27
28typedef enum {
29        ICONV_OK,
30        ICONV_TRYNEXT,
31        ICONV_FATAL
32} iconv_result;
33
34static iconv_result
35do_iconv(const char* to_ces, const char* from_ces,
36         char *inbuf,  size_t inbytesleft,
37         char *outbuf_orig, size_t outbytesleft_orig)
38{
39#ifdef HAVE_ICONV_H
40        size_t rc;
41        iconv_result ret = ICONV_OK;
42
43        size_t outbytesleft = outbytesleft_orig - 1;
44        char* outbuf = outbuf_orig;
45
46        iconv_t cd  = iconv_open(to_ces, from_ces);
47
48        if(cd == (iconv_t)-1)
49        {
50                return ICONV_FATAL;
51        }
52        rc = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
53        if(rc == (size_t)-1)
54        {
55                if(errno == E2BIG)
56                {
57                        ret = ICONV_FATAL;
58                }
59                else
60                {
61                        ret = ICONV_TRYNEXT;
62                        memset(outbuf_orig, '\0', outbytesleft_orig);
63                }
64        }
65        iconv_close(cd);
66
67        return ret;
68#else // HAVE_ICONV_H
69        return ICONV_FATAL;
70#endif // HAVE_ICONV_H
71}
72
73#define N_LANG_ALT 8
74struct {
75        char *lang;
76        char *cpnames[N_LANG_ALT];
77} iconv_map[] = {
78        { "ja_JP",     { "CP932", "CP950", "CP936", "ISO-8859-1", 0 } },
79        { "zh_CN",  { "CP936", "CP950", "CP932", "ISO-8859-1", 0 } },
80        { "zh_TW",  { "CP950", "CP936", "CP932", "ISO-8859-1", 0 } },
81        { "ko_KR",  { "CP949", "ISO-8859-1", 0 } },
82        { 0,        { 0 } }
83};
84static int lang_index = -1;
85
86static int
87_lang2cp(char *lang)
88{
89        int cp;
90
91        if(!lang || lang[0] == '\0')
92                return -1;
93        for(cp = 0; iconv_map[cp].lang; cp++)
94        {
95                if(!strcasecmp(iconv_map[cp].lang, lang))
96                        return cp;
97        }
98        return -2;
99}
100
101static unsigned char*
102_get_utf8_text(const id3_ucs4_t* native_text)
103{
104        unsigned char *utf8_text = NULL;
105        char *in, *in8, *iconv_buf;
106        iconv_result rc;
107        int i, n;
108
109        in = (char*)id3_ucs4_latin1duplicate(native_text);
110        if(!in)
111        {
112                goto out;
113        }
114
115        in8 = (char*)id3_ucs4_utf8duplicate(native_text);
116        if(!in8)
117        {
118                free(in);
119                goto out;
120        }
121
122        iconv_buf = (char*)calloc(MAX_ICONV_BUF, sizeof(char));
123        if(!iconv_buf)
124        {
125                free(in); free(in8);
126                goto out;
127        }
128
129        i = lang_index;
130        // (1) try utf8 -> default
131        rc = do_iconv(iconv_map[i].cpnames[0], "UTF-8", in8, strlen(in8), iconv_buf, MAX_ICONV_BUF);
132        if(rc == ICONV_OK)
133        {
134                utf8_text = (unsigned char*)in8;
135                free(iconv_buf);
136        }
137        else if(rc == ICONV_TRYNEXT)
138        {
139                // (2) try default -> utf8
140                rc = do_iconv("UTF-8", iconv_map[i].cpnames[0], in, strlen(in), iconv_buf, MAX_ICONV_BUF);
141                if(rc == ICONV_OK)
142                {
143                        utf8_text = (unsigned char*)iconv_buf;
144                }
145                else if(rc == ICONV_TRYNEXT)
146                {
147                        // (3) try other encodes
148                        for(n = 1; n < N_LANG_ALT && iconv_map[i].cpnames[n]; n++)
149                        {
150                                rc = do_iconv("UTF-8", iconv_map[i].cpnames[n], in, strlen(in), iconv_buf, MAX_ICONV_BUF);
151                                if(rc == ICONV_OK)
152                                {
153                                        utf8_text = (unsigned char*)iconv_buf;
154                                        break;
155                                }
156                        }
157                        if(!utf8_text)
158                        {
159                                // cannot iconv
160                                utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
161                                free(iconv_buf);
162                        }
163                }
164                free(in8);
165        }
166        free(in);
167
168 out:
169        if(!utf8_text)
170        {
171                utf8_text = (unsigned char*)strdup("UNKNOWN");
172        }
173
174        return utf8_text;
175}
176
177
178static void
179vc_scan(struct song_metadata *psong, const char *comment, const size_t length)
180{
181        char strbuf[1024];
182
183        if(length > (sizeof(strbuf) - 1))
184        {
185                if( strncasecmp(comment, "LYRICS=", 7) != 0 )
186                {
187                        DPRINTF(E_WARN, L_SCANNER, "Vorbis %.*s too long [%s]\n", (index(comment, '=')-comment), comment, psong->path);
188                }
189                return;
190        }
191        strncpy(strbuf, comment, length);
192        strbuf[length] = '\0';
193
194        // ALBUM, ARTIST, PUBLISHER, COPYRIGHT, DISCNUMBER, ISRC, EAN/UPN, LABEL, LABELNO,
195        // LICENSE, OPUS, SOURCEMEDIA, TITLE, TRACKNUMBER, VERSION, ENCODED-BY, ENCODING,
196        // -- foollowing tags are muliples
197        // COMPOSER, ARRANGER, LYRICIST, AUTHOR, CONDUCTOR, PERFORMER, ENSEMBLE, PART
198        // PARTNUMBER, GENRE, DATE, LOCATION, COMMENT
199        if(!strncasecmp(strbuf, "ALBUM=", 6))
200        {
201                if( *(strbuf+6) )
202                        psong->album = strdup(strbuf + 6);
203        }
204        else if(!strncasecmp(strbuf, "ARTIST=", 7))
205        {
206                if( *(strbuf+7) )
207                        psong->contributor[ROLE_ARTIST] = strdup(strbuf + 7);
208        }
209        else if(!strncasecmp(strbuf, "ARTISTSORT=", 11))
210        {
211                psong->contributor_sort[ROLE_ARTIST] = strdup(strbuf + 11);
212        }
213        else if(!strncasecmp(strbuf, "TITLE=", 6))
214        {
215                if( *(strbuf+6) )
216                        psong->title = strdup(strbuf + 6);
217        }
218        else if(!strncasecmp(strbuf, "TRACKNUMBER=", 12))
219        {
220                psong->track = atoi(strbuf + 12);
221        }
222        else if(!strncasecmp(strbuf, "DISCNUMBER=", 11))
223        {
224                psong->disc = atoi(strbuf + 11);
225        }
226        else if(!strncasecmp(strbuf, "GENRE=", 6))
227        {
228                if( *(strbuf+6) )
229                        psong->genre = strdup(strbuf + 6);
230        }
231        else if(!strncasecmp(strbuf, "DATE=", 5))
232        {
233                if(length >= (5 + 10) &&
234                   isdigit(strbuf[5 + 0]) && isdigit(strbuf[5 + 1]) && ispunct(strbuf[5 + 2]) &&
235                   isdigit(strbuf[5 + 3]) && isdigit(strbuf[5 + 4]) && ispunct(strbuf[5 + 5]) &&
236                   isdigit(strbuf[5 + 6]) && isdigit(strbuf[5 + 7]) && isdigit(strbuf[5 + 8]) && isdigit(strbuf[5 + 9]))
237                {
238                        // nn-nn-yyyy
239                        strbuf[5 + 10] = '\0';
240                        psong->year = atoi(strbuf + 5 + 6);
241                }
242                else
243                {
244                        // year first. year is at most 4 digit.
245                        strbuf[5 + 4] = '\0';
246                        psong->year = atoi(strbuf + 5);
247                }
248        }
249        else if(!strncasecmp(strbuf, "COMMENT=", 8))
250        {
251                if( *(strbuf+8) )
252                        psong->comment = strdup(strbuf + 8);
253        }
254        else if(!strncasecmp(strbuf, "MUSICBRAINZ_ALBUMID=", 20))
255        {
256                psong->musicbrainz_albumid = strdup(strbuf + 20);
257        }
258        else if(!strncasecmp(strbuf, "MUSICBRAINZ_TRACKID=", 20))
259        {
260                psong->musicbrainz_trackid = strdup(strbuf + 20);
261        }
262        else if(!strncasecmp(strbuf, "MUSICBRAINZ_TRACKID=", 20))
263        {
264                psong->musicbrainz_trackid = strdup(strbuf + 20);
265        }
266        else if(!strncasecmp(strbuf, "MUSICBRAINZ_ARTISTID=", 21))
267        {
268                psong->musicbrainz_artistid = strdup(strbuf + 21);
269        }
270        else if(!strncasecmp(strbuf, "MUSICBRAINZ_ALBUMARTISTID=", 26))
271        {
272                psong->musicbrainz_albumartistid = strdup(strbuf + 26);
273        }
274}
Note: See TracBrowser for help on using the repository browser.