diff options
Diffstat (limited to 'media-libs/taglib/files')
8 files changed, 2370 insertions, 0 deletions
diff --git a/media-libs/taglib/files/taglib-1.10-ds-rusxmms.patch b/media-libs/taglib/files/taglib-1.10-ds-rusxmms.patch new file mode 100644 index 0000000..584c237 --- /dev/null +++ b/media-libs/taglib/files/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/media-libs/taglib/files/taglib-1.6.1-install-examples.patch b/media-libs/taglib/files/taglib-1.6.1-install-examples.patch new file mode 100644 index 0000000..f537681 --- /dev/null +++ b/media-libs/taglib/files/taglib-1.6.1-install-examples.patch @@ -0,0 +1,16 @@ +diff -purN taglib-1.6.1.orig/examples/CMakeLists.txt taglib-1.6.1/examples/CMakeLists.txt +--- taglib-1.6.1.orig/examples/CMakeLists.txt 2009-09-09 14:16:38.000000000 -0400 ++++ taglib-1.6.1/examples/CMakeLists.txt 2009-12-14 18:47:33.405385063 -0500 +@@ -45,6 +45,12 @@ ADD_EXECUTABLE(strip-id3v1 strip-id3v1.c + + TARGET_LINK_LIBRARIES(strip-id3v1 tag ) + ++INSTALL(TARGETS ++ tagreader tagreader_c tagwriter framelist strip-id3v1 ++ LIBRARY DESTINATION ${LIB_INSTALL_DIR} ++ RUNTIME DESTINATION ${BIN_INSTALL_DIR} ++ ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ++) + + endif(BUILD_EXAMPLES) + diff --git a/media-libs/taglib/files/taglib-1.9.1-abi-breakage.patch b/media-libs/taglib/files/taglib-1.9.1-abi-breakage.patch new file mode 100644 index 0000000..930439f --- /dev/null +++ b/media-libs/taglib/files/taglib-1.9.1-abi-breakage.patch @@ -0,0 +1,107 @@ +From 3bf30af66c8fd77a88d9379a0956ddb2fc70dc20 Mon Sep 17 00:00:00 2001 +From: Tsuda Kageyu <tsuda.kageyu@gmail.com> +Date: Wed, 6 Nov 2013 17:01:21 +0900 +Subject: [PATCH 2/6] Fixed ABI breakage in TagLib::String + +--- + taglib/toolkit/tstring.cpp | 20 ++++++++++++++++++-- + taglib/toolkit/tstring.h | 12 ++++++++++-- + tests/test_string.cpp | 14 ++++++++++++++ + 3 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp +index 75a9833..fb6e947 100644 +--- a/taglib/toolkit/tstring.cpp ++++ b/taglib/toolkit/tstring.cpp +@@ -209,8 +209,16 @@ String::String(const std::string &s, Type t) + String::String(const wstring &s, Type t) + : d(new StringPrivate()) + { +- if(t == UTF16 || t == UTF16BE || t == UTF16LE) ++ if(t == UTF16 || t == UTF16BE || t == UTF16LE) { ++ // This looks ugly but needed for the compatibility with TagLib1.8. ++ // Should be removed in TabLib2.0. ++ if (t == UTF16BE) ++ t = WCharByteOrder; ++ else if (t == UTF16LE) ++ t = (WCharByteOrder == UTF16LE ? UTF16BE : UTF16LE); ++ + copyFromUTF16(s.c_str(), s.length(), t); ++ } + else { + debug("String::String() -- A TagLib::wstring should not contain Latin1 or UTF-8."); + } +@@ -219,8 +227,16 @@ String::String(const wstring &s, Type t) + String::String(const wchar_t *s, Type t) + : d(new StringPrivate()) + { +- if(t == UTF16 || t == UTF16BE || t == UTF16LE) ++ if(t == UTF16 || t == UTF16BE || t == UTF16LE) { ++ // This looks ugly but needed for the compatibility with TagLib1.8. ++ // Should be removed in TabLib2.0. ++ if (t == UTF16BE) ++ t = WCharByteOrder; ++ else if (t == UTF16LE) ++ t = (WCharByteOrder == UTF16LE ? UTF16BE : UTF16LE); ++ + copyFromUTF16(s, ::wcslen(s), t); ++ } + else { + debug("String::String() -- A const wchar_t * should not contain Latin1 or UTF-8."); + } +diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h +index 57945be..605b9c2 100644 +--- a/taglib/toolkit/tstring.h ++++ b/taglib/toolkit/tstring.h +@@ -134,13 +134,21 @@ namespace TagLib { + + /*! + * Makes a deep copy of the data in \a s. ++ * ++ * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless ++ * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior ++ * will be changed in TagLib2.0. + */ +- String(const wstring &s, Type t = WCharByteOrder); ++ String(const wstring &s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a s. ++ * ++ * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless ++ * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior ++ * will be changed in TagLib2.0. + */ +- String(const wchar_t *s, Type t = WCharByteOrder); ++ String(const wchar_t *s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a c. +diff --git a/tests/test_string.cpp b/tests/test_string.cpp +index a815a0b..9a574b3 100644 +--- a/tests/test_string.cpp ++++ b/tests/test_string.cpp +@@ -75,6 +75,20 @@ public: + String unicode3(L"\u65E5\u672C\u8A9E"); + CPPUNIT_ASSERT(*(unicode3.toCWString() + 1) == L'\u672C'); + ++ String unicode4(L"\u65e5\u672c\u8a9e", String::UTF16BE); ++ CPPUNIT_ASSERT(unicode4[1] == L'\u672c'); ++ ++ String unicode5(L"\u65e5\u672c\u8a9e", String::UTF16LE); ++ CPPUNIT_ASSERT(unicode5[1] == L'\u2c67'); ++ ++ wstring stduni = L"\u65e5\u672c\u8a9e"; ++ ++ String unicode6(stduni, String::UTF16BE); ++ CPPUNIT_ASSERT(unicode6[1] == L'\u672c'); ++ ++ String unicode7(stduni, String::UTF16LE); ++ CPPUNIT_ASSERT(unicode7[1] == L'\u2c67'); ++ + CPPUNIT_ASSERT(strcmp(String::number(0).toCString(), "0") == 0); + CPPUNIT_ASSERT(strcmp(String::number(12345678).toCString(), "12345678") == 0); + CPPUNIT_ASSERT(strcmp(String::number(-12345678).toCString(), "-12345678") == 0); +-- +1.8.4.2 + diff --git a/media-libs/taglib/files/taglib-1.9.1-bytevector-simpler.patch b/media-libs/taglib/files/taglib-1.9.1-bytevector-simpler.patch new file mode 100644 index 0000000..0b134ec --- /dev/null +++ b/media-libs/taglib/files/taglib-1.9.1-bytevector-simpler.patch @@ -0,0 +1,131 @@ +From 4a7d31c87bf41c1de21cb725176d5b34c2a95720 Mon Sep 17 00:00:00 2001 +From: Tsuda Kageyu <tsuda.kageyu@gmail.com> +Date: Thu, 14 Nov 2013 14:05:32 +0900 +Subject: [PATCH 3/6] Rewrote ByteVector::replace() simpler + +--- + taglib/toolkit/tbytevector.cpp | 77 +++++++++++++++--------------------------- + tests/test_bytevector.cpp | 5 +++ + 2 files changed, 33 insertions(+), 49 deletions(-) + +diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp +index b658246..566a20f 100644 +--- a/taglib/toolkit/tbytevector.cpp ++++ b/taglib/toolkit/tbytevector.cpp +@@ -31,6 +31,7 @@ + #include <iostream> + #include <cstdio> + #include <cstring> ++#include <cstddef> + + #include <tstring.h> + #include <tdebug.h> +@@ -508,62 +509,40 @@ ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &wit + if(pattern.size() == 0 || pattern.size() > size()) + return *this; + +- const uint withSize = with.size(); +- const uint patternSize = pattern.size(); +- int offset = 0; ++ const size_t withSize = with.size(); ++ const size_t patternSize = pattern.size(); ++ const ptrdiff_t diff = withSize - patternSize; ++ ++ size_t offset = 0; ++ while (true) ++ { ++ offset = find(pattern, offset); ++ if(offset == static_cast<size_t>(-1)) // Use npos in taglib2. ++ break; + +- if(withSize == patternSize) { +- // I think this case might be common enough to optimize it + detach(); +- offset = find(pattern); +- while(offset >= 0) { +- ::memcpy(data() + offset, with.data(), withSize); +- offset = find(pattern, offset + withSize); +- } +- return *this; +- } + +- // calculate new size: +- uint newSize = 0; +- for(;;) { +- int next = find(pattern, offset); +- if(next < 0) { +- if(offset == 0) +- // pattern not found, do nothing: +- return *this; +- newSize += size() - offset; +- break; ++ if(diff < 0) { ++ ::memmove( ++ data() + offset + withSize, ++ data() + offset + patternSize, ++ size() - offset - patternSize); ++ resize(size() + diff); + } +- newSize += (next - offset) + withSize; +- offset = next + patternSize; +- } +- +- // new private data of appropriate size: +- ByteVectorPrivate *newData = new ByteVectorPrivate(newSize, 0); +- char *target = DATA(newData); +- const char *source = data(); +- +- // copy modified data into new private data: +- offset = 0; +- for(;;) { +- int next = find(pattern, offset); +- if(next < 0) { +- ::memcpy(target, source + offset, size() - offset); +- break; ++ else if(diff > 0) { ++ resize(size() + diff); ++ ::memmove( ++ data() + offset + withSize, ++ data() + offset + patternSize, ++ size() - diff - offset - patternSize); + } +- int chunkSize = next - offset; +- ::memcpy(target, source + offset, chunkSize); +- target += chunkSize; +- ::memcpy(target, with.data(), withSize); +- target += withSize; +- offset += chunkSize + patternSize; +- } + +- // replace private data: +- if(d->deref()) +- delete d; ++ ::memcpy(data() + offset, with.data(), with.size()); + +- d = newData; ++ offset += withSize; ++ if(offset > size() - patternSize) ++ break; ++ } + + return *this; + } +diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp +index 9efd23a..eca74f8 100644 +--- a/tests/test_bytevector.cpp ++++ b/tests/test_bytevector.cpp +@@ -239,6 +239,11 @@ public: + a.replace(ByteVector("ab"), ByteVector()); + CPPUNIT_ASSERT_EQUAL(ByteVector("cdf"), a); + } ++ { ++ ByteVector a("abcdabf"); ++ a.replace(ByteVector("bf"), ByteVector("x")); ++ CPPUNIT_ASSERT_EQUAL(ByteVector("abcdax"), a); ++ } + } + + }; +-- +1.8.4.2 + diff --git a/media-libs/taglib/files/taglib-1.9.1-ds-rusxmms-enforce.patch b/media-libs/taglib/files/taglib-1.9.1-ds-rusxmms-enforce.patch new file mode 100644 index 0000000..e980b7a --- /dev/null +++ b/media-libs/taglib/files/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/media-libs/taglib/files/taglib-1.9.1-ds-rusxmms.patch b/media-libs/taglib/files/taglib-1.9.1-ds-rusxmms.patch new file mode 100644 index 0000000..b64b5b5 --- /dev/null +++ b/media-libs/taglib/files/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) diff --git a/media-libs/taglib/files/taglib-1.9.1-missing-deletes.patch b/media-libs/taglib/files/taglib-1.9.1-missing-deletes.patch new file mode 100644 index 0000000..9cdbdcf --- /dev/null +++ b/media-libs/taglib/files/taglib-1.9.1-missing-deletes.patch @@ -0,0 +1,48 @@ +From c14a3b5c3d0831f7c113d0cf95840c4671d9ebd4 Mon Sep 17 00:00:00 2001 +From: Tsuda Kageyu <tsuda.kageyu@gmail.com> +Date: Tue, 13 May 2014 20:07:02 +0900 +Subject: [PATCH] Added some missing deletes to test_flac.cpp. + +--- + tests/test_flac.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/test_flac.cpp b/tests/test_flac.cpp +index caec715..364fb11 100644 +--- a/tests/test_flac.cpp ++++ b/tests/test_flac.cpp +@@ -91,6 +91,7 @@ public: + newpic->setData("JPEG data"); + f->addPicture(newpic); + f->save(); ++ delete f; + + f = new FLAC::File(newname.c_str()); + lst = f->pictureList(); +@@ -138,6 +139,7 @@ public: + f->removePictures(); + f->addPicture(newpic); + f->save(); ++ delete f; + + f = new FLAC::File(newname.c_str()); + lst = f->pictureList(); +@@ -165,6 +167,7 @@ public: + + f->removePictures(); + f->save(); ++ delete f; + + f = new FLAC::File(newname.c_str()); + lst = f->pictureList(); +@@ -185,6 +188,7 @@ public: + tag->setTitle("NEW TITLE 2"); + f->save(); + CPPUNIT_ASSERT_EQUAL(String("NEW TITLE 2"), tag->title()); ++ delete f; + + f = new FLAC::File(newname.c_str()); + tag = f->tag(); +-- +1.9.0 + diff --git a/media-libs/taglib/files/taglib-1.9.1-order-big-endian.patch b/media-libs/taglib/files/taglib-1.9.1-order-big-endian.patch new file mode 100644 index 0000000..86d5201 --- /dev/null +++ b/media-libs/taglib/files/taglib-1.9.1-order-big-endian.patch @@ -0,0 +1,33 @@ +From db3e961d1098d5efe57364f540f68a5996dc83c2 Mon Sep 17 00:00:00 2001 +From: Tsuda Kageyu <tsuda.kageyu@gmail.com> +Date: Tue, 13 May 2014 18:22:16 +0900 +Subject: [PATCH] Fixed a wrong byte order handling on big-endian machines. + +--- + taglib/toolkit/tstring.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp +index 603455a..1ec083b 100644 +--- a/taglib/toolkit/tstring.cpp ++++ b/taglib/toolkit/tstring.cpp +@@ -47,10 +47,14 @@ + + namespace + { +- + inline unsigned short combine(unsigned char c1, unsigned char c2) + { +- return (c1 << 8) | c2; ++ using namespace TagLib::Utils; ++ ++ if(SystemByteOrder == LittleEndian) ++ return (c1 << 8) | c2; ++ else ++ return (c2 << 8) | c1; + } + + void UTF16toUTF8(const wchar_t *src, size_t srcLength, char *dst, size_t dstLength) +-- +1.9.0 + |