diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2021-03-12 03:55:34 +0100 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2021-03-12 03:55:34 +0100 |
commit | 60bd665e74cfeeaf70882173a0dd56c883e2014a (patch) | |
tree | 8a0066bb9f0259becac5605641e8e1eed1ae0e89 /patches/taglib | |
download | rusxmms2-60bd665e74cfeeaf70882173a0dd56c883e2014a.tar.gz rusxmms2-60bd665e74cfeeaf70882173a0dd56c883e2014a.tar.bz2 rusxmms2-60bd665e74cfeeaf70882173a0dd56c883e2014a.tar.xz rusxmms2-60bd665e74cfeeaf70882173a0dd56c883e2014a.zip |
Added to git tree
Diffstat (limited to 'patches/taglib')
-rw-r--r-- | patches/taglib/README | 36 | ||||
-rw-r--r-- | patches/taglib/taglib-1.10-ds-rusxmms.patch | 1339 | ||||
-rw-r--r-- | patches/taglib/taglib-1.11-ds-rusxmms.patch | 684 | ||||
-rw-r--r-- | patches/taglib/taglib-1.4-ds-rusxmms.patch | 504 | ||||
-rw-r--r-- | patches/taglib/taglib-1.5-ds-rusxmms.patch | 584 | ||||
-rw-r--r-- | patches/taglib/taglib-1.6-ds-rusxmms.patch | 587 | ||||
-rw-r--r-- | patches/taglib/taglib-1.7-ds-rusxmms-r2.patch | 506 | ||||
-rw-r--r-- | patches/taglib/taglib-1.7-ds-rusxmms.patch | 515 | ||||
-rw-r--r-- | patches/taglib/taglib-1.8-ds-rusxmms-r2.patch | 507 | ||||
-rw-r--r-- | patches/taglib/taglib-1.8-ds-rusxmms-r9.patch | 609 | ||||
-rw-r--r-- | patches/taglib/taglib-1.8-ds-rusxmms.patch | 519 | ||||
-rw-r--r-- | patches/taglib/taglib-1.9.1-ds-rusxmms-enforce.patch | 20 | ||||
-rw-r--r-- | patches/taglib/taglib-1.9.1-ds-rusxmms.patch | 676 |
13 files changed, 7086 insertions, 0 deletions
diff --git a/patches/taglib/README b/patches/taglib/README new file mode 100644 index 0000000..0d3e78e --- /dev/null +++ b/patches/taglib/README @@ -0,0 +1,36 @@ +taglib-*-ds-rusxmms-enforce.patch will prevent applications from +overloading taglib ID3 v.1 parser/renderer. For instance, kid3 +has it's onw recoder and bypasses RusXMMS unless this patch is +applied. + +If you want to set unicode ID3v.2 titles, please, set in the +LibRCC configuration (xmms.xml) "id3v2" class to point appropriate +unicode encoding. + +1. Some Info Encoding Handling +1.1 Reading encodings + - Unicode ID3 v.2 tags are read as defined by ID3V2 tag, no RusXMMS + is envolved. + - Latin1 ID3 v.2 and ID3 v.1 tags are read using RusXMMS library. + The 'id3' and 'id3v2' classes are used corespondingly. +1.2 Writing ID3 v.1 encodings + - ID3 v.1 tag is written using RusXMMS library. The 'id3' class + selects output encoding. +1.3 Writting ID3 v.2 encodings + - ID3 v.2 tag output encodings is selected with help of 'id3v2' class of + RusXMMS. + - If unicode encoding is set (UTF-8, UTF-16, UTF-16BE, UTF-16LE) + the tag is written using selected encoding (independent of original one). + - Otherwise, original unicode encodings are kept. + - If original encoding is also non-unicode, than the tag is stored + in 'id3v2' class encoding. However, it is really a bad idea! Set an + unicode encoding. +2. Recomended class settings + - id3 = CP1251 + - id3v2 = UTF-16 +3. Notes + - TagLib supports UTF-16LE encodings within ID3 v.2 tags (described by + number 4). The UTF-16LE is not part of standard and probably added for + compatibility with some nasty Windows applications. RusXMMS will not + allow to write tags in UTF-16LE. +
\ No newline at end of file diff --git a/patches/taglib/taglib-1.10-ds-rusxmms.patch b/patches/taglib/taglib-1.10-ds-rusxmms.patch new file mode 100644 index 0000000..584c237 --- /dev/null +++ b/patches/taglib/taglib-1.10-ds-rusxmms.patch @@ -0,0 +1,1339 @@ +diff -dPNur taglib-1.10/config.h.cmake taglib-1.10-ds/config.h.cmake +--- taglib-1.10/config.h.cmake 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/config.h.cmake 2015-11-26 23:03:07.058061207 +0100 +@@ -25,4 +25,7 @@ + /* Indicates whether debug messages are shown even in release mode */ + #cmakedefine TRACE_IN_RELEASE 1 + ++/* Defined if you have LibRCC from RusXMMS project */ ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine TESTS_DIR "@TESTS_DIR@" +diff -dPNur taglib-1.10/ConfigureChecks.cmake taglib-1.10-ds/ConfigureChecks.cmake +--- taglib-1.10/ConfigureChecks.cmake 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/ConfigureChecks.cmake 2015-11-26 23:03:07.058061207 +0100 +@@ -201,6 +201,8 @@ + endif() + endif() + ++SET(HAVE_LIBRCC 1) ++ + if(BUILD_TESTS) + find_package(CppUnit) + if(NOT CppUnit_FOUND) +diff -dPNur taglib-1.10/examples/tagreader_c.c taglib-1.10-ds/examples/tagreader_c.c +--- taglib-1.10/examples/tagreader_c.c 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/examples/tagreader_c.c 2015-11-26 23:03:07.059061228 +0100 +@@ -38,7 +38,7 @@ + TagLib_Tag *tag; + const TagLib_AudioProperties *properties; + +- taglib_set_strings_unicode(FALSE); ++ //taglib_set_strings_unicode(FALSE); + + for(i = 1; i < argc; i++) { + printf("******************** \"%s\" ********************\n", argv[i]); +diff -dPNur taglib-1.10/examples/tagwriter.cpp taglib-1.10-ds/examples/tagwriter.cpp +--- taglib-1.10/examples/tagwriter.cpp 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/examples/tagwriter.cpp 2015-11-26 23:03:07.059061228 +0100 +@@ -115,7 +115,7 @@ + if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) { + + char field = argv[i][1]; +- TagLib::String value = argv[i + 1]; ++ TagLib::String value(argv[i + 1], TagLib::String::Locale); + + TagLib::List<TagLib::FileRef>::ConstIterator it; + for(it = fileList.begin(); it != fileList.end(); ++it) { +diff -dPNur taglib-1.10/taglib/CMakeLists.txt taglib-1.10-ds/taglib/CMakeLists.txt +--- taglib-1.10/taglib/CMakeLists.txt 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/CMakeLists.txt 2015-11-26 23:03:07.059061228 +0100 +@@ -38,6 +38,7 @@ + audioproperties.h + taglib_export.h + ${CMAKE_CURRENT_BINARY_DIR}/../taglib_config.h ++ toolkit/rccpatch.h + toolkit/taglib.h + toolkit/tstring.h + toolkit/tlist.h +@@ -291,6 +292,7 @@ + ) + + set(toolkit_SRCS ++ toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -337,7 +339,7 @@ + add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) + + if(ZLIB_FOUND) +- target_link_libraries(tag ${ZLIB_LIBRARIES}) ++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) + endif() + + set_target_properties(tag PROPERTIES +diff -dPNur taglib-1.10/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.10-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.10/taglib/mpeg/id3v1/id3v1tag.cpp 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2015-11-26 23:03:07.059061228 +0100 +@@ -64,17 +64,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -257,7 +258,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.10/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.10-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.10/taglib/mpeg/id3v2/frames/commentsframe.cpp 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2015-11-26 23:03:07.059061228 +0100 +@@ -150,10 +150,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -173,11 +173,13 @@ + ByteVector v; + + String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); + + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.10/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.10-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.10/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2015-11-26 23:03:07.059061228 +0100 +@@ -187,12 +187,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -223,11 +223,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkTextEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.10/taglib/mpeg/id3v2/id3v2frame.cpp taglib-1.10-ds/taglib/mpeg/id3v2/id3v2frame.cpp +--- taglib-1.10/taglib/mpeg/id3v2/id3v2frame.cpp 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/mpeg/id3v2/id3v2frame.cpp 2015-11-26 23:03:07.060061249 +0100 +@@ -339,7 +339,7 @@ + if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) + return String::UTF16; + +- if(encoding != String::Latin1) ++ if((encoding != String::Latin1)&&(encoding != String::Latin1ID3V2)) + return encoding; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { +diff -dPNur taglib-1.10/taglib/toolkit/rccpatch.cpp taglib-1.10-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.10/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.10-ds/taglib/toolkit/rccpatch.cpp 2015-11-26 23:03:07.060061249 +0100 +@@ -0,0 +1,237 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++//#define RCC_DEBUG ++ ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# ifdef RCC_DEBUG ++# include <stdio.h> ++# endif /* RCC_DEBUG */ ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccTaglibPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccTaglibPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccTaglibPatchInit(); ++ if (rcc_initialized) atexit(rccTaglibPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Output: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" OutputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Input: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" InputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ if (res) v.setData(res, rlen + 1); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccTaglibPatchTryInit(); ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccTaglibPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccTaglibPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } else { ++ // Error or no-language configured: If Latin1ID3V2 is returned we normally will use the default unicode encoding unless Latin1 is selected by taglib ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.10/taglib/toolkit/rccpatch.h taglib-1.10-ds/taglib/toolkit/rccpatch.h +--- taglib-1.10/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.10-ds/taglib/toolkit/rccpatch.h 2015-11-26 23:03:07.060061249 +0100 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccTaglibPatchFree(); ++void rccTaglibPatchInit(); ++void rccTaglibPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType(); ++TagLib::String::Type rccTaglibPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.10/taglib/toolkit/tstring.cpp taglib-1.10-ds/taglib/toolkit/tstring.cpp +--- taglib-1.10/taglib/toolkit/tstring.cpp 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/toolkit/tstring.cpp 2015-11-26 23:10:01.286853654 +0100 +@@ -29,6 +29,7 @@ + #include <config.h> + #endif + ++#include "rccpatch.h" + #include "tstring.h" + #include "tdebug.h" + #include "tstringlist.h" +@@ -167,8 +168,11 @@ + String::String(const std::string &s, Type t) + : d(new StringPrivate()) + { +- if(t == Latin1) +- copyFromLatin1(s.c_str(), s.length()); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(&s[0], s.length(), true, t); + else if(t == String::UTF8) + copyFromUTF8(s.c_str(), s.length()); + else { +@@ -215,8 +219,11 @@ + String::String(const char *s, Type t) + : d(new StringPrivate()) + { +- if(t == Latin1) +- copyFromLatin1(s, ::strlen(s)); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(s, ::strlen(s), true, t); + else if(t == String::UTF8) + copyFromUTF8(s, ::strlen(s)); + else { +@@ -237,7 +244,10 @@ + String::String(char c, Type t) + : d(new StringPrivate(1, static_cast<uchar>(c))) + { +- if(t != Latin1 && t != UTF8) { ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t != Latin1 && t != Latin1ID3 && t != Latin1ID3V2 && t != UTF8) { + debug("String::String() -- char should not contain UTF16."); + } + } +@@ -248,8 +258,11 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1) +- copyFromLatin1(v.data(), v.size()); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(v.data(), v.size(), true, t); + else if(t == UTF8) + copyFromUTF8(v.data(), v.size()); + else +@@ -396,8 +409,38 @@ + + ByteVector String::data(Type t) const + { +- switch(t) +- { ++ ByteVector v; ++ ++ if (t == Locale) { ++ // The source is either Unicode or real Latin1 (if rcc is bypassed) ++ std::string s = to8Bit(true); ++ ++ // In case of UTF8 locale, this probably will return NULL (no recoding needed), but we will take UTF8 path in the next swtich ++ v = rccTaglibPatchRecodeOutput(s); ++ if (v.size()) return v; ++ ++ t = rccTaglibPatchGetLocaleType(); ++ } ++ ++ switch(t) { ++ case Latin1ID3: ++ case Latin1ID3V2: ++ { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeOutputID3(s, true); ++ if (v.size()) ++ return v; ++ ++ // we don't know if we got NULL because rcc is disabled (error) or UTF8 output is required ++ if ((t == Latin1ID3V2)&&(rccTaglibPatchGetID3Type() == UTF8)) { ++ v.setData(s.c_str(), s.length()); ++ } else { ++ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) ++ v.append(char(*it)); ++ } ++ return v; ++ } + case Latin1: + { + ByteVector v(size(), 0); +@@ -738,12 +781,30 @@ + // private members + //////////////////////////////////////////////////////////////////////////////// + +-void String::copyFromLatin1(const char *s, size_t length) ++void String::copyFromLatin1(const char *s, size_t length, bool prepare, Type t) + { + d->data.resize(length); + + for(size_t i = 0; i < length; ++i) + d->data[i] = static_cast<uchar>(s[i]); ++ ++ // librcc conversation ++ if (prepare) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccTaglibPatchRecodeInput(s); ++ ++ if (v.size()) { ++ copyFromUTF8(v.data(), v.size()); ++ } else { ++ // We don't know if we got UTF-8 encoded string or either rcc is disable or something is failed, ++ // since standard applications are really expecting here Latin1, it is safe to just check if we have violations of UTF8 ++ //if (Unicode::isLegalUTF8(s)) t = UTF8; ++ } ++ } + } + + void String::copyFromUTF8(const char *s, size_t length) +@@ -859,7 +920,33 @@ + + std::ostream &operator<<(std::ostream &s, const TagLib::String &str) + { +- s << str.to8Bit(); ++ TagLib::ByteVector bv = str.data(TagLib::String::Locale); ++ s << bv; + return s; + } + ++TagLib::String::Type TagLib::String::ID3Type(int i) ++{ ++ if(i == Latin1) ++ return Latin1ID3V2; ++ return Type(i); ++}; ++ ++TagLib::String::Type TagLib::String::ID3WType(Type type) ++{ ++ Type rcc_type = rccTaglibPatchGetID3Type(); ++ if((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)||(rcc_type == Latin1)) { ++ if(type == Latin1) return ++ rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++TagLib::String::Type TagLib::String::ID3RealType(Type type) ++{ ++ if((type == Latin1ID3) || (type == Latin1ID3V2)) ++ return Latin1; ++ return type; ++} +diff -dPNur taglib-1.10/taglib/toolkit/tstring.h taglib-1.10-ds/taglib/toolkit/tstring.h +--- taglib-1.10/taglib/toolkit/tstring.h 2015-11-11 22:41:59.000000000 +0100 ++++ taglib-1.10-ds/taglib/toolkit/tstring.h 2015-11-26 23:03:07.061061271 +0100 +@@ -96,6 +96,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3v2 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -117,6 +129,10 @@ + */ + UTF16LE = 4 + }; ++ ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); + + /*! + * Constructs an empty String. +@@ -519,7 +535,7 @@ + * Converts a \e Latin-1 string into \e UTF-16(without BOM/CPU byte order) + * and copies it to the internal buffer. + */ +- void copyFromLatin1(const char *s, size_t length); ++ void copyFromLatin1(const char *s, size_t length, bool prepare = false, Type t = Latin1); + + /*! + * Converts a \e UTF-8 string into \e UTF-16(without BOM/CPU byte order) +diff -dPNur taglib-1.10/taglib-1.10-ds-rusxmms.patch taglib-1.10-ds/taglib-1.10-ds-rusxmms.patch +--- taglib-1.10/taglib-1.10-ds-rusxmms.patch 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.10-ds/taglib-1.10-ds-rusxmms.patch 2015-11-14 15:40:37.000000000 +0100 +@@ -0,0 +1,669 @@ ++diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake ++index 88980ea..e4f44d3 100644 ++--- a/ConfigureChecks.cmake +++++ b/ConfigureChecks.cmake ++@@ -201,6 +201,8 @@ if(NOT ZLIB_SOURCE) ++ endif() ++ endif() ++ +++SET(HAVE_LIBRCC 1) +++ ++ if(BUILD_TESTS) ++ find_package(CppUnit) ++ if(NOT CppUnit_FOUND) ++diff --git a/config.h.cmake b/config.h.cmake ++index ee0e67a..2abd49c 100644 ++--- a/config.h.cmake +++++ b/config.h.cmake ++@@ -25,4 +25,7 @@ ++ /* Indicates whether debug messages are shown even in release mode */ ++ #cmakedefine TRACE_IN_RELEASE 1 ++ +++/* Defined if you have LibRCC from RusXMMS project */ +++#cmakedefine HAVE_LIBRCC 1 +++ ++ #cmakedefine TESTS_DIR "@TESTS_DIR@" ++diff --git a/examples/tagreader_c.c b/examples/tagreader_c.c ++index 0436992..e0f17d8 100644 ++--- a/examples/tagreader_c.c +++++ b/examples/tagreader_c.c ++@@ -38,7 +38,7 @@ int main(int argc, char *argv[]) ++ TagLib_Tag *tag; ++ const TagLib_AudioProperties *properties; ++ ++- taglib_set_strings_unicode(FALSE); +++ //taglib_set_strings_unicode(FALSE); ++ ++ for(i = 1; i < argc; i++) { ++ printf("******************** \"%s\" ********************\n", argv[i]); ++diff --git a/examples/tagwriter.cpp b/examples/tagwriter.cpp ++index ed8b0d7..6a7a263 100644 ++--- a/examples/tagwriter.cpp +++++ b/examples/tagwriter.cpp ++@@ -115,7 +115,7 @@ int main(int argc, char *argv[]) ++ if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) { ++ ++ char field = argv[i][1]; ++- TagLib::String value = argv[i + 1]; +++ TagLib::String value(argv[i + 1], TagLib::String::Locale); ++ ++ TagLib::List<TagLib::FileRef>::ConstIterator it; ++ for(it = fileList.begin(); it != fileList.end(); ++it) { ++diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt ++index 73c1a2f..cd7ea22 100644 ++--- a/taglib/CMakeLists.txt +++++ b/taglib/CMakeLists.txt ++@@ -38,6 +38,7 @@ set(tag_HDRS ++ audioproperties.h ++ taglib_export.h ++ ${CMAKE_CURRENT_BINARY_DIR}/../taglib_config.h +++ toolkit/rccpatch.h ++ toolkit/taglib.h ++ toolkit/tstring.h ++ toolkit/tlist.h ++@@ -291,6 +292,7 @@ set(xm_SRCS ++ ) ++ ++ set(toolkit_SRCS +++ toolkit/rccpatch.cpp ++ toolkit/tstring.cpp ++ toolkit/tstringlist.cpp ++ toolkit/tbytevector.cpp ++@@ -337,7 +339,7 @@ set(tag_LIB_SRCS ++ add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) ++ ++ if(ZLIB_FOUND) ++- target_link_libraries(tag ${ZLIB_LIBRARIES}) +++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) ++ endif() ++ ++ set_target_properties(tag PROPERTIES ++diff --git a/taglib/mpeg/id3v1/id3v1tag.cpp b/taglib/mpeg/id3v1/id3v1tag.cpp ++index 9fc8cfd..5352acc 100644 ++--- a/taglib/mpeg/id3v1/id3v1tag.cpp +++++ b/taglib/mpeg/id3v1/id3v1tag.cpp ++@@ -64,17 +64,18 @@ StringHandler::StringHandler() ++ ++ String ID3v1::StringHandler::parse(const ByteVector &data) const ++ { ++- return String(data, String::Latin1).stripWhiteSpace(); +++ return String(data, String::Latin1ID3).stripWhiteSpace(); ++ } ++ ++ ByteVector ID3v1::StringHandler::render(const String &s) const ++ { ++ if(!s.isLatin1()) ++ { +++ if (String::ID3WType(String::Latin1) == String::Latin1) ++ return ByteVector(); ++ } ++ ++- return s.data(String::Latin1); +++ return s.data(String::Latin1ID3); ++ } ++ ++ //////////////////////////////////////////////////////////////////////////////// ++@@ -257,7 +258,7 @@ void ID3v1::Tag::parse(const ByteVector &data) ++ d->track = uchar(data[offset + 29]); ++ } ++ else ++- d->comment = data.mid(offset, 30); +++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); ++ ++ offset += 30; ++ ++diff --git a/taglib/mpeg/id3v2/frames/commentsframe.cpp b/taglib/mpeg/id3v2/frames/commentsframe.cpp ++index deaa9d9..c0aba2b 100644 ++--- a/taglib/mpeg/id3v2/frames/commentsframe.cpp +++++ b/taglib/mpeg/id3v2/frames/commentsframe.cpp ++@@ -150,10 +150,10 @@ void CommentsFrame::parseFields(const ByteVector &data) ++ return; ++ } ++ ++- d->textEncoding = String::Type(data[0]); +++ d->textEncoding = String::ID3Type(data[0]); ++ d->language = data.mid(1, 3); ++ ++- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; +++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; ++ ++ ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); ++ ++@@ -173,11 +173,13 @@ ByteVector CommentsFrame::renderFields() const ++ ByteVector v; ++ ++ String::Type encoding = d->textEncoding; +++ +++ encoding = String::ID3WType(encoding); ++ ++ encoding = checkTextEncoding(d->description, encoding); ++ encoding = checkTextEncoding(d->text, encoding); ++ ++- v.append(char(encoding)); +++ v.append(char(String::ID3RealType(encoding))); ++ v.append(d->language.size() == 3 ? d->language : "XXX"); ++ v.append(d->description.data(encoding)); ++ v.append(textDelimiter(encoding)); ++diff --git a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp ++index b77dd54..a4a7277 100644 ++--- a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +++++ b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp ++@@ -187,12 +187,12 @@ void TextIdentificationFrame::parseFields(const ByteVector &data) ++ ++ // read the string data type (the first byte of the field data) ++ ++- d->textEncoding = String::Type(data[0]); +++ d->textEncoding = String::ID3Type(data[0]); ++ ++ // split the byte array into chunks based on the string type (two byte delimiter ++ // for unicode encodings) ++ ++- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; +++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; ++ ++ // build a small counter to strip nulls off the end of the field ++ ++@@ -223,11 +223,14 @@ void TextIdentificationFrame::parseFields(const ByteVector &data) ++ ++ ByteVector TextIdentificationFrame::renderFields() const ++ { ++- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); +++ String::Type encoding = d->textEncoding; +++ +++ encoding = String::ID3WType(encoding); +++ encoding = checkTextEncoding(d->fieldList, encoding); ++ ++ ByteVector v; ++ ++- v.append(char(encoding)); +++ v.append(char(String::ID3RealType(encoding))); ++ ++ for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { ++ ++diff --git a/taglib/mpeg/id3v2/id3v2frame.cpp b/taglib/mpeg/id3v2/id3v2frame.cpp ++index bee5375..fea5ab3 100644 ++--- a/taglib/mpeg/id3v2/id3v2frame.cpp +++++ b/taglib/mpeg/id3v2/id3v2frame.cpp ++@@ -339,7 +339,7 @@ String::Type Frame::checkEncoding(const StringList &fields, String::Type encodin ++ if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) ++ return String::UTF16; ++ ++- if(encoding != String::Latin1) +++ if((encoding != String::Latin1)&&(encoding != String::Latin1ID3V2)) ++ return encoding; ++ ++ for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { ++diff --git a/taglib/toolkit/rccpatch.cpp b/taglib/toolkit/rccpatch.cpp ++new file mode 100644 ++index 0000000..af99323 ++--- /dev/null +++++ b/taglib/toolkit/rccpatch.cpp ++@@ -0,0 +1,237 @@ +++#include <stdlib.h> +++ +++#include <string> +++#include "tstring.h" +++#include "tbytevector.h" +++ +++//#define RCC_DEBUG +++ +++ +++#ifndef HAVE_LIBRCC +++# include <config.h> +++#endif +++ +++#ifdef HAVE_LIBRCC +++# ifdef RCC_DEBUG +++# include <stdio.h> +++# endif /* RCC_DEBUG */ +++# include <librcc.h> +++# include <string.h> +++#endif /* HAVE_LIBRCC */ +++ +++ +++#ifdef HAVE_LIBRCC +++# define ID3_CLASS 0 +++# define ID3V2_CLASS 1 +++# define UTF_CLASS 2 +++# define OUT_CLASS 3 +++static rcc_class classes[] = { +++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, +++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, +++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, +++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, +++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } +++}; +++ +++static int rcc_initialized = 0; +++ +++static rcc_context ctx = NULL; +++#endif /* HAVE_LIBRCC */ +++ +++ +++void rccTaglibPatchFree() { +++#ifdef HAVE_LIBRCC +++ if (rcc_initialized) { +++ rccFree(); +++ rcc_initialized = 0; +++ } +++#endif /* HAVE_LIBRCC */ +++} +++ +++void rccTaglibPatchInit() { +++#ifdef HAVE_LIBRCC +++ if (rcc_initialized) return; +++ rccInit(); +++ rccInitDefaultContext(NULL, 0, 0, classes, 0); +++ rccLoad(NULL, "xmms"); +++ rccInitDb4(NULL, NULL, 0); +++ rcc_initialized = 1; +++#endif /* HAVE_LIBRCC */ +++} +++ +++void rccTaglibPatchSetContext(void *newctx) { +++#ifdef HAVE_LIBRCC +++ if (newctx) { +++ ctx = (rcc_context)newctx; +++ rcc_initialized = 1; +++ } +++#endif /* HAVE_LIBRCC */ +++} +++ +++static void rccTaglibPatchTryInit() { +++#ifdef HAVE_LIBRCC +++ if (!rcc_initialized) { +++ rccTaglibPatchInit(); +++ if (rcc_initialized) atexit(rccTaglibPatchFree); +++ } +++#endif /* HAVE_LIBRCC */ +++} +++ +++ +++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s) { +++ TagLib::ByteVector v; +++#ifdef HAVE_LIBRCC +++ size_t rlen; +++ char *res; +++ +++ rccTaglibPatchTryInit(); +++ +++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); +++#ifdef RCC_DEBUG +++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { +++ if (*c > 127) { +++ printf(" Output: %s - %s\n", s.c_str(), res?res:"null"); +++ break; +++ } +++ } +++#endif /* RCC_DEBUG */ +++ +++ if (res) v.setData(res, rlen); +++ else v.setData("", 0); +++ //v.setData(s.c_str(), s.length()); +++ +++ return v; +++#else +++ v.setData("", 0); +++ +++ return v; +++#endif /* HAVE_LIBRCC */ +++} +++ +++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false) { +++ TagLib::ByteVector v; +++#ifdef HAVE_LIBRCC +++ size_t rlen; +++ char *res; +++ +++ rccTaglibPatchTryInit(); +++ +++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); +++#ifdef RCC_DEBUG +++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { +++ if (*c > 127) { +++ printf(" OutputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); +++ break; +++ } +++ } +++#endif /* RCC_DEBUG */ +++ +++ if (res) v.setData(res, rlen); +++ else v.setData("", 0); +++ //v.setData(s.c_str(), s.length()); +++ +++ return v; +++#else +++ v.setData("", 0); +++ +++ return v; +++#endif /* HAVE_LIBRCC */ +++} +++ +++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s) { +++ TagLib::ByteVector v; +++#ifdef HAVE_LIBRCC +++ size_t rlen; +++ char *res; +++ +++ rccTaglibPatchTryInit(); +++ +++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); +++#ifdef RCC_DEBUG +++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { +++ if (*c > 127) { +++ printf(" Input: %s - %s\n", s.c_str(), res?res:"null"); +++ break; +++ } +++ } +++#endif /* RCC_DEBUG */ +++ +++ if (res) v.setData(res, rlen); +++ else +++#endif /* HAVE_LIBRCC */ +++ v.setData("", 0); +++ +++ return v; +++} +++ +++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false) { +++ TagLib::ByteVector v; +++#ifdef HAVE_LIBRCC +++ size_t rlen; +++ char *res; +++ +++ rccTaglibPatchTryInit(); +++ +++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); +++#ifdef RCC_DEBUG +++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { +++ if (*c > 127) { +++ printf(" InputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); +++ break; +++ } +++ } +++#endif /* RCC_DEBUG */ +++ if (res) v.setData(res, rlen + 1); +++ else +++#endif /* HAVE_LIBRCC */ +++ v.setData("", 0); +++ +++ return v; +++} +++ +++TagLib::String::Type rccTaglibPatchGetLocaleType() { +++#ifdef HAVE_LIBRCC +++ size_t len; +++ char charset[32]; +++ +++ rccTaglibPatchTryInit(); +++ if (!rccLocaleGetCharset(charset, NULL, 31)) { +++ if (!strncmp(charset, "UTF", 3)) { +++ len = strlen(charset); +++ +++ if (charset[len-1]=='8') return TagLib::String::UTF8; +++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; +++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; +++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; +++ } +++ return TagLib::String::Latin1; +++ } +++#endif /* HAVE_LIBRCC */ +++ return TagLib::String::UTF8; +++} +++ +++TagLib::String::Type rccTaglibPatchGetID3Type() { +++#ifdef HAVE_LIBRCC +++ size_t len; +++ const char *charset; +++ +++ rccTaglibPatchTryInit(); +++ +++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); +++ if (charset) { +++ if (!strncmp(charset, "UTF", 3)) { +++ len = strlen(charset); +++ +++ if (charset[len-1]=='8') return TagLib::String::UTF8; +++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; +++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; +++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; +++ } +++ return TagLib::String::Latin1ID3V2; +++ } else { +++ // Error or no-language configured: If Latin1ID3V2 is returned we normally will use the default unicode encoding unless Latin1 is selected by taglib +++ return TagLib::String::Latin1ID3V2; +++ } +++#endif /* HAVE_LIBRCC */ +++ return TagLib::String::Latin1; +++} ++diff --git a/taglib/toolkit/rccpatch.h b/taglib/toolkit/rccpatch.h ++new file mode 100644 ++index 0000000..31f4410 ++--- /dev/null +++++ b/taglib/toolkit/rccpatch.h ++@@ -0,0 +1,20 @@ +++#ifndef _RCC_PATCH_H +++#define _RCC_PATCH_H +++ +++#include <string.h> +++#include "tstring.h" +++#include "tbytevector.h" +++ +++void rccTaglibPatchFree(); +++void rccTaglibPatchInit(); +++void rccTaglibPatchSetContext(void *newctx); +++ +++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s); +++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s); +++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false); +++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false); +++ +++TagLib::String::Type rccTaglibPatchGetLocaleType(); +++TagLib::String::Type rccTaglibPatchGetID3Type(); +++ +++#endif /* _RCC_PATCH_H */ ++diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp ++index 258e1fc..70ff160 100644 ++--- a/taglib/toolkit/tstring.cpp +++++ b/taglib/toolkit/tstring.cpp ++@@ -29,6 +29,7 @@ ++ #include <config.h> ++ #endif ++ +++#include "rccpatch.h" ++ #include "tstring.h" ++ #include "tdebug.h" ++ #include "tstringlist.h" ++@@ -167,8 +168,11 @@ String::String(const String &s) ++ String::String(const std::string &s, Type t) ++ : d(new StringPrivate()) ++ { ++- if(t == Latin1) ++- copyFromLatin1(s.c_str(), s.length()); +++ if(t == Locale) +++ t = rccTaglibPatchGetLocaleType(); +++ +++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) +++ copyFromLatin1(&s[0], s.length(), true, t); ++ else if(t == String::UTF8) ++ copyFromUTF8(s.c_str(), s.length()); ++ else { ++@@ -215,8 +219,11 @@ String::String(const wchar_t *s, Type t) ++ String::String(const char *s, Type t) ++ : d(new StringPrivate()) ++ { ++- if(t == Latin1) ++- copyFromLatin1(s, ::strlen(s)); +++ if(t == Locale) +++ t = rccTaglibPatchGetLocaleType(); +++ +++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) +++ copyFromLatin1(s, ::strlen(s), true, t); ++ else if(t == String::UTF8) ++ copyFromUTF8(s, ::strlen(s)); ++ else { ++@@ -248,8 +255,11 @@ String::String(const ByteVector &v, Type t) ++ if(v.isEmpty()) ++ return; ++ ++- if(t == Latin1) ++- copyFromLatin1(v.data(), v.size()); +++ if(t == Locale) +++ t = rccTaglibPatchGetLocaleType(); +++ +++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) +++ copyFromLatin1(v.data(), v.size(), true, t); ++ else if(t == UTF8) ++ copyFromUTF8(v.data(), v.size()); ++ else ++@@ -396,8 +406,38 @@ bool String::isNull() const ++ ++ ByteVector String::data(Type t) const ++ { ++- switch(t) ++- { +++ ByteVector v; +++ +++ if (t == Locale) { +++ // The source is either Unicode or real Latin1 (if rcc is bypassed) +++ std::string s = to8Bit(true); +++ +++ // In case of UTF8 locale, this probably will return NULL (no recoding needed), but we will take UTF8 path in the next swtich +++ v = rccTaglibPatchRecodeOutput(s); +++ if (v.size()) return v; +++ +++ t = rccTaglibPatchGetLocaleType(); +++ } +++ +++ switch(t) { +++ case Latin1ID3: +++ case Latin1ID3V2: +++ { +++ std::string s = to8Bit(true); +++ if (t == Latin1ID3) v = rccTaglibPatchRecodeOutputID3(s, false); +++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeOutputID3(s, true); +++ if (v.size()) +++ return v; +++ +++ // we don't know if we got NULL because rcc is disabled (error) or UTF8 output is required +++ if ((t == Latin1ID3V2)&&(rccTaglibPatchGetID3Type() == UTF8)) { +++ v.setData(s.c_str(), s.length()); +++ } else { +++ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) +++ v.append(char(*it)); +++ } +++ return v; +++ } ++ case Latin1: ++ { ++ ByteVector v(size(), 0); ++@@ -738,12 +778,30 @@ void String::detach() ++ // private members ++ //////////////////////////////////////////////////////////////////////////////// ++ ++-void String::copyFromLatin1(const char *s, size_t length) +++void String::copyFromLatin1(const char *s, size_t length, bool prepare, Type t) ++ { ++ d->data.resize(length); ++ ++ for(size_t i = 0; i < length; ++i) ++ d->data[i] = static_cast<uchar>(s[i]); +++ +++ // librcc conversation +++ if (prepare) { +++ std::string s = to8Bit(false); +++ ByteVector v; +++ +++ if (t == Latin1ID3) v = rccTaglibPatchRecodeInputID3(s, false); +++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeInputID3(s, true); +++ else /* Latin1 converted from Locale */ v = rccTaglibPatchRecodeInput(s); +++ +++ if (v.size()) { +++ copyFromUTF8(v.data(), v.size()); +++ } else { +++ // We don't know if we got UTF-8 encoded string or either rcc is disable or something is failed, +++ // since standard applications are really expecting here Latin1, it is safe to just check if we have violations of UTF8 +++ //if (Unicode::isLegalUTF8(s)) t = UTF8; +++ } +++ } ++ } ++ ++ void String::copyFromUTF8(const char *s, size_t length) ++@@ -859,7 +917,33 @@ const TagLib::String operator+(const TagLib::String &s1, const char *s2) ++ ++ std::ostream &operator<<(std::ostream &s, const TagLib::String &str) ++ { ++- s << str.to8Bit(); +++ TagLib::ByteVector bv = str.data(TagLib::String::Locale); +++ s << bv; ++ return s; ++ } ++ +++TagLib::String::Type TagLib::String::ID3Type(int i) +++{ +++ if(i == Latin1) +++ return Latin1ID3V2; +++ return Type(i); +++}; +++ +++TagLib::String::Type TagLib::String::ID3WType(Type type) +++{ +++ Type rcc_type = rccTaglibPatchGetID3Type(); +++ if((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)||(rcc_type == Latin1)) { +++ if(type == Latin1) return +++ rcc_type; +++ return type; +++ } +++ +++ return rcc_type; +++}; +++ +++TagLib::String::Type TagLib::String::ID3RealType(Type type) +++{ +++ if((type == Latin1ID3) || (type == Latin1ID3V2)) +++ return Latin1; +++ return type; +++} ++diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h ++index 8b73988..8efca25 100644 ++--- a/taglib/toolkit/tstring.h +++++ b/taglib/toolkit/tstring.h ++@@ -96,6 +96,18 @@ namespace TagLib { ++ */ ++ enum Type { ++ /*! +++ * Determine using current locale settings +++ */ +++ Locale = -1, +++ /*! +++ * Latin1 for ID3 tags. +++ */ +++ Latin1ID3 = 65, +++ /*! +++ * Latin1 for ID3v2 tags. +++ */ +++ Latin1ID3V2 = 66, +++ /*! ++ * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. ++ */ ++ Latin1 = 0, ++@@ -117,6 +129,10 @@ namespace TagLib { ++ */ ++ UTF16LE = 4 ++ }; +++ +++ static Type ID3Type(int i); +++ static Type ID3WType(Type type); +++ static Type ID3RealType(Type type); ++ ++ /*! ++ * Constructs an empty String. ++@@ -519,7 +535,7 @@ namespace TagLib { ++ * Converts a \e Latin-1 string into \e UTF-16(without BOM/CPU byte order) ++ * and copies it to the internal buffer. ++ */ ++- void copyFromLatin1(const char *s, size_t length); +++ void copyFromLatin1(const char *s, size_t length, bool prepare = false, Type t = Latin1); ++ ++ /*! ++ * Converts a \e UTF-8 string into \e UTF-16(without BOM/CPU byte order) diff --git a/patches/taglib/taglib-1.11-ds-rusxmms.patch b/patches/taglib/taglib-1.11-ds-rusxmms.patch new file mode 100644 index 0000000..9f777c8 --- /dev/null +++ b/patches/taglib/taglib-1.11-ds-rusxmms.patch @@ -0,0 +1,684 @@ +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/config.h.cmake taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/config.h.cmake +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/config.h.cmake 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/config.h.cmake 2019-09-01 08:32:29.569443643 +0200 +@@ -30,6 +30,9 @@ + /* Indicates whether debug messages are shown even in release mode */ + #cmakedefine TRACE_IN_RELEASE 1 + ++/* Defined if you have LibRCC from RusXMMS project */ ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine TESTS_DIR "@TESTS_DIR@" + + #endif +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/ConfigureChecks.cmake taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/ConfigureChecks.cmake +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/ConfigureChecks.cmake 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/ConfigureChecks.cmake 2019-09-01 08:32:29.577443787 +0200 +@@ -213,3 +213,5 @@ + if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + set(PLATFORM WINRT 1) + endif() ++ ++SET(HAVE_LIBRCC 1) +\ No newline at end of file +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/examples/tagreader_c.c taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/examples/tagreader_c.c +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/examples/tagreader_c.c 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/examples/tagreader_c.c 2019-09-01 08:32:29.577443787 +0200 +@@ -38,7 +38,7 @@ + TagLib_Tag *tag; + const TagLib_AudioProperties *properties; + +- taglib_set_strings_unicode(FALSE); ++ //taglib_set_strings_unicode(FALSE); + + for(i = 1; i < argc; i++) { + printf("******************** \"%s\" ********************\n", argv[i]); +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/examples/tagwriter.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/examples/tagwriter.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/examples/tagwriter.cpp 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/examples/tagwriter.cpp 2019-09-01 08:32:29.577443787 +0200 +@@ -115,7 +115,7 @@ + if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) { + + char field = argv[i][1]; +- TagLib::String value = argv[i + 1]; ++ TagLib::String value(argv[i + 1], TagLib::String::Locale); + + TagLib::List<TagLib::FileRef>::ConstIterator it; + for(it = fileList.begin(); it != fileList.end(); ++it) { +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/CMakeLists.txt taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/CMakeLists.txt +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/CMakeLists.txt 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/CMakeLists.txt 2019-09-01 08:32:29.577443787 +0200 +@@ -41,6 +41,7 @@ + audioproperties.h + taglib_export.h + ${CMAKE_CURRENT_BINARY_DIR}/../taglib_config.h ++ toolkit/rccpatch.h + toolkit/taglib.h + toolkit/tstring.h + toolkit/tlist.h +@@ -312,6 +313,7 @@ + ) + + set(toolkit_SRCS ++ toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -354,7 +356,9 @@ + add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) + + if(HAVE_ZLIB AND NOT HAVE_ZLIB_SOURCE) +- target_link_libraries(tag ${ZLIB_LIBRARIES}) ++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) ++else () ++ target_link_libraries(tag rcc) + endif() + + set_target_properties(tag PROPERTIES +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v1/id3v1tag.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v1/id3v1tag.cpp 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2019-09-01 08:32:29.577443787 +0200 +@@ -69,15 +69,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { +- if(s.isLatin1()) +- return s.data(String::Latin1); +- else ++ if(!s.isLatin1()) ++ { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); ++ } ++ ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -262,7 +265,7 @@ + d->track = static_cast<unsigned char>(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v2/frames/commentsframe.cpp 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2019-09-01 08:32:29.578443805 +0200 +@@ -150,10 +150,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -173,11 +173,13 @@ + ByteVector v; + + String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); + + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2019-09-01 08:32:29.578443805 +0200 +@@ -191,12 +191,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -227,11 +227,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkTextEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v2/id3v2frame.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v2/id3v2frame.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/mpeg/id3v2/id3v2frame.cpp 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/mpeg/id3v2/id3v2frame.cpp 2019-09-01 08:32:29.578443805 +0200 +@@ -297,7 +297,7 @@ + if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) + return String::UTF16; + +- if(encoding != String::Latin1) ++ if((encoding != String::Latin1)&&(encoding != String::Latin1ID3V2)) + return encoding; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/rccpatch.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/rccpatch.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/rccpatch.cpp 2019-09-01 08:32:29.578443805 +0200 +@@ -0,0 +1,237 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++//#define RCC_DEBUG ++ ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# ifdef RCC_DEBUG ++# include <stdio.h> ++# endif /* RCC_DEBUG */ ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccTaglibPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccTaglibPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccTaglibPatchInit(); ++ if (rcc_initialized) atexit(rccTaglibPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Output: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" OutputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Input: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" InputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ if (res) v.setData(res, rlen + 1); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccTaglibPatchTryInit(); ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccTaglibPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccTaglibPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } else { ++ // Error or no-language configured: If Latin1ID3V2 is returned we normally will use the default unicode encoding unless Latin1 is selected by taglib ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/rccpatch.h taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/rccpatch.h +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/rccpatch.h 2019-09-01 08:32:29.578443805 +0200 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccTaglibPatchFree(); ++void rccTaglibPatchInit(); ++void rccTaglibPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType(); ++TagLib::String::Type rccTaglibPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/tstring.cpp taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/tstring.cpp +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/tstring.cpp 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/tstring.cpp 2019-09-01 08:27:18.763821274 +0200 +@@ -33,6 +33,7 @@ + #include <trefcounter.h> + #include <tutils.h> + ++#include "rccpatch.h" + #include "tstring.h" + + namespace +@@ -48,16 +49,6 @@ + return String::UTF16BE; + } + +- // Converts a Latin-1 string into UTF-16(without BOM/CPU byte order) +- // and copies it to the internal buffer. +- void copyFromLatin1(std::wstring &data, const char *s, size_t length) +- { +- data.resize(length); +- +- for(size_t i = 0; i < length; ++i) +- data[i] = static_cast<unsigned char>(s[i]); +- } +- + // Converts a UTF-8 string into UTF-16(without BOM/CPU byte order) + // and copies it to the internal buffer. + void copyFromUTF8(std::wstring &data, const char *s, size_t length) +@@ -73,6 +64,36 @@ + debug("String::copyFromUTF8() - UTF8-CPP error: " + message); + data.clear(); + } ++ ++ } ++ ++ // Converts a Latin-1 string into UTF-16(without BOM/CPU byte order) ++ // and copies it to the internal buffer. ++ void copyFromLatin1(std::wstring &data, const char *s, size_t length, bool prepare, String::Type t) ++ { ++ // librcc conversation ++ if (prepare) { ++ ByteVector v; ++ std::string std_s(s); ++ ++ if (t == String::Latin1ID3) v = rccTaglibPatchRecodeInputID3(std_s, false); ++ else if (t == String::Latin1ID3V2) v = rccTaglibPatchRecodeInputID3(std_s, true); ++ else /* Latin1 converted from Locale */ v = rccTaglibPatchRecodeInput(std_s); ++ ++ if (v.size()) { ++ copyFromUTF8(data, v.data(), v.size()); ++ return; ++ } else { ++ // We don't know if we got UTF-8 encoded string or either rcc is disable or something is failed, ++ // since standard applications are really expecting here Latin1, it is safe to just check if we have violations of UTF8 ++ //if (Unicode::isLegalUTF8(s)) t = UTF8; ++ } ++ } ++ ++ data.resize(length); ++ ++ for(size_t i = 0; i < length; ++i) ++ data[i] = static_cast<unsigned char>(s[i]); + } + + // Helper functions to read a UTF-16 character from an array. +@@ -175,8 +196,11 @@ + String::String(const std::string &s, Type t) : + d(new StringPrivate()) + { ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ + if(t == Latin1) +- copyFromLatin1(d->data, s.c_str(), s.length()); ++ copyFromLatin1(d->data, s.c_str(), s.length(), true, t); + else if(t == String::UTF8) + copyFromUTF8(d->data, s.c_str(), s.length()); + else { +@@ -223,8 +247,11 @@ + String::String(const char *s, Type t) : + d(new StringPrivate()) + { +- if(t == Latin1) +- copyFromLatin1(d->data, s, ::strlen(s)); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(d->data, s, ::strlen(s), true, t); + else if(t == String::UTF8) + copyFromUTF8(d->data, s, ::strlen(s)); + else { +@@ -245,8 +272,11 @@ + String::String(char c, Type t) : + d(new StringPrivate()) + { +- if(t == Latin1) +- copyFromLatin1(d->data, &c, 1); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(d->data, &c, 1, true, t); + else if(t == String::UTF8) + copyFromUTF8(d->data, &c, 1); + else { +@@ -260,8 +290,11 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1) +- copyFromLatin1(d->data, v.data(), v.size()); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(d->data, v.data(), v.size(), true, t); + else if(t == UTF8) + copyFromUTF8(d->data, v.data(), v.size()); + else +@@ -416,8 +449,38 @@ + + ByteVector String::data(Type t) const + { +- switch(t) +- { ++ ByteVector v; ++ ++ if (t == Locale) { ++ // The source is either Unicode or real Latin1 (if rcc is bypassed) ++ std::string s = to8Bit(true); ++ ++ // In case of UTF8 locale, this probably will return NULL (no recoding needed), but we will take UTF8 path in the next swtich ++ v = rccTaglibPatchRecodeOutput(s); ++ if (v.size()) return v; ++ ++ t = rccTaglibPatchGetLocaleType(); ++ } ++ ++ switch(t) { ++ case Latin1ID3: ++ case Latin1ID3V2: ++ { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeOutputID3(s, true); ++ if (v.size()) ++ return v; ++ ++ // we don't know if we got NULL because rcc is disabled (error) or UTF8 output is required ++ if ((t == Latin1ID3V2)&&(rccTaglibPatchGetID3Type() == UTF8)) { ++ v.setData(s.c_str(), s.length()); ++ } else { ++ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) ++ v.append(char(*it)); ++ } ++ return v; ++ } + case Latin1: + { + ByteVector v(size(), 0); +@@ -741,7 +804,33 @@ + + std::ostream &operator<<(std::ostream &s, const TagLib::String &str) + { +- s << str.to8Bit(); ++ TagLib::ByteVector bv = str.data(TagLib::String::Locale); ++ s << bv; + return s; + } + ++TagLib::String::Type TagLib::String::ID3Type(int i) ++{ ++ if(i == Latin1) ++ return Latin1ID3V2; ++ return Type(i); ++}; ++ ++TagLib::String::Type TagLib::String::ID3WType(Type type) ++{ ++ Type rcc_type = rccTaglibPatchGetID3Type(); ++ if((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)||(rcc_type == Latin1)) { ++ if(type == Latin1) return ++ rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++TagLib::String::Type TagLib::String::ID3RealType(Type type) ++{ ++ if((type == Latin1ID3) || (type == Latin1ID3V2)) ++ return Latin1; ++ return type; ++} +diff -dPNur taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/tstring.h taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/tstring.h +--- taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c/taglib/toolkit/tstring.h 2018-10-28 14:43:45.000000000 +0100 ++++ taglib-5cb589a5b82c13ba8f0542e5e79629da7645cb3c-ds/taglib/toolkit/tstring.h 2019-09-01 08:32:29.579443823 +0200 +@@ -96,6 +96,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3v2 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -117,6 +129,10 @@ + */ + UTF16LE = 4 + }; ++ ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); + + /*! + * Constructs an empty String. diff --git a/patches/taglib/taglib-1.4-ds-rusxmms.patch b/patches/taglib/taglib-1.4-ds-rusxmms.patch new file mode 100644 index 0000000..5b67c7c --- /dev/null +++ b/patches/taglib/taglib-1.4-ds-rusxmms.patch @@ -0,0 +1,504 @@ +diff -dPNur taglib-1.4/configure.in taglib-1.4-new/configure.in +--- taglib-1.4/configure.in 2005-07-27 02:45:33.000000000 +0200 ++++ taglib-1.4-new/configure.in 2005-09-16 01:45:30.000000000 +0200 +@@ -98,6 +98,20 @@ + + AC_SUBST(AUTODIRS) + ++AC_CHECK_LIB(rcc, rccInit,[ ++ AC_CHECK_HEADERS(librcc.h,[ ++ LIBRCC_LIBS="-lrcc" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) ++ + dnl ======================================================= + dnl FILE: ./taglib/configure.in.in + dnl ======================================================= +diff -dPNur taglib-1.4/configure.in.in taglib-1.4-new/configure.in.in +--- taglib-1.4/configure.in.in 2005-07-23 23:43:58.000000000 +0200 ++++ taglib-1.4-new/configure.in.in 2005-09-16 01:45:30.000000000 +0200 +@@ -94,3 +94,16 @@ + + AC_SUBST(AUTODIRS) + ++AC_CHECK_LIB(rcc, rccInit,[ ++ AC_CHECK_HEADERS(librcc.h,[ ++ LIBRCC_LIBS="-lrcc" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) +diff -dPNur taglib-1.4/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.4-new/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.4/taglib/mpeg/id3v1/id3v1tag.cpp 2005-05-17 22:17:16.000000000 +0200 ++++ taglib-1.4-new/taglib/mpeg/id3v1/id3v1tag.cpp 2005-09-16 01:46:37.000000000 +0200 +@@ -55,12 +55,12 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1); ++ return String(data, String::Latin1ID3); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -231,7 +231,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.4/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.4-new/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.4/taglib/mpeg/id3v2/frames/commentsframe.cpp 2005-07-25 23:16:32.000000000 +0200 ++++ taglib-1.4-new/taglib/mpeg/id3v2/frames/commentsframe.cpp 2005-09-16 01:45:30.000000000 +0200 +@@ -115,7 +115,7 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + + int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; +@@ -131,12 +131,13 @@ + ByteVector CommentsFrame::renderFields() const + { + ByteVector v; ++ String::Type textEncoding = String::ID3WType(d->textEncoding); + +- v.append(char(d->textEncoding)); ++ v.append(char(textEncoding)); + v.append(d->language.size() == 3 ? d->language : " "); +- v.append(d->description.data(d->textEncoding)); +- v.append(textDelimiter(d->textEncoding)); +- v.append(d->text.data(d->textEncoding)); ++ v.append(d->description.data(textEncoding)); ++ v.append(textDelimiter(textEncoding)); ++ v.append(d->text.data(textEncoding)); + + return v; + } +diff -dPNur taglib-1.4/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.4-new/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.4/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2005-05-17 22:17:26.000000000 +0200 ++++ taglib-1.4-new/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2005-09-16 01:45:30.000000000 +0200 +@@ -96,7 +96,7 @@ + { + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) +@@ -121,8 +121,9 @@ + ByteVector v; + + if(d->fieldList.size() > 0) { ++ String::Type textEncoding = String::ID3WType(d->textEncoding); + +- v.append(char(d->textEncoding)); ++ v.append(char(textEncoding)); + + for(StringList::Iterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +@@ -131,9 +132,9 @@ + // encoding. + + if(it != d->fieldList.begin()) +- v.append(textDelimiter(d->textEncoding)); ++ v.append(textDelimiter(textEncoding)); + +- v.append((*it).data(d->textEncoding)); ++ v.append((*it).data(textEncoding)); + } + } + +diff -dPNur taglib-1.4/taglib/toolkit/Makefile.am taglib-1.4-new/taglib/toolkit/Makefile.am +--- taglib-1.4/taglib/toolkit/Makefile.am 2005-07-25 23:16:32.000000000 +0200 ++++ taglib-1.4-new/taglib/toolkit/Makefile.am 2005-09-16 01:45:30.000000000 +0200 +@@ -1,12 +1,15 @@ +-INCLUDES = $(all_includes) ++INCLUDES = $(all_includes) @LIBRCC_INCLUDES@ ++libtoolkit_la_LDFLAGS = @LIBRCC_LIBS@ + + noinst_LTLIBRARIES = libtoolkit.la + + libtoolkit_la_SOURCES = \ ++ rccpatch.cpp \ + tstring.cpp tstringlist.cpp tbytevector.cpp \ + tbytevectorlist.cpp tfile.cpp tdebug.cpp unicode.cpp + + taglib_include_HEADERS = \ ++ rccpatch.h \ + taglib.h tstring.h tlist.h tlist.tcc tstringlist.h \ + tbytevector.h tbytevectorlist.h tfile.h \ + tmap.h tmap.tcc +diff -dPNur taglib-1.4/taglib/toolkit/rccpatch.cpp taglib-1.4-new/taglib/toolkit/rccpatch.cpp +--- taglib-1.4/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.4-new/taglib/toolkit/rccpatch.cpp 2005-09-16 01:45:30.000000000 +0200 +@@ -0,0 +1,202 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++char *rccPatchRecode(const char *str, size_t len, size_t *rlen) { ++#ifdef HAVE_LIBRCC ++ rccPatchTryInit(); ++ ++ return rccSizedRecode(ctx, ID3_CLASS, OUT_CLASS, str, len, rlen); ++#else ++ return NULL; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.4/taglib/toolkit/rccpatch.h taglib-1.4-new/taglib/toolkit/rccpatch.h +--- taglib-1.4/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.4-new/taglib/toolkit/rccpatch.h 2005-09-16 01:45:30.000000000 +0200 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.4/taglib/toolkit/tstring.cpp taglib-1.4-new/taglib/toolkit/tstring.cpp +--- taglib-1.4/taglib/toolkit/tstring.cpp 2005-07-25 23:31:15.000000000 +0200 ++++ taglib-1.4-new/taglib/toolkit/tstring.cpp 2005-09-16 01:45:30.000000000 +0200 +@@ -19,6 +19,7 @@ + * USA * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -161,7 +162,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -334,10 +335,18 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: ++ case Latin1ID3: + case Latin1: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s); ++ else v = rccPatchRecodeOutput(s); ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -649,6 +658,30 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s); ++ else v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ } ++ ++ t = UTF8; ++ } ++ + switch(t) { + case UTF16: + { +@@ -738,6 +771,17 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ if ((type == Latin1)||(type == Latin1ID3)) return rccPatchGetID3Type(); ++ return type; ++}; +diff -dPNur taglib-1.4/taglib/toolkit/tstring.h taglib-1.4-new/taglib/toolkit/tstring.h +--- taglib-1.4/taglib/toolkit/tstring.h 2005-07-25 23:55:14.000000000 +0200 ++++ taglib-1.4-new/taglib/toolkit/tstring.h 2005-09-16 01:45:30.000000000 +0200 +@@ -75,6 +75,14 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 5, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -97,6 +105,9 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.5-ds-rusxmms.patch b/patches/taglib/taglib-1.5-ds-rusxmms.patch new file mode 100644 index 0000000..0d80fb5 --- /dev/null +++ b/patches/taglib/taglib-1.5-ds-rusxmms.patch @@ -0,0 +1,584 @@ +diff -dPNur taglib-1.5/config-taglib.h.cmake taglib-1.5-ds/config-taglib.h.cmake +--- taglib-1.5/config-taglib.h.cmake 2008-01-11 01:56:23.000000000 +0100 ++++ taglib-1.5-ds/config-taglib.h.cmake 2008-11-20 15:58:31.000000000 +0100 +@@ -6,4 +6,6 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 +diff -dPNur taglib-1.5/ConfigureChecks.cmake taglib-1.5-ds/ConfigureChecks.cmake +--- taglib-1.5/ConfigureChecks.cmake 2008-01-11 01:56:23.000000000 +0100 ++++ taglib-1.5-ds/ConfigureChecks.cmake 2008-11-20 15:58:31.000000000 +0100 +@@ -14,6 +14,8 @@ + #check for libz using the cmake supplied FindZLIB.cmake + FIND_PACKAGE(ZLIB) + ++SET(HAVE_LIBRCC 1) ++ + IF(ZLIB_FOUND) + SET(HAVE_ZLIB 1) + ELSE(ZLIB_FOUND) +diff -dPNur taglib-1.5/configure.in taglib-1.5-ds/configure.in +--- taglib-1.5/configure.in 2008-02-13 00:53:05.000000000 +0100 ++++ taglib-1.5-ds/configure.in 2008-11-20 15:24:19.000000000 +0100 +@@ -98,6 +98,20 @@ + + AC_SUBST(AUTODIRS) + ++AC_CHECK_LIB(rcc, rccInit,[ ++ AC_CHECK_HEADERS(librcc.h,[ ++ LIBRCC_LIBS="-lrcc" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) ++ + #AM_INIT_AUTOMAKE(taglib,1.0) + dnl don't remove the below + dnl AC_OUTPUT(taglib-config) +diff -dPNur taglib-1.5/configure.in.in taglib-1.5-ds/configure.in.in +--- taglib-1.5/configure.in.in 2008-01-30 02:34:06.000000000 +0100 ++++ taglib-1.5-ds/configure.in.in 2008-11-20 15:24:19.000000000 +0100 +@@ -94,6 +94,21 @@ + + AC_SUBST(AUTODIRS) + ++AC_CHECK_LIB(rcc, rccInit,[ ++ AC_CHECK_HEADERS(librcc.h,[ ++ LIBRCC_LIBS="-lrcc" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) ++ ++ + #AM_INIT_AUTOMAKE(taglib,1.0) + dnl don't remove the below + dnl AC_OUTPUT(taglib-config) +diff -dPNur taglib-1.5/taglib/CMakeLists.txt taglib-1.5-ds/taglib/CMakeLists.txt +--- taglib-1.5/taglib/CMakeLists.txt 2008-02-12 05:15:20.000000000 +0100 ++++ taglib-1.5-ds/taglib/CMakeLists.txt 2008-11-20 15:58:31.000000000 +0100 +@@ -119,6 +119,7 @@ + ) + + SET(toolkit_SRCS ++toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -140,7 +141,7 @@ + + ADD_LIBRARY(tag SHARED ${tag_LIB_SRCS}) + +-TARGET_LINK_LIBRARIES(tag ) ++TARGET_LINK_LIBRARIES(tag rcc) + if(ZLIB_FOUND) + TARGET_LINK_LIBRARIES(tag ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) +diff -dPNur taglib-1.5/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.5-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.5/taglib/mpeg/id3v1/id3v1tag.cpp 2008-02-04 16:14:45.000000000 +0100 ++++ taglib-1.5-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2008-11-20 15:24:19.000000000 +0100 +@@ -59,17 +59,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -240,7 +241,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.5/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.5-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.5/taglib/mpeg/id3v2/frames/commentsframe.cpp 2008-02-04 16:14:46.000000000 +0100 ++++ taglib-1.5-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2008-11-20 15:24:19.000000000 +0100 +@@ -136,10 +136,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = d->textEncoding == (String::Latin1 || String::Latin1ID3 || String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -155,10 +155,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkEncoding(d->description, encoding); + encoding = checkEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.5/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.5-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.5/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2008-02-04 16:14:46.000000000 +0100 ++++ taglib-1.5-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2008-11-20 15:24:19.000000000 +0100 +@@ -105,12 +105,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -139,11 +139,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.5/taglib/toolkit/CMakeLists.txt taglib-1.5-ds/taglib/toolkit/CMakeLists.txt +--- taglib-1.5/taglib/toolkit/CMakeLists.txt 2008-01-11 01:54:01.000000000 +0100 ++++ taglib-1.5-ds/taglib/toolkit/CMakeLists.txt 2008-11-20 15:58:31.000000000 +0100 +@@ -1 +1 @@ +-INSTALL( FILES taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) ++INSTALL( FILES rccpatch.h taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) +diff -dPNur taglib-1.5/taglib/toolkit/Makefile.am taglib-1.5-ds/taglib/toolkit/Makefile.am +--- taglib-1.5/taglib/toolkit/Makefile.am 2008-01-11 01:54:01.000000000 +0100 ++++ taglib-1.5-ds/taglib/toolkit/Makefile.am 2008-11-20 15:24:19.000000000 +0100 +@@ -1,14 +1,20 @@ + INCLUDES = \ + -I$(top_srcdir)/taglib \ +- $(all_includes) ++ $(all_includes) \ ++ @LIBRCC_INCLUDES@ + + noinst_LTLIBRARIES = libtoolkit.la + ++libtoolkit_la_LDFLAGS = @LIBRCC_LIBS@ ++ + libtoolkit_la_SOURCES = \ ++ rccpatch.cpp \ + tstring.cpp tstringlist.cpp tbytevector.cpp \ + tbytevectorlist.cpp tfile.cpp tdebug.cpp unicode.cpp + ++ + taglib_include_HEADERS = \ ++ rccpatch.h \ + taglib.h tstring.h tlist.h tlist.tcc tstringlist.h \ + tbytevector.h tbytevectorlist.h tfile.h \ + tmap.h tmap.tcc +diff -dPNur taglib-1.5/taglib/toolkit/rccpatch.cpp taglib-1.5-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.5/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.5-ds/taglib/toolkit/rccpatch.cpp 2008-11-20 15:58:31.000000000 +0100 +@@ -0,0 +1,198 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.5/taglib/toolkit/rccpatch.h taglib-1.5-ds/taglib/toolkit/rccpatch.h +--- taglib-1.5/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.5-ds/taglib/toolkit/rccpatch.h 2008-11-20 15:24:19.000000000 +0100 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.5/taglib/toolkit/tstring.cpp taglib-1.5-ds/taglib/toolkit/tstring.cpp +--- taglib-1.5/taglib/toolkit/tstring.cpp 2008-02-04 16:14:45.000000000 +0100 ++++ taglib-1.5-ds/taglib/toolkit/tstring.cpp 2008-11-20 15:24:21.000000000 +0100 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -167,7 +168,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -358,10 +359,21 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: + case Latin1: ++ case Latin1ID3: ++ case Latin1ID3V2: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeOutputID3(s, true); ++ else /* if (t == Latin1(Locale) */ v = rccPatchRecodeOutput(s); ++ ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -692,6 +704,31 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ } ++ ++ t = UTF8; ++ } ++ + switch(t) { + case UTF16: + { +@@ -781,6 +818,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.5/taglib/toolkit/tstring.h taglib-1.5-ds/taglib/toolkit/tstring.h +--- taglib-1.5/taglib/toolkit/tstring.h 2008-02-04 16:14:45.000000000 +0100 ++++ taglib-1.5-ds/taglib/toolkit/tstring.h 2008-11-20 15:24:21.000000000 +0100 +@@ -81,6 +81,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -103,6 +115,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.6-ds-rusxmms.patch b/patches/taglib/taglib-1.6-ds-rusxmms.patch new file mode 100644 index 0000000..5eb1a2a --- /dev/null +++ b/patches/taglib/taglib-1.6-ds-rusxmms.patch @@ -0,0 +1,587 @@ +diff -dPNur taglib-1.6/config-taglib.h.cmake taglib-1.6-ds/config-taglib.h.cmake +--- taglib-1.6/config-taglib.h.cmake 2008-11-12 09:17:11.000000000 +0100 ++++ taglib-1.6-ds/config-taglib.h.cmake 2009-10-02 17:53:08.000000000 +0200 +@@ -6,6 +6,8 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 + #cmakedefine WITH_ASF 1 + #cmakedefine WITH_MP4 1 +diff -dPNur taglib-1.6/ConfigureChecks.cmake taglib-1.6-ds/ConfigureChecks.cmake +--- taglib-1.6/ConfigureChecks.cmake 2008-12-21 22:46:41.000000000 +0100 ++++ taglib-1.6-ds/ConfigureChecks.cmake 2009-10-02 17:53:08.000000000 +0200 +@@ -14,6 +14,8 @@ + #check for libz using the cmake supplied FindZLIB.cmake + FIND_PACKAGE(ZLIB) + ++SET(HAVE_LIBRCC 1) ++ + IF(ZLIB_FOUND) + SET(HAVE_ZLIB 1) + ELSE(ZLIB_FOUND) +diff -dPNur taglib-1.6/configure.in taglib-1.6-ds/configure.in +--- taglib-1.6/configure.in 2009-09-13 13:58:46.000000000 +0200 ++++ taglib-1.6-ds/configure.in 2009-10-02 17:53:08.000000000 +0200 +@@ -99,6 +99,20 @@ + + AC_SUBST(AUTODIRS) + ++AC_CHECK_LIB(rcc, rccInit,[ ++ AC_CHECK_HEADERS(librcc.h,[ ++ LIBRCC_LIBS="-lrcc" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) ++ + #AM_INIT_AUTOMAKE(taglib,1.0) + dnl don't remove the below + dnl AC_OUTPUT(taglib-config) +diff -dPNur taglib-1.6/configure.in.in taglib-1.6-ds/configure.in.in +--- taglib-1.6/configure.in.in 2009-09-13 13:30:19.000000000 +0200 ++++ taglib-1.6-ds/configure.in.in 2009-10-02 17:53:08.000000000 +0200 +@@ -95,6 +95,21 @@ + + AC_SUBST(AUTODIRS) + ++AC_CHECK_LIB(rcc, rccInit,[ ++ AC_CHECK_HEADERS(librcc.h,[ ++ LIBRCC_LIBS="-lrcc" ++ LIBRCC_INCLUDES="-DHAVE_LIBRCC" ++ ],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++])],[ ++ LIBRCC_LIBS="" ++ LIBRCC_INCLUDES="" ++]) ++AC_SUBST(LIBRCC_LIBS) ++AC_SUBST(LIBRCC_INCLUDES) ++ ++ + #AM_INIT_AUTOMAKE(taglib,1.0) + dnl don't remove the below + dnl AC_OUTPUT(taglib-config) +diff -dPNur taglib-1.6/taglib/CMakeLists.txt taglib-1.6-ds/taglib/CMakeLists.txt +--- taglib-1.6/taglib/CMakeLists.txt 2009-09-13 12:19:34.000000000 +0200 ++++ taglib-1.6-ds/taglib/CMakeLists.txt 2009-10-02 17:53:08.000000000 +0200 +@@ -163,6 +163,7 @@ + ) + + SET(toolkit_SRCS ++toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -190,7 +191,7 @@ + add_library(tag SHARED ${tag_LIB_SRCS}) + endif(ENABLE_STATIC) + +-TARGET_LINK_LIBRARIES(tag ) ++TARGET_LINK_LIBRARIES(tag rcc) + if(ZLIB_FOUND) + TARGET_LINK_LIBRARIES(tag ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) +diff -dPNur taglib-1.6/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.6-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.6/taglib/mpeg/id3v1/id3v1tag.cpp 2008-02-04 16:11:56.000000000 +0100 ++++ taglib-1.6-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -59,17 +59,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -240,7 +241,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.6/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.6-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.6/taglib/mpeg/id3v2/frames/commentsframe.cpp 2008-02-04 16:11:56.000000000 +0100 ++++ taglib-1.6-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -136,10 +136,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = d->textEncoding == (String::Latin1 || String::Latin1ID3 || String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -155,10 +155,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkEncoding(d->description, encoding); + encoding = checkEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.6/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.6-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.6/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2008-02-04 16:11:56.000000000 +0100 ++++ taglib-1.6-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -105,12 +105,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -139,11 +139,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.6/taglib/toolkit/CMakeLists.txt taglib-1.6-ds/taglib/toolkit/CMakeLists.txt +--- taglib-1.6/taglib/toolkit/CMakeLists.txt 2006-09-20 14:52:28.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/CMakeLists.txt 2009-10-02 17:53:08.000000000 +0200 +@@ -1 +1 @@ +-INSTALL( FILES taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) ++INSTALL( FILES rccpatch.h taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) +diff -dPNur taglib-1.6/taglib/toolkit/Makefile.am taglib-1.6-ds/taglib/toolkit/Makefile.am +--- taglib-1.6/taglib/toolkit/Makefile.am 2009-09-04 11:07:27.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/Makefile.am 2009-10-03 02:34:01.000000000 +0200 +@@ -1,15 +1,21 @@ + DEFS = -DMAKE_TAGLIB_LIB @DEFS@ + INCLUDES = \ + -I$(top_srcdir)/taglib \ +- $(all_includes) ++ $(all_includes) \ ++ @LIBRCC_INCLUDES@ ++ ++libtoolkit_la_LIBADD = @LIBRCC_LIBS@ + + noinst_LTLIBRARIES = libtoolkit.la + + libtoolkit_la_SOURCES = \ ++ rccpatch.cpp \ + tstring.cpp tstringlist.cpp tbytevector.cpp \ + tbytevectorlist.cpp tfile.cpp tdebug.cpp unicode.cpp + ++ + taglib_include_HEADERS = \ ++ rccpatch.h \ + taglib.h tstring.h tlist.h tlist.tcc tstringlist.h \ + tbytevector.h tbytevectorlist.h tfile.h \ + tmap.h tmap.tcc +diff -dPNur taglib-1.6/taglib/toolkit/rccpatch.cpp taglib-1.6-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.6/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.6-ds/taglib/toolkit/rccpatch.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -0,0 +1,198 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.6/taglib/toolkit/rccpatch.h taglib-1.6-ds/taglib/toolkit/rccpatch.h +--- taglib-1.6/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.6-ds/taglib/toolkit/rccpatch.h 2009-10-02 17:53:08.000000000 +0200 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.6/taglib/toolkit/tstring.cpp taglib-1.6-ds/taglib/toolkit/tstring.cpp +--- taglib-1.6/taglib/toolkit/tstring.cpp 2009-04-29 17:57:05.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/tstring.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -167,7 +168,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -369,10 +370,21 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: + case Latin1: ++ case Latin1ID3: ++ case Latin1ID3V2: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeOutputID3(s, true); ++ else /* if (t == Latin1(Locale) */ v = rccPatchRecodeOutput(s); ++ ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -707,6 +719,31 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ } ++ ++ t = UTF8; ++ } ++ + switch(t) { + case UTF16: + { +@@ -796,6 +833,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.6/taglib/toolkit/tstring.h taglib-1.6-ds/taglib/toolkit/tstring.h +--- taglib-1.6/taglib/toolkit/tstring.h 2009-07-02 22:54:32.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/tstring.h 2009-10-02 17:53:08.000000000 +0200 +@@ -81,6 +81,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -103,6 +115,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.7-ds-rusxmms-r2.patch b/patches/taglib/taglib-1.7-ds-rusxmms-r2.patch new file mode 100644 index 0000000..0757692 --- /dev/null +++ b/patches/taglib/taglib-1.7-ds-rusxmms-r2.patch @@ -0,0 +1,506 @@ +diff -dPNur taglib-1.7.2/config-taglib.h.cmake taglib-1.7.2-ds/config-taglib.h.cmake +--- taglib-1.7.2/config-taglib.h.cmake 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/config-taglib.h.cmake 2013-01-29 12:30:59.000000000 +0100 +@@ -6,6 +6,8 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 + #cmakedefine WITH_ASF 1 + #cmakedefine WITH_MP4 1 +diff -dPNur taglib-1.7.2/ConfigureChecks.cmake taglib-1.7.2-ds/ConfigureChecks.cmake +--- taglib-1.7.2/ConfigureChecks.cmake 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/ConfigureChecks.cmake 2013-01-29 12:30:59.000000000 +0100 +@@ -14,6 +14,8 @@ + #check for libz using the cmake supplied FindZLIB.cmake + FIND_PACKAGE(ZLIB) + ++SET(HAVE_LIBRCC 1) ++ + IF(ZLIB_FOUND) + SET(HAVE_ZLIB 1) + ELSE(ZLIB_FOUND) +diff -dPNur taglib-1.7.2/taglib/CMakeLists.txt taglib-1.7.2-ds/taglib/CMakeLists.txt +--- taglib-1.7.2/taglib/CMakeLists.txt 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/CMakeLists.txt 2013-01-29 12:30:59.000000000 +0100 +@@ -171,6 +171,7 @@ + ) + + SET(toolkit_SRCS ++toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -198,7 +199,7 @@ + add_library(tag SHARED ${tag_LIB_SRCS}) + endif(ENABLE_STATIC) + +-TARGET_LINK_LIBRARIES(tag ) ++TARGET_LINK_LIBRARIES(tag rcc) + if(ZLIB_FOUND) + TARGET_LINK_LIBRARIES(tag ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) +diff -dPNur taglib-1.7.2/taglib/CMakeLists.txt.orig taglib-1.7.2-ds/taglib/CMakeLists.txt.orig +diff -dPNur taglib-1.7.2/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.7.2-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.7.2/taglib/mpeg/id3v1/id3v1tag.cpp 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2013-01-29 12:30:59.000000000 +0100 +@@ -59,17 +59,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -240,7 +241,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.7.2/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.7.2-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.7.2/taglib/mpeg/id3v2/frames/commentsframe.cpp 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-01-29 12:30:59.000000000 +0100 +@@ -136,10 +136,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -155,10 +155,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkEncoding(d->description, encoding); + encoding = checkEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.7.2/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.7.2-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.7.2/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-01-29 12:30:59.000000000 +0100 +@@ -105,12 +105,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -139,11 +139,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.7.2/taglib/toolkit/CMakeLists.txt taglib-1.7.2-ds/taglib/toolkit/CMakeLists.txt +--- taglib-1.7.2/taglib/toolkit/CMakeLists.txt 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/toolkit/CMakeLists.txt 2013-01-29 12:30:59.000000000 +0100 +@@ -1 +1 @@ +-INSTALL( FILES taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) ++INSTALL( FILES rccpatch.h taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) +diff -dPNur taglib-1.7.2/taglib/toolkit/rccpatch.cpp taglib-1.7.2-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.7.2/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.7.2-ds/taglib/toolkit/rccpatch.cpp 2013-01-29 12:35:45.000000000 +0100 +@@ -0,0 +1,192 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.7.2/taglib/toolkit/rccpatch.h taglib-1.7.2-ds/taglib/toolkit/rccpatch.h +--- taglib-1.7.2/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.7.2-ds/taglib/toolkit/rccpatch.h 2013-01-29 12:30:59.000000000 +0100 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.7.2/taglib/toolkit/tstring.cpp taglib-1.7.2-ds/taglib/toolkit/tstring.cpp +--- taglib-1.7.2/taglib/toolkit/tstring.cpp 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/toolkit/tstring.cpp 2013-01-29 12:34:24.000000000 +0100 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -167,7 +168,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -369,10 +370,21 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: + case Latin1: ++ case Latin1ID3: ++ case Latin1ID3V2: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeOutputID3(s, true); ++ else /* if (t == Latin1(Locale) */ v = rccPatchRecodeOutput(s); ++ ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -717,6 +729,30 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ t = UTF8; ++ } ++ } ++ + switch(t) { + case UTF16: + { +@@ -806,6 +842,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.7.2/taglib/toolkit/tstring.h taglib-1.7.2-ds/taglib/toolkit/tstring.h +--- taglib-1.7.2/taglib/toolkit/tstring.h 2012-04-20 17:57:13.000000000 +0200 ++++ taglib-1.7.2-ds/taglib/toolkit/tstring.h 2013-01-29 12:30:59.000000000 +0100 +@@ -88,6 +88,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -110,6 +122,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.7-ds-rusxmms.patch b/patches/taglib/taglib-1.7-ds-rusxmms.patch new file mode 100644 index 0000000..fce777f --- /dev/null +++ b/patches/taglib/taglib-1.7-ds-rusxmms.patch @@ -0,0 +1,515 @@ +diff -dPNur taglib-1.6/config-taglib.h.cmake taglib-1.6-ds/config-taglib.h.cmake +--- taglib-1.6/config-taglib.h.cmake 2008-11-12 09:17:11.000000000 +0100 ++++ taglib-1.6-ds/config-taglib.h.cmake 2009-10-02 17:53:08.000000000 +0200 +@@ -6,6 +6,8 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 + #cmakedefine WITH_ASF 1 + #cmakedefine WITH_MP4 1 +diff -dPNur taglib-1.6/ConfigureChecks.cmake taglib-1.6-ds/ConfigureChecks.cmake +--- taglib-1.6/ConfigureChecks.cmake 2008-12-21 22:46:41.000000000 +0100 ++++ taglib-1.6-ds/ConfigureChecks.cmake 2009-10-02 17:53:08.000000000 +0200 +@@ -14,6 +14,8 @@ + #check for libz using the cmake supplied FindZLIB.cmake + FIND_PACKAGE(ZLIB) + ++SET(HAVE_LIBRCC 1) ++ + IF(ZLIB_FOUND) + SET(HAVE_ZLIB 1) + ELSE(ZLIB_FOUND) +diff -dPNur taglib-1.6/configure.in taglib-1.6-ds/configure.in +diff -dPNur taglib-1.6/configure.in.in taglib-1.6-ds/configure.in.in +diff -dPNur taglib-1.6/taglib/CMakeLists.txt taglib-1.6-ds/taglib/CMakeLists.txt +--- taglib-1.6/taglib/CMakeLists.txt 2009-09-13 12:19:34.000000000 +0200 ++++ taglib-1.6-ds/taglib/CMakeLists.txt 2009-10-02 17:53:08.000000000 +0200 +@@ -163,6 +163,7 @@ + ) + + SET(toolkit_SRCS ++toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -190,7 +191,7 @@ + add_library(tag SHARED ${tag_LIB_SRCS}) + endif(ENABLE_STATIC) + +-TARGET_LINK_LIBRARIES(tag ) ++TARGET_LINK_LIBRARIES(tag rcc) + if(ZLIB_FOUND) + TARGET_LINK_LIBRARIES(tag ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) +diff -dPNur taglib-1.6/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.6-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.6/taglib/mpeg/id3v1/id3v1tag.cpp 2008-02-04 16:11:56.000000000 +0100 ++++ taglib-1.6-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -59,17 +59,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -240,7 +241,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.6/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.6-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.6/taglib/mpeg/id3v2/frames/commentsframe.cpp 2008-02-04 16:11:56.000000000 +0100 ++++ taglib-1.6-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -136,10 +136,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -155,10 +155,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkEncoding(d->description, encoding); + encoding = checkEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.6/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.6-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.6/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2008-02-04 16:11:56.000000000 +0100 ++++ taglib-1.6-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -105,12 +105,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -139,11 +139,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.6/taglib/toolkit/CMakeLists.txt taglib-1.6-ds/taglib/toolkit/CMakeLists.txt +--- taglib-1.6/taglib/toolkit/CMakeLists.txt 2006-09-20 14:52:28.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/CMakeLists.txt 2009-10-02 17:53:08.000000000 +0200 +@@ -1 +1 @@ +-INSTALL( FILES taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) ++INSTALL( FILES rccpatch.h taglib.h tstring.h tlist.h tlist.tcc tstringlist.h tbytevector.h tbytevectorlist.h tfile.h tmap.h tmap.tcc DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) +diff -dPNur taglib-1.6/taglib/toolkit/Makefile.am taglib-1.6-ds/taglib/toolkit/Makefile.am +diff -dPNur taglib-1.6/taglib/toolkit/rccpatch.cpp taglib-1.6-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.6/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.6-ds/taglib/toolkit/rccpatch.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -0,0 +1,198 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.6/taglib/toolkit/rccpatch.h taglib-1.6-ds/taglib/toolkit/rccpatch.h +--- taglib-1.6/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.6-ds/taglib/toolkit/rccpatch.h 2009-10-02 17:53:08.000000000 +0200 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.6/taglib/toolkit/tstring.cpp taglib-1.6-ds/taglib/toolkit/tstring.cpp +--- taglib-1.6/taglib/toolkit/tstring.cpp 2009-04-29 17:57:05.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/tstring.cpp 2009-10-02 17:53:08.000000000 +0200 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -167,7 +168,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -369,10 +370,21 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: + case Latin1: ++ case Latin1ID3: ++ case Latin1ID3V2: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeOutputID3(s, true); ++ else /* if (t == Latin1(Locale) */ v = rccPatchRecodeOutput(s); ++ ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -707,6 +719,31 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ } ++ ++ t = UTF8; ++ } ++ + switch(t) { + case UTF16: + { +@@ -796,6 +833,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.6/taglib/toolkit/tstring.h taglib-1.6-ds/taglib/toolkit/tstring.h +--- taglib-1.6/taglib/toolkit/tstring.h 2009-07-02 22:54:32.000000000 +0200 ++++ taglib-1.6-ds/taglib/toolkit/tstring.h 2009-10-02 17:53:08.000000000 +0200 +@@ -81,6 +81,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -103,6 +115,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.8-ds-rusxmms-r2.patch b/patches/taglib/taglib-1.8-ds-rusxmms-r2.patch new file mode 100644 index 0000000..bed92a2 --- /dev/null +++ b/patches/taglib/taglib-1.8-ds-rusxmms-r2.patch @@ -0,0 +1,507 @@ +diff -dPNur taglib-1.8/config-taglib.h.cmake taglib-1.8-ds/config-taglib.h.cmake +--- taglib-1.8/config-taglib.h.cmake 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/config-taglib.h.cmake 2013-01-29 12:45:48.000000000 +0100 +@@ -3,6 +3,8 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 + #cmakedefine WITH_ASF 1 + #cmakedefine WITH_MP4 1 +diff -dPNur taglib-1.8/ConfigureChecks.cmake taglib-1.8-ds/ConfigureChecks.cmake +--- taglib-1.8/ConfigureChecks.cmake 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/ConfigureChecks.cmake 2013-01-29 12:45:48.000000000 +0100 +@@ -14,6 +14,8 @@ + set(HAVE_ZLIB 0) + endif() + ++SET(HAVE_LIBRCC 1) ++ + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) + find_package(CppUnit) + if(NOT CppUnit_FOUND AND BUILD_TESTS) +diff -dPNur taglib-1.8/taglib/CMakeLists.txt taglib-1.8-ds/taglib/CMakeLists.txt +--- taglib-1.8/taglib/CMakeLists.txt 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/CMakeLists.txt 2013-01-29 12:45:48.000000000 +0100 +@@ -35,6 +35,7 @@ + audioproperties.h + taglib_export.h + ${CMAKE_BINARY_DIR}/taglib_config.h ++ toolkit/rccpatch.h + toolkit/taglib.h + toolkit/tstring.h + toolkit/tlist.h +@@ -269,6 +270,7 @@ + ) + + set(toolkit_SRCS ++ toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -296,7 +298,7 @@ + add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) + + if(ZLIB_FOUND) +- target_link_libraries(tag ${ZLIB_LIBRARIES}) ++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) + endif() + + set_target_properties(tag PROPERTIES +diff -dPNur taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2013-01-29 12:45:48.000000000 +0100 +@@ -64,17 +64,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -247,7 +248,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-01-29 12:45:48.000000000 +0100 +@@ -150,10 +150,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -174,10 +174,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-01-29 12:45:48.000000000 +0100 +@@ -187,12 +187,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -223,11 +223,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkTextEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.8/taglib/toolkit/rccpatch.cpp taglib-1.8-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.8/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.8-ds/taglib/toolkit/rccpatch.cpp 2013-01-29 12:35:45.000000000 +0100 +@@ -0,0 +1,192 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.8/taglib/toolkit/rccpatch.h taglib-1.8-ds/taglib/toolkit/rccpatch.h +--- taglib-1.8/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.8-ds/taglib/toolkit/rccpatch.h 2013-01-29 12:45:48.000000000 +0100 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.8/taglib/toolkit/tstring.cpp taglib-1.8-ds/taglib/toolkit/tstring.cpp +--- taglib-1.8/taglib/toolkit/tstring.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/toolkit/tstring.cpp 2013-01-29 12:46:14.000000000 +0100 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -168,7 +169,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -397,10 +398,21 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: + case Latin1: ++ case Latin1ID3: ++ case Latin1ID3V2: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeOutputID3(s, true); ++ else /* if (t == Latin1(Locale) */ v = rccPatchRecodeOutput(s); ++ ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -750,6 +762,30 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ t = UTF8; ++ } ++ } ++ + switch(t) { + case UTF16: + { +@@ -839,6 +875,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.8/taglib/toolkit/tstring.h taglib-1.8-ds/taglib/toolkit/tstring.h +--- taglib-1.8/taglib/toolkit/tstring.h 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/toolkit/tstring.h 2013-01-29 12:45:48.000000000 +0100 +@@ -90,6 +90,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -112,6 +124,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.8-ds-rusxmms-r9.patch b/patches/taglib/taglib-1.8-ds-rusxmms-r9.patch new file mode 100644 index 0000000..28a7b84 --- /dev/null +++ b/patches/taglib/taglib-1.8-ds-rusxmms-r9.patch @@ -0,0 +1,609 @@ +diff -dPNur taglib-1.8/config-taglib.h.cmake taglib-1.8-ds/config-taglib.h.cmake +--- taglib-1.8/config-taglib.h.cmake 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/config-taglib.h.cmake 2013-05-22 20:13:15.000000000 +0200 +@@ -3,6 +3,8 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 + #cmakedefine WITH_ASF 1 + #cmakedefine WITH_MP4 1 +diff -dPNur taglib-1.8/ConfigureChecks.cmake taglib-1.8-ds/ConfigureChecks.cmake +--- taglib-1.8/ConfigureChecks.cmake 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/ConfigureChecks.cmake 2013-05-22 20:13:15.000000000 +0200 +@@ -14,6 +14,8 @@ + set(HAVE_ZLIB 0) + endif() + ++SET(HAVE_LIBRCC 1) ++ + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) + find_package(CppUnit) + if(NOT CppUnit_FOUND AND BUILD_TESTS) +diff -dPNur taglib-1.8/examples/tagreader_c.c taglib-1.8-ds/examples/tagreader_c.c +--- taglib-1.8/examples/tagreader_c.c 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/examples/tagreader_c.c 2013-05-22 20:13:15.000000000 +0200 +@@ -38,7 +38,7 @@ + TagLib_Tag *tag; + const TagLib_AudioProperties *properties; + +- taglib_set_strings_unicode(FALSE); ++// taglib_set_strings_unicode(FALSE); + + for(i = 1; i < argc; i++) { + printf("******************** \"%s\" ********************\n", argv[i]); +diff -dPNur taglib-1.8/examples/tagwriter.cpp taglib-1.8-ds/examples/tagwriter.cpp +--- taglib-1.8/examples/tagwriter.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/examples/tagwriter.cpp 2013-05-22 20:13:15.000000000 +0200 +@@ -92,7 +92,7 @@ + if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) { + + char field = argv[i][1]; +- TagLib::String value = argv[i + 1]; ++ TagLib::String value(argv[i + 1], TagLib::String::Locale); + + TagLib::List<TagLib::FileRef>::Iterator it; + for(it = fileList.begin(); it != fileList.end(); ++it) { +diff -dPNur taglib-1.8/taglib/CMakeLists.txt taglib-1.8-ds/taglib/CMakeLists.txt +--- taglib-1.8/taglib/CMakeLists.txt 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/CMakeLists.txt 2013-05-22 20:13:15.000000000 +0200 +@@ -35,6 +35,7 @@ + audioproperties.h + taglib_export.h + ${CMAKE_BINARY_DIR}/taglib_config.h ++ toolkit/rccpatch.h + toolkit/taglib.h + toolkit/tstring.h + toolkit/tlist.h +@@ -269,6 +270,7 @@ + ) + + set(toolkit_SRCS ++ toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -296,7 +298,7 @@ + add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) + + if(ZLIB_FOUND) +- target_link_libraries(tag ${ZLIB_LIBRARIES}) ++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) + endif() + + set_target_properties(tag PROPERTIES +diff -dPNur taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2013-05-22 20:13:15.000000000 +0200 +@@ -64,17 +64,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -247,7 +248,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-05-22 20:13:16.000000000 +0200 +@@ -150,10 +150,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -174,10 +174,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-05-22 20:13:16.000000000 +0200 +@@ -187,12 +187,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -223,11 +223,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkTextEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/id3v2frame.cpp taglib-1.8-ds/taglib/mpeg/id3v2/id3v2frame.cpp +--- taglib-1.8/taglib/mpeg/id3v2/id3v2frame.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/id3v2frame.cpp 2013-05-22 20:10:07.000000000 +0200 +@@ -295,7 +295,7 @@ + if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) + return String::UTF16; + +- if(encoding != String::Latin1) ++ if((encoding != String::Latin1)&&(encoding != String::Latin1ID3V2)) + return encoding; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { +diff -dPNur taglib-1.8/taglib/toolkit/rccpatch.cpp taglib-1.8-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.8/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.8-ds/taglib/toolkit/rccpatch.cpp 2013-05-22 20:13:16.000000000 +0200 +@@ -0,0 +1,237 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++//#define RCC_DEBUG ++ ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# ifdef RCC_DEBUG ++# include <stdio.h> ++# endif /* RCC_DEBUG */ ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccTaglibPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccTaglibPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccTaglibPatchInit(); ++ if (rcc_initialized) atexit(rccTaglibPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Output: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" OutputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Input: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" InputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccTaglibPatchTryInit(); ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccTaglibPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccTaglibPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } else { ++ // Error or no-language configured: If Latin1ID3V2 is returned we normally will use the default unicode encoding unless Latin1 is selected by taglib ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.8/taglib/toolkit/rccpatch.h taglib-1.8-ds/taglib/toolkit/rccpatch.h +--- taglib-1.8/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.8-ds/taglib/toolkit/rccpatch.h 2013-05-22 20:13:16.000000000 +0200 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccTaglibPatchFree(); ++void rccTaglibPatchInit(); ++void rccTaglibPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType(); ++TagLib::String::Type rccTaglibPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.8/taglib/toolkit/tstring.cpp taglib-1.8-ds/taglib/toolkit/tstring.cpp +--- taglib-1.8/taglib/toolkit/tstring.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/toolkit/tstring.cpp 2013-05-22 20:13:16.000000000 +0200 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -168,7 +169,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -397,10 +398,38 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) { ++ // The source is either Unicode or real Latin1 (if rcc is bypassed) ++ std::string s = to8Bit(true); ++ ++ // In case of UTF8 locale, this probably will return NULL (no recoding needed), but we will take UTF8 path in the next swtich ++ v = rccTaglibPatchRecodeOutput(s); ++ if (v.size()) return v; + ++ t = rccTaglibPatchGetLocaleType(); ++ } ++ ++ switch(t) { ++ case Latin1ID3: ++ case Latin1ID3V2: ++ { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeOutputID3(s, true); ++ if (v.size()) break; ++ ++ // we don't know if we got NULL because rcc is disabled (error) or UTF8 output is required ++ if ((t == Latin1ID3V2)&&(rccTaglibPatchGetID3Type() == UTF8)) { ++ v.setData(s.c_str(), s.length()); ++ } else { ++ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) ++ v.append(char(*it)); ++ } ++ break; ++ } + case Latin1: + { ++ // We can have the UTF16 inside, but first 256 positions is equal to Latin1 + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -750,6 +779,34 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccTaglibPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccTaglibPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ t = UTF8; ++ } else { ++ // We don't know if we got UTF-8 encoded string or either rcc is disable or something is failed, ++ // since standard applications are really expecting here Latin1, it is safe to just check if we have violations of UTF8 ++ //if (Unicode::isLegalUTF8(s)) t = UTF8; ++ } ++ } ++ + switch(t) { + case UTF16: + { +@@ -839,6 +896,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccTaglibPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)||(rcc_type == Latin1)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.8/taglib/toolkit/tstring.h taglib-1.8-ds/taglib/toolkit/tstring.h +--- taglib-1.8/taglib/toolkit/tstring.h 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/toolkit/tstring.h 2013-05-22 20:13:16.000000000 +0200 +@@ -90,6 +90,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -112,6 +124,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ diff --git a/patches/taglib/taglib-1.8-ds-rusxmms.patch b/patches/taglib/taglib-1.8-ds-rusxmms.patch new file mode 100644 index 0000000..a5c04a5 --- /dev/null +++ b/patches/taglib/taglib-1.8-ds-rusxmms.patch @@ -0,0 +1,519 @@ +diff -dPNur taglib-1.8/config-taglib.h.cmake taglib-1.8-ds/config-taglib.h.cmake +--- taglib-1.8/config-taglib.h.cmake 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/config-taglib.h.cmake 2012-11-11 09:59:50.000000000 +0100 +@@ -3,6 +3,8 @@ + /* Define if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++#cmakedefine HAVE_LIBRCC 1 ++ + #cmakedefine NO_ITUNES_HACKS 1 + #cmakedefine WITH_ASF 1 + #cmakedefine WITH_MP4 1 +diff -dPNur taglib-1.8/ConfigureChecks.cmake taglib-1.8-ds/ConfigureChecks.cmake +--- taglib-1.8/ConfigureChecks.cmake 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/ConfigureChecks.cmake 2012-11-11 10:01:48.000000000 +0100 +@@ -14,6 +14,8 @@ + set(HAVE_ZLIB 0) + endif() + ++SET(HAVE_LIBRCC 1) ++ + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) + find_package(CppUnit) + if(NOT CppUnit_FOUND AND BUILD_TESTS) +diff -dPNur taglib-1.8/taglib/CMakeLists.txt taglib-1.8-ds/taglib/CMakeLists.txt +--- taglib-1.8/taglib/CMakeLists.txt 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/CMakeLists.txt 2012-11-11 10:04:40.000000000 +0100 +@@ -35,6 +35,7 @@ + audioproperties.h + taglib_export.h + ${CMAKE_BINARY_DIR}/taglib_config.h ++ toolkit/rccpatch.h + toolkit/taglib.h + toolkit/tstring.h + toolkit/tlist.h +@@ -269,6 +270,7 @@ + ) + + set(toolkit_SRCS ++ toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -296,7 +298,7 @@ + add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) + + if(ZLIB_FOUND) +- target_link_libraries(tag ${ZLIB_LIBRARIES}) ++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) + endif() + + set_target_properties(tag PROPERTIES +diff -dPNur taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2012-11-11 09:59:50.000000000 +0100 +@@ -64,17 +64,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -247,7 +248,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.8/taglib/mpeg/id3v1/id3v1tag.cpp.orig taglib-1.8-ds/taglib/mpeg/id3v1/id3v1tag.cpp.orig +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2012-11-11 09:59:50.000000000 +0100 +@@ -150,10 +150,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -174,10 +174,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); +- +- v.append(char(encoding)); ++ ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/commentsframe.cpp.orig taglib-1.8-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp.orig +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2012-11-11 09:59:50.000000000 +0100 +@@ -187,12 +187,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -223,11 +223,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkTextEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.8/taglib/mpeg/id3v2/frames/textidentificationframe.cpp.orig taglib-1.8-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp.orig +diff -dPNur taglib-1.8/taglib/toolkit/rccpatch.cpp taglib-1.8-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.8/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.8-ds/taglib/toolkit/rccpatch.cpp 2012-11-11 10:00:09.000000000 +0100 +@@ -0,0 +1,198 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccPatchInit(); ++ if (rcc_initialized) atexit(rccPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++ if (res) v.setData(res, rlen); ++ else v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::String::Type rccPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccPatchTryInit(); ++ ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.8/taglib/toolkit/rccpatch.h taglib-1.8-ds/taglib/toolkit/rccpatch.h +--- taglib-1.8/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.8-ds/taglib/toolkit/rccpatch.h 2012-11-11 10:00:09.000000000 +0100 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccPatchFree(); ++void rccPatchInit(); ++void rccPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccPatchGetLocaleType(); ++TagLib::String::Type rccPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.8/taglib/toolkit/tstring.cpp taglib-1.8-ds/taglib/toolkit/tstring.cpp +--- taglib-1.8/taglib/toolkit/tstring.cpp 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/toolkit/tstring.cpp 2012-11-11 10:00:09.000000000 +0100 +@@ -23,6 +23,7 @@ + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + ++#include "rccpatch.h" + #include "tstring.h" + #include "unicode.h" + #include "tdebug.h" +@@ -168,7 +169,7 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1 || t == UTF8) { ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2 || t == UTF8) { + + int length = 0; + d->data.resize(v.size()); +@@ -397,10 +398,21 @@ + { + ByteVector v; + +- switch(t) { ++ if (t == Locale) t = rccPatchGetLocaleType(); + ++ switch(t) { ++ case Locale: + case Latin1: ++ case Latin1ID3: ++ case Latin1ID3V2: + { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeOutputID3(s, true); ++ else /* if (t == Latin1(Locale) */ v = rccPatchRecodeOutput(s); ++ ++ if (v.size()) return v; ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + v.append(char(*it)); + break; +@@ -750,6 +762,31 @@ + + void String::prepare(Type t) + { ++ if (t == Locale) t = rccPatchGetLocaleType(); ++ ++ if ((t == Latin1)||(t == Latin1ID3)||(t == Latin1ID3V2)) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccPatchRecodeInput(s); ++ ++ if (v.size()) { ++ int length = 0; ++ d->data.resize(v.size()); ++ wstring::iterator targetIt = d->data.begin(); ++ for(ByteVector::ConstIterator it = v.begin(); it != v.end() && (*it); ++it) { ++ *targetIt = uchar(*it); ++ ++targetIt; ++ ++length; ++ } ++ d->data.resize(length); ++ } ++ ++ t = UTF8; ++ } ++ + switch(t) { + case UTF16: + { +@@ -839,6 +876,27 @@ + + std::ostream &operator<<(std::ostream &s, const String &str) + { +- s << str.to8Bit(); ++ ByteVector bv = str.data(String::Locale); ++ s << bv; + return s; + } ++ ++String::Type String::ID3Type(int i) { ++ if (i == Latin1) return Latin1ID3V2; ++ return Type(i); ++}; ++ ++String::Type String::ID3WType(Type type) { ++ Type rcc_type = rccPatchGetID3Type(); ++ if ((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)) { ++ if (type == Latin1) return rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++String::Type String::ID3RealType(Type type) { ++ if ((type == Latin1ID3)||(type == Latin1ID3V2)) return Latin1; ++ return type; ++} +diff -dPNur taglib-1.8/taglib/toolkit/tstring.cpp.orig taglib-1.8-ds/taglib/toolkit/tstring.cpp.orig +diff -dPNur taglib-1.8/taglib/toolkit/tstring.h taglib-1.8-ds/taglib/toolkit/tstring.h +--- taglib-1.8/taglib/toolkit/tstring.h 2012-09-06 20:03:15.000000000 +0200 ++++ taglib-1.8-ds/taglib/toolkit/tstring.h 2012-11-11 10:00:09.000000000 +0100 +@@ -90,6 +90,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -112,6 +124,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ +diff -dPNur taglib-1.8/taglib/toolkit/tstring.h.orig taglib-1.8-ds/taglib/toolkit/tstring.h.orig diff --git a/patches/taglib/taglib-1.9.1-ds-rusxmms-enforce.patch b/patches/taglib/taglib-1.9.1-ds-rusxmms-enforce.patch new file mode 100644 index 0000000..e980b7a --- /dev/null +++ b/patches/taglib/taglib-1.9.1-ds-rusxmms-enforce.patch @@ -0,0 +1,20 @@ +--- taglib-1.9.1/taglib/mpeg/id3v1/id3v1tag.h 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-taurus/taglib/mpeg/id3v1/id3v1tag.h 2013-11-12 00:24:31.206495291 +0100 +@@ -68,7 +68,7 @@ + * Decode a string from \a data. The default implementation assumes that + * \a data is an ISO-8859-1 (Latin1) character array. + */ +- virtual String parse(const ByteVector &data) const; ++ String parse(const ByteVector &data) const; + + /*! + * Encode a ByteVector with the data from \a s. The default implementation +@@ -79,7 +79,7 @@ + * instead do not write an ID3v1 tag in the case that the data is not + * ISO-8859-1. + */ +- virtual ByteVector render(const String &s) const; ++ ByteVector render(const String &s) const; + }; + + //! The main class in the ID3v1 implementation diff --git a/patches/taglib/taglib-1.9.1-ds-rusxmms.patch b/patches/taglib/taglib-1.9.1-ds-rusxmms.patch new file mode 100644 index 0000000..b64b5b5 --- /dev/null +++ b/patches/taglib/taglib-1.9.1-ds-rusxmms.patch @@ -0,0 +1,676 @@ +diff -dPNur taglib-1.9.1/config.h.cmake taglib-1.9.1-ds/config.h.cmake +--- taglib-1.9.1/config.h.cmake 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/config.h.cmake 2013-11-11 13:43:48.500304915 +0100 +@@ -31,6 +31,9 @@ + /* Defined if you have libz */ + #cmakedefine HAVE_ZLIB 1 + ++/* Defined if you have LibRCC from RusXMMS project */ ++#cmakedefine HAVE_LIBRCC 1 ++ + /* Indicates whether debug messages are shown even in release mode */ + #cmakedefine TRACE_IN_RELEASE 1 + +diff -dPNur taglib-1.9.1/ConfigureChecks.cmake taglib-1.9.1-ds/ConfigureChecks.cmake +--- taglib-1.9.1/ConfigureChecks.cmake 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/ConfigureChecks.cmake 2013-11-11 13:42:53.017126134 +0100 +@@ -216,6 +216,7 @@ + set(HAVE_ZLIB 0) + endif() + ++SET(HAVE_LIBRCC 1) + + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) + +diff -dPNur taglib-1.9.1/examples/tagreader_c.c taglib-1.9.1-ds/examples/tagreader_c.c +--- taglib-1.9.1/examples/tagreader_c.c 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/examples/tagreader_c.c 2013-11-11 13:42:53.017126134 +0100 +@@ -38,7 +38,7 @@ + TagLib_Tag *tag; + const TagLib_AudioProperties *properties; + +- taglib_set_strings_unicode(FALSE); ++// taglib_set_strings_unicode(FALSE); + + for(i = 1; i < argc; i++) { + printf("******************** \"%s\" ********************\n", argv[i]); +diff -dPNur taglib-1.9.1/examples/tagwriter.cpp taglib-1.9.1-ds/examples/tagwriter.cpp +--- taglib-1.9.1/examples/tagwriter.cpp 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/examples/tagwriter.cpp 2013-11-11 13:42:53.028126368 +0100 +@@ -92,7 +92,7 @@ + if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) { + + char field = argv[i][1]; +- TagLib::String value = argv[i + 1]; ++ TagLib::String value(argv[i + 1], TagLib::String::Locale); + + TagLib::List<TagLib::FileRef>::Iterator it; + for(it = fileList.begin(); it != fileList.end(); ++it) { +diff -dPNur taglib-1.9.1/taglib/CMakeLists.txt taglib-1.9.1-ds/taglib/CMakeLists.txt +--- taglib-1.9.1/taglib/CMakeLists.txt 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/CMakeLists.txt 2013-11-11 13:42:53.042126665 +0100 +@@ -36,6 +36,7 @@ + audioproperties.h + taglib_export.h + ${CMAKE_BINARY_DIR}/taglib_config.h ++ toolkit/rccpatch.h + toolkit/taglib.h + toolkit/tstring.h + toolkit/tlist.h +@@ -281,6 +282,7 @@ + ) + + set(toolkit_SRCS ++ toolkit/rccpatch.cpp + toolkit/tstring.cpp + toolkit/tstringlist.cpp + toolkit/tbytevector.cpp +@@ -310,7 +312,7 @@ + add_library(tag ${tag_LIB_SRCS} ${tag_HDRS}) + + if(ZLIB_FOUND) +- target_link_libraries(tag ${ZLIB_LIBRARIES}) ++ target_link_libraries(tag rcc ${ZLIB_LIBRARIES}) + endif() + + set_target_properties(tag PROPERTIES +diff -dPNur taglib-1.9.1/taglib/mpeg/id3v1/id3v1tag.cpp taglib-1.9.1-ds/taglib/mpeg/id3v1/id3v1tag.cpp +--- taglib-1.9.1/taglib/mpeg/id3v1/id3v1tag.cpp 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/mpeg/id3v1/id3v1tag.cpp 2013-11-11 13:42:53.043126686 +0100 +@@ -64,17 +64,18 @@ + + String ID3v1::StringHandler::parse(const ByteVector &data) const + { +- return String(data, String::Latin1).stripWhiteSpace(); ++ return String(data, String::Latin1ID3).stripWhiteSpace(); + } + + ByteVector ID3v1::StringHandler::render(const String &s) const + { + if(!s.isLatin1()) + { ++ if (String::ID3WType(String::Latin1) == String::Latin1) + return ByteVector(); + } + +- return s.data(String::Latin1); ++ return s.data(String::Latin1ID3); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -257,7 +258,7 @@ + d->track = uchar(data[offset + 29]); + } + else +- d->comment = data.mid(offset, 30); ++ d->comment = TagPrivate::stringHandler->parse(data.mid(offset, 30)); + + offset += 30; + +diff -dPNur taglib-1.9.1/taglib/mpeg/id3v2/frames/commentsframe.cpp taglib-1.9.1-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp +--- taglib-1.9.1/taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/mpeg/id3v2/frames/commentsframe.cpp 2013-11-11 13:42:53.043126686 +0100 +@@ -150,10 +150,10 @@ + return; + } + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + d->language = data.mid(1, 3); + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + +@@ -174,10 +174,12 @@ + + String::Type encoding = d->textEncoding; + ++ encoding = String::ID3WType(encoding); ++ + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); +diff -dPNur taglib-1.9.1/taglib/mpeg/id3v2/frames/textidentificationframe.cpp taglib-1.9.1-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +--- taglib-1.9.1/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/mpeg/id3v2/frames/textidentificationframe.cpp 2013-11-11 13:42:53.044126708 +0100 +@@ -187,12 +187,12 @@ + + // read the string data type (the first byte of the field data) + +- d->textEncoding = String::Type(data[0]); ++ d->textEncoding = String::ID3Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + +- int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; ++ int byteAlign = (d->textEncoding == String::Latin1 || d->textEncoding == String::Latin1ID3 || d->textEncoding == String::Latin1ID3V2 || d->textEncoding == String::UTF8) ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + +@@ -223,11 +223,14 @@ + + ByteVector TextIdentificationFrame::renderFields() const + { +- String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); ++ String::Type encoding = d->textEncoding; ++ ++ encoding = String::ID3WType(encoding); ++ encoding = checkTextEncoding(d->fieldList, encoding); + + ByteVector v; + +- v.append(char(encoding)); ++ v.append(char(String::ID3RealType(encoding))); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + +diff -dPNur taglib-1.9.1/taglib/mpeg/id3v2/id3v2frame.cpp taglib-1.9.1-ds/taglib/mpeg/id3v2/id3v2frame.cpp +--- taglib-1.9.1/taglib/mpeg/id3v2/id3v2frame.cpp 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/mpeg/id3v2/id3v2frame.cpp 2013-11-11 13:42:53.045126729 +0100 +@@ -302,7 +302,7 @@ + if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) + return String::UTF16; + +- if(encoding != String::Latin1) ++ if((encoding != String::Latin1)&&(encoding != String::Latin1ID3V2)) + return encoding; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { +diff -dPNur taglib-1.9.1/taglib/toolkit/rccpatch.cpp taglib-1.9.1-ds/taglib/toolkit/rccpatch.cpp +--- taglib-1.9.1/taglib/toolkit/rccpatch.cpp 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.9.1-ds/taglib/toolkit/rccpatch.cpp 2013-11-11 13:42:53.045126729 +0100 +@@ -0,0 +1,237 @@ ++#include <stdlib.h> ++ ++#include <string> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++//#define RCC_DEBUG ++ ++ ++#ifndef HAVE_LIBRCC ++# include <config.h> ++#endif ++ ++#ifdef HAVE_LIBRCC ++# ifdef RCC_DEBUG ++# include <stdio.h> ++# endif /* RCC_DEBUG */ ++# include <librcc.h> ++# include <string.h> ++#endif /* HAVE_LIBRCC */ ++ ++ ++#ifdef HAVE_LIBRCC ++# define ID3_CLASS 0 ++# define ID3V2_CLASS 1 ++# define UTF_CLASS 2 ++# define OUT_CLASS 3 ++static rcc_class classes[] = { ++ { "id3", RCC_CLASS_STANDARD, NULL, NULL, "ID3 Encoding", 0 }, ++ { "id3v2", RCC_CLASS_STANDARD, "id3", NULL, "ID3 v.2 Encoding", 0 }, ++ { "utf", RCC_CLASS_KNOWN, "UTF-8", NULL, "Unicode Encoding", 0}, ++ { "out", RCC_CLASS_TRANSLATE_LOCALE, "LC_CTYPE", NULL, "Output Encoding", 0 }, ++ { NULL, RCC_CLASS_STANDARD, NULL, NULL, NULL, 0 } ++}; ++ ++static int rcc_initialized = 0; ++ ++static rcc_context ctx = NULL; ++#endif /* HAVE_LIBRCC */ ++ ++ ++void rccTaglibPatchFree() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) { ++ rccFree(); ++ rcc_initialized = 0; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchInit() { ++#ifdef HAVE_LIBRCC ++ if (rcc_initialized) return; ++ rccInit(); ++ rccInitDefaultContext(NULL, 0, 0, classes, 0); ++ rccLoad(NULL, "xmms"); ++ rccInitDb4(NULL, NULL, 0); ++ rcc_initialized = 1; ++#endif /* HAVE_LIBRCC */ ++} ++ ++void rccTaglibPatchSetContext(void *newctx) { ++#ifdef HAVE_LIBRCC ++ if (newctx) { ++ ctx = (rcc_context)newctx; ++ rcc_initialized = 1; ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++static void rccTaglibPatchTryInit() { ++#ifdef HAVE_LIBRCC ++ if (!rcc_initialized) { ++ rccTaglibPatchInit(); ++ if (rcc_initialized) atexit(rccTaglibPatchFree); ++ } ++#endif /* HAVE_LIBRCC */ ++} ++ ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, OUT_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Output: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, UTF_CLASS, v2?ID3V2_CLASS:ID3_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" OutputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else v.setData("", 0); ++ //v.setData(s.c_str(), s.length()); ++ ++ return v; ++#else ++ v.setData("", 0); ++ ++ return v; ++#endif /* HAVE_LIBRCC */ ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, OUT_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" Input: %s - %s\n", s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ ++ if (res) v.setData(res, rlen); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false) { ++ TagLib::ByteVector v; ++#ifdef HAVE_LIBRCC ++ size_t rlen; ++ char *res; ++ ++ rccTaglibPatchTryInit(); ++ ++ res = rccSizedRecode(ctx, v2?ID3V2_CLASS:ID3_CLASS, UTF_CLASS, s.c_str(), s.length(), &rlen); ++#ifdef RCC_DEBUG ++ for (const unsigned char *c = (const unsigned char*)s.c_str(); *c; c++) { ++ if (*c > 127) { ++ printf(" InputID3(%i): %s - %s\n", v2, s.c_str(), res?res:"null"); ++ break; ++ } ++ } ++#endif /* RCC_DEBUG */ ++ if (res) v.setData(res, rlen + 1); ++ else ++#endif /* HAVE_LIBRCC */ ++ v.setData("", 0); ++ ++ return v; ++} ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ char charset[32]; ++ ++ rccTaglibPatchTryInit(); ++ if (!rccLocaleGetCharset(charset, NULL, 31)) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::UTF8; ++} ++ ++TagLib::String::Type rccTaglibPatchGetID3Type() { ++#ifdef HAVE_LIBRCC ++ size_t len; ++ const char *charset; ++ ++ rccTaglibPatchTryInit(); ++ ++ charset = rccGetCurrentCharsetName(ctx, ID3V2_CLASS); ++ if (charset) { ++ if (!strncmp(charset, "UTF", 3)) { ++ len = strlen(charset); ++ ++ if (charset[len-1]=='8') return TagLib::String::UTF8; ++ if (!strcmp(charset+(len-2),"16")) return TagLib::String::UTF16; ++ if (!strcmp(charset+(len-4),"16LE")) return TagLib::String::UTF16LE; ++ if (!strcmp(charset+(len-4),"16BE")) return TagLib::String::UTF16BE; ++ } ++ return TagLib::String::Latin1ID3V2; ++ } else { ++ // Error or no-language configured: If Latin1ID3V2 is returned we normally will use the default unicode encoding unless Latin1 is selected by taglib ++ return TagLib::String::Latin1ID3V2; ++ } ++#endif /* HAVE_LIBRCC */ ++ return TagLib::String::Latin1; ++} +diff -dPNur taglib-1.9.1/taglib/toolkit/rccpatch.h taglib-1.9.1-ds/taglib/toolkit/rccpatch.h +--- taglib-1.9.1/taglib/toolkit/rccpatch.h 1970-01-01 01:00:00.000000000 +0100 ++++ taglib-1.9.1-ds/taglib/toolkit/rccpatch.h 2013-11-11 13:42:53.045126729 +0100 +@@ -0,0 +1,20 @@ ++#ifndef _RCC_PATCH_H ++#define _RCC_PATCH_H ++ ++#include <string.h> ++#include "tstring.h" ++#include "tbytevector.h" ++ ++void rccTaglibPatchFree(); ++void rccTaglibPatchInit(); ++void rccTaglibPatchSetContext(void *newctx); ++ ++TagLib::ByteVector rccTaglibPatchRecodeOutput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeInput(const std::string &s); ++TagLib::ByteVector rccTaglibPatchRecodeOutputID3(const std::string &s, bool v2 = false); ++TagLib::ByteVector rccTaglibPatchRecodeInputID3(const std::string &s, bool v2 = false); ++ ++TagLib::String::Type rccTaglibPatchGetLocaleType(); ++TagLib::String::Type rccTaglibPatchGetID3Type(); ++ ++#endif /* _RCC_PATCH_H */ +diff -dPNur taglib-1.9.1/taglib/toolkit/tstring.cpp taglib-1.9.1-ds/taglib/toolkit/tstring.cpp +--- taglib-1.9.1/taglib/toolkit/tstring.cpp 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/toolkit/tstring.cpp 2013-11-11 13:42:53.046126750 +0100 +@@ -29,6 +29,7 @@ + #include <config.h> + #endif + ++#include "rccpatch.h" + #include "tstring.h" + #include "tdebug.h" + #include "tstringlist.h" +@@ -197,8 +198,11 @@ + String::String(const std::string &s, Type t) + : d(new StringPrivate()) + { +- if(t == Latin1) +- copyFromLatin1(&s[0], s.length()); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(&s[0], s.length(), true, t); + else if(t == String::UTF8) + copyFromUTF8(&s[0], s.length()); + else { +@@ -229,8 +233,11 @@ + String::String(const char *s, Type t) + : d(new StringPrivate()) + { +- if(t == Latin1) +- copyFromLatin1(s, ::strlen(s)); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(s, ::strlen(s), true, t); + else if(t == String::UTF8) + copyFromUTF8(s, ::strlen(s)); + else { +@@ -251,7 +258,10 @@ + String::String(char c, Type t) + : d(new StringPrivate(1, static_cast<uchar>(c))) + { +- if(t != Latin1 && t != UTF8) { ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t != Latin1 && t != Latin1ID3 && t != Latin1ID3V2 && t != UTF8) { + debug("String::String() -- A char should not contain UTF16."); + } + } +@@ -262,8 +272,11 @@ + if(v.isEmpty()) + return; + +- if(t == Latin1) +- copyFromLatin1(v.data(), v.size()); ++ if(t == Locale) ++ t = rccTaglibPatchGetLocaleType(); ++ ++ if(t == Latin1 || t == Latin1ID3 || t == Latin1ID3V2) ++ copyFromLatin1(v.data(), v.size(), true, t); + else if(t == UTF8) + copyFromUTF8(v.data(), v.size()); + else +@@ -428,16 +441,46 @@ + + ByteVector String::data(Type t) const + { +- switch(t) +- { ++ ByteVector v; ++ ++ if (t == Locale) { ++ // The source is either Unicode or real Latin1 (if rcc is bypassed) ++ std::string s = to8Bit(true); ++ ++ // In case of UTF8 locale, this probably will return NULL (no recoding needed), but we will take UTF8 path in the next swtich ++ v = rccTaglibPatchRecodeOutput(s); ++ if (v.size()) return v; ++ ++ t = rccTaglibPatchGetLocaleType(); ++ } ++ ++ switch(t) { ++ case Latin1ID3: ++ case Latin1ID3V2: ++ { ++ std::string s = to8Bit(true); ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeOutputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeOutputID3(s, true); ++ if (v.size()) ++ return v; ++ ++ // we don't know if we got NULL because rcc is disabled (error) or UTF8 output is required ++ if ((t == Latin1ID3V2)&&(rccTaglibPatchGetID3Type() == UTF8)) { ++ v.setData(s.c_str(), s.length()); ++ } else { ++ for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) ++ v.append(char(*it)); ++ } ++ return v; ++ } + case Latin1: + { + ByteVector v(size(), 0); + char *p = v.data(); +- ++ + for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) + *p++ = static_cast<char>(*it); +- ++ + return v; + } + case UTF8: +@@ -763,12 +806,29 @@ + // private members + //////////////////////////////////////////////////////////////////////////////// + +-void String::copyFromLatin1(const char *s, size_t length) ++void String::copyFromLatin1(const char *s, size_t length, bool prepare, Type t) + { + d->data.resize(length); +- + for(size_t i = 0; i < length; ++i) + d->data[i] = static_cast<uchar>(s[i]); ++ ++ // librcc conversation ++ if (prepare) { ++ std::string s = to8Bit(false); ++ ByteVector v; ++ ++ if (t == Latin1ID3) v = rccTaglibPatchRecodeInputID3(s, false); ++ else if (t == Latin1ID3V2) v = rccTaglibPatchRecodeInputID3(s, true); ++ else /* Latin1 converted from Locale */ v = rccTaglibPatchRecodeInput(s); ++ ++ if (v.size()) { ++ copyFromUTF8(v.data(), v.size()); ++ } else { ++ // We don't know if we got UTF-8 encoded string or either rcc is disable or something is failed, ++ // since standard applications are really expecting here Latin1, it is safe to just check if we have violations of UTF8 ++ //if (Unicode::isLegalUTF8(s)) t = UTF8; ++ } ++ } + } + + void String::copyFromUTF8(const char *s, size_t length) +@@ -874,7 +934,33 @@ + + std::ostream &operator<<(std::ostream &s, const TagLib::String &str) + { +- s << str.to8Bit(); ++ TagLib::ByteVector bv = str.data(TagLib::String::Locale); ++ s << bv; + return s; + } + ++TagLib::String::Type TagLib::String::ID3Type(int i) ++{ ++ if(i == Latin1) ++ return Latin1ID3V2; ++ return Type(i); ++}; ++ ++TagLib::String::Type TagLib::String::ID3WType(Type type) ++{ ++ Type rcc_type = rccTaglibPatchGetID3Type(); ++ if((rcc_type == Latin1ID3)||(rcc_type == Latin1ID3V2)||(rcc_type == Latin1)) { ++ if(type == Latin1) return ++ rcc_type; ++ return type; ++ } ++ ++ return rcc_type; ++}; ++ ++TagLib::String::Type TagLib::String::ID3RealType(Type type) ++{ ++ if((type == Latin1ID3) || (type == Latin1ID3V2)) ++ return Latin1; ++ return type; ++} +diff -dPNur taglib-1.9.1/taglib/toolkit/tstring.h taglib-1.9.1-ds/taglib/toolkit/tstring.h +--- taglib-1.9.1/taglib/toolkit/tstring.h 2013-10-08 17:50:01.000000000 +0200 ++++ taglib-1.9.1-ds/taglib/toolkit/tstring.h 2013-11-11 13:42:53.047126771 +0100 +@@ -90,6 +90,18 @@ + */ + enum Type { + /*! ++ * Determine using current locale settings ++ */ ++ Locale = -1, ++ /*! ++ * Latin1 for ID3 tags. ++ */ ++ Latin1ID3 = 65, ++ /*! ++ * Latin1 for ID3v2 tags. ++ */ ++ Latin1ID3V2 = 66, ++ /*! + * IS08859-1, or <i>Latin1</i> encoding. 8 bit characters. + */ + Latin1 = 0, +@@ -112,6 +124,10 @@ + UTF16LE = 4 + }; + ++ static Type ID3Type(int i); ++ static Type ID3WType(Type type); ++ static Type ID3RealType(Type type); ++ + /*! + * Constructs an empty String. + */ +@@ -479,7 +495,7 @@ + * Converts a \e Latin-1 string into \e UTF-16(without BOM/CPU byte order) + * and copies it to the internal buffer. + */ +- void copyFromLatin1(const char *s, size_t length); ++ void copyFromLatin1(const char *s, size_t length, bool prepare = false, Type t = Latin1); + + /*! + * Converts a \e UTF-8 string into \e UTF-16(without BOM/CPU byte order) |