Link Here
|
|
|
1 |
diff -dPNur ./config.h.cmake ./config.h.cmake |
2 |
--- ./config.h.cmake 2013-10-08 17:50:01.000000000 +0200 |
3 |
+++ ./config.h.cmake 2013-11-11 13:43:48.500304915 +0100 |
4 |
@@ -31,6 +31,9 @@ |
5 |
/* Defined if you have libz */ |
6 |
#cmakedefine HAVE_ZLIB 1 |
7 |
|
8 |
+/* Defined if you have LibRCC from RusXMMS project */ |
9 |
+#cmakedefine HAVE_LIBRCC 1 |
10 |
+ |
11 |
/* Indicates whether debug messages are shown even in release mode */ |
12 |
#cmakedefine TRACE_IN_RELEASE 1 |
13 |
|
14 |
diff -dPNur ./ConfigureChecks.cmake ./ConfigureChecks.cmake |
15 |
--- ./ConfigureChecks.cmake 2013-10-08 17:50:01.000000000 +0200 |
16 |
+++ ./ConfigureChecks.cmake 2013-11-11 13:42:53.017126134 +0100 |
17 |
@@ -216,6 +216,7 @@ |
18 |
set(HAVE_ZLIB 0) |
19 |
endif() |
20 |
|
21 |
+SET(HAVE_LIBRCC 1) |
22 |
|
23 |
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) |
24 |
|
25 |
diff -dPNur ./examples/tagreader_c.c ./examples/tagreader_c.c |
26 |
--- ./examples/tagreader_c.c 2013-10-08 17:50:01.000000000 +0200 |
27 |
+++ ./examples/tagreader_c.c 2013-11-11 13:42:53.017126134 +0100 |
28 |
@@ -38,7 +38,7 @@ |
29 |
TagLib_Tag *tag; |
30 |
const TagLib_AudioProperties *properties; |
31 |
|
32 |
- taglib_set_strings_unicode(FALSE); |
33 |
+// taglib_set_strings_unicode(FALSE); |
34 |
|
35 |
for(i = 1; i < argc; i++) { |
36 |
printf("******************** \"%s\" ********************\n", argv[i]); |
37 |
diff -dPNur ./examples/tagwriter.cpp ./examples/tagwriter.cpp |
38 |
--- ./examples/tagwriter.cpp 2013-10-08 17:50:01.000000000 +0200 |
39 |
+++ ./examples/tagwriter.cpp 2013-11-11 13:42:53.028126368 +0100 |
40 |
@@ -92,7 +92,7 @@ |
41 |
if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) { |
42 |
|
43 |
char field = argv[i][1]; |
44 |
- TagLib::String value = argv[i + 1]; |
45 |
+ TagLib::String value(argv[i + 1], TagLib::String::Locale); |
46 |
|
47 |
TagLib::List<TagLib::FileRef>::Iterator it; |
48 |
for(it = fileList.begin(); it != fileList.end(); ++it) { |
49 |
diff -dPNur ./taglib/CMakeLists.txt ./taglib/CMakeLists.txt |
50 |
--- ./taglib/CMakeLists.txt 2013-10-08 17:50:01.000000000 +0200 |
51 |
+++ ./taglib/CMakeLists.txt 2013-11-11 13:42:53.042126665 +0100 |
52 |
@@ -36,6 +36,7 @@ |
53 |
audioproperties.h |
54 |
taglib_export.h |
55 |
${CMAKE_BINARY_DIR}/taglib_config.h |
56 |
+ toolkit/rccpatch.h |
57 |
toolkit/taglib.h |
58 |
toolkit/tstring.h |
59 |
toolkit/tlist.h |
60 |
@@ -281,6 +282,7 @@ |
61 |
) |
62 |
|
63 |
set(toolkit_SRCS |
64 |
+ toolkit/rccpatch.cpp |
65 |
toolkit/tstring.cpp |
66 |
toolkit/tstringlist.cpp |
67 |
toolkit/tbytevector.cpp |
68 |
@@ -310,7 +312,7 @@ |
69 |
add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) |
70 |
|
71 |
if(ZLIB_FOUND) |
72 |
- target_link_libraries(tag ${ZLIB_LIBRARIES}) |
73 |
+ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) |
74 |
endif() |
75 |
|
76 |
set_target_properties(tag PROPERTIES |
77 |
diff -dPNur ./taglib/mpeg/id3v1/id3v1tag.cpp ./taglib/mpeg/id3v1/id3v1tag.cpp |
78 |
--- ./taglib/mpeg/id3v1/id3v1tag.cpp 2013-10-08 17:50:01.000000000 +0200 |
79 |
+++ ./taglib/mpeg/id3v1/id3v1tag.cpp 2013-11-11 13:42:53.043126686 +0100 |
80 |
@@ -64,17 +64,18 @@ |
81 |
|
82 |
String ID3v1::StringHandler::parse(const ByteVector &data) const |
83 |
{ |
84 |
- return String(data, String::Latin1).stripWhiteSpace(); |
85 |
+ return String(data, String::Latin1ID3).stripWhiteSpace(); |
86 |
} |
87 |
|
88 |
ByteVector ID3v1::StringHandler::render(const String &s) const |
89 |
{ |
90 |
if(!s.isLatin1()) |
91 |
{ |
92 |
+ if (String::ID3WType(String::Latin1) == String::Latin1) |
93 |
return ByteVector(); |
94 |
} |
95 |
|
96 |
- return s.data(String::Latin1); |
97 |
+ return s.data(String::Latin1ID3); |
98 |
} |
99 |
|
100 |
//////////////////////////////////////////////////////////////////////////////// |
101 |
@@ -257,7 +258,7 @@ |
102 |
d->track = uchar(data[offset + 29]); |
103 |
} |
104 |
else |
105 |
- d->comment = data.mid(offset, 30); |
106 |
+ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); |
107 |
|
108 |
offset += 30; |
109 |
|
110 |
diff -dPNur ./taglib/mpeg/id3v2/frames/commentsframe.cpp ./taglib/mpeg/id3v2/frames/commentsframe.cpp |
111 |
--- ./taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-10-08 17:50:01.000000000 +0200 |
112 |
+++ ./taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-11-11 13:42:53.043126686 +0100 |
113 |
@@ -150,10 +150,10 @@ |
114 |
return; |
115 |
} |
116 |
|
117 |
- d->textEncoding = String::Type(data[0]); |
118 |
+ d->textEncoding = String::ID3Type(data[0]); |
119 |
d->language = data.mid(1, 3); |
120 |
|
121 |
- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; |
122 |
+ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; |
123 |
|
124 |
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); |
125 |
|
126 |
@@ -174,10 +174,12 @@ |
127 |
|
128 |
String::Type encoding = d->textEncoding; |
129 |
|
130 |
+ encoding = String::ID3WType(encoding); |
131 |
+ |
132 |
encoding = checkTextEncoding(d->description, encoding); |
133 |
encoding = checkTextEncoding(d->text, encoding); |
134 |
|
135 |
- v.append(char(encoding)); |
136 |
+ v.append(char(String::ID3RealType(encoding))); |
137 |
v.append(d->language.size() == 3 ? d->language : "XXX"); |
138 |
v.append(d->description.data(encoding)); |
139 |
v.append(textDelimiter(encoding)); |
140 |
diff -dPNur ./taglib/mpeg/id3v2/frames/textidentificationframe.cpp ./taglib/mpeg/id3v2/frames/textidentificationframe.cpp |
141 |
--- ./taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-10-08 17:50:01.000000000 +0200 |
142 |
+++ ./taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-11-11 13:42:53.044126708 +0100 |
143 |
@@ -187,12 +187,12 @@ |
144 |
|
145 |
// read the string data type (the first byte of the field data) |
146 |
|
147 |
- d->textEncoding = String::Type(data[0]); |
148 |
+ d->textEncoding = String::ID3Type(data[0]); |
149 |
|
150 |
// split the byte array into chunks based on the string type (two byte delimiter |
151 |
// for unicode encodings) |
152 |
|
153 |
- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; |
154 |
+ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; |
155 |
|
156 |
// build a small counter to strip nulls off the end of the field |
157 |
|
158 |
@@ -223,11 +223,14 @@ |
159 |
|
160 |
ByteVector TextIdentificationFrame::renderFields() const |
161 |
{ |
162 |
- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); |
163 |
+ String::Type encoding = d->textEncoding; |
164 |
+ |
165 |
+ encoding = String::ID3WType(encoding); |
166 |
+ encoding = checkTextEncoding(d->fieldList, encoding); |
167 |
|
168 |
ByteVector v; |
169 |
|
170 |
- v.append(char(encoding)); |
171 |
+ v.append(char(String::ID3RealType(encoding))); |
172 |
|
173 |
for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { |
174 |
|
175 |
diff -dPNur ./taglib/mpeg/id3v2/id3v2frame.cpp ./taglib/mpeg/id3v2/id3v2frame.cpp |
176 |
--- ./taglib/mpeg/id3v2/id3v2frame.cpp 2013-10-08 17:50:01.000000000 +0200 |
177 |
+++ ./taglib/mpeg/id3v2/id3v2frame.cpp 2013-11-11 13:42:53.045126729 +0100 |
178 |
@@ -302,7 +302,7 @@ |
179 |
if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) |
180 |
return String::UTF16; |
181 |
|
182 |
- if(encoding != String::Latin1) |
183 |
+ if((encoding != String::Latin1)&&(encoding != String::Latin1ID3V2)) |
184 |
return encoding; |
185 |
|
186 |
for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { |
187 |
diff -dPNur ./taglib/toolkit/rccpatch.cpp ./taglib/toolkit/rccpatch.cpp |
188 |
--- ./taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 |
189 |
+++ ./taglib/toolkit/rccpatch.cpp 2013-11-11 13:42:53.045126729 +0100 |
190 |
@@ -0,0 +1,237 @@ |
191 |
+#include <stdlib.h> |
192 |
+ |
193 |
+#include <string> |
194 |
+#include "tstring.h" |
195 |
+#include "tbytevector.h" |
196 |
+ |
197 |
+//#define RCC_DEBUG |
198 |
+ |
199 |
+ |
200 |
+#ifndef HAVE_LIBRCC |
201 |
+# include <config.h> |
202 |
+#endif |
203 |
+ |
204 |
+#ifdef HAVE_LIBRCC |
205 |
+# ifdef RCC_DEBUG |
206 |
+# include <stdio.h> |
207 |
+# endif /* RCC_DEBUG */ |
208 |
+# include <librcc.h> |
209 |
+# include <string.h> |
210 |
+#endif /* HAVE_LIBRCC */ |
211 |
+ |
212 |
+ |
213 |
+#ifdef HAVE_LIBRCC |
214 |
+# define ID3_CLASS 0 |
215 |
+# define ID3V2_CLASS 1 |
216 |
+# define UTF_CLASS 2 |
217 |
+# define OUT_CLASS 3 |
218 |
+static rcc_class classes[] = { |
219 |
+ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, |
220 |
+ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, |
221 |
+ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, |
222 |
+ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, |
223 |
+ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } |
224 |
+}; |
225 |
+ |
226 |
+static int rcc_initialized = 0; |
227 |
+ |
228 |
+static rcc_context ctx = NULL; |
229 |
+#endif /* HAVE_LIBRCC */ |
230 |
+ |
231 |
+ |
232 |
+void rccTaglibPatchFree() { |
233 |
+#ifdef HAVE_LIBRCC |
234 |
+ if (rcc_initialized) { |
235 |
+ rccFree(); |
236 |
+ rcc_initialized = 0; |
237 |
+ } |
238 |
+#endif /* HAVE_LIBRCC */ |
239 |
+} |
240 |
+ |
241 |
+void rccTaglibPatchInit() { |
242 |
+#ifdef HAVE_LIBRCC |
243 |
+ if (rcc_initialized) return; |
244 |
+ rccInit(); |
245 |
+ rccInitDefaultContext(NULL, 0, 0, classes, 0); |
246 |
+ rccLoad(NULL, "xmms"); |
247 |
+ rccInitDb4(NULL, NULL, 0); |
248 |
+ rcc_initialized = 1; |
249 |
+#endif /* HAVE_LIBRCC */ |
250 |
+} |
251 |
+ |
252 |
+void rccTaglibPatchSetContext(void *newctx) { |
253 |
+#ifdef HAVE_LIBRCC |
254 |
+ if (newctx) { |
255 |
+ ctx = (rcc_context)newctx; |
256 |
+ rcc_initialized = 1; |
257 |
+ } |
258 |
+#endif /* HAVE_LIBRCC */ |
259 |
+} |
260 |
+ |
261 |
+static void rccTaglibPatchTryInit() { |
262 |
+#ifdef HAVE_LIBRCC |
263 |
+ if (!rcc_initialized) { |
264 |
+ rccTaglibPatchInit(); |
265 |
+ if (rcc_initialized) atexit(rccTaglibPatchFree); |
266 |
+ } |
267 |
+#endif /* HAVE_LIBRCC */ |
268 |
+} |
269 |
+ |
270 |
+ |
271 |
+TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s) { |
272 |
+ TagLib::ByteVector v; |
273 |
+#ifdef HAVE_LIBRCC |
274 |
+ size_t rlen; |
275 |
+ char *res; |
276 |
+ |
277 |
+ rccTaglibPatchTryInit(); |
278 |
+ |
279 |
+ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); |
280 |
+#ifdef RCC_DEBUG |
281 |
+ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { |
282 |
+ if (*c > 127) { |
283 |
+ printf(" Output: %s - %s\n", s.c_str(), res?res:"null"); |
284 |
+ break; |
285 |
+ } |
286 |
+ } |
287 |
+#endif /* RCC_DEBUG */ |
288 |
+ |
289 |
+ if (res) v.setData(res, rlen); |
290 |
+ else v.setData("", 0); |
291 |
+ //v.setData(s.c_str(), s.length()); |
292 |
+ |
293 |
+ return v; |
294 |
+#else |
295 |
+ v.setData("", 0); |
296 |
+ |
297 |
+ return v; |
298 |
+#endif /* HAVE_LIBRCC */ |
299 |
+} |
300 |
+ |
301 |
+TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false) { |
302 |
+ TagLib::ByteVector v; |
303 |
+#ifdef HAVE_LIBRCC |
304 |
+ size_t rlen; |
305 |
+ char *res; |
306 |
+ |
307 |
+ rccTaglibPatchTryInit(); |
308 |
+ |
309 |
+ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); |
310 |
+#ifdef RCC_DEBUG |
311 |
+ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { |
312 |
+ if (*c > 127) { |
313 |
+ printf(" OutputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); |
314 |
+ break; |
315 |
+ } |
316 |
+ } |
317 |
+#endif /* RCC_DEBUG */ |
318 |
+ |
319 |
+ if (res) v.setData(res, rlen); |
320 |
+ else v.setData("", 0); |
321 |
+ //v.setData(s.c_str(), s.length()); |
322 |
+ |
323 |
+ return v; |
324 |
+#else |
325 |
+ v.setData("", 0); |
326 |
+ |
327 |
+ return v; |
328 |
+#endif /* HAVE_LIBRCC */ |
329 |
+} |
330 |
+ |
331 |
+TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s) { |
332 |
+ TagLib::ByteVector v; |
333 |
+#ifdef HAVE_LIBRCC |
334 |
+ size_t rlen; |
335 |
+ char *res; |
336 |
+ |
337 |
+ rccTaglibPatchTryInit(); |
338 |
+ |
339 |
+ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); |
340 |
+#ifdef RCC_DEBUG |
341 |
+ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { |
342 |
+ if (*c > 127) { |
343 |
+ printf(" Input: %s - %s\n", s.c_str(), res?res:"null"); |
344 |
+ break; |
345 |
+ } |
346 |
+ } |
347 |
+#endif /* RCC_DEBUG */ |
348 |
+ |
349 |
+ if (res) v.setData(res, rlen); |
350 |
+ else |
351 |
+#endif /* HAVE_LIBRCC */ |
352 |
+ v.setData("", 0); |
353 |
+ |
354 |
+ return v; |
355 |
+} |
356 |
+ |
357 |
+TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false) { |
358 |
+ TagLib::ByteVector v; |
359 |
+#ifdef HAVE_LIBRCC |
360 |
+ size_t rlen; |
361 |
+ char *res; |
362 |
+ |
363 |
+ rccTaglibPatchTryInit(); |
364 |
+ |
365 |
+ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); |
366 |
+#ifdef RCC_DEBUG |
367 |
+ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { |
368 |
+ if (*c > 127) { |
369 |
+ printf(" InputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); |
370 |
+ break; |
371 |
+ } |
372 |
+ } |
373 |
+#endif /* RCC_DEBUG */ |
374 |
+ if (res) v.setData(res, rlen + 1); |
375 |
+ else |
376 |
+#endif /* HAVE_LIBRCC */ |
377 |
+ v.setData("", 0); |
378 |
+ |
379 |
+ return v; |
380 |
+} |
381 |
+ |
382 |
+TagLib::String::Type rccTaglibPatchGetLocaleType() { |
383 |
+#ifdef HAVE_LIBRCC |
384 |
+ size_t len; |
385 |
+ char charset[32]; |
386 |
+ |
387 |
+ rccTaglibPatchTryInit(); |
388 |
+ if (!rccLocaleGetCharset(charset, NULL, 31)) { |
389 |
+ if (!strncmp(charset, "UTF", 3)) { |
390 |
+ len = strlen(charset); |
391 |
+ |
392 |
+ if (charset[len-1]=='8') return TagLib::String::UTF8; |
393 |
+ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; |
394 |
+ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; |
395 |
+ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; |
396 |
+ } |
397 |
+ return TagLib::String::Latin1; |
398 |
+ } |
399 |
+#endif /* HAVE_LIBRCC */ |
400 |
+ return TagLib::String::UTF8; |
401 |
+} |
402 |
+ |
403 |
+TagLib::String::Type rccTaglibPatchGetID3Type() { |
404 |
+#ifdef HAVE_LIBRCC |
405 |
+ size_t len; |
406 |
+ const char *charset; |
407 |
+ |
408 |
+ rccTaglibPatchTryInit(); |
409 |
+ |
410 |
+ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); |
411 |
+ if (charset) { |
412 |
+ if (!strncmp(charset, "UTF", 3)) { |
413 |
+ len = strlen(charset); |
414 |
+ |
415 |
+ if (charset[len-1]=='8') return TagLib::String::UTF8; |
416 |
+ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; |
417 |
+ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; |
418 |
+ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; |
419 |
+ } |
420 |
+ return TagLib::String::Latin1ID3V2; |
421 |
+ } else { |
422 |
+ // Error or no-language configured: If Latin1ID3V2 is returned we normally will use the default unicode encoding unless Latin1 is selected by taglib |
423 |
+ return TagLib::String::Latin1ID3V2; |
424 |
+ } |
425 |
+#endif /* HAVE_LIBRCC */ |
426 |
+ return TagLib::String::Latin1; |
427 |
+} |
428 |
diff -dPNur ./taglib/toolkit/rccpatch.h ./taglib/toolkit/rccpatch.h |
429 |
--- ./taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 |
430 |
+++ ./taglib/toolkit/rccpatch.h 2013-11-11 13:42:53.045126729 +0100 |
431 |
@@ -0,0 +1,20 @@ |
432 |
+#ifndef _RCC_PATCH_H |
433 |
+#define _RCC_PATCH_H |
434 |
+ |
435 |
+#include <string.h> |
436 |
+#include "tstring.h" |
437 |
+#include "tbytevector.h" |
438 |
+ |
439 |
+void rccTaglibPatchFree(); |
440 |
+void rccTaglibPatchInit(); |
441 |
+void rccTaglibPatchSetContext(void *newctx); |
442 |
+ |
443 |
+TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s); |
444 |
+TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s); |
445 |
+TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false); |
446 |
+TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false); |
447 |
+ |
448 |
+TagLib::String::Type rccTaglibPatchGetLocaleType(); |
449 |
+TagLib::String::Type rccTaglibPatchGetID3Type(); |
450 |
+ |
451 |
+#endif /* _RCC_PATCH_H */ |
452 |
diff -dPNur ./taglib/toolkit/tstring.cpp ./taglib/toolkit/tstring.cpp |
453 |
--- ./taglib/toolkit/tstring.cpp 2013-10-08 17:50:01.000000000 +0200 |
454 |
+++ ./taglib/toolkit/tstring.cpp 2013-11-11 13:42:53.046126750 +0100 |
455 |
@@ -29,6 +29,7 @@ |
456 |
#include <config.h> |
457 |
#endif |
458 |
|
459 |
+#include "rccpatch.h" |
460 |
#include "tstring.h" |
461 |
#include "tdebug.h" |
462 |
#include "tstringlist.h" |
463 |
@@ -197,8 +198,11 @@ |
464 |
String::String(const std::string &s, Type t) |
465 |
: d(new StringPrivate()) |
466 |
{ |
467 |
- if(t == Latin1) |
468 |
- copyFromLatin1(&s[0], s.length()); |
469 |
+ if(t == Locale) |
470 |
+ t = rccTaglibPatchGetLocaleType(); |
471 |
+ |
472 |
+ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) |
473 |
+ copyFromLatin1(&s[0], s.length(), true, t); |
474 |
else if(t == String::UTF8) |
475 |
copyFromUTF8(&s[0], s.length()); |
476 |
else { |
477 |
@@ -229,8 +233,11 @@ |
478 |
String::String(const char *s, Type t) |
479 |
: d(new StringPrivate()) |
480 |
{ |
481 |
- if(t == Latin1) |
482 |
- copyFromLatin1(s, ::strlen(s)); |
483 |
+ if(t == Locale) |
484 |
+ t = rccTaglibPatchGetLocaleType(); |
485 |
+ |
486 |
+ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) |
487 |
+ copyFromLatin1(s, ::strlen(s), true, t); |
488 |
else if(t == String::UTF8) |
489 |
copyFromUTF8(s, ::strlen(s)); |
490 |
else { |
491 |
@@ -251,7 +258,10 @@ |
492 |
String::String(char c, Type t) |
493 |
: d(new StringPrivate(1, static_cast<uchar>(c))) |
494 |
{ |
495 |
- if(t != Latin1 && t != UTF8) { |
496 |
+ if(t == Locale) |
497 |
+ t = rccTaglibPatchGetLocaleType(); |
498 |
+ |
499 |
+ if(t != Latin1 && t != Latin1ID3 && t != Latin1ID3V2 && t != UTF8) { |
500 |
debug("String::String() -- A char should not contain UTF16."); |
501 |
} |
502 |
} |
503 |
@@ -262,8 +272,11 @@ |
504 |
if(v.isEmpty()) |
505 |
return; |
506 |
|
507 |
- if(t == Latin1) |
508 |
- copyFromLatin1(v.data(), v.size()); |
509 |
+ if(t == Locale) |
510 |
+ t = rccTaglibPatchGetLocaleType(); |
511 |
+ |
512 |
+ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) |
513 |
+ copyFromLatin1(v.data(), v.size(), true, t); |
514 |
else if(t == UTF8) |
515 |
copyFromUTF8(v.data(), v.size()); |
516 |
else |
517 |
@@ -428,16 +441,46 @@ |
518 |
|
519 |
ByteVector String::data(Type t) const |
520 |
{ |
521 |
- switch(t) |
522 |
- { |
523 |
+ ByteVector v; |
524 |
+ |
525 |
+ if (t == Locale) { |
526 |
+ // The source is either Unicode or real Latin1 (if rcc is bypassed) |
527 |
+ std::string s = to8Bit(true); |
528 |
+ |
529 |
+ // In case of UTF8 locale, this probably will return NULL (no recoding needed), but we will take UTF8 path in the next swtich |
530 |
+ v = rccTaglibPatchRecodeOutput(s); |
531 |
+ if (v.size()) return v; |
532 |
+ |
533 |
+ t = rccTaglibPatchGetLocaleType(); |
534 |
+ } |
535 |
+ |
536 |
+ switch(t) { |
537 |
+ case Latin1ID3: |
538 |
+ case Latin1ID3V2: |
539 |
+ { |
540 |
+ std::string s = to8Bit(true); |
541 |
+ if (t == Latin1ID3) v = rccTaglibPatchRecodeOutputID3(s, false); |
542 |
+ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeOutputID3(s, true); |
543 |
+ if (v.size()) |
544 |
+ return v; |
545 |
+ |
546 |
+ // we don't know if we got NULL because rcc is disabled (error) or UTF8 output is required |
547 |
+ if ((t == Latin1ID3V2)&&(rccTaglibPatchGetID3Type() == UTF8)) { |
548 |
+ v.setData(s.c_str(), s.length()); |
549 |
+ } else { |
550 |
+ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) |
551 |
+ v.append(char(*it)); |
552 |
+ } |
553 |
+ return v; |
554 |
+ } |
555 |
case Latin1: |
556 |
{ |
557 |
ByteVector v(size(), 0); |
558 |
char *p = v.data(); |
559 |
- |
560 |
+ |
561 |
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) |
562 |
*p++ = static_cast<char>(*it); |
563 |
- |
564 |
+ |
565 |
return v; |
566 |
} |
567 |
case UTF8: |
568 |
@@ -763,12 +806,29 @@ |
569 |
// private members |
570 |
//////////////////////////////////////////////////////////////////////////////// |
571 |
|
572 |
-void String::copyFromLatin1(const char *s, size_t length) |
573 |
+void String::copyFromLatin1(const char *s, size_t length, bool prepare, Type t) |
574 |
{ |
575 |
d->data.resize(length); |
576 |
- |
577 |
for(size_t i = 0; i < length; ++i) |
578 |
d->data[i] = static_cast<uchar>(s[i]); |
579 |
+ |
580 |
+ // librcc conversation |
581 |
+ if (prepare) { |
582 |
+ std::string s = to8Bit(false); |
583 |
+ ByteVector v; |
584 |
+ |
585 |
+ if (t == Latin1ID3) v = rccTaglibPatchRecodeInputID3(s, false); |
586 |
+ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeInputID3(s, true); |
587 |
+ else /* Latin1 converted from Locale */ v = rccTaglibPatchRecodeInput(s); |
588 |
+ |
589 |
+ if (v.size()) { |
590 |
+ copyFromUTF8(v.data(), v.size()); |
591 |
+ } else { |
592 |
+ // We don't know if we got UTF-8 encoded string or either rcc is disable or something is failed, |
593 |
+ // since standard applications are really expecting here Latin1, it is safe to just check if we have violations of UTF8 |
594 |
+ //if (Unicode::isLegalUTF8(s)) t = UTF8; |
595 |
+ } |
596 |
+ } |
597 |
} |
598 |
|
599 |
void String::copyFromUTF8(const char *s, size_t length) |
600 |
@@ -874,7 +934,33 @@ |
601 |
|
602 |
std::ostream &operator<<(std::ostream &s, const TagLib::String &str) |
603 |
{ |
604 |
- s << str.to8Bit(); |
605 |
+ TagLib::ByteVector bv = str.data(TagLib::String::Locale); |
606 |
+ s << bv; |
607 |
return s; |
608 |
} |
609 |
|
610 |
+TagLib::String::Type TagLib::String::ID3Type(int i) |
611 |
+{ |
612 |
+ if(i == Latin1) |
613 |
+ return Latin1ID3V2; |
614 |
+ return Type(i); |
615 |
+}; |
616 |
+ |
617 |
+TagLib::String::Type TagLib::String::ID3WType(Type type) |
618 |
+{ |
619 |
+ Type rcc_type = rccTaglibPatchGetID3Type(); |
620 |
+ if((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)||(rcc_type == Latin1)) { |
621 |
+ if(type == Latin1) return |
622 |
+ rcc_type; |
623 |
+ return type; |
624 |
+ } |
625 |
+ |
626 |
+ return rcc_type; |
627 |
+}; |
628 |
+ |
629 |
+TagLib::String::Type TagLib::String::ID3RealType(Type type) |
630 |
+{ |
631 |
+ if((type == Latin1ID3) || (type == Latin1ID3V2)) |
632 |
+ return Latin1; |
633 |
+ return type; |
634 |
+} |
635 |
diff -dPNur ./taglib/toolkit/tstring.h ./taglib/toolkit/tstring.h |
636 |
--- ./taglib/toolkit/tstring.h 2013-10-08 17:50:01.000000000 +0200 |
637 |
+++ ./taglib/toolkit/tstring.h 2013-11-11 13:42:53.047126771 +0100 |
638 |
@@ -90,6 +90,18 @@ |
639 |
*/ |
640 |
enum Type { |
641 |
/*! |
642 |
+ * Determine using current locale settings |
643 |
+ */ |
644 |
+ Locale = -1, |
645 |
+ /*! |
646 |
+ * Latin1 for ID3 tags. |
647 |
+ */ |
648 |
+ Latin1ID3 = 65, |
649 |
+ /*! |
650 |
+ * Latin1 for ID3v2 tags. |
651 |
+ */ |
652 |
+ Latin1ID3V2 = 66, |
653 |
+ /*! |
654 |
* IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. |
655 |
*/ |
656 |
Latin1 = 0, |
657 |
@@ -112,6 +124,10 @@ |
658 |
UTF16LE = 4 |
659 |
}; |
660 |
|
661 |
+ static Type ID3Type(int i); |
662 |
+ static Type ID3WType(Type type); |
663 |
+ static Type ID3RealType(Type type); |
664 |
+ |
665 |
/*! |
666 |
* Constructs an empty String. |
667 |
*/ |
668 |
@@ -479,7 +495,7 @@ |
669 |
* Converts a \e Latin-1 string into \e UTF-16(without BOM/CPU byte order) |
670 |
* and copies it to the internal buffer. |
671 |
*/ |
672 |
- void copyFromLatin1(const char *s, size_t length); |
673 |
+ void copyFromLatin1(const char *s, size_t length, bool prepare = false, Type t = Latin1); |
674 |
|
675 |
/*! |
676 |
* Converts a \e UTF-8 string into \e UTF-16(without BOM/CPU byte order) |